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 + + canonical_repo + https://bitbucket.org/alchemyviewer/3p-abseil-src + copyright + Copyright 2018 The Abseil Authors. + description + Abseil Common Libraries + license + Apache 2.0 + license_file + LICENSES/abseil-cpp.txt + name + abseil-cpp + platforms + + common + + archive + + hash + b95e484e5b6cc0d10da48d3cf0ad37cd + hash_algorithm + md5 + url + http://depot.alchemyviewer.org/pub/packages/common/abseil_cpp-20190327.190862343-common-190862343.tar.bz2 + + name + common + + + version + 20190327.190862343 + 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 << "\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::const_iterator not_cached_id = cached_ids.end(); + auto not_cached_id = cached_ids.end(); cached_category_count = cached_ids.size(); for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 915dbc296..f8c5e81f3 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -27,7 +27,7 @@ #ifndef LL_LLINVENTORYMODEL_H #define LL_LLINVENTORYMODEL_H -#include +#include #include #include #include @@ -76,7 +76,7 @@ public: typedef std::vector > cat_array_t; typedef std::vector > item_array_t; - typedef std::set changed_items_t; + typedef uuid_set_t changed_items_t; class FetchItemHttpHandler : public LLHTTPClient::ResponderWithResult { @@ -154,13 +154,13 @@ private: // the inventory using several different identifiers. // mInventory member data is the 'master' list of inventory, and // mCategoryMap and mItemMap store uuid->object mappings. - typedef std::unordered_map > cat_map_t; - typedef std::unordered_map > item_map_t; + typedef boost::unordered_map > cat_map_t; + typedef boost::unordered_map > item_map_t; cat_map_t mCategoryMap; item_map_t mItemMap; // This last set of indices is used to map parents to children. - typedef std::unordered_map parent_cat_map_t; - typedef std::unordered_map parent_item_map_t; + typedef boost::unordered_map parent_cat_map_t; + typedef boost::unordered_map parent_item_map_t; parent_cat_map_t mParentChildCategoryTree; parent_item_map_t mParentChildItemTree; @@ -467,7 +467,7 @@ public: LLInitializedS32& operator++() { ++mValue; return *this; } LLInitializedS32& operator--() { --mValue; return *this; } }; - typedef std::unordered_map update_map_t; + typedef boost::unordered_map update_map_t; // Call when there are category updates. Call them *before* the // actual update so the method can do descendent accounting correctly. @@ -592,8 +592,8 @@ protected: cat_array_t* getUnlockedCatArray(const LLUUID& id); item_array_t* getUnlockedItemArray(const LLUUID& id); private: - std::unordered_map mCategoryLock; - std::unordered_map mItemLock; + boost::unordered_map mCategoryLock; + boost::unordered_map mItemLock; //-------------------------------------------------------------------- // Debugging diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index c9c91de85..b1b9858cf 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -589,7 +589,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask) if (!mCategoryMap.size()) return; - std::vector deleted_categories_ids; + uuid_vec_t deleted_categories_ids; for (category_map_t::iterator iter = mCategoryMap.begin(); iter != mCategoryMap.end(); @@ -665,7 +665,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask) } // Remove deleed categories from the list - for (std::vector::iterator deleted_id = deleted_categories_ids.begin(); deleted_id != deleted_categories_ids.end(); ++deleted_id) + for (auto deleted_id = deleted_categories_ids.begin(); deleted_id != deleted_categories_ids.end(); ++deleted_id) { removeCategory(*deleted_id); } diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index baa245788..afc4bebd0 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -30,6 +30,7 @@ #include "lluuid.h" #include "llmd5.h" #include +#include #include class LLViewerInventoryCategory; @@ -177,7 +178,7 @@ protected: virtual void onAssetAdded(const LLUUID& asset_id) {} virtual void done() = 0; - typedef std::vector item_ref_t; + typedef uuid_vec_t item_ref_t; item_ref_t mAddedItems; item_ref_t mWatchedAssets; @@ -256,7 +257,7 @@ protected: class LLInventoryCategoriesObserver : public LLInventoryObserver { public: - typedef boost::function callback_t; + typedef std::function callback_t; LLInventoryCategoriesObserver() {}; virtual void changed(U32 mask); @@ -284,7 +285,7 @@ protected: LLUUID mCatID; }; - typedef std::map category_map_t; + typedef boost::unordered_map category_map_t; typedef category_map_t::value_type category_map_value_t; category_map_t mCategoryMap; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 82fc9d391..a8a155436 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1118,7 +1118,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc setSelectionByID(obj_id, take_keyboard_focus); } -void LLInventoryPanel::setSelectCallback(const boost::function& items, BOOL user_action)>& cb) +void LLInventoryPanel::setSelectCallback(const std::function& items, BOOL user_action)>& cb) { if (mFolderRoot.get()) { @@ -1365,15 +1365,13 @@ bool LLInventoryPanel::isSelectionRemovable() bool can_delete = false; if (mFolderRoot.get()) { - std::set selection_set = mFolderRoot.get()->getSelectionList(); + auto selection_set = mFolderRoot.get()->getSelectionList(); if (!selection_set.empty()) { can_delete = true; - for (std::set::iterator iter = selection_set.begin(); - iter != selection_set.end(); - ++iter) + for (const auto& id : selection_set) { - LLFolderViewItem *item = getItemByID(*iter); + LLFolderViewItem *item = getItemByID(id); const LLFolderViewEventListener* listener =item->getListener(); if (!listener) { diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index a29b0ea99..524710b67 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -129,7 +129,7 @@ public: void closeAllFolders(); void openDefaultFolderForType(LLAssetType::EType); void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus); - void setSelectCallback(const boost::function& items, BOOL user_action)>& cb); + void setSelectCallback(const std::function& items, BOOL user_action)>& cb); void clearSelection(); bool isSelectionRemovable(); LLInventoryFilter& getFilter(); @@ -211,7 +211,7 @@ protected: LLScrollContainer* mScroller; LLPointer mGroupedItemBridge; - std::map mItemMap; + boost::unordered_map mItemMap; /** * Pointer to LLInventoryFolderViewModelBuilder. * diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h index 4983af562..057c8d5e7 100644 --- a/indra/newview/lllandmarklist.h +++ b/indra/newview/lllandmarklist.h @@ -68,7 +68,7 @@ protected: typedef std::map landmark_list_t; landmark_list_t mList; - typedef std::set landmark_bad_list_t; + typedef uuid_set_t landmark_bad_list_t; landmark_bad_list_t mBadList; typedef std::map landmark_requested_list_t; diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 10efa114c..b2ee4fba4 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -1123,10 +1123,10 @@ void LLMarketplaceInventoryObserver::changed(U32 mask) // When things are added to the marketplace, we might need to re-validate and fix the containing listings if (mask & LLInventoryObserver::ADD) { - const 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(); // First, count the number of items in this list... S32 count = 0; for (;id_it != id_end; ++id_it) @@ -1159,10 +1159,10 @@ void LLMarketplaceInventoryObserver::changed(U32 mask) if (mask & (LLInventoryObserver::INTERNAL | LLInventoryObserver::STRUCTURE)) { - 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) { LLInventoryObject* obj = gInventory.getObject(*id_it); @@ -1878,7 +1878,7 @@ bool LLMarketplaceData::isUpdating(const LLUUID& folder_id, S32 depth) else { const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); - std::set::iterator it = mPendingUpdateSet.find(marketplace_listings_uuid); + auto it = mPendingUpdateSet.find(marketplace_listings_uuid); if (it != mPendingUpdateSet.end()) { // If we're waiting for data for the marketplace listings root, we are in the updating process for all @@ -1896,7 +1896,7 @@ bool LLMarketplaceData::isUpdating(const LLUUID& folder_id, S32 depth) void LLMarketplaceData::setUpdating(const LLUUID& folder_id, bool isUpdating) { - std::set::iterator it = mPendingUpdateSet.find(folder_id); + auto it = mPendingUpdateSet.find(folder_id); if (it != mPendingUpdateSet.end()) { mPendingUpdateSet.erase(it); diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index 8aa4dfad8..91a741018 100644 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -271,7 +271,7 @@ private: // Update data U32 mMarketPlaceDataFetched; status_updated_signal_t* mDataFetchedSignal; - std::set mPendingUpdateSet; + uuid_set_t mPendingUpdateSet; // Listing folders waiting for validation typedef std::map waiting_list_t; diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index e83f1f4e0..7e7095529 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -111,7 +111,7 @@ protected: typedef boost::unordered_map get_callback_te_map_t; get_callback_te_map_t mGetTECallbacks; - typedef std::set getall_queue_t; + typedef uuid_set_t getall_queue_t; getall_queue_t mGetAllQueue; getall_queue_t mGetAllRequested; typedef std::map getall_pending_map_t; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 577d2a4b6..f9b72c774 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -70,14 +70,14 @@ LLMediaCtrl::Params::Params() : start_url("start_url"), border_visible("border_visible", false), decouple_texture_size("decouple_texture_size", false), + trusted_content("trusted_content", false), + focus_on_click("focus_on_click", true), texture_width("texture_width", 1024), texture_height("texture_height", 1024), caret_color("caret_color"), initial_mime_type("initial_mime_type"), - error_page_url("error_page_url"), media_id("media_id"), - trusted_content("trusted_content", false), - focus_on_click("focus_on_click", true) + error_page_url("error_page_url") { } @@ -85,24 +85,25 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : LLPanel( p.name, p.rect, FALSE), LLInstanceTracker(LLUUID::generateNewID()), mTextureDepthBytes( 4 ), - mBorder(NULL), + mBorder(nullptr), mFrequentUpdates( true ), mForceUpdate( false ), - mHomePageUrl( "" ), + mTrusted(p.trusted_content), mAlwaysRefresh( false ), - mMediaSource( 0 ), mTakeFocusOnClick( p.focus_on_click ), - mCurrentNavUrl( "about:blank" ), mStretchToFill( true ), mMaintainAspectRatio ( true ), + mClearCache(false), + mHoverTextChanged(false), mDecoupleTextureSize ( false ), + mUpdateScrolls( false ), + mHomePageUrl( "" ), + mHomePageMimeType(p.initial_mime_type), + mCurrentNavUrl( "about:blank" ), + mErrorPageURL(p.error_page_url), + mMediaSource( nullptr ), mTextureWidth ( 1024 ), mTextureHeight ( 1024 ), - mClearCache(false), - mHomePageMimeType(p.initial_mime_type), - mErrorPageURL(p.error_page_url), - mTrusted(p.trusted_content), - mHoverTextChanged(false), mContextMenu() { { @@ -140,10 +141,17 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : LLMediaCtrl::~LLMediaCtrl() { + auto menu = mContextMenu.get(); + if (menu) + { + menu->die(); + mContextMenu.markDead(); + } + if (mMediaSource) { mMediaSource->remObserver( this ); - mMediaSource = NULL; + mMediaSource = nullptr; } } @@ -157,7 +165,9 @@ void LLMediaCtrl::setBorderVisible( BOOL border_visible ) addChild( mBorder ); } if(mBorder) + { mBorder->setVisible(border_visible); + } }; //////////////////////////////////////////////////////////////////////////////// @@ -240,7 +250,7 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) mMediaSource->mouseUp(x, y, mask); } - gFocusMgr.setMouseCapture( NULL ); + gFocusMgr.setMouseCapture(nullptr ); return TRUE; } @@ -285,7 +295,7 @@ BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask ) } } - gFocusMgr.setMouseCapture( NULL ); + gFocusMgr.setMouseCapture(nullptr ); return TRUE; } @@ -309,12 +319,19 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) setFocus( TRUE ); } - LLMenuGL* menu = (LLMenuGL*)mContextMenu.get(); - if (menu) + auto con_menu = (LLMenuGL*)mContextMenu.get(); + if (con_menu) { - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this,menu, x, y); + /* Singu Note: Share your toys!! + // hide/show debugging options + bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); + con_menu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); + con_menu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); + */ + + con_menu->buildDrawLabels(); + con_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, con_menu, x, y); } return TRUE; @@ -366,7 +383,7 @@ void LLMediaCtrl::onFocusLost() if( LLEditMenuHandler::gEditMenuHandler == mMediaSource ) { // Clear focus for edit menu items - LLEditMenuHandler::gEditMenuHandler = NULL; + LLEditMenuHandler::gEditMenuHandler = nullptr; } } @@ -379,13 +396,21 @@ void LLMediaCtrl::onFocusLost() // BOOL LLMediaCtrl::postBuild () { - LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_media_ctrl.xml",LLMenuGL::sMenuContainer); + /*LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; + registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); + registar.add("Open.ViewSource", boost::bind(&LLMediaCtrl::onShowSource, this)); + + // stinson 05/05/2014 : use this as the parent of the context menu if the static menu + // container has yet to be created + LLView* menuParent = (gMenuHolder != nullptr) ? dynamic_cast(gMenuHolder) : dynamic_cast(this); + llassert(menuParent != NULL);*/ + auto menu = LLUICtrlFactory::getInstance()->buildMenu("menu_media_ctrl.xml",LLMenuGL::sMenuContainer); if(menu) { mContextMenu = menu->getHandle(); } - setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2)); + setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2)); return true; } @@ -395,6 +420,12 @@ void LLMediaCtrl::onOpenWebInspector() mMediaSource->getMediaPlugin()->showWebInspector( true ); } +void LLMediaCtrl::onShowSource() +{ + if (mMediaSource && mMediaSource->hasMedia()) + mMediaSource->getMediaPlugin()->showPageSource(); +} + //////////////////////////////////////////////////////////////////////////////// // BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) @@ -446,12 +477,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) { BOOL result = FALSE; - // only accept 'printable' characters, sigh... - if (uni_char >= 32 // discard 'control' characters - && uni_char != 127) // SDL thinks this is 'delete' - yuck. + if (mMediaSource) { - if (mMediaSource) - result = mMediaSource->handleUnicodeCharHere(uni_char); + result = mMediaSource->handleUnicodeCharHere(uni_char); } if ( ! result ) @@ -462,7 +490,7 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::onVisibilityChange ( const LLSD& new_visibility ) +void LLMediaCtrl::onVisibilityChanged( const LLSD& new_visibility ) { // set state of frequent updates automatically if visibility changes if ( new_visibility.asBoolean() ) @@ -514,6 +542,16 @@ void LLMediaCtrl::navigateForward() } } +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::navigateStop() +{ + if (mMediaSource && mMediaSource->hasMedia()) + { + mMediaSource->getMediaPlugin()->browse_stop(); + } +} + //////////////////////////////////////////////////////////////////////////////// // bool LLMediaCtrl::canNavigateBack() @@ -551,23 +589,7 @@ void LLMediaCtrl::clearCache() //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::set404RedirectUrl( std::string redirect_url ) -{ - if(mMediaSource && mMediaSource->hasMedia()) - mMediaSource->getMediaPlugin()->set_status_redirect( 404, redirect_url ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLMediaCtrl::clr404RedirectUrl() -{ - if(mMediaSource && mMediaSource->hasMedia()) - mMediaSource->getMediaPlugin()->set_status_redirect(404, ""); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) +void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type, bool clean_browser) { // don't browse to anything that starts with secondlife:// or sl:// const std::string protocol1 = "secondlife://"; @@ -582,12 +604,9 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) if (ensureMediaSourceExists()) { - if (mCurrentNavUrl != url_in) - { - mCurrentNavUrl = url_in; - mMediaSource->setSize(mTextureWidth, mTextureHeight); - mMediaSource->navigateTo(url_in, mime_type, mime_type.empty()); - } + mCurrentNavUrl = url_in; + mMediaSource->setSize(mTextureWidth, mTextureHeight); + mMediaSource->navigateTo(url_in, mime_type, mime_type.empty(), false, clean_browser); } } @@ -609,7 +628,6 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str mMediaSource->setSize(mTextureWidth, mTextureHeight); mMediaSource->navigateTo(LLWeb::escapeURL(expanded_filename), "text/html", false); } - } //////////////////////////////////////////////////////////////////////////////// @@ -699,7 +717,13 @@ bool LLMediaCtrl::ensureMediaSourceExists() mMediaSource->addObserver( this ); mMediaSource->setBackgroundColor( getBackgroundColor() ); mMediaSource->setTrustedBrowser(mTrusted); - mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); + + F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; + if (scale_factor != mMediaSource->getPageZoomFactor()) + { + mMediaSource->setPageZoomFactor( scale_factor ); + mUpdateScrolls = true; + } if(mClearCache) { @@ -721,7 +745,11 @@ bool LLMediaCtrl::ensureMediaSourceExists() // void LLMediaCtrl::unloadMediaSource() { - mMediaSource = NULL; + if (mMediaSource) + { + mMediaSource->remObserver(this); + mMediaSource = nullptr; + } } //////////////////////////////////////////////////////////////////////////////// @@ -735,10 +763,11 @@ LLPluginClassMedia* LLMediaCtrl::getMediaPlugin() // void LLMediaCtrl::draw() { - if ( gRestoreGL == 1 ) + if ( gRestoreGL == 1 || mUpdateScrolls) { LLRect r = getRect(); reshape( r.getWidth(), r.getHeight(), FALSE ); + mUpdateScrolls = false; return; } @@ -760,8 +789,8 @@ void LLMediaCtrl::draw() bool draw_media = false; - LLPluginClassMedia* media_plugin = NULL; - LLViewerMediaTexture* media_texture = NULL; + LLPluginClassMedia* media_plugin = nullptr; + LLViewerMediaTexture* media_texture = nullptr; if(mMediaSource && mMediaSource->hasMedia()) { @@ -784,7 +813,12 @@ void LLMediaCtrl::draw() { gGL.pushUIMatrix(); { - mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); + F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; + if (scale_factor != mMediaSource->getPageZoomFactor()) + { + mMediaSource->setPageZoomFactor( scale_factor ); + mUpdateScrolls = true; + } // scale texture to fit the space using texture coords gGL.getTexUnit(0)->bind(media_texture); @@ -793,52 +827,8 @@ void LLMediaCtrl::draw() F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth(); F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight(); - LLRect r = getRect(); - S32 width, height; - S32 x_offset = 0; - S32 y_offset = 0; - - if(mStretchToFill) - { - if(mMaintainAspectRatio) - { - F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight()); - F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); - if(media_aspect > view_aspect) - { - // max width, adjusted height - width = r.getWidth(); - height = llmin(llmax(ll_round(width / media_aspect), 0), r.getHeight()); - } - else - { - // max height, adjusted width - height = r.getHeight(); - width = llmin(llmax(ll_round(height * media_aspect), 0), r.getWidth()); - } - } - else - { - width = r.getWidth(); - height = r.getHeight(); - } - } - else - { - width = llmin(media_plugin->getWidth(), r.getWidth()); - height = llmin(media_plugin->getHeight(), r.getHeight()); - } - - x_offset = (r.getWidth() - width) / 2; - y_offset = (r.getHeight() - height) / 2; - - /*if (mIgnoreUIScale) - { - x_offset = ll_round((F32)x_offset * LLUI::getScaleFactor().mV[VX]); - y_offset = ll_round((F32)y_offset * LLUI::getScaleFactor().mV[VY]); - width = ll_round((F32)width * LLUI::getScaleFactor().mV[VX]); - height = ll_round((F32)height * LLUI::getScaleFactor().mV[VY]); - }*/ + S32 x_offset, y_offset, width, height; + calcOffsetsAndSize(&x_offset, &y_offset, &width, &height); // draw the browser gGL.setSceneBlendType(LLRender::BT_REPLACE); @@ -897,6 +887,50 @@ void LLMediaCtrl::draw() setBackgroundOpaque(background_opaque); } +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::calcOffsetsAndSize(S32 *x_offset, S32 *y_offset, S32 *width, S32 *height) +{ + const LLRect &r = getRect(); + *x_offset = *y_offset = 0; + + const auto& media_plugin = mMediaSource->getMediaPlugin(); + + if(mStretchToFill) + { + if(mMaintainAspectRatio) + { + F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight()); + F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); + if(media_aspect > view_aspect) + { + // max width, adjusted height + *width = r.getWidth(); + *height = llmin(llmax(ll_round(*width / media_aspect), 0), r.getHeight()); + } + else + { + // max height, adjusted width + *height = r.getHeight(); + *width = llmin(llmax(ll_round(*height * media_aspect), 0), r.getWidth()); + } + } + else + { + *width = r.getWidth(); + *height = r.getHeight(); + } + } + else + { + *width = llmin(media_plugin->getWidth(), r.getWidth()); + *height = llmin(media_plugin->getHeight(), r.getHeight()); + } + + *x_offset = (r.getWidth() - *width) / 2; + *y_offset = (r.getHeight() - *height) / 2; +} + //////////////////////////////////////////////////////////////////////////////// // void LLMediaCtrl::convertInputCoords(S32& x, S32& y) @@ -1000,17 +1034,24 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_CLICK_LINK_HREF: { - LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL; // retrieve the event parameters std::string url = self->getClickURL(); std::string target = self->getClickTarget(); std::string uuid = self->getClickUUID(); + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL; - LLWeb::loadURL(url, target, std::string()); + // try as slurl first + if (!LLURLDispatcher::dispatch(url, "clicked", nullptr, mTrusted)) + { + LLWeb::loadURL(url, target, uuid); + } - //LLNotification::Params notify_params("PopupAttempt"); + // CP: removing this code because we no longer support popups so this breaks the flow. + // replaced with a bare call to LLWeb::LoadURL(...) + //LLNotification::Params notify_params; + //notify_params.name = "PopupAttempt"; //notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID); - //notify_params.functor(boost::bind(&LLMediaCtrl::onPopup, this, _1, _2)); + //notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2); //if (mTrusted) //{ @@ -1098,7 +1139,24 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_DEBUG_MESSAGE: { - LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL; + std::string level = self->getDebugMessageLevel(); + if (level == "debug") + { + LL_DEBUGS("Media") << self->getDebugMessageText() << LL_ENDL; + } + else if (level == "info") + { + LL_INFOS("Media") << self->getDebugMessageText() << LL_ENDL; + } + else if (level == "warn") + { + LL_WARNS("Media") << self->getDebugMessageText() << LL_ENDL; + } + else if (level == "error") + { + LL_ERRS("Media") << self->getDebugMessageText() << LL_ENDL; + } + }; break; @@ -1119,7 +1177,7 @@ std::string LLMediaCtrl::getCurrentNavUrl() return mCurrentNavUrl; } -bool LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) +void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) { if (response["open"]) { @@ -1130,7 +1188,6 @@ bool LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) // Make sure the opening instance knows its window open request was denied, so it can clean things up. LLViewerMedia::proxyWindowClosed(notification["payload"]["uuid"]); } - return FALSE; } void LLMediaCtrl::showNotification(LLNotificationPtr notify) diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 02f4558d0..6235ee9cb 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -2,31 +2,25 @@ * @file llmediactrl.h * @brief Web browser UI control * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,6 +31,7 @@ #include "lluictrl.h" #include "llframetimer.h" +#include "llnotificationptr.h" class LLViewBorder; class LLUICtrlFactory; @@ -51,6 +46,7 @@ class LLMediaCtrl : { LOG_CLASS(LLMediaCtrl); public: + struct Params : public LLInitParam::Block { Optional start_url; @@ -88,24 +84,25 @@ public: // Defaults to true. void setTakeFocusOnClick( bool take_focus ); - virtual LLXMLNodePtr getXML(bool save_children = true) const; + virtual LLXMLNodePtr getXML(bool save_children = true) const override; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); // handle mouse related methods - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen); + BOOL handleHover( S32 x, S32 y, MASK mask ) override; + BOOL handleMouseUp( S32 x, S32 y, MASK mask ) override; + BOOL handleMouseDown( S32 x, S32 y, MASK mask ) override; + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override; + BOOL handleDoubleClick( S32 x, S32 y, MASK mask ) override; + BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ) override; + BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) override; // navigation - void navigateTo( std::string url_in, std::string mime_type = ""); + void navigateTo( std::string url_in, std::string mime_type = "", bool clean_browser = false); void navigateBack(); void navigateHome(); void navigateForward(); + void navigateStop(); void navigateToLocalPage( const std::string& subdir, const std::string& filename_in ); bool canNavigateBack(); bool canNavigateForward(); @@ -128,9 +125,6 @@ public: // Clear the browser cache when the instance gets loaded void clearCache(); - void set404RedirectUrl( std::string redirect_url ); - void clr404RedirectUrl(); - // accessor/mutator for flag that indicates if frequent updates to texture happen bool getFrequentUpdates() { return mFrequentUpdates; }; void setFrequentUpdates( bool frequentUpdatesIn ) { mFrequentUpdates = frequentUpdatesIn; }; @@ -153,42 +147,48 @@ public: void setTextureSize(S32 width, S32 height); - void showNotification(boost::shared_ptr notify); + void showNotification(LLNotificationPtr notify); void hideNotification(); void setTrustedContent(bool trusted); // over-rides - virtual BOOL handleKeyHere( KEY key, MASK mask); - virtual BOOL handleKeyUpHere(KEY key, MASK mask); - virtual void handleVisibilityChange ( BOOL new_visibility ); - virtual BOOL handleUnicodeCharHere(llwchar uni_char); - virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE); - virtual void draw(); - virtual BOOL postBuild(); + BOOL handleKeyHere( KEY key, MASK mask) override; + BOOL handleKeyUpHere(KEY key, MASK mask) override; + void handleVisibilityChange ( BOOL new_visibility ) override; + BOOL handleUnicodeCharHere(llwchar uni_char) override; + void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE) override; + void draw() override; + BOOL postBuild() override; // focus overrides - void onFocusLost(); - void onFocusReceived(); + void onFocusLost() override; + void onFocusReceived() override; // Incoming media event dispatcher - virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override; // right click debugging item void onOpenWebInspector(); + void onShowSource(); LLUUID getTextureID() {return mMediaTextureID;} // The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true. - virtual bool wantsKeyUpKeyDown() const; - virtual bool wantsReturnKey() const; + bool wantsKeyUpKeyDown() const override; + bool wantsReturnKey() const override; + + virtual BOOL acceptsTextInput() const override { return TRUE; } protected: void convertInputCoords(S32& x, S32& y); private: - void onVisibilityChange ( const LLSD& new_visibility ); - bool onPopup(const LLSD& notification, const LLSD& response); + void calcOffsetsAndSize(S32 *x_offset, S32 *y_offset, S32 *width, S32 *height); + + private: + void onVisibilityChanged ( const LLSD& new_visibility ); + void onPopup(const LLSD& notification, const LLSD& response); const S32 mTextureDepthBytes; LLUUID mMediaTextureID; @@ -204,7 +204,8 @@ public: mHidingInitialLoad, mClearCache, mHoverTextChanged, - mDecoupleTextureSize; + mDecoupleTextureSize, + mUpdateScrolls; std::string mHomePageUrl, mHomePageMimeType, diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 28303be2c..44599742d 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -645,18 +645,14 @@ void LLMeshRepoThread::runQueue(std::deque& set, std::function fn) +void LLMeshRepoThread::runSet(uuid_set_t& set, std::function fn) { - std::set incomplete; - for (std::set::iterator iter = set.begin(); iter != set.end(); ++iter) + for (auto iter = set.begin(); iter != set.end();) { - LLUUID mesh_id = *iter; - if (!fn(mesh_id)) - { - incomplete.insert(mesh_id); - } + if (fn(*iter)) + iter = set.erase(iter); + else ++iter; } - set = incomplete; } void LLMeshRepoThread::run() @@ -2694,7 +2690,7 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID); if (iter != mLoadingSkins.end()) { - for (std::set::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id) + for (auto obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id) { LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id); if (vobj) @@ -2834,7 +2830,7 @@ void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id) { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - std::set::iterator iter = mLoadingPhysicsShapes.find(mesh_id); + auto iter = mLoadingPhysicsShapes.find(mesh_id); if (iter == mLoadingPhysicsShapes.end()) { //no request pending for this skin info mLoadingPhysicsShapes.insert(mesh_id); @@ -2862,7 +2858,7 @@ LLModel::Decomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh_id { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - std::set::iterator iter = mLoadingDecompositions.find(mesh_id); + auto iter = mLoadingDecompositions.find(mesh_id); if (iter == mLoadingDecompositions.end()) { //no request pending for this skin info mLoadingDecompositions.insert(mesh_id); diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 9226c3c00..62666bc65 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -259,16 +259,16 @@ public: }; //set of requested skin info - std::set mSkinRequests; + uuid_set_t mSkinRequests; //queue of completed skin info requests std::queue mSkinInfoQ; //set of requested decompositions - std::set mDecompositionRequests; + uuid_set_t mDecompositionRequests; //set of requested physics shapes - std::set mPhysicsShapeRequests; + uuid_set_t mPhysicsShapeRequests; //queue of completed Decomposition info requests std::queue mDecompositionQ; @@ -295,7 +295,7 @@ public: ~LLMeshRepoThread(); void runQueue(std::deque, F32> >& queue, U32& count, S32& active_requests); - void runSet(std::set& set, std::function fn); + void runSet(uuid_set_t& set, std::function fn); void pushHeaderRequest(const LLVolumeParams& mesh_params, F32 delay = 0) { std::shared_ptr req; @@ -572,20 +572,20 @@ public: std::vector mPendingRequests; //list of mesh ids awaiting skin info - typedef std::map > skin_load_map; + typedef std::map skin_load_map; skin_load_map mLoadingSkins; //list of mesh ids that need to send skin info fetch requests std::queue mPendingSkinRequests; //list of mesh ids awaiting decompositions - std::set mLoadingDecompositions; + uuid_set_t mLoadingDecompositions; //list of mesh ids that need to send decomposition fetch requests std::queue mPendingDecompositionRequests; //list of mesh ids awaiting physics shapes - std::set mLoadingPhysicsShapes; + uuid_set_t mLoadingPhysicsShapes; //list of mesh ids that need to send physics shape fetch requests std::queue mPendingPhysicsShapeRequests; diff --git a/indra/newview/llpaneldirfind.cpp b/indra/newview/llpaneldirfind.cpp index 7c7a7c21c..2cd261ae5 100644 --- a/indra/newview/llpaneldirfind.cpp +++ b/indra/newview/llpaneldirfind.cpp @@ -243,9 +243,6 @@ BOOL LLPanelDirFind::postBuild() // need to handle secondlife:///app/ URLs for direct teleports mWebBrowser->setTrustedContent( true ); - // redirect 404 pages from S3 somewhere else - mWebBrowser->set404RedirectUrl( getString("redirect_404_url") ); - navigateToDefaultPage(); } diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp index 2080117c5..aa7f55196 100644 --- a/indra/newview/llpanelgroupbulkban.cpp +++ b/indra/newview/llpanelgroupbulkban.cpp @@ -129,7 +129,7 @@ void LLPanelGroupBulkBan::submit() (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); return; } - std::vector banned_agent_list; + uuid_vec_t banned_agent_list; std::vector agents = mImplementation->mBulkAgentList->getAllData(); std::vector::iterator iter = agents.begin(); for(;iter != agents.end(); ++iter) @@ -153,7 +153,7 @@ void LLPanelGroupBulkBan::submit() std::vector banned_avatar_names; std::vector out_of_limit_names; bool banning_self = FALSE; - std::vector::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), gAgent.getID()); + auto conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), gAgent.getID()); if (conflict != banned_agent_list.end()) { banned_agent_list.erase(conflict); @@ -164,7 +164,7 @@ void LLPanelGroupBulkBan::submit() for (const LLGroupMgrGroupData::ban_list_t::value_type& group_ban_pair : group_datap->mBanList) { const LLUUID& group_ban_agent_id = group_ban_pair.first; - std::vector::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), group_ban_agent_id); + auto conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), group_ban_agent_id); if (conflict != banned_agent_list.end()) { LLAvatarName av_name; @@ -182,8 +182,8 @@ void LLPanelGroupBulkBan::submit() // Otherwise we have a possibility of cutting more then we need to. if (banned_agent_list.size() > GB_MAX_BANNED_AGENTS - group_datap->mBanList.size()) { - std::vector::iterator exeedes_limit = banned_agent_list.begin() + GB_MAX_BANNED_AGENTS - group_datap->mBanList.size(); - for (std::vector::iterator itor = exeedes_limit ; + auto exeedes_limit = banned_agent_list.begin() + GB_MAX_BANNED_AGENTS - group_datap->mBanList.size(); + for (auto itor = exeedes_limit ; itor != banned_agent_list.end(); ++itor) { LLAvatarName av_name; diff --git a/indra/newview/llpanelgroupbulkimpl.h b/indra/newview/llpanelgroupbulkimpl.h index 235eeb8f9..ec2e06b47 100644 --- a/indra/newview/llpanelgroupbulkimpl.h +++ b/indra/newview/llpanelgroupbulkimpl.h @@ -78,7 +78,7 @@ public: std::string mBanLimitFail; std::string mCannotBanYourself; - std::set mInviteeIDs; + uuid_set_t mInviteeIDs; void (*mCloseCallback)(void* data); void* mCloseCallbackUserData; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index cf28f992c..ae4197578 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1710,7 +1710,7 @@ void LLPanelObjectInventory::updateInventory() // << " panel UUID: " << panel->mTaskUUID << "\n" // << " task UUID: " << object->mID << LL_ENDL; // We're still interested in this task's inventory. - std::set selected_items; + uuid_set_t selected_items; BOOL inventory_has_focus = FALSE; if (mHaveInventory) { @@ -1748,11 +1748,10 @@ void LLPanelObjectInventory::updateInventory() } // restore previous selection - std::set::iterator selection_it; bool first_item = true; - for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) + for (const auto id : selected_items) { - LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it); + LLFolderViewItem* selected_item = mFolders->getItemByID(id); if (selected_item) { diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index 02184af85..5203ce31f 100644 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -137,6 +137,8 @@ protected: // for LLInventoryObserver virtual void changed(U32 mask); BOOL mDirty; + +public: virtual const char *getTitleName() const { return "Preview"; } protected: diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index c0ab5ef97..eb0bece56 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -86,10 +86,9 @@ protected: void LLInventoryGestureAvailable::done() { - for(uuid_vec_t::iterator it = mComplete.begin(); it != mComplete.end(); ++it) + for(auto id : mComplete) { - LLPreview* preview = LLPreview::find((*it)); - if(preview) + if (auto preview = LLPreview::find(id)) { preview->refresh(); } @@ -98,15 +97,6 @@ void LLInventoryGestureAvailable::done() delete this; } -// Used for sorting -struct SortItemPtrsByName -{ - bool operator()(const LLInventoryItem* i1, const LLInventoryItem* i2) - { - return (LLStringUtil::compareDict(i1->getName(), i2->getName()) < 0); - } -}; - // static LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& item_id, const LLUUID& object_id, BOOL take_focus) { @@ -128,7 +118,7 @@ LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& // Move window to top-left of screen LLMultiFloater* hostp = preview->getHost(); - if (hostp == NULL) + if (hostp == nullptr) { LLRect r = preview->getRect(); LLRect screen = gFloaterView->getRect(); @@ -226,7 +216,7 @@ BOOL LLPreviewGesture::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, } else if (drop) { - LLScrollListItem* line = NULL; + LLScrollListItem* line = nullptr; if (cargo_type == DAD_ANIMATION) { line = addStep( STEP_ANIMATION ); @@ -342,23 +332,23 @@ bool LLPreviewGesture::handleSaveChangesDialog(const LLSD& notification, const L LLPreviewGesture::LLPreviewGesture() : LLPreview("Gesture Preview"), - mTriggerEditor(NULL), - mModifierCombo(NULL), - mKeyCombo(NULL), - mLibraryList(NULL), - mAddBtn(NULL), - mUpBtn(NULL), - mDownBtn(NULL), - mDeleteBtn(NULL), - mStepList(NULL), - mOptionsText(NULL), - mAnimationRadio(NULL), - mAnimationCombo(NULL), - mSoundCombo(NULL), - mChatEditor(NULL), - mSaveBtn(NULL), - mPreviewBtn(NULL), - mPreviewGesture(NULL), + mTriggerEditor(nullptr), + mModifierCombo(nullptr), + mKeyCombo(nullptr), + mLibraryList(nullptr), + mAddBtn(nullptr), + mUpBtn(nullptr), + mDownBtn(nullptr), + mDeleteBtn(nullptr), + mStepList(nullptr), + mOptionsText(nullptr), + mAnimationRadio(nullptr), + mAnimationCombo(nullptr), + mSoundCombo(nullptr), + mChatEditor(nullptr), + mSaveBtn(nullptr), + mPreviewBtn(nullptr), + mPreviewGesture(nullptr), mDirty(FALSE) { } @@ -367,14 +357,11 @@ LLPreviewGesture::LLPreviewGesture() LLPreviewGesture::~LLPreviewGesture() { // Userdata for all steps is a LLGestureStep we need to clean up - std::vector data_list = mStepList->getAllData(); - std::vector::iterator data_itor; - for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor) + for (auto& item : mStepList->getAllData()) { - LLScrollListItem* item = *data_itor; LLGestureStep* step = (LLGestureStep*)item->getUserdata(); delete step; - step = NULL; + step = nullptr; } } @@ -517,9 +504,10 @@ BOOL LLPreviewGesture::postBuild() if (item) { - childSetCommitCallback("desc", LLPreview::onText, this); - childSetText("desc", item->getDescription()); - getChild("desc")->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); + auto desc = getChild("desc"); + desc->setCommitCallback(LLPreview::onText, this); + desc->setValue(item->getDescription()); + desc->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe); } return TRUE; @@ -541,7 +529,20 @@ static const std::string valid_key_to_string(KEY key) { std::string skey(1,(char)key); std::string strkey = LLKeyboard::stringFromKey(key); - return ((skey == strkey && key >= ' ' && key <= '~') || (skey != strkey) ) ? strkey : ""; + return ((skey == strkey && key >= ' ' && key <= '~') || (skey != strkey) ) ? strkey : LLStringUtil::null; +} + +void load_and_sort(LLComboBox* combo, const LLViewerInventoryItem::item_array_t& items) +{ + combo->removeall(); + + // Load up the combobox + for (const auto& item : items) + { + combo->add(item->getName(), item->getAssetUUID()); + } + // Sort + combo->sortByName(); } void LLPreviewGesture::addKeys() @@ -549,10 +550,10 @@ void LLPreviewGesture::addKeys() LLComboBox* combo = mKeyCombo; combo->add( NONE_LABEL ); - for (KEY key = ' '; key < KEY_NONE; key++) + for (KEY key = ' '; key < KEY_NONE; ++key) { std::string keystr = valid_key_to_string(key); - if(keystr != "")combo->add( keystr, ADD_BOTTOM ); + if (!keystr.empty()) combo->add( keystr, ADD_BOTTOM ); } combo->setCurrentByIndex(0); } @@ -562,22 +563,7 @@ void LLPreviewGesture::addKeys() void LLPreviewGesture::addAnimations() { LLComboBox* combo = mAnimationCombo; - combo->removeall(); - - std::string none_text = getString("none_text"); - - combo->add(none_text, LLUUID::null); - - // Add all the default (legacy) animations - S32 i; - for (i = 0; i < gUserAnimStatesCount; ++i) - { - // Use the user-readable name - std::string label = LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName ); - const LLUUID& id = gUserAnimStates[i].mID; - combo->add(label, id); - } // Get all inventory items that are animations LLViewerInventoryCategory::cat_array_t cats; @@ -592,38 +578,21 @@ void LLPreviewGesture::addAnimations() LLInventoryModel::EXCLUDE_TRASH, is_copyable_animation); - // Copy into something we can sort - std::vector animations; + load_and_sort(combo, items); - S32 count = items.size(); - for(i = 0; i < count; ++i) + // Add all the default (legacy) animations + for (S32 i = gUserAnimStatesCount - 1; i >= 0; --i) { - animations.push_back( items.at(i) ); - } - - // Do the sort - std::sort(animations.begin(), animations.end(), SortItemPtrsByName()); - - // And load up the combobox - std::vector::iterator it; - for (it = animations.begin(); it != animations.end(); ++it) - { - LLInventoryItem* item = *it; - - combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM); + // Use the user-readable name + const auto& state = gUserAnimStates[i]; + combo->add(LLAnimStateLabels::getStateLabel(state.mName), state.mID, ADD_TOP); } + combo->add(getString("none_text"), LLUUID::null, ADD_TOP); } void LLPreviewGesture::addSounds() { - LLComboBox* combo = mSoundCombo; - combo->removeall(); - - std::string none_text = getString("none_text"); - - combo->add(none_text, LLUUID::null); - // Get all inventory items that are sounds LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; @@ -637,27 +606,9 @@ void LLPreviewGesture::addSounds() LLInventoryModel::EXCLUDE_TRASH, is_copyable_sound); - // Copy sounds into something we can sort - std::vector sounds; - - S32 i; - S32 count = items.size(); - for(i = 0; i < count; ++i) - { - sounds.push_back( items.at(i) ); - } - - // Do the sort - std::sort(sounds.begin(), sounds.end(), SortItemPtrsByName()); - - // And load up the combobox - std::vector::iterator it; - for (it = sounds.begin(); it != sounds.end(); ++it) - { - LLInventoryItem* item = *it; - - combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM); - } + LLComboBox* combo = mSoundCombo; + load_and_sort(combo, items); + combo->add(getString("none_text"), LLUUID::null, ADD_TOP); } @@ -732,12 +683,12 @@ void LLPreviewGesture::refresh() BOOL have_replace = !replace.empty(); LLScrollListItem* library_item = mLibraryList->getFirstSelected(); - BOOL have_library = (library_item != NULL); + BOOL have_library = (library_item != nullptr); LLScrollListItem* step_item = mStepList->getFirstSelected(); S32 step_index = mStepList->getFirstSelectedIndex(); S32 step_count = mStepList->getItemCount(); - BOOL have_step = (step_item != NULL); + BOOL have_step = (step_item != nullptr); mReplaceText->setEnabled(have_trigger || have_replace); mReplaceEditor->setEnabled(have_trigger || have_replace); @@ -937,7 +888,7 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, } delete gesture; - gesture = NULL; + gesture = nullptr; self->mAssetStatus = PREVIEW_ASSET_LOADED; } @@ -960,7 +911,7 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, } } delete item_idp; - item_idp = NULL; + item_idp = nullptr; } @@ -1007,7 +958,7 @@ void LLPreviewGesture::loadUIFromGesture(LLMultiGesture* gesture) { LLGestureStep* step = gesture->mSteps[i]; - LLGestureStep* new_step = NULL; + LLGestureStep* new_step = nullptr; switch(step->getType()) { @@ -1109,13 +1060,13 @@ void LLPreviewGesture::saveIfNeeded() LLNotificationsUtil::add("GestureSaveFailedTooManySteps"); delete gesture; - gesture = NULL; + gesture = nullptr; } else if (!ok) { LLNotificationsUtil::add("GestureSaveFailedTryAgain"); delete gesture; - gesture = NULL; + gesture = nullptr; } else { @@ -1187,7 +1138,7 @@ void LLPreviewGesture::saveIfNeeded() { // we're done with this gesture delete gesture; - gesture = NULL; + gesture = nullptr; } mDirty = FALSE; @@ -1200,7 +1151,7 @@ void LLPreviewGesture::saveIfNeeded() } delete [] buffer; - buffer = NULL; + buffer = nullptr; } @@ -1237,7 +1188,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, { // Saving into in-world object inventory LLViewerObject* object = gObjectList.findObject(info->mObjectUUID); - LLViewerInventoryItem* item = NULL; + LLViewerInventoryItem* item = nullptr; if(object) { item = (LLViewerInventoryItem*)object->getInventoryObject(info->mItemUUID); @@ -1271,7 +1222,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, LLNotificationsUtil::add("GestureSaveFailedReason", args); } delete info; - info = NULL; + info = nullptr; } @@ -1306,11 +1257,8 @@ LLMultiGesture* LLPreviewGesture::createGesture() LLKeyboard::keyFromString(key_string, &(gesture->mKey)); } - std::vector data_list = mStepList->getAllData(); - std::vector::iterator data_itor; - for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor) + for (auto& item : mStepList->getAllData()) { - LLScrollListItem* item = *data_itor; LLGestureStep* step = (LLGestureStep*)item->getUserdata(); switch(step->getType()) @@ -1366,11 +1314,7 @@ LLMultiGesture* LLPreviewGesture::createGesture() void LLPreviewGesture::updateLabel(LLScrollListItem* item) { LLGestureStep* step = (LLGestureStep*)item->getUserdata(); - - LLScrollListCell* cell = item->getColumn(0); - LLScrollListText* text_cell = (LLScrollListText*)cell; - std::string label = getLabel( step->getLabel()); - text_cell->setText(label); + static_cast(item->getColumn(0))->setText(getLabel(step->getLabel())); } void LLPreviewGesture::onCommitSetDirty() @@ -1518,9 +1462,7 @@ void LLPreviewGesture::onCommitWait() LLLocale locale(LLLocale::USER_LOCALE); F32 wait_seconds = (F32)atof(mWaitTimeEditor->getText().c_str()); - if (wait_seconds < 0.f) wait_seconds = 0.f; - if (wait_seconds > 3600.f) wait_seconds = 3600.f; - wait_step->mWaitSeconds = wait_seconds; + wait_step->mWaitSeconds = llclamp(wait_seconds, 0.f, 3600.f); } // Enable the input area if necessary @@ -1579,7 +1521,7 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) { // Order of enum EStepType MUST match the library_list element in floater_preview_gesture.xml - LLGestureStep* step = NULL; + LLGestureStep* step = nullptr; switch( step_type) { case STEP_ANIMATION: @@ -1596,13 +1538,14 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) break; default: LL_ERRS() << "Unknown step type: " << (S32)step_type << LL_ENDL; - return NULL; + return nullptr; } // Create an enabled item with this step LLSD row; - row["columns"][0]["value"] = getLabel(step->getLabel()); - row["columns"][0]["font"] = "SANSSERIF_SMALL"; + auto& element = row["columns"][0]; + element["value"] = getLabel(step->getLabel()); + element["font"] = "SANSSERIF_SMALL"; LLScrollListItem* step_item = mStepList->addElement(row); step_item->setUserdata(step); @@ -1616,57 +1559,80 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) } // static -std::string LLPreviewGesture::getLabel(std::vector labels) +std::string LLPreviewGesture::getLabel(const std::vector& v_labels) { - std::vector v_labels = labels ; - std::string result(""); - if( v_labels.size() != 2) { - return result; + return LLStringUtil::null; } - - if(v_labels[0]=="Chat") + + auto result(v_labels[0]); + if (result == "Chat") { - result=LLTrans::getString("Chat Message"); + static const auto chat = LLTrans::getString("Chat Message"); + result = chat; } - else if(v_labels[0]=="Sound") + else if (result == "Sound") { - result=LLTrans::getString("Sound"); + static const auto sound = LLTrans::getString("Sound"); + result = sound; } - else if(v_labels[0]=="Wait") + else if (result == "Wait") { - result=LLTrans::getString("Wait"); + static const auto wait = LLTrans::getString("Wait"); + result = wait; } - else if(v_labels[0]=="AnimFlagStop") + else if (result == "AnimFlagStop") { - result=LLTrans::getString("AnimFlagStop"); + static const auto stop = LLTrans::getString("AnimFlagStop"); + result = stop; } - else if(v_labels[0]=="AnimFlagStart") + else if (result == "AnimFlagStart") { - result=LLTrans::getString("AnimFlagStart"); + static const auto start = LLTrans::getString("AnimFlagStart"); + result = start; } // lets localize action value std::string action = v_labels[1]; if ("None" == action) { - action = LLTrans::getString("GestureActionNone"); + static const auto none = LLTrans::getString("GestureActionNone"); + action = none; } else if ("until animations are done" == action) { //action = LLFloaterReg::getInstance("preview_gesture")->getChild("wait_anim_check")->getLabel(); //Worst. Thing. Ever. We are in a static function. Find any existing gesture preview and grab the label from its 'wait_anim_check' element. - for(preview_map_t::iterator it = LLPreview::sInstances.begin(); it != LLPreview::sInstances.end();++it) + static auto wait_anim = LLStringUtil::null; + if (wait_anim.empty()) { - LLPreviewGesture* pPreview = dynamic_cast(it->second); - if(pPreview) + for(const auto& pair : LLPreview::sInstances) { - pPreview->getChild("wait_anim_check")->getLabel(); - break; + const auto& pPreview(pair.second); +#ifndef LL_WINDOWS +#if __cplusplus >= 201606 + constexpr std::string_view gesture("Gesture"); + if (pPreview && pPreview->getTitleName().compare(gesture) == 0) + LL_COMPILE_TIME_MESSAGE("String view support detected, remove this macro check, this line and the old check below"); +#endif +#endif + if (pPreview && pPreview->getTitleName() == +#ifndef LL_WINDOWS + static_cast( +#endif + "Gesture" +#ifndef LL_WINDOWS + ) +#endif + ) + { + wait_anim = pPreview->getChild("wait_anim_check")->getLabel(); + break; + } } } - + action = wait_anim; } result.append(action); return result; @@ -1716,13 +1682,14 @@ void LLPreviewGesture::onClickDelete() void LLPreviewGesture::onCommitActive() { - if (!LLGestureMgr::instance().isGestureActive(mItemUUID)) + auto& inst(LLGestureMgr::instance()); + if (!inst.isGestureActive(mItemUUID)) { - LLGestureMgr::instance().activateGesture(mItemUUID); + inst.activateGesture(mItemUUID); } else { - LLGestureMgr::instance().deactivateGesture(mItemUUID); + inst.deactivateGesture(mItemUUID); } // Make sure the (active) label in the inventory gets updated. @@ -1773,7 +1740,7 @@ void LLPreviewGesture::onDonePreview(LLMultiGesture* gesture) mPreviewBtn->setLabel(getString("preview_txt")); delete mPreviewGesture; - mPreviewGesture = NULL; + mPreviewGesture = nullptr; refresh(); } diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h index 7bb27063f..757d84308 100644 --- a/indra/newview/llpreviewgesture.h +++ b/indra/newview/llpreviewgesture.h @@ -113,7 +113,7 @@ protected: // "Sound", "Chat", or "Wait" LLScrollListItem* addStep(const enum EStepType step_type); - static std::string getLabel(std::vector labels); + static std::string getLabel(const std::vector& labels); static void updateLabel(LLScrollListItem* item); void onCommitSetDirty(); diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index f191b3368..1bfa37c84 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -613,7 +613,7 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data } else { - LL_WARNS() << "Inventory item for script " << info->mItemUUID + LL_WARNS() << "Inventory item for notecard " << info->mItemUUID << " is no longer in agent inventory." << LL_ENDL; } } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 75ead67ca..d0f011998 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -272,6 +272,7 @@ BOOL LLScriptEdCore::postBuild() mEditor = getChild("Script Editor"); mEditor->setHandleEditKeysDirectly(TRUE); + mEditor->setParseHighlights(TRUE); childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this); childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE)); @@ -480,9 +481,33 @@ bool LLScriptEdCore::writeToFile(const std::string& filename) std::string utf8text = mEditor->getText(); // Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889 - if (utf8text.size() == 0) + if (utf8text.empty()) { - utf8text = " "; + utf8text.push_back(' '); + } + else // We cut the fat ones down to size + { + std::stringstream strm(utf8text); + utf8text.clear(); + bool quote = false; + for (std::string line; std::getline(strm, line);) + { + //if ((std::count(line.begin(), line.end(), '"') % 2) == 0) quote = !quote; // This would work if escaping wasn't a thing + bool backslash = false; + for (const auto& ch : line) + { + switch (ch) + { + case '\\': backslash = !backslash; break; + case '"': if (!backslash) quote = !quote; // Fall through + default: backslash = false; break; + } + } + if (!quote) LLStringUtil::trimTail(line); + if (!utf8text.empty()) utf8text += '\n'; + utf8text += line; + } + if (utf8text.empty()) utf8text.push_back(' '); } fputs(utf8text.c_str(), fp); diff --git a/indra/newview/llsculptidsize.h b/indra/newview/llsculptidsize.h index 87ee417b8..678155e1d 100644 --- a/indra/newview/llsculptidsize.h +++ b/indra/newview/llsculptidsize.h @@ -127,7 +127,7 @@ public: private: container mSizeInfo; - typedef std::set std_LLUUID; + typedef uuid_set_t std_LLUUID; std_LLUUID mMarkAsUnloaded; }; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 994f3cd66..fe25b88fb 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -7418,8 +7418,7 @@ S32 LLObjectSelection::getSelectedObjectRenderCost() { S32 cost = 0; LLVOVolume::texture_cost_t textures; - typedef std::set uuid_list_t; - uuid_list_t computed_objects; + uuid_set_t computed_objects; typedef std::list > child_list_t; typedef const child_list_t const_child_list_t; diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp index e4523889a..03f67b41d 100644 --- a/indra/newview/llslurl.cpp +++ b/indra/newview/llslurl.cpp @@ -61,8 +61,8 @@ const std::string MAIN_GRID_SLURL_BASE = "http://maps.secondlife.com/secondlife/ const std::string SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app"; const char* SYSTEM_GRID_SLURL_BASE = "secondlife://%s/secondlife/"; -const char* DEFAULT_SLURL_BASE = "https://%s/region/"; -const char* DEFAULT_APP_SLURL_BASE = "x-grid-location-info://%s/app"; +const char* DEFAULT_SLURL_BASE = "x-grid-info://%s/region/"; +const char* DEFAULT_APP_SLURL_BASE = "x-grid-info://%s/app"; #define MAINGRID "secondlife" // resolve a simstring from a slurl diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index ced6d48ee..64125b1ec 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -564,12 +564,12 @@ void LLSpeakerMgr::updateSpeakerList() // Are we bound to the currently active voice channel? if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive())) { - std::set participants; + uuid_set_t participants; LLVoiceClient::getInstance()->getParticipantList(participants); // If we are, add all voice client participants to our list of known speakers std::vector speakers; speakers.reserve(participants.size()); - for (std::set::iterator participant_it = participants.begin(); participant_it != participants.end(); ++participant_it) + for (auto participant_it = participants.begin(); participant_it != participants.end(); ++participant_it) { speakers.emplace_back( *participant_it, diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a3ce7c158..462302873 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -640,21 +640,34 @@ bool idle_startup() // LL_DEBUGS("AppInit") << "Initializing messaging system..." << LL_ENDL; - std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg"); + auto app_settings_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, LLStringUtil::null); + std::string message_template_path = gDirUtilp->add(app_settings_path, "message_template.msg"); LLFILE* found_template = NULL; found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */ + if (!found_template) + { + app_settings_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, #if LL_WINDOWS - // On the windows dev builds, unpackaged, the message_template.msg + // On the windows dev builds, unpackaged, the message_template.msg // file will be located in: // indra/build-vc**/newview//app_settings. - if (!found_template) - { - message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg"); - found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ - } + "app_settings" + #elif LL_DARWIN + // On Mac dev builds, message_template.msg lives in: + // indra/build-*/newview//Second Life/Contents/Resources/app_settings + "../Resources/app_settings" + #else // LL_LINUX and other + // On the linux dev builds, the message_template.msg + // file will be located in: + // indra/build-linux**/newview/packaged/app_settings. + "../app_settings" #endif + , LLStringUtil::null); + message_template_path = gDirUtilp->add(app_settings_path, "message_template.msg"); + found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ + } if (found_template) { @@ -695,22 +708,8 @@ bool idle_startup() LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic)); } - #if LL_WINDOWS - // On the windows dev builds, unpackaged, the message.xml file will - // be located in indra/build-vc**/newview//app_settings. - std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml"); - - if (!LLFile::isfile(message_path.c_str())) - { - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "")); - } - else - { - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - } - #else - LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); - #endif + // Take into account dev checkout status on all platforms, by using app_settings_path ~Liru + LLMessageConfig::initClass("viewer", app_settings_path); } else @@ -1141,9 +1140,7 @@ bool idle_startup() // Load URL History File LLURLHistory::loadFile("url_history.xml"); - // Load media plugin cookies - LLViewerMedia::loadCookieFile(); - + //------------------------------------------------- // Handle startup progress screen //------------------------------------------------- diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index ed878a02f..077b6a8c7 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1064,9 +1064,9 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create else { // Look for a still valid entry in the LRU - for (std::set::iterator iter2 = mLRU.begin(); iter2 != mLRU.end();) + for (auto iter2 = mLRU.begin(); iter2 != mLRU.end();) { - std::set::iterator curiter2 = iter2++; + auto curiter2 = iter2++; LLUUID oldid = *curiter2; // Erase entry from LRU regardless mLRU.erase(curiter2); diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index 6aeea41a4..49b2eabc2 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -193,7 +193,7 @@ private: std::string mHeaderDataFileName; EntriesInfo mHeaderEntriesInfo; std::set mFreeList; // deleted entries - std::set mLRU; + uuid_set_t mLRU; typedef std::map id_map_t; id_map_t mHeaderIDMap; diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 5de76de4d..41b0616e9 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -163,10 +163,10 @@ private: map_t mRequestMap; // Set of requests that require network data - typedef std::set queue_t; + typedef uuid_set_t queue_t; queue_t mNetworkQueue; queue_t mHTTPTextureQueue; - typedef std::map > cancel_queue_t; + typedef std::map cancel_queue_t; cancel_queue_t mCancelQueue; LLTextureInfo mTextureInfo; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 3cdfb4396..0bd917067 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -271,7 +271,7 @@ void LLCategoryDropDescendentsObserver::done() S32 count = items.size(); if(count) { - std::set unique_ids; + uuid_set_t unique_ids; for(S32 i = 0; i < count; ++i) { unique_ids.insert(items.get(i)->getUUID()); @@ -472,7 +472,7 @@ void LLToolDragAndDrop::beginMultiDrag( // find categories (i.e. inventory folders) in the cargo. LLInventoryCategory* cat = NULL; S32 count = llmin(cargo_ids.size(), types.size()); - std::set cat_ids; + uuid_set_t cat_ids; for(S32 i = 0; i < count; ++i) { cat = gInventory.getCategory(cargo_ids[i]); diff --git a/indra/newview/lltracker.h b/indra/newview/lltracker.h index 5c62dbd1d..1dc56ceed 100644 --- a/indra/newview/lltracker.h +++ b/indra/newview/lltracker.h @@ -143,8 +143,8 @@ protected: std::string mTrackedLandmarkName; LLUUID mTrackedLandmarkAssetID; LLUUID mTrackedLandmarkItemID; - std::vector mLandmarkAssetIDList; - std::vector mLandmarkItemIDList; + uuid_vec_t mLandmarkAssetIDList; + uuid_vec_t mLandmarkItemIDList; BOOL mHasReachedLandmark; BOOL mHasLandmarkPosition; BOOL mLandmarkHasBeenVisited; diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index e1e110187..75b2d8766 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -66,18 +66,17 @@ public: F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT); protected: - // virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, - void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), + LLGetAssetCallback callback, void *user_data, BOOL duplicate, BOOL is_priority); void queueRequestUDP(const LLUUID& uuid, LLAssetType::EType type, - void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), + LLGetAssetCallback callback, void *user_data, BOOL duplicate, BOOL is_priority); @@ -87,7 +86,7 @@ protected: void assetRequestCoro(LLViewerAssetRequest *req, const LLUUID uuid, LLAssetType::EType atype, - void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), + LLGetAssetCallback callback, void *user_data); std::string getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 65887fdae..e9b544df4 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1714,7 +1714,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) LLInventoryModel::item_array_t* items; // Get the list of direct descendants in tha categoy passed as argument gInventory.getDirectDescendentsOf(id, categories, items); - std::vector list_uuids; + uuid_vec_t list_uuids; // Make a unique list with all the UUIDs of the direct descendants (items and categories are not treated differently) // Note: we need to do that shallow copy as purging things will invalidate the categories or items lists for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it) @@ -1726,7 +1726,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) list_uuids.push_back((*it)->getUUID()); } // Iterate through the list and only purge the UUIDs that are not on the clipboard - for (std::vector::const_iterator it = list_uuids.begin(); it != list_uuids.end(); ++it) + for (auto it = list_uuids.begin(); it != list_uuids.end(); ++it) { if (!LLInventoryClipboard::instance().isOnClipboard(*it)) { @@ -2259,7 +2259,7 @@ void LLViewerInventoryItem::setWearableType(LLWearableType::EType type) LL_WARNS() << "Calling LLViewerInventoryItem::setWearableType for item that does not have an unknown wearable type!?" << LL_ENDL; return; } - mFlags = (mFlags & ~LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK) | type; + mFlags = (mFlags & ~LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK) | type; } time_t LLViewerInventoryItem::getCreationDate() const diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index aa2099066..1dec47062 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -42,20 +42,21 @@ #include "llfocusmgr.h" #include "rlvhandler.h" +#include #include // ---------------------------------------------------------------------------- // Constants -#define X_I 1 -#define Y_I 2 -#define Z_I 0 -#define RX_I 4 -#define RY_I 5 -#define RZ_I 3 +constexpr auto X_I = 1; +constexpr auto Y_I = 2; +constexpr auto Z_I = 0; +constexpr auto RX_I = 4; +constexpr auto RY_I = 5; +constexpr auto RZ_I = 3; // minimum time after setting away state before coming back -const F32 MIN_AFK_TIME = 2.f; +constexpr F32 MIN_AFK_TIME = 2.f; F32 LLViewerJoystick::sLastDelta[] = {0,0,0,0,0,0,0}; F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0}; @@ -85,8 +86,7 @@ bool isOUYA(const std::string& desc) { return desc.find("OUYA") != std::string:: bool isXboxLike(const std::string& desc) { - return desc.find("Xbox") != std::string::npos - || isOUYA(desc); + return boost::algorithm::icontains(desc, "xbox") || isOUYA(desc); } bool isDS3Like(const std::string& desc) @@ -111,13 +111,26 @@ enum DS3Keys DS3_LOGO_KEY }; +void set_joystick_type(const S32& type) +{ + switch (type) + { + case 0: sType = SPACE_NAV; break; + case 1: case 2: sType = XBOX; break; + case 3: sType = DS3; break; + default: sType = UNKNOWN; break; + } +} + S32 get_joystick_type() { - if (sType == SPACE_NAV) return 0; - if (sType == XBOX) return isOUYA(LLViewerJoystick::getInstance()->getDescription()) ? 1 : 2; - if (sType == DS3) return 3; - - return -1; // sType == NONE || sType == UNKNOWN + switch (sType) + { + case SPACE_NAV: return 0; + case XBOX: return isOUYA(LLViewerJoystick::getInstance()->getDescription()) ? 1 : 2; + case DS3: return 3; + default: return -1; // sType == NONE || sType == UNKNOWN + } } // @@ -126,8 +139,8 @@ S32 get_joystick_type() // should be. It has to be equal to 3000 because the SpaceNavigator on Windows // refuses to respond to the DirectInput SetProperty call; it always returns // values in the [-3000, 3000] range. -#define MAX_SPACENAVIGATOR_INPUT 3000.0f -#define MAX_JOYSTICK_INPUT_VALUE MAX_SPACENAVIGATOR_INPUT +constexpr auto MAX_SPACENAVIGATOR_INPUT = 3000.0f; +constexpr auto MAX_JOYSTICK_INPUT_VALUE = MAX_SPACENAVIGATOR_INPUT; // ----------------------------------------------------------------------------- void LLViewerJoystick::updateEnabled(bool autoenable) @@ -1390,7 +1403,8 @@ void LLViewerJoystick::setSNDefaults(S32 type) const float platformScaleAvXZ = 2.f; const bool is_3d_cursor = true; #endif - + + set_joystick_type(type); // Breaks resetting to default but allows declaring a new identity and button config for the controller //gViewerWindow->alertXml("CacheWillClear"); const bool ouya = type == 1; const bool xbox = ouya || type == 2; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 7dc6e325c..a224b2e22 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -32,9 +32,6 @@ #include "llviewerprecompiledheaders.h" -#include "llviewermedia.h" - - #include "llviewermedia.h" #include "llagent.h" @@ -45,9 +42,10 @@ #include "lldir.h" #include "lldiriterator.h" #include "llevent.h" // LLSimpleListener +#include "aifilepicker.h" +#include "llfloaterdestinations.h" #include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows. #include "llfocusmgr.h" -#include "llhttpclient.h" #include "llkeyboard.h" #include "llmarketplacefunctions.h" #include "llmediaentry.h" @@ -59,7 +57,6 @@ #include "llpanelprofile.h" #include "llparcel.h" #include "llpluginclassmedia.h" -#include "llplugincookiestore.h" #include "llurldispatcher.h" #include "lluuid.h" #include "llvieweraudio.h" @@ -78,13 +75,10 @@ #include "llwebprofile.h" #include "llwindow.h" #include "llvieweraudio.h" +#include "llhttpclient.h" -#include "aifilepicker.h" #include "llstartup.h" -#include // for SkinFolder listener -#include - std::string getProfileURL(const std::string& agent_name); /*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable"; @@ -176,18 +170,15 @@ public: : mMediaImpl(media_impl), mInitialized(false) { - if(mMediaImpl->mMimeTypeProbe != NULL) + if(mMediaImpl->mMimeProbe) { LL_ERRS() << "impl already has an outstanding responder" << LL_ENDL; } - mMediaImpl->mMimeTypeProbe = this; + mMediaImpl->mMimeProbe = this; } - ~LLMimeDiscoveryResponder() - { - disconnectOwner(); - } + ~LLMimeDiscoveryResponder() { disconnectOwner(); } private: /* virtual */ void completedHeaders() @@ -266,14 +257,14 @@ private: { if(mMediaImpl) { - if(mMediaImpl->mMimeTypeProbe != this) + if(mMediaImpl->mMimeProbe != this) { - LL_ERRS() << "internal error: mMediaImpl->mMimeTypeProbe != this" << LL_ENDL; + LL_ERRS() << "internal error: mMediaImpl->mMimeProbe != this" << LL_ENDL; } - mMediaImpl->mMimeTypeProbe = NULL; + mMediaImpl->mMimeProbe = nullptr; } - mMediaImpl = NULL; + mMediaImpl = nullptr; } @@ -342,8 +333,6 @@ public: for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie) { // *TODO: What about bad status codes? Does this destroy previous cookies? - LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie->second, mHost); - if (cookie->second.substr(0, cookie->second.find('=')) == "_my_secondlife_session") { // Set cookie for snapshot publishing. @@ -362,10 +351,9 @@ public: }; -LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL; LLURL LLViewerMedia::sOpenIDURL; std::string LLViewerMedia::sOpenIDCookie; -LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL; +LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = nullptr; static LLViewerMedia::impl_list sViewerMediaImplList; static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap; static LLTimer sMediaCreateTimer; @@ -376,8 +364,6 @@ static LLUUID sOnlyAudibleTextureID = LLUUID::null; static F64 sLowestLoadableImplInterest = 0.0f; static bool sAnyMediaShowing = false; static boost::signals2::connection sTeleportFinishConnection; -static std::string sUpdatedCookies; -static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt"; ////////////////////////////////////////////////////////////////////////////////////////// static void add_media_impl(LLViewerMediaImpl* media) @@ -820,12 +806,6 @@ void LLViewerMedia::updateMedia(void *dummy_arg) createSpareBrowserMediaSource(); sAnyMediaShowing = false; - sUpdatedCookies = getCookieStore()->getChangedCookies(); - if(!sUpdatedCookies.empty()) - { - LL_DEBUGS() << "updated cookies will be sent to all loaded plugins: " << LL_ENDL; - LL_DEBUGS() << sUpdatedCookies << LL_ENDL; - } impl_list::iterator iter = sViewerMediaImplList.begin(); impl_list::iterator end = sViewerMediaImplList.end(); @@ -1176,63 +1156,6 @@ void LLViewerMedia::clearAllCookies() plugin->clear_cookies(); } } - - // Clear all cookies from the cookie store - getCookieStore()->setAllCookies(""); - - // FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly. - // It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded. - // Until such time as we can centralize cookie storage, the following hack should cover these cases: - - // HACK: Look for cookie files in all possible places and delete them. - // NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file) - - // Places that cookie files can be: - // /browser_profile/cookies - // /first_last/browser_profile/cookies (note that there may be any number of these!) - // /first_last/plugin_cookies.txt (note that there may be any number of these!) - - std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter(); - std::string target; - std::string filename; - - LL_DEBUGS() << "base dir = " << base_dir << LL_ENDL; - - // The non-logged-in version is easy - target = base_dir; - target += "browser_profile"; - target += gDirUtilp->getDirDelimiter(); - target += "cookies"; - LL_DEBUGS() << "target = " << target << LL_ENDL; - if(LLFile::isfile(target)) - { - LLFile::remove(target); - } - - // the hard part: iterate over all user directories and delete the cookie file from each one - LLDirIterator dir_iter(base_dir, "*_*"); - while (dir_iter.next(filename)) - { - target = gDirUtilp->add(base_dir, filename); - gDirUtilp->append(target, "browser_profile"); - gDirUtilp->append(target, "cookies"); - LL_DEBUGS() << "target = " << target << LL_ENDL; - if(LLFile::isfile(target)) - { - LLFile::remove(target); - } - - // Other accounts may have new-style cookie files too -- delete them as well - target = gDirUtilp->add(base_dir, filename); - gDirUtilp->append(target, PLUGIN_COOKIE_FILE_NAME); - LL_DEBUGS() << "target = " << target << LL_ENDL; - if(LLFile::isfile(target)) - { - LLFile::remove(target); - } - } - - // If we have an OpenID cookie, re-add it to the cookie store. setOpenIDCookie(); } @@ -1263,7 +1186,7 @@ void LLViewerMedia::setCookiesEnabled(bool enabled) LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); if(plugin) { - plugin->enable_cookies(enabled); + plugin->cookies_enabled(enabled); } } } @@ -1281,7 +1204,7 @@ void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int por LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); if(plugin) { - plugin->proxy_setup(enable, host, port); + //pimpl->mMediaSource->proxy_setup(enable, host, port); } } } @@ -1289,128 +1212,7 @@ void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int por ///////////////////////////////////////////////////////////////////////////////////////// // static ///////////////////////////////////////////////////////////////////////////////////////// -// static -LLPluginCookieStore *LLViewerMedia::getCookieStore() -{ - if(sCookieStore == NULL) - { - sCookieStore = new LLPluginCookieStore; - } - - return sCookieStore; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::loadCookieFile() -{ - // build filename for each user - std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME); - - if (resolved_filename.empty()) - { - LL_INFOS() << "can't get path to plugin cookie file - probably not logged in yet." << LL_ENDL; - return; - } - - // open the file for reading - llifstream file(resolved_filename); - if (!file.is_open()) - { - LL_WARNS() << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << LL_ENDL; - return; - } - - getCookieStore()->readAllCookies(file, true); - - file.close(); - - // send the clear_cookies message to all loaded plugins - impl_list::iterator iter = sViewerMediaImplList.begin(); - impl_list::iterator end = sViewerMediaImplList.end(); - for (; iter != end; iter++) - { - LLViewerMediaImpl* pimpl = *iter; - LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); - if(plugin) - { - plugin->clear_cookies(); - } - } - - // If we have an OpenID cookie, re-add it to the cookie store. - setOpenIDCookie(); -} - - -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::saveCookieFile() -{ - // build filename for each user - std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME); - - if (resolved_filename.empty()) - { - LL_INFOS() << "can't get path to plugin cookie file - probably not logged in yet." << LL_ENDL; - return; - } - - // open a file for writing - llofstream file (resolved_filename); - if (!file.is_open()) - { - LL_WARNS() << "can't open plugin cookie file \"" << PLUGIN_COOKIE_FILE_NAME << "\" for writing" << LL_ENDL; - return; - } - - getCookieStore()->writePersistentCookies(file); - - file.close(); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path, bool secure) -{ - std::stringstream cookie; - - cookie << name << "=" << LLPluginCookieStore::quoteString(value); - - if(expires.notNull()) - { - cookie << "; expires=" << expires.asRFC1123(); - } - - cookie << "; domain=" << domain; - - cookie << "; path=" << path; - - if(secure) - { - cookie << "; secure"; - } - - getCookieStore()->setCookies(cookie.str()); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path, bool secure) -{ - // A session cookie just has a NULL date. - addCookie(name, value, domain, LLDate(), path, secure); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::removeCookie(const std::string &name, const std::string &domain, const std::string &path ) -{ - // To remove a cookie, add one with the same name, domain, and path that expires in the past. - - addCookie(name, "", domain, LLDate(LLDate::now().secondsSinceEpoch() - 1.0), path); -} - +//// static AIHTTPHeaders LLViewerMedia::getHeaders() { @@ -1427,64 +1229,120 @@ AIHTTPHeaders LLViewerMedia::getHeaders() ///////////////////////////////////////////////////////////////////////////////////////// // static +bool LLViewerMedia::parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure) +{ + std::size_t name_pos = raw_cookie.find_first_of('='); + if (name_pos != std::string::npos) + { + name = raw_cookie.substr(0, name_pos); + std::size_t value_pos = raw_cookie.find_first_of(';', name_pos); + if (value_pos != std::string::npos) + { + value = raw_cookie.substr(name_pos + 1, value_pos - name_pos - 1); + path = "/"; // assume root path for now + + httponly = true; // hard coded for now + secure = true; + + return true; + } + } + + return false; +} + void LLViewerMedia::setOpenIDCookie() { if(!sOpenIDCookie.empty()) { - // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port] - // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that. - // We therefore do it here. - std::string authority = sOpenIDURL.mAuthority; - std::string::size_type host_start = authority.find('@'); - if(host_start == std::string::npos) - { - // no username/password - host_start = 0; - } - else - { - // Hostname starts after the @. - // (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.) - ++host_start; - } - std::string::size_type host_end = authority.rfind(':'); - if((host_end == std::string::npos) || (host_end < host_start)) - { - // no port - host_end = authority.size(); - } - - getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start)); - if (gSavedSettings.getString("WebProfileURL").empty()) return; - // Do a web profile get so we can store the cookie - AIHTTPHeaders headers; - headers.addHeader("Accept", "*/*"); - headers.addHeader("Cookie", sOpenIDCookie); - headers.addHeader("User-Agent", getCurrentUserAgent()); + std::string profileUrl = getProfileURL(""); - std::string profile_url = getProfileURL(""); - LLURL raw_profile_url( profile_url.c_str() ); - - LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << LL_ENDL; - LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; - LLHTTPClient::get(profile_url, - new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), - headers); + getOpenIDCookieCoro(profileUrl); } } +/*static*/ +void LLViewerMedia::getOpenIDCookieCoro(std::string url) +{ + // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port] + // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that. + // We therefore do it here. + std::string authority = sOpenIDURL.mAuthority; + std::string::size_type hostStart = authority.find('@'); + if(hostStart == std::string::npos) + { // no username/password + hostStart = 0; + } + else + { // Hostname starts after the @. + // (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.) + ++hostStart; + } + std::string::size_type hostEnd = authority.rfind(':'); + if((hostEnd == std::string::npos) || (hostEnd < hostStart)) + { // no port + hostEnd = authority.size(); + } + + if (url.length()) + { + LLMediaCtrl* media_instance = LLFloaterDestinations::getInstance()->getChild("destination_guide_contents"); + if (media_instance) + { + std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart); + std::string cookie_name = ""; + std::string cookie_value = ""; + std::string cookie_path = ""; + bool httponly = true; + bool secure = true; + if (parseRawCookie(sOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) && + media_instance->getMediaPlugin()) + { + // MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the + // url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked. + // For now, we use the URL for the OpenID POST request since it will have the same authority + // as the domain field. + // (Feels like there must be a less dirty way to construct a URL from component LLURL parts) + // MAINT-6392 - Rider: Do not change, however, the original URI requested, since it is used further + // down. + std::string cefUrl(std::string(sOpenIDURL.mURI) + "://" + std::string(sOpenIDURL.mAuthority)); + + media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host, cookie_path, httponly, secure); + } + } + } + + // Note: Rider: MAINT-6392 - Some viewer code requires access to the my.sl.com openid cookie for such + // actions as posting snapshots to the feed. This is handled through HTTPCore rather than CEF and so + // we must learn to SHARE the cookies. + + // Do a web profile get so we can store the cookie + AIHTTPHeaders headers; + headers.addHeader("Accept", "*/*"); + headers.addHeader("Cookie", sOpenIDCookie); + headers.addHeader("User-Agent", getCurrentUserAgent()); + + LLURL raw_profile_url(url.data()); + + LL_DEBUGS("MediaAuth") << "Requesting " << url << LL_ENDL; + LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; + LLHTTPClient::get(url, + new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), + headers); +} + ///////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token) +void LLViewerMedia::openIDSetup(const std::string &openidUrl, const std::string &openidToken) { - LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL; + LL_DEBUGS("MediaAuth") << "url = \"" << openidUrl << "\", token = \"" << openidToken << "\"" << LL_ENDL; // post the token to the url // the responder will need to extract the cookie(s). // Save the OpenID URL for later -- we may need the host when adding the cookie. - sOpenIDURL.init(openid_url.c_str()); + sOpenIDURL.init(openidUrl.c_str()); // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies. sOpenIDCookie.clear(); @@ -1496,13 +1354,13 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string headers.addHeader("Content-Type", "application/x-www-form-urlencoded"); // postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here. - size_t size = openid_token.size(); + size_t size = openidToken.size(); U8* data = new U8[size]; - memcpy(data, openid_token.data(), size); + memcpy(data, openidToken.data(), size); LLHTTPClient::postRaw( - openid_url, - data, + openidUrl, + data, size, new LLViewerMediaOpenIDResponder(), headers); @@ -1570,7 +1428,7 @@ void LLViewerMedia::createSpareBrowserMediaSource() // The null owner will keep the browser plugin from fully initializing // (specifically, it keeps LLPluginClassMedia from negotiating a size change, // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color) - sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0); + sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", nullptr, 0, 0, 1.0); if (!sSpareBrowserMediaSource) failedLoading = true; } } @@ -1580,7 +1438,7 @@ void LLViewerMedia::createSpareBrowserMediaSource() LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() { LLPluginClassMedia* result = sSpareBrowserMediaSource; - sSpareBrowserMediaSource = NULL; + sSpareBrowserMediaSource = nullptr; return result; }; @@ -1626,7 +1484,7 @@ std::string LLViewerMedia::getParcelAudioURL() // static void LLViewerMedia::initClass() { - gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL); + gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, nullptr); sTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished)); } @@ -1635,8 +1493,13 @@ void LLViewerMedia::initClass() // static void LLViewerMedia::cleanupClass() { - gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); + gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, nullptr); sTeleportFinishConnection.disconnect(); + if (sSpareBrowserMediaSource != nullptr) + { + delete sSpareBrowserMediaSource; + sSpareBrowserMediaSource = nullptr; + } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1645,6 +1508,8 @@ void LLViewerMedia::onTeleportFinished() { // On teleport, clear this setting (i.e. set it to true) gSavedSettings.setBOOL("MediaTentativeAutoPlay", true); + + LLViewerMediaImpl::sMimeTypesFailed.clear(); } @@ -1656,6 +1521,7 @@ void LLViewerMedia::setOnlyAudibleMediaTextureID(const LLUUID& texture_id) sForceUpdate = true; } +std::vector LLViewerMediaImpl::sMimeTypesFailed; ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMediaImpl ////////////////////////////////////////////////////////////////////////////////////////// @@ -1665,6 +1531,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, U8 media_auto_scale, U8 media_loop) : + mZoomFactor(1.0), mMovieImageHasMips(false), mMediaWidth(media_width), mMediaHeight(media_height), @@ -1685,6 +1552,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mNavigateServerRequest(false), mMediaSourceFailed(false), mRequestedVolume(1.0f), + mPreviousVolume(1.0f), mIsMuted(false), mNeedsMuteCheck(false), mPreviousMediaState(MEDIA_NONE), @@ -1693,16 +1561,16 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mIsParcelMedia(false), mProximity(-1), mProximityDistance(0.0f), - mMimeTypeProbe(NULL), mMediaAutoPlay(false), mInNearbyMediaList(false), mClearCache(false), mBackgroundColor(LLColor4::white), mNavigateSuspended(false), mNavigateSuspendedDeferred(false), - mIsUpdated(false), mTrustedBrowser(false), - mZoomFactor(1.0) + mCleanBrowser(false), + mIsUpdated(false), + mMimeProbe(nullptr) { // Set up the mute list observer if it hasn't been set up already. @@ -1770,7 +1638,7 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) mMimeType = mime_type; } - return (mPluginBase != NULL); + return (mPluginBase != nullptr); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1825,15 +1693,16 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) ////////////////////////////////////////////////////////////////////////////////////////// /*static*/ -LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target) +LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target, bool clean_browser) { std::string plugin_basename = LLMIMETypes::implType(media_type); - LLPluginClassMedia* media_source = NULL; + LLPluginClassMedia* media_source = nullptr; // HACK: we always try to keep a spare running webkit plugin around to improve launch times. // If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it. + // Do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others) if ((plugin_basename == "media_plugin_cef") && - !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")) + !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !clean_browser) { media_source = LLViewerMedia::getSpareBrowserMediaSource(); if(media_source) @@ -1841,6 +1710,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ media_source->setOwner(owner); media_source->setTarget(target); media_source->setSize(default_width, default_height); + media_source->setZoomFactor(zoom_factor); return media_source; } @@ -1860,7 +1730,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ std::string user_data_path_cookies = gDirUtilp->getOSUserAppDir(); user_data_path_cookies += gDirUtilp->getDirDelimiter(); - std::string user_data_path_logs = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef_log.txt"); // Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.) // If the linden username returned is blank, that can only mean we are @@ -1870,7 +1740,6 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ std::string linden_user_dir = gDirUtilp->getLindenUserDir(); if ( ! linden_user_dir.empty() ) { - // gDirUtilp->getLindenUserDir() is whole path, not just Linden name user_data_path_cookies = linden_user_dir; user_data_path_cookies += gDirUtilp->getDirDelimiter(); }; @@ -1888,24 +1757,28 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ else { media_source = new LLPluginClassMedia(owner); + media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getS32("BrowserProxyType"), + gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"), + gSavedSettings.getString("BrowserProxyUsername"), gSavedSettings.getString("BrowserProxyPassword")); media_source->setSize(default_width, default_height); - media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies, user_data_path_logs); + media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies, user_data_path_cef_log); media_source->setLanguageCode(LLUI::getLanguage()); + media_source->setZoomFactor(zoom_factor); // collect 'cookies enabled' setting from prefs and send to embedded browser bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" ); - media_source->enable_cookies( cookies_enabled ); + media_source->cookies_enabled( cookies_enabled || clean_browser); // collect 'plugins enabled' setting from prefs and send to embedded browser bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" ); - media_source->setPluginsEnabled( plugins_enabled ); + media_source->setPluginsEnabled( plugins_enabled || clean_browser); // collect 'javascript enabled' setting from prefs and send to embedded browser bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); - media_source->setJavascriptEnabled( javascript_enabled ); + media_source->setJavascriptEnabled( javascript_enabled || clean_browser); bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); - media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled ); + media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || clean_browser); // need to set agent string here before instance created media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent()); @@ -1926,12 +1799,18 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL; - /* There is a reason why ^^ is ONCE - LLSD args; - args["MIME_TYPE"] = media_type; - LLNotificationsUtil::add("NoPlugin", args); - */ - return NULL; + + if(gAgent.isInitialized()) + { + if (std::find(sMimeTypesFailed.begin(), sMimeTypesFailed.end(), media_type) == sMimeTypesFailed.end()) + { + LLSD args; + args["MIME_TYPE"] = media_type; + LLNotificationsUtil::add("NoPlugin", args); + sMimeTypesFailed.push_back(media_type); + } + } + return nullptr; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1943,6 +1822,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the previous media source's last set size before destroying it. mMediaWidth = mMediaSource->getSetWidth(); mMediaHeight = mMediaSource->getSetHeight(); + mZoomFactor = mMediaSource->getZoomFactor(); } // Always delete the old media impl first. @@ -1965,7 +1845,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the MIME type that really caused the plugin to load mCurrentMimeType = mMimeType; - LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget); + LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mZoomFactor, mTarget, mCleanBrowser); if (media_source) { @@ -1988,24 +1868,14 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "ca-bundle.crt" ); media_source->addCertificateFilePath( ca_path ); - media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); + media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getS32("BrowserProxyType"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"), + gSavedSettings.getString("BrowserProxyUsername"), gSavedSettings.getString("BrowserProxyPassword")); if(mClearCache) { mClearCache = false; media_source->clear_cache(); } - - // TODO: Only send cookies to plugins that need them - // Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message. - // Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message, - // which could cause odd race conditions. - std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies(); - LL_DEBUGS() << "setting cookies: " << all_cookies << LL_ENDL; - if(!all_cookies.empty()) - { - media_source->set_cookies(all_cookies); - } mPluginBase = media_source; mPluginBase->setDeleteOK(false) ; @@ -2108,7 +1978,7 @@ void LLViewerMediaImpl::play() LLPluginClassMedia* mMediaSource = getMediaPlugin(); // If the media source isn't there, try to initialize it and load an URL. - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { if(!initializeMedia(mMimeType)) { @@ -2221,6 +2091,20 @@ void LLViewerMediaImpl::setVolume(F32 volume) updateVolume(); } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::setMute(bool mute) +{ + if (mute) + { + mPreviousVolume = mRequestedVolume; + setVolume(0.0); + } + else + { + setVolume(mPreviousVolume); + } +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateVolume() { @@ -2630,7 +2514,7 @@ void LLViewerMediaImpl::unload() } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request) +void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request, bool clean_browser) { if (url.empty()) { @@ -2649,6 +2533,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // Always set the current URL and MIME type. mMediaURL = url; mMimeType = mime_type; + mCleanBrowser = clean_browser; // Clear the current media URL, since it will no longer be correct. mCurrentMediaURL.clear(); @@ -2705,7 +2590,7 @@ void LLViewerMediaImpl::navigateInternal() return; } - if(mMimeTypeProbe != NULL) + if(mMimeProbe != nullptr) { LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL; return; @@ -2754,11 +2639,14 @@ void LLViewerMediaImpl::navigateInternal() } else if("data" == scheme || "file" == scheme || "about" == scheme) { - // FIXME: figure out how to really discover the type for these schemes - // We use "data" internally for a text/html url for loading the login screen - if(initializeMedia("text/html")) + if ("blank" != uri.hostName()) { - loadURI(); + // FIXME: figure out how to really discover the type for these schemes + // We use "data" internally for a text/html url for loading the login screen + if(initializeMedia("text/html")) + { + loadURI(); + } } } else @@ -2798,36 +2686,37 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) if (mMediaSource) { - // FIXME: THIS IS SO WRONG. - // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... - if (MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END) + switch (mask) { - result = true; - } + case MASK_CONTROL: + { + result = true; // Avoid redundant code, set false for default. + switch(key) + { + // FIXME: THIS IS SO WRONG. + // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... + case KEY_LEFT: case KEY_RIGHT: case KEY_HOME: case KEY_END: break; - if( MASK_CONTROL & mask ) - { - if('C' == key) + case 'C': mMediaSource->copy(); break; + case 'V': mMediaSource->paste(); break; + case 'X': mMediaSource->cut(); break; + + default: result = false; break; + } + break; + } + case MASK_SHIFT|MASK_CONTROL: + if (key == 'I') { - mMediaSource->copy(); - result = true; - } - else if('V' == key) - { - mMediaSource->paste(); - result = true; - } - else if('X' == key) - { - mMediaSource->cut(); + mMediaSource->showWebInspector(true); result = true; } + break; } // Singu Note: At the very least, let's allow the login menu to function extern LLMenuBarGL* gLoginMenuBarView; - if (gLoginMenuBarView && gLoginMenuBarView->getVisible() && gLoginMenuBarView->handleAcceleratorKey(key, mask)) - return true; + result = result || (gLoginMenuBarView && gLoginMenuBarView->getVisible() && gLoginMenuBarView->handleAcceleratorKey(key, mask)); if(!result) { @@ -2835,7 +2724,7 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN, key, mask, native_key_data); } } - + return result; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2918,7 +2807,7 @@ void LLViewerMediaImpl::update() { LL_RECORD_BLOCK_TIME(FTM_MEDIA_DO_UPDATE); LLPluginClassMedia* mMediaSource = getMediaPlugin(); - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { if(mPriority == PRIORITY_UNLOADED) { @@ -2928,7 +2817,7 @@ void LLViewerMediaImpl::update() { // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. } - else if(mMimeTypeProbe != NULL) + else if(mMimeProbe != nullptr) { // this media source is doing a MIME type probe -- don't try loading it again. } @@ -2953,17 +2842,10 @@ void LLViewerMediaImpl::update() // TODO: this is updated every frame - is this bad? updateJavascriptObject(); - - // If we didn't just create the impl, it may need to get cookie updates. - if(!sUpdatedCookies.empty()) - { - // TODO: Only send cookies to plugins that need them - mMediaSource->set_cookies(sUpdatedCookies); - } } - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { return; } @@ -2976,7 +2858,7 @@ void LLViewerMediaImpl::update() setNavigateSuspended(false); mMediaSource = getMediaPlugin(); - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { return; } @@ -3018,12 +2900,14 @@ void LLViewerMediaImpl::update() if(width > 0 && height > 0) { - U8* data = NULL; + U8* data = nullptr; { LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); data = mMediaSource->getBitsData(); } + if(data != NULL) + { // Offset the pixels pointer to match x_pos and y_pos data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); data += ( y_pos * mMediaSource->getTextureDepth() ); @@ -3039,6 +2923,7 @@ void LLViewerMediaImpl::update() width, height, TRUE); // + } } } @@ -3061,7 +2946,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() if(mTextureId.isNull()) { // The code that created this instance will read from the plugin's bits. - return NULL; + return nullptr; } LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId ); @@ -3299,7 +3184,7 @@ bool LLViewerMediaImpl::isPlayable() const static void handle_pick_file_request_continued(LLPluginClassMedia* plugin, AIFilePicker* filepicker) { - plugin->sendPickFileResponse(filepicker->hasFilename() ? filepicker->getFilename() : LLStringUtil::null); + plugin->sendPickFileResponse(filepicker->hasFilename() ? filepicker->getFilenames() : std::vector()); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -3313,7 +3198,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL; std::string url = plugin->getClickURL(); std::string nav_type = plugin->getClickNavType(); - LLURLDispatcher::dispatch(url, nav_type, NULL, mTrustedBrowser); + LLURLDispatcher::dispatch(url, nav_type, nullptr, mTrustedBrowser); } break; case MEDIA_EVENT_CLICK_LINK_HREF: @@ -3373,6 +3258,13 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; + case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD: + { + //llinfos << "Media event - file download requested - filename is " << self->getFileDownloadFilename() << llendl; + LLNotificationsUtil::add("MediaFileDownloadUnsupported"); + } + break; + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN: { LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL; @@ -3471,7 +3363,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; - case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST: { LLNotification::Params auth_request_params("AuthRequest"); @@ -3527,6 +3418,32 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; + case MEDIA_EVENT_DEBUG_MESSAGE: + { + std::string level = plugin->getDebugMessageLevel(); + if (level == "debug") + { + LL_DEBUGS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else if (level == "info") + { + LL_INFOS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else if (level == "warn") + { + LL_WARNS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else if (level == "error") + { + LL_ERRS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else + { + LL_INFOS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + }; + break; + default: break; } @@ -3540,9 +3457,46 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla //////////////////////////////////////////////////////////////////////////////// // virtual -void LLViewerMediaImpl::handleCookieSet(LLPluginClassMedia* self, const std::string &cookie) +void +LLViewerMediaImpl::undo() { - LLViewerMedia::getCookieStore()->setCookies(cookie); + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->undo(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canUndo() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canUndo(); + else + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::redo() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->redo(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canRedo() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canRedo(); + else + return FALSE; } //////////////////////////////////////////////////////////////////////////////// @@ -3611,6 +3565,50 @@ LLViewerMediaImpl::canPaste() const return FALSE; } +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::doDelete() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->doDelete(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canDoDelete() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canDoDelete(); + else + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::selectAll() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->selectAll(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canSelectAll() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canSelectAll(); + else + return FALSE; +} + void LLViewerMediaImpl::setUpdated(BOOL updated) { mIsUpdated = updated ; @@ -3628,7 +3626,7 @@ void LLViewerMediaImpl::calculateInterest() LL_RECORD_BLOCK_TIME(FTM_MEDIA_CALCULATE_INTEREST); LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId ); - if(texture != NULL) + if(texture != nullptr) { mInterest = texture->getMaxVirtualSize(); } @@ -3863,16 +3861,16 @@ void LLViewerMediaImpl::setNavigateSuspended(bool suspend) void LLViewerMediaImpl::cancelMimeTypeProbe() { - if(mMimeTypeProbe != NULL) + if(mMimeProbe) { // There doesn't seem to be a way to actually cancel an outstanding request. // Simulate it by telling the LLMimeDiscoveryResponder not to write back any results. - mMimeTypeProbe->cancelRequest(); + mMimeProbe->cancelRequest(); - // The above should already have set mMimeTypeProbe to NULL. - if(mMimeTypeProbe != NULL) + // The above should already have set mMimeProbe to nullptr. + if (mMimeProbe) { - LL_ERRS() << "internal error: mMimeTypeProbe is not NULL after cancelling request." << LL_ENDL; + LL_ERRS() << "internal error: mMimeProbe is not nullptr after cancelling request." << LL_ENDL; } } } @@ -3905,7 +3903,7 @@ const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const LLVOVolume *LLViewerMediaImpl::getSomeObject() { - LLVOVolume *result = NULL; + LLVOVolume *result = nullptr; std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ; if(iter != mObjectList.end()) @@ -4015,13 +4013,13 @@ bool LLViewerMediaImpl::isObjectAttachedToAnotherAvatar(LLVOVolume *obj) bool result = false; LLXform *xform = obj; // Walk up parent chain - while (NULL != xform) + while (nullptr != xform) { LLViewerObject *object = dynamic_cast (xform); - if (NULL != object) + if (nullptr != object) { LLVOAvatar *avatar = object->asAvatar(); - if ((NULL != avatar) && (avatar != gAgentAvatarp)) + if ((nullptr != avatar) && (avatar != gAgentAvatarp)) { result = true; break; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 0a3485ccf..14dc08fae 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -2,31 +2,25 @@ * @file llviewermedia.h * @brief Client interface to the media engine * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -46,7 +40,6 @@ #include "llnotificationptr.h" #include "llurl.h" - #include "llviewerpluginmanager.h" class LLViewerMediaImpl; @@ -55,7 +48,6 @@ class LLViewerMediaTexture; class LLMediaEntry; class LLVOVolume; class LLMimeDiscoveryResponder; -class LLPluginCookieStore; typedef LLPointer viewer_media_t; /////////////////////////////////////////////////////////////////////////////// @@ -111,10 +103,14 @@ public: // Is any media currently "showing"? Includes Parcel Media. Does not include media in the UI. static bool isAnyMediaShowing(); + // Shows if any media is playing, counts visible non time based media as playing. Does not include media in the UI. + static bool isAnyMediaPlaying(); // Set all media enabled or disabled, depending on val. Does not include media in the UI. static void setAllMediaEnabled(bool val); + // Set all media paused(stopped for non time based) or playing, depending on val. Does not include media in the UI. + static void setAllMediaPaused(bool val); - static void updateMedia(void* dummy_arg = NULL); + static void updateMedia(void* dummy_arg = nullptr); static void initClass(); static void cleanupClass(); @@ -151,13 +147,6 @@ public: // Set the proxy config for all loaded plugins static void setProxyConfig(bool enable, const std::string &host, int port); - static LLPluginCookieStore *getCookieStore(); - static void loadCookieFile(); - static void saveCookieFile(); - static void addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path = std::string("/"), bool secure = false ); - static void addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path = std::string("/"), bool secure = false ); - static void removeCookie(const std::string &name, const std::string &domain, const std::string &path = std::string("/") ); - static void openIDSetup(const std::string &openid_url, const std::string &openid_token); static void openIDCookieResponse(const std::string &cookie); @@ -172,10 +161,12 @@ public: static class AIHTTPHeaders getHeaders(); private: + static bool parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure); static void setOpenIDCookie(); static void onTeleportFinished(); - - static LLPluginCookieStore *sCookieStore; + + static void getOpenIDCookieCoro(std::string url); + static LLURL sOpenIDURL; static std::string sOpenIDCookie; static LLPluginClassMedia* sSpareBrowserMediaSource; @@ -201,7 +192,7 @@ public: ~LLViewerMediaImpl(); // Override inherited version from LLViewerMediaEventEmitter - virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event); + void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event) override; void createMediaSource(); void destroyMediaSource(); @@ -223,6 +214,7 @@ public: void skipBack(F32 step_scale); void skipForward(F32 step_scale); void setVolume(F32 volume); + void setMute(bool mute); void updateVolume(); F32 getVolume(); void focus(bool focus); @@ -244,7 +236,7 @@ public: void navigateReload(); void navigateHome(); void unload(); - void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false); + void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false, bool clean_browser = false); void navigateInternal(); void navigateStop(); bool handleKeyHere(KEY key, MASK mask); @@ -301,7 +293,7 @@ public: void setTarget(const std::string& target) { mTarget = target; } // utility function to create a ready-to-use media instance from a desired media type. - static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null); + static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target = LLStringUtil::null, bool clean_browser = false); // Internally set our desired browser user agent string, including // the Second Life version and skin name. Used because we can @@ -313,40 +305,51 @@ public: static bool handleSkinCurrentChanged(const LLSD& newvalue); // need these to handle mouseup... - /*virtual*/ void onMouseCaptureLost(); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ void onMouseCaptureLost() override; + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; // Grr... the only thing I want as an LLMouseHandler are the onMouseCaptureLost and handleMouseUp calls. // Sadly, these are all pure virtual, so I have to supply implementations here: - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; }; - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) { return FALSE; }; - /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; }; - /*virtual*/ const std::string& getName() const; - /*virtual*/ BOOL isView() const { return FALSE; }; + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override { return FALSE; }; + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) override { return FALSE; }; + /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) override {return FALSE; }; + /*virtual*/ const std::string& getName() const override; + /*virtual*/ BOOL isView() const override { return FALSE; }; - /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}; - /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}; - /*virtual*/ BOOL hasMouseCapture() { return gFocusMgr.getMouseCapture() == this; }; + /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const override {}; + /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const override {}; + /*virtual*/ BOOL hasMouseCapture() override { return gFocusMgr.getMouseCapture() == this; }; // Inherited from LLPluginClassMediaOwner - /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent); - /*virtual*/ void handleCookieSet(LLPluginClassMedia* self, const std::string &cookie); + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent) override; // LLEditMenuHandler overrides - /*virtual*/ void cut(); - /*virtual*/ BOOL canCut() const; + /*virtual*/ void undo() override; + /*virtual*/ BOOL canUndo() const override; - /*virtual*/ void copy(); - /*virtual*/ BOOL canCopy() const; + /*virtual*/ void redo() override; + /*virtual*/ BOOL canRedo() const override; - /*virtual*/ void paste(); - /*virtual*/ BOOL canPaste() const; + /*virtual*/ void cut() override; + /*virtual*/ BOOL canCut() const override; + + /*virtual*/ void copy() override; + /*virtual*/ BOOL canCopy() const override; + + /*virtual*/ void paste() override; + /*virtual*/ BOOL canPaste() const override; + + /*virtual*/ void doDelete() override; + /*virtual*/ BOOL canDoDelete() const override; + + /*virtual*/ void selectAll() override; + /*virtual*/ BOOL canSelectAll() const override; void addObject(LLVOVolume* obj) ; void removeObject(LLVOVolume* obj) ; @@ -466,6 +469,7 @@ private: bool mNavigateServerRequest; bool mMediaSourceFailed; F32 mRequestedVolume; + F32 mPreviousVolume; bool mIsMuted; bool mNeedsMuteCheck; int mPreviousMediaState; @@ -475,7 +479,6 @@ private: S32 mProximity; F64 mProximityDistance; F64 mProximityCamera; - LLMimeDiscoveryResponder *mMimeTypeProbe; bool mMediaAutoPlay; std::string mMediaEntryURL; bool mInNearbyMediaList; // used by LLPanelNearbyMedia::refreshList() for performance reasons @@ -486,11 +489,15 @@ private: bool mTrustedBrowser; std::string mTarget; LLNotificationPtr mNotification; + bool mCleanBrowser; // force the creation of a clean browsing target with full options enabled + static std::vector sMimeTypesFailed; private: BOOL mIsUpdated ; std::list< LLVOVolume* > mObjectList ; + LLMimeDiscoveryResponder* mMimeProbe; + private: LLViewerMediaTexture *updatePlaceholderImage(); }; diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp index de90c8571..5e72ab348 100644 --- a/indra/newview/llviewermedia_streamingaudio.cpp +++ b/indra/newview/llviewermedia_streamingaudio.cpp @@ -162,7 +162,7 @@ LLPluginClassMedia* LLStreamingAudio_MediaPlugins::initializeMedia(const std::st { LLPluginClassMediaOwner* owner = NULL; S32 default_size = 1; // audio-only - be minimal, doesn't matter - LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size); + LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size, 1.0); if (media_source) { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4b552ca10..81eacc728 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -9342,6 +9342,31 @@ class ListToggleMute : public view_listener_t } }; +LLMediaCtrl* get_focused_media_ctrl() +{ + auto media_ctrl = dynamic_cast(gFocusMgr.getKeyboardFocus()); + llassert(media_ctrl); // This listener only applies to media_ctrls + return media_ctrl; +} + +class MediaCtrlWebInspector : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + get_focused_media_ctrl()->onOpenWebInspector(); + return true; + } +}; + +class MediaCtrlViewSource : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + get_focused_media_ctrl()->onShowSource(); + return true; + } +}; + struct MarketplaceViewSortAction : view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -9693,6 +9718,10 @@ void initialize_menus() LLTextEditor::setIsFriendCallback(LLAvatarActions::isFriend); LLTextEditor::addMenuListeners(); + // Media Ctrl menus + addMenu(new MediaCtrlWebInspector(), "Open.WebInspector"); + addMenu(new MediaCtrlViewSource(), "Open.ViewSource"); + addMenu(new MarketplaceViewSortAction, "Marketplace.ViewSort.Action"); addMenu(new MarketplaceViewSortCheckItem, "Marketplace.ViewSort.CheckItem"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 65da02e4c..919fdf45e 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -719,11 +719,11 @@ bool join_group_response(const LLSD& notification, const LLSD& response) return false; } -static void highlight_inventory_objects_in_panel(const std::vector& items, LLInventoryPanel *inventory_panel) +static void highlight_inventory_objects_in_panel(const uuid_vec_t& items, LLInventoryPanel *inventory_panel) { if (NULL == inventory_panel) return; - for (std::vector::const_iterator item_iter = items.begin(); + for (auto item_iter = items.begin(); item_iter != items.end(); ++item_iter) { @@ -881,7 +881,7 @@ private: } LLHandle mActivePanel; - typedef std::set selected_items_t; + typedef uuid_set_t selected_items_t; selected_items_t mSelectedItems; /** @@ -951,18 +951,16 @@ void LLViewerInventoryMoveObserver::changed(U32 mask) if((mask & (LLInventoryObserver::STRUCTURE)) != 0) { - const std::set& changed_items = gInventory.getChangedIDs(); + const uuid_set_t& changed_items = gInventory.getChangedIDs(); - std::set::const_iterator id_it = changed_items.begin(); - std::set::const_iterator id_end = changed_items.end(); + auto id_it = changed_items.begin(); + auto id_end = changed_items.end(); for (;id_it != id_end; ++id_it) { if ((*id_it) == mObjectID) { active_panel->clearSelection(); - std::vector items; - items.push_back(mObjectID); - highlight_inventory_objects_in_panel(items, active_panel); + highlight_inventory_objects_in_panel({mObjectID}, active_panel); active_panel->getRootFolder()->scrollToShowSelection(); gInventory.removeObserver(this); @@ -2241,6 +2239,7 @@ void autoresponder_finish(bool show_autoresponded, const LLUUID& session_id, con } } +#include const std::string NOT_ONLINE_MSG("User not online - message will be stored and delivered later."); const std::string NOT_ONLINE_INVENTORY("User not online - inventory has been saved."); void translate_if_needed(std::string& message) @@ -2253,6 +2252,17 @@ void translate_if_needed(std::string& message) { message = LLTrans::getString("not_online_inventory"); } + else if (boost::algorithm::ends_with(message, "Received Items folder.")) + { + boost::smatch match; + const boost::regex gift_exp("^You've received a gift! (.*) has given you \\\"(.*)\\\", and says \\\"(.*)\\\"\\. You can find your gift in your Received Items folder\\.$"); + bool gift = boost::regex_match(message, match, gift_exp); + if (gift || boost::regex_match(message, match, boost::regex("^Your purchase of (.*) has been delivered to your Received Items folder\\.$"))) + message = LLTrans::getString(gift ? "ReceivedGift" : "ReceivedPurchase", + gift ? LLSD().with("USER", match[1].str()).with("PRODUCT", match[2].str()).with("MESSAGE", match[3].str()) + : LLSD().with("PRODUCT", match[1].str())); + if (gSavedSettings.getBOOL("LiruReceivedItemsNotify")) LLNotificationsUtil::add("SystemMessage", LLSD().with("MESSAGE", message)); + } } void process_improved_im(LLMessageSystem *msg, void **user_data) @@ -2323,12 +2333,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) return; // NaCl End - // Singu TODO: LLIMProcessing goes here - if (chat.mSourceType == CHAT_SOURCE_SYSTEM) - { // Translate server message if required (MAINT-6109) - translate_if_needed(message); - } - // make sure that we don't have an empty or all-whitespace name LLStringUtil::trim(name); if (name.empty()) @@ -2368,6 +2372,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) args["NAME"] = name; } + // Singu TODO: LLIMProcessing goes here + if (chat.mSourceType == CHAT_SOURCE_SYSTEM) + { // Translate server message if required (MAINT-6109) + translate_if_needed(message); + } + LLViewerObject *source = gObjectList.findObject(session_id); //Session ID is probably the wrong thing. if (source || (source = gObjectList.findObject(from_id))) { @@ -8004,9 +8014,7 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response) void handle_lure(const LLUUID& invitee) { - std::vector ids; - ids.push_back(invitee); - handle_lure(ids); + handle_lure(uuid_vec_t{invitee}); } // Prompt for a message to the invited user. diff --git a/indra/newview/llviewerobjectbackup.h b/indra/newview/llviewerobjectbackup.h index 2b2283dff..7c1b13616 100644 --- a/indra/newview/llviewerobjectbackup.h +++ b/indra/newview/llviewerobjectbackup.h @@ -212,7 +212,7 @@ private: std::string mFolder; // Export texture list - typedef boost::unordered_set textures_set_t; + typedef uuid_set_t textures_set_t; textures_set_t mTexturesList; textures_set_t mBadPermsTexturesList; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 0f45eea51..f0ca03ab7 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1137,7 +1137,7 @@ void LLViewerObjectList::fetchObjectCosts() U32 object_index = 0; for ( - std::set::iterator iter = mStaleObjectCost.begin(); + auto iter = mStaleObjectCost.begin(); iter != mStaleObjectCost.end(); ) { @@ -1195,7 +1195,7 @@ void LLViewerObjectList::fetchPhysicsFlags() U32 object_index = 0; for ( - std::set::iterator iter = mStalePhysicsFlags.begin(); + auto iter = mStalePhysicsFlags.begin(); iter != mStalePhysicsFlags.end(); ) { diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 3f96c11bf..aa86c5c5c 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -217,18 +217,18 @@ public: vobj_list_t mMapObjects; - std::set mDeadObjects; + uuid_set_t mDeadObjects; boost::unordered_map > mUUIDObjectMap; boost::unordered_map > mUUIDAvatarMap; //set of objects that need to update their cost - std::set mStaleObjectCost; - std::set mPendingObjectCost; + uuid_set_t mStaleObjectCost; + uuid_set_t mPendingObjectCost; //set of objects that need to update their physics flags - std::set mStalePhysicsFlags; - std::set mPendingPhysicsFlags; + uuid_set_t mStalePhysicsFlags; + uuid_set_t mPendingPhysicsFlags; std::vector mDebugBeacons; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 028ad4a52..72ef3aafe 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1294,7 +1294,7 @@ public: S32 you_index = input["body"]["Index"][0]["You" ].asInteger(); std::vector& avatar_locs = region->mMapAvatars; - std::vector& avatar_ids = region->mMapAvatarIDs; + uuid_vec_t& avatar_ids = region->mMapAvatarIDs; std::list map_avids(avatar_ids.begin(), avatar_ids.end()); avatar_locs.clear(); avatar_ids.clear(); @@ -1986,6 +1986,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("EnvironmentSettings"); capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); + capabilityNames.append("ExtEnvironment"); capabilityNames.append("FetchLib2"); capabilityNames.append("FetchLibDescendents2"); capabilityNames.append("FetchInventory2"); diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 01d2014d2..3c9ce82e7 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -441,7 +441,9 @@ void LLEmbeddedItems::bindEmbeddedChars( const LLFontGL* font ) const case LLAssetType::AT_BODYPART: img_name = "inv_item_skin.tga"; break; case LLAssetType::AT_ANIMATION: img_name = "inv_item_animation.tga";break; case LLAssetType::AT_GESTURE: img_name = "inv_item_gesture.tga"; break; - default: llassert(0); continue; + case LLAssetType::AT_MESH: img_name = "Inv_Mesh"; break; + case LLAssetType::AT_SETTINGS: img_name = "Inv_Settings"; break; + default: img_name = "Inv_Invalid"; break; // use the Inv_Invalid icon for undefined object types (see MAINT-3981) } LLUIImagePtr image = LLUI::getUIImage(img_name); @@ -1461,7 +1463,6 @@ LLView* LLViewerTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlF BOOL parse_html = true; node->getAttributeBOOL("allow_html", parse_html); text_editor->setParseHTML(parse_html); - text_editor->setParseHighlights(TRUE); BOOL commit_on_focus_lost = FALSE; node->getAttributeBOOL("commit_on_focus_lost",commit_on_focus_lost); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 8e113b632..c770ca2e5 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -656,7 +656,7 @@ public: } } } - for(std::set::iterator it = gObjectList.mDeadObjects.begin();it!=gObjectList.mDeadObjects.end();++it) + for(auto it = gObjectList.mDeadObjects.begin();it!=gObjectList.mDeadObjects.end();++it) { LLViewerObject *obj = gObjectList.findObject(*it); if(obj && obj->isAvatar()) @@ -1640,6 +1640,17 @@ std::string LLViewerWindow::translateString(const char* tag, return LLTrans::getString( std::string(tag), args_copy); } +static const std::string font_dir() +{ + return gDirUtilp->getExecutableDir() + #if LL_DARWIN + + "../Resources/" + #elif !defined(LL_WINDOWS) + + "../" + #endif + ; +} + // // Classes // @@ -1808,7 +1819,7 @@ LLViewerWindow::LLViewerWindow( LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), mDisplayScale.mV[VX], mDisplayScale.mV[VY], - gDirUtilp->getAppRODataDir()); + font_dir()); } // Create container for all sub-views LLView::Params rvp; @@ -5497,7 +5508,8 @@ void LLViewerWindow::initFonts(F32 zoom_factor) LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), mDisplayScale.mV[VX] * zoom_factor, mDisplayScale.mV[VY] * zoom_factor, - gDirUtilp->getAppRODataDir()); + font_dir()); + // Force font reloads, which can be very slow LLFontGL::loadDefaultFonts(); } void LLViewerWindow::toggleFullscreen(BOOL show_progress) diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp index b4ec788f7..f3dd91ab5 100644 --- a/indra/newview/llvlmanager.cpp +++ b/indra/newview/llvlmanager.cpp @@ -70,7 +70,7 @@ void LLVLManager::addLayerData(LLVLData *vl_datap, const S32 mesg_size) { mLandBits += mesg_size * 8; } - else if (WATER_LAYER_CODE == vl_datap->mType || WHITECORE_CLOUD_LAYER_CODE == vl_datap->mType) + else if (WATER_LAYER_CODE == vl_datap->mType || WHITECORE_WATER_LAYER_CODE == vl_datap->mType) { mWaterBits += mesg_size * 8; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7b7a3cda2..26f136549 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5743,9 +5743,9 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) return 6; } -bool LLVOAvatar::allTexturesCompletelyDownloaded(std::set& ids) const +bool LLVOAvatar::allTexturesCompletelyDownloaded(uuid_set_t& ids) const { - for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) + for (auto it = ids.begin(); it != ids.end(); ++it) { LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); if (imagep && imagep->getDiscardLevel()!=0) @@ -5758,14 +5758,14 @@ bool LLVOAvatar::allTexturesCompletelyDownloaded(std::set& ids) const bool LLVOAvatar::allLocalTexturesCompletelyDownloaded() const { - std::set local_ids; + uuid_set_t local_ids; collectLocalTextureUUIDs(local_ids); return allTexturesCompletelyDownloaded(local_ids); } bool LLVOAvatar::allBakedTexturesCompletelyDownloaded() const { - std::set baked_ids; + uuid_set_t baked_ids; collectBakedTextureUUIDs(baked_ids); return allTexturesCompletelyDownloaded(baked_ids); } @@ -5777,9 +5777,9 @@ void LLVOAvatar::bakedTextureOriginCounts(S32 &sb_count, // server-bake, has ori { sb_count = host_count = both_count = neither_count = 0; - std::set baked_ids; + uuid_set_t baked_ids; collectBakedTextureUUIDs(baked_ids); - for (std::set::const_iterator it = baked_ids.begin(); it != baked_ids.end(); ++it) + for (auto it = baked_ids.begin(); it != baked_ids.end(); ++it) { LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); bool has_url = false, has_host = false; @@ -5802,9 +5802,9 @@ std::string LLVOAvatar::bakedTextureOriginInfo() { std::string result; - std::set baked_ids; + uuid_set_t baked_ids; collectBakedTextureUUIDs(baked_ids); - for (std::set::const_iterator it = baked_ids.begin(); it != baked_ids.end(); ++it) + for (auto it = baked_ids.begin(); it != baked_ids.end(); ++it) { LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); bool has_url = false, has_host = false; @@ -5830,10 +5830,10 @@ std::string LLVOAvatar::bakedTextureOriginInfo() return result; } -S32Bytes LLVOAvatar::totalTextureMemForUUIDS(std::set& ids) +S32Bytes LLVOAvatar::totalTextureMemForUUIDS(uuid_set_t& ids) { S32Bytes result(0); - for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) + for (auto it = ids.begin(); it != ids.end(); ++it) { LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); if (imagep) @@ -5844,7 +5844,7 @@ S32Bytes LLVOAvatar::totalTextureMemForUUIDS(std::set& ids) return result; } -void LLVOAvatar::collectLocalTextureUUIDs(std::set& ids) const +void LLVOAvatar::collectLocalTextureUUIDs(uuid_set_t& ids) const { for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { @@ -5870,7 +5870,7 @@ void LLVOAvatar::collectLocalTextureUUIDs(std::set& ids) const ids.erase(IMG_INVISIBLE); } -void LLVOAvatar::collectBakedTextureUUIDs(std::set& ids) const +void LLVOAvatar::collectBakedTextureUUIDs(uuid_set_t& ids) const { for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { @@ -5889,7 +5889,7 @@ void LLVOAvatar::collectBakedTextureUUIDs(std::set& ids) const ids.erase(IMG_INVISIBLE); } -void LLVOAvatar::collectTextureUUIDs(std::set& ids) +void LLVOAvatar::collectTextureUUIDs(uuid_set_t& ids) { collectLocalTextureUUIDs(ids); collectBakedTextureUUIDs(ids); @@ -5900,15 +5900,15 @@ void LLVOAvatar::releaseOldTextures() S32Bytes current_texture_mem; // Any textures that we used to be using but are no longer using should no longer be flagged as "NO_DELETE" - std::set baked_texture_ids; + uuid_set_t baked_texture_ids; collectBakedTextureUUIDs(baked_texture_ids); S32Bytes new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids); - std::set local_texture_ids; + uuid_set_t local_texture_ids; collectLocalTextureUUIDs(local_texture_ids); //S32 new_local_mem = totalTextureMemForUUIDS(local_texture_ids); - std::set new_texture_ids; + uuid_set_t new_texture_ids; new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end()); new_texture_ids.insert(local_texture_ids.begin(),local_texture_ids.end()); S32Bytes new_total_mem = totalTextureMemForUUIDS(new_texture_ids); @@ -5919,7 +5919,7 @@ void LLVOAvatar::releaseOldTextures() { LL_WARNS() << "extra local textures stored for non-self av" << LL_ENDL; } - for (std::set::iterator it = mTextureIDs.begin(); it != mTextureIDs.end(); ++it) + for (auto it = mTextureIDs.begin(); it != mTextureIDs.end(); ++it) { if (new_texture_ids.find(*it) == new_texture_ids.end()) { @@ -6843,7 +6843,7 @@ void LLVOAvatar::updateAttachmentOverrides() { LL_DEBUGS("AnimatedObjects") << "updating" << LL_ENDL; - std::set meshes_seen; + uuid_set_t meshes_seen; // Handle the case that we're updating the skeleton of an animated object. LLControlAvatar *control_av = asControlAvatar(); @@ -6888,8 +6888,8 @@ void LLVOAvatar::updateAttachmentOverrides() // Remove meshes that are no longer present on the skeleton // have to work with a copy because removeAttachmentOverrides() will change mActiveOverrideMeshes. - std::set active_override_meshes = mActiveOverrideMeshes; - for (std::set::iterator it = active_override_meshes.begin(); it != active_override_meshes.end(); ++it) + uuid_set_t active_override_meshes = mActiveOverrideMeshes; + for (auto it = active_override_meshes.begin(); it != active_override_meshes.end(); ++it) { if (meshes_seen.find(*it) == meshes_seen.end()) { @@ -6899,7 +6899,7 @@ void LLVOAvatar::updateAttachmentOverrides() } // addAttachmentPosOverridesForObject //----------------------------------------------------------------------------- -void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::set* meshes_seen, bool recursive) +void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, uuid_set_t* meshes_seen, bool recursive) { if (vo->getAvatar() != this && vo->getAvatarAncestor() != this) { @@ -10859,7 +10859,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() max_attachment_complexity = llmax(max_attachment_complexity, DEFAULT_MAX_ATTACHMENT_COMPLEXITY); // Diagnostic list of all textures on our avatar - static std::set all_textures; + static uuid_set_t all_textures; if (mVisualComplexityStale) { diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 72eac5ed8..7df17cc7c 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -187,16 +187,16 @@ public: void updateLODRiggedAttachments( void ); void updateSoftwareSkinnedVertices(const LLMeshSkinInfo* skin, const LLVector4a* weight, const LLVolumeFace& vol_face, LLVertexBuffer *buffer); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. - S32Bytes totalTextureMemForUUIDS(std::set& ids); - bool allTexturesCompletelyDownloaded(std::set& ids) const; + S32Bytes totalTextureMemForUUIDS(uuid_set_t& ids); + bool allTexturesCompletelyDownloaded(uuid_set_t& ids) const; bool allLocalTexturesCompletelyDownloaded() const; bool allBakedTexturesCompletelyDownloaded() const; void bakedTextureOriginCounts(S32 &sb_count, S32 &host_count, S32 &both_count, S32 &neither_count); std::string bakedTextureOriginInfo(); - void collectLocalTextureUUIDs(std::set& ids) const; - void collectBakedTextureUUIDs(std::set& ids) const; - void collectTextureUUIDs(std::set& ids); + void collectLocalTextureUUIDs(uuid_set_t& ids) const; + void collectBakedTextureUUIDs(uuid_set_t& ids) const; + void collectTextureUUIDs(uuid_set_t& ids); void releaseOldTextures(); /*virtual*/ void updateTextures(); LLViewerFetchedTexture* getBakedTextureImage(const U8 te, const LLUUID& uuid); @@ -257,7 +257,7 @@ public: virtual LLJoint* getJoint(const std::string &name); LLJoint* getJoint(S32 num); - void addAttachmentOverridesForObject(LLViewerObject *vo, std::set* meshes_seen = NULL, bool recursive = true); + void addAttachmentOverridesForObject(LLViewerObject *vo, uuid_set_t* meshes_seen = NULL, bool recursive = true); void removeAttachmentOverridesForObject(const LLUUID& mesh_id); void removeAttachmentOverridesForObject(LLViewerObject *vo); bool jointIsRiggedTo(const LLJoint *joint) const; @@ -275,7 +275,7 @@ public: // This encodes mesh id and LOD, so we can see whether display is up-to-date. std::map mLastRiggingInfoKey; - std::set mActiveOverrideMeshes; + uuid_set_t mActiveOverrideMeshes; virtual void onActiveOverrideMeshesChanged(); /*virtual*/ const LLUUID& getID() const; @@ -660,7 +660,7 @@ protected: LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ; BOOL mLoadedCallbacksPaused; - std::set mTextureIDs; + uuid_set_t mTextureIDs; //-------------------------------------------------------------------- // Local Textures //-------------------------------------------------------------------- diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 24af67adb..c98d19f82 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -309,7 +309,7 @@ const LLVoiceDeviceList& LLVoiceClient::getRenderDevices() //-------------------------------------------------- // participants -void LLVoiceClient::getParticipantList(std::set &participants) +void LLVoiceClient::getParticipantList(uuid_set_t &participants) { if (mVoiceModule) { @@ -317,7 +317,7 @@ void LLVoiceClient::getParticipantList(std::set &participants) } else { - participants = std::set(); + participants = uuid_set_t(); } } diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index b8cf474cc..1c2640085 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -139,7 +139,7 @@ public: virtual LLVoiceDeviceList& getCaptureDevices()=0; virtual LLVoiceDeviceList& getRenderDevices()=0; - virtual void getParticipantList(std::set &participants)=0; + virtual void getParticipantList(uuid_set_t &participants)=0; virtual bool isParticipant(const LLUUID& speaker_id)=0; //@} @@ -420,7 +420,7 @@ public: ///////////////////////////// BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled. // Use this to determine whether to show a "no speech" icon in the menu bar. - void getParticipantList(std::set &participants); + void getParticipantList(uuid_set_t &participants); bool isParticipant(const LLUUID& speaker_id); ////////////////////////// diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 5e64585bf..8eec26c6f 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -3932,7 +3932,7 @@ void LLVivoxVoiceClient::sessionState::removeAllParticipants() mParticipantList.shrink_to_fit(); } -void LLVivoxVoiceClient::getParticipantList(std::set &participants) +void LLVivoxVoiceClient::getParticipantList(uuid_set_t &participants) { if(mAudioSession) { diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 2d723184b..9cdf4126c 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -88,7 +88,7 @@ public: virtual LLVoiceDeviceList& getRenderDevices(); //@} - virtual void getParticipantList(std::set &participants); + virtual void getParticipantList(uuid_set_t &participants); virtual bool isParticipant(const LLUUID& speaker_id); // Send a text message to the specified user, initiating the session if necessary. diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8d1bb82d5..70e9a844e 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4283,7 +4283,6 @@ LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const return ret; } - BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) @@ -4317,7 +4316,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& transform = false; } else - { //cannot pick rigged attachments on other avatars or when not in build mode + { return FALSE; } } diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 33c9c3cf7..3146622c4 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -158,7 +158,8 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) sLastUpdate = current; // Send update request. - std::string url = gAgent.getRegion()->getCapability("EnvironmentSettings"); + std::string url = gAgent.getRegionCapability("ExtEnvironment"); + if (url.empty()) url = gAgent.getRegionCapability("EnvironmentSettings"); if (url.empty()) { LL_WARNS("WindlightCaps") << "Applying windlight settings not supported" << LL_ENDL; diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp index f423a95f7..66cd1209e 100644 --- a/indra/newview/llworldmapmessage.cpp +++ b/indra/newview/llworldmapmessage.cpp @@ -74,10 +74,10 @@ void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name) { - //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL; + //LL_INFOS("WorldMap") << LL_ENDL; LLMessageSystem* msg = gMessageSystem; - // Request for layer + // Request for region data msg->newMessageFast(_PREHASH_MapNameRequest); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); @@ -95,7 +95,7 @@ void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name, const std::string& callback_url, bool teleport) // immediately teleport when result returned { - //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL; + //LL_INFOS("WorldMap") << LL_ENDL; mSLURLRegionName = region_name; mSLURLRegionHandle = 0; mSLURL = callback_url; @@ -110,7 +110,7 @@ void LLWorldMapMessage::sendHandleRegionRequest(U64 region_handle, const std::string& callback_url, bool teleport) // immediately teleport when result returned { - //LL_INFOS("World Map") << "LLWorldMap::sendHandleRegionRequest()" << LL_ENDL; + //LL_INFOS("WorldMap") << LL_ENDL; mSLURLRegionName.clear(); mSLURLRegionHandle = region_handle; mSLURL = callback_url; @@ -123,13 +123,12 @@ void LLWorldMapMessage::sendHandleRegionRequest(U64 region_handle, U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); - sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true, LAYER_FLAG); + sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); } -// public void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent, S32 layer) { - //LL_INFOS("World Map") << "LLWorldMap::sendMapBlockRequest()" << ", min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << "), nonexistent = " << return_nonexistent << LL_ENDL; + //LL_INFOS("WorldMap" << " min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << ", nonexistent = " << return_nonexistent << LL_ENDL; LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_MapBlockRequest); msg->nextBlockFast(_PREHASH_AgentData); @@ -162,7 +161,7 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) } S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data); - //LL_INFOS("World Map") << "LLWorldMap::processMapBlockReply(), num_blocks = " << num_blocks << LL_ENDL; + //LL_INFOS("WorldMap") << "num_blocks = " << num_blocks << LL_ENDL; bool found_null_sim = false; @@ -239,7 +238,6 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) url_callback_t callback = LLWorldMapMessage::getInstance()->mSLURLCallback; if(callback != NULL) { - // Check if we reached the requested region if ((LLStringUtil::compareInsensitive(LLWorldMapMessage::getInstance()->mSLURLRegionName, name)==0) || (LLWorldMapMessage::getInstance()->mSLURLRegionHandle == handle)) @@ -264,7 +262,7 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) // public static void LLWorldMapMessage::processMapItemReply(LLMessageSystem* msg, void**) { - //LL_INFOS("World Map") << "LLWorldMap::processMapItemReply()" << LL_ENDL; + //LL_INFOS("WorldMap") << LL_ENDL; U32 type; msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type); diff --git a/indra/newview/rlvcommon.cpp b/indra/newview/rlvcommon.cpp index d6a6b9d3f..c3dc38ebe 100644 --- a/indra/newview/rlvcommon.cpp +++ b/indra/newview/rlvcommon.cpp @@ -459,7 +459,7 @@ bool RlvUtil::isNearbyAgent(const LLUUID& idAgent) RLV_ASSERT(idAgent.notNull()); if ( (idAgent.notNull()) && (gAgent.getID() != idAgent) ) { - std::vector idAgents; + uuid_vec_t idAgents; LLWorld::getInstance()->getAvatars(&idAgents, NULL); for (int idxAgent = 0, cntAgent = idAgents.size(); idxAgent < cntAgent; idxAgent++) diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 72ed7415f..c89c1782d 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -1035,7 +1035,7 @@ LLColor3 RlvHandler::camDrawColor() const case LLAssetType::AT_CLOTHING: { // NOTE: without its asset we don't know what type the wearable is so we need to look at the item's flags instead - LLWearableType::EType wtType = (LLWearableType::EType)(pItem->getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK); + LLWearableType::EType wtType = (LLWearableType::EType)(pItem->getFlags() & LLInventoryItem::II_FLAGS_SUBTYPE_MASK); LLViewerInventoryCategory* pFolder; if ( (!isWearable(wtType)) || ( (gAgent.getWearable(wtType)) && (!isRemovable(wtType)) ) || diff --git a/indra/newview/rlvinventory.h b/indra/newview/rlvinventory.h index 0aee6aa38..186bf6549 100644 --- a/indra/newview/rlvinventory.h +++ b/indra/newview/rlvinventory.h @@ -150,7 +150,7 @@ protected: /*virtual*/ void onDestinationCreated(const LLUUID& idFolder, const std::string& strName); protected: - typedef std::vector folder_ref_t; + typedef uuid_vec_t folder_ref_t; folder_ref_t m_Folders; LLUUID m_idTransaction; }; diff --git a/indra/newview/skins/Gemini.xml b/indra/newview/skins/Gemini.xml index f6a912fe9..165cbca03 100644 --- a/indra/newview/skins/Gemini.xml +++ b/indra/newview/skins/Gemini.xml @@ -7,7 +7,7 @@ additional_author_names Linden Lab skin_info - Originally made for the INFAMOUS Gemini viewer. Also default skin of Second Life 3.0. Use it if you don't like eye-cancer. + Originally made for the Gemini viewer, similar to the default skin of Second Life 3.0. Use it if you want a dark skin that's easy on the eyes. folder_name gemini diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index e79da44cc..f224a0d1f 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -295,6 +295,7 @@ with the same filename but different name + diff --git a/indra/newview/skins/default/xui/de/floater_chat_history.xml b/indra/newview/skins/default/xui/de/floater_chat_history.xml index 947af1926..2975caaca 100644 --- a/indra/newview/skins/default/xui/de/floater_chat_history.xml +++ b/indra/newview/skins/default/xui/de/floater_chat_history.xml @@ -16,7 +16,7 @@ - + + @@ -1170,12 +1170,20 @@ mouse_opaque="true" name="edit_object" v_pad="0" width="252"> Edit object features: - + - diff --git a/indra/newview/skins/default/xui/en-us/fonts.xml b/indra/newview/skins/default/xui/en-us/fonts.xml index 9ed679b43..a3899f239 100644 --- a/indra/newview/skins/default/xui/en-us/fonts.xml +++ b/indra/newview/skins/default/xui/en-us/fonts.xml @@ -3,8 +3,15 @@ DejaVuSansCondensed.ttf + NotoSansDisplay-Regular.ttf + SourceHanSansJP-Regular.otf + SourceHanSansKR-Regular.otf + SourceHanSansCN-Regular.otf + SourceHanSansHK-Regular.otf + SourceHanSansTW-Regular.otf YuGothR.ttc + meiryo.TTC MSGOTHIC.TTC gulim.ttc simhei.ttf @@ -22,14 +29,48 @@ - - DroidSans.ttf - - DroidSans-Bold.ttf + DejaVuSansCondensed-Bold.ttf + NotoSansDisplay-Bold.ttf + SourceHanSansJP-Bold.otf + SourceHanSansKR-Bold.otf + SourceHanSansCN-Bold.otf + SourceHanSansHK-Bold.otf + SourceHanSansTW-Bold.otf + + + + DroidSans.ttf + + + + DroidSans-Bold.ttf + DejaVuSansCondensed-Bold.ttf + NotoSansDisplay-Bold.ttf + SourceHanSansJP-Bold.otf + SourceHanSansKR-Bold.otf + SourceHanSansCN-Bold.otf + SourceHanSansHK-Bold.otf + SourceHanSansTW-Bold.otf + + + + DejaVuSansCondensed-Oblique.ttf + NotoSansDisplay-Italic.ttf + + + + DejaVuSansCondensed-BoldOblique.ttf + NotoSansDisplay-BoldItalic.ttf - DejaVuSans.ttf + DejaVuSansCondensed.ttf - DejaVuSansBold.ttf + DejaVuSansCondensed-Bold.ttf - DejaVuSansOblique.ttf + DejaVuSansCondensed-Oblique.ttf - DejaVuSansBoldOblique.ttf + DejaVuSansCondensed-BoldOblique.ttf - diff --git a/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml b/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml index ca9deedcc..51bd82c17 100644 --- a/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml +++ b/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml @@ -1,6 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index 51fe6c6d6..768561e19 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -1586,6 +1586,19 @@ Unable to download file fail + + + confirm + You have requested a file download, which is not supported within [SECOND_LIFE]. + + + Drop a landmark below to autoteleport there in the last 20 seconds before region restarts - Drop a backup landmark to autoteleport to below, should you already be at the above + Drop a backup landmark to autoteleport to below, should you already be at above diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml index 72d9b4c51..6dd9e25ae 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml @@ -17,7 +17,7 @@ Sound played when regions will restart: - + diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml index 52cb051d1..74e915cf9 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_general.xml @@ -1,6 +1,6 @@ - + My Home My Last Location @@ -28,7 +28,7 @@ - + Rating: I want to access content rated: diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml index d556bafed..7e4b025bd 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml @@ -66,7 +66,7 @@ follows="left|top|right" border_visible="false" mouse_opaque="false" drop_shadow_visible="true" border_drop_shadow_visible="false" />