diff --git a/autobuild.xml b/autobuild.xml
index 78e8aa34f..0a281b49b 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -47,6 +47,40 @@
version
1.2.15
+ abseil-cpp
+
apr_suite
copyright
@@ -106,11 +140,11 @@
archive
hash
- 76186b09770cab66dba6586cb1d2123f
+ d0cf074a2c95a65b8833350dad77c0ae
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/apr_suite-1.5.2-windows-201603261507.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/apr_suite-1.5.2-windows-201703090634.tar.bz2
name
windows
@@ -278,11 +312,11 @@
archive
hash
- d606e5c39d13f2c23d23ac498520cbac
+ ae0998e5d108c77c5cea2a68ad928151
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/boost-1.60.0-windows-201601152308.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/boost-1.63.0-windows-201703281813.tar.bz2
name
windows
@@ -362,11 +396,11 @@
archive
hash
- 90a37cec15019bff53a165b90f0180a7
+ 60bd2dbac5559141e05be6c424cf9cd0
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/colladadom-2.3-windows-201601152346.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/colladadom-2.3-windows-201703281922.tar.bz2
name
windows
@@ -448,11 +482,11 @@
archive
hash
- f20491b59795d311cf8d730556cd141e
+ da5be630ca350a7ed4c0e99250451d41
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/curl-7.48.0-windows-201603231720.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/curl-7.56.1-windows-201711241310.tar.bz2
name
windows
@@ -551,6 +585,100 @@
version
1
+ 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
+ 2f44b376e436f37cbad5c7567edddebd
+ hash_algorithm
+ md5
+ url
+ https://bitbucket.org/router_gray/rg_3p-dullahan/downloads/dullahan-1.1.1085-3.3497.1833.g13f506f-linux64-201902042123.tar.bz2
+
+ name
+ linux64
+
+ windows
+
+ archive
+
+ hash
+ 2ecc71350b30a1057091b9cd7af18b1c
+ url
+ https://depot.alchemyviewer.org/pub/windows/lib-vc142/dullahan-1.1.930-3.3282.1733.g9091548-windows-201802202358.tar.bz2
+
+ name
+ windows
+
+ windows64
+
+ archive
+
+ hash
+ 414190fd1ce3876ee3efc682b06ae65c
+ hash_algorithm
+ md5
+ url
+ http://depot.alchemyviewer.org/pub/packages/windows64/msvc-1920/dullahan-1.1.1320_73.1.12-gee4b49f-chromium-73.0.3683.75-windows64-190871757.tar.bz2
+
+ name
+ windows64
+
+
+ version
+ 1.1.1320_73.1.12+gee4b49f+chromium-73.0.3683.75
+
+ 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
@@ -610,11 +738,11 @@
archive
hash
- 454170939e4d1ba07060b73d6f81b9fc
+ f10218f7c28d63a3d9f1fb683d116bf8
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/expat-2.1.1-windows-201603261409.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/expat-2.2.0-windows-201703090626.tar.bz2
name
windows
@@ -698,11 +826,11 @@
archive
hash
- fe50f650c97e6350bedfd90102d3321f
+ b23a30967666da49346983658ed50e92
hash_algorithm
md5
url
- https://depot.alchemyviewer.org/pub/windows/lib/fmodstudio-1.08.04-windows-201605291158.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib/fmodstudio-1.10.00-windows-201709290225.tar.bz2
name
windows
@@ -769,6 +897,38 @@
version
2.11.0
+ 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
@@ -874,11 +1034,11 @@
archive
hash
- e5be5197f12f9ca8078ba9ce4f1bce10
+ bdbfc3b58cfc2f125881be748d092645
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/freetype-2.6.3-windows-201603011805.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/freetype-2.8.0-windows-201710192344.tar.bz2
name
windows
@@ -1024,11 +1184,11 @@
archive
hash
- 05134ab3cf05fbfb4bed996b53a0d472
+ 37035aad7d066dfe6f26dc009aa9dcea
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/glod-1.0pre4-windows-201601151027.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/glod-1.0pre4-windows-201703090622.tar.bz2
name
windows
@@ -1110,11 +1270,11 @@
archive
hash
- 19147e19b5cfaaaeb83ff1d9025c06df
+ fa7f683ba4ddd7db777c78c8213d2e46
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/google_breakpad-9e60a27-windows-201601151025.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/google_breakpad-7398ce15b79da-windows-201703090621.tar.bz2
name
windows
@@ -1170,7 +1330,7 @@
hash
e81d9e4526ceac49f1532d6518085985
url
- https://bitbucket.org/alchemyviewer/publiclibs/downloads/gperftools-2.1-windows-20140120.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib/gperftools-2.1-windows-20140120.tar.bz2
name
windows
@@ -1324,11 +1484,11 @@
archive
hash
- 581db1bb70a7f6b9a6718121d22597a9
+ a9a7af50c5c1b5319dfea82cd09fdd84
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/jpeglib-1.4.2-windows-201601151022.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/jpeglib-1.5.1-windows-201703090615.tar.bz2
name
windows
@@ -1410,11 +1570,11 @@
archive
hash
- 440a81e502be320c789337653ad1af7c
+ cfce0b7d65b28b34fd0643cbcf7b0bac
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/libhunspell-1.3.3-windows-201601151018.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/libhunspell-1.6.0-windows-201703090619.tar.bz2
name
windows
@@ -1516,11 +1676,11 @@
archive
hash
- 1bed832715f068e3363ba90a0415092f
+ e2927116641e2c74ada092bfb6b49a8d
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/libndofdev-0.1-windows-201601151016.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/libndofdev-0.1-windows-201703090613.tar.bz2
name
windows
@@ -1634,11 +1794,11 @@
archive
hash
- 5e7b3ea13fec60f6c9a8965a390cfbd5
+ 9aad0afaf2c1895224454c1dc433f481
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/libpng-1.6.21-windows-201603011800.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/libpng-1.6.34-windows-201710172201.tar.bz2
name
windows
@@ -1720,11 +1880,11 @@
archive
hash
- 6f1e3fcceab669df5c3d1c66821b2f24
+ a3f7c3421e9e4921dda3558c3b36dc59
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/libxml2-2.9.3-windows-201601151053.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/libxml2-2.9.4-windows-201703090740.tar.bz2
name
windows
@@ -1747,80 +1907,6 @@
version
2.9.3
- llceflib
-
- copyright
- Copyright (c) 2014-2015, Linden Research, Inc.
- description
- LLCefLib implements a headless web browser, rendering modern web content to a memory buffer and providing an API for injecting mouse and keyboard events. It uses the Chromium Embedded Framework (https://bitbucket.org/chromiumembedded/cef)
- license
- LGPL
- license_file
- LICENSES/llceflib.txt
- name
- llceflib
- platforms
-
- darwin
-
- archive
-
- hash
- 9551150830531abc405888066437e2c2
- hash_algorithm
- md5
- url
- https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/llceflib-3.2526.1364.gf6bf57b-darwin-201601160847.tar.bz2
-
- name
- darwin
-
- linux64
-
- archive
-
- hash
- 0e7613b2e038e18488452c2a9882144d
- hash_algorithm
- md5
- url
- http://depot.alchemyviewer.org/pub/linux64/lib-trusty/llceflib-3.2526.1373.gb660893-linux64-201603281900.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 30bbc702d7533f8e2c56bdd0f5f22b59
- hash_algorithm
- md5
- url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/llceflib-3.2526.1364.gf6bf57b-windows-201601160235.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 230e4ccb442bd538eabe2167f351a20d
- hash_algorithm
- md5
- url
- http://depot.alchemyviewer.org/pub/windows64/lib-vc14/llceflib-3.2526.1364.gf6bf57b-windows64-201601160304.tar.bz2
-
- name
- windows64
-
-
- version
- 3.2526.1373.gb660893
-
llphysicsextensions_stub
copyright
@@ -2062,11 +2148,11 @@
archive
hash
- e8c42c8ee03d570fa5e7fb88e7e1bc92
+ 41d090321853ea941c5ca57ba0d471d0
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/ogg_vorbis-1.3.2-1.3.5-windows-201601151012.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/ogg_vorbis-1.3.2-1.3.5-windows-201703090612.tar.bz2
name
windows
@@ -2236,11 +2322,11 @@
archive
hash
- 91b9fa570258f627a9265452d9e65231
+ 0d25e1794f5d86b675484bf5eda799e4
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/openssl-1.0.2g-windows-201603011823.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/openssl-1.1.0g-windows-201711200028.tar.bz2
name
windows
@@ -2354,11 +2440,11 @@
archive
hash
- 47a3316dae47cc4e7c1ea7b74ba8dd1e
+ 5a78539626b5f23522d0b466247f48b4
hash_algorithm
md5
url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/vivox_3p-slvoice/rev/302004/arch/CYGWIN/installer/slvoice-4.6.0017.22050.302004-windows-302004.tar.bz2
+ http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/21422/157291/slvoice-4.9.0002.30313.517593-windows-517593.tar.bz2
name
windows
@@ -2590,11 +2676,11 @@
archive
hash
- 7a619778a2ea5c3113549529dd4f7288
+ 4cd5d80362fef95fe486b5bc1c373174
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/xmlrpc_epi-0.54.2-windows-201603261505.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/xmlrpc_epi-0.54.2-windows-201703090632.tar.bz2
name
windows
@@ -2676,11 +2762,11 @@
archive
hash
- a26a7a9d550dc6988528e2e70bb5e85b
+ 75651f8b2fa45545461f73ba583180bb
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/windows/lib-vc14/zlib-1.2.8-windows-201601150945.tar.bz2
+ https://depot.alchemyviewer.org/pub/windows/lib-vc141/zlib-1.2.11-windows-201703090604.tar.bz2
name
windows
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index e9868cfea..32be5e4b4 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -108,7 +108,7 @@ if (WINDOWS)
endif (USE_LTO)
if (WORD_SIZE EQUAL 32)
- add_compile_options(/arch:SSE3)
+ add_compile_options(/arch:SSE2)
endif (WORD_SIZE EQUAL 32)
if (NOT DISABLE_FATAL_WARNINGS)
diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake
index 81a228706..8c441d650 100644
--- a/indra/cmake/BuildVersion.cmake
+++ b/indra/cmake/BuildVersion.cmake
@@ -46,6 +46,7 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
set(VIEWER_CHANNEL_VERSION_DEFINES
"LL_VIEWER_CHANNEL=\"${VIEWER_CHANNEL}\""
+ "LL_VIEWER_CHANNEL_GRK=\"${VIEWER_CHANNEL_GRK}\""
"LL_VIEWER_VERSION_MAJOR=${VIEWER_VERSION_MAJOR}"
"LL_VIEWER_VERSION_MINOR=${VIEWER_VERSION_MINOR}"
"LL_VIEWER_VERSION_PATCH=${VIEWER_VERSION_PATCH}"
diff --git a/indra/cmake/CEFPlugin.cmake b/indra/cmake/CEFPlugin.cmake
index 1b4c20ed3..f19e38254 100644
--- a/indra/cmake/CEFPlugin.cmake
+++ b/indra/cmake/CEFPlugin.cmake
@@ -6,7 +6,7 @@ if (USESYSTEMLIBS)
set(CEFPLUGIN OFF CACHE BOOL
"CEFPLUGIN support for the llplugin/llmedia test apps.")
else (USESYSTEMLIBS)
- use_prebuilt_binary(llceflib)
+ 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)
@@ -16,7 +16,7 @@ if (WINDOWS)
set(CEF_PLUGIN_LIBRARIES
libcef.lib
libcef_dll_wrapper.lib
- llceflib.lib
+ dullahan.lib
)
elseif (DARWIN)
FIND_LIBRARY(APPKIT_LIBRARY AppKit)
@@ -31,14 +31,14 @@ elseif (DARWIN)
set(CEF_PLUGIN_LIBRARIES
${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a
- ${ARCH_PREBUILT_DIRS_RELEASE}/libLLCefLib.a
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libdullahan.a
${APPKIT_LIBRARY}
${CEF_LIBRARY}
)
elseif (LINUX)
set(CEF_PLUGIN_LIBRARIES
- llceflib
+ dullahan
cef_dll_wrapper
cef
)
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index e500ac753..4c9a830f0 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -20,11 +20,9 @@ if(WINDOWS)
set(vivox_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
set(vivox_files
SLVoice.exe
- ca-bundle.crt
- libsndfile-1.dll
vivoxsdk.dll
ortp.dll
- vivoxoal.dll
+ vivoxplatform.dll
)
#*******************************
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index f1ccfcd34..016f031ea 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")
@@ -24,13 +22,36 @@ set(LIBS_OPEN_PREFIX)
set(SCRIPTS_PREFIX ../scripts)
set(VIEWER_PREFIX)
set(INTEGRATION_TESTS_PREFIX)
-set(LL_TESTS OFF CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation)")
+option(LL_TESTS "Build and run unit and integration tests (disable for build timing runs to reduce variation" 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 Whole Program Optimization and related folding and binary reduction routines" OFF)
+option(UNATTENDED "Disable use of uneeded tooling for automated builds" OFF)
+
+# 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(DISABLE_FATAL_WARNINGS TRUE CACHE BOOL "Set this to FALSE to enable fatal warnings.")
-option(INCREMENTAL_LINK "Use incremental linking or incremental LTCG for LTO on win32 builds (enable for faster links on some machines)" OFF)
-option(USE_LTO "Enable Whole Program Optimization and related folding and binary reduction routines" OFF)
+# Audio Engines
+option(FMODSTUDIO "Build with support for the FMOD Studio audio engine" OFF)
+
+# Window implementation
+option(LLWINDOW_SDL2 "Use SDL2 for window and input handling" OFF)
# Proprietary Library Features
option(NVAPI "Use nvapi driver interface library" OFF)
@@ -60,13 +81,14 @@ if (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake)
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 "http://bitbucket.org/lindenlab/master-message-template/raw/tip/message_template.msg" CACHE STRING "Location of the master message template")
+set(TEMPLATE_VERIFIER_MASTER_URL "https://forge.alchemyviewer.org/alchemy/tools/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 (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(WINDOWS ON BOOL FORCE)
if (WORD_SIZE EQUAL 64)
@@ -142,63 +164,94 @@ 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}")
+ if (XCODE_VERSION LESS 8.0.0)
+ message( FATAL_ERROR "Xcode 8.0.0 or greater is required." )
+ endif (XCODE_VERSION LESS 8.0.0)
+ message( "Building with " ${CMAKE_OSX_SYSROOT} )
+ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12)
- # 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)
+ set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0")
+ set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL 3)
+ set(CMAKE_XCODE_ATTRIBUTE_GCC_STRICT_ALIASING NO)
+ set(CMAKE_XCODE_ATTRIBUTE_GCC_FAST_MATH NO)
+ set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
+ set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++14")
+ if (USE_AVX2)
+ set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS avx2)
+ elseif (USE_AVX)
+ set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS avx)
+ else ()
+ set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS sse4.1)
+ endif ()
- # 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)
+ if (${CMAKE_BUILD_TYPE} STREQUAL "Release")
+ set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym)
+ else (${CMAKE_BUILD_TYPE} STREQUAL "Release")
+ set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf)
+ endif (${CMAKE_BUILD_TYPE} STREQUAL "Release")
- 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(AUTOBUILD_PLATFORM_NAME "darwin")
+ set(ADDRESS_SIZE 64)
+ if (NOT CMAKE_OSX_ARCHITECTURES)
+ if (ADDRESS_SIZE EQUAL 64)
+ set(CMAKE_OSX_ARCHITECTURES x86_64)
+ else (ADDRESS_SIZE EQUAL 64)
+ set(CMAKE_OSX_ARCHITECTURES i386)
+ endif (ADDRESS_SIZE EQUAL 64)
+ endif (NOT CMAKE_OSX_ARCHITECTURES)
+ if (ADDRESS_SIZE EQUAL 64)
+ set(ARCH x86_64)
+ else (ADDRESS_SIZE EQUAL 64)
+ set(ARCH i386)
+ endif (ADDRESS_SIZE EQUAL 64)
set(LL_ARCH ${ARCH}_darwin)
set(LL_ARCH_DIR universal-darwin)
+ set(AUTOBUILD_PLATFORM_NAME "darwin" CACHE STRING "Autobuild Platform Name")
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# Default deploy grid
set(GRID agni CACHE STRING "Target Grid")
-set(VIEWER_CHANNEL "Singularity Test" CACHE STRING "Viewer Channel Name")
+set(VIEWER_PRODUCT_NAME "Singularity" CACHE STRING "Viewer Base Name")
+string(TOLOWER ${VIEWER_PRODUCT_NAME} VIEWER_PRODUCT_NAME_LOWER)
-string(REPLACE " " "" VIEWER_CHANNEL_NOSPACE ${VIEWER_CHANNEL})
-set(VIEWER_CHANNEL_NOSPACE ${VIEWER_CHANNEL_NOSPACE} CACHE STRING "Prefix used for resulting artifacts.")
+set(VIEWER_CHANNEL_BASE "Test" CACHE STRING "Viewer Channel Name")
+set(VIEWER_CHANNEL "${VIEWER_PRODUCT_NAME} ${VIEWER_CHANNEL_BASE}")
+string(TOLOWER ${VIEWER_CHANNEL} VIEWER_CHANNEL_LOWER)
+string(REPLACE " " "" VIEWER_CHANNEL_ONEWORD ${VIEWER_CHANNEL})
+
+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_BASE MATCHES "Test")
+ set(VIEWER_CHANNEL_GRK "τ")
+ elseif (VIEWER_CHANNEL_BASE MATCHES "Alpha")
+ set(VIEWER_CHANNEL_GRK "α")
+ elseif (VIEWER_CHANNEL_BASE MATCHES "Beta")
+ set(VIEWER_CHANNEL_GRK "β")
+ endif ()
+endif (NOT VIEWER_CHANNEL_GRK)
+
+if(VIEWER_CHANNEL_LOWER MATCHES "^${VIEWER_PRODUCT_NAME_LOWER} release")
+ set(VIEWER_PACKAGE_ID "${VIEWER_PRODUCT_NAME}Release")
+ set(VIEWER_EXE_STRING "${VIEWER_PRODUCT_NAME}Viewer")
+ set(VIEWER_SHORTCUT_STRING "${VIEWER_PRODUCT_NAME} Viewer")
+else()
+ set(VIEWER_PACKAGE_ID ${VIEWER_CHANNEL_ONEWORD})
+ set(VIEWER_EXE_STRING ${VIEWER_CHANNEL_ONEWORD})
+ set(VIEWER_SHORTCUT_STRING ${VIEWER_CHANNEL})
+endif()
+
+set(VIEWER_CHANNEL_NOSPACE ${VIEWER_CHANNEL_ONEWORD} CACHE STRING "Prefix used for resulting artifacts.")
set(VIEWER_BRANDING_ID "singularity" CACHE STRING "Viewer branding id")
-set(ENABLE_SIGNING OFF CACHE BOOL "Enable signing the viewer")
-set(SIGNING_IDENTITY "" CACHE STRING "Specifies the signing identity to use, if necessary.")
-
set(VERSION_BUILD "0" CACHE STRING "Revision number passed in from the outside")
-set(STANDALONE OFF CACHE BOOL "Do not use Linden-supplied prebuilt libraries.")
-set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.")
+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)
+mark_as_advanced(AUTOBUILD_PLATFORM_NAME)
+
endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake
index 71bf0bd0b..2984f5261 100644
--- a/indra/cmake/ViewerMiscLibs.cmake
+++ b/indra/cmake/ViewerMiscLibs.cmake
@@ -15,3 +15,5 @@ else (NOT STANDALONE)
endif(LINUX AND ${ARCH} STREQUAL "x86_64")
set(STANDALONE ON)
endif(NOT STANDALONE)
+
+use_prebuilt_binary(fonts)
diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp
index 2dc3d49b4..ea783c968 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)
@@ -184,6 +183,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 26c9fc230..a7887fa9a 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
{
@@ -72,7 +63,7 @@ public:
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/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp
index 7ff348d81..3f5b65f52 100644
--- a/indra/llcharacter/llmotioncontroller.cpp
+++ b/indra/llcharacter/llmotioncontroller.cpp
@@ -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)
{
diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp
index 7fbb5c137..64de502b6 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:
- {
- std::unique_ptr step(new LLGestureStepAnimation());
- BOOL ok = step->deserialize(dp);
- if (!ok) return FALSE;
- mSteps.push_back(step.release());
- break;
- }
- case STEP_SOUND:
- {
- std::unique_ptr step(new LLGestureStepSound());
- BOOL ok = step->deserialize(dp);
- if (!ok) return FALSE;
- mSteps.push_back(step.release());
- break;
- }
- case STEP_CHAT:
- {
- std::unique_ptr step(new LLGestureStepChat());
- BOOL ok = step->deserialize(dp);
- if (!ok) return FALSE;
- mSteps.push_back(step.release());
- break;
- }
- case STEP_WAIT:
- {
- std::unique_ptr step(new LLGestureStepWait());
- BOOL ok = step->deserialize(dp);
- if (!ok) return FALSE;
- mSteps.push_back(step.release());
- 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 8e4821357..68395465b 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 @@ public:
// 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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
// 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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
};
-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 @@ public:
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/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 2d52cbb1a..c65c4717c 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -131,6 +131,7 @@ public:
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(); }
@@ -379,6 +380,7 @@ namespace
using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
virtual LLSD get(const LLSD::String&) const;
+ virtual LLSD getKeys() const;
void insert(const LLSD::String& k, const LLSD& v);
virtual void erase(const LLSD::String&);
LLSD& ref(const LLSD::String&);
@@ -421,6 +423,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));
@@ -501,7 +515,7 @@ namespace
virtual LLSD get(LLSD::Integer) const;
void set(LLSD::Integer, const LLSD&);
void insert(LLSD::Integer, const LLSD&);
- void append(const LLSD&);
+ LLSD& append(const LLSD&);
virtual void erase(LLSD::Integer);
LLSD& ref(LLSD::Integer);
virtual const LLSD& ref(LLSD::Integer) const;
@@ -569,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)
@@ -862,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)
@@ -895,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)
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index 6e71a717e..e9fcb8b47 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -287,6 +287,7 @@ public:
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 @@ public:
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&);
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index bb4dea06d..0a9fbb2a6 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 << " " << LLSD_NOTATION_HEADER << " ?>\n";
+ f = new LLSDNotationFormatter;
+ break;
+
default:
LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
}
@@ -168,6 +174,10 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
{
p = new LLSDXMLParser;
}
+ else if (header == LLSD_NOTATION_HEADER)
+ {
+ p = new LLSDNotationParser;
+ }
else
{
LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index c47cb6885..3b339355d 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/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 876589655..dc4a960c9 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -192,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.
@@ -313,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()
*****************************************************************************/
@@ -672,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 (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+ {
+ clone.append(llsd_clone(*ita, 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 (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+ {
+ shallow.append(*ita);
+ }
+ }
+ else
+ {
+ return value;
+ }
+
+ return shallow;
+}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 99cb79aa5..1d68009ca 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
@@ -419,4 +435,87 @@ private:
} // 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/llstring.cpp b/indra/llcommon/llstring.cpp
index 7203b4d6e..4e8649503 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -233,7 +233,7 @@ llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len)
{
out += cur_char;
}
- i++;
+ ++i;
}
return out;
}
@@ -493,7 +493,7 @@ std::string wstring_to_utf8str(const LLWString& utf32str, S32 len)
std::string out;
out.reserve(len);
- for (S32 i = 0; i < len; i++)
+ for (S32 i = 0; i < len; ++i)
{
S32 n = wchar_to_utf8chars(utf32str[i], tchars);
tchars[n] = 0;
@@ -576,6 +576,78 @@ 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 S32 index, const S32 max_len)
+{
+ if (0 == max_len)
+ {
+ return std::string();
+ }
+ if (utf8str.length() - index <= max_len)
+ {
+ return utf8str.substr(index, max_len);
+ }
+ else
+ {
+ S32 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 S32 symbol_len)
{
if (0 == symbol_len)
@@ -668,6 +740,12 @@ bool LLStringOps::isHexString(const std::string& str)
}
#if LL_WINDOWS
+
+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)
{
std::string out;
@@ -705,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:
@@ -726,6 +809,67 @@ wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page
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)
@@ -736,7 +880,108 @@ 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;
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 35407ca4e..e1eb06f2b 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -27,6 +27,9 @@
#ifndef LL_LLSTRING_H
#define LL_LLSTRING_H
+#include "llwin32headerslean.h"
+
+#include
#include
#include
//#include
@@ -34,8 +37,12 @@
#include
#include
#include
-#include "llsd.h"
#include "llfasttimer.h"
+#include "llformat.h"
+#include "llsd.h"
+// [RLVa:KB] - Checked: RLVa-2.1.0
+#include
+// [/RLVa:KB]
#if LL_LINUX || LL_SOLARIS
#include
@@ -305,7 +312,7 @@ public:
static bool isValidIndex(const string_type& string, size_type i)
{
- return !string.empty() && (i <= string.size());
+ return !string.empty() && (0 <= i) && (i <= string.size());
}
static bool contains(const string_type& string, T c, size_type i=0)
@@ -343,6 +350,19 @@ public:
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);
@@ -503,6 +523,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.
@@ -510,37 +561,91 @@ 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.
+//
#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);}
@@ -575,6 +680,11 @@ 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(
@@ -623,22 +733,77 @@ LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
* This replaces the unsafe W2A macro from ATL.
*/
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)
+{
+ 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));
/**
* Converts a string to wide string.
- *
- * It will allocate memory for result string with "new []". Don't forget to release it with "delete []".
*/
-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,
+ 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));
/**
- * Converts incoming string into urf8 string
+ * Convert a Windows wide string to our LLWString
+ */
+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));
+
+/**
+ * Convert LLWString to Windows wide string
+ */
+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 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
@@ -1612,6 +1777,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/llunittype.h b/indra/llcommon/llunittype.h
index ac8504ca6..81f244e42 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -132,23 +132,34 @@ struct LLUnit
return mValue;
}
- LL_FORCE_INLINE void value(storage_t value)
+ LL_FORCE_INLINE void value(const storage_t& value)
{
mValue = value;
}
template
- storage_t valueInUnits()
+ storage_t valueInUnits() const
{
return LLUnit(*this).value();
}
template
- void valueInUnits(storage_t value)
+ 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;
@@ -159,60 +170,60 @@ struct LLUnit
mValue -= convert(other).mValue;
}
- LL_FORCE_INLINE void operator *= (storage_t multiplicand)
+ LL_FORCE_INLINE void operator *= (const storage_t& multiplicand)
{
mValue *= multiplicand;
}
- LL_FORCE_INLINE void operator *= (self_t 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 /= (storage_t divisor)
+ LL_FORCE_INLINE void operator /= (const storage_t& divisor)
{
mValue /= divisor;
}
- void operator /= (self_t 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 == (LLUnit other) const
+ LL_FORCE_INLINE bool operator == (const LLUnit& other) const
{
return mValue == convert(other).value();
}
template
- LL_FORCE_INLINE bool operator != (LLUnit other) const
+ LL_FORCE_INLINE bool operator != (const LLUnit& other) const
{
return mValue != convert(other).value();
}
template
- LL_FORCE_INLINE bool operator < (LLUnit other) const
+ LL_FORCE_INLINE bool operator < (const LLUnit& other) const
{
return mValue < convert(other).value();
}
template
- LL_FORCE_INLINE bool operator <= (LLUnit other) const
+ LL_FORCE_INLINE bool operator <= (const LLUnit& other) const
{
return mValue <= convert(other).value();
}
template
- LL_FORCE_INLINE bool operator > (LLUnit other) const
+ LL_FORCE_INLINE bool operator > (const LLUnit& other) const
{
return mValue > convert(other).value();
}
template
- LL_FORCE_INLINE bool operator >= (LLUnit other) const
+ LL_FORCE_INLINE bool operator >= (const LLUnit& other) const
{
return mValue >= convert(other).value();
}
diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h
index faa5f3a75..591635a29 100644
--- a/indra/llcommon/lluri.h
+++ b/indra/llcommon/lluri.h
@@ -32,7 +32,6 @@
#include
class LLSD;
-class LLUUID;
class LLApp;
/**
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 31bbd9036..fe4fb2676 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#include "stdtypes.h"
#include "llpreprocessor.h"
@@ -289,7 +290,7 @@ inline U32 LLUUID::getCRC32() const
}
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;
diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt
index 028117151..e0659895e 100644
--- a/indra/llinventory/CMakeLists.txt
+++ b/indra/llinventory/CMakeLists.txt
@@ -21,12 +21,17 @@ set(llinventory_SOURCE_FILES
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
)
@@ -39,7 +44,9 @@ set(llinventory_HEADER_FILES
llfoldertype.h
llinventory.h
llinventorydefines.h
+ llinventorysettings.h
llinventorytype.h
+ llinvtranslationbrdg.h
lllandmark.h
llnotecard.h
llparcel.h
@@ -47,6 +54,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
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index 5fe513310..f0a865f0d 100644
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -101,11 +101,15 @@ 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_MARKETPLACE_LISTINGS, new FolderEntry("merchant", 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 bea5dc379..5f41578dd 100644
--- a/indra/llinventory/llfoldertype.h
+++ b/indra/llinventory/llfoldertype.h
@@ -97,6 +97,9 @@ public:
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 0a19d27d3..86992aee6 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -1168,10 +1168,10 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
static U32 WT_UNKNOWN = 16; // LLWearableType::WT_UNKNOWN
static U32 WT_COUNT = 17; // LLWearableType::WT_COUNT
// 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)
diff --git a/indra/llinventory/llinventorydefines.cpp b/indra/llinventory/llinventorydefines.cpp
index 7def65a30..575331a26 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.
+ * 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 fc81d1f72..54562673f 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.
+ * 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 @@ public:
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 000000000..bf8043d4d
--- /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 000000000..906540689
--- /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 fcef1611c..30f98eb2a 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -191,7 +191,7 @@ LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType a
}
else
{
- return IT_NONE;
+ return IT_UNKNOWN;
}
}
@@ -210,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 1d9627ffb..2350867b4 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -135,6 +135,8 @@ public:
// 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 000000000..715c60c30
--- /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 b3924ed6e..407689b79 100644
--- a/indra/llinventory/llparcel.cpp
+++ b/indra/llinventory/llparcel.cpp
@@ -230,6 +230,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)
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index ce3e0eab1..e91f9a320 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;
@@ -105,6 +106,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);
@@ -508,6 +513,13 @@ public:
{ 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 +605,10 @@ public:
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 +619,6 @@ public:
BOOL getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; }
BOOL getSellWithObjects() const { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; }
-
protected:
LLUUID mID;
LLUUID mOwnerID;
@@ -674,9 +689,13 @@ protected:
BOOL mRegionPushOverride;
BOOL mRegionDenyAnonymousOverride;
BOOL mRegionDenyAgeUnverifiedOverride;
+ BOOL mRegionAllowAccessoverride;
+ BOOL mRegionAllowEnvironmentOverride;
BOOL mAllowGroupAVSounds;
BOOL mAllowAnyAVSounds;
+ S32 mCurrentEnvironmentVersion;
+ bool mIsDefaultDayCycle;
public:
// HACK, make private
diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp
new file mode 100644
index 000000000..7d7547ecb
--- /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 (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+ {
+ newSettings[key_name].append(*ita);
+ }
+ 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 (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+ {
+ newSettings[key_name].append(*ita);
+ }
+ 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 000000000..592ae3478
--- /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 000000000..25516ec6e
--- /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 (LLSD::array_const_iterator it = curtrack.beginArray(); it != curtrack.endArray(); ++it)
+ {
+ LLSettingsBase::TrackPosition keyframe = LLSettingsBase::TrackPosition((*it)[SETTING_KEYKFRAME].asReal());
+ keyframe = llclamp(keyframe, 0.0f, 1.0f);
+ LLSettingsBase::ptr_t setting;
+
+
+ if ((*it).has(SETTING_KEYNAME))
+ {
+ std::string key_name = (*it)[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 (LLSD::array_iterator track = value.beginArray(); track != value.endArray(); ++track)
+ {
+ S32 index = 0;
+ while (index < (*track).size())
+ {
+ LLSD& elem = (*track)[index];
+
+ ++framecount;
+ if (index >= LLSettingsDay::FRAME_MAX)
+ {
+ (*track).erase(index);
+ continue;
+ }
+
+ if (!elem.has(LLSettingsDay::SETTING_KEYKFRAME))
+ {
+ (*track).erase(index);
+ continue;
+ }
+
+ if (!elem[LLSettingsDay::SETTING_KEYKFRAME].isReal())
+ {
+ (*track).erase(index);
+ continue;
+ }
+
+ if (!elem.has(LLSettingsDay::SETTING_KEYNAME) &&
+ !elem.has(LLSettingsDay::SETTING_KEYID))
+ {
+ (*track).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(S32 track)
+{
+ static CycleTrack_t emptyTrack;
+ if (mDayTracks.size() <= track)
+ return emptyTrack;
+
+ return mDayTracks[track];
+}
+
+const LLSettingsDay::CycleTrack_t& LLSettingsDay::getCycleTrackConst(S32 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 000000000..8776f6725
--- /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(S32 track);
+ const CycleTrack_t & getCycleTrackConst(S32 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 000000000..0eac6294e
--- /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.4099, 0.4099, 0.4099, 0.0).getValue();
+ dfltsetting[SETTING_CLOUD_POS_DENSITY1] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
+ dfltsetting[SETTING_CLOUD_POS_DENSITY2] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).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.000, 0.0010, -0.4799, 1.0).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.7342, 0.7815, 0.8999, 0.0).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 000000000..cd173a6b1
--- /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 000000000..4af1a5dc0
--- /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 000000000..e0bfd29f2
--- /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 48cad96da..29bc58b33 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -87,6 +87,7 @@ set(llmath_HEADER_FILES
raytrace.h
v2math.h
v3color.h
+ v3colorutil.h
v3dmath.h
v3math.h
v4color.h
diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index 721503443..9ea9f0993 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 aed99de28..1495d0584 100644
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -154,6 +154,7 @@ public:
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/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index 699eaf2ab..1529b2587 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 4106f9ffe..e7a279fb4 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 @@ public:
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;
@@ -79,6 +84,7 @@ public:
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)
@@ -100,6 +106,7 @@ public:
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
@@ -166,6 +173,24 @@ public:
//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();
+}
+
// checker
inline BOOL LLQuaternion::isFinite() const
{
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 562b45e31..744423a67 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2195,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.
@@ -2202,7 +2208,6 @@ BOOL LLVolume::generate()
{
rot_mat.rotate(*profile++, tmp);
dst->setAdd(tmp,offset);
- llassert(dst->isFinite3());
++dst;
}
}
diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp
index bc1c2502d..e4706c75b 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 c1ec3f516..b738fe70c 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
@@ -145,6 +146,10 @@ inline LLVector2::LLVector2(const LLVector3 &vec)
mV[VY] = vec.mV[VY];
}
+inline LLVector2::LLVector2(const LLSD &sd)
+{
+ setValue(sd);
+}
// Clear and Assignment Functions
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index 6fe39e219..1a5cbeb51 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -100,6 +100,23 @@ public:
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
diff --git a/indra/llmath/v3colorutil.h b/indra/llmath/v3colorutil.h
new file mode 100644
index 000000000..6d8cd9329
--- /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/v4color.h b/indra/llmath/v4color.h
index 3f9e1efd8..2297a6616 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
@@ -477,6 +479,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/v4math.h b/indra/llmath/v4math.h
index b4a59f01c..a179ced70 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)
@@ -175,6 +188,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,6 +220,11 @@ inline LLVector4::LLVector4(const LLVector3 &vec, F32 w)
mV[VW] = w;
}
+inline LLVector4::LLVector4(const LLSD &sd)
+{
+ setValue(sd);
+}
+
inline BOOL LLVector4::isFinite() const
{
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index f06b751d4..5e139e7cb 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -58,6 +58,42 @@ const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-0
const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds
+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;
+// }
+
+}
+
///----------------------------------------------------------------------------
/// LLAssetInfo
///----------------------------------------------------------------------------
@@ -150,13 +186,13 @@ void LLAssetInfo::setFromNameValue( const LLNameValue& nv )
}
///----------------------------------------------------------------------------
-/// LLAssetRequest
+/// LLBaseDownloadRequest
///----------------------------------------------------------------------------
LLBaseDownloadRequest::LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetType::EType type)
: mUUID(uuid),
mType(type),
- mDownCallback(NULL),
+ mDownCallback(),
mUserData(NULL),
mHost(),
mIsTemp(FALSE),
@@ -173,19 +209,21 @@ LLBaseDownloadRequest::LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetTy
LLBaseDownloadRequest::~LLBaseDownloadRequest()
{
}
+
// virtual
LLBaseDownloadRequest* LLBaseDownloadRequest::getCopy()
{
return new LLBaseDownloadRequest(*this);
}
+
///----------------------------------------------------------------------------
/// LLAssetRequest
///----------------------------------------------------------------------------
LLAssetRequest::LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType type)
: LLBaseDownloadRequest(uuid, type),
- mUpCallback( NULL ),
+ mUpCallback(),
mInfoCallback( NULL ),
mIsLocal(FALSE),
mIsUserWaiting(FALSE),
@@ -273,6 +311,7 @@ LLBaseDownloadRequest* LLEstateAssetRequest::getCopy()
return new LLEstateAssetRequest(*this);
}
+
///----------------------------------------------------------------------------
/// LLAssetStorage
///----------------------------------------------------------------------------
@@ -291,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,
@@ -443,7 +480,7 @@ 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,
+ LLAssetStorage::LLGetAssetCallback callback,
void *user_data,
BOOL is_priority)
{
@@ -1305,9 +1342,13 @@ BOOL is_priority)
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)
{
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index 7e924f216..0e29d9207 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"
@@ -60,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:
@@ -111,15 +120,13 @@ protected:
LLAssetType::EType mType;
public:
- void (*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat);
-
+ LLGetAssetCallback mDownCallback;
+// void(*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat);
void *mUserData;
LLHost mHost;
BOOL mIsTemp;
-
F64Seconds mTime; // Message system time
-
BOOL mIsPriority;
BOOL mDataSentInFirstPacket;
BOOL mDataIsInVFS;
@@ -135,7 +142,8 @@ public:
virtual LLBaseDownloadRequest* getCopy();
- void (*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
+ LLStoreAssetCallback mUpCallback;
+// void (*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
void (*mInfoCallback)(LLAssetInfo *, void *, S32);
BOOL mIsLocal;
@@ -185,8 +193,6 @@ protected:
// 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 LLAssetStorage
@@ -195,7 +201,8 @@ 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
{
@@ -240,10 +247,9 @@ public:
// public interface methods
// note that your callback may get called BEFORE the function returns
-
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
@@ -382,8 +388,8 @@ 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) = 0;
@@ -429,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/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 2e39e17b5..be364a3bd 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 @@ protected:
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;
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index eafb0ea97..143914408 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;
diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp
index 75ae8fff7..3043f61e6 100644
--- a/indra/llmessage/llcircuit.cpp
+++ b/indra/llmessage/llcircuit.cpp
@@ -544,7 +544,7 @@ void LLCircuitData::checkPeriodTime()
mBytesOutLastPeriod = mBytesOutThisPeriod;
mBytesInThisPeriod = S32Bytes(0);
mBytesOutThisPeriod = S32Bytes(0);
- mLastPeriodLength = period_length;
+ mLastPeriodLength = F32Seconds::convert(period_length);
mPeriodTime = mt_sec;
}
@@ -1390,8 +1390,8 @@ F32Milliseconds LLCircuitData::getPingInTransitTime()
if (mPingsInTransit)
{
- time_since_ping_was_sent = ((mPingsInTransit*mHeartbeatInterval - F32Seconds(1))
- + (LLMessageSystem::getMessageTimeSeconds() - mPingTime));
+ time_since_ping_was_sent = F32Milliseconds::convert(((mPingsInTransit*mHeartbeatInterval - F32Seconds(1))
+ + (LLMessageSystem::getMessageTimeSeconds() - mPingTime)));
}
return time_since_ping_was_sent;
diff --git a/indra/llmessage/lldispatcher.cpp b/indra/llmessage/lldispatcher.cpp
index 6f740346e..ffcb68cae 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 9d1751f58..43c63ac4d 100644
--- a/indra/llmessage/lldispatcher.h
+++ b/indra/llmessage/lldispatcher.h
@@ -105,6 +105,12 @@ public:
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/llregionflags.h b/indra/llmessage/llregionflags.h
index c1cf26574..fb2c9185b 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
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 1a588ae8d..6598a402c 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");
@@ -1374,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");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index ec1f2da86..e57e2379e 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;
@@ -1374,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;
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 75de5393f..e1edaa80f 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -62,6 +62,7 @@ bool LLPluginClassMedia::init_impl(void)
return true;
}
+
void LLPluginClassMedia::reset_impl(void)
{
mTextureParamsReceived = false;
@@ -91,16 +92,22 @@ 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);
@@ -119,6 +126,10 @@ void LLPluginClassMedia::reset_impl(void)
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
}
@@ -189,7 +205,14 @@ void LLPluginClassMedia::idle_impl(void)
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.
@@ -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);
}
@@ -335,7 +358,7 @@ bool LLPluginClassMedia::textureValid(void)
mMediaHeight <= 0 ||
mRequestedMediaWidth != mMediaWidth ||
mRequestedMediaHeight != mMediaHeight ||
- getBitsData() == NULL
+ getBitsData() == nullptr
)
return false;
@@ -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;
}
@@ -678,15 +701,22 @@ F64 LLPluginClassMedia::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 (std::vector::const_iterator in_iter = files.begin(); in_iter != files.end(); ++in_iter)
+ {
+ file_list.append(LLSD::String(*in_iter));
+ }
+ message.setValueLLSD("file_list", file_list);
+
sendMessage(message);
}
@@ -704,6 +734,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");
@@ -722,12 +764,33 @@ void LLPluginClassMedia::paste()
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_logs)
+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("cache_path", user_data_path_cache);
message.setValue("cookies_path", user_data_path_cookies);
- message.setValue("logs_path", user_data_path_logs);
+ message.setValue("cef_log_file", user_data_path_cef_log);
+
sendMessage(message);
}
@@ -825,7 +888,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 << ", "
@@ -926,7 +989,6 @@ 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;
@@ -936,10 +998,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
}
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");
@@ -961,6 +1020,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");
@@ -973,14 +1040,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")
@@ -1042,7 +1120,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")
@@ -1057,13 +1140,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);
@@ -1102,7 +1178,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
// }
// 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;
}
}
@@ -1145,7 +1221,7 @@ void LLPluginClassMedia::focus(bool 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");
@@ -1165,27 +1241,23 @@ void LLPluginClassMedia::clear_cookies()
sendMessage(message);
}
-void LLPluginClassMedia::set_cookies(const std::string &cookies)
+void LLPluginClassMedia::cookies_enabled(bool enable)
{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
- message.setValue("cookies", cookies);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::enable_cookies(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);
}
@@ -1217,16 +1289,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");
@@ -1276,6 +1338,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");
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index c2b993488..ebb9a36b5 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -57,6 +57,7 @@ public:
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,6 +73,7 @@ public:
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; };
@@ -83,7 +85,7 @@ public:
// 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
@@ -127,9 +129,9 @@ public:
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);
@@ -137,7 +139,7 @@ public:
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);
@@ -146,6 +148,12 @@ public:
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; };
@@ -155,8 +163,16 @@ public:
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_cache, const std::string &user_data_path_cookies, const std::string &user_data_path_logs);
+ 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);
@@ -167,17 +183,15 @@ public:
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);
@@ -215,6 +229,13 @@ public:
// 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; };
@@ -232,6 +253,9 @@ public:
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; };
@@ -326,8 +350,12 @@ protected:
int mMediaWidth;
int mMediaHeight;
+ F64 mZoomFactor;
+
float mRequestedVolume;
+ // Priority of this media stream
+ EPriority mPriority;
int mLowPrioritySizeLimit;
bool mAllowDownsample;
@@ -343,9 +371,15 @@ protected:
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;
@@ -368,6 +402,8 @@ protected:
std::string mClickNavType;
std::string mClickTarget;
std::string mClickUUID;
+ bool mClickEnforceTarget;
+ std::string mOverrideClickTarget;
std::string mDebugMessageText;
std::string mDebugMessageLevel;
S32 mGeometryX;
@@ -380,6 +416,7 @@ protected:
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 391c23d88..010f54c8f 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -34,7 +34,6 @@
#include
class LLPluginClassMedia;
-class LLPluginCookieStore;
class LLPluginClassMediaOwner
{
@@ -86,7 +85,6 @@ public:
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/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 9c5579119..f954d2cc8 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"
@@ -279,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);
@@ -298,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;
@@ -487,20 +484,12 @@ void LLFontFreetype::renderGlyph(const U32 glyph_index) const
if (mFTFace == NULL)
return;
- FT_Error error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_DEFAULT);
-#ifdef SHOW_ASSERT
- if (error)
+ if (FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_RENDER | FT_LOAD_TARGET_LIGHT) != 0)
{
- LL_ERRS() << "FT_Load_Glyph returned " << error << LL_ENDL;
+ // 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));
}
-#endif
- error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode);
-#ifdef SHOW_ASSERT
- if (error)
- {
- LL_ERRS() << "FT_Render_Glyph returned " << error << LL_ENDL;
- }
-#endif
+
mRenderGlyphCount++;
}
@@ -568,6 +557,7 @@ 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/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index bb9f6e4c8..1dea74985 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -26,24 +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 "lltexture.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
@@ -52,7 +56,7 @@ 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;
LLColor4U LLFontGL::sShadowColor(0, 0, 0, 255);
LLFontRegistry* LLFontGL::sFontRegistry = NULL;
@@ -937,7 +941,7 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st
sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
sScaleX = x_scale;
sScaleY = y_scale;
- sAppDir = app_dir;
+ sFontDir = app_dir;
// Font registry init
if (!sFontRegistry)
@@ -997,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;
@@ -1115,6 +1119,7 @@ LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
//else leave baseline
return gl_vfont_align;
}
+
//static
LLFontGL* LLFontGL::getFontMonospace()
{
@@ -1203,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)
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index 1c5a9f94f..4c1d409be 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -214,7 +214,8 @@ public:
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;
@@ -235,7 +236,6 @@ protected:
// Registry holds all instantiated fonts.
static LLFontRegistry* sFontRegistry;
-
};
#endif
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index 98ee83193..7e11477e8 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -225,7 +225,7 @@ std::string currentOsName()
return "Windows";
#elif LL_DARWIN
return "Mac";
-#elif LL_SDL
+#elif LL_SDL || LL_MESA_HEADLESS
return "Linux";
#else
return "";
@@ -426,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;
@@ -441,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;
@@ -449,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;
}
@@ -491,6 +491,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
{
LL_WARNS() << "createFont failed in some way" << LL_ENDL;
}
+
mFontMap[norm_desc] = result;
return result;
}
@@ -533,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/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
index 505dcf670..0096525f0 100644
--- a/indra/llrender/llpostprocess.cpp
+++ b/indra/llrender/llpostprocess.cpp
@@ -502,8 +502,8 @@ void LLPostProcess::destroyGL()
/*static*/void LLPostProcess::cleanupClass()
{
- if(instanceExists())
- getInstance()->destroyGL() ;
+ if (instanceExists())
+ deleteSingleton();
}
void LLPostProcess::copyFrameBuffer()
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 3996470be..e2e34538b 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -4477,9 +4477,22 @@ void LLTextEditor::replaceUrl(const std::string &url,
{
S32 start = seg->getStart();
S32 end = seg->getEnd();
- text = text.substr(0, start) + wlabel + text.substr(end, text.size() - end + 1);
- seg->setEnd(start + wlabel.size());
- modified = true;
+ 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?
@@ -4508,7 +4521,6 @@ void LLTextEditor::replaceUrl(const std::string &url,
{
mWText = text;
mTextIsUpToDate = FALSE;
- deselect();
setCursorPos(mCursorPos);
needsReflow();
}
diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp
index b98ff7768..c1ae9eae1 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.clear();
- }
- if (mSkinBaseDir.empty())
- {
- // ...normal installation running
- mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
- }
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
mOSUserDir = getCurrentUserHome(tmp_str);
mOSUserAppDir = "";
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index 29ab1a5c9..1127614aa 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);
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 9f89641a3..8547f1408 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -140,18 +140,7 @@ LLDir_Win32::LLDir_Win32()
// LL_INFOS() << "mAppRODataDir = " << mAppRODataDir << LL_ENDL;
- auto build_dir_pos = mExecutableDir.rfind("build-");
- if (build_dir_pos != std::string::npos)
- {
- // ...we're in a dev checkout
- mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "indra" + mDirDelimiter + "newview" + mDirDelimiter + "skins";
- if (LLFile::isdir(mSkinBaseDir))
- LL_INFOS() << "Running in dev checkout with mSkinBaseDir " << mSkinBaseDir << LL_ENDL;
- else mSkinBaseDir.clear();
- }
-
- if (mSkinBaseDir.empty()) // ...normal installation running
- mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
// Build the default cache directory
mDefaultCacheDir = buildSLOSCacheDir();
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index f64b48667..756660716 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 = 5;
-const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:", "mailto:" };
-
+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 cf92c3a51..d05b00b95 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -168,7 +168,7 @@ public:
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();
@@ -290,11 +290,7 @@ public:
//
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/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 8c11a05d3..dcde667e3 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,20 +69,20 @@ 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, "Unsupported video card", OSMB_YESNO);
+ S32 button = OSMessageBox(buffer.c_str(), "Unsupported video card", OSMB_YESNO);
if (OSBTN_YES == button)
{
return FALSE;
@@ -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)
+// 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.
+
+bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
{
- OSStatus err;
- BOOL glNeedsInit = FALSE;
+ mRawKeyEvent = event;
+ bool retVal = gKeyboard->handleKeyUp(key, mask);
+ mRawKeyEvent = NULL;
+ return retVal;
+}
- if(mGlobalHandlerRef == NULL)
+bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask)
+{
+ mRawKeyEvent = event;
+ bool retVal = gKeyboard->handleKeyDown(key, mask);
+ mRawKeyEvent = NULL;
+ return retVal;
+}
+
+void callResetKeys()
+{
+ gKeyboard->resetKeys();
+}
+
+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;
+}
+
+void callFocus()
+{
+ if (gWindowImplementation)
{
- InstallApplicationEventHandler(mEventHandlerUPP, GetEventTypeCount (CommandHandlerEventList), CommandHandlerEventList, (void*)this, &mGlobalHandlerRef);
+ gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation);
+ }
+}
+
+void callFocusLost()
+{
+ if (gWindowImplementation)
+ {
+ gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
+ }
+}
+
+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));
+}
+
+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));
+}
+
+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));
+}
+
+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));
+
+}
+
+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));
+}
+
+void callResize(unsigned int width, unsigned int height)
+{
+ if (gWindowImplementation != NULL)
+ {
+ gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height);
+ }
+}
+
+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);
+}
+
+void callMouseExit()
+{
+ gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation);
+}
+
+void callWindowFocus()
+{
+ if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
+ {
+ gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation);
+ // Reset badge count
+ updateBadge(0);
+ }
+ else
+ {
+ LL_WARNS("COCOA") << "Window Implementation or callbacks not yet initialized." << LL_ENDL;
}
+
+}
+
+void callWindowUnfocus()
+{
+ gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
+}
+
+void callWindowHide()
+{
+ if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
+ {
+ gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, false);
+ }
+}
+
+void callWindowUnhide()
+{
+ if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
+ {
+ gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, true);
+ }
+}
+
+void callDeltaUpdate(double *delta, MASK mask)
+{
+ gWindowImplementation->updateMouseDeltas(delta);
+}
+
+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);
+}
+
+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);
+}
+
+void callModifier(MASK mask)
+{
+ gKeyboard->handleModifier(mask);
+}
+
+void callHandleDragEntered(std::string url)
+{
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING);
+}
+
+void callHandleDragExited(std::string url)
+{
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING);
+}
+
+void callHandleDragUpdated(std::string url)
+{
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK);
+}
+
+void callHandleDragDropped(std::string url)
+{
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED);
+}
+
+void callQuitHandler()
+{
+ if (gWindowImplementation)
+ {
+ if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation))
+ {
+ gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation);
+ }
+ }
+}
+
+void getPreeditSelectionRange(int *position, int *length)
+{
+ if (gWindowImplementation->getPreeditor())
+ {
+ gWindowImplementation->getPreeditor()->getSelectionRange(position, length);
+ }
+}
+
+void getPreeditMarkedRange(int *position, int *length)
+{
+ if (gWindowImplementation->getPreeditor())
+ {
+ gWindowImplementation->getPreeditor()->getPreeditRange(position, length);
+ }
+}
+
+void setPreeditMarkedRange(int position, int length)
+{
+ if (gWindowImplementation->getPreeditor())
+ {
+ gWindowImplementation->getPreeditor()->markAsPreedit(position, length);
+ }
+}
+
+bool handleUnicodeCharacter(wchar_t c)
+{
+ bool success = false;
+ if (gWindowImplementation->getPreeditor())
+ {
+ success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c);
+ }
+
+ return success;
+}
+
+void resetPreedit()
+{
+ if (gWindowImplementation->getPreeditor())
+ {
+ gWindowImplementation->getPreeditor()->resetPreedit();
+ }
+}
+
+// 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])
+ {
+ 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);
+ }
+}
+
+void getPreeditLocation(float *location, unsigned int length)
+{
+ if (gWindowImplementation->getPreeditor())
+ {
+ 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];
+ }
+}
+
+void LLWindowMacOSX::updateMouseDeltas(double* deltas)
+{
+ if (mCursorDecoupled)
+ {
+ mCursorLastEventDeltaX = ll_round(deltas[0]);
+ mCursorLastEventDeltaY = ll_round(-deltas[1]);
+
+ if (mCursorIgnoreNextDelta)
+ {
+ mCursorLastEventDeltaX = 0;
+ mCursorLastEventDeltaY = 0;
+ mCursorIgnoreNextDelta = FALSE;
+ }
+ } else {
+ mCursorLastEventDeltaX = 0;
+ mCursorLastEventDeltaY = 0;
+ }
+}
+
+void LLWindowMacOSX::getMouseDeltas(S32* delta)
+{
+ delta[0] = mCursorLastEventDeltaX;
+ delta[1] = mCursorLastEventDeltaY;
+}
+
+BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, S32 vsync_setting)
+{
mFullscreen = fullscreen;
-
- if (mFullscreen && (mOldDisplayMode == NULL))
+
+ if (mWindow == 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);
-
- // 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);
-
- if(resolutionList != NULL)
- {
- F32 closestAspect = 0;
- U32 closestHeight = 0;
- U32 closestWidth = 0;
- int i;
-
- LL_DEBUGS("Window") << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL;
-
- for(i=0; i < resolutionCount; i++)
- {
- F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight;
-
- LL_DEBUGS("Window") << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL;
-
- if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) &&
- (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio)))
- {
- LL_DEBUGS("Window") << " (new closest mode) " << LL_ENDL;
-
- // This is the closest mode we've seen yet.
- closestWidth = resolutionList[i].mWidth;
- closestHeight = resolutionList[i].mHeight;
- closestAspect = aspect;
- }
- }
-
- width = closestWidth;
- height = closestHeight;
- }
- }
-
- if((width == 0) || (height == 0))
- {
- // Mode search failed for some reason. Use the old-school default.
- width = 1024;
- height = 768;
- }
-
- 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
-
- // Switch the display to the desired resolution and refresh
- refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate(
- mDisplay,
- BITS_PER_PIXEL,
- width,
- height,
- refresh,
- &exactMatch);
-
- if (refDisplayMode)
- {
- LL_DEBUGS("Window") << "createContext: switching display resolution" << LL_ENDL;
- mOldDisplayMode = CGDisplayCurrentMode (mDisplay);
- CGDisplaySwitchToMode (mDisplay, refDisplayMode);
- // CFRelease(refDisplayMode);
-
- AddEventTypesToHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList);
- }
-
-
- mFullscreen = TRUE;
- mFullscreenWidth = CGDisplayPixelsWide(mDisplay);
- mFullscreenHeight = CGDisplayPixelsHigh(mDisplay);
- mFullscreenBits = CGDisplayBitsPerPixel(mDisplay);
- mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate));
-
- 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);
- }
+ mWindow = getMainAppWindow();
}
- if(!mFullscreen && (mWindow == NULL))
+ // Disable vertical sync for swap
+ bool vsync_enabled;
+ GLint frames_per_swap;
+ switch (vsync_setting)
{
- //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);
-
- 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
+ //default:
+ case 0: //E_VSYNC_DISABLED:
+ {
+ LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL;
+ vsync_enabled = false;
+ frames_per_swap = 0;
+ break;
}
-
+ case -1: //E_VSYNC_ADAPTIVE:
+ default: //case E_VSYNC_NORMAL:
{
- // 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);
- }
+ LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL;
+ vsync_enabled = true;
+ frames_per_swap = 1;
+ break;
+ }
}
if(mContext == NULL)
{
- AGLRendererInfo rendererInfo = NULL;
-
- //-----------------------------------------------------------------------
- // Create GL drawing context
- //-----------------------------------------------------------------------
-
- 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.
-
- 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);
- }
-
- // May want to get the real error text like this:
- // (char *) aglErrorString(aglGetError());
-
- if(aglGetError() != AGL_NO_ERROR)
- {
- setupFailure("Can't find suitable pixel format", "Error", OSMB_OK);
- return FALSE;
- }
- }
-
- if(mPixelFormat)
- {
- LL_DEBUGS("Window") << "createContext: creating GL context" << LL_ENDL;
- mContext = aglCreateContext(mPixelFormat, NULL);
- }
-
- if(mContext == NULL)
- {
- setupFailure("Can't make GL context", "Error", OSMB_OK);
- return FALSE;
- }
-
- gGLManager.mVRAM = 0;
-
- if(rendererInfo != NULL)
- {
- 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);
- }
-
- // Since we just created the context, it needs to be set up.
- glNeedsInit = TRUE;
+ // 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);
}
-
+
+ // 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 (mFullscreen && (mOldDisplayMode != NULL))
- {
- // 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;
- }
- }
- else if(!mFullscreen && (mWindow != NULL))
- {
- LL_DEBUGS("Window") << "createContext: attaching windowed drawable" << LL_ENDL;
-
- // 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;
- }
- }
- else
- {
- setupFailure("Can't get fullscreen or windowed drawable.", "Error", OSMB_OK);
- return FALSE;
- }
if(mContext != NULL)
{
- LL_DEBUGS("Window") << "createContext: setting current context" << LL_ENDL;
-
- if (!aglSetCurrentContext(mContext))
+
+
+ CGLError err = CGLSetCurrentContext(mContext);
+ if (err != kCGLNoError)
{
setupFailure("Can't activate GL rendering context", "Error", OSMB_OK);
return FALSE;
}
}
- if(glNeedsInit)
- {
- // 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
-
- S32 i;
- for (i = 0; i < CARD_COUNT; i++)
- {
- if (check_for_card(RENDERER, CARD_LIST[i]))
- {
- close();
- return FALSE;
- }
- }
- }
-
- GLint colorBits, alphaBits, depthBits, stencilBits;
-
- 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))
- {
- close();
- setupFailure("Can't get pixel format description", "Error", OSMB_OK);
- return FALSE;
- }
-
- 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)
- {
- 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;
- }
-
- 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;
- }
-
- // Disable vertical sync for swap
- GLint frames_per_swap = 0;
- if (vsync_mode != 1)
- {
- LL_DEBUGS("GLInit") << "Disabling vertical sync" << LL_ENDL;
- frames_per_swap = 0;
- }
- else
- {
- LL_DEBUGS("GLinit") << "Keeping vertical sync" << LL_ENDL;
- frames_per_swap = 1;
- }
- 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,109 +651,17 @@ 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.
+// 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, const LLCoordScreen * const posp)
{
- BOOL needsRebuild = FALSE;
- BOOL result = true;
-
- 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;
+ return FALSE;
}
void LLWindowMacOSX::destroyContext()
@@ -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)
+ // Destroy our LLOpenGLView
+ if(mGLView != NULL)
{
- LL_DEBUGS("Window") << "destroyContext: removing global event handler" << LL_ENDL;
- RemoveEventHandler(mGlobalHandlerRef);
- mGlobalHandlerRef = NULL;
+ removeGLView(mGLView);
+ mGLView = NULL;
}
-
- if(mWindowHandlerRef != NULL)
- {
- LL_DEBUGS("Window") << "destroyContext: removing window event handler" << LL_ENDL;
- RemoveEventHandler(mWindowHandlerRef);
- mWindowHandlerRef = NULL;
- }
-
- // Cleanup any TSM document we created.
- if(mTSMDocument != NULL)
- {
- LL_DEBUGS("Window") << "destroyContext: deleting TSM document" << LL_ENDL;
- DeactivateTSMDocument(mTSMDocument);
- DeleteTSMDocument(mTSMDocument);
- mTSMDocument = NULL;
- }
-
- // 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;
+ CGLDestroyContext(mContext);
+ }
+
+ // Close the window
+ if(mWindow != 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);
+ return true;
+ } else {
+ return false;
}
-
- 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 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)
{
@@ -1808,6 +1296,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r
}
}
}
+ CFRelease(modes);
}
}
@@ -1817,122 +1306,52 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r
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;
-
+ to->mY = from.mY;
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;
-
+ to->mY = from.mY;
return TRUE;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to)
{
- if(mFullscreen)
+ if(mWindow)
{
- // 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;
+ float mouse_point[2];
+ float scale_factor = getScaleFactor();
+ mouse_point[0] = from.mX;
+ mouse_point[1] = from.mY;
+
+ convertScreenToWindow(mWindow, 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);
+ to->mX = mouse_point[0] * scale_factor;
+ to->mY = mouse_point[1] * scale_factor;
return TRUE;
}
-
return FALSE;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to)
{
- if(mFullscreen)
+ if(mWindow)
{
- // 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;
+ 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);
- 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);
+ to->mX = mouse_point[0];
+ to->mY = mouse_point[1];
return TRUE;
}
-
return FALSE;
}
@@ -1960,862 +1379,8 @@ void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& ca
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;
- }
-
- SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds);
- result = noErr;
- }
- break;
-
- case kEventWindowBoundsChanged:
- {
- // Get new window bounds
- Rect newBounds;
- GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds);
-
- // Get previous window bounds
- Rect oldBounds;
- GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &oldBounds);
-
- // 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));
-
- // 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);
-
- // Maximized flag is if zoom event and increasing window size
- mMaximized = (isZoomEvent && newBoundsLarger);
-
- aglUpdateContext(mContext);
-
- mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top);
- }
- break;
-
- case kEventWindowGetIdealSize:
- // Only recommend a new ideal size when un-maximizing
- if (mMaximized == TRUE)
- {
- Point nonMaximizedSize;
-
- nonMaximizedSize.v = mPreviousWindowRect.bottom - mPreviousWindowRect.top;
- nonMaximizedSize.h = mPreviousWindowRect.right - mPreviousWindowRect.left;
-
- SetEventParameter(event, kEventParamDimensions, typeQDPoint, sizeof(Point), &nonMaximizedSize);
- result = noErr;
- }
- break;
-
- 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;
-
- case kEventClassTSMDocumentAccess:
- if (mPreeditor)
- {
- switch(evtKind)
- {
-
- 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;
-
- 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;
-}
-
+ // 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);
+}
-OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
+void LLWindowMacOSX::updateUnreadCount(S32 num_conversations)
+{
+ updateBadge(num_conversations);
+}
+
+#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)
+ 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 = 0;
+ }
+ 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)
{
- 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))
- {
- // This is a string that might be an URL.
- err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data);
- }
-
- }
-
- 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);
- }
-
- }
- }
+ // 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 d8d46edb9..292af641a 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 @@ public:
/*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, const LLCoordScreen * const posp = nullptr);
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
/*virtual*/ void showCursor();
@@ -76,19 +77,18 @@ public:
/*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 @@ public:
/*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 @@ protected:
BOOL shouldPostQuit() { return mPostQuit; }
+private:
+ void restoreGLContext();
protected:
//
@@ -155,43 +165,36 @@ protected:
//
// 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;
- 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;
+ // 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;
+
+ 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 @@ protected:
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/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 3d6919393..2c02cd143 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -2476,18 +2476,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;
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 2f073c0ec..25f4de882 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -3350,34 +3350,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;
@@ -3389,25 +3364,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)
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index ca82f7512..02466adde 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -109,7 +109,6 @@ public:
/*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);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 6f338aa4c..d457aa430 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1164,6 +1164,7 @@ add_custom_target(generate_viewer_version ALL
)
set_source_files_properties(
+ llimpanel.cpp
llversioninfo.cpp
PROPERTIES
DEPENDS generate_viewer_version # dummy dependency to force recompile every time
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index ad8787a7e..e0be85ca3 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
@@ -3474,6 +3477,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
@@ -7042,7 +7078,7 @@ This should be as low as possible, but too low may break functionality
Type
String
Value
- %Y-%m-%d
+ %F
ShortTimeFormat
@@ -7053,7 +7089,7 @@ This should be as low as possible, but too low may break functionality
Type
String
Value
- %H:%M
+ %R
LongTimeFormat
@@ -7064,7 +7100,7 @@ This should be as low as possible, but too low may break functionality
Type
String
Value
- %H:%M:%S
+ %T
TimestampFormat
@@ -7075,7 +7111,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
diff --git a/indra/newview/app_settings/settings_ascent.xml b/indra/newview/app_settings/settings_ascent.xml
index a11c8a970..ff2f40154 100644
--- a/indra/newview/app_settings/settings_ascent.xml
+++ b/indra/newview/app_settings/settings_ascent.xml
@@ -927,7 +927,7 @@ RIP Latif Khalifa.
Type
String
Value
- Default
+ Default
SinguReplaceLinks
@@ -1087,6 +1087,17 @@ Changing this setting only affects new text.
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
+
OBJExportNotifyFailed
Comment
@@ -1793,6 +1804,8 @@ Changing this setting only affects new text.
Boolean
Value
0
+ IsCOA
+ 1
ToolbarVisibleMeanEvents
@@ -1924,19 +1937,6 @@ Changing this setting only affects new text.
IsCOA
1
- ToolbarVisibleMarketplaceListings
-
- Comment
- Whether or not the button for Marketplace Listings is on the toolbar
- Persist
- 1
- Type
- Boolean
- Value
- 0
- IsCOA
- 1
-
ToolbarVisibleNotificationsConsole
Comment
diff --git a/indra/newview/ascentprefschat.cpp b/indra/newview/ascentprefschat.cpp
index 141b57dcd..150c9a3a4 100644
--- a/indra/newview/ascentprefschat.cpp
+++ b/indra/newview/ascentprefschat.cpp
@@ -128,9 +128,9 @@ void LLPrefsAscentChat::onCommitTimeDate(LLUICtrl* ctrl)
if (tempTimeFormat == 0)
{
- short_time = "%H:%M";
- long_time = "%H:%M:%S";
- timestamp = " %H:%M:%S";
+ short_time = "%R";
+ long_time = "%T";
+ timestamp = " %T";
}
else
{
@@ -141,7 +141,7 @@ void LLPrefsAscentChat::onCommitTimeDate(LLUICtrl* ctrl)
if (tempDateFormat == 0)
{
- short_date = "%Y-%m-%d";
+ short_date = "%F";
long_date = "%A %d %B %Y";
timestamp = "%a %d %b %Y" + timestamp;
}
@@ -153,7 +153,7 @@ void LLPrefsAscentChat::onCommitTimeDate(LLUICtrl* ctrl)
}
else
{
- short_date = "%m/%d/%Y";
+ short_date = "%D";
long_date = "%A, %B %d %Y";
timestamp = "%a %b %d %Y" + timestamp;
}
@@ -218,11 +218,11 @@ void LLPrefsAscentChat::refreshValues()
}
format = gSavedSettings.getString("ShortDateFormat");
- if (format.find("%m/%d/%") != std::string::npos)
+ if (format.find("%D") != std::string::npos || format.find("%m/%d/%") != std::string::npos)
{
mDateFormat = 2;
}
- else if (format.find("%d/%m/%") != -1)
+ else if (format.find("%d/%m/%") != std::string::npos)
{
mDateFormat = 1;
}
diff --git a/indra/newview/chatbar_as_cmdline.cpp b/indra/newview/chatbar_as_cmdline.cpp
index 2863cfe92..145f3c9fe 100644
--- a/indra/newview/chatbar_as_cmdline.cpp
+++ b/indra/newview/chatbar_as_cmdline.cpp
@@ -632,7 +632,7 @@ 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);
diff --git a/indra/newview/daeexport.h b/indra/newview/daeexport.h
index fbdd5b84c..910057340 100644
--- a/indra/newview/daeexport.h
+++ b/indra/newview/daeexport.h
@@ -77,7 +77,7 @@ public:
};
typedef std::vector > obj_info_t;
- typedef std::vector id_list_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;
diff --git a/indra/newview/fonts/DejaVuSansCondensed-Bold.ttf b/indra/newview/fonts/DejaVuSansCondensed-Bold.ttf
deleted file mode 100644
index 9edd89c3d..000000000
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 826e619b7..000000000
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 19d188832..000000000
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 d065b64eb..000000000
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 ad1efca88..000000000
Binary files a/indra/newview/fonts/DroidSans.ttf and /dev/null differ
diff --git a/indra/newview/hippogridmanager.cpp b/indra/newview/hippogridmanager.cpp
index 315b7cf8b..bf82c7fde 100644
--- a/indra/newview/hippogridmanager.cpp
+++ b/indra/newview/hippogridmanager.cpp
@@ -109,7 +109,7 @@ void HippoGridInfo::setPlatform(const std::string& platform)
{
setPlatform(PLATFORM_WHITECORE);
}
- else if (tmp == "opensim")
+ else if (tmp == "opensim" || tmp == "halcyon")
{
setPlatform(PLATFORM_OPENSIM);
}
diff --git a/indra/newview/jcfloaterareasearch.cpp b/indra/newview/jcfloaterareasearch.cpp
index 9fb8a58dc..4c5ad09e1 100644
--- a/indra/newview/jcfloaterareasearch.cpp
+++ b/indra/newview/jcfloaterareasearch.cpp
@@ -217,7 +217,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 +281,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.
diff --git a/indra/newview/jcfloaterareasearch.h b/indra/newview/jcfloaterareasearch.h
index 413dbab99..32c40c253 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;
@@ -91,8 +92,8 @@ private:
LLUUID owner_id;
LLUUID group_id;
};
- std::set mPendingObjects;
- std::map mCachedObjects;
+ uuid_set_t mPendingObjects;
+ boost::unordered_map mCachedObjects;
std::string mFilterStrings[LIST_OBJECT_COUNT];
};
diff --git a/indra/newview/lgghunspell_wrapper.cpp b/indra/newview/lgghunspell_wrapper.cpp
index c28f83a0c..d19e91485 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/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h
index 731705288..9b6b80e6c 100644
--- a/indra/newview/llaccountingcostmanager.h
+++ b/indra/newview/llaccountingcostmanager.h
@@ -64,11 +64,11 @@ public:
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 457de28d5..f5ea77a9d 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3094,7 +3094,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())
{
@@ -4457,7 +4457,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();
@@ -4556,12 +4556,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);
}
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index facff5fe3..c31e758e1 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -525,7 +525,7 @@ public:
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);
@@ -936,7 +936,7 @@ public:
void friendsChanged();
private:
LLFriendObserver* mFriendObserver;
- std::set mProxyForAgents;
+ uuid_set_t mProxyForAgents;
/** Groups
** **
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index bf5d47d0a..de298c752 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1400,8 +1400,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();
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index baa6809ea..dc7665727 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1307,7 +1307,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
@@ -1336,7 +1336,7 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
// [SL:KB] - Patch: Appearance-WearableDuplicateAssets | Checked: 2015-06-30 (Catznip-3.7)
static void removeDuplicateWearableItemsByAssetID(LLInventoryModel::item_array_t& items)
{
- std::set idsAsset;
+ uuid_set_t idsAsset;
items.erase(std::remove_if(items.begin(), items.end(),
[&idsAsset](const LLViewerInventoryItem* pItem)
{
@@ -2602,7 +2602,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
if (isAgentAvatarValid())
{
// Include attachments which should be in COF but don't have their link created yet
- std::set pendingAttachments;
+ uuid_set_t pendingAttachments;
if (LLAttachmentsMgr::instance().getPendingAttachments(pendingAttachments))
{
for (const LLUUID& idAttachItem : pendingAttachments)
@@ -3806,7 +3806,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)
@@ -3858,7 +3858,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())
{
@@ -3866,7 +3866,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())
{
@@ -4351,7 +4351,7 @@ private:
bool mFailed;
std::vector > mPendingCopies;
std::vector > mPendingLinks;
- std::set mWearItems;
+ uuid_set_t mWearItems;
std::vector mActiveRequests;
};
@@ -4661,10 +4661,10 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val)
mAttachmentInvLinkEnabled = val;
}
-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)
{
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index a0c7fc3d8..46edd4a99 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -290,7 +290,7 @@ private:
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);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a10b6a6e3..42a7a99a9 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -566,11 +566,25 @@ LLAppViewer::LLAppViewer() :
LL_ERRS() << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << LL_ENDL;
}
- mDumpPath ="";
+ mDumpPath.clear();
// 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);
+ }
sInstance = this;
}
@@ -640,7 +654,8 @@ bool LLAppViewer::init()
// 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.
@@ -1730,9 +1745,6 @@ bool LLAppViewer::cleanup()
removeDumpDir();
writeDebugInfo();
- if(!gDirUtilp->getLindenUserDir(true).empty())
- LLViewerMedia::saveCookieFile();
-
// Stop the plugin read thread if it's running.
LLPluginProcessParent::setUseReadThread(false);
// Stop curl responder call backs.
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index b7fabd8a8..7c58c7c03 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -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();
}
@@ -313,6 +335,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);
}
}
diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp
index e556ec61b..5395d42df 100644
--- a/indra/newview/llattachmentsmgr.cpp
+++ b/indra/newview/llattachmentsmgr.cpp
@@ -305,7 +305,7 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
<< " recently arrived items" << LL_ENDL;
uuid_vec_t ids_to_link;
- for (std::set::iterator it = mRecentlyArrivedAttachments.begin();
+ for (auto it = mRecentlyArrivedAttachments.begin();
it != mRecentlyArrivedAttachments.end(); ++it)
{
if (isAgentAvatarValid() &&
@@ -344,7 +344,7 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
}
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.2)
-bool LLAttachmentsMgr::getPendingAttachments(std::set& ids) const
+bool LLAttachmentsMgr::getPendingAttachments(uuid_set_t& ids) const
{
ids.clear();
diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h
index cd516adbf..84fb76bbe 100644
--- a/indra/newview/llattachmentsmgr.h
+++ b/indra/newview/llattachmentsmgr.h
@@ -95,7 +95,7 @@ public:
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.1)
public:
void clearPendingAttachmentLink(const LLUUID& idItem);
- bool getPendingAttachments(std::set& ids) const;
+ bool getPendingAttachments(uuid_set_t& ids) const;
protected:
void onRegisterAttachmentComplete(const LLUUID& idAttachLink);
friend class LLRegisterAttachmentCallback;
@@ -136,12 +136,12 @@ private:
LLItemRequestTimes mDetachRequests;
// Attachments that have arrived but have not been linked in the COF yet.
- std::set mRecentlyArrivedAttachments;
+ uuid_set_t mRecentlyArrivedAttachments;
LLTimer mCOFLinkBatchTimer;
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-18 (Catznip-2.1)
// Attachments that have pending link creation
- std::set mPendingAttachLinks;
+ uuid_set_t mPendingAttachLinks;
// [/SL:KB]
// // Attachments that are linked in the COF but may be invalid.
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 269c24956..4aaf69c1b 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
@@ -616,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;
@@ -647,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);
}
}
@@ -688,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)
@@ -705,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"))
{
@@ -723,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())
@@ -731,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
{
@@ -775,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;
@@ -787,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();
-
+ bool folders_count = false; // Singu Note: Was a count, but break right after == 1, so bool.
//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++;
+ folders_count = true;
+ 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 ? "ShareFolderConfirmation" : "ShareItemsConfirmation";
LLSD substitutions;
substitutions["RESIDENTS"] = residents;
substitutions["ITEMS"] = items;
@@ -854,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();
@@ -875,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)
{
@@ -927,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)) //
@@ -1286,3 +1265,8 @@ void LLAvatarActions::copyUUIDs(const uuid_vec_t& ids)
if (!ids_string.empty())
gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(ids_string));
}
+
+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 57e1ddd17..9f75e793f 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 @@ public:
*/
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/llcallingcard.h b/indra/newview/llcallingcard.h
index 104b5122c..9d4948783 100644
--- a/indra/newview/llcallingcard.h
+++ b/indra/newview/llcallingcard.h
@@ -165,7 +165,7 @@ public:
*/
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 @@ protected:
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 @@ public:
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/llcompilequeue.h b/indra/newview/llcompilequeue.h
index 9bb67d9cb..25212de11 100644
--- a/indra/newview/llcompilequeue.h
+++ b/indra/newview/llcompilequeue.h
@@ -110,7 +110,7 @@ protected:
LLButton* mCloseBtn;
// Object Queue
- std::vector mObjectIDs;
+ uuid_vec_t mObjectIDs;
LLUUID mCurrentObjectID;
bool mDone;
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index c3fcc5461..b348bc6ae 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -220,26 +220,8 @@ void LLDrawPoolTerrain::render(S32 pass)
}
// 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;
- gGL.setPolygonOffset(-1.0f, -1.0f);
- renderOwnership();
- sShader = old_shader;
- sShader->bind();
- }
- else
- {
- renderOwnership();
- }
+ hilightParcelOwners();
}
}
@@ -267,7 +249,14 @@ void LLDrawPoolTerrain::renderDeferred(S32 pass)
{
return;
}
+
renderFullShader();
+
+ // Special-case for land ownership feedback
+ {
+ hilightParcelOwners();
+ }
+
}
void LLDrawPoolTerrain::beginShadowPass(S32 pass)
@@ -459,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!
@@ -493,6 +505,7 @@ void LLDrawPoolTerrain::renderFull4TU()
glEnable(GL_TEXTURE_GEN_T);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+
glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
@@ -601,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
diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h
index e87229c0f..08ab12276 100644
--- a/indra/newview/lldrawpoolterrain.h
+++ b/indra/newview/lldrawpoolterrain.h
@@ -80,6 +80,7 @@ public:
static S32 sDetailMode;
static F32 sDetailScale; // meters per texture
+
protected:
void renderSimple();
void renderOwnership();
@@ -88,6 +89,9 @@ protected:
void renderFull4TU();
void renderFullShader();
void drawLoop();
+
+private:
+ void hilightParcelOwners();
};
#endif // LL_LLDRAWPOOLSIMPLE_H
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index d578b6062..71e1b6a8c 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -1233,7 +1233,7 @@ BOOL LLFavoritesBarCtrl::isClipboardPasteable() 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++)
@@ -1262,7 +1262,7 @@ void LLFavoritesBarCtrl::pasteFromClipboard() const
if(model && isClipboardPasteable())
{
LLInventoryItem* item = NULL;
- std::vector objects;
+ uuid_vec_t objects;
LLInventoryClipboard::instance().retrieve(objects);
S32 count = objects.size();
LLUUID parent_id(mFavoriteFolderId);
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index ef6f55c5e..48f26624f 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -236,7 +236,7 @@ private:
typedef std::map slurls_map_t;
slurls_map_t mSLURLs;
- std::set mMissingSLURLs;
+ uuid_set_t mMissingSLURLs;
bool mIsDirty;
struct IsNotInFavorites
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 7c991e4d4..cc9628d2a 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -70,7 +70,7 @@
#include "lldxhardware.h"
#endif
-#include "cef/llceflib.h"
+#include "cef/dullahan.h"
extern LLMemoryInfo gSysMemory;
extern U32 gPacketsIn;
@@ -286,8 +286,17 @@ LLFloaterAbout::LLFloaterAbout()
support.append( gAudiop ? gAudiop->getDriverName(want_fullname) : "(none)" );
support += '\n';
- support.append("LLCEFLib/CEF Version: ");
- support.append(LLCEFLIB_VERSION);
+ std::stringstream supportstrm;
+ supportstrm << "Dullahan: "
+ << DULLAHAN_VERSION_MAJOR
+ << '.'
+ << DULLAHAN_VERSION_MINOR
+ << '.'
+ << DULLAHAN_VERSION_BUILD
+
+ << " / CEF: " << CEF_VERSION
+ << " / Chrome: " << CHROME_VERSION_MAJOR;
+ support += supportstrm.str();
support += '\n';
if (gPacketsIn > 0)
diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp
index cbd8d9e92..bb614ec31 100644
--- a/indra/newview/llfloateravatarlist.cpp
+++ b/indra/newview/llfloateravatarlist.cpp
@@ -561,7 +561,7 @@ void LLFloaterAvatarList::updateAvatarList(const LLViewerRegion* region, bool fi
{
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());
const F32 max_range(radar_range_radius() * radar_range_radius());
@@ -636,7 +636,7 @@ void LLFloaterAvatarList::expireAvatarList(const std::list& ids)
{
if (!ids.empty())
{
- std::vector existing_avs;
+ uuid_vec_t existing_avs;
std::vector neighbors;
gAgent.getRegion()->getNeighboringRegions(neighbors);
for (const LLViewerRegion* region : neighbors)
diff --git a/indra/newview/llfloaterblacklist.cpp b/indra/newview/llfloaterblacklist.cpp
index 255552928..bfbfd0a09 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()
@@ -88,7 +88,7 @@ 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;
@@ -246,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")
{
@@ -276,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;
}
@@ -300,7 +300,7 @@ 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;
}
@@ -340,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 9b5c4171f..c15c99a9c 100644
--- a/indra/newview/llfloaterblacklist.h
+++ b/indra/newview/llfloaterblacklist.h
@@ -16,8 +16,7 @@ public:
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 @@ public:
*/
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 7e9589a79..7fb149ee5 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();
diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h
index 428e8ae96..ccbeb6741 100644
--- a/indra/newview/llfloaterbulkpermission.h
+++ b/indra/newview/llfloaterbulkpermission.h
@@ -89,7 +89,7 @@ private:
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 8e5ff91ff..9f4088347 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/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp
index b0607210f..49930a925 100644
--- a/indra/newview/llfloaterchat.cpp
+++ b/indra/newview/llfloaterchat.cpp
@@ -292,10 +292,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);
diff --git a/indra/newview/llfloaterexploresounds.cpp b/indra/newview/llfloaterexploresounds.cpp
index 36caef3e9..94400f31f 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/llfloatergroupinvite.cpp b/indra/newview/llfloatergroupinvite.cpp
index 207ec78f5..656854e41 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 d1485ead9..48c15c3aa 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/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp
index f6c24f2fb..c4abc4ac7 100644
--- a/indra/newview/llfloaterinspect.cpp
+++ b/indra/newview/llfloaterinspect.cpp
@@ -371,7 +371,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 633507b5c..643639692 100644
--- a/indra/newview/llfloaterinspect.h
+++ b/indra/newview/llfloaterinspect.h
@@ -82,7 +82,7 @@ private:
LLSafeHandle mObjectSelection;
//
std::map > mInventoryNums; //
- std::vector mQueue;
+ uuid_vec_t mQueue;
//
std::map mOwnerNameCacheConnection;
std::map mLastOwnerNameCacheConnection; //
diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp
index b2d1d63fa..e4f594fa0 100644
--- a/indra/newview/llfloaterjoystick.cpp
+++ b/indra/newview/llfloaterjoystick.cpp
@@ -59,26 +59,29 @@ 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);
mAxisStats[i]->addValue(value * gFrameIntervalSeconds);
-
- if (mAxisStatsBar[i]->mMinBar > value)
+ auto& bar = mAxisStatsBar[i];
+
+ if (bar->mMinBar > value)
{
- mAxisStatsBar[i]->mMinBar = value;
+ bar->mMinBar = value;
}
- if (mAxisStatsBar[i]->mMaxBar < value)
+ if (bar->mMaxBar < value)
{
- mAxisStatsBar[i]->mMaxBar = value;
+ bar->mMaxBar = value;
}
}
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 2318dd601..9f5aa1b5f 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -1606,7 +1606,7 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo
}
LLVector3d mypos = gAgent.getPositionGlobal();
- std::vector avatar_ids;
+ uuid_vec_t avatar_ids;
LLWorld::instance().getAvatars(&avatar_ids, NULL, mypos, F32_MAX);
for(S32 i = 0; i < rows; ++i)
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 168dcc4f1..1329c60df 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -42,7 +42,6 @@
//#include "llviewertexturelist.h"
#include "llsafehandle.h"
-typedef std::set uuid_list_t;
const F32 CACHE_REFRESH_TIME = 2.5f;
class LLButton;
@@ -172,7 +171,7 @@ public:
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);
+ 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*);
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 82ae608f3..99692709d 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1545,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.
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index a6013fbb3..d78a9ef28 100644
--- a/indra/newview/llfloatertopobjects.cpp
+++ b/indra/newview/llfloatertopobjects.cpp
@@ -328,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)
@@ -359,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))
@@ -370,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)
{
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index 4751b15e1..2e5a1b905 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -169,8 +169,8 @@ private:
// 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 3fd05a12c..a8223bec4 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -865,14 +865,12 @@ 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;
}
@@ -1048,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)
{
@@ -2118,8 +2116,7 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
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;
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 7433e87bb..848787632 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -54,6 +54,8 @@
#include "lltooldraganddrop.h"
#include "llviewertexture.h"
+#include
+
class LLFolderViewEventListener;
class LLFolderViewGroupedItemModel;
class LLFolderViewFolder;
@@ -158,7 +160,7 @@ public:
// 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, descendants are not
void sanitizeSelection();
@@ -330,7 +332,7 @@ protected:
S32 mSignalSelectCallback;
S32 mMinWidth;
S32 mRunningHeight;
- std::map mItemMap;
+ boost::unordered_map mItemMap;
LLUUID mSelectThisID; // if non null, select this item
LLHandle mParentPanel;
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 1f87716f2..dab9a1a95 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -378,10 +378,9 @@ void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection,
getRoot()->setSelection(selection, openitem, take_keyboard_focus);
}
-std::set LLFolderViewItem::getSelectionList() const
+uuid_set_t LLFolderViewItem::getSelectionList() const
{
- std::set selection;
- return selection;
+ return uuid_set_t();
}
EInventorySortGroup LLFolderViewItem::getSortGroup() const
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index c33eb575b..9bb163c80 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;
@@ -218,7 +220,7 @@ public:
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();
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index 1d821e3f8..ae5bded83 100644
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -69,7 +69,7 @@ const F32 MAX_WAIT_ANIM_SECS = 30.f;
// Lightweight constructor.
// init() does the heavy lifting.
LLGestureMgr::LLGestureMgr()
-: mValid(FALSE),
+: mValid(false),
mPlaying(),
mActive(),
mLoadingCount(0)
@@ -87,7 +87,7 @@ LLGestureMgr::~LLGestureMgr()
LLMultiGesture* gesture = (*it).second;
delete gesture;
- gesture = NULL;
+ gesture = nullptr;
}
gInventory.removeObserver(this);
}
@@ -148,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)
{
- // 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;
-
- if (isGestureActive(item->getUUID()))
- {
- continue;
- }
- else
- { // Make gesture active and persistent through login sessions. -Aura 07-12-06
- activateGesture(item->getUUID());
- }
-
- count++;
- }
-
- mLoadingCount = count;
mDeactivateSimilarNames.clear();
- for (it = items.begin(); it != items.end(); ++it)
- {
- LLViewerInventoryItem* item = *it;
-
- if (isGestureActive(item->getUUID()))
- {
- continue;
- }
-
- // 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(),
- no_inform_server,
- deactivate_similar);
- }
+ // Load up the assets
+ mLoadingCount = 0;
// Inform the database of this change
LLMessageSystem* msg = gMessageSystem;
+ bool start_message = true;
- BOOL start_message = TRUE;
-
- for (it = items.begin(); it != items.end(); ++it)
+ for (const auto& item : items)
{
- LLViewerInventoryItem* item = *it;
-
- if (isGestureActive(item->getUUID()))
+ const auto& id = item->getUUID();
+ if (isGestureActive(id))
{
continue;
}
+ // Make gesture active and persistent through login sessions. -Aura 07-12-06
+ activateGesture(id);
+
+ ++mLoadingCount;
+
+ 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(id, asset_id,
+ no_inform_server,
+ deactivate_similar);
+
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;
}
}
@@ -241,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
@@ -252,8 +230,8 @@ 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 = gInventory.getLinkedItemID(item_id);
@@ -275,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())
@@ -287,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,
@@ -304,7 +282,7 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id,
void LLGestureMgr::deactivateGesture(const LLUUID& item_id)
{
const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);
- item_map_t::iterator it = mActive.find(base_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;
@@ -314,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);
@@ -330,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);
@@ -346,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 = gInventory.getLinkedItemID(in_item_id);
- uuid_vec_t gest_item_ids;
+
+ // 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;
@@ -368,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
{
@@ -385,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 = gInventory.getLinkedItemID(item_id);
- item_map_t::iterator it = mActive.find(base_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 = gInventory.getLinkedItemID(item_id);
- item_map_t::iterator it = mActive.find(base_item_id);
- if (it == mActive.end()) return FALSE;
+ 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 = gInventory.getLinkedItemID(item_id);
- item_map_t::iterator it = mActive.find(base_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;
@@ -481,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())
{
@@ -490,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,
@@ -508,7 +467,7 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset
{
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;
@@ -528,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);
@@ -565,7 +524,7 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool local)
LLAssetType::AT_ANIMATION,
onAssetLoadComplete,
(void *)id,
- TRUE);
+ true);
}
break;
}
@@ -581,8 +540,8 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool local)
gAssetStorage->getAssetData(sound_id,
LLAssetType::AT_SOUND,
onAssetLoadComplete,
- NULL,
- TRUE);
+ nullptr,
+ true);
}
break;
}
@@ -624,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(" ");
@@ -639,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;
@@ -659,7 +617,7 @@ BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::strin
matching.push_back(gesture);
}
- gesture = NULL;
+ gesture = nullptr;
}
@@ -673,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;
@@ -738,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;
}
@@ -757,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)
+ bool notify = false;
+ for (auto it = mPlaying.begin(), end = mPlaying.end(); it != end;)
{
- 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())
- {
- // 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 gesture out of the playing list
+ it = mPlaying.erase(it);
+ end = mPlaying.end();
+ notify = true;
}
-
- // And take done gestures out of the playing list
- mPlaying.erase(new_end, mPlaying.end());
-
- notifyObservers();
+ else ++it;
}
+
+ // Something finished playing
+ if (notify) notifyObservers();
}
@@ -818,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;
}
@@ -841,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
{
@@ -867,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;
}
@@ -896,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;
}
@@ -916,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;
}
@@ -945,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;
}
@@ -971,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)
@@ -984,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);
@@ -1008,38 +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:
@@ -1047,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;
@@ -1080,32 +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();
- std::vector buffer(size+1);
-
+ // ensure there's a trailing nullptr so strlen will work.
+ std::vector buffer(size+1, '\0');
file.read((U8*)&buffer[0], size);
- // ensure there's a trailing NULL so strlen will work.
- buffer[size] = '\0';
LLMultiGesture* gesture = new LLMultiGesture();
LLDataPackerAsciiBuffer dp(&buffer[0], size+1);
- BOOL ok = gesture->deserialize(dp);
- if (ok)
+ if (gesture->deserialize(dp))
{
if (deactivate_similar)
{
@@ -1155,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);
@@ -1172,7 +1085,7 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs,
self.mActive.erase(item_id);
delete gesture;
- gesture = NULL;
+ gesture = nullptr;
}
}
else
@@ -1240,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:
@@ -1293,28 +1203,19 @@ 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)
+ 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);
}
- 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();
@@ -1324,7 +1225,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture)
// callback might have deleted gesture, can't
// rely on this pointer any more
- gesture = NULL;
+ gesture = nullptr;
}
notifyObservers();
@@ -1334,7 +1235,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture)
void LLGestureMgr::stopGesture(const LLUUID& item_id)
{
const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);
- item_map_t::iterator it = mActive.find(base_item_id);
+ auto it = mActive.find(base_item_id);
if (it == mActive.end()) return;
LLMultiGesture* gesture = (*it).second;
@@ -1351,9 +1252,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);
}
@@ -1366,27 +1267,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();
@@ -1395,7 +1292,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
@@ -1408,37 +1305,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;
}
}
diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h
index 419ae77e7..eb23faf69 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 @@ public:
// 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 @@ public:
* 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 = NULL);
// 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 @@ public:
// 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 @@ protected:
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 @@ private:
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/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index d97cd8d35..317998558 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -601,3 +601,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 0cce7460b..ac2b0f10d 100644
--- a/indra/newview/llgroupactions.h
+++ b/indra/newview/llgroupactions.h
@@ -121,6 +121,11 @@ public:
*/
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 b4bd6770e..5ad340218 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -160,7 +160,7 @@ LLGroupRoleData::~LLGroupRoleData()
{
}
-S32 LLGroupRoleData::getMembersInRole(uuid_vec_t members,
+S32 LLGroupRoleData::getMembersInRole(uuid_vec_t& members,
BOOL needs_sort)
{
if (mRoleID.isNull())
@@ -895,7 +895,7 @@ void LLGroupMgrGroupData::banMemberById(const LLUUID& participant_uuid)
return; // can't ban group owner
}
- std::vector ids;
+ uuid_vec_t ids;
ids.push_back(participant_uuid);
LLGroupBanData ban_data;
@@ -2083,7 +2083,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)
diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h
index 1e7e4f5ae..73a854624 100644
--- a/indra/newview/llgroupmgr.h
+++ b/indra/newview/llgroupmgr.h
@@ -148,7 +148,7 @@ public:
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 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; }
@@ -401,7 +401,7 @@ public:
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/llimpanel.cpp b/indra/newview/llimpanel.cpp
index b80225d3e..29324f87f 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -59,12 +59,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)
@@ -211,7 +213,7 @@ private:
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 )
@@ -280,7 +282,7 @@ 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),
@@ -331,7 +333,8 @@ LLFloaterIMPanel::LLFloaterIMPanel(
{
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
{
@@ -550,7 +553,6 @@ BOOL LLFloaterIMPanel::postBuild()
mHistoryEditor = getChild("im_history");
mHistoryEditor->setParseHTML(TRUE);
- mHistoryEditor->setParseHighlights(TRUE);
sTitleString = getString("title_string");
sTypingStartString = getString("typing_start_string");
@@ -561,11 +563,21 @@ 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:
+ getChildView("Support Check")->setVisible(true);
+ // Singu Note: We could make a button feature for dumping Help->About contents for support, too.
+ break;
+ default:
+ break;
+ }
setDefaultBtn("send_btn");
@@ -691,7 +703,7 @@ private:
LLUUID mSessionID;
};
-bool LLFloaterIMPanel::inviteToSession(const std::vector& ids)
+bool LLFloaterIMPanel::inviteToSession(const uuid_vec_t& ids)
{
LLViewerRegion* region = gAgent.getRegion();
if (!region)
@@ -939,9 +951,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;
}
@@ -968,7 +978,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());
@@ -1108,6 +1118,7 @@ void LLFloaterIMPanel::onFlyoutCommit(LLComboBox* flyout, const LLSD& value)
{
switch (mSessionType)
{
+ case SUPPORT_SESSION:
case GROUP_SESSION: LLGroupActions::show(mOtherParticipantUUID); 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.
@@ -1154,13 +1165,8 @@ void show_log_browser(const std::string& name, const std::string& id)
const std::string file(LLLogChat::makeLogFileName(name));
if (gSavedSettings.getBOOL("LiruLegacyLogLaunch"))
{
-#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
- return;
+ if (!LLWindow::ShellEx(file)) // 0 = success, otherwise fallback on internal browser.
+ return;
}
LLFloaterWebContent::Params p;
p.url("file:///" + file);
@@ -1318,6 +1324,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)
@@ -1352,6 +1360,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, LL_VIEWER_CHANNEL_GRK));
+ }
+
if ( mSessionInitialized )
{
// Split messages that are too long, same code like in llimpanel.cpp
@@ -1411,7 +1424,7 @@ void LLFloaterIMPanel::onSendMsg()
// Look for actions here.
if (action)
{
- utf8_text.replace(0,3,"");
+ utf8_text.erase(0,3);
}
else
{
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index 6a2e54dbe..832c0ddee 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -60,7 +60,7 @@ public:
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 +77,7 @@ public:
// 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 +114,7 @@ public:
{
P2P_SESSION,
GROUP_SESSION,
+ SUPPORT_SESSION,
ADHOC_SESSION
};
const SType& getSessionType() const { return mSessionType; }
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 6dba5b453..d56cf58c7 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -50,6 +50,7 @@
#include "llavatarnamecache.h"
#include "llfloaterchat.h"
#include "llfloaterchatterbox.h"
+#include "llgroupactions.h"
#include "llimpanel.h"
#include "llmutelist.h"
#include "llspeakers.h"
@@ -616,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);
@@ -660,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())
{
@@ -792,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)
@@ -1051,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())
@@ -1111,7 +1088,7 @@ std::string LLIMMgr::getOfflineMessage(const LLUUID& id)
void LLIMMgr::noteOfflineUsers(
LLFloaterIMPanel* floater,
- const std::vector& ids)
+ const uuid_vec_t& ids)
{
if(ids.empty())
{
@@ -1136,7 +1113,7 @@ void LLIMMgr::noteOfflineUsers(
}
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();
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 12aa856bd..be10c57ff 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -92,7 +92,7 @@ public:
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,
@@ -199,20 +199,18 @@ private:
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 noteOfflineUsers(LLFloaterIMPanel* panel, const uuid_vec_t& ids);
+ void noteMutedUsers(LLFloaterIMPanel* panel, const uuid_vec_t& ids);
void processIMTypingCore(const LLIMInfo* im_info, BOOL typing);
- static void onInviteNameLookup(const LLUUID& id, const std::string& full_name, bool is_group, LLSD payload);
-
private:
std::set > mFloaters;
@@ -221,7 +219,7 @@ private:
// 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 16e0b9c6c..e06b40724 100644
--- a/indra/newview/llinventoryactions.cpp
+++ b/indra/newview/llinventoryactions.cpp
@@ -107,11 +107,8 @@ bool get_selection_object_uuids(LLFolderView *root, uuid_vec_t& ids)
{
uuid_vec_t results;
//S32 no_object = 0;
- std::set selectedItems = root->getSelectionList();
- for(std::set::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
+ for(const auto& id : root->getSelectionList())
{
- const LLUUID& id(*it);
-
if(id.notNull())
{
results.push_back(id);
@@ -134,12 +131,12 @@ bool LLInventoryAction::doToSelected(LLFolderView* root, std::string action, BOO
if (!root)
return true;
- std::set selected_items = root->getSelectionList();
+ 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)))
{
- std::set::iterator set_iter = std::find_if(selected_items.begin(), selected_items.end(), boost::bind(&depth_nesting_in_marketplace, _1) >= 0);
+ 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)
@@ -177,7 +174,7 @@ bool LLInventoryAction::doToSelected(LLFolderView* root, std::string action, BOO
// Copying to the marketplace needs confirmation if nocopy items are involved
if (("copy_to_marketplace_listings" == action))
{
- std::set::iterator set_iter = selected_items.begin();
+ 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));
@@ -233,8 +230,6 @@ bool LLInventoryAction::doToSelected(LLFolderView* root, std::string action, BOO
LLFloater::setFloaterHost(multi_floaterp);
}
- std::set::iterator set_iter;
-
// This rather warty piece of code is to allow items to be removed
// from the avatar in a batch, eliminating redundant
@@ -250,9 +245,9 @@ bool LLInventoryAction::doToSelected(LLFolderView* root, std::string action, BOO
}
else
{
- for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
+ for (const auto& id : selected_items)
{
- LLFolderViewItem* folder_item = root->getItemByID(*set_iter);
+ LLFolderViewItem* folder_item = root->getItemByID(id);
if(!folder_item) continue;
LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener();
if(!bridge) continue;
@@ -286,10 +281,9 @@ void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root)
return;
}
- std::set selected_items = root->getSelectionList();
- for (std::set::const_iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
+ for (const auto& item : root->getSelectionList())
{
- const LLInventoryObject* obj(gInventory.getObject(*set_iter));
+ const LLInventoryObject* obj(gInventory.getObject(item));
if (!obj) continue;
if (gInventory.isObjectDescendentOf(obj->getParentUUID(), marketplacelistings_id))
{
@@ -522,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)
@@ -644,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();
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 49693f6c2..5326a64d3 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -128,7 +128,7 @@ bool isAddAction(const std::string& action)
bool isRemoveAction(const std::string& action)
{
- return ("take_off" == action || "detach" == action || "deactivate" == action);
+ return ("take_off" == action || "detach" == action);
}
// Used by LLFolderBridge as callback for directory fetching recursion
@@ -531,7 +531,7 @@ 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++)
@@ -573,7 +573,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++)
@@ -611,7 +611,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++)
@@ -2217,7 +2217,7 @@ BOOL LLFolderBridge::isClipboardPasteable() const
return FALSE;
}
- std::vector objects;
+ uuid_vec_t objects;
LLInventoryClipboard::instance().retrieve(objects);
const LLViewerInventoryCategory *current_cat = getCategory();
@@ -2265,7 +2265,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++)
@@ -2905,10 +2905,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)
@@ -3370,9 +3370,9 @@ void LLFolderBridge::pasteFromClipboard(bool only_copies)
if (clipboard.isCutMode())
{
//Items are not removed from folder on "cut", so we need update listing folder on "paste" operation
- std::vector objects;
+ uuid_vec_t objects;
clipboard.retrieve(objects);
- for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter)
+ 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) ||
@@ -3420,7 +3420,7 @@ void LLFolderBridge::perform_pasteFromClipboard(bool only_copies)
const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
- std::vector objects;
+ uuid_vec_t objects;
LLInventoryClipboard::instance().retrieve(objects);
LLViewerInventoryCategory* dest_folder = getCategory();
@@ -3429,7 +3429,7 @@ void LLFolderBridge::perform_pasteFromClipboard(bool only_copies)
std::string error_msg;
const LLViewerInventoryCategory* master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID);
int index = 0;
- for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter)
+ for (auto iter = objects.begin(); iter != objects.end(); ++iter)
{
const LLUUID& item_id = (*iter);
LLInventoryItem *item = model->getItem(item_id);
@@ -3456,7 +3456,7 @@ void LLFolderBridge::perform_pasteFromClipboard(bool only_copies)
else
{
// Check that all items can be moved into that folder : for the moment, only stock folder mismatch is checked
- for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter)
+ for (auto iter = objects.begin(); iter != objects.end(); ++iter)
{
const LLUUID& item_id = (*iter);
LLInventoryItem *item = model->getItem(item_id);
@@ -3475,7 +3475,7 @@ void LLFolderBridge::perform_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)
{
@@ -3629,9 +3629,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)
{
@@ -5654,7 +5654,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)
diff --git a/indra/newview/llinventoryclipboard.cpp b/indra/newview/llinventoryclipboard.cpp
index 2a6fe947d..fd121ee01 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 35a5c6fcf..e6d493882 100644
--- a/indra/newview/llinventoryclipboard.h
+++ b/indra/newview/llinventoryclipboard.h
@@ -51,12 +51,12 @@ public:
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 @@ public:
protected:
static LLInventoryClipboard sInstance;
- std::vector mObjects;
+ uuid_vec_t mObjects;
bool mCutMode;
public:
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 2d3c58bb3..d23ad4417 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -1507,7 +1507,7 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_
gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,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;
+ 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;
@@ -1613,7 +1613,7 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_
((folder_type != LLFolderType::FT_MARKETPLACE_STOCK) && (unique_key != default_key)))
{
// Create one folder per vector at the right depth and of the right type
- std::map >::iterator items_vector_it = items_vector.begin();
+ auto items_vector_it = items_vector.begin();
while (items_vector_it != items_vector.end())
{
// Create a new folder
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index f4c374108..4b82be393 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -249,7 +249,7 @@ public:
LLInventoryItem* item);
protected:
- std::set mSeen;
+ uuid_set_t mSeen;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -492,7 +492,7 @@ public:
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 f2739df69..c7c4f9144 100644
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -193,13 +193,13 @@ 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_WEARABLES_MASK)
+ switch (misc_flag & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK)
{
case 0: return LLInventoryType::ICONNAME_SETTINGS_SKY;
case 1: return LLInventoryType::ICONNAME_SETTINGS_WATER;
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 30a3ca092..4a7dea11f 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -95,7 +95,7 @@ public:
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
protected:
LLInventoryModel* mModel;
- std::set mCachedCatIDs;
+ uuid_set_t mCachedCatIDs;
};
bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
@@ -420,7 +420,7 @@ 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;
+ uuid_vec_t folder_ids;
for (cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
{
LLViewerInventoryCategory* cat = cit->second;
@@ -431,7 +431,7 @@ 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 (auto folder_ids_it = folder_ids.begin(); folder_ids_it != folder_ids.end(); ++folder_ids_it)
{
LLUUID folder_id = (*folder_ids_it);
@@ -444,12 +444,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);
@@ -461,7 +461,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);
@@ -2081,7 +2081,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];
@@ -2117,7 +2117,7 @@ bool LLInventoryModel::loadSkeleton(
}
// go ahead and add the cats returned during the download
- std::set