diff --git a/.gitattributes b/.gitattributes index bfbd414682ec73548c28c7edc7a52e3e457ce717..3188bae7306dca27d4446bdab51f2a0617642ec6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,9 @@ * text eol=lf +# Viewer Files +*.db2 binary +*.llm binary + *.sln text eol=crlf *.vcproj text eol=crlf *.vcxproj text eol=crlf @@ -9,5 +13,10 @@ *.tga binary *.jpg binary *.j2k binary +*.j2c binary +*.ico binary +*.icns binary +*.bmp binary +*.BMP binary /indra/tools/manifests/compatibility.manifest text eol=crlf \ No newline at end of file diff --git a/indra/cmake/InstallRequiredSystemLibrariesAL.cmake b/indra/cmake/InstallRequiredSystemLibrariesAL.cmake index 6dd525a21d73ccd932b14a6eb437f73ec3c00651..c13d04b2e550a4abec510ab70caf55a1d3078982 100644 --- a/indra/cmake/InstallRequiredSystemLibrariesAL.cmake +++ b/indra/cmake/InstallRequiredSystemLibrariesAL.cmake @@ -1,733 +1,733 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -InstallRequiredSystemLibraries ------------------------------- - -Include this module to search for compiler-provided system runtime -libraries and add install rules for them. Some optional variables -may be set prior to including the module to adjust behavior: - -``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS`` - Specify additional runtime libraries that may not be detected. - After inclusion any detected libraries will be appended to this. - -``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP`` - Set to TRUE to skip calling the :command:`install(PROGRAMS)` command to - allow the includer to specify its own install rule, using the value of - ``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS`` to get the list of libraries. - -``CMAKE_INSTALL_DEBUG_LIBRARIES`` - Set to TRUE to install the debug runtime libraries when available - with MSVC tools. - -``CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY`` - Set to TRUE to install only the debug runtime libraries with MSVC - tools even if the release runtime libraries are also available. - -``CMAKE_INSTALL_UCRT_LIBRARIES`` - Set to TRUE to install the Windows Universal CRT libraries for - app-local deployment (e.g. to Windows XP). This is meaningful - only with MSVC from Visual Studio 2015 or higher. - - One may set a ``CMAKE_WINDOWS_KITS_10_DIR`` *environment variable* - to an absolute path to tell CMake to look for Windows 10 SDKs in - a custom location. The specified directory is expected to contain - ``Redist/ucrt/DLLs/*`` directories. - -``CMAKE_INSTALL_MFC_LIBRARIES`` - Set to TRUE to install the MSVC MFC runtime libraries. - -``CMAKE_INSTALL_OPENMP_LIBRARIES`` - Set to TRUE to install the MSVC OpenMP runtime libraries - -``CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION`` - Specify the :command:`install(PROGRAMS)` command ``DESTINATION`` - option. If not specified, the default is ``bin`` on Windows - and ``lib`` elsewhere. - -``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS`` - Set to TRUE to disable warnings about required library files that - do not exist. (For example, Visual Studio Express editions may - not provide the redistributable files.) - -``CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT`` - Specify the :command:`install(PROGRAMS)` command ``COMPONENT`` - option. If not specified, no such option will be used. -#]=======================================================================] - -cmake_policy(PUSH) -cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced - -set(_IRSL_HAVE_Intel FALSE) -set(_IRSL_HAVE_MSVC FALSE) -foreach(LANG IN ITEMS C CXX Fortran) - if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Intel") - if(NOT _IRSL_HAVE_Intel) - get_filename_component(_Intel_basedir "${CMAKE_${LANG}_COMPILER}" PATH) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(_Intel_archdir intel64) - else() - set(_Intel_archdir x86) - endif() - set(_Intel_compiler_ver ${CMAKE_${LANG}_COMPILER_VERSION}) - if(WIN32) - get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../redist/${_Intel_archdir}/compiler" ABSOLUTE) - elseif(APPLE) - get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib" ABSOLUTE) - else() - if(EXISTS "${_Intel_basedir}/../lib/${_Intel_archdir}_lin") - get_filename_component(_Intel_redistdir "${_Intel_basedir}/../lib/${_Intel_archdir}" ABSOLUTE) - else() - get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib/${_Intel_archdir}_lin" ABSOLUTE) - endif() - endif() - set(_IRSL_HAVE_Intel TRUE) - endif() - elseif("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "MSVC") - set(_IRSL_HAVE_MSVC TRUE) - endif() -endforeach() - -if(MSVC) - file(TO_CMAKE_PATH "$ENV{SYSTEMROOT}" SYSTEMROOT) - - if(CMAKE_CL_64) - if(MSVC_VERSION GREATER 1599) - # VS 10 and later: - set(CMAKE_MSVC_ARCH x64) - else() - # VS 9 and earlier: - set(CMAKE_MSVC_ARCH amd64) - endif() - else() - set(CMAKE_MSVC_ARCH x86) - endif() - - get_filename_component(devenv_dir "${CMAKE_MAKE_PROGRAM}" PATH) - get_filename_component(base_dir "${devenv_dir}/../.." ABSOLUTE) - - if(MSVC_VERSION EQUAL 1300) - set(__install__libs - "${SYSTEMROOT}/system32/msvcp70.dll" - "${SYSTEMROOT}/system32/msvcr70.dll" - ) - endif() - - if(MSVC_VERSION EQUAL 1310) - set(__install__libs - "${SYSTEMROOT}/system32/msvcp71.dll" - "${SYSTEMROOT}/system32/msvcr71.dll" - ) - endif() - - if(MSVC_TOOLSET_VERSION EQUAL 80) - # Find the runtime library redistribution directory. - get_filename_component(msvc_install_dir - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0;InstallDir]" ABSOLUTE) - if(DEFINED MSVC80_REDIST_DIR AND EXISTS "${MSVC80_REDIST_DIR}") - set(MSVC_REDIST_DIR "${MSVC80_REDIST_DIR}") # use old cache entry - endif() - find_path(MSVC_REDIST_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest - PATHS - "${msvc_install_dir}/../../VC/redist" - "${base_dir}/VC/redist" - ) - mark_as_advanced(MSVC_REDIST_DIR) - set(MSVC_CRT_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC80.CRT") - - # Install the manifest that allows DLLs to be loaded from the - # directory containing the executable. - if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) - set(__install__libs - "${MSVC_CRT_DIR}/Microsoft.VC80.CRT.manifest" - "${MSVC_CRT_DIR}/msvcm80.dll" - "${MSVC_CRT_DIR}/msvcp80.dll" - "${MSVC_CRT_DIR}/msvcr80.dll" - ) - else() - set(__install__libs) - endif() - - if(CMAKE_INSTALL_DEBUG_LIBRARIES) - set(MSVC_CRT_DIR - "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.VC80.DebugCRT") - set(__install__libs ${__install__libs} - "${MSVC_CRT_DIR}/Microsoft.VC80.DebugCRT.manifest" - "${MSVC_CRT_DIR}/msvcm80d.dll" - "${MSVC_CRT_DIR}/msvcp80d.dll" - "${MSVC_CRT_DIR}/msvcr80d.dll" - ) - endif() - endif() - - if(MSVC_TOOLSET_VERSION EQUAL 90) - # Find the runtime library redistribution directory. - get_filename_component(msvc_install_dir - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0;InstallDir]" ABSOLUTE) - get_filename_component(msvc_express_install_dir - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\9.0;InstallDir]" ABSOLUTE) - if(DEFINED MSVC90_REDIST_DIR AND EXISTS "${MSVC90_REDIST_DIR}") - set(MSVC_REDIST_DIR "${MSVC90_REDIST_DIR}") # use old cache entry - endif() - find_path(MSVC_REDIST_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest - PATHS - "${msvc_install_dir}/../../VC/redist" - "${msvc_express_install_dir}/../../VC/redist" - "${base_dir}/VC/redist" - ) - mark_as_advanced(MSVC_REDIST_DIR) - set(MSVC_CRT_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC90.CRT") - - # Install the manifest that allows DLLs to be loaded from the - # directory containing the executable. - if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) - set(__install__libs - "${MSVC_CRT_DIR}/Microsoft.VC90.CRT.manifest" - "${MSVC_CRT_DIR}/msvcm90.dll" - "${MSVC_CRT_DIR}/msvcp90.dll" - "${MSVC_CRT_DIR}/msvcr90.dll" - ) - else() - set(__install__libs) - endif() - - if(CMAKE_INSTALL_DEBUG_LIBRARIES) - set(MSVC_CRT_DIR - "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.VC90.DebugCRT") - set(__install__libs ${__install__libs} - "${MSVC_CRT_DIR}/Microsoft.VC90.DebugCRT.manifest" - "${MSVC_CRT_DIR}/msvcm90d.dll" - "${MSVC_CRT_DIR}/msvcp90d.dll" - "${MSVC_CRT_DIR}/msvcr90d.dll" - ) - endif() - endif() - - set(MSVC_REDIST_NAME "") - set(_MSVC_DLL_VERSION "") - set(_MSVC_IDE_VERSION "") - if(MSVC_VERSION GREATER_EQUAL 2000) - message(WARNING "MSVC ${MSVC_VERSION} not yet supported.") - elseif(MSVC_VERSION_VERSION GREATER_EQUAL 143) - message(WARNING "MSVC toolset v${MSVC_VERSION_VERSION} not yet supported.") - elseif(MSVC_TOOLSET_VERSION EQUAL 142) - set(MSVC_REDIST_NAME VC142) - set(_MSVC_DLL_VERSION 140) - set(_MSVC_IDE_VERSION 16) - elseif(MSVC_TOOLSET_VERSION EQUAL 141) - set(MSVC_REDIST_NAME VC142) - set(_MSVC_DLL_VERSION 140) - set(_MSVC_IDE_VERSION 16) - elseif(MSVC_TOOLSET_VERSION) - set(MSVC_REDIST_NAME VC${MSVC_TOOLSET_VERSION}) - math(EXPR _MSVC_DLL_VERSION "${MSVC_TOOLSET_VERSION} / 10 * 10") - math(EXPR _MSVC_IDE_VERSION "${MSVC_TOOLSET_VERSION} / 10") - endif() - - set(_MSVCRT_DLL_VERSION "") - set(_MSVCRT_IDE_VERSION "") - if(_MSVC_IDE_VERSION GREATER_EQUAL 10) - set(_MSVCRT_DLL_VERSION "${_MSVC_DLL_VERSION}") - set(_MSVCRT_IDE_VERSION "${_MSVC_IDE_VERSION}") - endif() - - if(_MSVCRT_DLL_VERSION) - set(v "${_MSVCRT_DLL_VERSION}") - set(vs "${_MSVCRT_IDE_VERSION}") - - # Find the runtime library redistribution directory. - if(vs VERSION_LESS 15 AND DEFINED MSVC${vs}_REDIST_DIR AND EXISTS "${MSVC${vs}_REDIST_DIR}") - set(MSVC_REDIST_DIR "${MSVC${vs}_REDIST_DIR}") # use old cache entry - endif() - if(NOT vs VERSION_LESS 15) - set(_vs_redist_paths "") - cmake_host_system_information(RESULT _vs_dir QUERY VS_${vs}_DIR) # undocumented query - if(IS_DIRECTORY "${_vs_dir}") - file(GLOB _vs_redist_paths "${_vs_dir}/VC/Redist/MSVC/*") - endif() - unset(_vs_dir) - else() - get_filename_component(_vs_dir - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${vs}.0;InstallDir]" ABSOLUTE) - set(programfilesx86 "ProgramFiles(x86)") - set(_vs_redist_paths - "${_vs_dir}/../../VC/redist" - "${base_dir}/VC/redist" - "$ENV{ProgramFiles}/Microsoft Visual Studio ${vs}.0/VC/redist" - "$ENV{${programfilesx86}}/Microsoft Visual Studio ${vs}.0/VC/redist" - ) - unset(_vs_dir) - unset(programfilesx86) - endif() - find_path(MSVC_REDIST_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.CRT PATHS ${_vs_redist_paths}) - unset(_vs_redist_paths) - mark_as_advanced(MSVC_REDIST_DIR) - set(MSVC_CRT_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.CRT") - - if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) - set(__install__libs - "${MSVC_CRT_DIR}/msvcp${v}.dll" - ) - if(NOT vs VERSION_LESS 14) - file(GLOB __msvcr_dlls "${MSVC_CRT_DIR}/*.dll") - list(APPEND __install__libs ${__msvcr_dlls}) - else() - list(APPEND __install__libs "${MSVC_CRT_DIR}/msvcr${v}.dll") - endif() - else() - set(__install__libs) - endif() - - if(CMAKE_INSTALL_DEBUG_LIBRARIES) - set(MSVC_CRT_DIR - "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.DebugCRT") - set(__install__libs ${__install__libs} - "${MSVC_CRT_DIR}/msvcp${v}d.dll" - ) - if(NOT vs VERSION_LESS 14) - list(APPEND __install__libs - "${MSVC_CRT_DIR}/vcruntime${v}d.dll" - "${MSVC_CRT_DIR}/concrt${v}d.dll" - ) - else() - list(APPEND __install__libs "${MSVC_CRT_DIR}/msvcr${v}d.dll") - endif() - endif() - - if(CMAKE_INSTALL_UCRT_LIBRARIES AND NOT vs VERSION_LESS 14) - # Find the Windows Kits directory. - get_filename_component(windows_kits_dir - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots;KitsRoot10]" ABSOLUTE) - set(programfilesx86 "ProgramFiles(x86)") - if(";${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION};$ENV{UCRTVersion};$ENV{WindowsSDKVersion};" MATCHES [=[;(10\.[0-9.]+)[;\]]=]) - set(__ucrt_version "${CMAKE_MATCH_1}/") - else() - set(__ucrt_version "") - endif() - find_path(WINDOWS_KITS_DIR - NAMES - Redist/${__ucrt_version}ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll - Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll - PATHS - $ENV{CMAKE_WINDOWS_KITS_10_DIR} - "${windows_kits_dir}" - "$ENV{ProgramFiles}/Windows Kits/10" - "$ENV{${programfilesx86}}/Windows Kits/10" - ) - mark_as_advanced(WINDOWS_KITS_DIR) - - # Glob the list of UCRT DLLs. - if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) - if(EXISTS "${WINDOWS_KITS_DIR}/Redist/${__ucrt_version}ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll") - file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/Redist/${__ucrt_version}ucrt/DLLs/${CMAKE_MSVC_ARCH}/*.dll") - else() - file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/*.dll") - endif() - list(APPEND __install__libs ${__ucrt_dlls}) - endif() - if(CMAKE_INSTALL_DEBUG_LIBRARIES) - if(EXISTS "${WINDOWS_KITS_DIR}/bin/${__ucrt_version}${CMAKE_MSVC_ARCH}/ucrt/ucrtbased.dll") - file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/bin/${__ucrt_version}${CMAKE_MSVC_ARCH}/ucrt/*.dll") - else() - file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/bin/${CMAKE_MSVC_ARCH}/ucrt/*.dll") - endif() - list(APPEND __install__libs ${__ucrt_dlls}) - endif() - endif() - endif() - - if(CMAKE_INSTALL_MFC_LIBRARIES) - if(MSVC_VERSION EQUAL 1300) - set(__install__libs ${__install__libs} - "${SYSTEMROOT}/system32/mfc70.dll" - ) - endif() - - if(MSVC_VERSION EQUAL 1310) - set(__install__libs ${__install__libs} - "${SYSTEMROOT}/system32/mfc71.dll" - ) - endif() - - if(MSVC_VERSION EQUAL 1400) - if(CMAKE_INSTALL_DEBUG_LIBRARIES) - set(MSVC_MFC_DIR - "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.VC80.DebugMFC") - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/Microsoft.VC80.DebugMFC.manifest" - "${MSVC_MFC_DIR}/mfc80d.dll" - "${MSVC_MFC_DIR}/mfc80ud.dll" - "${MSVC_MFC_DIR}/mfcm80d.dll" - "${MSVC_MFC_DIR}/mfcm80ud.dll" - ) - endif() - - set(MSVC_MFC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC80.MFC") - # Install the manifest that allows DLLs to be loaded from the - # directory containing the executable. - if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/Microsoft.VC80.MFC.manifest" - "${MSVC_MFC_DIR}/mfc80.dll" - "${MSVC_MFC_DIR}/mfc80u.dll" - "${MSVC_MFC_DIR}/mfcm80.dll" - "${MSVC_MFC_DIR}/mfcm80u.dll" - ) - endif() - - # include the language dll's for vs8 as well as the actual dll's - set(MSVC_MFCLOC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC80.MFCLOC") - # Install the manifest that allows DLLs to be loaded from the - # directory containing the executable. - set(__install__libs ${__install__libs} - "${MSVC_MFCLOC_DIR}/Microsoft.VC80.MFCLOC.manifest" - "${MSVC_MFCLOC_DIR}/mfc80chs.dll" - "${MSVC_MFCLOC_DIR}/mfc80cht.dll" - "${MSVC_MFCLOC_DIR}/mfc80enu.dll" - "${MSVC_MFCLOC_DIR}/mfc80esp.dll" - "${MSVC_MFCLOC_DIR}/mfc80deu.dll" - "${MSVC_MFCLOC_DIR}/mfc80fra.dll" - "${MSVC_MFCLOC_DIR}/mfc80ita.dll" - "${MSVC_MFCLOC_DIR}/mfc80jpn.dll" - "${MSVC_MFCLOC_DIR}/mfc80kor.dll" - ) - endif() - - if(MSVC_VERSION EQUAL 1500) - if(CMAKE_INSTALL_DEBUG_LIBRARIES) - set(MSVC_MFC_DIR - "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.VC90.DebugMFC") - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/Microsoft.VC90.DebugMFC.manifest" - "${MSVC_MFC_DIR}/mfc90d.dll" - "${MSVC_MFC_DIR}/mfc90ud.dll" - "${MSVC_MFC_DIR}/mfcm90d.dll" - "${MSVC_MFC_DIR}/mfcm90ud.dll" - ) - endif() - - set(MSVC_MFC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC90.MFC") - # Install the manifest that allows DLLs to be loaded from the - # directory containing the executable. - if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/Microsoft.VC90.MFC.manifest" - "${MSVC_MFC_DIR}/mfc90.dll" - "${MSVC_MFC_DIR}/mfc90u.dll" - "${MSVC_MFC_DIR}/mfcm90.dll" - "${MSVC_MFC_DIR}/mfcm90u.dll" - ) - endif() - - # include the language dll's for vs9 as well as the actual dll's - set(MSVC_MFCLOC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC90.MFCLOC") - # Install the manifest that allows DLLs to be loaded from the - # directory containing the executable. - set(__install__libs ${__install__libs} - "${MSVC_MFCLOC_DIR}/Microsoft.VC90.MFCLOC.manifest" - "${MSVC_MFCLOC_DIR}/mfc90chs.dll" - "${MSVC_MFCLOC_DIR}/mfc90cht.dll" - "${MSVC_MFCLOC_DIR}/mfc90enu.dll" - "${MSVC_MFCLOC_DIR}/mfc90esp.dll" - "${MSVC_MFCLOC_DIR}/mfc90deu.dll" - "${MSVC_MFCLOC_DIR}/mfc90fra.dll" - "${MSVC_MFCLOC_DIR}/mfc90ita.dll" - "${MSVC_MFCLOC_DIR}/mfc90jpn.dll" - "${MSVC_MFCLOC_DIR}/mfc90kor.dll" - ) - endif() - - set(_MFC_DLL_VERSION "") - set(_MFC_IDE_VERSION "") - if(_MSVC_IDE_VERSION GREATER_EQUAL 10) - set(_MFC_DLL_VERSION ${_MSVC_DLL_VERSION}) - set(_MFC_IDE_VERSION ${_MSVC_IDE_VERSION}) - endif() - - if(_MFC_DLL_VERSION) - set(v "${_MFC_DLL_VERSION}") - set(vs "${_MFC_IDE_VERSION}") - - # Starting with VS 15 the MFC DLLs may be in a different directory. - if (NOT vs VERSION_LESS 15) - file(GLOB _MSVC_REDIST_DIRS "${MSVC_REDIST_DIR}/../*") - find_path(MSVC_REDIST_MFC_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.MFC - PATHS ${_MSVC_REDIST_DIRS} NO_DEFAULT_PATH) - mark_as_advanced(MSVC_REDIST_MFC_DIR) - unset(_MSVC_REDIST_DIRS) - else() - set(MSVC_REDIST_MFC_DIR "${MSVC_REDIST_DIR}") - endif() - - # Multi-Byte Character Set versions of MFC are available as optional - # addon since Visual Studio 12. So for version 12 or higher, check - # whether they are available and exclude them if they are not. - - if(CMAKE_INSTALL_DEBUG_LIBRARIES) - set(MSVC_MFC_DIR - "${MSVC_REDIST_MFC_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.DebugMFC") - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/mfc${v}ud.dll" - "${MSVC_MFC_DIR}/mfcm${v}ud.dll" - ) - if("${v}" LESS 12 OR EXISTS "${MSVC_MFC_DIR}/mfc${v}d.dll") - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/mfc${v}d.dll" - ) - endif() - if("${v}" LESS 12 OR EXISTS "${MSVC_MFC_DIR}/mfcm${v}d.dll") - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/mfcm${v}d.dll" - ) - endif() - endif() - - set(MSVC_MFC_DIR "${MSVC_REDIST_MFC_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.MFC") - if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/mfc${v}u.dll" - "${MSVC_MFC_DIR}/mfcm${v}u.dll" - ) - if("${v}" LESS 12 OR EXISTS "${MSVC_MFC_DIR}/mfc${v}.dll") - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/mfc${v}.dll" - ) - endif() - if("${v}" LESS 12 OR EXISTS "${MSVC_MFC_DIR}/mfcm${v}.dll") - set(__install__libs ${__install__libs} - "${MSVC_MFC_DIR}/mfcm${v}.dll" - ) - endif() - endif() - - # include the language dll's as well as the actual dll's - set(MSVC_MFCLOC_DIR "${MSVC_REDIST_MFC_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.MFCLOC") - set(__install__libs ${__install__libs} - "${MSVC_MFCLOC_DIR}/mfc${v}chs.dll" - "${MSVC_MFCLOC_DIR}/mfc${v}cht.dll" - "${MSVC_MFCLOC_DIR}/mfc${v}deu.dll" - "${MSVC_MFCLOC_DIR}/mfc${v}enu.dll" - "${MSVC_MFCLOC_DIR}/mfc${v}esn.dll" - "${MSVC_MFCLOC_DIR}/mfc${v}fra.dll" - "${MSVC_MFCLOC_DIR}/mfc${v}ita.dll" - "${MSVC_MFCLOC_DIR}/mfc${v}jpn.dll" - "${MSVC_MFCLOC_DIR}/mfc${v}kor.dll" - "${MSVC_MFCLOC_DIR}/mfc${v}rus.dll" - ) - endif() - endif() - - # MSVC 8 was the first version with OpenMP - # Furthermore, there is no debug version of this - if(CMAKE_INSTALL_OPENMP_LIBRARIES AND _IRSL_HAVE_MSVC) - set(_MSOMP_DLL_VERSION ${_MSVC_DLL_VERSION}) - set(_MSOMP_IDE_VERSION ${_MSVC_IDE_VERSION}) - - if(_MSOMP_DLL_VERSION) - set(v "${_MSOMP_DLL_VERSION}") - set(vs "${_MSOMP_IDE_VERSION}") - set(MSVC_OPENMP_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.OPENMP") - - if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) - set(__install__libs ${__install__libs} - "${MSVC_OPENMP_DIR}/vcomp${v}.dll") - endif() - endif() - endif() - - foreach(lib - ${__install__libs} - ) - if(EXISTS ${lib}) - set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS - ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} ${lib}) - else() - if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) - message(WARNING "system runtime library file does not exist: '${lib}'") - # This warning indicates an incomplete Visual Studio installation - # or a bug somewhere above here in this file. - # If you would like to avoid this warning, fix the real problem, or - # set CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS before including - # this file. - endif() - endif() - endforeach() -endif() - -if(_IRSL_HAVE_Intel) - unset(__install_libs) - if(CMAKE_INSTALL_OPENMP_LIBRARIES) - if(WIN32) - list(APPEND __install_libs "${_Intel_redistdir}/libiomp5md.dll" "${_Intel_redistdir}/libiompstubs5md.dll") - elseif(APPLE) - list(APPEND __install_libs "${_Intel_redistdir}/libiomp5.dylib" "${_Intel_redistdir}/libiompstubs5.dylib") - else() - list(APPEND __install_libs "${_Intel_redistdir}/libiomp5.so" "${_Intel_redistdir}/libiompstubs5.so") - if(_Intel_compiler_ver VERSION_LESS 17) - list(APPEND __install_libs "${_Intel_redistdir}/libomp_db.so") - endif() - if(_Intel_compiler_ver VERSION_LESS 13) - list(APPEND __install_libs "${_Intel_redistdir}/libiompprof5.so") - endif() - endif() - endif() - if(WIN32) - set(__install_dirs "${_Intel_redistdir}/1033") - if(EXISTS "${_Intel_redistdir}/1041") - list(APPEND __install_dirs "${_Intel_redistdir}/1041") - endif() - if(_Intel_compiler_ver VERSION_LESS 18) - list(APPEND __install_dirs "${_Intel_redistdir}/irml" "${_Intel_redistdir}/irml_c") - endif() - foreach(__Intel_lib IN ITEMS cilkrts20.dll libchkp.dll libioffload_host.dll libirngmd.dll - libmmd.dll libmmdd.dll libmpx.dll liboffload.dll svml_dispmd.dll) - - list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") - endforeach() - if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel) - list(APPEND __install_libs "${_Intel_redistdir}/libgfxoffload.dll") - endif() - if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) - foreach(__Intel_lib IN ITEMS ifdlg100.dll libicaf.dll libifcoremd.dll libifcoremdd.dll libifcorert.dll libifcorertd.dll libifportmd.dll) - - list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") - endforeach() - endif() - elseif(APPLE) - foreach(__Intel_lib IN ITEMS libchkp.dylib libcilkrts.5.dylib libcilkrts.dylib libimf.dylib libintlc.dylib libirc.dylib libirng.dylib libsvml.dylib) - list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") - endforeach() - if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel) - if(_Intel_compiler_ver VERSION_LESS 17) - list(APPEND __install_libs "${_Intel_redistdir}/libistrconv.dylib") - endif() - endif() - if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) - foreach(__Intel_lib IN ITEMS libifcore.dylib libifcoremt.dylib libifport.dylib libifportmt.dylib) - - list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") - endforeach() - endif() - else() - foreach(__Intel_lib IN ITEMS libchkp.so libcilkrts.so libcilkrts.so.5 libimf.so libintlc.so libintlc.so.5 libirc.so libpdbx.so libpdbx.so.5 libsvml.so) - - list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") - endforeach() - if(_Intel_compiler_ver VERSION_GREATER_EQUAL 13) - foreach(__Intel_lib IN ITEMS libirng.so liboffload.so liboffload.so.5) - - list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") - endforeach() - endif() - if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel) - set(__install_dirs "${_Intel_redistdir}/irml") - list(APPEND __install_libs "${_Intel_redistdir}/cilk_db.so") - if(_Intel_compiler_ver VERSION_GREATER_EQUAL 15) - list(APPEND __install_libs "${_Intel_redistdir}/libistrconv.so" "${_Intel_redistdir}/libgfxoffload.so") - endif() - endif() - if(_Intel_compiler_ver VERSION_GREATER_EQUAL 16) - foreach(__Intel_lib IN ITEMS libioffload_host.so libioffload_host.so.5 libioffload_target.so libioffload_target.so.5 libmpx.so offload_main) - - list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") - endforeach() - endif() - if(_Intel_compiler_ver VERSION_LESS 15) - foreach(__Intel_lib IN ITEMS libcxaguard.so libcxaguard.so.5) - - list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") - endforeach() - endif() - if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) - foreach(__Intel_lib IN ITEMS libicaf.so libifcore.so libifcore.so.5 libifcoremt.so libifcoremt.so.5 libifport.so libifport.so.5) - - list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") - endforeach() - endif() - endif() - - foreach(lib IN LISTS __install_libs) - if(EXISTS ${lib}) - list(APPEND CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ${lib}) - else() - if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) - message(WARNING "system runtime library file does not exist: '${lib}'") - endif() - endif() - endforeach() - - foreach(dir IN LISTS __install_dirs) - if(EXISTS ${dir}) - list(APPEND CMAKE_INSTALL_SYSTEM_RUNTIME_DIRECTORIES ${dir}) - else() - if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) - message(WARNING "system runtime library file does not exist: '${dir}'") - endif() - endif() - endforeach() -endif() - -if(WATCOM) - get_filename_component( CompilerPath ${CMAKE_C_COMPILER} PATH ) - if(CMAKE_C_COMPILER_VERSION) - set(_compiler_version ${CMAKE_C_COMPILER_VERSION}) - else() - set(_compiler_version ${CMAKE_CXX_COMPILER_VERSION}) - endif() - string(REGEX MATCHALL "[0-9]+" _watcom_version_list "${_compiler_version}") - list(GET _watcom_version_list 0 _watcom_major) - list(GET _watcom_version_list 1 _watcom_minor) - set( __install__libs - ${CompilerPath}/clbr${_watcom_major}${_watcom_minor}.dll - ${CompilerPath}/mt7r${_watcom_major}${_watcom_minor}.dll - ${CompilerPath}/plbr${_watcom_major}${_watcom_minor}.dll ) - foreach(lib - ${__install__libs} - ) - if(EXISTS ${lib}) - set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS - ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} ${lib}) - else() - if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) - message(WARNING "system runtime library file does not exist: '${lib}'") - # This warning indicates an incomplete Watcom installation - # or a bug somewhere above here in this file. - # If you would like to avoid this warning, fix the real problem, or - # set CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS before including - # this file. - endif() - endif() - endforeach() -endif() - - -# Include system runtime libraries in the installation if any are -# specified by CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS. -if(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS) - if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP) - if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION) - if(WIN32) - set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION bin) - else() - set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION lib) - endif() - endif() - if(CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT) - set(_CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT - COMPONENT ${CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT}) - endif() - install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} - DESTINATION ${CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION} - ${_CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT} - ) - - install(DIRECTORY ${CMAKE_INSTALL_SYSTEM_RUNTIME_DIRECTORIES} - DESTINATION ${CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION} - ${_CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT} - ) - endif() -endif() - -cmake_policy(POP) +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +InstallRequiredSystemLibraries +------------------------------ + +Include this module to search for compiler-provided system runtime +libraries and add install rules for them. Some optional variables +may be set prior to including the module to adjust behavior: + +``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS`` + Specify additional runtime libraries that may not be detected. + After inclusion any detected libraries will be appended to this. + +``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP`` + Set to TRUE to skip calling the :command:`install(PROGRAMS)` command to + allow the includer to specify its own install rule, using the value of + ``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS`` to get the list of libraries. + +``CMAKE_INSTALL_DEBUG_LIBRARIES`` + Set to TRUE to install the debug runtime libraries when available + with MSVC tools. + +``CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY`` + Set to TRUE to install only the debug runtime libraries with MSVC + tools even if the release runtime libraries are also available. + +``CMAKE_INSTALL_UCRT_LIBRARIES`` + Set to TRUE to install the Windows Universal CRT libraries for + app-local deployment (e.g. to Windows XP). This is meaningful + only with MSVC from Visual Studio 2015 or higher. + + One may set a ``CMAKE_WINDOWS_KITS_10_DIR`` *environment variable* + to an absolute path to tell CMake to look for Windows 10 SDKs in + a custom location. The specified directory is expected to contain + ``Redist/ucrt/DLLs/*`` directories. + +``CMAKE_INSTALL_MFC_LIBRARIES`` + Set to TRUE to install the MSVC MFC runtime libraries. + +``CMAKE_INSTALL_OPENMP_LIBRARIES`` + Set to TRUE to install the MSVC OpenMP runtime libraries + +``CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION`` + Specify the :command:`install(PROGRAMS)` command ``DESTINATION`` + option. If not specified, the default is ``bin`` on Windows + and ``lib`` elsewhere. + +``CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS`` + Set to TRUE to disable warnings about required library files that + do not exist. (For example, Visual Studio Express editions may + not provide the redistributable files.) + +``CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT`` + Specify the :command:`install(PROGRAMS)` command ``COMPONENT`` + option. If not specified, no such option will be used. +#]=======================================================================] + +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced + +set(_IRSL_HAVE_Intel FALSE) +set(_IRSL_HAVE_MSVC FALSE) +foreach(LANG IN ITEMS C CXX Fortran) + if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Intel") + if(NOT _IRSL_HAVE_Intel) + get_filename_component(_Intel_basedir "${CMAKE_${LANG}_COMPILER}" PATH) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_Intel_archdir intel64) + else() + set(_Intel_archdir x86) + endif() + set(_Intel_compiler_ver ${CMAKE_${LANG}_COMPILER_VERSION}) + if(WIN32) + get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../redist/${_Intel_archdir}/compiler" ABSOLUTE) + elseif(APPLE) + get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib" ABSOLUTE) + else() + if(EXISTS "${_Intel_basedir}/../lib/${_Intel_archdir}_lin") + get_filename_component(_Intel_redistdir "${_Intel_basedir}/../lib/${_Intel_archdir}" ABSOLUTE) + else() + get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib/${_Intel_archdir}_lin" ABSOLUTE) + endif() + endif() + set(_IRSL_HAVE_Intel TRUE) + endif() + elseif("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "MSVC") + set(_IRSL_HAVE_MSVC TRUE) + endif() +endforeach() + +if(MSVC) + file(TO_CMAKE_PATH "$ENV{SYSTEMROOT}" SYSTEMROOT) + + if(CMAKE_CL_64) + if(MSVC_VERSION GREATER 1599) + # VS 10 and later: + set(CMAKE_MSVC_ARCH x64) + else() + # VS 9 and earlier: + set(CMAKE_MSVC_ARCH amd64) + endif() + else() + set(CMAKE_MSVC_ARCH x86) + endif() + + get_filename_component(devenv_dir "${CMAKE_MAKE_PROGRAM}" PATH) + get_filename_component(base_dir "${devenv_dir}/../.." ABSOLUTE) + + if(MSVC_VERSION EQUAL 1300) + set(__install__libs + "${SYSTEMROOT}/system32/msvcp70.dll" + "${SYSTEMROOT}/system32/msvcr70.dll" + ) + endif() + + if(MSVC_VERSION EQUAL 1310) + set(__install__libs + "${SYSTEMROOT}/system32/msvcp71.dll" + "${SYSTEMROOT}/system32/msvcr71.dll" + ) + endif() + + if(MSVC_TOOLSET_VERSION EQUAL 80) + # Find the runtime library redistribution directory. + get_filename_component(msvc_install_dir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0;InstallDir]" ABSOLUTE) + if(DEFINED MSVC80_REDIST_DIR AND EXISTS "${MSVC80_REDIST_DIR}") + set(MSVC_REDIST_DIR "${MSVC80_REDIST_DIR}") # use old cache entry + endif() + find_path(MSVC_REDIST_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest + PATHS + "${msvc_install_dir}/../../VC/redist" + "${base_dir}/VC/redist" + ) + mark_as_advanced(MSVC_REDIST_DIR) + set(MSVC_CRT_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC80.CRT") + + # Install the manifest that allows DLLs to be loaded from the + # directory containing the executable. + if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) + set(__install__libs + "${MSVC_CRT_DIR}/Microsoft.VC80.CRT.manifest" + "${MSVC_CRT_DIR}/msvcm80.dll" + "${MSVC_CRT_DIR}/msvcp80.dll" + "${MSVC_CRT_DIR}/msvcr80.dll" + ) + else() + set(__install__libs) + endif() + + if(CMAKE_INSTALL_DEBUG_LIBRARIES) + set(MSVC_CRT_DIR + "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.VC80.DebugCRT") + set(__install__libs ${__install__libs} + "${MSVC_CRT_DIR}/Microsoft.VC80.DebugCRT.manifest" + "${MSVC_CRT_DIR}/msvcm80d.dll" + "${MSVC_CRT_DIR}/msvcp80d.dll" + "${MSVC_CRT_DIR}/msvcr80d.dll" + ) + endif() + endif() + + if(MSVC_TOOLSET_VERSION EQUAL 90) + # Find the runtime library redistribution directory. + get_filename_component(msvc_install_dir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0;InstallDir]" ABSOLUTE) + get_filename_component(msvc_express_install_dir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\9.0;InstallDir]" ABSOLUTE) + if(DEFINED MSVC90_REDIST_DIR AND EXISTS "${MSVC90_REDIST_DIR}") + set(MSVC_REDIST_DIR "${MSVC90_REDIST_DIR}") # use old cache entry + endif() + find_path(MSVC_REDIST_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest + PATHS + "${msvc_install_dir}/../../VC/redist" + "${msvc_express_install_dir}/../../VC/redist" + "${base_dir}/VC/redist" + ) + mark_as_advanced(MSVC_REDIST_DIR) + set(MSVC_CRT_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC90.CRT") + + # Install the manifest that allows DLLs to be loaded from the + # directory containing the executable. + if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) + set(__install__libs + "${MSVC_CRT_DIR}/Microsoft.VC90.CRT.manifest" + "${MSVC_CRT_DIR}/msvcm90.dll" + "${MSVC_CRT_DIR}/msvcp90.dll" + "${MSVC_CRT_DIR}/msvcr90.dll" + ) + else() + set(__install__libs) + endif() + + if(CMAKE_INSTALL_DEBUG_LIBRARIES) + set(MSVC_CRT_DIR + "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.VC90.DebugCRT") + set(__install__libs ${__install__libs} + "${MSVC_CRT_DIR}/Microsoft.VC90.DebugCRT.manifest" + "${MSVC_CRT_DIR}/msvcm90d.dll" + "${MSVC_CRT_DIR}/msvcp90d.dll" + "${MSVC_CRT_DIR}/msvcr90d.dll" + ) + endif() + endif() + + set(MSVC_REDIST_NAME "") + set(_MSVC_DLL_VERSION "") + set(_MSVC_IDE_VERSION "") + if(MSVC_VERSION GREATER_EQUAL 2000) + message(WARNING "MSVC ${MSVC_VERSION} not yet supported.") + elseif(MSVC_VERSION_VERSION GREATER_EQUAL 143) + message(WARNING "MSVC toolset v${MSVC_VERSION_VERSION} not yet supported.") + elseif(MSVC_TOOLSET_VERSION EQUAL 142) + set(MSVC_REDIST_NAME VC142) + set(_MSVC_DLL_VERSION 140) + set(_MSVC_IDE_VERSION 16) + elseif(MSVC_TOOLSET_VERSION EQUAL 141) + set(MSVC_REDIST_NAME VC142) + set(_MSVC_DLL_VERSION 140) + set(_MSVC_IDE_VERSION 16) + elseif(MSVC_TOOLSET_VERSION) + set(MSVC_REDIST_NAME VC${MSVC_TOOLSET_VERSION}) + math(EXPR _MSVC_DLL_VERSION "${MSVC_TOOLSET_VERSION} / 10 * 10") + math(EXPR _MSVC_IDE_VERSION "${MSVC_TOOLSET_VERSION} / 10") + endif() + + set(_MSVCRT_DLL_VERSION "") + set(_MSVCRT_IDE_VERSION "") + if(_MSVC_IDE_VERSION GREATER_EQUAL 10) + set(_MSVCRT_DLL_VERSION "${_MSVC_DLL_VERSION}") + set(_MSVCRT_IDE_VERSION "${_MSVC_IDE_VERSION}") + endif() + + if(_MSVCRT_DLL_VERSION) + set(v "${_MSVCRT_DLL_VERSION}") + set(vs "${_MSVCRT_IDE_VERSION}") + + # Find the runtime library redistribution directory. + if(vs VERSION_LESS 15 AND DEFINED MSVC${vs}_REDIST_DIR AND EXISTS "${MSVC${vs}_REDIST_DIR}") + set(MSVC_REDIST_DIR "${MSVC${vs}_REDIST_DIR}") # use old cache entry + endif() + if(NOT vs VERSION_LESS 15) + set(_vs_redist_paths "") + cmake_host_system_information(RESULT _vs_dir QUERY VS_${vs}_DIR) # undocumented query + if(IS_DIRECTORY "${_vs_dir}") + file(GLOB _vs_redist_paths "${_vs_dir}/VC/Redist/MSVC/*") + endif() + unset(_vs_dir) + else() + get_filename_component(_vs_dir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${vs}.0;InstallDir]" ABSOLUTE) + set(programfilesx86 "ProgramFiles(x86)") + set(_vs_redist_paths + "${_vs_dir}/../../VC/redist" + "${base_dir}/VC/redist" + "$ENV{ProgramFiles}/Microsoft Visual Studio ${vs}.0/VC/redist" + "$ENV{${programfilesx86}}/Microsoft Visual Studio ${vs}.0/VC/redist" + ) + unset(_vs_dir) + unset(programfilesx86) + endif() + find_path(MSVC_REDIST_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.CRT PATHS ${_vs_redist_paths}) + unset(_vs_redist_paths) + mark_as_advanced(MSVC_REDIST_DIR) + set(MSVC_CRT_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.CRT") + + if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) + set(__install__libs + "${MSVC_CRT_DIR}/msvcp${v}.dll" + ) + if(NOT vs VERSION_LESS 14) + file(GLOB __msvcr_dlls "${MSVC_CRT_DIR}/*.dll") + list(APPEND __install__libs ${__msvcr_dlls}) + else() + list(APPEND __install__libs "${MSVC_CRT_DIR}/msvcr${v}.dll") + endif() + else() + set(__install__libs) + endif() + + if(CMAKE_INSTALL_DEBUG_LIBRARIES) + set(MSVC_CRT_DIR + "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.DebugCRT") + set(__install__libs ${__install__libs} + "${MSVC_CRT_DIR}/msvcp${v}d.dll" + ) + if(NOT vs VERSION_LESS 14) + list(APPEND __install__libs + "${MSVC_CRT_DIR}/vcruntime${v}d.dll" + "${MSVC_CRT_DIR}/concrt${v}d.dll" + ) + else() + list(APPEND __install__libs "${MSVC_CRT_DIR}/msvcr${v}d.dll") + endif() + endif() + + if(CMAKE_INSTALL_UCRT_LIBRARIES AND NOT vs VERSION_LESS 14) + # Find the Windows Kits directory. + get_filename_component(windows_kits_dir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots;KitsRoot10]" ABSOLUTE) + set(programfilesx86 "ProgramFiles(x86)") + if(";${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION};$ENV{UCRTVersion};$ENV{WindowsSDKVersion};" MATCHES [=[;(10\.[0-9.]+)[;\]]=]) + set(__ucrt_version "${CMAKE_MATCH_1}/") + else() + set(__ucrt_version "") + endif() + find_path(WINDOWS_KITS_DIR + NAMES + Redist/${__ucrt_version}ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll + Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll + PATHS + $ENV{CMAKE_WINDOWS_KITS_10_DIR} + "${windows_kits_dir}" + "$ENV{ProgramFiles}/Windows Kits/10" + "$ENV{${programfilesx86}}/Windows Kits/10" + ) + mark_as_advanced(WINDOWS_KITS_DIR) + + # Glob the list of UCRT DLLs. + if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) + if(EXISTS "${WINDOWS_KITS_DIR}/Redist/${__ucrt_version}ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll") + file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/Redist/${__ucrt_version}ucrt/DLLs/${CMAKE_MSVC_ARCH}/*.dll") + else() + file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/*.dll") + endif() + list(APPEND __install__libs ${__ucrt_dlls}) + endif() + if(CMAKE_INSTALL_DEBUG_LIBRARIES) + if(EXISTS "${WINDOWS_KITS_DIR}/bin/${__ucrt_version}${CMAKE_MSVC_ARCH}/ucrt/ucrtbased.dll") + file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/bin/${__ucrt_version}${CMAKE_MSVC_ARCH}/ucrt/*.dll") + else() + file(GLOB __ucrt_dlls "${WINDOWS_KITS_DIR}/bin/${CMAKE_MSVC_ARCH}/ucrt/*.dll") + endif() + list(APPEND __install__libs ${__ucrt_dlls}) + endif() + endif() + endif() + + if(CMAKE_INSTALL_MFC_LIBRARIES) + if(MSVC_VERSION EQUAL 1300) + set(__install__libs ${__install__libs} + "${SYSTEMROOT}/system32/mfc70.dll" + ) + endif() + + if(MSVC_VERSION EQUAL 1310) + set(__install__libs ${__install__libs} + "${SYSTEMROOT}/system32/mfc71.dll" + ) + endif() + + if(MSVC_VERSION EQUAL 1400) + if(CMAKE_INSTALL_DEBUG_LIBRARIES) + set(MSVC_MFC_DIR + "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.VC80.DebugMFC") + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/Microsoft.VC80.DebugMFC.manifest" + "${MSVC_MFC_DIR}/mfc80d.dll" + "${MSVC_MFC_DIR}/mfc80ud.dll" + "${MSVC_MFC_DIR}/mfcm80d.dll" + "${MSVC_MFC_DIR}/mfcm80ud.dll" + ) + endif() + + set(MSVC_MFC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC80.MFC") + # Install the manifest that allows DLLs to be loaded from the + # directory containing the executable. + if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/Microsoft.VC80.MFC.manifest" + "${MSVC_MFC_DIR}/mfc80.dll" + "${MSVC_MFC_DIR}/mfc80u.dll" + "${MSVC_MFC_DIR}/mfcm80.dll" + "${MSVC_MFC_DIR}/mfcm80u.dll" + ) + endif() + + # include the language dll's for vs8 as well as the actual dll's + set(MSVC_MFCLOC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC80.MFCLOC") + # Install the manifest that allows DLLs to be loaded from the + # directory containing the executable. + set(__install__libs ${__install__libs} + "${MSVC_MFCLOC_DIR}/Microsoft.VC80.MFCLOC.manifest" + "${MSVC_MFCLOC_DIR}/mfc80chs.dll" + "${MSVC_MFCLOC_DIR}/mfc80cht.dll" + "${MSVC_MFCLOC_DIR}/mfc80enu.dll" + "${MSVC_MFCLOC_DIR}/mfc80esp.dll" + "${MSVC_MFCLOC_DIR}/mfc80deu.dll" + "${MSVC_MFCLOC_DIR}/mfc80fra.dll" + "${MSVC_MFCLOC_DIR}/mfc80ita.dll" + "${MSVC_MFCLOC_DIR}/mfc80jpn.dll" + "${MSVC_MFCLOC_DIR}/mfc80kor.dll" + ) + endif() + + if(MSVC_VERSION EQUAL 1500) + if(CMAKE_INSTALL_DEBUG_LIBRARIES) + set(MSVC_MFC_DIR + "${MSVC_REDIST_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.VC90.DebugMFC") + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/Microsoft.VC90.DebugMFC.manifest" + "${MSVC_MFC_DIR}/mfc90d.dll" + "${MSVC_MFC_DIR}/mfc90ud.dll" + "${MSVC_MFC_DIR}/mfcm90d.dll" + "${MSVC_MFC_DIR}/mfcm90ud.dll" + ) + endif() + + set(MSVC_MFC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC90.MFC") + # Install the manifest that allows DLLs to be loaded from the + # directory containing the executable. + if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/Microsoft.VC90.MFC.manifest" + "${MSVC_MFC_DIR}/mfc90.dll" + "${MSVC_MFC_DIR}/mfc90u.dll" + "${MSVC_MFC_DIR}/mfcm90.dll" + "${MSVC_MFC_DIR}/mfcm90u.dll" + ) + endif() + + # include the language dll's for vs9 as well as the actual dll's + set(MSVC_MFCLOC_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.VC90.MFCLOC") + # Install the manifest that allows DLLs to be loaded from the + # directory containing the executable. + set(__install__libs ${__install__libs} + "${MSVC_MFCLOC_DIR}/Microsoft.VC90.MFCLOC.manifest" + "${MSVC_MFCLOC_DIR}/mfc90chs.dll" + "${MSVC_MFCLOC_DIR}/mfc90cht.dll" + "${MSVC_MFCLOC_DIR}/mfc90enu.dll" + "${MSVC_MFCLOC_DIR}/mfc90esp.dll" + "${MSVC_MFCLOC_DIR}/mfc90deu.dll" + "${MSVC_MFCLOC_DIR}/mfc90fra.dll" + "${MSVC_MFCLOC_DIR}/mfc90ita.dll" + "${MSVC_MFCLOC_DIR}/mfc90jpn.dll" + "${MSVC_MFCLOC_DIR}/mfc90kor.dll" + ) + endif() + + set(_MFC_DLL_VERSION "") + set(_MFC_IDE_VERSION "") + if(_MSVC_IDE_VERSION GREATER_EQUAL 10) + set(_MFC_DLL_VERSION ${_MSVC_DLL_VERSION}) + set(_MFC_IDE_VERSION ${_MSVC_IDE_VERSION}) + endif() + + if(_MFC_DLL_VERSION) + set(v "${_MFC_DLL_VERSION}") + set(vs "${_MFC_IDE_VERSION}") + + # Starting with VS 15 the MFC DLLs may be in a different directory. + if (NOT vs VERSION_LESS 15) + file(GLOB _MSVC_REDIST_DIRS "${MSVC_REDIST_DIR}/../*") + find_path(MSVC_REDIST_MFC_DIR NAMES ${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.MFC + PATHS ${_MSVC_REDIST_DIRS} NO_DEFAULT_PATH) + mark_as_advanced(MSVC_REDIST_MFC_DIR) + unset(_MSVC_REDIST_DIRS) + else() + set(MSVC_REDIST_MFC_DIR "${MSVC_REDIST_DIR}") + endif() + + # Multi-Byte Character Set versions of MFC are available as optional + # addon since Visual Studio 12. So for version 12 or higher, check + # whether they are available and exclude them if they are not. + + if(CMAKE_INSTALL_DEBUG_LIBRARIES) + set(MSVC_MFC_DIR + "${MSVC_REDIST_MFC_DIR}/Debug_NonRedist/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.DebugMFC") + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/mfc${v}ud.dll" + "${MSVC_MFC_DIR}/mfcm${v}ud.dll" + ) + if("${v}" LESS 12 OR EXISTS "${MSVC_MFC_DIR}/mfc${v}d.dll") + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/mfc${v}d.dll" + ) + endif() + if("${v}" LESS 12 OR EXISTS "${MSVC_MFC_DIR}/mfcm${v}d.dll") + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/mfcm${v}d.dll" + ) + endif() + endif() + + set(MSVC_MFC_DIR "${MSVC_REDIST_MFC_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.MFC") + if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/mfc${v}u.dll" + "${MSVC_MFC_DIR}/mfcm${v}u.dll" + ) + if("${v}" LESS 12 OR EXISTS "${MSVC_MFC_DIR}/mfc${v}.dll") + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/mfc${v}.dll" + ) + endif() + if("${v}" LESS 12 OR EXISTS "${MSVC_MFC_DIR}/mfcm${v}.dll") + set(__install__libs ${__install__libs} + "${MSVC_MFC_DIR}/mfcm${v}.dll" + ) + endif() + endif() + + # include the language dll's as well as the actual dll's + set(MSVC_MFCLOC_DIR "${MSVC_REDIST_MFC_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.MFCLOC") + set(__install__libs ${__install__libs} + "${MSVC_MFCLOC_DIR}/mfc${v}chs.dll" + "${MSVC_MFCLOC_DIR}/mfc${v}cht.dll" + "${MSVC_MFCLOC_DIR}/mfc${v}deu.dll" + "${MSVC_MFCLOC_DIR}/mfc${v}enu.dll" + "${MSVC_MFCLOC_DIR}/mfc${v}esn.dll" + "${MSVC_MFCLOC_DIR}/mfc${v}fra.dll" + "${MSVC_MFCLOC_DIR}/mfc${v}ita.dll" + "${MSVC_MFCLOC_DIR}/mfc${v}jpn.dll" + "${MSVC_MFCLOC_DIR}/mfc${v}kor.dll" + "${MSVC_MFCLOC_DIR}/mfc${v}rus.dll" + ) + endif() + endif() + + # MSVC 8 was the first version with OpenMP + # Furthermore, there is no debug version of this + if(CMAKE_INSTALL_OPENMP_LIBRARIES AND _IRSL_HAVE_MSVC) + set(_MSOMP_DLL_VERSION ${_MSVC_DLL_VERSION}) + set(_MSOMP_IDE_VERSION ${_MSVC_IDE_VERSION}) + + if(_MSOMP_DLL_VERSION) + set(v "${_MSOMP_DLL_VERSION}") + set(vs "${_MSOMP_IDE_VERSION}") + set(MSVC_OPENMP_DIR "${MSVC_REDIST_DIR}/${CMAKE_MSVC_ARCH}/Microsoft.${MSVC_REDIST_NAME}.OPENMP") + + if(NOT CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY) + set(__install__libs ${__install__libs} + "${MSVC_OPENMP_DIR}/vcomp${v}.dll") + endif() + endif() + endif() + + foreach(lib + ${__install__libs} + ) + if(EXISTS ${lib}) + set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS + ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} ${lib}) + else() + if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) + message(WARNING "system runtime library file does not exist: '${lib}'") + # This warning indicates an incomplete Visual Studio installation + # or a bug somewhere above here in this file. + # If you would like to avoid this warning, fix the real problem, or + # set CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS before including + # this file. + endif() + endif() + endforeach() +endif() + +if(_IRSL_HAVE_Intel) + unset(__install_libs) + if(CMAKE_INSTALL_OPENMP_LIBRARIES) + if(WIN32) + list(APPEND __install_libs "${_Intel_redistdir}/libiomp5md.dll" "${_Intel_redistdir}/libiompstubs5md.dll") + elseif(APPLE) + list(APPEND __install_libs "${_Intel_redistdir}/libiomp5.dylib" "${_Intel_redistdir}/libiompstubs5.dylib") + else() + list(APPEND __install_libs "${_Intel_redistdir}/libiomp5.so" "${_Intel_redistdir}/libiompstubs5.so") + if(_Intel_compiler_ver VERSION_LESS 17) + list(APPEND __install_libs "${_Intel_redistdir}/libomp_db.so") + endif() + if(_Intel_compiler_ver VERSION_LESS 13) + list(APPEND __install_libs "${_Intel_redistdir}/libiompprof5.so") + endif() + endif() + endif() + if(WIN32) + set(__install_dirs "${_Intel_redistdir}/1033") + if(EXISTS "${_Intel_redistdir}/1041") + list(APPEND __install_dirs "${_Intel_redistdir}/1041") + endif() + if(_Intel_compiler_ver VERSION_LESS 18) + list(APPEND __install_dirs "${_Intel_redistdir}/irml" "${_Intel_redistdir}/irml_c") + endif() + foreach(__Intel_lib IN ITEMS cilkrts20.dll libchkp.dll libioffload_host.dll libirngmd.dll + libmmd.dll libmmdd.dll libmpx.dll liboffload.dll svml_dispmd.dll) + + list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") + endforeach() + if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel) + list(APPEND __install_libs "${_Intel_redistdir}/libgfxoffload.dll") + endif() + if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) + foreach(__Intel_lib IN ITEMS ifdlg100.dll libicaf.dll libifcoremd.dll libifcoremdd.dll libifcorert.dll libifcorertd.dll libifportmd.dll) + + list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") + endforeach() + endif() + elseif(APPLE) + foreach(__Intel_lib IN ITEMS libchkp.dylib libcilkrts.5.dylib libcilkrts.dylib libimf.dylib libintlc.dylib libirc.dylib libirng.dylib libsvml.dylib) + list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") + endforeach() + if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel) + if(_Intel_compiler_ver VERSION_LESS 17) + list(APPEND __install_libs "${_Intel_redistdir}/libistrconv.dylib") + endif() + endif() + if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) + foreach(__Intel_lib IN ITEMS libifcore.dylib libifcoremt.dylib libifport.dylib libifportmt.dylib) + + list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") + endforeach() + endif() + else() + foreach(__Intel_lib IN ITEMS libchkp.so libcilkrts.so libcilkrts.so.5 libimf.so libintlc.so libintlc.so.5 libirc.so libpdbx.so libpdbx.so.5 libsvml.so) + + list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") + endforeach() + if(_Intel_compiler_ver VERSION_GREATER_EQUAL 13) + foreach(__Intel_lib IN ITEMS libirng.so liboffload.so liboffload.so.5) + + list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") + endforeach() + endif() + if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel) + set(__install_dirs "${_Intel_redistdir}/irml") + list(APPEND __install_libs "${_Intel_redistdir}/cilk_db.so") + if(_Intel_compiler_ver VERSION_GREATER_EQUAL 15) + list(APPEND __install_libs "${_Intel_redistdir}/libistrconv.so" "${_Intel_redistdir}/libgfxoffload.so") + endif() + endif() + if(_Intel_compiler_ver VERSION_GREATER_EQUAL 16) + foreach(__Intel_lib IN ITEMS libioffload_host.so libioffload_host.so.5 libioffload_target.so libioffload_target.so.5 libmpx.so offload_main) + + list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") + endforeach() + endif() + if(_Intel_compiler_ver VERSION_LESS 15) + foreach(__Intel_lib IN ITEMS libcxaguard.so libcxaguard.so.5) + + list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") + endforeach() + endif() + if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) + foreach(__Intel_lib IN ITEMS libicaf.so libifcore.so libifcore.so.5 libifcoremt.so libifcoremt.so.5 libifport.so libifport.so.5) + + list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}") + endforeach() + endif() + endif() + + foreach(lib IN LISTS __install_libs) + if(EXISTS ${lib}) + list(APPEND CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ${lib}) + else() + if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) + message(WARNING "system runtime library file does not exist: '${lib}'") + endif() + endif() + endforeach() + + foreach(dir IN LISTS __install_dirs) + if(EXISTS ${dir}) + list(APPEND CMAKE_INSTALL_SYSTEM_RUNTIME_DIRECTORIES ${dir}) + else() + if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) + message(WARNING "system runtime library file does not exist: '${dir}'") + endif() + endif() + endforeach() +endif() + +if(WATCOM) + get_filename_component( CompilerPath ${CMAKE_C_COMPILER} PATH ) + if(CMAKE_C_COMPILER_VERSION) + set(_compiler_version ${CMAKE_C_COMPILER_VERSION}) + else() + set(_compiler_version ${CMAKE_CXX_COMPILER_VERSION}) + endif() + string(REGEX MATCHALL "[0-9]+" _watcom_version_list "${_compiler_version}") + list(GET _watcom_version_list 0 _watcom_major) + list(GET _watcom_version_list 1 _watcom_minor) + set( __install__libs + ${CompilerPath}/clbr${_watcom_major}${_watcom_minor}.dll + ${CompilerPath}/mt7r${_watcom_major}${_watcom_minor}.dll + ${CompilerPath}/plbr${_watcom_major}${_watcom_minor}.dll ) + foreach(lib + ${__install__libs} + ) + if(EXISTS ${lib}) + set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS + ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} ${lib}) + else() + if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) + message(WARNING "system runtime library file does not exist: '${lib}'") + # This warning indicates an incomplete Watcom installation + # or a bug somewhere above here in this file. + # If you would like to avoid this warning, fix the real problem, or + # set CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS before including + # this file. + endif() + endif() + endforeach() +endif() + + +# Include system runtime libraries in the installation if any are +# specified by CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS. +if(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS) + if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP) + if(NOT CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION) + if(WIN32) + set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION bin) + else() + set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION lib) + endif() + endif() + if(CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT) + set(_CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT + COMPONENT ${CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT}) + endif() + install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} + DESTINATION ${CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION} + ${_CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT} + ) + + install(DIRECTORY ${CMAKE_INSTALL_SYSTEM_RUNTIME_DIRECTORIES} + DESTINATION ${CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION} + ${_CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT} + ) + endif() +endif() + +cmake_policy(POP) diff --git a/indra/deps/CMakeLists.txt b/indra/deps/CMakeLists.txt index 764e3a733f57e5d931ff0d64dfc90c8cbfb4de6a..1c8354ad4aedb3513e1a7eec7d2afdd77b92abca 100644 --- a/indra/deps/CMakeLists.txt +++ b/indra/deps/CMakeLists.txt @@ -1,60 +1,60 @@ -project(deps) - -include(FetchContent) - -set(CMAKE_FOLDER "Third Party") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -FetchContent_Declare( - Catch2 - GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v2.11.0 - ) -FetchContent_Declare( - fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG 6.1.2 - ) -FetchContent_Declare( - nlohmann_json - GIT_REPOSITORY https://github.com/nlohmann/json.git - GIT_TAG v3.7.3 - ) -FetchContent_Declare( - absl - GIT_REPOSITORY https://git.alchemyviewer.org/alchemy/thirdparty/abseil-cpp.git - GIT_TAG 9b9a2536d1c212d792db9eb26b670b30397ee14c -) - -# This is a hack because absl has dumb cmake -set(OLD_BUILD_TEST ${BUILD_TESTING}) -set(BUILD_TESTING OFF) -FetchContent_MakeAvailable(absl) -set(BUILD_TESTING ${OLD_BUILD_TEST}) - -# Supress warnings inside abseil under MSVC -if(WINDOWS) - target_compile_options(absl_strings PRIVATE /wd4018) - target_compile_options(absl_str_format_internal PRIVATE /wd4018) - target_compile_options(absl_flags_usage_internal PRIVATE /wd4018) -endif() - - -if (BUILD_TESTING) - FetchContent_MakeAvailable(Catch2) -endif() - -#Download the rest of the libraries -FetchContent_MakeAvailable(fmt) - -# Typically you don't care so much for a third party library's tests to be -# run from your own project's code. -set(JSON_BuildTests OFF CACHE INTERNAL "") - -# If you only include this third party in PRIVATE source files, you do not -# need to install it when your main project gets installed. -set(JSON_Install OFF CACHE INTERNAL "") -FetchContent_MakeAvailable(nlohmann_json) - -unset(CMAKE_FOLDER) -unset(CMAKE_POSITION_INDEPENDENT_CODE) +project(deps) + +include(FetchContent) + +set(CMAKE_FOLDER "Third Party") +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v2.11.0 + ) +FetchContent_Declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG 6.1.2 + ) +FetchContent_Declare( + nlohmann_json + GIT_REPOSITORY https://github.com/nlohmann/json.git + GIT_TAG v3.7.3 + ) +FetchContent_Declare( + absl + GIT_REPOSITORY https://git.alchemyviewer.org/alchemy/thirdparty/abseil-cpp.git + GIT_TAG 9b9a2536d1c212d792db9eb26b670b30397ee14c +) + +# This is a hack because absl has dumb cmake +set(OLD_BUILD_TEST ${BUILD_TESTING}) +set(BUILD_TESTING OFF) +FetchContent_MakeAvailable(absl) +set(BUILD_TESTING ${OLD_BUILD_TEST}) + +# Supress warnings inside abseil under MSVC +if(WINDOWS) + target_compile_options(absl_strings PRIVATE /wd4018) + target_compile_options(absl_str_format_internal PRIVATE /wd4018) + target_compile_options(absl_flags_usage_internal PRIVATE /wd4018) +endif() + + +if (BUILD_TESTING) + FetchContent_MakeAvailable(Catch2) +endif() + +#Download the rest of the libraries +FetchContent_MakeAvailable(fmt) + +# Typically you don't care so much for a third party library's tests to be +# run from your own project's code. +set(JSON_BuildTests OFF CACHE INTERNAL "") + +# If you only include this third party in PRIVATE source files, you do not +# need to install it when your main project gets installed. +set(JSON_Install OFF CACHE INTERNAL "") +FetchContent_MakeAvailable(nlohmann_json) + +unset(CMAKE_FOLDER) +unset(CMAKE_POSITION_INDEPENDENT_CODE) diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index fea1d4907fdbcf8a54efc22a0ede1056a7d0390d..38e392ff6c97f84f47b864e13a29f96ff62a056f 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -1,2348 +1,2348 @@ -/** - * @file llsdserialize.cpp - * @author Phoenix - * @date 2006-03-05 - * @brief Implementation of LLSD parsers and formatters - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llsdserialize.h" -#include "llwin32headerslean.h" -#include "llpointer.h" -#include "llstreamtools.h" // for fullread -#include "llbase64.h" - -#include <iostream> - -#include <boost/iostreams/device/array.hpp> -#include <boost/iostreams/stream.hpp> - -#ifdef LL_USESYSTEMLIBS -# include <zlib.h> -#else -# include "zlib/zlib.h" // for davep's dirty little zip functions -#endif - -#if !LL_WINDOWS -#include <netinet/in.h> // htonl & ntohl -#endif - -#include "lldate.h" -#include "llsd.h" -#include "llstring.h" -#include "lluri.h" - -// File constants -static const int MAX_HDR_LEN = 20; -static const S32 UNZIP_LLSD_MAX_DEPTH = 96; -static const char LEGACY_NON_HEADER[] = "<llsd>"; -const std::string LLSD_BINARY_HEADER("LLSD/Binary"); -const std::string LLSD_XML_HEADER("LLSD/XML"); - -//used to deflate a gzipped asset (currently used for navmeshes) -#define windowBits 15 -#define ENABLE_ZLIB_GZIP 32 - -/** - * LLSDSerialize - */ - -// static -void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options) -{ - LLPointer<LLSDFormatter> f = NULL; - - switch (type) - { - case LLSD_BINARY: - str << "<? " << LLSD_BINARY_HEADER << " ?>\n"; - f = new LLSDBinaryFormatter; - break; - - case LLSD_XML: - str << "<? " << LLSD_XML_HEADER << " ?>\n"; - f = new LLSDXMLFormatter; - break; - - default: - LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL; - } - - if (f.notNull()) - { - f->format(sd, str, options); - } -} - -// static -bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) -{ - LLPointer<LLSDParser> p = NULL; - char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */ - int i; - int inbuf = 0; - bool legacy_no_header = false; - bool fail_if_not_legacy = false; - std::string header; - - /* - * Get the first line before anything. - */ - str.get(hdr_buf, MAX_HDR_LEN, '\n'); - if (str.fail()) - { - str.clear(); - fail_if_not_legacy = true; - } - - if (!strnicmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ - { - legacy_no_header = true; - inbuf = (int)str.gcount(); - } - else - { - if (fail_if_not_legacy) - goto fail; - /* - * Remove the newline chars - */ - for (i = 0; i < MAX_HDR_LEN; i++) - { - if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' || - hdr_buf[i] == '\n') - { - hdr_buf[i] = 0; - break; - } - } - header = hdr_buf; - - std::string::size_type start = header.find_first_not_of("<? "); - std::string::size_type end = std::string::npos; - if (start != std::string::npos) - { - end = header.find_first_of(" ?", start); - } - if ((start == std::string::npos) || (end == std::string::npos)) - goto fail; - - header = header.substr(start, end - start); - ws(str); - } - /* - * Create the parser as appropriate - */ - if (legacy_no_header) - { // Create a LLSD XML parser, and parse the first chunk read above - LLSDXMLParser* x = new LLSDXMLParser(); - x->parsePart(hdr_buf, inbuf); // Parse the first part that was already read - x->parseLines(str, sd); // Parse the rest of it - delete x; - return true; - } - - if (header == LLSD_BINARY_HEADER) - { - p = new LLSDBinaryParser; - } - else if (header == LLSD_XML_HEADER) - { - p = new LLSDXMLParser; - } - else - { - LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL; - } - - if (p.notNull()) - { - p->parse(str, sd, max_bytes); - return true; - } - -fail: - LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL; - return false; -} - -/** - * Endian handlers - */ -#if LL_BIG_ENDIAN -U64 ll_htonll(U64 hostlonglong) { return hostlonglong; } -U64 ll_ntohll(U64 netlonglong) { return netlonglong; } -F64 ll_htond(F64 hostlonglong) { return hostlonglong; } -F64 ll_ntohd(F64 netlonglong) { return netlonglong; } -#else -// I read some comments one a indicating that doing an integer add -// here would be faster than a bitwise or. For now, the or has -// programmer clarity, since the intended outcome matches the -// operation. -U64 ll_htonll(U64 hostlonglong) -{ - return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) | - ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32)); -} -U64 ll_ntohll(U64 netlonglong) -{ - return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) | - ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32)); -} -union LLEndianSwapper -{ - F64 d; - U64 i; -}; -F64 ll_htond(F64 hostdouble) -{ - LLEndianSwapper tmp; - tmp.d = hostdouble; - tmp.i = ll_htonll(tmp.i); - return tmp.d; -} -F64 ll_ntohd(F64 netdouble) -{ - LLEndianSwapper tmp; - tmp.d = netdouble; - tmp.i = ll_ntohll(tmp.i); - return tmp.d; -} -#endif - -/** - * Local functions. - */ -/** - * @brief Figure out what kind of string it is (raw or delimited) and handoff. - * - * @param istr The stream to read from. - * @param value [out] The string which was found. - * @param max_bytes The maximum possible length of the string. Passing in - * a negative value will skip this check. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes); - -/** - * @brief Parse a delimited string. - * - * @param istr The stream to read from, with the delimiter already popped. - * @param value [out] The string which was found. - * @param d The delimiter to use. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_string_delim(std::istream& istr, std::string& value, char d); - -/** - * @brief Read a raw string off the stream. - * - * @param istr The stream to read from, with the (len) parameter - * leading the stream. - * @param value [out] The string which was found. - * @param d The delimiter to use. - * @param max_bytes The maximum possible length of the string. Passing in - * a negative value will skip this check. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_string_raw( - std::istream& istr, - std::string& value, - S32 max_bytes); - -/** - * @brief helper method for dealing with the different notation boolean format. - * - * @param istr The stream to read from with the leading character stripped. - * @param data [out] the result of the parse. - * @param compare The string to compare the boolean against - * @param vale The value to assign to data if the parse succeeds. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_boolean( - std::istream& istr, - LLSD& data, - const std::string& compare, - bool value); - -/** - * @brief Do notation escaping of a string to an ostream. - * - * @param value The string to escape and serialize - * @param str The stream to serialize to. - */ -void serialize_string(const std::string& value, std::ostream& str); - - -/** - * Local constants. - */ -static const std::string NOTATION_TRUE_SERIAL("true"); -static const std::string NOTATION_FALSE_SERIAL("false"); - -static const char BINARY_TRUE_SERIAL = '1'; -static const char BINARY_FALSE_SERIAL = '0'; - - -/** - * LLSDParser - */ -LLSDParser::LLSDParser() - : mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false) -{ -} - -// virtual -LLSDParser::~LLSDParser() -{ } - -S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes, S32 max_depth) -{ - mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true; - mMaxBytesLeft = max_bytes; - return doParse(istr, data, max_depth); -} - - -// Parse using routine to get() lines, faster than parse() -S32 LLSDParser::parseLines(std::istream& istr, LLSD& data) -{ - mCheckLimits = false; - mParseLines = true; - return doParse(istr, data); -} - - -int LLSDParser::get(std::istream& istr) const -{ - if(mCheckLimits) --mMaxBytesLeft; - return istr.get(); -} - -std::istream& LLSDParser::get( - std::istream& istr, - char* s, - std::streamsize n, - char delim) const -{ - istr.get(s, n, delim); - if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); - return istr; -} - -std::istream& LLSDParser::get( - std::istream& istr, - std::streambuf& sb, - char delim) const -{ - istr.get(sb, delim); - if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); - return istr; -} - -std::istream& LLSDParser::ignore(std::istream& istr) const -{ - istr.ignore(); - if(mCheckLimits) --mMaxBytesLeft; - return istr; -} - -std::istream& LLSDParser::putback(std::istream& istr, char c) const -{ - istr.putback(c); - if(mCheckLimits) ++mMaxBytesLeft; - return istr; -} - -std::istream& LLSDParser::read( - std::istream& istr, - char* s, - std::streamsize n) const -{ - istr.read(s, n); - if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); - return istr; -} - -void LLSDParser::account(S32 bytes) const -{ - if(mCheckLimits) mMaxBytesLeft -= bytes; -} - - -/** - * LLSDNotationParser - */ -LLSDNotationParser::LLSDNotationParser() -{ -} - -// virtual -LLSDNotationParser::~LLSDNotationParser() -{ } - -// virtual -S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const -{ - // map: { string:object, string:object } - // array: [ object, object, object ] - // undef: ! - // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE - // integer: i#### - // real: r#### - // uuid: u#### - // string: "g'day" | 'have a "nice" day' | s(size)"raw data" - // uri: l"escaped" - // date: d"YYYY-MM-DDTHH:MM:SS.FFZ" - // binary: b##"ff3120ab1" | b(size)"raw data" - char c; - c = istr.peek(); - if (max_depth == 0) - { - return PARSE_FAILURE; - } - while(isspace(c)) - { - // pop the whitespace. - c = get(istr); - c = istr.peek(); - continue; - } - if(!istr.good()) - { - return 0; - } - S32 parse_count = 1; - switch(c) - { - case '{': - { - S32 child_count = parseMap(istr, data, max_depth - 1); - if((child_count == PARSE_FAILURE) || data.isUndefined()) - { - parse_count = PARSE_FAILURE; - } - else - { - parse_count += child_count; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading map." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case '[': - { - S32 child_count = parseArray(istr, data, max_depth - 1); - if((child_count == PARSE_FAILURE) || data.isUndefined()) - { - parse_count = PARSE_FAILURE; - } - else - { - parse_count += child_count; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading array." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case '!': - c = get(istr); - data.clear(); - break; - - case '0': - c = get(istr); - data = false; - break; - - case 'F': - case 'f': - ignore(istr); - c = istr.peek(); - if(isalpha(c)) - { - int cnt = deserialize_boolean( - istr, - data, - NOTATION_FALSE_SERIAL, - false); - if(PARSE_FAILURE == cnt) parse_count = cnt; - else account(cnt); - } - else - { - data = false; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - - case '1': - c = get(istr); - data = true; - break; - - case 'T': - case 't': - ignore(istr); - c = istr.peek(); - if(isalpha(c)) - { - int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true); - if(PARSE_FAILURE == cnt) parse_count = cnt; - else account(cnt); - } - else - { - data = true; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - - case 'i': - { - c = get(istr); - S32 integer = 0; - istr >> integer; - data = integer; - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading integer." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'r': - { - c = get(istr); - F64 real = 0.0; - istr >> real; - data = real; - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading real." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'u': - { - c = get(istr); - LLUUID id; - istr >> id; - data = id; - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading uuid." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case '\"': - case '\'': - case 's': - if(!parseString(istr, data)) - { - parse_count = PARSE_FAILURE; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading string." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - - case 'l': - { - c = get(istr); // pop the 'l' - c = get(istr); // pop the delimiter - std::string str; - int cnt = deserialize_string_delim(istr, str, c); - if(PARSE_FAILURE == cnt) - { - parse_count = PARSE_FAILURE; - } - else - { - data = LLURI(str); - account(cnt); - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading link." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'd': - { - c = get(istr); // pop the 'd' - c = get(istr); // pop the delimiter - std::string str; - int cnt = deserialize_string_delim(istr, str, c); - if(PARSE_FAILURE == cnt) - { - parse_count = PARSE_FAILURE; - } - else - { - data = LLDate(str); - account(cnt); - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading date." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'b': - if(!parseBinary(istr, data)) - { - parse_count = PARSE_FAILURE; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading data." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - - default: - parse_count = PARSE_FAILURE; - LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c - << ")" << LL_ENDL; - break; - } - if(PARSE_FAILURE == parse_count) - { - data.clear(); - } - return parse_count; -} - -S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const -{ - // map: { string:object, string:object } - map = LLSD::emptyMap(); - S32 parse_count = 0; - char c = get(istr); - if(c == '{') - { - // eat commas, white - bool found_name = false; - std::string name; - c = get(istr); - while(c != '}' && istr.good()) - { - if(!found_name) - { - if((c == '\"') || (c == '\'') || (c == 's')) - { - putback(istr, c); - found_name = true; - int count = deserialize_string(istr, name, mMaxBytesLeft); - if(PARSE_FAILURE == count) return PARSE_FAILURE; - account(count); - } - c = get(istr); - } - else - { - if(isspace(c) || (c == ':')) - { - c = get(istr); - continue; - } - putback(istr, c); - LLSD child; - S32 count = doParse(istr, child, max_depth); - if(count > 0) - { - // There must be a value for every key, thus - // child_count must be greater than 0. - parse_count += count; - map.insert(name, child); - } - else - { - return PARSE_FAILURE; - } - found_name = false; - c = get(istr); - } - } - if(c != '}') - { - map.clear(); - return PARSE_FAILURE; - } - } - return parse_count; -} - -S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const -{ - // array: [ object, object, object ] - array = LLSD::emptyArray(); - S32 parse_count = 0; - char c = get(istr); - if(c == '[') - { - // eat commas, white - c = get(istr); - while((c != ']') && istr.good()) - { - LLSD child; - if(isspace(c) || (c == ',')) - { - c = get(istr); - continue; - } - putback(istr, c); - S32 count = doParse(istr, child, max_depth); - if(PARSE_FAILURE == count) - { - return PARSE_FAILURE; - } - else - { - parse_count += count; - array.append(child); - } - c = get(istr); - } - if(c != ']') - { - return PARSE_FAILURE; - } - } - return parse_count; -} - -bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const -{ - std::string value; - int count = deserialize_string(istr, value, mMaxBytesLeft); - if(PARSE_FAILURE == count) return false; - account(count); - data = value; - return true; -} - -bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const -{ - // binary: b##"ff3120ab1" - // or: b(len)"..." - - // I want to manually control those values here to make sure the - // parser doesn't break when someone changes a constant somewhere - // else. - const U32 BINARY_BUFFER_SIZE = 256; - const U32 STREAM_GET_COUNT = 255; - - // need to read the base out. - char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */ - get(istr, buf, STREAM_GET_COUNT, '"'); - char c = get(istr); - if(c != '"') return false; - if(0 == strncmp("b(", buf, 2)) - { - // We probably have a valid raw binary stream. determine - // the size, and read it. - S32 len = strtol(buf + 2, NULL, 0); - if(mCheckLimits && (len > mMaxBytesLeft)) return false; - std::vector<U8> value; - if(len) - { - value.resize(len); - account((int)fullread(istr, (char *)&value[0], len)); - } - c = get(istr); // strip off the trailing double-quote - data = value; - } - else if(0 == strncmp("b64", buf, 3)) - { - // *FIX: A bit inefficient, but works for now. To make the - // format better, I would need to add a hint into the - // serialization format that indicated how long it was. - std::stringstream coded_stream; - get(istr, *(coded_stream.rdbuf()), '\"'); - c = get(istr); - std::string encoded(coded_stream.str()); - size_t len = LLBase64::requiredDecryptionSpace(encoded); - std::vector<U8> value; - if(len) - { - value.resize(len); - len = LLBase64::decode(encoded, &value[0], len); - value.resize(len); - } - data = value; - } - else if(0 == strncmp("b16", buf, 3)) - { - // yay, base 16. We pop the next character which is either a - // double quote or base 16 data. If it's a double quote, we're - // done parsing. If it's not, put the data back, and read the - // stream until the next double quote. - char* read; /*Flawfinder: ignore*/ - U8 byte; - U8 byte_buffer[BINARY_BUFFER_SIZE]; - U8* write; - std::vector<U8> value; - c = get(istr); - while(c != '"') - { - putback(istr, c); - read = buf; - write = byte_buffer; - get(istr, buf, STREAM_GET_COUNT, '"'); - c = get(istr); - while(*read != '\0') /*Flawfinder: ignore*/ - { - byte = hex_as_nybble(*read++); - byte = byte << 4; - byte |= hex_as_nybble(*read++); - *write++ = byte; - } - // copy the data out of the byte buffer - value.insert(value.end(), byte_buffer, write); - } - data = value; - } - else - { - return false; - } - return true; -} - - -/** - * LLSDBinaryParser - */ - -// virtual -S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const -{ -/** - * Undefined: '!'<br> - * Boolean: '1' for true '0' for false<br> - * Integer: 'i' + 4 bytes network byte order<br> - * Real: 'r' + 8 bytes IEEE double<br> - * UUID: 'u' + 16 byte unsigned integer<br> - * String: 's' + 4 byte integer size + string<br> - * strings also secretly support the notation format - * Date: 'd' + 8 byte IEEE double for seconds since epoch<br> - * URI: 'l' + 4 byte integer size + string uri<br> - * Binary: 'b' + 4 byte integer size + binary data<br> - * Array: '[' + 4 byte integer size + all values + ']'<br> - * Map: '{' + 4 byte integer size every(key + value) + '}'<br> - * map keys are serialized as s + 4 byte integer size + string or in the - * notation format. - */ - char c; - c = get(istr); - if(!istr.good()) - { - return 0; - } - if (max_depth == 0) - { - return PARSE_FAILURE; - } - S32 parse_count = 1; - switch(c) - { - case '{': - { - S32 child_count = parseMap(istr, data, max_depth - 1); - if((child_count == PARSE_FAILURE) || data.isUndefined()) - { - parse_count = PARSE_FAILURE; - } - else - { - parse_count += child_count; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary map." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case '[': - { - S32 child_count = parseArray(istr, data, max_depth - 1); - if((child_count == PARSE_FAILURE) || data.isUndefined()) - { - parse_count = PARSE_FAILURE; - } - else - { - parse_count += child_count; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary array." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case '!': - data.clear(); - break; - - case '0': - data = false; - break; - - case '1': - data = true; - break; - - case 'i': - { - U32 value_nbo = 0; - read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - data = (S32)ntohl(value_nbo); - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary integer." << LL_ENDL; - } - break; - } - - case 'r': - { - F64 real_nbo = 0.0; - read(istr, (char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/ - data = ll_ntohd(real_nbo); - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary real." << LL_ENDL; - } - break; - } - - case 'u': - { - LLUUID id; - read(istr, (char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/ - data = id; - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary uuid." << LL_ENDL; - } - break; - } - - case '\'': - case '"': - { - std::string value; - int cnt = deserialize_string_delim(istr, value, c); - if(PARSE_FAILURE == cnt) - { - parse_count = PARSE_FAILURE; - } - else - { - data = value; - account(cnt); - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary (notation-style) string." - << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case 's': - { - std::string value; - if(parseString(istr, value)) - { - data = value; - } - else - { - parse_count = PARSE_FAILURE; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary string." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'l': - { - std::string value; - if(parseString(istr, value)) - { - data = LLURI(value); - } - else - { - parse_count = PARSE_FAILURE; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary link." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'd': - { - F64 real = 0.0; - read(istr, (char*)&real, sizeof(F64)); /*Flawfinder: ignore*/ - data = LLDate(real); - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary date." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - case 'b': - { - // We probably have a valid raw binary stream. determine - // the size, and read it. - U32 size_nbo = 0; - read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(size_nbo); - if(mCheckLimits && (size > mMaxBytesLeft)) - { - parse_count = PARSE_FAILURE; - } - else - { - std::vector<U8> value; - if(size > 0) - { - value.resize(size); - account((int)fullread(istr, (char*)&value[0], size)); - } - data = value; - } - if(istr.fail()) - { - LL_INFOS() << "STREAM FAILURE reading binary." << LL_ENDL; - parse_count = PARSE_FAILURE; - } - break; - } - - default: - parse_count = PARSE_FAILURE; - LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c - << ")" << LL_ENDL; - break; - } - if(PARSE_FAILURE == parse_count) - { - data.clear(); - } - return parse_count; -} - -S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const -{ - map = LLSD::emptyMap(); - U32 value_nbo = 0; - read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(value_nbo); - S32 parse_count = 0; - S32 count = 0; - char c = get(istr); - while(c != '}' && (count < size) && istr.good()) - { - std::string name; - switch(c) - { - case 'k': - if(!parseString(istr, name)) - { - return PARSE_FAILURE; - } - break; - case '\'': - case '"': - { - int cnt = deserialize_string_delim(istr, name, c); - if(PARSE_FAILURE == cnt) return PARSE_FAILURE; - account(cnt); - break; - } - } - LLSD child; - S32 child_count = doParse(istr, child, max_depth); - if(child_count > 0) - { - // There must be a value for every key, thus child_count - // must be greater than 0. - parse_count += child_count; - map.insert(name, child); - } - else - { - return PARSE_FAILURE; - } - ++count; - c = get(istr); - } - if((c != '}') || (count < size)) - { - // Make sure it is correctly terminated and we parsed as many - // as were said to be there. - return PARSE_FAILURE; - } - return parse_count; -} - -S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const -{ - array = LLSD::emptyArray(); - U32 value_nbo = 0; - read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(value_nbo); - - // *FIX: This would be a good place to reserve some space in the - // array... - - S32 parse_count = 0; - S32 count = 0; - char c = istr.peek(); - while((c != ']') && (count < size) && istr.good()) - { - LLSD child; - S32 child_count = doParse(istr, child, max_depth); - if(PARSE_FAILURE == child_count) - { - return PARSE_FAILURE; - } - if(child_count) - { - parse_count += child_count; - array.append(child); - } - ++count; - c = istr.peek(); - } - c = get(istr); - if((c != ']') || (count < size)) - { - // Make sure it is correctly terminated and we parsed as many - // as were said to be there. - return PARSE_FAILURE; - } - return parse_count; -} - -bool LLSDBinaryParser::parseString( - std::istream& istr, - std::string& value) const -{ - // *FIX: This is memory inefficient. - U32 value_nbo = 0; - read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ - S32 size = (S32)ntohl(value_nbo); - if(mCheckLimits && (size > mMaxBytesLeft)) return false; - if(size < 0) return false; - std::vector<char> buf; - if(size) - { - buf.resize(size); - account((int)fullread(istr, &buf[0], size)); - value.assign(buf.begin(), buf.end()); - } - return true; -} - - -/** - * LLSDFormatter - */ -LLSDFormatter::LLSDFormatter() : - mBoolAlpha(false) -{ -} - -// virtual -LLSDFormatter::~LLSDFormatter() -{ } - -void LLSDFormatter::boolalpha(bool alpha) -{ - mBoolAlpha = alpha; -} - -void LLSDFormatter::realFormat(const std::string& format) -{ - mRealFormat = format; -} - -void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const -{ - std::string buffer = llformat(mRealFormat.c_str(), real); - ostr << buffer; -} - -/** - * LLSDNotationFormatter - */ -LLSDNotationFormatter::LLSDNotationFormatter() -{ -} - -// virtual -LLSDNotationFormatter::~LLSDNotationFormatter() -{ } - -// static -std::string LLSDNotationFormatter::escapeString(const std::string& in) -{ - std::ostringstream ostr; - serialize_string(in, ostr); - return ostr.str(); -} - -// virtual -S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const -{ - S32 rv = format_impl(data, ostr, options, 0); - return rv; -} - -S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const -{ - S32 format_count = 1; - std::string pre; - std::string post; - - if (options & LLSDFormatter::OPTIONS_PRETTY) - { - for (U32 i = 0; i < level; i++) - { - pre += " "; - } - post = "\n"; - } - - switch(data.type()) - { - case LLSD::TypeMap: - { - if (0 != level) ostr << post << pre; - ostr << "{"; - std::string inner_pre; - if (options & LLSDFormatter::OPTIONS_PRETTY) - { - inner_pre = pre + " "; - } - - bool need_comma = false; - auto iter = data.beginMap(); - auto end = data.endMap(); - for(; iter != end; ++iter) - { - if(need_comma) ostr << ","; - need_comma = true; - ostr << post << inner_pre << '\''; - serialize_string((*iter).first, ostr); - ostr << "':"; - format_count += format_impl((*iter).second, ostr, options, level + 2); - } - ostr << post << pre << "}"; - break; - } - - case LLSD::TypeArray: - { - ostr << post << pre << "["; - bool need_comma = false; - auto iter = data.beginArray(); - auto end = data.endArray(); - for(; iter != end; ++iter) - { - if(need_comma) ostr << ","; - need_comma = true; - format_count += format_impl(*iter, ostr, options, level + 1); - } - ostr << "]"; - break; - } - - case LLSD::TypeUndefined: - ostr << "!"; - break; - - case LLSD::TypeBoolean: - if(mBoolAlpha || -#if( LL_WINDOWS || __GNUC__ > 2) - (ostr.flags() & std::ios::boolalpha) -#else - (ostr.flags() & 0x0100) -#endif - ) - { - ostr << (data.asBoolean() - ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL); - } - else - { - ostr << (data.asBoolean() ? 1 : 0); - } - break; - - case LLSD::TypeInteger: - ostr << "i" << data.asInteger(); - break; - - case LLSD::TypeReal: - ostr << "r"; - if(mRealFormat.empty()) - { - ostr << data.asReal(); - } - else - { - formatReal(data.asReal(), ostr); - } - break; - - case LLSD::TypeUUID: - ostr << "u" << data.asUUID(); - break; - - case LLSD::TypeString: - ostr << '\''; - serialize_string(data.asStringRef(), ostr); - ostr << '\''; - break; - - case LLSD::TypeDate: - ostr << "d\"" << data.asDate() << "\""; - break; - - case LLSD::TypeURI: - ostr << "l\""; - serialize_string(data.asString(), ostr); - ostr << "\""; - break; - - case LLSD::TypeBinary: - { - // *FIX: memory inefficient. - const std::vector<U8>& buffer = data.asBinary(); - ostr << "b(" << buffer.size() << ")\""; - if(!buffer.empty()) - { - if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY) - { - std::ios_base::fmtflags old_flags = ostr.flags(); - ostr.setf( std::ios::hex, std::ios::basefield ); - ostr << "0x"; - for (unsigned char i : buffer) - { - ostr << static_cast<int>(i); - } - ostr.flags(old_flags); - } - else - { - ostr.write(reinterpret_cast<const char*>(&buffer[0]), buffer.size()); - } - } - ostr << "\""; - break; - } - - default: - // *NOTE: This should never happen. - ostr << "!"; - break; - } - return format_count; -} - - -/** - * LLSDBinaryFormatter - */ -LLSDBinaryFormatter::LLSDBinaryFormatter() -{ -} - -// virtual -LLSDBinaryFormatter::~LLSDBinaryFormatter() -{ } - -// virtual -S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const -{ - S32 format_count = 1; - switch(data.type()) - { - case LLSD::TypeMap: - { - ostr.put('{'); - U32 size_nbo = htonl(data.size()); - ostr.write(reinterpret_cast<const char*>(&size_nbo), sizeof(U32)); - auto iter = data.beginMap(); - auto end = data.endMap(); - for(; iter != end; ++iter) - { - ostr.put('k'); - formatString((*iter).first, ostr); - format_count += format((*iter).second, ostr); - } - ostr.put('}'); - break; - } - - case LLSD::TypeArray: - { - ostr.put('['); - U32 size_nbo = htonl(data.size()); - ostr.write(reinterpret_cast<const char*>(&size_nbo), sizeof(U32)); - auto iter = data.beginArray(); - auto end = data.endArray(); - for(; iter != end; ++iter) - { - format_count += format(*iter, ostr); - } - ostr.put(']'); - break; - } - - case LLSD::TypeUndefined: - ostr.put('!'); - break; - - case LLSD::TypeBoolean: - if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL); - else ostr.put(BINARY_FALSE_SERIAL); - break; - - case LLSD::TypeInteger: - { - ostr.put('i'); - U32 value_nbo = htonl(data.asInteger()); - ostr.write((const char*)(&value_nbo), sizeof(U32)); - break; - } - - case LLSD::TypeReal: - { - ostr.put('r'); - F64 value_nbo = ll_htond(data.asReal()); - ostr.write((const char*)(&value_nbo), sizeof(F64)); - break; - } - - case LLSD::TypeUUID: - { - ostr.put('u'); - LLUUID temp = data.asUUID(); - ostr.write((const char*)(&(temp.mData)), UUID_BYTES); - break; - } - - case LLSD::TypeString: - ostr.put('s'); - formatString(data.asStringRef(), ostr); - break; - - case LLSD::TypeDate: - { - ostr.put('d'); - F64 value = data.asReal(); - ostr.write((const char*)(&value), sizeof(F64)); - break; - } - - case LLSD::TypeURI: - ostr.put('l'); - formatString(data.asString(), ostr); - break; - - case LLSD::TypeBinary: - { - ostr.put('b'); - const std::vector<U8>& buffer = data.asBinary(); - U32 size_nbo = htonl(buffer.size()); - ostr.write((const char*)(&size_nbo), sizeof(U32)); - if(!buffer.empty()) ostr.write((const char*)&buffer[0], buffer.size()); - break; - } - - default: - // *NOTE: This should never happen. - ostr.put('!'); - break; - } - return format_count; -} - -void LLSDBinaryFormatter::formatString( - const std::string& string, - std::ostream& ostr) const -{ - U32 size_nbo = htonl(string.size()); - ostr.write((const char*)(&size_nbo), sizeof(U32)); - ostr.write(string.c_str(), string.size()); -} - -/** - * local functions - */ -int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes) -{ - int c = istr.get(); - if(istr.fail()) - { - // No data in stream, bail out but mention the character we - // grabbed. - return LLSDParser::PARSE_FAILURE; - } - - int rv = LLSDParser::PARSE_FAILURE; - switch(c) - { - case '\'': - case '"': - rv = deserialize_string_delim(istr, value, c); - break; - case 's': - // technically, less than max_bytes, but this is just meant to - // catch egregious protocol errors. parse errors will be - // caught in the case of incorrect counts. - rv = deserialize_string_raw(istr, value, max_bytes); - break; - default: - break; - } - if(LLSDParser::PARSE_FAILURE == rv) return rv; - return rv + 1; // account for the character grabbed at the top. -} - -int deserialize_string_delim( - std::istream& istr, - std::string& value, - char delim) -{ - std::ostringstream write_buffer; - bool found_escape = false; - bool found_hex = false; - bool found_digit = false; - U8 byte = 0; - int count = 0; - - while (true) - { - int next_byte = istr.get(); - ++count; - - if(istr.fail()) - { - // If our stream is empty, break out - value = write_buffer.str(); - return LLSDParser::PARSE_FAILURE; - } - - char next_char = (char)next_byte; // Now that we know it's not EOF - - if(found_escape) - { - // next character(s) is a special sequence. - if(found_hex) - { - if(found_digit) - { - found_digit = false; - found_hex = false; - found_escape = false; - byte = byte << 4; - byte |= hex_as_nybble(next_char); - write_buffer << byte; - byte = 0; - } - else - { - // next character is the first nybble of - // - found_digit = true; - byte = hex_as_nybble(next_char); - } - } - else if(next_char == 'x') - { - found_hex = true; - } - else - { - switch(next_char) - { - case 'a': - write_buffer << '\a'; - break; - case 'b': - write_buffer << '\b'; - break; - case 'f': - write_buffer << '\f'; - break; - case 'n': - write_buffer << '\n'; - break; - case 'r': - write_buffer << '\r'; - break; - case 't': - write_buffer << '\t'; - break; - case 'v': - write_buffer << '\v'; - break; - default: - write_buffer << next_char; - break; - } - found_escape = false; - } - } - else if(next_char == '\\') - { - found_escape = true; - } - else if(next_char == delim) - { - break; - } - else - { - write_buffer << next_char; - } - } - - value = write_buffer.str(); - return count; -} - -int deserialize_string_raw( - std::istream& istr, - std::string& value, - S32 max_bytes) -{ - int count = 0; - const S32 BUF_LEN = 20; - char buf[BUF_LEN]; /* Flawfinder: ignore */ - istr.get(buf, BUF_LEN - 1, ')'); - count += (int)istr.gcount(); - int c = istr.get(); - c = istr.get(); - count += 2; - if(((c == '"') || (c == '\'')) && (buf[0] == '(')) - { - // We probably have a valid raw string. determine - // the size, and read it. - // *FIX: This is memory inefficient. - S32 len = strtol(buf + 1, NULL, 0); - if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE; - std::vector<char> buf2; - if(len) - { - buf2.resize(len); - count += (int)fullread(istr, (char *)&buf2[0], len); - value.assign(buf2.begin(), buf2.end()); - } - c = istr.get(); - ++count; - if(!((c == '"') || (c == '\''))) - { - return LLSDParser::PARSE_FAILURE; - } - } - else - { - return LLSDParser::PARSE_FAILURE; - } - return count; -} - -static const char* NOTATION_STRING_CHARACTERS[256] = -{ - "\\x00", // 0 - "\\x01", // 1 - "\\x02", // 2 - "\\x03", // 3 - "\\x04", // 4 - "\\x05", // 5 - "\\x06", // 6 - "\\a", // 7 - "\\b", // 8 - "\\t", // 9 - "\\n", // 10 - "\\v", // 11 - "\\f", // 12 - "\\r", // 13 - "\\x0e", // 14 - "\\x0f", // 15 - "\\x10", // 16 - "\\x11", // 17 - "\\x12", // 18 - "\\x13", // 19 - "\\x14", // 20 - "\\x15", // 21 - "\\x16", // 22 - "\\x17", // 23 - "\\x18", // 24 - "\\x19", // 25 - "\\x1a", // 26 - "\\x1b", // 27 - "\\x1c", // 28 - "\\x1d", // 29 - "\\x1e", // 30 - "\\x1f", // 31 - " ", // 32 - "!", // 33 - "\"", // 34 - "#", // 35 - "$", // 36 - "%", // 37 - "&", // 38 - "\\'", // 39 - "(", // 40 - ")", // 41 - "*", // 42 - "+", // 43 - ",", // 44 - "-", // 45 - ".", // 46 - "/", // 47 - "0", // 48 - "1", // 49 - "2", // 50 - "3", // 51 - "4", // 52 - "5", // 53 - "6", // 54 - "7", // 55 - "8", // 56 - "9", // 57 - ":", // 58 - ";", // 59 - "<", // 60 - "=", // 61 - ">", // 62 - "?", // 63 - "@", // 64 - "A", // 65 - "B", // 66 - "C", // 67 - "D", // 68 - "E", // 69 - "F", // 70 - "G", // 71 - "H", // 72 - "I", // 73 - "J", // 74 - "K", // 75 - "L", // 76 - "M", // 77 - "N", // 78 - "O", // 79 - "P", // 80 - "Q", // 81 - "R", // 82 - "S", // 83 - "T", // 84 - "U", // 85 - "V", // 86 - "W", // 87 - "X", // 88 - "Y", // 89 - "Z", // 90 - "[", // 91 - "\\\\", // 92 - "]", // 93 - "^", // 94 - "_", // 95 - "`", // 96 - "a", // 97 - "b", // 98 - "c", // 99 - "d", // 100 - "e", // 101 - "f", // 102 - "g", // 103 - "h", // 104 - "i", // 105 - "j", // 106 - "k", // 107 - "l", // 108 - "m", // 109 - "n", // 110 - "o", // 111 - "p", // 112 - "q", // 113 - "r", // 114 - "s", // 115 - "t", // 116 - "u", // 117 - "v", // 118 - "w", // 119 - "x", // 120 - "y", // 121 - "z", // 122 - "{", // 123 - "|", // 124 - "}", // 125 - "~", // 126 - "\\x7f", // 127 - "\\x80", // 128 - "\\x81", // 129 - "\\x82", // 130 - "\\x83", // 131 - "\\x84", // 132 - "\\x85", // 133 - "\\x86", // 134 - "\\x87", // 135 - "\\x88", // 136 - "\\x89", // 137 - "\\x8a", // 138 - "\\x8b", // 139 - "\\x8c", // 140 - "\\x8d", // 141 - "\\x8e", // 142 - "\\x8f", // 143 - "\\x90", // 144 - "\\x91", // 145 - "\\x92", // 146 - "\\x93", // 147 - "\\x94", // 148 - "\\x95", // 149 - "\\x96", // 150 - "\\x97", // 151 - "\\x98", // 152 - "\\x99", // 153 - "\\x9a", // 154 - "\\x9b", // 155 - "\\x9c", // 156 - "\\x9d", // 157 - "\\x9e", // 158 - "\\x9f", // 159 - "\\xa0", // 160 - "\\xa1", // 161 - "\\xa2", // 162 - "\\xa3", // 163 - "\\xa4", // 164 - "\\xa5", // 165 - "\\xa6", // 166 - "\\xa7", // 167 - "\\xa8", // 168 - "\\xa9", // 169 - "\\xaa", // 170 - "\\xab", // 171 - "\\xac", // 172 - "\\xad", // 173 - "\\xae", // 174 - "\\xaf", // 175 - "\\xb0", // 176 - "\\xb1", // 177 - "\\xb2", // 178 - "\\xb3", // 179 - "\\xb4", // 180 - "\\xb5", // 181 - "\\xb6", // 182 - "\\xb7", // 183 - "\\xb8", // 184 - "\\xb9", // 185 - "\\xba", // 186 - "\\xbb", // 187 - "\\xbc", // 188 - "\\xbd", // 189 - "\\xbe", // 190 - "\\xbf", // 191 - "\\xc0", // 192 - "\\xc1", // 193 - "\\xc2", // 194 - "\\xc3", // 195 - "\\xc4", // 196 - "\\xc5", // 197 - "\\xc6", // 198 - "\\xc7", // 199 - "\\xc8", // 200 - "\\xc9", // 201 - "\\xca", // 202 - "\\xcb", // 203 - "\\xcc", // 204 - "\\xcd", // 205 - "\\xce", // 206 - "\\xcf", // 207 - "\\xd0", // 208 - "\\xd1", // 209 - "\\xd2", // 210 - "\\xd3", // 211 - "\\xd4", // 212 - "\\xd5", // 213 - "\\xd6", // 214 - "\\xd7", // 215 - "\\xd8", // 216 - "\\xd9", // 217 - "\\xda", // 218 - "\\xdb", // 219 - "\\xdc", // 220 - "\\xdd", // 221 - "\\xde", // 222 - "\\xdf", // 223 - "\\xe0", // 224 - "\\xe1", // 225 - "\\xe2", // 226 - "\\xe3", // 227 - "\\xe4", // 228 - "\\xe5", // 229 - "\\xe6", // 230 - "\\xe7", // 231 - "\\xe8", // 232 - "\\xe9", // 233 - "\\xea", // 234 - "\\xeb", // 235 - "\\xec", // 236 - "\\xed", // 237 - "\\xee", // 238 - "\\xef", // 239 - "\\xf0", // 240 - "\\xf1", // 241 - "\\xf2", // 242 - "\\xf3", // 243 - "\\xf4", // 244 - "\\xf5", // 245 - "\\xf6", // 246 - "\\xf7", // 247 - "\\xf8", // 248 - "\\xf9", // 249 - "\\xfa", // 250 - "\\xfb", // 251 - "\\xfc", // 252 - "\\xfd", // 253 - "\\xfe", // 254 - "\\xff" // 255 -}; - -void serialize_string(const std::string& value, std::ostream& str) -{ - std::string::const_iterator it = value.begin(); - std::string::const_iterator end = value.end(); - U8 c; - for(; it != end; ++it) - { - c = (U8)(*it); - str << NOTATION_STRING_CHARACTERS[c]; - } -} - -int deserialize_boolean( - std::istream& istr, - LLSD& data, - const std::string& compare, - bool value) -{ - // - // this method is a little goofy, because it gets the stream at - // the point where the t or f has already been - // consumed. Basically, parse for a patch to the string passed in - // starting at index 1. If it's a match: - // * assign data to value - // * return the number of bytes read - // otherwise: - // * set data to LLSD::null - // * return LLSDParser::PARSE_FAILURE (-1) - // - int bytes_read = 0; - std::string::size_type ii = 0; - char c = istr.peek(); - while((++ii < compare.size()) - && (tolower(c) == (int)compare[ii]) - && istr.good()) - { - istr.ignore(); - ++bytes_read; - c = istr.peek(); - } - if(compare.size() != ii) - { - data.clear(); - return LLSDParser::PARSE_FAILURE; - } - data = value; - return bytes_read; -} - -std::ostream& operator<<(std::ostream& s, const LLSD& llsd) -{ - s << LLSDNotationStreamer(llsd); - return s; -} - - -//dirty little zippers -- yell at davep if these are horrid - -//return a string containing gzipped bytes of binary serialized LLSD -// VERY inefficient -- creates several copies of LLSD block in memory -std::string zip_llsd(LLSD& data) -{ - std::stringstream llsd_strm; - - LLSDSerialize::toBinary(data, llsd_strm); - - const U32 CHUNK = 65536; - - z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - - S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION); - if (ret != Z_OK) - { - LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; - return std::string(); - } - - std::string source = llsd_strm.str(); - - U8 out[CHUNK]; - - strm.avail_in = source.size(); - strm.next_in = (U8*) source.data(); - U8* output = NULL; - - U32 cur_size = 0; - - U32 have = 0; - - do - { - strm.avail_out = CHUNK; - strm.next_out = out; - - ret = deflate(&strm, Z_FINISH); - if (ret == Z_OK || ret == Z_STREAM_END) - { //copy result into output - if (strm.avail_out >= CHUNK) - { - free(output); - LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; - return std::string(); - } - - have = CHUNK-strm.avail_out; - U8* new_output = (U8*) realloc(output, cur_size+have); - if (new_output == NULL) - { - LL_WARNS() << "Failed to compress LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL; - deflateEnd(&strm); - if (output) - { - free(output); - } - return std::string(); - } - output = new_output; - memcpy(output+cur_size, out, have); - cur_size += have; - } - else - { - free(output); - LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; - return std::string(); - } - } - while (ret == Z_OK); - - std::string::size_type size = cur_size; - - std::string result((char*) output, size); - deflateEnd(&strm); - free(output); - - return result; -} - -// <alchemy> -//decompress a block of LLSD from provided istream -// not very efficient -- creats a copy of decompressed LLSD block in memory -// and deserializes from that copy using LLSDSerialize -LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size) -{ - std::unique_ptr<U8 []> in; - try - { - in = std::make_unique<U8 []>(size); - } - catch (const std::bad_alloc&) - { - return ZR_MEM_ERROR; - } - is.read((char*)in.get(), size); - - return unzip_llsd(data, in.get(), size); -} - -LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, U8* in, S32 size) -{ - U8* result = NULL; - U32 cur_size = 0; - z_stream strm; - - const U32 CHUNK = 65536; - - U8 out[CHUNK]; - - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = size; - strm.next_in = in; - - S32 ret = inflateInit(&strm); - - do - { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - - switch (ret) - { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; - case Z_DATA_ERROR: - case Z_MEM_ERROR: - case Z_STREAM_ERROR: - inflateEnd(&strm); - free(result); - return ZR_MEM_ERROR; - break; - } - - U32 have = CHUNK-strm.avail_out; - - U8* new_result = (U8*)realloc(result, cur_size + have); - if (new_result == NULL) - { - LL_WARNS() << "Failed to unzip LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL; - inflateEnd(&strm); - if (result) - { - free(result); - } - return ZR_MEM_ERROR; - } - result = new_result; - memcpy(result+cur_size, out, have); - cur_size += have; - - } while (ret == Z_OK); - - inflateEnd(&strm); - - if (ret != Z_STREAM_END) - { - free(result); - return ZR_DATA_ERROR; - } - - //result now points to the decompressed LLSD block - { - char* result_ptr = strip_deprecated_header((char*)result, cur_size); - - boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size); - - if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH)) - { - LL_WARNS() << "Failed to unzip LLSD block" << LL_ENDL; - free(result); - return ZR_PARSE_ERROR; - } - } - - free(result); - return ZR_OK; -} - -//This unzip function will only work with a gzip header and trailer - while the contents -//of the actual compressed data is the same for either format (gzip vs zlib ), the headers -//and trailers are different for the formats. -U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, std::istream& is, S32 size) -{ - if (size == 0) - { - LL_WARNS() << "No data to unzip." << LL_ENDL; - return NULL; - } - auto in = std::make_unique<U8[]>(size); - is.read((char*)in.get(), size); - return unzip_llsdNavMesh(valid, outsize, in.get(), size); -} - -U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, U8* in, S32 size ) -{ - if (size == 0) - { - LL_WARNS() << "No data to unzip." << LL_ENDL; - return NULL; - } - U8* result = NULL; - U32 cur_size = 0; - z_stream strm; - - const U32 CHUNK = 0x4000; - - U8 out[CHUNK]; - - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = size; - strm.next_in = in; - - - S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); - do - { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - switch (ret) - { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; - case Z_DATA_ERROR: - case Z_MEM_ERROR: - case Z_STREAM_ERROR: - inflateEnd(&strm); - free(result); - valid = false; - return NULL; - } - U32 have = CHUNK-strm.avail_out; - - U8* new_result = (U8*) realloc(result, cur_size + have); - if (new_result == NULL) - { - LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size - << " bytes; requested " << cur_size + have - << " bytes; total syze: ." << size << " bytes." - << LL_ENDL; - inflateEnd(&strm); - if (result) - { - free(result); - } - valid = false; - return NULL; - } - result = new_result; - memcpy(result+cur_size, out, have); - cur_size += have; - - } while (ret == Z_OK); - - inflateEnd(&strm); - - if (ret != Z_STREAM_END) - { - free(result); - valid = false; - return NULL; - } - - //result now points to the decompressed LLSD block - { - outsize= cur_size; - valid = true; - } - - return result; -} - -char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size) -{ - const char* deprecated_header = "<? LLSD/Binary ?>"; - constexpr size_t deprecated_header_size = 17; - - if (cur_size > deprecated_header_size - && memcmp(in, deprecated_header, deprecated_header_size) == 0) - { - in = in + deprecated_header_size; - cur_size = cur_size - deprecated_header_size; - if (header_size) - { - *header_size = deprecated_header_size + 1; - } - } - - return in; -} -// </alchemy> - +/** + * @file llsdserialize.cpp + * @author Phoenix + * @date 2006-03-05 + * @brief Implementation of LLSD parsers and formatters + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llsdserialize.h" +#include "llwin32headerslean.h" +#include "llpointer.h" +#include "llstreamtools.h" // for fullread +#include "llbase64.h" + +#include <iostream> + +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> + +#ifdef LL_USESYSTEMLIBS +# include <zlib.h> +#else +# include "zlib/zlib.h" // for davep's dirty little zip functions +#endif + +#if !LL_WINDOWS +#include <netinet/in.h> // htonl & ntohl +#endif + +#include "lldate.h" +#include "llsd.h" +#include "llstring.h" +#include "lluri.h" + +// File constants +static const int MAX_HDR_LEN = 20; +static const S32 UNZIP_LLSD_MAX_DEPTH = 96; +static const char LEGACY_NON_HEADER[] = "<llsd>"; +const std::string LLSD_BINARY_HEADER("LLSD/Binary"); +const std::string LLSD_XML_HEADER("LLSD/XML"); + +//used to deflate a gzipped asset (currently used for navmeshes) +#define windowBits 15 +#define ENABLE_ZLIB_GZIP 32 + +/** + * LLSDSerialize + */ + +// static +void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options) +{ + LLPointer<LLSDFormatter> f = NULL; + + switch (type) + { + case LLSD_BINARY: + str << "<? " << LLSD_BINARY_HEADER << " ?>\n"; + f = new LLSDBinaryFormatter; + break; + + case LLSD_XML: + str << "<? " << LLSD_XML_HEADER << " ?>\n"; + f = new LLSDXMLFormatter; + break; + + default: + LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL; + } + + if (f.notNull()) + { + f->format(sd, str, options); + } +} + +// static +bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) +{ + LLPointer<LLSDParser> p = NULL; + char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */ + int i; + int inbuf = 0; + bool legacy_no_header = false; + bool fail_if_not_legacy = false; + std::string header; + + /* + * Get the first line before anything. + */ + str.get(hdr_buf, MAX_HDR_LEN, '\n'); + if (str.fail()) + { + str.clear(); + fail_if_not_legacy = true; + } + + if (!strnicmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ + { + legacy_no_header = true; + inbuf = (int)str.gcount(); + } + else + { + if (fail_if_not_legacy) + goto fail; + /* + * Remove the newline chars + */ + for (i = 0; i < MAX_HDR_LEN; i++) + { + if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' || + hdr_buf[i] == '\n') + { + hdr_buf[i] = 0; + break; + } + } + header = hdr_buf; + + std::string::size_type start = header.find_first_not_of("<? "); + std::string::size_type end = std::string::npos; + if (start != std::string::npos) + { + end = header.find_first_of(" ?", start); + } + if ((start == std::string::npos) || (end == std::string::npos)) + goto fail; + + header = header.substr(start, end - start); + ws(str); + } + /* + * Create the parser as appropriate + */ + if (legacy_no_header) + { // Create a LLSD XML parser, and parse the first chunk read above + LLSDXMLParser* x = new LLSDXMLParser(); + x->parsePart(hdr_buf, inbuf); // Parse the first part that was already read + x->parseLines(str, sd); // Parse the rest of it + delete x; + return true; + } + + if (header == LLSD_BINARY_HEADER) + { + p = new LLSDBinaryParser; + } + else if (header == LLSD_XML_HEADER) + { + p = new LLSDXMLParser; + } + else + { + LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL; + } + + if (p.notNull()) + { + p->parse(str, sd, max_bytes); + return true; + } + +fail: + LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL; + return false; +} + +/** + * Endian handlers + */ +#if LL_BIG_ENDIAN +U64 ll_htonll(U64 hostlonglong) { return hostlonglong; } +U64 ll_ntohll(U64 netlonglong) { return netlonglong; } +F64 ll_htond(F64 hostlonglong) { return hostlonglong; } +F64 ll_ntohd(F64 netlonglong) { return netlonglong; } +#else +// I read some comments one a indicating that doing an integer add +// here would be faster than a bitwise or. For now, the or has +// programmer clarity, since the intended outcome matches the +// operation. +U64 ll_htonll(U64 hostlonglong) +{ + return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) | + ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32)); +} +U64 ll_ntohll(U64 netlonglong) +{ + return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) | + ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32)); +} +union LLEndianSwapper +{ + F64 d; + U64 i; +}; +F64 ll_htond(F64 hostdouble) +{ + LLEndianSwapper tmp; + tmp.d = hostdouble; + tmp.i = ll_htonll(tmp.i); + return tmp.d; +} +F64 ll_ntohd(F64 netdouble) +{ + LLEndianSwapper tmp; + tmp.d = netdouble; + tmp.i = ll_ntohll(tmp.i); + return tmp.d; +} +#endif + +/** + * Local functions. + */ +/** + * @brief Figure out what kind of string it is (raw or delimited) and handoff. + * + * @param istr The stream to read from. + * @param value [out] The string which was found. + * @param max_bytes The maximum possible length of the string. Passing in + * a negative value will skip this check. + * @return Returns number of bytes read off of the stream. Returns + * PARSE_FAILURE (-1) on failure. + */ +int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes); + +/** + * @brief Parse a delimited string. + * + * @param istr The stream to read from, with the delimiter already popped. + * @param value [out] The string which was found. + * @param d The delimiter to use. + * @return Returns number of bytes read off of the stream. Returns + * PARSE_FAILURE (-1) on failure. + */ +int deserialize_string_delim(std::istream& istr, std::string& value, char d); + +/** + * @brief Read a raw string off the stream. + * + * @param istr The stream to read from, with the (len) parameter + * leading the stream. + * @param value [out] The string which was found. + * @param d The delimiter to use. + * @param max_bytes The maximum possible length of the string. Passing in + * a negative value will skip this check. + * @return Returns number of bytes read off of the stream. Returns + * PARSE_FAILURE (-1) on failure. + */ +int deserialize_string_raw( + std::istream& istr, + std::string& value, + S32 max_bytes); + +/** + * @brief helper method for dealing with the different notation boolean format. + * + * @param istr The stream to read from with the leading character stripped. + * @param data [out] the result of the parse. + * @param compare The string to compare the boolean against + * @param vale The value to assign to data if the parse succeeds. + * @return Returns number of bytes read off of the stream. Returns + * PARSE_FAILURE (-1) on failure. + */ +int deserialize_boolean( + std::istream& istr, + LLSD& data, + const std::string& compare, + bool value); + +/** + * @brief Do notation escaping of a string to an ostream. + * + * @param value The string to escape and serialize + * @param str The stream to serialize to. + */ +void serialize_string(const std::string& value, std::ostream& str); + + +/** + * Local constants. + */ +static const std::string NOTATION_TRUE_SERIAL("true"); +static const std::string NOTATION_FALSE_SERIAL("false"); + +static const char BINARY_TRUE_SERIAL = '1'; +static const char BINARY_FALSE_SERIAL = '0'; + + +/** + * LLSDParser + */ +LLSDParser::LLSDParser() + : mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false) +{ +} + +// virtual +LLSDParser::~LLSDParser() +{ } + +S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes, S32 max_depth) +{ + mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true; + mMaxBytesLeft = max_bytes; + return doParse(istr, data, max_depth); +} + + +// Parse using routine to get() lines, faster than parse() +S32 LLSDParser::parseLines(std::istream& istr, LLSD& data) +{ + mCheckLimits = false; + mParseLines = true; + return doParse(istr, data); +} + + +int LLSDParser::get(std::istream& istr) const +{ + if(mCheckLimits) --mMaxBytesLeft; + return istr.get(); +} + +std::istream& LLSDParser::get( + std::istream& istr, + char* s, + std::streamsize n, + char delim) const +{ + istr.get(s, n, delim); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); + return istr; +} + +std::istream& LLSDParser::get( + std::istream& istr, + std::streambuf& sb, + char delim) const +{ + istr.get(sb, delim); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); + return istr; +} + +std::istream& LLSDParser::ignore(std::istream& istr) const +{ + istr.ignore(); + if(mCheckLimits) --mMaxBytesLeft; + return istr; +} + +std::istream& LLSDParser::putback(std::istream& istr, char c) const +{ + istr.putback(c); + if(mCheckLimits) ++mMaxBytesLeft; + return istr; +} + +std::istream& LLSDParser::read( + std::istream& istr, + char* s, + std::streamsize n) const +{ + istr.read(s, n); + if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount(); + return istr; +} + +void LLSDParser::account(S32 bytes) const +{ + if(mCheckLimits) mMaxBytesLeft -= bytes; +} + + +/** + * LLSDNotationParser + */ +LLSDNotationParser::LLSDNotationParser() +{ +} + +// virtual +LLSDNotationParser::~LLSDNotationParser() +{ } + +// virtual +S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const +{ + // map: { string:object, string:object } + // array: [ object, object, object ] + // undef: ! + // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE + // integer: i#### + // real: r#### + // uuid: u#### + // string: "g'day" | 'have a "nice" day' | s(size)"raw data" + // uri: l"escaped" + // date: d"YYYY-MM-DDTHH:MM:SS.FFZ" + // binary: b##"ff3120ab1" | b(size)"raw data" + char c; + c = istr.peek(); + if (max_depth == 0) + { + return PARSE_FAILURE; + } + while(isspace(c)) + { + // pop the whitespace. + c = get(istr); + c = istr.peek(); + continue; + } + if(!istr.good()) + { + return 0; + } + S32 parse_count = 1; + switch(c) + { + case '{': + { + S32 child_count = parseMap(istr, data, max_depth - 1); + if((child_count == PARSE_FAILURE) || data.isUndefined()) + { + parse_count = PARSE_FAILURE; + } + else + { + parse_count += child_count; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading map." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case '[': + { + S32 child_count = parseArray(istr, data, max_depth - 1); + if((child_count == PARSE_FAILURE) || data.isUndefined()) + { + parse_count = PARSE_FAILURE; + } + else + { + parse_count += child_count; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading array." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case '!': + c = get(istr); + data.clear(); + break; + + case '0': + c = get(istr); + data = false; + break; + + case 'F': + case 'f': + ignore(istr); + c = istr.peek(); + if(isalpha(c)) + { + int cnt = deserialize_boolean( + istr, + data, + NOTATION_FALSE_SERIAL, + false); + if(PARSE_FAILURE == cnt) parse_count = cnt; + else account(cnt); + } + else + { + data = false; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + + case '1': + c = get(istr); + data = true; + break; + + case 'T': + case 't': + ignore(istr); + c = istr.peek(); + if(isalpha(c)) + { + int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true); + if(PARSE_FAILURE == cnt) parse_count = cnt; + else account(cnt); + } + else + { + data = true; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + + case 'i': + { + c = get(istr); + S32 integer = 0; + istr >> integer; + data = integer; + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading integer." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'r': + { + c = get(istr); + F64 real = 0.0; + istr >> real; + data = real; + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading real." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'u': + { + c = get(istr); + LLUUID id; + istr >> id; + data = id; + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading uuid." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case '\"': + case '\'': + case 's': + if(!parseString(istr, data)) + { + parse_count = PARSE_FAILURE; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading string." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + + case 'l': + { + c = get(istr); // pop the 'l' + c = get(istr); // pop the delimiter + std::string str; + int cnt = deserialize_string_delim(istr, str, c); + if(PARSE_FAILURE == cnt) + { + parse_count = PARSE_FAILURE; + } + else + { + data = LLURI(str); + account(cnt); + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading link." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'd': + { + c = get(istr); // pop the 'd' + c = get(istr); // pop the delimiter + std::string str; + int cnt = deserialize_string_delim(istr, str, c); + if(PARSE_FAILURE == cnt) + { + parse_count = PARSE_FAILURE; + } + else + { + data = LLDate(str); + account(cnt); + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading date." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'b': + if(!parseBinary(istr, data)) + { + parse_count = PARSE_FAILURE; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading data." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + + default: + parse_count = PARSE_FAILURE; + LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c + << ")" << LL_ENDL; + break; + } + if(PARSE_FAILURE == parse_count) + { + data.clear(); + } + return parse_count; +} + +S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const +{ + // map: { string:object, string:object } + map = LLSD::emptyMap(); + S32 parse_count = 0; + char c = get(istr); + if(c == '{') + { + // eat commas, white + bool found_name = false; + std::string name; + c = get(istr); + while(c != '}' && istr.good()) + { + if(!found_name) + { + if((c == '\"') || (c == '\'') || (c == 's')) + { + putback(istr, c); + found_name = true; + int count = deserialize_string(istr, name, mMaxBytesLeft); + if(PARSE_FAILURE == count) return PARSE_FAILURE; + account(count); + } + c = get(istr); + } + else + { + if(isspace(c) || (c == ':')) + { + c = get(istr); + continue; + } + putback(istr, c); + LLSD child; + S32 count = doParse(istr, child, max_depth); + if(count > 0) + { + // There must be a value for every key, thus + // child_count must be greater than 0. + parse_count += count; + map.insert(name, child); + } + else + { + return PARSE_FAILURE; + } + found_name = false; + c = get(istr); + } + } + if(c != '}') + { + map.clear(); + return PARSE_FAILURE; + } + } + return parse_count; +} + +S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const +{ + // array: [ object, object, object ] + array = LLSD::emptyArray(); + S32 parse_count = 0; + char c = get(istr); + if(c == '[') + { + // eat commas, white + c = get(istr); + while((c != ']') && istr.good()) + { + LLSD child; + if(isspace(c) || (c == ',')) + { + c = get(istr); + continue; + } + putback(istr, c); + S32 count = doParse(istr, child, max_depth); + if(PARSE_FAILURE == count) + { + return PARSE_FAILURE; + } + else + { + parse_count += count; + array.append(child); + } + c = get(istr); + } + if(c != ']') + { + return PARSE_FAILURE; + } + } + return parse_count; +} + +bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const +{ + std::string value; + int count = deserialize_string(istr, value, mMaxBytesLeft); + if(PARSE_FAILURE == count) return false; + account(count); + data = value; + return true; +} + +bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const +{ + // binary: b##"ff3120ab1" + // or: b(len)"..." + + // I want to manually control those values here to make sure the + // parser doesn't break when someone changes a constant somewhere + // else. + const U32 BINARY_BUFFER_SIZE = 256; + const U32 STREAM_GET_COUNT = 255; + + // need to read the base out. + char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */ + get(istr, buf, STREAM_GET_COUNT, '"'); + char c = get(istr); + if(c != '"') return false; + if(0 == strncmp("b(", buf, 2)) + { + // We probably have a valid raw binary stream. determine + // the size, and read it. + S32 len = strtol(buf + 2, NULL, 0); + if(mCheckLimits && (len > mMaxBytesLeft)) return false; + std::vector<U8> value; + if(len) + { + value.resize(len); + account((int)fullread(istr, (char *)&value[0], len)); + } + c = get(istr); // strip off the trailing double-quote + data = value; + } + else if(0 == strncmp("b64", buf, 3)) + { + // *FIX: A bit inefficient, but works for now. To make the + // format better, I would need to add a hint into the + // serialization format that indicated how long it was. + std::stringstream coded_stream; + get(istr, *(coded_stream.rdbuf()), '\"'); + c = get(istr); + std::string encoded(coded_stream.str()); + size_t len = LLBase64::requiredDecryptionSpace(encoded); + std::vector<U8> value; + if(len) + { + value.resize(len); + len = LLBase64::decode(encoded, &value[0], len); + value.resize(len); + } + data = value; + } + else if(0 == strncmp("b16", buf, 3)) + { + // yay, base 16. We pop the next character which is either a + // double quote or base 16 data. If it's a double quote, we're + // done parsing. If it's not, put the data back, and read the + // stream until the next double quote. + char* read; /*Flawfinder: ignore*/ + U8 byte; + U8 byte_buffer[BINARY_BUFFER_SIZE]; + U8* write; + std::vector<U8> value; + c = get(istr); + while(c != '"') + { + putback(istr, c); + read = buf; + write = byte_buffer; + get(istr, buf, STREAM_GET_COUNT, '"'); + c = get(istr); + while(*read != '\0') /*Flawfinder: ignore*/ + { + byte = hex_as_nybble(*read++); + byte = byte << 4; + byte |= hex_as_nybble(*read++); + *write++ = byte; + } + // copy the data out of the byte buffer + value.insert(value.end(), byte_buffer, write); + } + data = value; + } + else + { + return false; + } + return true; +} + + +/** + * LLSDBinaryParser + */ + +// virtual +S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const +{ +/** + * Undefined: '!'<br> + * Boolean: '1' for true '0' for false<br> + * Integer: 'i' + 4 bytes network byte order<br> + * Real: 'r' + 8 bytes IEEE double<br> + * UUID: 'u' + 16 byte unsigned integer<br> + * String: 's' + 4 byte integer size + string<br> + * strings also secretly support the notation format + * Date: 'd' + 8 byte IEEE double for seconds since epoch<br> + * URI: 'l' + 4 byte integer size + string uri<br> + * Binary: 'b' + 4 byte integer size + binary data<br> + * Array: '[' + 4 byte integer size + all values + ']'<br> + * Map: '{' + 4 byte integer size every(key + value) + '}'<br> + * map keys are serialized as s + 4 byte integer size + string or in the + * notation format. + */ + char c; + c = get(istr); + if(!istr.good()) + { + return 0; + } + if (max_depth == 0) + { + return PARSE_FAILURE; + } + S32 parse_count = 1; + switch(c) + { + case '{': + { + S32 child_count = parseMap(istr, data, max_depth - 1); + if((child_count == PARSE_FAILURE) || data.isUndefined()) + { + parse_count = PARSE_FAILURE; + } + else + { + parse_count += child_count; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary map." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case '[': + { + S32 child_count = parseArray(istr, data, max_depth - 1); + if((child_count == PARSE_FAILURE) || data.isUndefined()) + { + parse_count = PARSE_FAILURE; + } + else + { + parse_count += child_count; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary array." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case '!': + data.clear(); + break; + + case '0': + data = false; + break; + + case '1': + data = true; + break; + + case 'i': + { + U32 value_nbo = 0; + read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + data = (S32)ntohl(value_nbo); + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary integer." << LL_ENDL; + } + break; + } + + case 'r': + { + F64 real_nbo = 0.0; + read(istr, (char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/ + data = ll_ntohd(real_nbo); + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary real." << LL_ENDL; + } + break; + } + + case 'u': + { + LLUUID id; + read(istr, (char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/ + data = id; + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary uuid." << LL_ENDL; + } + break; + } + + case '\'': + case '"': + { + std::string value; + int cnt = deserialize_string_delim(istr, value, c); + if(PARSE_FAILURE == cnt) + { + parse_count = PARSE_FAILURE; + } + else + { + data = value; + account(cnt); + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary (notation-style) string." + << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case 's': + { + std::string value; + if(parseString(istr, value)) + { + data = value; + } + else + { + parse_count = PARSE_FAILURE; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary string." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'l': + { + std::string value; + if(parseString(istr, value)) + { + data = LLURI(value); + } + else + { + parse_count = PARSE_FAILURE; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary link." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'd': + { + F64 real = 0.0; + read(istr, (char*)&real, sizeof(F64)); /*Flawfinder: ignore*/ + data = LLDate(real); + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary date." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + case 'b': + { + // We probably have a valid raw binary stream. determine + // the size, and read it. + U32 size_nbo = 0; + read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + S32 size = (S32)ntohl(size_nbo); + if(mCheckLimits && (size > mMaxBytesLeft)) + { + parse_count = PARSE_FAILURE; + } + else + { + std::vector<U8> value; + if(size > 0) + { + value.resize(size); + account((int)fullread(istr, (char*)&value[0], size)); + } + data = value; + } + if(istr.fail()) + { + LL_INFOS() << "STREAM FAILURE reading binary." << LL_ENDL; + parse_count = PARSE_FAILURE; + } + break; + } + + default: + parse_count = PARSE_FAILURE; + LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c + << ")" << LL_ENDL; + break; + } + if(PARSE_FAILURE == parse_count) + { + data.clear(); + } + return parse_count; +} + +S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const +{ + map = LLSD::emptyMap(); + U32 value_nbo = 0; + read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + S32 size = (S32)ntohl(value_nbo); + S32 parse_count = 0; + S32 count = 0; + char c = get(istr); + while(c != '}' && (count < size) && istr.good()) + { + std::string name; + switch(c) + { + case 'k': + if(!parseString(istr, name)) + { + return PARSE_FAILURE; + } + break; + case '\'': + case '"': + { + int cnt = deserialize_string_delim(istr, name, c); + if(PARSE_FAILURE == cnt) return PARSE_FAILURE; + account(cnt); + break; + } + } + LLSD child; + S32 child_count = doParse(istr, child, max_depth); + if(child_count > 0) + { + // There must be a value for every key, thus child_count + // must be greater than 0. + parse_count += child_count; + map.insert(name, child); + } + else + { + return PARSE_FAILURE; + } + ++count; + c = get(istr); + } + if((c != '}') || (count < size)) + { + // Make sure it is correctly terminated and we parsed as many + // as were said to be there. + return PARSE_FAILURE; + } + return parse_count; +} + +S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const +{ + array = LLSD::emptyArray(); + U32 value_nbo = 0; + read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + S32 size = (S32)ntohl(value_nbo); + + // *FIX: This would be a good place to reserve some space in the + // array... + + S32 parse_count = 0; + S32 count = 0; + char c = istr.peek(); + while((c != ']') && (count < size) && istr.good()) + { + LLSD child; + S32 child_count = doParse(istr, child, max_depth); + if(PARSE_FAILURE == child_count) + { + return PARSE_FAILURE; + } + if(child_count) + { + parse_count += child_count; + array.append(child); + } + ++count; + c = istr.peek(); + } + c = get(istr); + if((c != ']') || (count < size)) + { + // Make sure it is correctly terminated and we parsed as many + // as were said to be there. + return PARSE_FAILURE; + } + return parse_count; +} + +bool LLSDBinaryParser::parseString( + std::istream& istr, + std::string& value) const +{ + // *FIX: This is memory inefficient. + U32 value_nbo = 0; + read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ + S32 size = (S32)ntohl(value_nbo); + if(mCheckLimits && (size > mMaxBytesLeft)) return false; + if(size < 0) return false; + std::vector<char> buf; + if(size) + { + buf.resize(size); + account((int)fullread(istr, &buf[0], size)); + value.assign(buf.begin(), buf.end()); + } + return true; +} + + +/** + * LLSDFormatter + */ +LLSDFormatter::LLSDFormatter() : + mBoolAlpha(false) +{ +} + +// virtual +LLSDFormatter::~LLSDFormatter() +{ } + +void LLSDFormatter::boolalpha(bool alpha) +{ + mBoolAlpha = alpha; +} + +void LLSDFormatter::realFormat(const std::string& format) +{ + mRealFormat = format; +} + +void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const +{ + std::string buffer = llformat(mRealFormat.c_str(), real); + ostr << buffer; +} + +/** + * LLSDNotationFormatter + */ +LLSDNotationFormatter::LLSDNotationFormatter() +{ +} + +// virtual +LLSDNotationFormatter::~LLSDNotationFormatter() +{ } + +// static +std::string LLSDNotationFormatter::escapeString(const std::string& in) +{ + std::ostringstream ostr; + serialize_string(in, ostr); + return ostr.str(); +} + +// virtual +S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const +{ + S32 rv = format_impl(data, ostr, options, 0); + return rv; +} + +S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const +{ + S32 format_count = 1; + std::string pre; + std::string post; + + if (options & LLSDFormatter::OPTIONS_PRETTY) + { + for (U32 i = 0; i < level; i++) + { + pre += " "; + } + post = "\n"; + } + + switch(data.type()) + { + case LLSD::TypeMap: + { + if (0 != level) ostr << post << pre; + ostr << "{"; + std::string inner_pre; + if (options & LLSDFormatter::OPTIONS_PRETTY) + { + inner_pre = pre + " "; + } + + bool need_comma = false; + auto iter = data.beginMap(); + auto end = data.endMap(); + for(; iter != end; ++iter) + { + if(need_comma) ostr << ","; + need_comma = true; + ostr << post << inner_pre << '\''; + serialize_string((*iter).first, ostr); + ostr << "':"; + format_count += format_impl((*iter).second, ostr, options, level + 2); + } + ostr << post << pre << "}"; + break; + } + + case LLSD::TypeArray: + { + ostr << post << pre << "["; + bool need_comma = false; + auto iter = data.beginArray(); + auto end = data.endArray(); + for(; iter != end; ++iter) + { + if(need_comma) ostr << ","; + need_comma = true; + format_count += format_impl(*iter, ostr, options, level + 1); + } + ostr << "]"; + break; + } + + case LLSD::TypeUndefined: + ostr << "!"; + break; + + case LLSD::TypeBoolean: + if(mBoolAlpha || +#if( LL_WINDOWS || __GNUC__ > 2) + (ostr.flags() & std::ios::boolalpha) +#else + (ostr.flags() & 0x0100) +#endif + ) + { + ostr << (data.asBoolean() + ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL); + } + else + { + ostr << (data.asBoolean() ? 1 : 0); + } + break; + + case LLSD::TypeInteger: + ostr << "i" << data.asInteger(); + break; + + case LLSD::TypeReal: + ostr << "r"; + if(mRealFormat.empty()) + { + ostr << data.asReal(); + } + else + { + formatReal(data.asReal(), ostr); + } + break; + + case LLSD::TypeUUID: + ostr << "u" << data.asUUID(); + break; + + case LLSD::TypeString: + ostr << '\''; + serialize_string(data.asStringRef(), ostr); + ostr << '\''; + break; + + case LLSD::TypeDate: + ostr << "d\"" << data.asDate() << "\""; + break; + + case LLSD::TypeURI: + ostr << "l\""; + serialize_string(data.asString(), ostr); + ostr << "\""; + break; + + case LLSD::TypeBinary: + { + // *FIX: memory inefficient. + const std::vector<U8>& buffer = data.asBinary(); + ostr << "b(" << buffer.size() << ")\""; + if(!buffer.empty()) + { + if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY) + { + std::ios_base::fmtflags old_flags = ostr.flags(); + ostr.setf( std::ios::hex, std::ios::basefield ); + ostr << "0x"; + for (unsigned char i : buffer) + { + ostr << static_cast<int>(i); + } + ostr.flags(old_flags); + } + else + { + ostr.write(reinterpret_cast<const char*>(&buffer[0]), buffer.size()); + } + } + ostr << "\""; + break; + } + + default: + // *NOTE: This should never happen. + ostr << "!"; + break; + } + return format_count; +} + + +/** + * LLSDBinaryFormatter + */ +LLSDBinaryFormatter::LLSDBinaryFormatter() +{ +} + +// virtual +LLSDBinaryFormatter::~LLSDBinaryFormatter() +{ } + +// virtual +S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const +{ + S32 format_count = 1; + switch(data.type()) + { + case LLSD::TypeMap: + { + ostr.put('{'); + U32 size_nbo = htonl(data.size()); + ostr.write(reinterpret_cast<const char*>(&size_nbo), sizeof(U32)); + auto iter = data.beginMap(); + auto end = data.endMap(); + for(; iter != end; ++iter) + { + ostr.put('k'); + formatString((*iter).first, ostr); + format_count += format((*iter).second, ostr); + } + ostr.put('}'); + break; + } + + case LLSD::TypeArray: + { + ostr.put('['); + U32 size_nbo = htonl(data.size()); + ostr.write(reinterpret_cast<const char*>(&size_nbo), sizeof(U32)); + auto iter = data.beginArray(); + auto end = data.endArray(); + for(; iter != end; ++iter) + { + format_count += format(*iter, ostr); + } + ostr.put(']'); + break; + } + + case LLSD::TypeUndefined: + ostr.put('!'); + break; + + case LLSD::TypeBoolean: + if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL); + else ostr.put(BINARY_FALSE_SERIAL); + break; + + case LLSD::TypeInteger: + { + ostr.put('i'); + U32 value_nbo = htonl(data.asInteger()); + ostr.write((const char*)(&value_nbo), sizeof(U32)); + break; + } + + case LLSD::TypeReal: + { + ostr.put('r'); + F64 value_nbo = ll_htond(data.asReal()); + ostr.write((const char*)(&value_nbo), sizeof(F64)); + break; + } + + case LLSD::TypeUUID: + { + ostr.put('u'); + LLUUID temp = data.asUUID(); + ostr.write((const char*)(&(temp.mData)), UUID_BYTES); + break; + } + + case LLSD::TypeString: + ostr.put('s'); + formatString(data.asStringRef(), ostr); + break; + + case LLSD::TypeDate: + { + ostr.put('d'); + F64 value = data.asReal(); + ostr.write((const char*)(&value), sizeof(F64)); + break; + } + + case LLSD::TypeURI: + ostr.put('l'); + formatString(data.asString(), ostr); + break; + + case LLSD::TypeBinary: + { + ostr.put('b'); + const std::vector<U8>& buffer = data.asBinary(); + U32 size_nbo = htonl(buffer.size()); + ostr.write((const char*)(&size_nbo), sizeof(U32)); + if(!buffer.empty()) ostr.write((const char*)&buffer[0], buffer.size()); + break; + } + + default: + // *NOTE: This should never happen. + ostr.put('!'); + break; + } + return format_count; +} + +void LLSDBinaryFormatter::formatString( + const std::string& string, + std::ostream& ostr) const +{ + U32 size_nbo = htonl(string.size()); + ostr.write((const char*)(&size_nbo), sizeof(U32)); + ostr.write(string.c_str(), string.size()); +} + +/** + * local functions + */ +int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes) +{ + int c = istr.get(); + if(istr.fail()) + { + // No data in stream, bail out but mention the character we + // grabbed. + return LLSDParser::PARSE_FAILURE; + } + + int rv = LLSDParser::PARSE_FAILURE; + switch(c) + { + case '\'': + case '"': + rv = deserialize_string_delim(istr, value, c); + break; + case 's': + // technically, less than max_bytes, but this is just meant to + // catch egregious protocol errors. parse errors will be + // caught in the case of incorrect counts. + rv = deserialize_string_raw(istr, value, max_bytes); + break; + default: + break; + } + if(LLSDParser::PARSE_FAILURE == rv) return rv; + return rv + 1; // account for the character grabbed at the top. +} + +int deserialize_string_delim( + std::istream& istr, + std::string& value, + char delim) +{ + std::ostringstream write_buffer; + bool found_escape = false; + bool found_hex = false; + bool found_digit = false; + U8 byte = 0; + int count = 0; + + while (true) + { + int next_byte = istr.get(); + ++count; + + if(istr.fail()) + { + // If our stream is empty, break out + value = write_buffer.str(); + return LLSDParser::PARSE_FAILURE; + } + + char next_char = (char)next_byte; // Now that we know it's not EOF + + if(found_escape) + { + // next character(s) is a special sequence. + if(found_hex) + { + if(found_digit) + { + found_digit = false; + found_hex = false; + found_escape = false; + byte = byte << 4; + byte |= hex_as_nybble(next_char); + write_buffer << byte; + byte = 0; + } + else + { + // next character is the first nybble of + // + found_digit = true; + byte = hex_as_nybble(next_char); + } + } + else if(next_char == 'x') + { + found_hex = true; + } + else + { + switch(next_char) + { + case 'a': + write_buffer << '\a'; + break; + case 'b': + write_buffer << '\b'; + break; + case 'f': + write_buffer << '\f'; + break; + case 'n': + write_buffer << '\n'; + break; + case 'r': + write_buffer << '\r'; + break; + case 't': + write_buffer << '\t'; + break; + case 'v': + write_buffer << '\v'; + break; + default: + write_buffer << next_char; + break; + } + found_escape = false; + } + } + else if(next_char == '\\') + { + found_escape = true; + } + else if(next_char == delim) + { + break; + } + else + { + write_buffer << next_char; + } + } + + value = write_buffer.str(); + return count; +} + +int deserialize_string_raw( + std::istream& istr, + std::string& value, + S32 max_bytes) +{ + int count = 0; + const S32 BUF_LEN = 20; + char buf[BUF_LEN]; /* Flawfinder: ignore */ + istr.get(buf, BUF_LEN - 1, ')'); + count += (int)istr.gcount(); + int c = istr.get(); + c = istr.get(); + count += 2; + if(((c == '"') || (c == '\'')) && (buf[0] == '(')) + { + // We probably have a valid raw string. determine + // the size, and read it. + // *FIX: This is memory inefficient. + S32 len = strtol(buf + 1, NULL, 0); + if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE; + std::vector<char> buf2; + if(len) + { + buf2.resize(len); + count += (int)fullread(istr, (char *)&buf2[0], len); + value.assign(buf2.begin(), buf2.end()); + } + c = istr.get(); + ++count; + if(!((c == '"') || (c == '\''))) + { + return LLSDParser::PARSE_FAILURE; + } + } + else + { + return LLSDParser::PARSE_FAILURE; + } + return count; +} + +static const char* NOTATION_STRING_CHARACTERS[256] = +{ + "\\x00", // 0 + "\\x01", // 1 + "\\x02", // 2 + "\\x03", // 3 + "\\x04", // 4 + "\\x05", // 5 + "\\x06", // 6 + "\\a", // 7 + "\\b", // 8 + "\\t", // 9 + "\\n", // 10 + "\\v", // 11 + "\\f", // 12 + "\\r", // 13 + "\\x0e", // 14 + "\\x0f", // 15 + "\\x10", // 16 + "\\x11", // 17 + "\\x12", // 18 + "\\x13", // 19 + "\\x14", // 20 + "\\x15", // 21 + "\\x16", // 22 + "\\x17", // 23 + "\\x18", // 24 + "\\x19", // 25 + "\\x1a", // 26 + "\\x1b", // 27 + "\\x1c", // 28 + "\\x1d", // 29 + "\\x1e", // 30 + "\\x1f", // 31 + " ", // 32 + "!", // 33 + "\"", // 34 + "#", // 35 + "$", // 36 + "%", // 37 + "&", // 38 + "\\'", // 39 + "(", // 40 + ")", // 41 + "*", // 42 + "+", // 43 + ",", // 44 + "-", // 45 + ".", // 46 + "/", // 47 + "0", // 48 + "1", // 49 + "2", // 50 + "3", // 51 + "4", // 52 + "5", // 53 + "6", // 54 + "7", // 55 + "8", // 56 + "9", // 57 + ":", // 58 + ";", // 59 + "<", // 60 + "=", // 61 + ">", // 62 + "?", // 63 + "@", // 64 + "A", // 65 + "B", // 66 + "C", // 67 + "D", // 68 + "E", // 69 + "F", // 70 + "G", // 71 + "H", // 72 + "I", // 73 + "J", // 74 + "K", // 75 + "L", // 76 + "M", // 77 + "N", // 78 + "O", // 79 + "P", // 80 + "Q", // 81 + "R", // 82 + "S", // 83 + "T", // 84 + "U", // 85 + "V", // 86 + "W", // 87 + "X", // 88 + "Y", // 89 + "Z", // 90 + "[", // 91 + "\\\\", // 92 + "]", // 93 + "^", // 94 + "_", // 95 + "`", // 96 + "a", // 97 + "b", // 98 + "c", // 99 + "d", // 100 + "e", // 101 + "f", // 102 + "g", // 103 + "h", // 104 + "i", // 105 + "j", // 106 + "k", // 107 + "l", // 108 + "m", // 109 + "n", // 110 + "o", // 111 + "p", // 112 + "q", // 113 + "r", // 114 + "s", // 115 + "t", // 116 + "u", // 117 + "v", // 118 + "w", // 119 + "x", // 120 + "y", // 121 + "z", // 122 + "{", // 123 + "|", // 124 + "}", // 125 + "~", // 126 + "\\x7f", // 127 + "\\x80", // 128 + "\\x81", // 129 + "\\x82", // 130 + "\\x83", // 131 + "\\x84", // 132 + "\\x85", // 133 + "\\x86", // 134 + "\\x87", // 135 + "\\x88", // 136 + "\\x89", // 137 + "\\x8a", // 138 + "\\x8b", // 139 + "\\x8c", // 140 + "\\x8d", // 141 + "\\x8e", // 142 + "\\x8f", // 143 + "\\x90", // 144 + "\\x91", // 145 + "\\x92", // 146 + "\\x93", // 147 + "\\x94", // 148 + "\\x95", // 149 + "\\x96", // 150 + "\\x97", // 151 + "\\x98", // 152 + "\\x99", // 153 + "\\x9a", // 154 + "\\x9b", // 155 + "\\x9c", // 156 + "\\x9d", // 157 + "\\x9e", // 158 + "\\x9f", // 159 + "\\xa0", // 160 + "\\xa1", // 161 + "\\xa2", // 162 + "\\xa3", // 163 + "\\xa4", // 164 + "\\xa5", // 165 + "\\xa6", // 166 + "\\xa7", // 167 + "\\xa8", // 168 + "\\xa9", // 169 + "\\xaa", // 170 + "\\xab", // 171 + "\\xac", // 172 + "\\xad", // 173 + "\\xae", // 174 + "\\xaf", // 175 + "\\xb0", // 176 + "\\xb1", // 177 + "\\xb2", // 178 + "\\xb3", // 179 + "\\xb4", // 180 + "\\xb5", // 181 + "\\xb6", // 182 + "\\xb7", // 183 + "\\xb8", // 184 + "\\xb9", // 185 + "\\xba", // 186 + "\\xbb", // 187 + "\\xbc", // 188 + "\\xbd", // 189 + "\\xbe", // 190 + "\\xbf", // 191 + "\\xc0", // 192 + "\\xc1", // 193 + "\\xc2", // 194 + "\\xc3", // 195 + "\\xc4", // 196 + "\\xc5", // 197 + "\\xc6", // 198 + "\\xc7", // 199 + "\\xc8", // 200 + "\\xc9", // 201 + "\\xca", // 202 + "\\xcb", // 203 + "\\xcc", // 204 + "\\xcd", // 205 + "\\xce", // 206 + "\\xcf", // 207 + "\\xd0", // 208 + "\\xd1", // 209 + "\\xd2", // 210 + "\\xd3", // 211 + "\\xd4", // 212 + "\\xd5", // 213 + "\\xd6", // 214 + "\\xd7", // 215 + "\\xd8", // 216 + "\\xd9", // 217 + "\\xda", // 218 + "\\xdb", // 219 + "\\xdc", // 220 + "\\xdd", // 221 + "\\xde", // 222 + "\\xdf", // 223 + "\\xe0", // 224 + "\\xe1", // 225 + "\\xe2", // 226 + "\\xe3", // 227 + "\\xe4", // 228 + "\\xe5", // 229 + "\\xe6", // 230 + "\\xe7", // 231 + "\\xe8", // 232 + "\\xe9", // 233 + "\\xea", // 234 + "\\xeb", // 235 + "\\xec", // 236 + "\\xed", // 237 + "\\xee", // 238 + "\\xef", // 239 + "\\xf0", // 240 + "\\xf1", // 241 + "\\xf2", // 242 + "\\xf3", // 243 + "\\xf4", // 244 + "\\xf5", // 245 + "\\xf6", // 246 + "\\xf7", // 247 + "\\xf8", // 248 + "\\xf9", // 249 + "\\xfa", // 250 + "\\xfb", // 251 + "\\xfc", // 252 + "\\xfd", // 253 + "\\xfe", // 254 + "\\xff" // 255 +}; + +void serialize_string(const std::string& value, std::ostream& str) +{ + std::string::const_iterator it = value.begin(); + std::string::const_iterator end = value.end(); + U8 c; + for(; it != end; ++it) + { + c = (U8)(*it); + str << NOTATION_STRING_CHARACTERS[c]; + } +} + +int deserialize_boolean( + std::istream& istr, + LLSD& data, + const std::string& compare, + bool value) +{ + // + // this method is a little goofy, because it gets the stream at + // the point where the t or f has already been + // consumed. Basically, parse for a patch to the string passed in + // starting at index 1. If it's a match: + // * assign data to value + // * return the number of bytes read + // otherwise: + // * set data to LLSD::null + // * return LLSDParser::PARSE_FAILURE (-1) + // + int bytes_read = 0; + std::string::size_type ii = 0; + char c = istr.peek(); + while((++ii < compare.size()) + && (tolower(c) == (int)compare[ii]) + && istr.good()) + { + istr.ignore(); + ++bytes_read; + c = istr.peek(); + } + if(compare.size() != ii) + { + data.clear(); + return LLSDParser::PARSE_FAILURE; + } + data = value; + return bytes_read; +} + +std::ostream& operator<<(std::ostream& s, const LLSD& llsd) +{ + s << LLSDNotationStreamer(llsd); + return s; +} + + +//dirty little zippers -- yell at davep if these are horrid + +//return a string containing gzipped bytes of binary serialized LLSD +// VERY inefficient -- creates several copies of LLSD block in memory +std::string zip_llsd(LLSD& data) +{ + std::stringstream llsd_strm; + + LLSDSerialize::toBinary(data, llsd_strm); + + const U32 CHUNK = 65536; + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION); + if (ret != Z_OK) + { + LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; + return std::string(); + } + + std::string source = llsd_strm.str(); + + U8 out[CHUNK]; + + strm.avail_in = source.size(); + strm.next_in = (U8*) source.data(); + U8* output = NULL; + + U32 cur_size = 0; + + U32 have = 0; + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + + ret = deflate(&strm, Z_FINISH); + if (ret == Z_OK || ret == Z_STREAM_END) + { //copy result into output + if (strm.avail_out >= CHUNK) + { + free(output); + LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; + return std::string(); + } + + have = CHUNK-strm.avail_out; + U8* new_output = (U8*) realloc(output, cur_size+have); + if (new_output == NULL) + { + LL_WARNS() << "Failed to compress LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL; + deflateEnd(&strm); + if (output) + { + free(output); + } + return std::string(); + } + output = new_output; + memcpy(output+cur_size, out, have); + cur_size += have; + } + else + { + free(output); + LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; + return std::string(); + } + } + while (ret == Z_OK); + + std::string::size_type size = cur_size; + + std::string result((char*) output, size); + deflateEnd(&strm); + free(output); + + return result; +} + +// <alchemy> +//decompress a block of LLSD from provided istream +// not very efficient -- creats a copy of decompressed LLSD block in memory +// and deserializes from that copy using LLSDSerialize +LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size) +{ + std::unique_ptr<U8 []> in; + try + { + in = std::make_unique<U8 []>(size); + } + catch (const std::bad_alloc&) + { + return ZR_MEM_ERROR; + } + is.read((char*)in.get(), size); + + return unzip_llsd(data, in.get(), size); +} + +LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, U8* in, S32 size) +{ + U8* result = NULL; + U32 cur_size = 0; + z_stream strm; + + const U32 CHUNK = 65536; + + U8 out[CHUNK]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = size; + strm.next_in = in; + + S32 ret = inflateInit(&strm); + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + case Z_STREAM_ERROR: + inflateEnd(&strm); + free(result); + return ZR_MEM_ERROR; + break; + } + + U32 have = CHUNK-strm.avail_out; + + U8* new_result = (U8*)realloc(result, cur_size + have); + if (new_result == NULL) + { + LL_WARNS() << "Failed to unzip LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL; + inflateEnd(&strm); + if (result) + { + free(result); + } + return ZR_MEM_ERROR; + } + result = new_result; + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (ret == Z_OK); + + inflateEnd(&strm); + + if (ret != Z_STREAM_END) + { + free(result); + return ZR_DATA_ERROR; + } + + //result now points to the decompressed LLSD block + { + char* result_ptr = strip_deprecated_header((char*)result, cur_size); + + boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size); + + if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH)) + { + LL_WARNS() << "Failed to unzip LLSD block" << LL_ENDL; + free(result); + return ZR_PARSE_ERROR; + } + } + + free(result); + return ZR_OK; +} + +//This unzip function will only work with a gzip header and trailer - while the contents +//of the actual compressed data is the same for either format (gzip vs zlib ), the headers +//and trailers are different for the formats. +U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, std::istream& is, S32 size) +{ + if (size == 0) + { + LL_WARNS() << "No data to unzip." << LL_ENDL; + return NULL; + } + auto in = std::make_unique<U8[]>(size); + is.read((char*)in.get(), size); + return unzip_llsdNavMesh(valid, outsize, in.get(), size); +} + +U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, U8* in, S32 size ) +{ + if (size == 0) + { + LL_WARNS() << "No data to unzip." << LL_ENDL; + return NULL; + } + U8* result = NULL; + U32 cur_size = 0; + z_stream strm; + + const U32 CHUNK = 0x4000; + + U8 out[CHUNK]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = size; + strm.next_in = in; + + + S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + case Z_STREAM_ERROR: + inflateEnd(&strm); + free(result); + valid = false; + return NULL; + } + U32 have = CHUNK-strm.avail_out; + + U8* new_result = (U8*) realloc(result, cur_size + have); + if (new_result == NULL) + { + LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size + << " bytes; requested " << cur_size + have + << " bytes; total syze: ." << size << " bytes." + << LL_ENDL; + inflateEnd(&strm); + if (result) + { + free(result); + } + valid = false; + return NULL; + } + result = new_result; + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (ret == Z_OK); + + inflateEnd(&strm); + + if (ret != Z_STREAM_END) + { + free(result); + valid = false; + return NULL; + } + + //result now points to the decompressed LLSD block + { + outsize= cur_size; + valid = true; + } + + return result; +} + +char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size) +{ + const char* deprecated_header = "<? LLSD/Binary ?>"; + constexpr size_t deprecated_header_size = 17; + + if (cur_size > deprecated_header_size + && memcmp(in, deprecated_header, deprecated_header_size) == 0) + { + in = in + deprecated_header_size; + cur_size = cur_size - deprecated_header_size; + if (header_size) + { + *header_size = deprecated_header_size + 1; + } + } + + return in; +} +// </alchemy> + diff --git a/indra/llmessage/llmessageprecompiled.cpp b/indra/llmessage/llmessageprecompiled.cpp index 4c43c94f033420b35b1f348b561634d7e8e2342e..3ee59cdbb91bb025b605f839b0eba7e2b7fb27f3 100644 --- a/indra/llmessage/llmessageprecompiled.cpp +++ b/indra/llmessage/llmessageprecompiled.cpp @@ -1,27 +1,27 @@ -/** - * @file llmessageprecompiled.cpp - * @brief Includes common headers - * - * $LicenseInfo:firstyear=2019&license=viewerlgpl$ - * Alchemy Viewer Source Code - * Copyright (C) 2019, Alchemy Viewer Project, 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 "llmessageprecompiled.h" +/** + * @file llmessageprecompiled.cpp + * @brief Includes common headers + * + * $LicenseInfo:firstyear=2019&license=viewerlgpl$ + * Alchemy Viewer Source Code + * Copyright (C) 2019, Alchemy Viewer Project, 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 "llmessageprecompiled.h" diff --git a/indra/llmessage/llmessageprecompiled.h b/indra/llmessage/llmessageprecompiled.h index 3aef589ac50093b3a8eff72349dc02d6d0a25224..12679d7830e13a192fe97720f4dc5b98b845ba94 100644 --- a/indra/llmessage/llmessageprecompiled.h +++ b/indra/llmessage/llmessageprecompiled.h @@ -1,43 +1,43 @@ -/** - * @file llmessageprecompiled.h - * @brief Includes common headers - * - * $LicenseInfo:firstyear=2019&license=viewerlgpl$ - * Alchemy Viewer Source Code - * Copyright (C) 2019, Alchemy Viewer Project, 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_LLMESSAGEPRECOMPILED_H -#define LL_LLMESSAGEPRECOMPILED_H - -#include "linden_common.h" - -#include "llwin32headerslean.h" - -#include "llapr.h" -#include "llsd.h" -#include "llsingleton.h" -#include "llstring.h" -#include "llstringtable.h" -#include "llstl.h" -#include "lltimer.h" - -#endif // LL_LLMESSAGEPRECOMPILED_H - +/** + * @file llmessageprecompiled.h + * @brief Includes common headers + * + * $LicenseInfo:firstyear=2019&license=viewerlgpl$ + * Alchemy Viewer Source Code + * Copyright (C) 2019, Alchemy Viewer Project, 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_LLMESSAGEPRECOMPILED_H +#define LL_LLMESSAGEPRECOMPILED_H + +#include "linden_common.h" + +#include "llwin32headerslean.h" + +#include "llapr.h" +#include "llsd.h" +#include "llsingleton.h" +#include "llstring.h" +#include "llstringtable.h" +#include "llstl.h" +#include "lltimer.h" + +#endif // LL_LLMESSAGEPRECOMPILED_H + diff --git a/indra/llui/lluiprecompiled.cpp b/indra/llui/lluiprecompiled.cpp index 9a722ae709d3ae9f4e62c1253add314445c1dd66..60433436429525db98e67f581e39bdde94afe69d 100644 --- a/indra/llui/lluiprecompiled.cpp +++ b/indra/llui/lluiprecompiled.cpp @@ -1,27 +1,27 @@ -/** - * @file lluiprecompiled.cpp - * @brief Includes common headers - * - * $LicenseInfo:firstyear=2019&license=viewerlgpl$ - * Alchemy Viewer Source Code - * Copyright (C) 2019, Alchemy Viewer Project, 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 "lluiprecompiled.h" +/** + * @file lluiprecompiled.cpp + * @brief Includes common headers + * + * $LicenseInfo:firstyear=2019&license=viewerlgpl$ + * Alchemy Viewer Source Code + * Copyright (C) 2019, Alchemy Viewer Project, 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 "lluiprecompiled.h" diff --git a/indra/llui/lluiprecompiled.h b/indra/llui/lluiprecompiled.h index b112559582ad279981b7bed0b6a729cf8670e947..adc541809fd6c19b64e0f988965fa25241dd3ed0 100644 --- a/indra/llui/lluiprecompiled.h +++ b/indra/llui/lluiprecompiled.h @@ -1,74 +1,74 @@ -/** - * @file lluiprecompiled.h - * @brief Includes common headers - * - * $LicenseInfo:firstyear=2019&license=viewerlgpl$ - * Alchemy Viewer Source Code - * Copyright (C) 2019, Alchemy Viewer Project, 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_LLUIPRECOMPILED_H -#define LL_LLUIPRECOMPILED_H - -#include "linden_common.h" - -#include <functional> -#include <map> -#include <limits> -#include <list> -#include <memory> -#include <queue> -#include <vector> - -#include "absl/container/node_hash_map.h" -#include <absl/container/flat_hash_map.h> - -#include "llhandle.h" -#include "llfasttimer.h" -#include "llframetimer.h" -#include "llheteromap.h" -#include "llinitparam.h" -#include "llinstancetracker.h" -#include "llpointer.h" -#include "llregistry.h" -#include "llsd.h" -#include "llsingleton.h" -#include "llstl.h" -#include "llstring.h" -#include "lltreeiterators.h" - -#include "llcoord.h" -#include "llrect.h" -#include "llquaternion.h" -#include "v2math.h" -#include "v4color.h" -#include "m3math.h" - -#include "lldir.h" - -#include "llgl.h" -#include "llfontgl.h" -#include "llglslshader.h" -#include "llrender2dutils.h" - -#include "llcontrol.h" -#include "llxmlnode.h" - -#endif // LL_LLUIPRECOMPILED_H +/** + * @file lluiprecompiled.h + * @brief Includes common headers + * + * $LicenseInfo:firstyear=2019&license=viewerlgpl$ + * Alchemy Viewer Source Code + * Copyright (C) 2019, Alchemy Viewer Project, 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_LLUIPRECOMPILED_H +#define LL_LLUIPRECOMPILED_H + +#include "linden_common.h" + +#include <functional> +#include <map> +#include <limits> +#include <list> +#include <memory> +#include <queue> +#include <vector> + +#include "absl/container/node_hash_map.h" +#include <absl/container/flat_hash_map.h> + +#include "llhandle.h" +#include "llfasttimer.h" +#include "llframetimer.h" +#include "llheteromap.h" +#include "llinitparam.h" +#include "llinstancetracker.h" +#include "llpointer.h" +#include "llregistry.h" +#include "llsd.h" +#include "llsingleton.h" +#include "llstl.h" +#include "llstring.h" +#include "lltreeiterators.h" + +#include "llcoord.h" +#include "llrect.h" +#include "llquaternion.h" +#include "v2math.h" +#include "v4color.h" +#include "m3math.h" + +#include "lldir.h" + +#include "llgl.h" +#include "llfontgl.h" +#include "llglslshader.h" +#include "llrender2dutils.h" + +#include "llcontrol.h" +#include "llxmlnode.h" + +#endif // LL_LLUIPRECOMPILED_H diff --git a/indra/llwindow/llwindowsdl2.cpp b/indra/llwindow/llwindowsdl2.cpp index 9ed1581272551ffa31b05cc49d7072d5e1d8bf5c..5519582069772c225035b2aa726bc1d92d69208f 100644 --- a/indra/llwindow/llwindowsdl2.cpp +++ b/indra/llwindow/llwindowsdl2.cpp @@ -46,7 +46,7 @@ #include "SDL2/SDL_syswm.h" #if LL_WINDOWS -#include <commdlg.h> +#include <commdlg.h> #include <shellapi.h> #include "../newview/res/resource.h" #endif diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 6d4a92e2f60f5bd495ccda67dd294545f079575d..ffae438d9b0250c47e0f826a0a27c6ca65ec5409 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -1,642 +1,642 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; secondlife setup.nsi -;; Copyright 2004-2011, Linden Research, Inc. -;; Copyright 2013-2015 Alchemy Viewer Project -;; -;; 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 -;; -;; NSIS 3 or higher required for Unicode support -;; -;; Author: James Cook, Don Kjer, Callum Prentice, Drake Arconis -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;-------------------------------- -;Unicode - Unicode true - -;-------------------------------- -;Include Modern UI - - !include "LogicLib.nsh" - !include "StdUtils.nsh" - !include "FileFunc.nsh" - !insertmacro GetParameters - !insertmacro GetOptions - !include "x64.nsh" - !include "WinVer.nsh" - !include "MUI2.nsh" - -;------------------------------- -;Global Variables - ; These will be replaced by manifest scripts - %%INST_VARS%% - %%WIN64_BIN_BUILD%% - - Var INSTEXE - Var INSTPROG - Var VIEWER_EXE - Var INSTSHORTCUT - Var AUTOSTART - Var COMMANDLINE ; command line passed to this installer, set in .onInit - Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer - Var SKIP_DIALOGS ; set from command line in .onInit. autoinstall - ; GUI and the defaults. - Var STARTMENUFOLDER - -;-------------------------------- -;Registry Keys - !define ALCHEMY_KEY "SOFTWARE\${VENDORSTR}" - !define INSTNAME_KEY "${ALCHEMY_KEY}\${APPNAMEONEWORD}" - !define MSCURRVER_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion" - !define MSNTCURRVER_KEY "SOFTWARE\Microsoft\Windows NT\CurrentVersion" - !define MSUNINSTALL_KEY "${MSCURRVER_KEY}\Uninstall\${APPNAMEONEWORD}" - -;-------------------------------- -;General - - ;Name and file - Name "${APPNAME}" - OutFile "${INSTOUTFILE}" - Caption "${CAPTIONSTR}" - BrandingText "${VENDORSTR}" - - ;Default installation folder -!ifdef WIN64_BIN_BUILD - InstallDir "$PROGRAMFILES64\${APPNAMEONEWORD}" -!else - InstallDir "$PROGRAMFILES\${APPNAMEONEWORD}" -!endif - - ;Get installation folder from registry if available and 32bit otherwise do it in init -!ifndef WIN64_BIN_BUILD - InstallDirRegKey HKLM "${INSTNAME_KEY}" "" -!endif - - ;Request application privileges for Windows UAC - RequestExecutionLevel admin - - ;Compression - SetCompress auto ; compress to saves space - SetCompressor /solid /final lzma ; compress whole installer as one block - - ;File Handling - SetOverwrite on - - ;Verify CRC - CRCCheck on - -;-------------------------------- -;Version Information - - VIProductVersion "${VERSION_LONG}" - VIAddVersionKey "ProductName" "${APPNAME} Installer" - VIAddVersionKey "Comments" "A viewer for the meta-verse!" - VIAddVersionKey "CompanyName" "Alchemy Viewer Project" - VIAddVersionKey "LegalCopyright" "Copyright © 2013-2019, Alchemy Viewer Project" - VIAddVersionKey "FileDescription" "${APPNAME} Installer" - VIAddVersionKey "ProductVersion" "${VERSION_LONG}" - VIAddVersionKey "FileVersion" "${VERSION_LONG}" - -;-------------------------------- -;Interface Settings - - ;Show Details - ShowInstDetails hide - ShowUninstDetails hide - - !define MUI_ICON "%%SOURCE%%\installers\windows\install_icon.ico" - !define MUI_UNICON "%%SOURCE%%\installers\windows\uninstall_icon.ico" - !define MUI_WELCOMEFINISHPAGE_BITMAP "%%SOURCE%%\installers\windows\install_welcome.bmp" - !define MUI_UNWELCOMEFINISHPAGE_BITMAP "%%SOURCE%%\installers\windows\uninstall_welcome.bmp" - !define MUI_ABORTWARNING - -;-------------------------------- -;Language Selection Dialog Settings - - ;Show all languages, despite user's codepage - !define MUI_LANGDLL_ALLLANGUAGES - - ;Remember the installer language - !define MUI_LANGDLL_REGISTRY_ROOT "HKLM" - !define MUI_LANGDLL_REGISTRY_KEY "${INSTNAME_KEY}" - !define MUI_LANGDLL_REGISTRY_VALUENAME "InstallerLanguage" - - ;Always show the dialog - !define MUI_LANGDLL_ALWAYSSHOW - -;-------------------------------- -;Install Pages - - !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip - !insertmacro MUI_PAGE_WELCOME - - ;License Page - !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip - !insertmacro MUI_PAGE_LICENSE "%%SOURCE%%\..\..\doc\LGPL-licence.txt" - - ;Directory Page - !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip - !insertmacro MUI_PAGE_DIRECTORY - - ;Start Menu Folder Page - !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" - !define MUI_STARTMENUPAGE_REGISTRY_KEY "${INSTNAME_KEY}" - !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" - !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip - !insertmacro MUI_PAGE_STARTMENU Application $STARTMENUFOLDER - - ;Install Progress Page - !define MUI_PAGE_CUSTOMFUNCTION_LEAVE CheckWindowsServPack - !insertmacro MUI_PAGE_INSTFILES - - ; Finish Page - !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip_finish - !define MUI_FINISHPAGE_RUN - !define MUI_FINISHPAGE_RUN_FUNCTION launch_viewer - !define MUI_FINISHPAGE_SHOWREADME - !define MUI_FINISHPAGE_SHOWREADME_TEXT "Create Desktop Shortcut" - !define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED - !define MUI_FINISHPAGE_SHOWREADME_FUNCTION create_desktop_shortcut - !define MUI_FINISHPAGE_NOREBOOTSUPPORT - !insertmacro MUI_PAGE_FINISH - -;-------------------------------- -;Uninstall Pages - - !insertmacro MUI_UNPAGE_WELCOME - !insertmacro MUI_UNPAGE_CONFIRM - !insertmacro MUI_UNPAGE_INSTFILES - !insertmacro MUI_UNPAGE_FINISH - -;-------------------------------- -;Languages - - !include "%%SOURCE%%\installers\windows\lang_en-us.nsi" - !include "%%SOURCE%%\installers\windows\lang_de.nsi" - !include "%%SOURCE%%\installers\windows\lang_es.nsi" - !include "%%SOURCE%%\installers\windows\lang_fr.nsi" - !include "%%SOURCE%%\installers\windows\lang_ja.nsi" - !include "%%SOURCE%%\installers\windows\lang_it.nsi" - !include "%%SOURCE%%\installers\windows\lang_pt-br.nsi" - !include "%%SOURCE%%\installers\windows\lang_ru.nsi" - !include "%%SOURCE%%\installers\windows\lang_tr.nsi" - !include "%%SOURCE%%\installers\windows\lang_zh.nsi" - -;-------------------------------- -;Reserve Files - - ;If you are using solid compression, files that are required before - ;the actual installation should be stored first in the data block, - ;because this will make your installer start faster. - - !insertmacro MUI_RESERVEFILE_LANGDLL - ReserveFile "${NSISDIR}\Plugins\x86-unicode\NSISdl.dll" - ReserveFile "${NSISDIR}\Plugins\x86-unicode\nsDialogs.dll" - ReserveFile "${NSISDIR}\Plugins\x86-unicode\StartMenu.dll" - ReserveFile "${NSISDIR}\Plugins\x86-unicode\StdUtils.dll" - ReserveFile "${NSISDIR}\Plugins\x86-unicode\System.dll" - ReserveFile "${NSISDIR}\Plugins\x86-unicode\UserInfo.dll" - -;-------------------------------- -; Local Functions - -;Page pre-checks for skip conditions -Function check_skip - StrCmp $SKIP_DIALOGS "true" 0 +2 - Abort -FunctionEnd - -Function check_skip_finish - StrCmp $SKIP_DIALOGS "true" 0 +4 - StrCmp $AUTOSTART "true" 0 +3 - Call launch_viewer - Abort -FunctionEnd - -Function launch_viewer - ${StdUtils.ExecShellAsUser} $0 "$INSTDIR\$INSTEXE" "open" "precheck $INSTDIR\$VIEWER_EXE $SHORTCUT_LANG_PARAM" -FunctionEnd - -Function create_desktop_shortcut - CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" -FunctionEnd - -;Check version compatibility -Function CheckWindowsVersion -!ifdef WIN64_BIN_BUILD - ${IfNot} ${RunningX64} - MessageBox MB_OK|MB_ICONSTOP "This version requires a 64 bit operating system." - Quit - ${EndIf} -!endif - - ${If} ${AtMostWinVista} - MessageBox MB_OK $(CheckWindowsVersionMB) - Quit - ${EndIf} -FunctionEnd - -;Check service pack compatibility and suggest upgrade -Function CheckWindowsServPack - ${If} ${IsWin7} - ${AndIfNot} ${IsServicePack} 1 - MessageBox MB_OK $(CheckWindowsServPackMB) - DetailPrint $(UseLatestServPackDP) - Return - ${EndIf} - - ${If} ${IsWin2008R2} - ${AndIfNot} ${IsServicePack} 1 - MessageBox MB_OK $(CheckWindowsServPackMB) - DetailPrint $(UseLatestServPackDP) - Return - ${EndIf} -FunctionEnd - -;Make sure the user can install/uninstall -Function CheckIfAdministrator - DetailPrint $(CheckAdministratorInstDP) - UserInfo::GetAccountType - Pop $R0 - StrCmp $R0 "Admin" lbl_is_admin - MessageBox MB_OK $(CheckAdministratorInstMB) - Quit -lbl_is_admin: - Return -FunctionEnd - -Function un.CheckIfAdministrator - DetailPrint $(CheckAdministratorUnInstDP) - UserInfo::GetAccountType - Pop $R0 - StrCmp $R0 "Admin" lbl_is_admin - MessageBox MB_OK $(CheckAdministratorUnInstMB) - Quit -lbl_is_admin: - Return -FunctionEnd - -;Checks for CPU compatibility -Function CheckCPUFlags - Push $1 - System::Call 'kernel32::IsProcessorFeaturePresent(i) i(10) .r1' - IntCmp $1 1 OK_SSE2 - MessageBox MB_OKCANCEL $(MissingSSE2) /SD IDOK IDOK OK_SSE2 - Quit - - OK_SSE2: - Pop $1 - Return -FunctionEnd - -;Checks if installed version is same as installer and offers to cancel -Function CheckIfAlreadyCurrent -!ifdef WIN64_BIN_BUILD - SetRegView 64 -!endif - Push $0 - ReadRegStr $0 HKLM "SOFTWARE\${VENDORSTR}\$INSTPROG" "Version" - StrCmp $0 ${VERSION_LONG} 0 continue_install - StrCmp $SKIP_DIALOGS "true" continue_install - MessageBox MB_OKCANCEL $(CheckIfCurrentMB) /SD IDOK IDOK continue_install - Quit -continue_install: - Pop $0 - Return -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Close the program, if running. Modifies no variables. -; Allows user to bail out of install process. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function CloseSecondLife - Push $0 - FindWindow $0 "Alchemy" "" - IntCmp $0 0 DONE - - StrCmp $SKIP_DIALOGS "true" CLOSE - MessageBox MB_OKCANCEL $(CloseSecondLifeInstMB) IDOK CLOSE IDCANCEL CANCEL_INSTALL - - CANCEL_INSTALL: - Quit - - CLOSE: - DetailPrint $(CloseSecondLifeInstDP) - SendMessage $0 16 0 0 - - LOOP: - FindWindow $0 "Alchemy" "" - IntCmp $0 0 DONE - Sleep 500 - Goto LOOP - - DONE: - Pop $0 - Return -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Close the program, if running. Modifies no variables. -; Allows user to bail out of uninstall process. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function un.CloseSecondLife - Push $0 - FindWindow $0 "Alchemy" "" - IntCmp $0 0 DONE - MessageBox MB_OKCANCEL $(CloseSecondLifeUnInstMB) IDOK CLOSE IDCANCEL CANCEL_UNINSTALL - - CANCEL_UNINSTALL: - Quit - - CLOSE: - DetailPrint $(CloseSecondLifeUnInstDP) - SendMessage $0 16 0 0 - - LOOP: - FindWindow $0 "Alchemy" "" - IntCmp $0 0 DONE - Sleep 500 - Goto LOOP - - DONE: - Pop $0 - Return -FunctionEnd - - - -;-------------------------------- -;Installer Sections - -Section "Viewer" - SectionIn RO - SetShellVarContext all -!ifdef WIN64_BIN_BUILD - SetRegView 64 -!endif - ;Start with some default values. - StrCpy $INSTPROG "${APPNAMEONEWORD}" - StrCpy $INSTEXE "${INSTEXE}" - StrCpy $VIEWER_EXE "${VIEWER_EXE}" - StrCpy $INSTSHORTCUT "${APPNAME}" - - Call CheckIfAlreadyCurrent - Call CloseSecondLife ; Make sure we're not running - - SetOutPath "$INSTDIR" - ;Remove all old files first to prevent incorrect installation - ;RMDir /r "$INSTDIR\*" - RMDir /r "$INSTDIR\app_settings" - RMDir /r "$INSTDIR\llplugin" - RMDir /r "$INSTDIR\skins" - RMDir /r "$INSTDIR\voice" - - ;This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py - %%INSTALL_FILES%% - - ;Pass the installer's language to the client to use as a default - StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)" - - ;Create startmenu shortcuts - !insertmacro MUI_STARTMENU_WRITE_BEGIN Application - CreateDirectory "$SMPROGRAMS\$STARTMENUFOLDER" -!ifdef WIN64_BIN_BUILD - CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\$INSTSHORTCUT x64.lnk" "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" - CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\Uninstall $INSTSHORTCUT x64.lnk" "$\"$INSTDIR\uninst.exe$\"" "" -!else - CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\$INSTSHORTCUT.lnk" "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" - CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\Uninstall $INSTSHORTCUT.lnk" "$INSTDIR\uninst.exe" "" -!endif - WriteINIStr "$SMPROGRAMS\$STARTMENUFOLDER\SL Create Account.url" "InternetShortcut" "URL" "http://join.secondlife.com/" - WriteINIStr "$SMPROGRAMS\$STARTMENUFOLDER\SL Your Account.url" "InternetShortcut" "URL" "http://www.secondlife.com/account/" - WriteINIStr "$SMPROGRAMS\$STARTMENUFOLDER\SL Scripting Language Help.url" "InternetShortcut" "URL" "http://wiki.secondlife.com/wiki/LSL_Portal" - - !insertmacro MUI_STARTMENU_WRITE_END - - ;Other shortcuts - SetOutPath "$INSTDIR" - CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" - CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" "$INSTDIR\uninst.exe" "" - - ;Write registry - WriteRegStr HKLM "${INSTNAME_KEY}" "" "$INSTDIR" - WriteRegStr HKLM "${INSTNAME_KEY}" "Version" "${VERSION_LONG}" - WriteRegStr HKLM "${INSTNAME_KEY}" "Shortcut" "$INSTSHORTCUT" - WriteRegStr HKLM "${INSTNAME_KEY}" "Exe" "$VIEWER_EXE" - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "Comments" "A viewer for the meta-verse!" -!ifdef WIN64_BIN_BUILD - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayName" "$INSTSHORTCUT x64" -!else - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayName" "$INSTSHORTCUT" -!endif - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayIcon" "$INSTDIR\$VIEWER_EXE" - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayVersion" "${VERSION_LONG}" - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "InstallLocation" "$INSTDIR" - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "InstallSource" "$EXEDIR\" - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "HelpLink" "https://www.alchemyviewer.org" - WriteRegDWORD HKLM "${MSUNINSTALL_KEY}" "NoModify" 1 - WriteRegDWORD HKLM "${MSUNINSTALL_KEY}" "NoRepair" 1 - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "Publisher" "${VENDORSTR}" - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "URLInfoAbout" "https://www.alchemyviewer.org" - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "URLUpdateInfo" "https://www.alchemyviewer.org/p/downloads.html" - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "UninstallString" "$\"$INSTDIR\uninst.exe$\"" - WriteRegStr HKLM "${MSUNINSTALL_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninst.exe$\" /S" - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "EstimatedSize" "$0" - - - ;Write URL registry info - DeleteRegKey HKEY_CLASSES_ROOT "${URLNAME}" - WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "" "URL:Second Life" - WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "URL Protocol" "" - WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\DefaultIcon" "" "$INSTDIR\$VIEWER_EXE" - ;; URL param must be last item passed to viewer, it ignores subsequent params - ;; to avoid parameter injection attacks. - WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\shell" "" "open" -!ifdef WIN64_BIN_BUILD - WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open" "FriendlyAppName" "$INSTSHORTCUT x64" -!else - WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open" "FriendlyAppName" "$INSTSHORTCUT" -!endif - WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" "$\"$INSTDIR\$VIEWER_EXE$\" -url $\"%1$\"" - - DeleteRegKey HKEY_CLASSES_ROOT "x-grid-info" - WriteRegStr HKEY_CLASSES_ROOT "x-grid-info" "" "URL:Hypergrid" - WriteRegStr HKEY_CLASSES_ROOT "x-grid-info" "URL Protocol" "" - WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\DefaultIcon" "" "$INSTDIR\$VIEWER_EXE" - ;; URL param must be last item passed to viewer, it ignores subsequent params - ;; to avoid parameter injection attacks. - WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\shell" "" "open" -!ifdef WIN64_BIN_BUILD - WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT x64" -!else - WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT" -!endif - WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-info\shell\open\command" "" "$\"$INSTDIR\$VIEWER_EXE$\" -url $\"%1$\"" - - DeleteRegKey HKEY_CLASSES_ROOT "x-grid-location-info}" - WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "" "URL:Hypergrid legacy" - WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "URL Protocol" "" - WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" "$INSTDIR\$VIEWER_EXE" - ;; URL param must be last item passed to viewer, it ignores subsequent params - ;; to avoid parameter injection attacks. - WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\shell" "" "open" -!ifdef WIN64_BIN_BUILD - WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT x64" -!else - WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT" -!endif - WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" "$\"$INSTDIR\$VIEWER_EXE$\" -url $\"%1$\"" - - ;Create uninstaller - SetOutPath "$INSTDIR" - WriteUninstaller "$INSTDIR\uninst.exe" - -SectionEnd - -;-------------------------------- -;Installer Functions -Function .onInit -!ifdef WIN64_BIN_BUILD - SetRegView 64 -!endif - ;Don't install on unsupported operating systems - Call CheckWindowsVersion - ;Don't install if not administator - Call CheckIfAdministrator - ;Don't install if we lack required cpu support - Call CheckCPUFlags - - Push $0 - - ;Get installation folder from registry if available for 64bit - ReadRegStr $0 HKLM "SOFTWARE\${VENDORSTR}\${APPNAMEONEWORD}" "" - IfErrors +2 0 ; If error jump past setting the instdir from registry - StrCpy $INSTDIR $0 - - ${GetParameters} $COMMANDLINE ; get our command line - - ${GetOptions} $COMMANDLINE "/SKIP_DIALOGS" $0 - IfErrors +2 0 ; If error jump past setting SKIP_DIALOGS - StrCpy $SKIP_DIALOGS "true" - - ${GetOptions} $COMMANDLINE "/AUTOSTART" $0 - IfErrors +2 0 ; If error jump past setting AUTOSTART - StrCpy $AUTOSTART "true" - - - ${GetOptions} $COMMANDLINE "/LANGID=" $0 ; /LANGID=1033 implies US English - ; If no language (error), then proceed - IfErrors lbl_configure_default_lang - ; No error means we got a language, so use it - StrCpy $LANGUAGE $0 - Goto lbl_return - -lbl_configure_default_lang: - ;For silent installs, no language prompt, use default - IfSilent lbl_return - StrCmp $SKIP_DIALOGS "true" lbl_return - - !insertmacro MUI_LANGDLL_DISPLAY - -lbl_return: - Pop $0 - Return -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; After install completes, launch app -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function .onInstSuccess - Push $R0 - Push $0 - ;; MAINT-7812: Only write nsis.winstall file with /marker switch - ${GetParameters} $R0 - ${GetOptionsS} $R0 "/marker" $0 - ;; If no /marker switch, skip to ClearErrors - IfErrors +4 0 - ;; $EXEDIR is where we find the installer file - ;; Put a marker file there so VMP will know we're done - ;; and it can delete the download directory next time. - ;; http://nsis.sourceforge.net/Write_text_to_a_file - FileOpen $0 "$EXEDIR\nsis.winstall" w - FileWrite $0 "NSIS done$\n" - FileClose $0 - - ClearErrors - Pop $0 - Pop $R0 -FunctionEnd - -;-------------------------------- -;Uninstaller Section - -Section "Uninstall" - SectionIn RO - SetShellVarContext all -!ifdef WIN64_BIN_BUILD - SetRegView 64 -!endif - - StrCpy $INSTPROG "${APPNAMEONEWORD}" - StrCpy $INSTSHORTCUT "${APPNAME}" - - Call un.CloseSecondLife - - !insertmacro MUI_STARTMENU_GETFOLDER Application $STARTMENUFOLDER - RMDir /r "$SMPROGRAMS\$STARTMENUFOLDER" - - # This placeholder is replaced by the complete list of files to uninstall by viewer_manifest.py - %%DELETE_FILES%% - - ;Optional/obsolete files. Delete won't fail if they don't exist. - Delete "$INSTDIR\message_template.msg" - Delete "$INSTDIR\VivoxVoiceService-*.log" - - ;Shortcuts in install directory - Delete "$INSTDIR\$INSTSHORTCUT.lnk" - Delete "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" - - Delete "$INSTDIR\uninst.exe" - RMDir "$INSTDIR" - - IfFileExists "$INSTDIR" FOLDERFOUND NOFOLDER - -FOLDERFOUND: - ;Silent uninstall always removes all files (/SD IDYES) - MessageBox MB_YESNO $(DeleteProgramFilesMB) /SD IDYES IDNO NOFOLDER - RMDir /r "$INSTDIR" - -NOFOLDER: - DeleteRegKey HKLM "SOFTWARE\${VENDORSTR}\$INSTPROG" - DeleteRegKey /ifempty HKLM "SOFTWARE\${VENDORSTR}" - DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" - -SectionEnd - -;-------------------------------- -;Uninstaller Functions - -Function un.onInit -!ifdef WIN64_BIN_BUILD - SetRegView 64 -!endif - Call un.CheckIfAdministrator - - !insertmacro MUI_UNGETLANGUAGE - -FunctionEnd +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; secondlife setup.nsi +;; Copyright 2004-2011, Linden Research, Inc. +;; Copyright 2013-2015 Alchemy Viewer Project +;; +;; 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 +;; +;; NSIS 3 or higher required for Unicode support +;; +;; Author: James Cook, Don Kjer, Callum Prentice, Drake Arconis +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;-------------------------------- +;Unicode + Unicode true + +;-------------------------------- +;Include Modern UI + + !include "LogicLib.nsh" + !include "StdUtils.nsh" + !include "FileFunc.nsh" + !insertmacro GetParameters + !insertmacro GetOptions + !include "x64.nsh" + !include "WinVer.nsh" + !include "MUI2.nsh" + +;------------------------------- +;Global Variables + ; These will be replaced by manifest scripts + %%INST_VARS%% + %%WIN64_BIN_BUILD%% + + Var INSTEXE + Var INSTPROG + Var VIEWER_EXE + Var INSTSHORTCUT + Var AUTOSTART + Var COMMANDLINE ; command line passed to this installer, set in .onInit + Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer + Var SKIP_DIALOGS ; set from command line in .onInit. autoinstall + ; GUI and the defaults. + Var STARTMENUFOLDER + +;-------------------------------- +;Registry Keys + !define ALCHEMY_KEY "SOFTWARE\${VENDORSTR}" + !define INSTNAME_KEY "${ALCHEMY_KEY}\${APPNAMEONEWORD}" + !define MSCURRVER_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion" + !define MSNTCURRVER_KEY "SOFTWARE\Microsoft\Windows NT\CurrentVersion" + !define MSUNINSTALL_KEY "${MSCURRVER_KEY}\Uninstall\${APPNAMEONEWORD}" + +;-------------------------------- +;General + + ;Name and file + Name "${APPNAME}" + OutFile "${INSTOUTFILE}" + Caption "${CAPTIONSTR}" + BrandingText "${VENDORSTR}" + + ;Default installation folder +!ifdef WIN64_BIN_BUILD + InstallDir "$PROGRAMFILES64\${APPNAMEONEWORD}" +!else + InstallDir "$PROGRAMFILES\${APPNAMEONEWORD}" +!endif + + ;Get installation folder from registry if available and 32bit otherwise do it in init +!ifndef WIN64_BIN_BUILD + InstallDirRegKey HKLM "${INSTNAME_KEY}" "" +!endif + + ;Request application privileges for Windows UAC + RequestExecutionLevel admin + + ;Compression + SetCompress auto ; compress to saves space + SetCompressor /solid /final lzma ; compress whole installer as one block + + ;File Handling + SetOverwrite on + + ;Verify CRC + CRCCheck on + +;-------------------------------- +;Version Information + + VIProductVersion "${VERSION_LONG}" + VIAddVersionKey "ProductName" "${APPNAME} Installer" + VIAddVersionKey "Comments" "A viewer for the meta-verse!" + VIAddVersionKey "CompanyName" "Alchemy Viewer Project" + VIAddVersionKey "LegalCopyright" "Copyright © 2013-2019, Alchemy Viewer Project" + VIAddVersionKey "FileDescription" "${APPNAME} Installer" + VIAddVersionKey "ProductVersion" "${VERSION_LONG}" + VIAddVersionKey "FileVersion" "${VERSION_LONG}" + +;-------------------------------- +;Interface Settings + + ;Show Details + ShowInstDetails hide + ShowUninstDetails hide + + !define MUI_ICON "%%SOURCE%%\installers\windows\install_icon.ico" + !define MUI_UNICON "%%SOURCE%%\installers\windows\uninstall_icon.ico" + !define MUI_WELCOMEFINISHPAGE_BITMAP "%%SOURCE%%\installers\windows\install_welcome.bmp" + !define MUI_UNWELCOMEFINISHPAGE_BITMAP "%%SOURCE%%\installers\windows\uninstall_welcome.bmp" + !define MUI_ABORTWARNING + +;-------------------------------- +;Language Selection Dialog Settings + + ;Show all languages, despite user's codepage + !define MUI_LANGDLL_ALLLANGUAGES + + ;Remember the installer language + !define MUI_LANGDLL_REGISTRY_ROOT "HKLM" + !define MUI_LANGDLL_REGISTRY_KEY "${INSTNAME_KEY}" + !define MUI_LANGDLL_REGISTRY_VALUENAME "InstallerLanguage" + + ;Always show the dialog + !define MUI_LANGDLL_ALWAYSSHOW + +;-------------------------------- +;Install Pages + + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip + !insertmacro MUI_PAGE_WELCOME + + ;License Page + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip + !insertmacro MUI_PAGE_LICENSE "%%SOURCE%%\..\..\doc\LGPL-licence.txt" + + ;Directory Page + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip + !insertmacro MUI_PAGE_DIRECTORY + + ;Start Menu Folder Page + !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" + !define MUI_STARTMENUPAGE_REGISTRY_KEY "${INSTNAME_KEY}" + !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip + !insertmacro MUI_PAGE_STARTMENU Application $STARTMENUFOLDER + + ;Install Progress Page + !define MUI_PAGE_CUSTOMFUNCTION_LEAVE CheckWindowsServPack + !insertmacro MUI_PAGE_INSTFILES + + ; Finish Page + !define MUI_PAGE_CUSTOMFUNCTION_PRE check_skip_finish + !define MUI_FINISHPAGE_RUN + !define MUI_FINISHPAGE_RUN_FUNCTION launch_viewer + !define MUI_FINISHPAGE_SHOWREADME + !define MUI_FINISHPAGE_SHOWREADME_TEXT "Create Desktop Shortcut" + !define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED + !define MUI_FINISHPAGE_SHOWREADME_FUNCTION create_desktop_shortcut + !define MUI_FINISHPAGE_NOREBOOTSUPPORT + !insertmacro MUI_PAGE_FINISH + +;-------------------------------- +;Uninstall Pages + + !insertmacro MUI_UNPAGE_WELCOME + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + !insertmacro MUI_UNPAGE_FINISH + +;-------------------------------- +;Languages + + !include "%%SOURCE%%\installers\windows\lang_en-us.nsi" + !include "%%SOURCE%%\installers\windows\lang_de.nsi" + !include "%%SOURCE%%\installers\windows\lang_es.nsi" + !include "%%SOURCE%%\installers\windows\lang_fr.nsi" + !include "%%SOURCE%%\installers\windows\lang_ja.nsi" + !include "%%SOURCE%%\installers\windows\lang_it.nsi" + !include "%%SOURCE%%\installers\windows\lang_pt-br.nsi" + !include "%%SOURCE%%\installers\windows\lang_ru.nsi" + !include "%%SOURCE%%\installers\windows\lang_tr.nsi" + !include "%%SOURCE%%\installers\windows\lang_zh.nsi" + +;-------------------------------- +;Reserve Files + + ;If you are using solid compression, files that are required before + ;the actual installation should be stored first in the data block, + ;because this will make your installer start faster. + + !insertmacro MUI_RESERVEFILE_LANGDLL + ReserveFile "${NSISDIR}\Plugins\x86-unicode\NSISdl.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\nsDialogs.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\StartMenu.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\StdUtils.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\System.dll" + ReserveFile "${NSISDIR}\Plugins\x86-unicode\UserInfo.dll" + +;-------------------------------- +; Local Functions + +;Page pre-checks for skip conditions +Function check_skip + StrCmp $SKIP_DIALOGS "true" 0 +2 + Abort +FunctionEnd + +Function check_skip_finish + StrCmp $SKIP_DIALOGS "true" 0 +4 + StrCmp $AUTOSTART "true" 0 +3 + Call launch_viewer + Abort +FunctionEnd + +Function launch_viewer + ${StdUtils.ExecShellAsUser} $0 "$INSTDIR\$INSTEXE" "open" "precheck $INSTDIR\$VIEWER_EXE $SHORTCUT_LANG_PARAM" +FunctionEnd + +Function create_desktop_shortcut + CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" +FunctionEnd + +;Check version compatibility +Function CheckWindowsVersion +!ifdef WIN64_BIN_BUILD + ${IfNot} ${RunningX64} + MessageBox MB_OK|MB_ICONSTOP "This version requires a 64 bit operating system." + Quit + ${EndIf} +!endif + + ${If} ${AtMostWinVista} + MessageBox MB_OK $(CheckWindowsVersionMB) + Quit + ${EndIf} +FunctionEnd + +;Check service pack compatibility and suggest upgrade +Function CheckWindowsServPack + ${If} ${IsWin7} + ${AndIfNot} ${IsServicePack} 1 + MessageBox MB_OK $(CheckWindowsServPackMB) + DetailPrint $(UseLatestServPackDP) + Return + ${EndIf} + + ${If} ${IsWin2008R2} + ${AndIfNot} ${IsServicePack} 1 + MessageBox MB_OK $(CheckWindowsServPackMB) + DetailPrint $(UseLatestServPackDP) + Return + ${EndIf} +FunctionEnd + +;Make sure the user can install/uninstall +Function CheckIfAdministrator + DetailPrint $(CheckAdministratorInstDP) + UserInfo::GetAccountType + Pop $R0 + StrCmp $R0 "Admin" lbl_is_admin + MessageBox MB_OK $(CheckAdministratorInstMB) + Quit +lbl_is_admin: + Return +FunctionEnd + +Function un.CheckIfAdministrator + DetailPrint $(CheckAdministratorUnInstDP) + UserInfo::GetAccountType + Pop $R0 + StrCmp $R0 "Admin" lbl_is_admin + MessageBox MB_OK $(CheckAdministratorUnInstMB) + Quit +lbl_is_admin: + Return +FunctionEnd + +;Checks for CPU compatibility +Function CheckCPUFlags + Push $1 + System::Call 'kernel32::IsProcessorFeaturePresent(i) i(10) .r1' + IntCmp $1 1 OK_SSE2 + MessageBox MB_OKCANCEL $(MissingSSE2) /SD IDOK IDOK OK_SSE2 + Quit + + OK_SSE2: + Pop $1 + Return +FunctionEnd + +;Checks if installed version is same as installer and offers to cancel +Function CheckIfAlreadyCurrent +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif + Push $0 + ReadRegStr $0 HKLM "SOFTWARE\${VENDORSTR}\$INSTPROG" "Version" + StrCmp $0 ${VERSION_LONG} 0 continue_install + StrCmp $SKIP_DIALOGS "true" continue_install + MessageBox MB_OKCANCEL $(CheckIfCurrentMB) /SD IDOK IDOK continue_install + Quit +continue_install: + Pop $0 + Return +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Close the program, if running. Modifies no variables. +; Allows user to bail out of install process. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function CloseSecondLife + Push $0 + FindWindow $0 "Alchemy" "" + IntCmp $0 0 DONE + + StrCmp $SKIP_DIALOGS "true" CLOSE + MessageBox MB_OKCANCEL $(CloseSecondLifeInstMB) IDOK CLOSE IDCANCEL CANCEL_INSTALL + + CANCEL_INSTALL: + Quit + + CLOSE: + DetailPrint $(CloseSecondLifeInstDP) + SendMessage $0 16 0 0 + + LOOP: + FindWindow $0 "Alchemy" "" + IntCmp $0 0 DONE + Sleep 500 + Goto LOOP + + DONE: + Pop $0 + Return +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Close the program, if running. Modifies no variables. +; Allows user to bail out of uninstall process. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function un.CloseSecondLife + Push $0 + FindWindow $0 "Alchemy" "" + IntCmp $0 0 DONE + MessageBox MB_OKCANCEL $(CloseSecondLifeUnInstMB) IDOK CLOSE IDCANCEL CANCEL_UNINSTALL + + CANCEL_UNINSTALL: + Quit + + CLOSE: + DetailPrint $(CloseSecondLifeUnInstDP) + SendMessage $0 16 0 0 + + LOOP: + FindWindow $0 "Alchemy" "" + IntCmp $0 0 DONE + Sleep 500 + Goto LOOP + + DONE: + Pop $0 + Return +FunctionEnd + + + +;-------------------------------- +;Installer Sections + +Section "Viewer" + SectionIn RO + SetShellVarContext all +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif + ;Start with some default values. + StrCpy $INSTPROG "${APPNAMEONEWORD}" + StrCpy $INSTEXE "${INSTEXE}" + StrCpy $VIEWER_EXE "${VIEWER_EXE}" + StrCpy $INSTSHORTCUT "${APPNAME}" + + Call CheckIfAlreadyCurrent + Call CloseSecondLife ; Make sure we're not running + + SetOutPath "$INSTDIR" + ;Remove all old files first to prevent incorrect installation + ;RMDir /r "$INSTDIR\*" + RMDir /r "$INSTDIR\app_settings" + RMDir /r "$INSTDIR\llplugin" + RMDir /r "$INSTDIR\skins" + RMDir /r "$INSTDIR\voice" + + ;This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py + %%INSTALL_FILES%% + + ;Pass the installer's language to the client to use as a default + StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)" + + ;Create startmenu shortcuts + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + CreateDirectory "$SMPROGRAMS\$STARTMENUFOLDER" +!ifdef WIN64_BIN_BUILD + CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\$INSTSHORTCUT x64.lnk" "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" + CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\Uninstall $INSTSHORTCUT x64.lnk" "$\"$INSTDIR\uninst.exe$\"" "" +!else + CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\$INSTSHORTCUT.lnk" "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" + CreateShortCut "$SMPROGRAMS\$STARTMENUFOLDER\Uninstall $INSTSHORTCUT.lnk" "$INSTDIR\uninst.exe" "" +!endif + WriteINIStr "$SMPROGRAMS\$STARTMENUFOLDER\SL Create Account.url" "InternetShortcut" "URL" "http://join.secondlife.com/" + WriteINIStr "$SMPROGRAMS\$STARTMENUFOLDER\SL Your Account.url" "InternetShortcut" "URL" "http://www.secondlife.com/account/" + WriteINIStr "$SMPROGRAMS\$STARTMENUFOLDER\SL Scripting Language Help.url" "InternetShortcut" "URL" "http://wiki.secondlife.com/wiki/LSL_Portal" + + !insertmacro MUI_STARTMENU_WRITE_END + + ;Other shortcuts + SetOutPath "$INSTDIR" + CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" + CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" "$INSTDIR\uninst.exe" "" + + ;Write registry + WriteRegStr HKLM "${INSTNAME_KEY}" "" "$INSTDIR" + WriteRegStr HKLM "${INSTNAME_KEY}" "Version" "${VERSION_LONG}" + WriteRegStr HKLM "${INSTNAME_KEY}" "Shortcut" "$INSTSHORTCUT" + WriteRegStr HKLM "${INSTNAME_KEY}" "Exe" "$VIEWER_EXE" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "Comments" "A viewer for the meta-verse!" +!ifdef WIN64_BIN_BUILD + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayName" "$INSTSHORTCUT x64" +!else + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayName" "$INSTSHORTCUT" +!endif + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayIcon" "$INSTDIR\$VIEWER_EXE" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "DisplayVersion" "${VERSION_LONG}" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "InstallLocation" "$INSTDIR" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "InstallSource" "$EXEDIR\" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "HelpLink" "https://www.alchemyviewer.org" + WriteRegDWORD HKLM "${MSUNINSTALL_KEY}" "NoModify" 1 + WriteRegDWORD HKLM "${MSUNINSTALL_KEY}" "NoRepair" 1 + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "Publisher" "${VENDORSTR}" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "URLInfoAbout" "https://www.alchemyviewer.org" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "URLUpdateInfo" "https://www.alchemyviewer.org/p/downloads.html" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "UninstallString" "$\"$INSTDIR\uninst.exe$\"" + WriteRegStr HKLM "${MSUNINSTALL_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninst.exe$\" /S" + ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 + IntFmt $0 "0x%08X" $0 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "EstimatedSize" "$0" + + + ;Write URL registry info + DeleteRegKey HKEY_CLASSES_ROOT "${URLNAME}" + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "" "URL:Second Life" + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "URL Protocol" "" + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\DefaultIcon" "" "$INSTDIR\$VIEWER_EXE" + ;; URL param must be last item passed to viewer, it ignores subsequent params + ;; to avoid parameter injection attacks. + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\shell" "" "open" +!ifdef WIN64_BIN_BUILD + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open" "FriendlyAppName" "$INSTSHORTCUT x64" +!else + WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open" "FriendlyAppName" "$INSTSHORTCUT" +!endif + WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" "$\"$INSTDIR\$VIEWER_EXE$\" -url $\"%1$\"" + + DeleteRegKey HKEY_CLASSES_ROOT "x-grid-info" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info" "" "URL:Hypergrid" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info" "URL Protocol" "" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\DefaultIcon" "" "$INSTDIR\$VIEWER_EXE" + ;; URL param must be last item passed to viewer, it ignores subsequent params + ;; to avoid parameter injection attacks. + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\shell" "" "open" +!ifdef WIN64_BIN_BUILD + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT x64" +!else + WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT" +!endif + WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-info\shell\open\command" "" "$\"$INSTDIR\$VIEWER_EXE$\" -url $\"%1$\"" + + DeleteRegKey HKEY_CLASSES_ROOT "x-grid-location-info}" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "" "URL:Hypergrid legacy" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "URL Protocol" "" + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" "$INSTDIR\$VIEWER_EXE" + ;; URL param must be last item passed to viewer, it ignores subsequent params + ;; to avoid parameter injection attacks. + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\shell" "" "open" +!ifdef WIN64_BIN_BUILD + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT x64" +!else + WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open" "FriendlyAppName" "$INSTSHORTCUT" +!endif + WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" "$\"$INSTDIR\$VIEWER_EXE$\" -url $\"%1$\"" + + ;Create uninstaller + SetOutPath "$INSTDIR" + WriteUninstaller "$INSTDIR\uninst.exe" + +SectionEnd + +;-------------------------------- +;Installer Functions +Function .onInit +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif + ;Don't install on unsupported operating systems + Call CheckWindowsVersion + ;Don't install if not administator + Call CheckIfAdministrator + ;Don't install if we lack required cpu support + Call CheckCPUFlags + + Push $0 + + ;Get installation folder from registry if available for 64bit + ReadRegStr $0 HKLM "SOFTWARE\${VENDORSTR}\${APPNAMEONEWORD}" "" + IfErrors +2 0 ; If error jump past setting the instdir from registry + StrCpy $INSTDIR $0 + + ${GetParameters} $COMMANDLINE ; get our command line + + ${GetOptions} $COMMANDLINE "/SKIP_DIALOGS" $0 + IfErrors +2 0 ; If error jump past setting SKIP_DIALOGS + StrCpy $SKIP_DIALOGS "true" + + ${GetOptions} $COMMANDLINE "/AUTOSTART" $0 + IfErrors +2 0 ; If error jump past setting AUTOSTART + StrCpy $AUTOSTART "true" + + + ${GetOptions} $COMMANDLINE "/LANGID=" $0 ; /LANGID=1033 implies US English + ; If no language (error), then proceed + IfErrors lbl_configure_default_lang + ; No error means we got a language, so use it + StrCpy $LANGUAGE $0 + Goto lbl_return + +lbl_configure_default_lang: + ;For silent installs, no language prompt, use default + IfSilent lbl_return + StrCmp $SKIP_DIALOGS "true" lbl_return + + !insertmacro MUI_LANGDLL_DISPLAY + +lbl_return: + Pop $0 + Return +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; After install completes, launch app +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function .onInstSuccess + Push $R0 + Push $0 + ;; MAINT-7812: Only write nsis.winstall file with /marker switch + ${GetParameters} $R0 + ${GetOptionsS} $R0 "/marker" $0 + ;; If no /marker switch, skip to ClearErrors + IfErrors +4 0 + ;; $EXEDIR is where we find the installer file + ;; Put a marker file there so VMP will know we're done + ;; and it can delete the download directory next time. + ;; http://nsis.sourceforge.net/Write_text_to_a_file + FileOpen $0 "$EXEDIR\nsis.winstall" w + FileWrite $0 "NSIS done$\n" + FileClose $0 + + ClearErrors + Pop $0 + Pop $R0 +FunctionEnd + +;-------------------------------- +;Uninstaller Section + +Section "Uninstall" + SectionIn RO + SetShellVarContext all +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif + + StrCpy $INSTPROG "${APPNAMEONEWORD}" + StrCpy $INSTSHORTCUT "${APPNAME}" + + Call un.CloseSecondLife + + !insertmacro MUI_STARTMENU_GETFOLDER Application $STARTMENUFOLDER + RMDir /r "$SMPROGRAMS\$STARTMENUFOLDER" + + # This placeholder is replaced by the complete list of files to uninstall by viewer_manifest.py + %%DELETE_FILES%% + + ;Optional/obsolete files. Delete won't fail if they don't exist. + Delete "$INSTDIR\message_template.msg" + Delete "$INSTDIR\VivoxVoiceService-*.log" + + ;Shortcuts in install directory + Delete "$INSTDIR\$INSTSHORTCUT.lnk" + Delete "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" + + Delete "$INSTDIR\uninst.exe" + RMDir "$INSTDIR" + + IfFileExists "$INSTDIR" FOLDERFOUND NOFOLDER + +FOLDERFOUND: + ;Silent uninstall always removes all files (/SD IDYES) + MessageBox MB_YESNO $(DeleteProgramFilesMB) /SD IDYES IDNO NOFOLDER + RMDir /r "$INSTDIR" + +NOFOLDER: + DeleteRegKey HKLM "SOFTWARE\${VENDORSTR}\$INSTPROG" + DeleteRegKey /ifempty HKLM "SOFTWARE\${VENDORSTR}" + DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" + +SectionEnd + +;-------------------------------- +;Uninstaller Functions + +Function un.onInit +!ifdef WIN64_BIN_BUILD + SetRegView 64 +!endif + Call un.CheckIfAdministrator + + !insertmacro MUI_UNGETLANGUAGE + +FunctionEnd diff --git a/indra/newview/installers/windows/lang_da.nsi b/indra/newview/installers/windows/lang_da.nsi index 756e275f69c1300d912dfb66664779e850e54358..e4458ce4083a952459a3b5bce5001c177f805e8c 100644 --- a/indra/newview/installers/windows/lang_da.nsi +++ b/indra/newview/installers/windows/lang_da.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "Danish" - -; Language string -LangString LanguageCode ${LANG_DANISH} "da" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_DANISH} "Vælg venligst sprog til installation" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_DANISH} "Installationsmappe" -LangString DirectoryChooseUpdate ${LANG_DANISH} "Vælg ${APPNAME} mappe til opdatering til version ${VERSION_LONG}.(XXX):" -LangString DirectoryChooseSetup ${LANG_DANISH} "Vælg mappe hvor ${APPNAME} skal installeres:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_DANISH} "Kunne ikke finde programmet '$INSTPROG'. Baggrundsopdatering fejlede." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_DANISH} "Checker Windows version..." -LangString CheckWindowsVersionMB ${LANG_DANISH} '${APPNAME} supporterer kun Windows XP.$\n$\nForsøg pÃ¥ installation pÃ¥ Windows $R0 kan resultere i nedbrud og datatab.$\n$\n' -LangString CheckWindowsServPackMB ${LANG_DANISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_DANISH} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_DANISH} "Checker rettigheder til installation..." -LangString CheckAdministratorInstMB ${LANG_DANISH} 'Det ser ud til at du benytter en konto med begrænsninger.$\nDu skal have "administrator" rettigheder for at installere ${APPNAME}.' - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_DANISH} "Checker rettigheder til at afinstallere..." -LangString CheckAdministratorUnInstMB ${LANG_DANISH} 'Det ser ud til at du benytter en konto med begrænsninger.$\nDu skal have "administrator" rettigheder for at afinstallere ${APPNAME}.' - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_DANISH} "Det ser ud til at ${APPNAME} ${VERSION_LONG} allerede er installeret.$\n$\nØnsker du at installere igen?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_DANISH} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_DANISH} "Venter pÃ¥ at Alchemy skal lukke ned..." -LangString CloseSecondLifeInstMB ${LANG_DANISH} "Alchemy kan ikke installeres mens programmet kører.$\n$\nAfslut programmet for at fortsætte.$\nVælg ANNULÉR for at afbryde installation." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_DANISH} "Venter pÃ¥ at Alchemy skal lukke ned..." -LangString CloseSecondLifeUnInstMB ${LANG_DANISH} "Alchemy kan ikke afinstalleres mens programmet kører.$\n$\nAfslut programmet for at fortsætte.$\nVælg ANNULÉR for at afbryde installation." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_DANISH} "Checker netværksforbindelse..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_DANISH} "Sletter cache filer i dokument mappen" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_DANISH} "Der er stadig filer i ${APPNAME} program mappen.$\n$\nDette er sandsynligvis filer du har oprettet eller flyttet til :$\n$INSTDIR$\n$\nØnsker du at fjerne disse filer?" - -; uninstall text -LangString UninstallTextMsg ${LANG_DANISH} "Dette vil afinstallere ${APPNAME} ${VERSION_LONG} fra dit system." +; First is default +!insertmacro MUI_LANGUAGE "Danish" + +; Language string +LangString LanguageCode ${LANG_DANISH} "da" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_DANISH} "Vælg venligst sprog til installation" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_DANISH} "Installationsmappe" +LangString DirectoryChooseUpdate ${LANG_DANISH} "Vælg ${APPNAME} mappe til opdatering til version ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_DANISH} "Vælg mappe hvor ${APPNAME} skal installeres:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_DANISH} "Kunne ikke finde programmet '$INSTPROG'. Baggrundsopdatering fejlede." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_DANISH} "Checker Windows version..." +LangString CheckWindowsVersionMB ${LANG_DANISH} '${APPNAME} supporterer kun Windows XP.$\n$\nForsøg pÃ¥ installation pÃ¥ Windows $R0 kan resultere i nedbrud og datatab.$\n$\n' +LangString CheckWindowsServPackMB ${LANG_DANISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_DANISH} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_DANISH} "Checker rettigheder til installation..." +LangString CheckAdministratorInstMB ${LANG_DANISH} 'Det ser ud til at du benytter en konto med begrænsninger.$\nDu skal have "administrator" rettigheder for at installere ${APPNAME}.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_DANISH} "Checker rettigheder til at afinstallere..." +LangString CheckAdministratorUnInstMB ${LANG_DANISH} 'Det ser ud til at du benytter en konto med begrænsninger.$\nDu skal have "administrator" rettigheder for at afinstallere ${APPNAME}.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_DANISH} "Det ser ud til at ${APPNAME} ${VERSION_LONG} allerede er installeret.$\n$\nØnsker du at installere igen?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_DANISH} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_DANISH} "Venter pÃ¥ at Alchemy skal lukke ned..." +LangString CloseSecondLifeInstMB ${LANG_DANISH} "Alchemy kan ikke installeres mens programmet kører.$\n$\nAfslut programmet for at fortsætte.$\nVælg ANNULÉR for at afbryde installation." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_DANISH} "Venter pÃ¥ at Alchemy skal lukke ned..." +LangString CloseSecondLifeUnInstMB ${LANG_DANISH} "Alchemy kan ikke afinstalleres mens programmet kører.$\n$\nAfslut programmet for at fortsætte.$\nVælg ANNULÉR for at afbryde installation." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_DANISH} "Checker netværksforbindelse..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_DANISH} "Sletter cache filer i dokument mappen" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_DANISH} "Der er stadig filer i ${APPNAME} program mappen.$\n$\nDette er sandsynligvis filer du har oprettet eller flyttet til :$\n$INSTDIR$\n$\nØnsker du at fjerne disse filer?" + +; uninstall text +LangString UninstallTextMsg ${LANG_DANISH} "Dette vil afinstallere ${APPNAME} ${VERSION_LONG} fra dit system." diff --git a/indra/newview/installers/windows/lang_de.nsi b/indra/newview/installers/windows/lang_de.nsi index b2e9299bd2b698ff5f7bdba2bc9deb0ebf9c8994..2351f705abce98e68128ddba6b15aa799b32a84a 100755 --- a/indra/newview/installers/windows/lang_de.nsi +++ b/indra/newview/installers/windows/lang_de.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "German" - -; Language string -LangString LanguageCode ${LANG_GERMAN} "de" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_GERMAN} "Bitte wählen Sie die Installationssprache" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_GERMAN} "Installations-Ordner" -LangString DirectoryChooseUpdate ${LANG_GERMAN} "Wählen Sie den ${APPNAME} Ordner für dieses Update:" -LangString DirectoryChooseSetup ${LANG_GERMAN} "Pfad in dem ${APPNAME} installiert werden soll:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_GERMAN} "Konnte Programm '$INSTPROG' nicht finden. Stilles Update fehlgeschlagen." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_GERMAN} "Ãœberprüfung der Windows Version ..." -LangString CheckWindowsVersionMB ${LANG_GERMAN} '${APPNAME} unterstützt nur Windows XP.$\n$\nDer Versuch es auf Windows $R0 zu installieren, könnte zu unvorhersehbaren Abstürzen und Datenverlust führen.$\n$\nTrotzdem installieren?' -LangString CheckWindowsServPackMB ${LANG_GERMAN} "Es wird empfohlen, das aktuellste Service Pack des Betriebssystems für ${APPNAME} zu verwenden.$\nEs ist hilftreich für Performance und Stabilität des Programms." -LangString UseLatestServPackDP ${LANG_GERMAN} "Bitte Windows Update benutzen, um das aktuellste Service Pack zu installieren." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_GERMAN} "Ãœberprüfung der Installations-Berechtigungen ..." -LangString CheckAdministratorInstMB ${LANG_GERMAN} 'Sie besitzen ungenügende Berechtigungen.$\nSie müssen ein "administrator" sein, um ${APPNAME} installieren zu können.' - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_GERMAN} "Ãœberprüfung der Entfernungs-Berechtigungen ..." -LangString CheckAdministratorUnInstMB ${LANG_GERMAN} 'Sie besitzen ungenügende Berechtigungen.$\nSie müssen ein "administrator" sein, um ${APPNAME} entfernen zu können..' - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_GERMAN} "Anscheinend ist ${APPNAME} ${VERSION_LONG} bereits installiert.$\n$\nWürden Sie es gerne erneut installieren?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_GERMAN} "Dieser PC besitzt möglicherweise keinen Prozessor mit SSE2-Unterstützung, die für die Ausführung von ${APPNAME} ${VERSION_LONG} benötigt wird. Trotzdem installieren?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Alchemy ..." -LangString CloseSecondLifeInstMB ${LANG_GERMAN} "Alchemy kann nicht installiert oder ersetzt werden, wenn es bereits läuft.$\n$\nBeenden Sie, was Sie gerade tun und klicken Sie OK, um Alchemy zu beenden.$\nKlicken Sie CANCEL, um die Installation abzubrechen." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Alchemy ..." -LangString CloseSecondLifeUnInstMB ${LANG_GERMAN} "Alchemy kann nicht entfernt werden, wenn es bereits läuft.$\n$\nBeenden Sie, was Sie gerade tun und klicken Sie OK, um Alchemy zu beenden.$\nKlicken Sie CANCEL, um abzubrechen." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_GERMAN} "Prüfe Netzwerkverbindung..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_GERMAN} "Löschung aller Cache Dateien in Dokumente und Einstellungen." - -; delete program files -LangString DeleteProgramFilesMB ${LANG_GERMAN} "Es existieren weiterhin Dateien in Ihrem SecondLife Programm Ordner.$\n$\nDies sind möglicherweise Dateien, die sie modifiziert oder bewegt haben:$\n$INSTDIR$\n$\nMöchten Sie diese ebenfalls löschen?" - -; uninstall text -LangString UninstallTextMsg ${LANG_GERMAN} "Dies wird ${APPNAME} ${VERSION_LONG} von Ihrem System entfernen." +; First is default +!insertmacro MUI_LANGUAGE "German" + +; Language string +LangString LanguageCode ${LANG_GERMAN} "de" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_GERMAN} "Bitte wählen Sie die Installationssprache" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_GERMAN} "Installations-Ordner" +LangString DirectoryChooseUpdate ${LANG_GERMAN} "Wählen Sie den ${APPNAME} Ordner für dieses Update:" +LangString DirectoryChooseSetup ${LANG_GERMAN} "Pfad in dem ${APPNAME} installiert werden soll:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_GERMAN} "Konnte Programm '$INSTPROG' nicht finden. Stilles Update fehlgeschlagen." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_GERMAN} "Ãœberprüfung der Windows Version ..." +LangString CheckWindowsVersionMB ${LANG_GERMAN} '${APPNAME} unterstützt nur Windows XP.$\n$\nDer Versuch es auf Windows $R0 zu installieren, könnte zu unvorhersehbaren Abstürzen und Datenverlust führen.$\n$\nTrotzdem installieren?' +LangString CheckWindowsServPackMB ${LANG_GERMAN} "Es wird empfohlen, das aktuellste Service Pack des Betriebssystems für ${APPNAME} zu verwenden.$\nEs ist hilftreich für Performance und Stabilität des Programms." +LangString UseLatestServPackDP ${LANG_GERMAN} "Bitte Windows Update benutzen, um das aktuellste Service Pack zu installieren." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_GERMAN} "Ãœberprüfung der Installations-Berechtigungen ..." +LangString CheckAdministratorInstMB ${LANG_GERMAN} 'Sie besitzen ungenügende Berechtigungen.$\nSie müssen ein "administrator" sein, um ${APPNAME} installieren zu können.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_GERMAN} "Ãœberprüfung der Entfernungs-Berechtigungen ..." +LangString CheckAdministratorUnInstMB ${LANG_GERMAN} 'Sie besitzen ungenügende Berechtigungen.$\nSie müssen ein "administrator" sein, um ${APPNAME} entfernen zu können..' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_GERMAN} "Anscheinend ist ${APPNAME} ${VERSION_LONG} bereits installiert.$\n$\nWürden Sie es gerne erneut installieren?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_GERMAN} "Dieser PC besitzt möglicherweise keinen Prozessor mit SSE2-Unterstützung, die für die Ausführung von ${APPNAME} ${VERSION_LONG} benötigt wird. Trotzdem installieren?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Alchemy ..." +LangString CloseSecondLifeInstMB ${LANG_GERMAN} "Alchemy kann nicht installiert oder ersetzt werden, wenn es bereits läuft.$\n$\nBeenden Sie, was Sie gerade tun und klicken Sie OK, um Alchemy zu beenden.$\nKlicken Sie CANCEL, um die Installation abzubrechen." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Alchemy ..." +LangString CloseSecondLifeUnInstMB ${LANG_GERMAN} "Alchemy kann nicht entfernt werden, wenn es bereits läuft.$\n$\nBeenden Sie, was Sie gerade tun und klicken Sie OK, um Alchemy zu beenden.$\nKlicken Sie CANCEL, um abzubrechen." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_GERMAN} "Prüfe Netzwerkverbindung..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_GERMAN} "Löschung aller Cache Dateien in Dokumente und Einstellungen." + +; delete program files +LangString DeleteProgramFilesMB ${LANG_GERMAN} "Es existieren weiterhin Dateien in Ihrem SecondLife Programm Ordner.$\n$\nDies sind möglicherweise Dateien, die sie modifiziert oder bewegt haben:$\n$INSTDIR$\n$\nMöchten Sie diese ebenfalls löschen?" + +; uninstall text +LangString UninstallTextMsg ${LANG_GERMAN} "Dies wird ${APPNAME} ${VERSION_LONG} von Ihrem System entfernen." diff --git a/indra/newview/installers/windows/lang_en-us.nsi b/indra/newview/installers/windows/lang_en-us.nsi index 6da77ef0a44cf2384839c7f162a04b65808c8dcd..dd1719c7b99bd1b399335fb85d6d3a1f6ede7070 100644 --- a/indra/newview/installers/windows/lang_en-us.nsi +++ b/indra/newview/installers/windows/lang_en-us.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "English" - -; Language string -LangString LanguageCode ${LANG_ENGLISH} "en" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_ENGLISH} "Please select the language of the installer" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_ENGLISH} "Installation Directory" -LangString DirectoryChooseUpdate ${LANG_ENGLISH} "Select the ${APPNAME} directory to update to version ${VERSION_LONG}.(XXX):" -LangString DirectoryChooseSetup ${LANG_ENGLISH} "Select the directory to install ${APPNAME} in:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_ENGLISH} "Could not find the program '$INSTPROG'. Silent update failed." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_ENGLISH} "Checking Windows version..." -LangString CheckWindowsVersionMB ${LANG_ENGLISH} "${APPNAME} only supports Windows 7 with Service Pack 1 and later.$\nInstallation on this Operating System is not supported. Quitting." -LangString CheckWindowsServPackMB ${LANG_ENGLISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_ENGLISH} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_ENGLISH} "Checking for permission to install..." -LangString CheckAdministratorInstMB ${LANG_ENGLISH} 'You appear to be using a "limited" account.$\nYou must be an "administrator" to install ${APPNAME}.' - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_ENGLISH} "Checking for permission to uninstall..." -LangString CheckAdministratorUnInstMB ${LANG_ENGLISH} 'You appear to be using a "limited" account.$\nYou must be an "administrator" to uninstall ${APPNAME}.' - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_ENGLISH} "It appears that ${APPNAME} ${VERSION_LONG} is already installed.$\n$\nWould you like to install it again?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_ENGLISH} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_ENGLISH} "Waiting for Alchemy to shut down..." -LangString CloseSecondLifeInstMB ${LANG_ENGLISH} "Alchemy can't be installed while it is already running.$\n$\nFinish what you're doing then select OK to close Alchemy and continue.$\nSelect CANCEL to cancel installation." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_ENGLISH} "Waiting for Alchemy to shut down..." -LangString CloseSecondLifeUnInstMB ${LANG_ENGLISH} "Alchemy can't be uninstalled while it is already running.$\n$\nFinish what you're doing then select OK to close Alchemy and continue.$\nSelect CANCEL to cancel." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_ENGLISH} "Checking network connection..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_ENGLISH} "Deleting cache files in Documents and Settings folder" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_ENGLISH} "There are still files in your ${APPNAME} program directory.$\n$\nThese are possibly files you created or moved to:$\n$INSTDIR$\n$\nDo you want to remove them?" - -; uninstall text -LangString UninstallTextMsg ${LANG_ENGLISH} "This will uninstall ${APPNAME} ${VERSION_LONG} from your system. Click Uninstall to start the uninstallation." +; First is default +!insertmacro MUI_LANGUAGE "English" + +; Language string +LangString LanguageCode ${LANG_ENGLISH} "en" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_ENGLISH} "Please select the language of the installer" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_ENGLISH} "Installation Directory" +LangString DirectoryChooseUpdate ${LANG_ENGLISH} "Select the ${APPNAME} directory to update to version ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_ENGLISH} "Select the directory to install ${APPNAME} in:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_ENGLISH} "Could not find the program '$INSTPROG'. Silent update failed." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_ENGLISH} "Checking Windows version..." +LangString CheckWindowsVersionMB ${LANG_ENGLISH} "${APPNAME} only supports Windows 7 with Service Pack 1 and later.$\nInstallation on this Operating System is not supported. Quitting." +LangString CheckWindowsServPackMB ${LANG_ENGLISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_ENGLISH} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_ENGLISH} "Checking for permission to install..." +LangString CheckAdministratorInstMB ${LANG_ENGLISH} 'You appear to be using a "limited" account.$\nYou must be an "administrator" to install ${APPNAME}.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_ENGLISH} "Checking for permission to uninstall..." +LangString CheckAdministratorUnInstMB ${LANG_ENGLISH} 'You appear to be using a "limited" account.$\nYou must be an "administrator" to uninstall ${APPNAME}.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_ENGLISH} "It appears that ${APPNAME} ${VERSION_LONG} is already installed.$\n$\nWould you like to install it again?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_ENGLISH} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_ENGLISH} "Waiting for Alchemy to shut down..." +LangString CloseSecondLifeInstMB ${LANG_ENGLISH} "Alchemy can't be installed while it is already running.$\n$\nFinish what you're doing then select OK to close Alchemy and continue.$\nSelect CANCEL to cancel installation." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_ENGLISH} "Waiting for Alchemy to shut down..." +LangString CloseSecondLifeUnInstMB ${LANG_ENGLISH} "Alchemy can't be uninstalled while it is already running.$\n$\nFinish what you're doing then select OK to close Alchemy and continue.$\nSelect CANCEL to cancel." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_ENGLISH} "Checking network connection..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_ENGLISH} "Deleting cache files in Documents and Settings folder" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_ENGLISH} "There are still files in your ${APPNAME} program directory.$\n$\nThese are possibly files you created or moved to:$\n$INSTDIR$\n$\nDo you want to remove them?" + +; uninstall text +LangString UninstallTextMsg ${LANG_ENGLISH} "This will uninstall ${APPNAME} ${VERSION_LONG} from your system. Click Uninstall to start the uninstallation." diff --git a/indra/newview/installers/windows/lang_es.nsi b/indra/newview/installers/windows/lang_es.nsi index b3f57380db073543cc49c65c5a2715b6549c850f..4c8531d15deb039e698e3fbb828706cb732302fc 100755 --- a/indra/newview/installers/windows/lang_es.nsi +++ b/indra/newview/installers/windows/lang_es.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "Spanish" - -; Language string -LangString LanguageCode ${LANG_SPANISH} "es" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_SPANISH} "Por favor seleccione el idioma de su instalador" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_SPANISH} "Directorio de instalación" -LangString DirectoryChooseUpdate ${LANG_SPANISH} "Seleccione el directorio de ${APPNAME} para actualizar el programa a la versión ${VERSION_LONG}.(XXX):" -LangString DirectoryChooseSetup ${LANG_SPANISH} "Seleccione el directorio en el que instalar ${APPNAME}:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_SPANISH} "No se pudo encontrar el programa '$INSTPROG'. Error al realizar la actualización desatendida." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_SPANISH} "Comprobando la versión de Windows..." -LangString CheckWindowsVersionMB ${LANG_SPANISH} '${APPNAME} sólo se puede ejecutar en Windows XP.$\n$\nSi intenta instalar el programa en Windows $R0, es posible que el sistema se bloquee y se pierdan datos.$\n$\n' -LangString CheckWindowsServPackMB ${LANG_SPANISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_SPANISH} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_SPANISH} "Comprobando los permisos para la instalación..." -LangString CheckAdministratorInstMB ${LANG_SPANISH} 'Parece que está usando una cuenta "limitada".$\nDebe iniciar sesión como "administrador" para instalar ${APPNAME}.' - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_SPANISH} "Comprobando los permisos para la desinstalación..." -LangString CheckAdministratorUnInstMB ${LANG_SPANISH} 'Parece que está usando una cuenta "limitada".$\nDebe iniciar sesión como "administrador" para desinstalar ${APPNAME}.' - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_SPANISH} "Parece que ${APPNAME} ${VERSION_LONG} ya está instalado.$\n$\n¿Desea volver a instalarlo?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_SPANISH} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_SPANISH} "Esperando que Alchemy se cierre..." -LangString CloseSecondLifeInstMB ${LANG_SPANISH} "Alchemy no se puede instalar mientras esté en ejecución.$\n$\nTermine lo que esté haciendo y seleccione Aceptar (OK) para cerrar Alchemy y continuar el proceso.$\nSeleccione Cancelar (CANCEL) para cancelar la instalación." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_SPANISH} "Esperando que Alchemy se cierre..." -LangString CloseSecondLifeUnInstMB ${LANG_SPANISH} "Alchemy no se puede desinstalar mientras esté en ejecución.$\n$\nTermine lo que esté haciendo y seleccione Aceptar (OK) para cerrar Alchemy y continuar el proceso.$\nSeleccione Cancelar (CANCEL) para cancelar la desinstalación." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_SPANISH} "Comprobando la conexión de red..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_SPANISH} "Eliminando los archivos de caché almacenados en la carpeta Documents and Settings..." - -; delete program files -LangString DeleteProgramFilesMB ${LANG_SPANISH} "Aún hay archivos en su directorio de programa de ${APPNAME}.$\n$\nPosiblemente son archivos que ha creado o movido a:$\n$INSTDIR$\n$\n¿Desea eliminarlos?" - -; uninstall text -LangString UninstallTextMsg ${LANG_SPANISH} "Este proceso desinstalará ${APPNAME} ${VERSION_LONG} de su sistema." +; First is default +!insertmacro MUI_LANGUAGE "Spanish" + +; Language string +LangString LanguageCode ${LANG_SPANISH} "es" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_SPANISH} "Por favor seleccione el idioma de su instalador" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_SPANISH} "Directorio de instalación" +LangString DirectoryChooseUpdate ${LANG_SPANISH} "Seleccione el directorio de ${APPNAME} para actualizar el programa a la versión ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_SPANISH} "Seleccione el directorio en el que instalar ${APPNAME}:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_SPANISH} "No se pudo encontrar el programa '$INSTPROG'. Error al realizar la actualización desatendida." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_SPANISH} "Comprobando la versión de Windows..." +LangString CheckWindowsVersionMB ${LANG_SPANISH} '${APPNAME} sólo se puede ejecutar en Windows XP.$\n$\nSi intenta instalar el programa en Windows $R0, es posible que el sistema se bloquee y se pierdan datos.$\n$\n' +LangString CheckWindowsServPackMB ${LANG_SPANISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_SPANISH} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_SPANISH} "Comprobando los permisos para la instalación..." +LangString CheckAdministratorInstMB ${LANG_SPANISH} 'Parece que está usando una cuenta "limitada".$\nDebe iniciar sesión como "administrador" para instalar ${APPNAME}.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_SPANISH} "Comprobando los permisos para la desinstalación..." +LangString CheckAdministratorUnInstMB ${LANG_SPANISH} 'Parece que está usando una cuenta "limitada".$\nDebe iniciar sesión como "administrador" para desinstalar ${APPNAME}.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_SPANISH} "Parece que ${APPNAME} ${VERSION_LONG} ya está instalado.$\n$\n¿Desea volver a instalarlo?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_SPANISH} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_SPANISH} "Esperando que Alchemy se cierre..." +LangString CloseSecondLifeInstMB ${LANG_SPANISH} "Alchemy no se puede instalar mientras esté en ejecución.$\n$\nTermine lo que esté haciendo y seleccione Aceptar (OK) para cerrar Alchemy y continuar el proceso.$\nSeleccione Cancelar (CANCEL) para cancelar la instalación." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_SPANISH} "Esperando que Alchemy se cierre..." +LangString CloseSecondLifeUnInstMB ${LANG_SPANISH} "Alchemy no se puede desinstalar mientras esté en ejecución.$\n$\nTermine lo que esté haciendo y seleccione Aceptar (OK) para cerrar Alchemy y continuar el proceso.$\nSeleccione Cancelar (CANCEL) para cancelar la desinstalación." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_SPANISH} "Comprobando la conexión de red..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_SPANISH} "Eliminando los archivos de caché almacenados en la carpeta Documents and Settings..." + +; delete program files +LangString DeleteProgramFilesMB ${LANG_SPANISH} "Aún hay archivos en su directorio de programa de ${APPNAME}.$\n$\nPosiblemente son archivos que ha creado o movido a:$\n$INSTDIR$\n$\n¿Desea eliminarlos?" + +; uninstall text +LangString UninstallTextMsg ${LANG_SPANISH} "Este proceso desinstalará ${APPNAME} ${VERSION_LONG} de su sistema." diff --git a/indra/newview/installers/windows/lang_fr.nsi b/indra/newview/installers/windows/lang_fr.nsi index a45392ea13eb849c53a887253a5deb49f9695706..74cdc072de61e74f567ac5438d5f6abd57d72c2e 100755 --- a/indra/newview/installers/windows/lang_fr.nsi +++ b/indra/newview/installers/windows/lang_fr.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "French" - -; Language string -LangString LanguageCode ${LANG_FRENCH} "fr" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_FRENCH} "Veuillez sélectionner la langue du programme d’installation" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_FRENCH} "Répertoire d'installation" -LangString DirectoryChooseUpdate ${LANG_FRENCH} "Sélectionnez le répertoire de ${APPNAME} pour installer la nouvelle version ${VERSION_LONG}. (XXX) :" -LangString DirectoryChooseSetup ${LANG_FRENCH} "Sélectionnez le répertoire dans lequel installer ${APPNAME} :" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_FRENCH} "Impossible de trouver le programme '$INSTPROG'. La mise à jour silencieuse a échoué." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_FRENCH} "Vérification de la version de Windows en cours..." -LangString CheckWindowsVersionMB ${LANG_FRENCH} "${APPNAME} prend uniquement en charge Windows XP.$\n$\nToute tentative d'installation sous Windows $R0 peut causer des crashs et des pertes de données.$\n$\n" -LangString CheckWindowsServPackMB ${LANG_FRENCH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_FRENCH} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_FRENCH} "Vérification de la permission pour effectuer l'installation en cours..." -LangString CheckAdministratorInstMB ${LANG_FRENCH} "Il semblerait que votre compte soit « limité ».$\nPour installer ${APPNAME}, vous devez avoir un compte « administrateur »." - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_FRENCH} "Vérification de la permission pour effectuer la désinstallation en cours..." -LangString CheckAdministratorUnInstMB ${LANG_FRENCH} "Il semblerait que votre compte soit « limité ».$\nPour désinstaller ${APPNAME}, vous devez avoir un compte « administrateur »." - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_FRENCH} "Il semblerait que vous ayez déjà installé ${APPNAME} ${VERSION_LONG}.$\n$\nSouhaitez-vous procéder à une nouvelle installation ?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_FRENCH} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_FRENCH} "En attente de la fermeture de Alchemy..." -LangString CloseSecondLifeInstMB ${LANG_FRENCH} "Alchemy ne peut pas être installé si l'application est déjà lancée..$\n$\nFinissez ce que vous faites puis sélectionnez OK pour fermer Alchemy et continuer.$\nSélectionnez ANNULER pour annuler l'installation." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_FRENCH} "En attente de la fermeture de Alchemy..." -LangString CloseSecondLifeUnInstMB ${LANG_FRENCH} "Alchemy ne peut pas être désinstallé si l'application est déjà lancée.$\n$\nFinissez ce que vous faites puis sélectionnez OK pour fermer Alchemy et continuer.$\nSélectionnez ANNULER pour annuler la désinstallation." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_FRENCH} "Connexion au réseau en cours de vérification..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_FRENCH} "Suppression des fichiers du cache dans le dossier Documents et Paramètres" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_FRENCH} "Il y a encore des fichiers dans votre répertoire ${APPNAME}.$\n$\nIl est possible que vous ayez créé ou déplacé ces dossiers vers : $\n$INSTDIR$\n$\nVoulez-vous les supprimer ?" - -; uninstall text -LangString UninstallTextMsg ${LANG_FRENCH} "Cela désinstallera ${APPNAME} ${VERSION_LONG} de votre système." +; First is default +!insertmacro MUI_LANGUAGE "French" + +; Language string +LangString LanguageCode ${LANG_FRENCH} "fr" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_FRENCH} "Veuillez sélectionner la langue du programme d’installation" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_FRENCH} "Répertoire d'installation" +LangString DirectoryChooseUpdate ${LANG_FRENCH} "Sélectionnez le répertoire de ${APPNAME} pour installer la nouvelle version ${VERSION_LONG}. (XXX) :" +LangString DirectoryChooseSetup ${LANG_FRENCH} "Sélectionnez le répertoire dans lequel installer ${APPNAME} :" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_FRENCH} "Impossible de trouver le programme '$INSTPROG'. La mise à jour silencieuse a échoué." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_FRENCH} "Vérification de la version de Windows en cours..." +LangString CheckWindowsVersionMB ${LANG_FRENCH} "${APPNAME} prend uniquement en charge Windows XP.$\n$\nToute tentative d'installation sous Windows $R0 peut causer des crashs et des pertes de données.$\n$\n" +LangString CheckWindowsServPackMB ${LANG_FRENCH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_FRENCH} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_FRENCH} "Vérification de la permission pour effectuer l'installation en cours..." +LangString CheckAdministratorInstMB ${LANG_FRENCH} "Il semblerait que votre compte soit « limité ».$\nPour installer ${APPNAME}, vous devez avoir un compte « administrateur »." + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_FRENCH} "Vérification de la permission pour effectuer la désinstallation en cours..." +LangString CheckAdministratorUnInstMB ${LANG_FRENCH} "Il semblerait que votre compte soit « limité ».$\nPour désinstaller ${APPNAME}, vous devez avoir un compte « administrateur »." + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_FRENCH} "Il semblerait que vous ayez déjà installé ${APPNAME} ${VERSION_LONG}.$\n$\nSouhaitez-vous procéder à une nouvelle installation ?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_FRENCH} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_FRENCH} "En attente de la fermeture de Alchemy..." +LangString CloseSecondLifeInstMB ${LANG_FRENCH} "Alchemy ne peut pas être installé si l'application est déjà lancée..$\n$\nFinissez ce que vous faites puis sélectionnez OK pour fermer Alchemy et continuer.$\nSélectionnez ANNULER pour annuler l'installation." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_FRENCH} "En attente de la fermeture de Alchemy..." +LangString CloseSecondLifeUnInstMB ${LANG_FRENCH} "Alchemy ne peut pas être désinstallé si l'application est déjà lancée.$\n$\nFinissez ce que vous faites puis sélectionnez OK pour fermer Alchemy et continuer.$\nSélectionnez ANNULER pour annuler la désinstallation." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_FRENCH} "Connexion au réseau en cours de vérification..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_FRENCH} "Suppression des fichiers du cache dans le dossier Documents et Paramètres" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_FRENCH} "Il y a encore des fichiers dans votre répertoire ${APPNAME}.$\n$\nIl est possible que vous ayez créé ou déplacé ces dossiers vers : $\n$INSTDIR$\n$\nVoulez-vous les supprimer ?" + +; uninstall text +LangString UninstallTextMsg ${LANG_FRENCH} "Cela désinstallera ${APPNAME} ${VERSION_LONG} de votre système." diff --git a/indra/newview/installers/windows/lang_it.nsi b/indra/newview/installers/windows/lang_it.nsi index 0a77f851721ada207ef6538d8b5fd89238892639..2163daddf68f02e549c45cd48f4b9f58bea521a4 100755 --- a/indra/newview/installers/windows/lang_it.nsi +++ b/indra/newview/installers/windows/lang_it.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "Italian" - -; Language string -LangString LanguageCode ${LANG_ITALIAN} "it" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_ITALIAN} "Scegliere per favore il linguaggio del programma di installazione" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_ITALIAN} "Directory di installazione" -LangString DirectoryChooseUpdate ${LANG_ITALIAN} "Scegli la directory di ${APPNAME} per l’update alla versione ${VERSION_LONG}.(XXX):" -LangString DirectoryChooseSetup ${LANG_ITALIAN} "Scegli la directory dove installare ${APPNAME}:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_ITALIAN} "Non riesco a trovare il programma '$INSTPROG'. Silent Update fallito." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_ITALIAN} "Controllo della versione di Windows…" -LangString CheckWindowsVersionMB ${LANG_ITALIAN} '${APPNAME} supporta solo Windows XP.$\n$\nTentare l’installazione su Windows $R0 può provocare blocchi di sistema e perdita di dati.$\n$\n' -LangString CheckWindowsServPackMB ${LANG_ITALIAN} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_ITALIAN} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_ITALIAN} "Controllo del permesso di installazione…" -LangString CheckAdministratorInstMB ${LANG_ITALIAN} 'Stai utilizzando un account “limitatoâ€.$\nSolo un “amministratore†può installare ${APPNAME}.' - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_ITALIAN} "Controllo del permesso di installazione…" -LangString CheckAdministratorUnInstMB ${LANG_ITALIAN} 'Stai utilizzando un account “limitatoâ€.$\nSolo un “amministratore†può installare ${APPNAME}.' - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_ITALIAN} "${APPNAME} ${VERSION_LONG} è stato sia già installato.$\n$\nVuoi ripetere l’installazione?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_ITALIAN} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_ITALIAN} "In attesa che Alchemy chiuda…" -LangString CloseSecondLifeInstMB ${LANG_ITALIAN} "Non è possibile installare Alchemy se è già in funzione..$\n$\nTermina le operazioni in corso e scegli OK per chiudere Alchemy e continuare.$\nScegli CANCELLA per annullare l’installazione." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_ITALIAN} "In attesa della chiusura di Alchemy…" -LangString CloseSecondLifeUnInstMB ${LANG_ITALIAN} "Non è possibile installare Alchemy se è già in funzione.$\n$\nTermina le operazioni in corso e scegli OK per chiudere Alchemy e continuare.$\nScegli CANCELLA per annullare." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_ITALIAN} "Verifica connessione di rete in corso..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_ITALIAN} "Cancellazione dei file cache nella cartella Documents and Settings" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_ITALIAN} "Sono ancora presenti dei file nella directory programmi di ${APPNAME}.$\n$\nPotrebbe trattarsi di file creati o trasferiti in:$\n$INSTDIR$\n$\nVuoi cancellarli?" - -; uninstall text -LangString UninstallTextMsg ${LANG_ITALIAN} "Così facendo ${APPNAME} verrà disinstallato ${VERSION_LONG} dal tuo sistema." +; First is default +!insertmacro MUI_LANGUAGE "Italian" + +; Language string +LangString LanguageCode ${LANG_ITALIAN} "it" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_ITALIAN} "Scegliere per favore il linguaggio del programma di installazione" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_ITALIAN} "Directory di installazione" +LangString DirectoryChooseUpdate ${LANG_ITALIAN} "Scegli la directory di ${APPNAME} per l’update alla versione ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_ITALIAN} "Scegli la directory dove installare ${APPNAME}:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_ITALIAN} "Non riesco a trovare il programma '$INSTPROG'. Silent Update fallito." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_ITALIAN} "Controllo della versione di Windows…" +LangString CheckWindowsVersionMB ${LANG_ITALIAN} '${APPNAME} supporta solo Windows XP.$\n$\nTentare l’installazione su Windows $R0 può provocare blocchi di sistema e perdita di dati.$\n$\n' +LangString CheckWindowsServPackMB ${LANG_ITALIAN} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_ITALIAN} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_ITALIAN} "Controllo del permesso di installazione…" +LangString CheckAdministratorInstMB ${LANG_ITALIAN} 'Stai utilizzando un account “limitatoâ€.$\nSolo un “amministratore†può installare ${APPNAME}.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_ITALIAN} "Controllo del permesso di installazione…" +LangString CheckAdministratorUnInstMB ${LANG_ITALIAN} 'Stai utilizzando un account “limitatoâ€.$\nSolo un “amministratore†può installare ${APPNAME}.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_ITALIAN} "${APPNAME} ${VERSION_LONG} è stato sia già installato.$\n$\nVuoi ripetere l’installazione?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_ITALIAN} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_ITALIAN} "In attesa che Alchemy chiuda…" +LangString CloseSecondLifeInstMB ${LANG_ITALIAN} "Non è possibile installare Alchemy se è già in funzione..$\n$\nTermina le operazioni in corso e scegli OK per chiudere Alchemy e continuare.$\nScegli CANCELLA per annullare l’installazione." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_ITALIAN} "In attesa della chiusura di Alchemy…" +LangString CloseSecondLifeUnInstMB ${LANG_ITALIAN} "Non è possibile installare Alchemy se è già in funzione.$\n$\nTermina le operazioni in corso e scegli OK per chiudere Alchemy e continuare.$\nScegli CANCELLA per annullare." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_ITALIAN} "Verifica connessione di rete in corso..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_ITALIAN} "Cancellazione dei file cache nella cartella Documents and Settings" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_ITALIAN} "Sono ancora presenti dei file nella directory programmi di ${APPNAME}.$\n$\nPotrebbe trattarsi di file creati o trasferiti in:$\n$INSTDIR$\n$\nVuoi cancellarli?" + +; uninstall text +LangString UninstallTextMsg ${LANG_ITALIAN} "Così facendo ${APPNAME} verrà disinstallato ${VERSION_LONG} dal tuo sistema." diff --git a/indra/newview/installers/windows/lang_ja.nsi b/indra/newview/installers/windows/lang_ja.nsi index f4cf3c75cfa0785b7303186d4ae8a5c66b943d37..1155fa7ebddd809fb236e9ad97a4e91abcd1101a 100755 --- a/indra/newview/installers/windows/lang_ja.nsi +++ b/indra/newview/installers/windows/lang_ja.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "Japanese" - -; Language string -LangString LanguageCode ${LANG_JAPANESE} "ja" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_JAPANESE} "インストーラã®è¨€èªžã‚’é¸æŠžã—ã¦ãã ã•ã„" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_JAPANESE} "インストール・ディレクトリ" -LangString DirectoryChooseUpdate ${LANG_JAPANESE} "アップデートã™ã‚‹ã‚»ã‚«ãƒ³ãƒ‰ãƒ©ã‚¤ãƒ•ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。:" -LangString DirectoryChooseSetup ${LANG_JAPANESE} "セカンドライフをインストールã™ã‚‹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。: " - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_JAPANESE} "プãƒã‚°ãƒ©ãƒ å'$INSTPROG'ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。サイレント・アップデートã«å¤±æ•—ã—ã¾ã—ãŸã€‚" - -; check windows version -LangString CheckWindowsVersionDP ${LANG_JAPANESE} "ウィンドウズã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã‚’ãƒã‚§ãƒƒã‚¯ä¸ã§ã™..." -LangString CheckWindowsVersionMB ${LANG_JAPANESE} "Second Life ã¯Windows XPã®ã¿ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚Windows $R0をインストールã™ã‚‹äº‹ã¯ã€ãƒ‡ãƒ¼ã‚¿ã®æ¶ˆå¤±ã‚„クラッシュã®åŽŸå› ã«ãªã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚インストールを続ã‘ã¾ã™ã‹ï¼Ÿ" -LangString CheckWindowsServPackMB ${LANG_JAPANESE} "It is recomended to run Firestorm on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_JAPANESE} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_JAPANESE} "インストールã®ãŸã‚ã®æ¨©é™ã‚’ãƒã‚§ãƒƒã‚¯ä¸ã§ã™..." -LangString CheckAdministratorInstMB ${LANG_JAPANESE} "セカンドライフをインストールã™ã‚‹ã«ã¯ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚" - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_JAPANESE} "アンインストールã®ãŸã‚ã®æ¨©é™ã‚’ãƒã‚§ãƒƒã‚¯ä¸ã§ã™..." -LangString CheckAdministratorUnInstMB ${LANG_JAPANESE} "セカンドライフをアンインストールã™ã‚‹ã«ã¯ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚" - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_JAPANESE} "セカンドライフ${VERSION_LONG} ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ¸ˆã¿ã§ã™ã€‚å†åº¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã‹ï¼Ÿ " - -; checkcpuflags -LangString MissingSSE2 ${LANG_JAPANESE} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_JAPANESE} "セカンドライフを終了ä¸ã§ã™..." -LangString CloseSecondLifeInstMB ${LANG_JAPANESE} "セカンドライフã®èµ·å‹•ä¸ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¯å‡ºæ¥ã¾ã›ã‚“。直ã¡ã«ã‚»ã‚«ãƒ³ãƒ‰ãƒ©ã‚¤ãƒ•ã‚’終了ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’開始ã™ã‚‹å ´åˆã¯OKボタンを押ã—ã¦ãã ã•ã„。CANCELを押ã™ã¨ä¸æ¢ã—ã¾ã™ã€‚" - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_JAPANESE} "セカンドライフを終了ä¸ã§ã™..." -LangString CloseSecondLifeUnInstMB ${LANG_JAPANESE} "セカンドライフã®èµ·å‹•ä¸ã«ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¯å‡ºæ¥ã¾ã›ã‚“。直ã¡ã«ã‚»ã‚«ãƒ³ãƒ‰ãƒ©ã‚¤ãƒ•ã‚’終了ã—ã¦ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’開始ã™ã‚‹å ´åˆã¯OKボタンを押ã—ã¦ãã ã•ã„。CANCELを押ã™ã¨ä¸æ¢ã—ã¾ã™ã€‚" - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_JAPANESE} "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®æŽ¥ç¶šã‚’確èªä¸..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_JAPANESE} " Documents and Settings フォルダã®ã‚ャッシュファイルをデリートä¸ã§ã™ã€‚" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_JAPANESE} "セカンドライフã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯ã€ã¾ã ファイルãŒæ®‹ã•ã‚Œã¦ã„ã¾ã™ã€‚$\n$INSTDIR$\nã«ã‚ãªãŸãŒä½œæˆã€ã¾ãŸã¯ç§»å‹•ã•ã›ãŸãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚å…¨ã¦å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ " - -; uninstall text -LangString UninstallTextMsg ${LANG_JAPANESE} "セカンドライフ${VERSION_LONG}をアンインストールã—ã¾ã™ã€‚" +; First is default +!insertmacro MUI_LANGUAGE "Japanese" + +; Language string +LangString LanguageCode ${LANG_JAPANESE} "ja" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_JAPANESE} "インストーラã®è¨€èªžã‚’é¸æŠžã—ã¦ãã ã•ã„" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_JAPANESE} "インストール・ディレクトリ" +LangString DirectoryChooseUpdate ${LANG_JAPANESE} "アップデートã™ã‚‹ã‚»ã‚«ãƒ³ãƒ‰ãƒ©ã‚¤ãƒ•ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。:" +LangString DirectoryChooseSetup ${LANG_JAPANESE} "セカンドライフをインストールã™ã‚‹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。: " + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_JAPANESE} "プãƒã‚°ãƒ©ãƒ å'$INSTPROG'ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。サイレント・アップデートã«å¤±æ•—ã—ã¾ã—ãŸã€‚" + +; check windows version +LangString CheckWindowsVersionDP ${LANG_JAPANESE} "ウィンドウズã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã‚’ãƒã‚§ãƒƒã‚¯ä¸ã§ã™..." +LangString CheckWindowsVersionMB ${LANG_JAPANESE} "Second Life ã¯Windows XPã®ã¿ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚Windows $R0をインストールã™ã‚‹äº‹ã¯ã€ãƒ‡ãƒ¼ã‚¿ã®æ¶ˆå¤±ã‚„クラッシュã®åŽŸå› ã«ãªã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚インストールを続ã‘ã¾ã™ã‹ï¼Ÿ" +LangString CheckWindowsServPackMB ${LANG_JAPANESE} "It is recomended to run Firestorm on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_JAPANESE} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_JAPANESE} "インストールã®ãŸã‚ã®æ¨©é™ã‚’ãƒã‚§ãƒƒã‚¯ä¸ã§ã™..." +LangString CheckAdministratorInstMB ${LANG_JAPANESE} "セカンドライフをインストールã™ã‚‹ã«ã¯ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚" + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_JAPANESE} "アンインストールã®ãŸã‚ã®æ¨©é™ã‚’ãƒã‚§ãƒƒã‚¯ä¸ã§ã™..." +LangString CheckAdministratorUnInstMB ${LANG_JAPANESE} "セカンドライフをアンインストールã™ã‚‹ã«ã¯ç®¡ç†è€…権é™ãŒå¿…è¦ã§ã™ã€‚" + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_JAPANESE} "セカンドライフ${VERSION_LONG} ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ¸ˆã¿ã§ã™ã€‚å†åº¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã‹ï¼Ÿ " + +; checkcpuflags +LangString MissingSSE2 ${LANG_JAPANESE} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_JAPANESE} "セカンドライフを終了ä¸ã§ã™..." +LangString CloseSecondLifeInstMB ${LANG_JAPANESE} "セカンドライフã®èµ·å‹•ä¸ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¯å‡ºæ¥ã¾ã›ã‚“。直ã¡ã«ã‚»ã‚«ãƒ³ãƒ‰ãƒ©ã‚¤ãƒ•ã‚’終了ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’開始ã™ã‚‹å ´åˆã¯OKボタンを押ã—ã¦ãã ã•ã„。CANCELを押ã™ã¨ä¸æ¢ã—ã¾ã™ã€‚" + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_JAPANESE} "セカンドライフを終了ä¸ã§ã™..." +LangString CloseSecondLifeUnInstMB ${LANG_JAPANESE} "セカンドライフã®èµ·å‹•ä¸ã«ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¯å‡ºæ¥ã¾ã›ã‚“。直ã¡ã«ã‚»ã‚«ãƒ³ãƒ‰ãƒ©ã‚¤ãƒ•ã‚’終了ã—ã¦ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’開始ã™ã‚‹å ´åˆã¯OKボタンを押ã—ã¦ãã ã•ã„。CANCELを押ã™ã¨ä¸æ¢ã—ã¾ã™ã€‚" + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_JAPANESE} "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®æŽ¥ç¶šã‚’確èªä¸..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_JAPANESE} " Documents and Settings フォルダã®ã‚ャッシュファイルをデリートä¸ã§ã™ã€‚" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_JAPANESE} "セカンドライフã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯ã€ã¾ã ファイルãŒæ®‹ã•ã‚Œã¦ã„ã¾ã™ã€‚$\n$INSTDIR$\nã«ã‚ãªãŸãŒä½œæˆã€ã¾ãŸã¯ç§»å‹•ã•ã›ãŸãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚å…¨ã¦å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ " + +; uninstall text +LangString UninstallTextMsg ${LANG_JAPANESE} "セカンドライフ${VERSION_LONG}をアンインストールã—ã¾ã™ã€‚" diff --git a/indra/newview/installers/windows/lang_pl.nsi b/indra/newview/installers/windows/lang_pl.nsi index bb99786941e7ef651a426cce1946acdd54883d25..36965146a96605c9b15b0a723630a9ba38fb58e9 100644 --- a/indra/newview/installers/windows/lang_pl.nsi +++ b/indra/newview/installers/windows/lang_pl.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "Polish" - -; Language string -LangString LanguageCode ${LANG_POLISH} "pl" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_POLISH} "ProszÄ™ wybrać jÄ™zyk instalatora" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_POLISH} "Katalog instalacji" -LangString DirectoryChooseUpdate ${LANG_POLISH} "Wybierz katalog instalacji ${APPNAME} w celu aktualizacji wersji ${VERSION_LONG}.(XXX):" -LangString DirectoryChooseSetup ${LANG_POLISH} "Wybierz katalog instalacji ${APPNAME} w:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_POLISH} "Nie można odnaleźć programu '$INSTPROG'. Cicha aktualizacja zakoÅ„czyÅ‚a siÄ™ niepowodzeniem." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_POLISH} "Sprawdzanie wersji Windows..." -LangString CheckWindowsVersionMB ${LANG_POLISH} '${APPNAME} obsÅ‚uguje tylko Windows XP.$\n$\nPróba zainstalowania na Windows $R0 może spowodować awarie i utratÄ™ danych.$\n$\n' -LangString CheckWindowsServPackMB ${LANG_POLISH} "Zalecane jest uruchamianie ${APPNAME} z najnowszym dostÄ™pnym Service Packiem zainstalowanym w systemie.$\nPomaga on w podniesieniu wydajnoÅ›ci i stabilnoÅ›ci programu." -LangString UseLatestServPackDP ${LANG_POLISH} "Użyj usÅ‚ugi Windows Update, aby zainstalować najnowszy Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_POLISH} "Sprawdzanie zezwolenia na instalacjÄ™..." -LangString CheckAdministratorInstMB ${LANG_POLISH} 'Używasz "ograniczonego" konta.$\nMusisz być zalogowany jako "administrator" aby zainstalować ${APPNAME}.' - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_POLISH} "Sprawdzanie zezwolenia na odinstalowanie..." -LangString CheckAdministratorUnInstMB ${LANG_POLISH} 'Używasz "ograniczonego" konta.$\nMusisz być być zalogowany jako "administrator" aby zainstalować ${APPNAME}.' - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_POLISH} "${APPNAME} ${VERSION_LONG} jest już zainstalowane.$\n$\nCzy chcesz zainstalować ${APPNAME} ponownie?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_POLISH} "Ten komputer może nie mieć procesora z obsÅ‚ugÄ… SSE2, który jest wymagany aby uruchomić ${APPNAME} w wersji ${VERSION_LONG}. Chcesz kontynuować?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_POLISH} "Oczekiwanie na zamkniÄ™cie Alchemy..." -LangString CloseSecondLifeInstMB ${LANG_POLISH} "Alchemy nie może zostać zainstalowane, ponieważ jest już wÅ‚Ä…czone.$\n$\nZakoÅ„cz swoje dziaÅ‚ania i wybierz OK aby zamknąć Alchemy i kontynuować.$\nWybierz CANCEL aby anulować instalacjÄ™." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_POLISH} "Oczekiwanie na zamkniÄ™cie Alchemy..." -LangString CloseSecondLifeUnInstMB ${LANG_POLISH} "Alchemy nie może zostać zainstalowane, ponieważ jest już wÅ‚Ä…czone.$\n$\nZakoÅ„cz swoje dziaÅ‚ania i wybierz OK aby zamknąć Alchemy i kontynuować.$\nWybierz CANCEL aby anulować." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_POLISH} "Sprawdzanie poÅ‚Ä…czenia sieciowego..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_POLISH} "Kasowanie plików pamiÄ™ci podrÄ™cznej (cache) w folderze Documents and Settings" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_POLISH} "Nadal istniejÄ… pliki w katalogu instalacyjnym ${APPNAME}.$\n$\nMożliwe, że sÄ… to pliki, które stworzyÅ‚eÅ›/stworzyÅ‚aÅ› lub przeniosÅ‚eÅ›/przeniosÅ‚aÅ› do:$\n$INSTDIR$\n$\nCzy chcesz je usunąć?" - -; uninstall text -LangString UninstallTextMsg ${LANG_POLISH} "To spowoduje odinstalowanie ${APPNAME} ${VERSION_LONG} z Twojego systemu." +; First is default +!insertmacro MUI_LANGUAGE "Polish" + +; Language string +LangString LanguageCode ${LANG_POLISH} "pl" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_POLISH} "ProszÄ™ wybrać jÄ™zyk instalatora" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_POLISH} "Katalog instalacji" +LangString DirectoryChooseUpdate ${LANG_POLISH} "Wybierz katalog instalacji ${APPNAME} w celu aktualizacji wersji ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_POLISH} "Wybierz katalog instalacji ${APPNAME} w:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_POLISH} "Nie można odnaleźć programu '$INSTPROG'. Cicha aktualizacja zakoÅ„czyÅ‚a siÄ™ niepowodzeniem." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_POLISH} "Sprawdzanie wersji Windows..." +LangString CheckWindowsVersionMB ${LANG_POLISH} '${APPNAME} obsÅ‚uguje tylko Windows XP.$\n$\nPróba zainstalowania na Windows $R0 może spowodować awarie i utratÄ™ danych.$\n$\n' +LangString CheckWindowsServPackMB ${LANG_POLISH} "Zalecane jest uruchamianie ${APPNAME} z najnowszym dostÄ™pnym Service Packiem zainstalowanym w systemie.$\nPomaga on w podniesieniu wydajnoÅ›ci i stabilnoÅ›ci programu." +LangString UseLatestServPackDP ${LANG_POLISH} "Użyj usÅ‚ugi Windows Update, aby zainstalować najnowszy Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_POLISH} "Sprawdzanie zezwolenia na instalacjÄ™..." +LangString CheckAdministratorInstMB ${LANG_POLISH} 'Używasz "ograniczonego" konta.$\nMusisz być zalogowany jako "administrator" aby zainstalować ${APPNAME}.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_POLISH} "Sprawdzanie zezwolenia na odinstalowanie..." +LangString CheckAdministratorUnInstMB ${LANG_POLISH} 'Używasz "ograniczonego" konta.$\nMusisz być być zalogowany jako "administrator" aby zainstalować ${APPNAME}.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_POLISH} "${APPNAME} ${VERSION_LONG} jest już zainstalowane.$\n$\nCzy chcesz zainstalować ${APPNAME} ponownie?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_POLISH} "Ten komputer może nie mieć procesora z obsÅ‚ugÄ… SSE2, który jest wymagany aby uruchomić ${APPNAME} w wersji ${VERSION_LONG}. Chcesz kontynuować?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_POLISH} "Oczekiwanie na zamkniÄ™cie Alchemy..." +LangString CloseSecondLifeInstMB ${LANG_POLISH} "Alchemy nie może zostać zainstalowane, ponieważ jest już wÅ‚Ä…czone.$\n$\nZakoÅ„cz swoje dziaÅ‚ania i wybierz OK aby zamknąć Alchemy i kontynuować.$\nWybierz CANCEL aby anulować instalacjÄ™." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_POLISH} "Oczekiwanie na zamkniÄ™cie Alchemy..." +LangString CloseSecondLifeUnInstMB ${LANG_POLISH} "Alchemy nie może zostać zainstalowane, ponieważ jest już wÅ‚Ä…czone.$\n$\nZakoÅ„cz swoje dziaÅ‚ania i wybierz OK aby zamknąć Alchemy i kontynuować.$\nWybierz CANCEL aby anulować." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_POLISH} "Sprawdzanie poÅ‚Ä…czenia sieciowego..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_POLISH} "Kasowanie plików pamiÄ™ci podrÄ™cznej (cache) w folderze Documents and Settings" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_POLISH} "Nadal istniejÄ… pliki w katalogu instalacyjnym ${APPNAME}.$\n$\nMożliwe, że sÄ… to pliki, które stworzyÅ‚eÅ›/stworzyÅ‚aÅ› lub przeniosÅ‚eÅ›/przeniosÅ‚aÅ› do:$\n$INSTDIR$\n$\nCzy chcesz je usunąć?" + +; uninstall text +LangString UninstallTextMsg ${LANG_POLISH} "To spowoduje odinstalowanie ${APPNAME} ${VERSION_LONG} z Twojego systemu." diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsi index d7984a50c614f43bcb0643a023dfe885f0240e6d..7b99a65239d329427a2339f4e54cb6bbae9c7a0d 100755 --- a/indra/newview/installers/windows/lang_pt-br.nsi +++ b/indra/newview/installers/windows/lang_pt-br.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "PortugueseBR" - -; Language string -LangString LanguageCode ${LANG_PORTUGUESEBR} "pt" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_PORTUGUESEBR} "Por favor seleccione a linguagem do instalador" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_PORTUGUESEBR} "Diretório de Instalação" -LangString DirectoryChooseUpdate ${LANG_PORTUGUESEBR} "Selecione o diretório do ${APPNAME} para atualizar para a versão ${VERSION_LONG}.(XXX):" -LangString DirectoryChooseSetup ${LANG_PORTUGUESEBR} "Selecione o diretório para a instalação do ${APPNAME} em:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_PORTUGUESEBR} "Não é possÃvel encontrar o programa '$INSTPROG'. Ocorreu uma falha na atualização silenciosa." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_PORTUGUESEBR} "Verificando a versão do Windows..." -LangString CheckWindowsVersionMB ${LANG_PORTUGUESEBR} 'O ${APPNAME} suporta apenas Windows XP.$\n$\nA tentativa de instalar no Windows $R0 pode resultar em falhas e perda de dados.$\n$\n' -LangString CheckWindowsServPackMB ${LANG_PORTUGUESEBR} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_PORTUGUESEBR} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_PORTUGUESEBR} "Verificando a permissão para instalação..." -LangString CheckAdministratorInstMB ${LANG_PORTUGUESEBR} 'Você parece estar usando uma conta "limitada".$\nVocê deve ser um "administrador" para poder instalar o ${APPNAME}.' - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_PORTUGUESEBR} "Verificando a permissão para desinstalação..." -LangString CheckAdministratorUnInstMB ${LANG_PORTUGUESEBR} 'Você parece estar usando uma conta "limitada".$\nVocê deve ser um "administrador" para poder desinstalar o ${APPNAME}.' - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_PORTUGUESEBR} "Parece que o ${APPNAME} ${VERSION_LONG} já está instalado.$\n$\nDeseja instalar novamente?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_PORTUGUESEBR} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_PORTUGUESEBR} "Esperando o encerramento do Alchemy..." -LangString CloseSecondLifeInstMB ${LANG_PORTUGUESEBR} "O Alchemy não pode ser instalado enquanto ainda está sendo executado.$\n$\nTermine o que estava fazendo e selecione OK para fechar o Alchemy e continuar.$\nSelecione CANCELAR para cancelar a instalação." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_PORTUGUESEBR} "Esperando o encerramento do Alchemy..." -LangString CloseSecondLifeUnInstMB ${LANG_PORTUGUESEBR} "O Alchemy não pode ser desinstalado enquanto ainda está sendo executado.$\n$\nTermine o que estava fazendo e selecione OK para fechar o Alchemy e continuar.$\nSelecione CANCELAR para cancelar." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_PORTUGUESEBR} "Verificando a conexão de rede..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_PORTUGUESEBR} "Excluindo arquivos de cache na pasta Documents and Settings" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_PORTUGUESEBR} "Ainda existem arquivos em seu diretório do programa ${APPNAME}.$\n$\nProvavelmente são arquivos que você criou ou moveu para:$\n$INSTDIR$\n$\nDeseja removê-los?" - -; uninstall text -LangString UninstallTextMsg ${LANG_PORTUGUESEBR} "Isso desinstalará o ${APPNAME} ${VERSION_LONG} do seu sistema." +; First is default +!insertmacro MUI_LANGUAGE "PortugueseBR" + +; Language string +LangString LanguageCode ${LANG_PORTUGUESEBR} "pt" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_PORTUGUESEBR} "Por favor seleccione a linguagem do instalador" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_PORTUGUESEBR} "Diretório de Instalação" +LangString DirectoryChooseUpdate ${LANG_PORTUGUESEBR} "Selecione o diretório do ${APPNAME} para atualizar para a versão ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_PORTUGUESEBR} "Selecione o diretório para a instalação do ${APPNAME} em:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_PORTUGUESEBR} "Não é possÃvel encontrar o programa '$INSTPROG'. Ocorreu uma falha na atualização silenciosa." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_PORTUGUESEBR} "Verificando a versão do Windows..." +LangString CheckWindowsVersionMB ${LANG_PORTUGUESEBR} 'O ${APPNAME} suporta apenas Windows XP.$\n$\nA tentativa de instalar no Windows $R0 pode resultar em falhas e perda de dados.$\n$\n' +LangString CheckWindowsServPackMB ${LANG_PORTUGUESEBR} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_PORTUGUESEBR} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_PORTUGUESEBR} "Verificando a permissão para instalação..." +LangString CheckAdministratorInstMB ${LANG_PORTUGUESEBR} 'Você parece estar usando uma conta "limitada".$\nVocê deve ser um "administrador" para poder instalar o ${APPNAME}.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_PORTUGUESEBR} "Verificando a permissão para desinstalação..." +LangString CheckAdministratorUnInstMB ${LANG_PORTUGUESEBR} 'Você parece estar usando uma conta "limitada".$\nVocê deve ser um "administrador" para poder desinstalar o ${APPNAME}.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_PORTUGUESEBR} "Parece que o ${APPNAME} ${VERSION_LONG} já está instalado.$\n$\nDeseja instalar novamente?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_PORTUGUESEBR} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_PORTUGUESEBR} "Esperando o encerramento do Alchemy..." +LangString CloseSecondLifeInstMB ${LANG_PORTUGUESEBR} "O Alchemy não pode ser instalado enquanto ainda está sendo executado.$\n$\nTermine o que estava fazendo e selecione OK para fechar o Alchemy e continuar.$\nSelecione CANCELAR para cancelar a instalação." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_PORTUGUESEBR} "Esperando o encerramento do Alchemy..." +LangString CloseSecondLifeUnInstMB ${LANG_PORTUGUESEBR} "O Alchemy não pode ser desinstalado enquanto ainda está sendo executado.$\n$\nTermine o que estava fazendo e selecione OK para fechar o Alchemy e continuar.$\nSelecione CANCELAR para cancelar." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_PORTUGUESEBR} "Verificando a conexão de rede..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_PORTUGUESEBR} "Excluindo arquivos de cache na pasta Documents and Settings" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_PORTUGUESEBR} "Ainda existem arquivos em seu diretório do programa ${APPNAME}.$\n$\nProvavelmente são arquivos que você criou ou moveu para:$\n$INSTDIR$\n$\nDeseja removê-los?" + +; uninstall text +LangString UninstallTextMsg ${LANG_PORTUGUESEBR} "Isso desinstalará o ${APPNAME} ${VERSION_LONG} do seu sistema." diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi index e61d39f56000309c8eeac53bc785a26bfe542797..9236ac6de78f0a54be0b5b0da05eec1919ca7ba4 100755 --- a/indra/newview/installers/windows/lang_ru.nsi +++ b/indra/newview/installers/windows/lang_ru.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "Russian" - -; Language string -LangString LanguageCode ${LANG_RUSSIAN} "ru" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_RUSSIAN} "Выберите Ñзык программы уÑтановки" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_RUSSIAN} "Каталог уÑтановки" -LangString DirectoryChooseUpdate ${LANG_RUSSIAN} "Выберите каталог ${APPNAME} Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾ верÑии ${VERSION_LONG}.(XXX):" -LangString DirectoryChooseSetup ${LANG_RUSSIAN} "Выберите каталог Ð´Ð»Ñ ÑƒÑтановки ${APPNAME}:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_RUSSIAN} "Ðе удалоÑÑŒ найти программу «$INSTPROG». ÐвтоматичеÑкое обновление не выполнено." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_RUSSIAN} "Проверка верÑии Windows..." -LangString CheckWindowsVersionMB ${LANG_RUSSIAN} '${APPNAME} может работать только в Windows XP.$\n$\nПопытка уÑтановки в Windows $R0 может привеÑти к Ñбою и потере данных.$\n$\n' -LangString CheckWindowsServPackMB ${LANG_RUSSIAN} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_RUSSIAN} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_RUSSIAN} "Проверка разрешений на уÑтановку..." -LangString CheckAdministratorInstMB ${LANG_RUSSIAN} 'ВероÑтно, у Ð²Ð°Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð½Ñ‹Ð¹ аккаунт.$\nÐ”Ð»Ñ ÑƒÑтановки ${APPNAME} необходимы права админиÑтратора.' - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_RUSSIAN} "Проверка разрешений на удаление..." -LangString CheckAdministratorUnInstMB ${LANG_RUSSIAN} 'ВероÑтно, у Ð²Ð°Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð½Ñ‹Ð¹ аккаунт.$\nÐ”Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ${APPNAME} необходимы права админиÑтратора.' - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_RUSSIAN} "ВероÑтно, верÑÐ¸Ñ ${APPNAME} ${VERSION_LONG} уже уÑтановлена.$\n$\nУÑтановить ее Ñнова?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_RUSSIAN} "Возможно, на Ñтом компьютере нет ЦП Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ SSE2, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼Ð° Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ ${APPNAME} ${VERSION_LONG}. Продолжить?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_RUSSIAN} "Ожидаю Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Alchemy..." -LangString CloseSecondLifeInstMB ${LANG_RUSSIAN} "Alchemy уже работает, выполнить уÑтановку невозможно.$\n$\nЗавершите текущую операцию и нажмите кнопку «OK», чтобы закрыть Alchemy и продолжить уÑтановку.$\nÐажмите кнопку «ОТМЕÐл Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ°Ð·Ð° от уÑтановки." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_RUSSIAN} "Ожидаю Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Alchemy..." -LangString CloseSecondLifeUnInstMB ${LANG_RUSSIAN} "Alchemy уже работает, выполнить удаление невозможно.$\n$\nЗавершите текущую операцию и нажмите кнопку «OK», чтобы закрыть Alchemy и продолжить удаление.$\nÐажмите кнопку «ОТМЕÐл Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ°Ð·Ð° от удалениÑ." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_RUSSIAN} "Проверка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Ñети..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_RUSSIAN} "Удаление файлов кÑша из папки «Documents and Settings»" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_RUSSIAN} "Ð’ каталоге программы ${APPNAME} оÑталиÑÑŒ файлы.$\n$\nВероÑтно, Ñто файлы, Ñозданные или перемещенные вами в $\n$INSTDIR$\n$\nУдалить их?" - -; uninstall text -LangString UninstallTextMsg ${LANG_RUSSIAN} "Программа ${APPNAME} ${VERSION_LONG} будет удалена из вашей ÑиÑтемы." +; First is default +!insertmacro MUI_LANGUAGE "Russian" + +; Language string +LangString LanguageCode ${LANG_RUSSIAN} "ru" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_RUSSIAN} "Выберите Ñзык программы уÑтановки" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_RUSSIAN} "Каталог уÑтановки" +LangString DirectoryChooseUpdate ${LANG_RUSSIAN} "Выберите каталог ${APPNAME} Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾ верÑии ${VERSION_LONG}.(XXX):" +LangString DirectoryChooseSetup ${LANG_RUSSIAN} "Выберите каталог Ð´Ð»Ñ ÑƒÑтановки ${APPNAME}:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_RUSSIAN} "Ðе удалоÑÑŒ найти программу «$INSTPROG». ÐвтоматичеÑкое обновление не выполнено." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_RUSSIAN} "Проверка верÑии Windows..." +LangString CheckWindowsVersionMB ${LANG_RUSSIAN} '${APPNAME} может работать только в Windows XP.$\n$\nПопытка уÑтановки в Windows $R0 может привеÑти к Ñбою и потере данных.$\n$\n' +LangString CheckWindowsServPackMB ${LANG_RUSSIAN} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_RUSSIAN} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_RUSSIAN} "Проверка разрешений на уÑтановку..." +LangString CheckAdministratorInstMB ${LANG_RUSSIAN} 'ВероÑтно, у Ð²Ð°Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð½Ñ‹Ð¹ аккаунт.$\nÐ”Ð»Ñ ÑƒÑтановки ${APPNAME} необходимы права админиÑтратора.' + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_RUSSIAN} "Проверка разрешений на удаление..." +LangString CheckAdministratorUnInstMB ${LANG_RUSSIAN} 'ВероÑтно, у Ð²Ð°Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð½Ñ‹Ð¹ аккаунт.$\nÐ”Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ${APPNAME} необходимы права админиÑтратора.' + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_RUSSIAN} "ВероÑтно, верÑÐ¸Ñ ${APPNAME} ${VERSION_LONG} уже уÑтановлена.$\n$\nУÑтановить ее Ñнова?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_RUSSIAN} "Возможно, на Ñтом компьютере нет ЦП Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ SSE2, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼Ð° Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ ${APPNAME} ${VERSION_LONG}. Продолжить?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_RUSSIAN} "Ожидаю Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Alchemy..." +LangString CloseSecondLifeInstMB ${LANG_RUSSIAN} "Alchemy уже работает, выполнить уÑтановку невозможно.$\n$\nЗавершите текущую операцию и нажмите кнопку «OK», чтобы закрыть Alchemy и продолжить уÑтановку.$\nÐажмите кнопку «ОТМЕÐл Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ°Ð·Ð° от уÑтановки." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_RUSSIAN} "Ожидаю Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Alchemy..." +LangString CloseSecondLifeUnInstMB ${LANG_RUSSIAN} "Alchemy уже работает, выполнить удаление невозможно.$\n$\nЗавершите текущую операцию и нажмите кнопку «OK», чтобы закрыть Alchemy и продолжить удаление.$\nÐажмите кнопку «ОТМЕÐл Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ°Ð·Ð° от удалениÑ." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_RUSSIAN} "Проверка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Ñети..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_RUSSIAN} "Удаление файлов кÑша из папки «Documents and Settings»" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_RUSSIAN} "Ð’ каталоге программы ${APPNAME} оÑталиÑÑŒ файлы.$\n$\nВероÑтно, Ñто файлы, Ñозданные или перемещенные вами в $\n$INSTDIR$\n$\nУдалить их?" + +; uninstall text +LangString UninstallTextMsg ${LANG_RUSSIAN} "Программа ${APPNAME} ${VERSION_LONG} будет удалена из вашей ÑиÑтемы." diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsi index 5d524929f2e5de1f3815c317a33595ebf7878e4d..6df21e89f45862ec08e4818ed9ad4fd07d0b42ec 100755 --- a/indra/newview/installers/windows/lang_tr.nsi +++ b/indra/newview/installers/windows/lang_tr.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "Turkish" - -; Language string -LangString LanguageCode ${LANG_TURKISH} "tr" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_TURKISH} "Lütfen yükleyicinin dilini seçin" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_TURKISH} "Yükleme Dizini" -LangString DirectoryChooseUpdate ${LANG_TURKISH} "${VERSION_LONG}.(XXX) sürümüne güncelleÅŸtirme yapmak için ${APPNAME} dizinini seçin:" -LangString DirectoryChooseSetup ${LANG_TURKISH} "${APPNAME}'ın yükleneceÄŸi dizini seçin:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_TURKISH} "'$INSTPROG' programı bulunamadı. Sessiz güncelleÅŸtirme baÅŸarılamadı." - -; check windows version -LangString CheckWindowsVersionDP ${LANG_TURKISH} "Windows sürümü kontrol ediliyor..." -LangString CheckWindowsVersionMB ${LANG_TURKISH} "${APPNAME} sadece Windows XP'i destekler.$\n$\nWindows $R0 üzerine yüklemeye çalışmak sistem çökmelerine ve veri kaybına neden olabilir.$\n$\n" -LangString CheckWindowsServPackMB ${LANG_TURKISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_TURKISH} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_TURKISH} "Yükleme izni kontrol ediliyor..." -LangString CheckAdministratorInstMB ${LANG_TURKISH} "'Sınırlı' bir hesap kullanıyor görünüyorsunuz.$\n${APPNAME}'ı yüklemek için bir 'yönetici' olmalısınız." - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_TURKISH} "Kaldırma izni kontrol ediliyor..." -LangString CheckAdministratorUnInstMB ${LANG_TURKISH} "'Sınırlı' bir hesap kullanıyor görünüyorsunuz.$\n${APPNAME}'ı kaldırmak için bir 'yönetici' olmalısınız." - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_TURKISH} "${APPNAME} ${VERSION_LONG} zaten yüklü.$\n$\nTekrar yüklemek ister misiniz?" - -; checkcpuflags -LangString MissingSSE2 ${LANG_TURKISH} "Bu makinede SSE2 desteÄŸine sahip bir CPU bulunmayabilir, ${APPNAME} ${VERSION_LONG} çalıştırmak için bu gereklidir. Devam etmek istiyor musunuz?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_TURKISH} "Alchemy'ın kapatılması bekleniyor..." -LangString CloseSecondLifeInstMB ${LANG_TURKISH} "Alchemy zaten çalışırken kapatılamaz.$\n$\nYaptığınız iÅŸi bitirdikten sonra Alchemy'ı kapatmak ve devam etmek için Tamam seçimini yapın.$\nYüklemeyi iptal etmek için Ä°PTAL seçimini yapın." - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_TURKISH} "Alchemy'ın kapatılması bekleniyor..." -LangString CloseSecondLifeUnInstMB ${LANG_TURKISH} "Alchemy zaten çalışırken kaldırılamaz.$\n$\nYaptığınız iÅŸi bitirdikten sonra Alchemy'ı kapatmak ve devam etmek için Tamam seçimini yapın.$\nÄ°ptal etmek için Ä°PTAL seçimini yapın." - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_TURKISH} "AÄŸ baÄŸlantısı kontrol ediliyor..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_TURKISH} "Belgeler ve Ayarlar klasöründeki önbellek dosyaları siliniyor" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_TURKISH} "${APPNAME} program dizininizde hala dosyalar var.$\n$\nBunlar muhtemelen sizin oluÅŸturduÄŸunuz veya ÅŸuraya taşıdığınız dosyalar:$\n$INSTDIR$\n$\nBunları kaldırmak istiyor musunuz?" - -; uninstall text -LangString UninstallTextMsg ${LANG_TURKISH} "Bu adımla ${APPNAME} ${VERSION_LONG} sisteminizden kaldırılacaktır." +; First is default +!insertmacro MUI_LANGUAGE "Turkish" + +; Language string +LangString LanguageCode ${LANG_TURKISH} "tr" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_TURKISH} "Lütfen yükleyicinin dilini seçin" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_TURKISH} "Yükleme Dizini" +LangString DirectoryChooseUpdate ${LANG_TURKISH} "${VERSION_LONG}.(XXX) sürümüne güncelleÅŸtirme yapmak için ${APPNAME} dizinini seçin:" +LangString DirectoryChooseSetup ${LANG_TURKISH} "${APPNAME}'ın yükleneceÄŸi dizini seçin:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_TURKISH} "'$INSTPROG' programı bulunamadı. Sessiz güncelleÅŸtirme baÅŸarılamadı." + +; check windows version +LangString CheckWindowsVersionDP ${LANG_TURKISH} "Windows sürümü kontrol ediliyor..." +LangString CheckWindowsVersionMB ${LANG_TURKISH} "${APPNAME} sadece Windows XP'i destekler.$\n$\nWindows $R0 üzerine yüklemeye çalışmak sistem çökmelerine ve veri kaybına neden olabilir.$\n$\n" +LangString CheckWindowsServPackMB ${LANG_TURKISH} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_TURKISH} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_TURKISH} "Yükleme izni kontrol ediliyor..." +LangString CheckAdministratorInstMB ${LANG_TURKISH} "'Sınırlı' bir hesap kullanıyor görünüyorsunuz.$\n${APPNAME}'ı yüklemek için bir 'yönetici' olmalısınız." + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_TURKISH} "Kaldırma izni kontrol ediliyor..." +LangString CheckAdministratorUnInstMB ${LANG_TURKISH} "'Sınırlı' bir hesap kullanıyor görünüyorsunuz.$\n${APPNAME}'ı kaldırmak için bir 'yönetici' olmalısınız." + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_TURKISH} "${APPNAME} ${VERSION_LONG} zaten yüklü.$\n$\nTekrar yüklemek ister misiniz?" + +; checkcpuflags +LangString MissingSSE2 ${LANG_TURKISH} "Bu makinede SSE2 desteÄŸine sahip bir CPU bulunmayabilir, ${APPNAME} ${VERSION_LONG} çalıştırmak için bu gereklidir. Devam etmek istiyor musunuz?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_TURKISH} "Alchemy'ın kapatılması bekleniyor..." +LangString CloseSecondLifeInstMB ${LANG_TURKISH} "Alchemy zaten çalışırken kapatılamaz.$\n$\nYaptığınız iÅŸi bitirdikten sonra Alchemy'ı kapatmak ve devam etmek için Tamam seçimini yapın.$\nYüklemeyi iptal etmek için Ä°PTAL seçimini yapın." + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_TURKISH} "Alchemy'ın kapatılması bekleniyor..." +LangString CloseSecondLifeUnInstMB ${LANG_TURKISH} "Alchemy zaten çalışırken kaldırılamaz.$\n$\nYaptığınız iÅŸi bitirdikten sonra Alchemy'ı kapatmak ve devam etmek için Tamam seçimini yapın.$\nÄ°ptal etmek için Ä°PTAL seçimini yapın." + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_TURKISH} "AÄŸ baÄŸlantısı kontrol ediliyor..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_TURKISH} "Belgeler ve Ayarlar klasöründeki önbellek dosyaları siliniyor" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_TURKISH} "${APPNAME} program dizininizde hala dosyalar var.$\n$\nBunlar muhtemelen sizin oluÅŸturduÄŸunuz veya ÅŸuraya taşıdığınız dosyalar:$\n$INSTDIR$\n$\nBunları kaldırmak istiyor musunuz?" + +; uninstall text +LangString UninstallTextMsg ${LANG_TURKISH} "Bu adımla ${APPNAME} ${VERSION_LONG} sisteminizden kaldırılacaktır." diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi index 764ac0cfd24317391c9c8a623b0a94d8286f55f6..3695b5e31cae2c75dfa8d6585baed0d5d827c8be 100755 --- a/indra/newview/installers/windows/lang_zh.nsi +++ b/indra/newview/installers/windows/lang_zh.nsi @@ -1,56 +1,56 @@ -; First is default -!insertmacro MUI_LANGUAGE "TradChinese" - -; Language string -LangString LanguageCode ${LANG_TRADCHINESE} "zh" - -; Language selection dialog -LangString SelectInstallerLanguage ${LANG_TRADCHINESE} "è«‹é¸æ“‡å®‰è£æ™‚使用的語言。" - -; installation directory text -LangString DirectoryChooseTitle ${LANG_TRADCHINESE} "安è£ç›®éŒ„" -LangString DirectoryChooseUpdate ${LANG_TRADCHINESE} "è«‹é¸æ“‡ ${APPNAME} 的安è£ç›®éŒ„ï¼Œä»¥ä¾¿æ–¼å°‡è»Ÿé«”æ›´æ–°æˆ ${VERSION_LONG} 版本(XXX):" -LangString DirectoryChooseSetup ${LANG_TRADCHINESE} "è«‹é¸æ“‡å®‰è£ ${APPNAME} 的目錄:" - -; CheckStartupParams message box -LangString CheckStartupParamsMB ${LANG_TRADCHINESE} "找ä¸åˆ° '$INSTPROG' 程åºã€‚自動更新失敗。" - -; check windows version -LangString CheckWindowsVersionDP ${LANG_TRADCHINESE} "檢查 Windows 版本…" -LangString CheckWindowsVersionMB ${LANG_TRADCHINESE} "${APPNAME} åªæ”¯æ´ Windows XP。$\n$\n如果嘗試在 Windows $R0 上安è£ï¼Œå¯èƒ½å°Žè‡´ç•¶æ©Ÿå’Œè³‡æ–™éºå¤±ã€‚$\n$\n" -LangString CheckWindowsServPackMB ${LANG_TRADCHINESE} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." -LangString UseLatestServPackDP ${LANG_TRADCHINESE} "Please use Windows Update to install the latest Service Pack." - -; checkifadministrator function (install) -LangString CheckAdministratorInstDP ${LANG_TRADCHINESE} "檢查安è£æ‰€éœ€çš„權é™..." -LangString CheckAdministratorInstMB ${LANG_TRADCHINESE} "您的帳戶似乎是「å—é™çš„帳戶ã€ã€‚$\næ‚¨å¿…é ˆæœ‰ã€Œç®¡ç†å“¡ã€æ¬Šé™æ‰å¯ä»¥å®‰è£ ${APPNAME}。" - -; checkifadministrator function (uninstall) -LangString CheckAdministratorUnInstDP ${LANG_TRADCHINESE} "檢查å¸è¼‰æ‰€éœ€çš„權é™..." -LangString CheckAdministratorUnInstMB ${LANG_TRADCHINESE} "您的帳戶似乎是「å—é™çš„帳戶ã€ã€‚$\næ‚¨å¿…é ˆæœ‰ã€Œç®¡ç†å“¡ã€æ¬Šé™æ‰å¯ä»¥å¸è¼‰ ${APPNAME}。" - -; checkifalreadycurrent -LangString CheckIfCurrentMB ${LANG_TRADCHINESE} "${APPNAME} ${VERSION_LONG} 版本似乎已經å˜åœ¨ã€‚$\n$\n您還想å†å®‰è£ä¸€æ¬¡ï¼Ÿ" - -; checkcpuflags -LangString MissingSSE2 ${LANG_TRADCHINESE} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" - -; closesecondlife function (install) -LangString CloseSecondLifeInstDP ${LANG_TRADCHINESE} "ç‰å¾… Alchemy åœæ¢é‹è¡Œâ€¦" -LangString CloseSecondLifeInstMB ${LANG_TRADCHINESE} "如果 Alchemy ä»åœ¨é‹è¡Œï¼Œå°‡ç„¡æ³•é€²è¡Œå®‰è£ã€‚$\n$\nè«‹çµæŸæ‚¨åœ¨ Alchemy 內的活動,然後é¸æ“‡ç¢ºå®šï¼Œå°‡ Alchemy 關閉,以繼續安è£ã€‚$\né¸æ“‡ã€Œå–消ã€ï¼Œå–消安è£ã€‚" - -; closesecondlife function (uninstall) -LangString CloseSecondLifeUnInstDP ${LANG_TRADCHINESE} "ç‰å¾… Alchemy åœæ¢é‹è¡Œâ€¦" -LangString CloseSecondLifeUnInstMB ${LANG_TRADCHINESE} "如果 Alchemy ä»åœ¨é‹è¡Œï¼Œå°‡ç„¡æ³•é€²è¡Œå¸è¼‰ã€‚$\n$\nè«‹çµæŸæ‚¨åœ¨ Alchemy 內的活動,然後é¸æ“‡ç¢ºå®šï¼Œå°‡ Alchemy 關閉,以繼續å¸è¼‰ã€‚$\né¸æ“‡ã€Œå–消ã€ï¼Œå–消å¸è¼‰ã€‚" - -; CheckNetworkConnection -LangString CheckNetworkConnectionDP ${LANG_TRADCHINESE} "æ£åœ¨æª¢æŸ¥ç¶²è·¯é€£æŽ¥..." - -; removecachefiles -LangString RemoveCacheFilesDP ${LANG_TRADCHINESE} "æ£åœ¨åˆªé™¤ Documents and Settings 文件夾ä¸çš„æš«å˜æ–‡ä»¶ã€‚" - -; delete program files -LangString DeleteProgramFilesMB ${LANG_TRADCHINESE} "在您的 ${APPNAME} 程å¼ç›®éŒ„裡ä»å˜æœ‰ä¸€äº›æ–‡ä»¶ã€‚$\n$\n這些文件å¯èƒ½æ˜¯æ‚¨æ–°å»ºæˆ–移動到 $\n$INSTDIR 文件夾ä¸çš„。$\n $\n您還想è¦åŠ 以刪除嗎?" - -; uninstall text -LangString UninstallTextMsg ${LANG_TRADCHINESE} "將從您的系統ä¸å¸è¼‰ ${APPNAME} ${VERSION_LONG}。" +; First is default +!insertmacro MUI_LANGUAGE "TradChinese" + +; Language string +LangString LanguageCode ${LANG_TRADCHINESE} "zh" + +; Language selection dialog +LangString SelectInstallerLanguage ${LANG_TRADCHINESE} "è«‹é¸æ“‡å®‰è£æ™‚使用的語言。" + +; installation directory text +LangString DirectoryChooseTitle ${LANG_TRADCHINESE} "安è£ç›®éŒ„" +LangString DirectoryChooseUpdate ${LANG_TRADCHINESE} "è«‹é¸æ“‡ ${APPNAME} 的安è£ç›®éŒ„ï¼Œä»¥ä¾¿æ–¼å°‡è»Ÿé«”æ›´æ–°æˆ ${VERSION_LONG} 版本(XXX):" +LangString DirectoryChooseSetup ${LANG_TRADCHINESE} "è«‹é¸æ“‡å®‰è£ ${APPNAME} 的目錄:" + +; CheckStartupParams message box +LangString CheckStartupParamsMB ${LANG_TRADCHINESE} "找ä¸åˆ° '$INSTPROG' 程åºã€‚自動更新失敗。" + +; check windows version +LangString CheckWindowsVersionDP ${LANG_TRADCHINESE} "檢查 Windows 版本…" +LangString CheckWindowsVersionMB ${LANG_TRADCHINESE} "${APPNAME} åªæ”¯æ´ Windows XP。$\n$\n如果嘗試在 Windows $R0 上安è£ï¼Œå¯èƒ½å°Žè‡´ç•¶æ©Ÿå’Œè³‡æ–™éºå¤±ã€‚$\n$\n" +LangString CheckWindowsServPackMB ${LANG_TRADCHINESE} "It is recomended to run ${APPNAME} on the latest service pack for your operating system.$\nThis will help with performance and stability of the program." +LangString UseLatestServPackDP ${LANG_TRADCHINESE} "Please use Windows Update to install the latest Service Pack." + +; checkifadministrator function (install) +LangString CheckAdministratorInstDP ${LANG_TRADCHINESE} "檢查安è£æ‰€éœ€çš„權é™..." +LangString CheckAdministratorInstMB ${LANG_TRADCHINESE} "您的帳戶似乎是「å—é™çš„帳戶ã€ã€‚$\næ‚¨å¿…é ˆæœ‰ã€Œç®¡ç†å“¡ã€æ¬Šé™æ‰å¯ä»¥å®‰è£ ${APPNAME}。" + +; checkifadministrator function (uninstall) +LangString CheckAdministratorUnInstDP ${LANG_TRADCHINESE} "檢查å¸è¼‰æ‰€éœ€çš„權é™..." +LangString CheckAdministratorUnInstMB ${LANG_TRADCHINESE} "您的帳戶似乎是「å—é™çš„帳戶ã€ã€‚$\næ‚¨å¿…é ˆæœ‰ã€Œç®¡ç†å“¡ã€æ¬Šé™æ‰å¯ä»¥å¸è¼‰ ${APPNAME}。" + +; checkifalreadycurrent +LangString CheckIfCurrentMB ${LANG_TRADCHINESE} "${APPNAME} ${VERSION_LONG} 版本似乎已經å˜åœ¨ã€‚$\n$\n您還想å†å®‰è£ä¸€æ¬¡ï¼Ÿ" + +; checkcpuflags +LangString MissingSSE2 ${LANG_TRADCHINESE} "This machine may not have a CPU with SSE2 support, which is required to run ${APPNAME} ${VERSION_LONG}. Do you want to continue?" + +; closesecondlife function (install) +LangString CloseSecondLifeInstDP ${LANG_TRADCHINESE} "ç‰å¾… Alchemy åœæ¢é‹è¡Œâ€¦" +LangString CloseSecondLifeInstMB ${LANG_TRADCHINESE} "如果 Alchemy ä»åœ¨é‹è¡Œï¼Œå°‡ç„¡æ³•é€²è¡Œå®‰è£ã€‚$\n$\nè«‹çµæŸæ‚¨åœ¨ Alchemy 內的活動,然後é¸æ“‡ç¢ºå®šï¼Œå°‡ Alchemy 關閉,以繼續安è£ã€‚$\né¸æ“‡ã€Œå–消ã€ï¼Œå–消安è£ã€‚" + +; closesecondlife function (uninstall) +LangString CloseSecondLifeUnInstDP ${LANG_TRADCHINESE} "ç‰å¾… Alchemy åœæ¢é‹è¡Œâ€¦" +LangString CloseSecondLifeUnInstMB ${LANG_TRADCHINESE} "如果 Alchemy ä»åœ¨é‹è¡Œï¼Œå°‡ç„¡æ³•é€²è¡Œå¸è¼‰ã€‚$\n$\nè«‹çµæŸæ‚¨åœ¨ Alchemy 內的活動,然後é¸æ“‡ç¢ºå®šï¼Œå°‡ Alchemy 關閉,以繼續å¸è¼‰ã€‚$\né¸æ“‡ã€Œå–消ã€ï¼Œå–消å¸è¼‰ã€‚" + +; CheckNetworkConnection +LangString CheckNetworkConnectionDP ${LANG_TRADCHINESE} "æ£åœ¨æª¢æŸ¥ç¶²è·¯é€£æŽ¥..." + +; removecachefiles +LangString RemoveCacheFilesDP ${LANG_TRADCHINESE} "æ£åœ¨åˆªé™¤ Documents and Settings 文件夾ä¸çš„æš«å˜æ–‡ä»¶ã€‚" + +; delete program files +LangString DeleteProgramFilesMB ${LANG_TRADCHINESE} "在您的 ${APPNAME} 程å¼ç›®éŒ„裡ä»å˜æœ‰ä¸€äº›æ–‡ä»¶ã€‚$\n$\n這些文件å¯èƒ½æ˜¯æ‚¨æ–°å»ºæˆ–移動到 $\n$INSTDIR 文件夾ä¸çš„。$\n $\n您還想è¦åŠ 以刪除嗎?" + +; uninstall text +LangString UninstallTextMsg ${LANG_TRADCHINESE} "將從您的系統ä¸å¸è¼‰ ${APPNAME} ${VERSION_LONG}。" diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index d6b3cd03afb47b7480b4baad6d9558eac988f467..398bb20b66934cff90154c60af5f0d76aa4f64d9 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1,2339 +1,2339 @@ -/** - * @file lldrawpoolavatar.cpp - * @brief LLDrawPoolAvatar class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "lldrawpoolavatar.h" -#include "llskinningutil.h" -#include "llrender.h" - -#include "llvoavatar.h" -#include "m3math.h" -#include "llmatrix4a.h" - -#include "llagent.h" //for gAgent.needsRenderAvatar() -#include "lldrawable.h" -#include "lldrawpoolbump.h" -#include "llface.h" -#include "llmeshrepository.h" -#include "llsky.h" -#include "llviewercamera.h" -#include "llviewerregion.h" -#include "noise.h" -#include "pipeline.h" -#include "llviewershadermgr.h" -#include "llvovolume.h" -#include "llvolume.h" -#include "llappviewer.h" -#include "llrendersphere.h" -#include "llviewerpartsim.h" -#include "llviewercontrol.h" // for gSavedSettings -#include "llviewertexturelist.h" - -#include <glm/mat3x3.hpp> -#include <glm/mat4x4.hpp> -#include <glm/gtc/matrix_inverse.hpp> -#include <glm/gtc/type_ptr.hpp> - -static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; -static U32 sBufferUsage = GL_STREAM_DRAW_ARB; -static U32 sShaderLevel = 0; - -LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = nullptr; -BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; -BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; -S32 LLDrawPoolAvatar::sShadowPass = -1; -S32 LLDrawPoolAvatar::sDiffuseChannel = 0; -F32 LLDrawPoolAvatar::sMinimumAlpha = 0.2f; - -LLUUID gBlackSquareID; - -static bool is_deferred_render = false; -static bool is_post_deferred_render = false; - -extern BOOL gUseGLPick; - -F32 CLOTHING_GRAVITY_EFFECT = 0.7f; -F32 CLOTHING_ACCEL_FORCE_FACTOR = 0.2f; - -// Format for gAGPVertices -// vertex format for bumpmapping: -// vertices 12 -// pad 4 -// normals 12 -// pad 4 -// texcoords0 8 -// texcoords1 8 -// total 48 -// -// for no bumpmapping -// vertices 12 -// texcoords 8 -// normals 12 -// total 32 -// - -S32 AVATAR_OFFSET_POS = 0; -S32 AVATAR_OFFSET_NORMAL = 16; -S32 AVATAR_OFFSET_TEX0 = 32; -S32 AVATAR_OFFSET_TEX1 = 40; -S32 AVATAR_VERTEX_BYTES = 48; - -static BOOL sRenderingSkinned = FALSE; -S32 normal_channel = -1; -S32 specular_channel = -1; -S32 cube_channel = -1; - -static LLTrace::BlockTimerStatHandle FTM_SHADOW_AVATAR("Avatar Shadow"); - -LLDrawPoolAvatar::LLDrawPoolAvatar() : - LLFacePool(POOL_AVATAR) -{ -} - -LLDrawPoolAvatar::~LLDrawPoolAvatar() -{ - if (!isDead()) - { - LL_WARNS() << "Destroying avatar drawpool that still contains faces" << LL_ENDL; - } -} - -// virtual -BOOL LLDrawPoolAvatar::isDead() -{ - if (!LLFacePool::isDead()) - { - return FALSE; - } - - for (auto& face : mRiggedFace) - { - if (!face.empty()) - { - return FALSE; - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// instancePool() -//----------------------------------------------------------------------------- -LLDrawPool *LLDrawPoolAvatar::instancePool() -{ - return new LLDrawPoolAvatar(); -} - - -S32 LLDrawPoolAvatar::getVertexShaderLevel() const -{ - return (S32) LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); -} - -void LLDrawPoolAvatar::prerender() -{ - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); - - sShaderLevel = mVertexShaderLevel; - - if (sShaderLevel > 0) - { - sBufferUsage = GL_DYNAMIC_DRAW_ARB; - } - else - { - sBufferUsage = GL_STREAM_DRAW_ARB; - } - - if (!mDrawFace.empty()) - { - const LLFace *facep = mDrawFace[0]; - if (facep && facep->getDrawable()) - { - LLVOAvatar* avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); - updateRiggedVertexBuffers(avatarp); - } - } -} - -LLMatrix4& LLDrawPoolAvatar::getModelView() -{ - static LLMatrix4 ret; - - ret.initRows(LLVector4(gGLModelView+0), - LLVector4(gGLModelView+4), - LLVector4(gGLModelView+8), - LLVector4(gGLModelView+12)); - - return ret; -} - -//----------------------------------------------------------------------------- -// render() -//----------------------------------------------------------------------------- - - - -void LLDrawPoolAvatar::beginDeferredPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); - - sSkipTransparent = TRUE; - is_deferred_render = true; - - if (LLPipeline::sImpostorRender) - { //impostor pass does not have rigid or impostor rendering - pass += 2; - } - - switch (pass) - { - case 0: - beginDeferredImpostor(); - break; - case 1: - beginDeferredRigid(); - break; - case 2: - beginDeferredSkinned(); - break; - case 3: - beginDeferredRiggedSimple(); - break; - case 4: - beginDeferredRiggedBump(); - break; - default: - beginDeferredRiggedMaterial(pass-5); - break; - } -} - -void LLDrawPoolAvatar::endDeferredPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); - - sSkipTransparent = FALSE; - is_deferred_render = false; - - if (LLPipeline::sImpostorRender) - { - pass += 2; - } - - switch (pass) - { - case 0: - endDeferredImpostor(); - break; - case 1: - endDeferredRigid(); - break; - case 2: - endDeferredSkinned(); - break; - case 3: - endDeferredRiggedSimple(); - break; - case 4: - endDeferredRiggedBump(); - break; - default: - endDeferredRiggedMaterial(pass-5); - break; - } -} - -void LLDrawPoolAvatar::renderDeferred(S32 pass) -{ - render(pass); -} - -S32 LLDrawPoolAvatar::getNumPostDeferredPasses() -{ - return 10; -} - -void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) -{ - switch (pass) - { - case 0: - beginPostDeferredAlpha(); - break; - case 1: - beginRiggedFullbright(); - break; - case 2: - beginRiggedFullbrightShiny(); - break; - case 3: - beginDeferredRiggedAlpha(); - break; - case 4: - beginRiggedFullbrightAlpha(); - break; - case 9: - beginRiggedGlow(); - break; - default: - beginDeferredRiggedMaterialAlpha(pass-5); - break; - } -} - -void LLDrawPoolAvatar::beginPostDeferredAlpha() -{ - sSkipOpaque = TRUE; - sShaderLevel = mVertexShaderLevel; - sVertexProgram = &gDeferredAvatarAlphaProgram; - sRenderingSkinned = TRUE; - - gPipeline.bindDeferredShader(*sVertexProgram); - - sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); - - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); -} - -void LLDrawPoolAvatar::beginDeferredRiggedAlpha() -{ - sVertexProgram = &gDeferredSkinnedAlphaProgram; - gPipeline.bindDeferredShader(*sVertexProgram); - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - gPipeline.enableLightsDynamic(); -} - -void LLDrawPoolAvatar::beginDeferredRiggedMaterialAlpha(S32 pass) -{ - switch (pass) - { - case 0: pass = 1; break; - case 1: pass = 5; break; - case 2: pass = 9; break; - default: pass = 13; break; - } - - pass += LLMaterial::SHADER_COUNT; - - sVertexProgram = &gDeferredMaterialProgram[pass]; - - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &(gDeferredMaterialWaterProgram[pass]); - } - - gPipeline.bindDeferredShader(*sVertexProgram); - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); - specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); - gPipeline.enableLightsDynamic(); -} - -void LLDrawPoolAvatar::endDeferredRiggedAlpha() -{ - LLVertexBuffer::unbind(); - gPipeline.unbindDeferredShader(*sVertexProgram); - sDiffuseChannel = 0; - normal_channel = -1; - specular_channel = -1; - sVertexProgram = nullptr; -} - -void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) -{ - switch (pass) - { - case 0: - endPostDeferredAlpha(); - break; - case 1: - endRiggedFullbright(); - break; - case 2: - endRiggedFullbrightShiny(); - break; - case 3: - endDeferredRiggedAlpha(); - break; - case 4: - endRiggedFullbrightAlpha(); - break; - case 5: - endRiggedGlow(); - break; - default: - endDeferredRiggedAlpha(); - break; - } -} - -void LLDrawPoolAvatar::endPostDeferredAlpha() -{ - // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done - sRenderingSkinned = FALSE; - sSkipOpaque = FALSE; - - gPipeline.unbindDeferredShader(*sVertexProgram); - sDiffuseChannel = 0; - sShaderLevel = mVertexShaderLevel; -} - -void LLDrawPoolAvatar::renderPostDeferred(S32 pass) -{ - static const S32 actual_pass[] = - { //map post deferred pass numbers to what render() expects - 2, //skinned - 4, // rigged fullbright - 6, //rigged fullbright shiny - 7, //rigged alpha - 8, //rigged fullbright alpha - 9, //rigged material alpha 1 - 10,//rigged material alpha 2 - 11,//rigged material alpha 3 - 12,//rigged material alpha 4 - 13, //rigged glow - }; - - S32 p = actual_pass[pass]; - - if (LLPipeline::sImpostorRender) - { //HACK for impostors so actual pass ends up being proper pass - p -= 2; - } - - is_post_deferred_render = true; - render(p); - is_post_deferred_render = false; -} - - -S32 LLDrawPoolAvatar::getNumShadowPasses() -{ - // avatars opaque, avatar alpha, avatar alpha mask, alpha attachments, alpha mask attachments, opaque attachments... - return NUM_SHADOW_PASSES; -} - -void LLDrawPoolAvatar::beginShadowPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); - - if (pass == SHADOW_PASS_AVATAR_OPAQUE) - { - sVertexProgram = &gDeferredAvatarShadowProgram; - - if ((sShaderLevel > 0)) // for hardware blending - { - sRenderingSkinned = TRUE; - sVertexProgram->bind(); - } - - gGL.diffuseColor4f(1,1,1,1); - } - else if (pass == SHADOW_PASS_AVATAR_ALPHA_BLEND) - { - sVertexProgram = &gDeferredAvatarAlphaShadowProgram; - - // bind diffuse tex so we can reference the alpha channel... - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - - if ((sShaderLevel > 0)) // for hardware blending - { - sRenderingSkinned = TRUE; - sVertexProgram->bind(); - } - - gGL.diffuseColor4f(1,1,1,1); - } - else if (pass == SHADOW_PASS_AVATAR_ALPHA_MASK) - { - sVertexProgram = &gDeferredAvatarAlphaMaskShadowProgram; - - // bind diffuse tex so we can reference the alpha channel... - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - - if ((sShaderLevel > 0)) // for hardware blending - { - sRenderingSkinned = TRUE; - sVertexProgram->bind(); - } - - gGL.diffuseColor4f(1,1,1,1); - } - else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND) - { - sVertexProgram = &gDeferredAttachmentAlphaShadowProgram; - - // bind diffuse tex so we can reference the alpha channel... - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - - if ((sShaderLevel > 0)) // for hardware blending - { - sRenderingSkinned = TRUE; - sVertexProgram->bind(); - } - - gGL.diffuseColor4f(1,1,1,1); - } - else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK) - { - sVertexProgram = &gDeferredAttachmentAlphaMaskShadowProgram; - - // bind diffuse tex so we can reference the alpha channel... - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - - if ((sShaderLevel > 0)) // for hardware blending - { - sRenderingSkinned = TRUE; - sVertexProgram->bind(); - } - - gGL.diffuseColor4f(1,1,1,1); - } - else // SHADOW_PASS_ATTACHMENT_OPAQUE - { - sVertexProgram = &gDeferredAttachmentShadowProgram; - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sVertexProgram->bind(); - } -} - -void LLDrawPoolAvatar::endShadowPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); - - if (pass == SHADOW_PASS_ATTACHMENT_OPAQUE) - { - LLVertexBuffer::unbind(); - } - - if (sShaderLevel > 0) - { - sVertexProgram->unbind(); - } - sVertexProgram = nullptr; - sRenderingSkinned = FALSE; - LLDrawPoolAvatar::sShadowPass = -1; -} - -void LLDrawPoolAvatar::renderShadow(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); - - if (mDrawFace.empty()) - { - return; - } - - const LLFace *facep = mDrawFace[0]; - if (!facep->getDrawable()) - { - return; - } - LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); - - if (avatarp->isDead() || avatarp->isUIAvatar() || avatarp->mDrawable.isNull()) - { - return; - } - - BOOL impostor = avatarp->isImpostor(); - if (impostor) - { - return; - } - - LLDrawPoolAvatar::sShadowPass = pass; - - if (pass == SHADOW_PASS_AVATAR_OPAQUE) - { - LLDrawPoolAvatar::sSkipTransparent = true; - avatarp->renderSkinned(); - LLDrawPoolAvatar::sSkipTransparent = false; - } - else if (pass == SHADOW_PASS_AVATAR_ALPHA_BLEND) - { - LLDrawPoolAvatar::sSkipOpaque = true; - avatarp->renderSkinned(); - LLDrawPoolAvatar::sSkipOpaque = false; - } - else if (pass == SHADOW_PASS_AVATAR_ALPHA_MASK) - { - LLDrawPoolAvatar::sSkipOpaque = true; - avatarp->renderSkinned(); - LLDrawPoolAvatar::sSkipOpaque = false; - } - else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND) // rigged alpha - { - LLDrawPoolAvatar::sSkipOpaque = true; - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA); - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE); - renderRigged(avatarp, RIGGED_ALPHA); - renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA); - renderRigged(avatarp, RIGGED_GLOW); - renderRigged(avatarp, RIGGED_SPECMAP_BLEND); - renderRigged(avatarp, RIGGED_NORMMAP_BLEND); - renderRigged(avatarp, RIGGED_NORMSPEC_BLEND); - LLDrawPoolAvatar::sSkipOpaque = false; - } - else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK) // rigged alpha mask - { - LLDrawPoolAvatar::sSkipOpaque = true; - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK); - renderRigged(avatarp, RIGGED_NORMMAP_MASK); - renderRigged(avatarp, RIGGED_SPECMAP_MASK); - renderRigged(avatarp, RIGGED_NORMSPEC_MASK); - renderRigged(avatarp, RIGGED_GLOW); - LLDrawPoolAvatar::sSkipOpaque = false; - } - else // rigged opaque (SHADOW_PASS_ATTACHMENT_OPAQUE - { - LLDrawPoolAvatar::sSkipTransparent = true; - renderRigged(avatarp, RIGGED_MATERIAL); - renderRigged(avatarp, RIGGED_SPECMAP); - renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE); - renderRigged(avatarp, RIGGED_NORMMAP); - renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); - renderRigged(avatarp, RIGGED_NORMSPEC); - renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE); - renderRigged(avatarp, RIGGED_SIMPLE); - renderRigged(avatarp, RIGGED_FULLBRIGHT); - renderRigged(avatarp, RIGGED_SHINY); - renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY); - renderRigged(avatarp, RIGGED_GLOW); - renderRigged(avatarp, RIGGED_DEFERRED_BUMP); - renderRigged(avatarp, RIGGED_DEFERRED_SIMPLE); - LLDrawPoolAvatar::sSkipTransparent = false; - } -} - -S32 LLDrawPoolAvatar::getNumPasses() -{ - if (LLPipeline::sImpostorRender) - { - return 8; - } - else - { - return 10; - } -} - - -S32 LLDrawPoolAvatar::getNumDeferredPasses() -{ - if (LLPipeline::sImpostorRender) - { - return 19; - } - else - { - return 21; - } -} - - -void LLDrawPoolAvatar::render(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); - if (LLPipeline::sImpostorRender) - { - renderAvatars(nullptr, pass+2); - return; - } - - renderAvatars(nullptr, pass); // render all avatars -} - -void LLDrawPoolAvatar::beginRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); - //reset vertex buffer mappings - LLVertexBuffer::unbind(); - - if (LLPipeline::sImpostorRender) - { //impostor render does not have impostors or rigid rendering - pass += 2; - } - - switch (pass) - { - case 0: - beginImpostor(); - break; - case 1: - beginRigid(); - break; - case 2: - beginSkinned(); - break; - case 3: - beginRiggedSimple(); - break; - case 4: - beginRiggedFullbright(); - break; - case 5: - beginRiggedShinySimple(); - break; - case 6: - beginRiggedFullbrightShiny(); - break; - case 7: - beginRiggedAlpha(); - break; - case 8: - beginRiggedFullbrightAlpha(); - break; - case 9: - beginRiggedGlow(); - break; - } - - if (pass == 0) - { //make sure no stale colors are left over from a previous render - gGL.diffuseColor4f(1,1,1,1); - } -} - -void LLDrawPoolAvatar::endRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); - - if (LLPipeline::sImpostorRender) - { - pass += 2; - } - - switch (pass) - { - case 0: - endImpostor(); - break; - case 1: - endRigid(); - break; - case 2: - endSkinned(); - break; - case 3: - endRiggedSimple(); - break; - case 4: - endRiggedFullbright(); - break; - case 5: - endRiggedShinySimple(); - break; - case 6: - endRiggedFullbrightShiny(); - break; - case 7: - endRiggedAlpha(); - break; - case 8: - endRiggedFullbrightAlpha(); - break; - case 9: - endRiggedGlow(); - break; - } -} - -void LLDrawPoolAvatar::beginImpostor() -{ - if (!LLPipeline::sReflectionRender) - { - LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); - LLVOAvatar::sNumVisibleAvatars = 0; - } - - if (LLGLSLShader::sNoFixedFunction) - { - gImpostorProgram.bind(); - gImpostorProgram.setMinimumAlpha(0.01f); - } - - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - sDiffuseChannel = 0; -} - -void LLDrawPoolAvatar::endImpostor() -{ - if (LLGLSLShader::sNoFixedFunction) - { - gImpostorProgram.unbind(); - } - gPipeline.enableLightsDynamic(); -} - -void LLDrawPoolAvatar::beginRigid() -{ - if (gPipeline.canUseVertexShaders()) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectAlphaMaskNoColorWaterProgram; - } - else - { - sVertexProgram = &gObjectAlphaMaskNoColorProgram; - } - - if (sVertexProgram != nullptr) - { //eyeballs render with the specular shader - sVertexProgram->bind(); - sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); - } - } - else - { - sVertexProgram = nullptr; - } -} - -void LLDrawPoolAvatar::endRigid() -{ - sShaderLevel = mVertexShaderLevel; - if (sVertexProgram != nullptr) - { - sVertexProgram->unbind(); - } -} - -void LLDrawPoolAvatar::beginDeferredImpostor() -{ - if (!LLPipeline::sReflectionRender) - { - LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); - LLVOAvatar::sNumVisibleAvatars = 0; - } - - sVertexProgram = &gDeferredImpostorProgram; - specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sVertexProgram->bind(); - sVertexProgram->setMinimumAlpha(0.01f); -} - -void LLDrawPoolAvatar::endDeferredImpostor() -{ - sShaderLevel = mVertexShaderLevel; - sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); - sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); - sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - gPipeline.unbindDeferredShader(*sVertexProgram); - sVertexProgram = nullptr; - sDiffuseChannel = 0; -} - -void LLDrawPoolAvatar::beginDeferredRigid() -{ - sVertexProgram = &gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sVertexProgram->bind(); - sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); -} - -void LLDrawPoolAvatar::endDeferredRigid() -{ - sShaderLevel = mVertexShaderLevel; - sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sVertexProgram->unbind(); - gGL.getTexUnit(0)->activate(); -} - - -void LLDrawPoolAvatar::beginSkinned() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gAvatarWaterProgram; - sShaderLevel = llmin((U32) 1, sShaderLevel); - } - else - { - sVertexProgram = &gAvatarProgram; - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectAlphaMaskNoColorWaterProgram; - } - else - { - sVertexProgram = &gObjectAlphaMaskNoColorProgram; - } - } - - if (sShaderLevel > 0) // for hardware blending - { - sRenderingSkinned = TRUE; - - sVertexProgram->bind(); - sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); - gGL.getTexUnit(0)->activate(); - } - else - { - if(gPipeline.canUseVertexShaders()) - { - // software skinning, use a basic shader for windlight. - // TODO: find a better fallback method for software skinning. - sVertexProgram->bind(); - } - } - - if (LLGLSLShader::sNoFixedFunction) - { - sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); - } -} - -void LLDrawPoolAvatar::endSkinned() -{ - // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done - if (sShaderLevel > 0) - { - sRenderingSkinned = FALSE; - sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); - gGL.getTexUnit(0)->activate(); - sVertexProgram->unbind(); - sShaderLevel = mVertexShaderLevel; - } - else - { - if(gPipeline.canUseVertexShaders()) - { - // software skinning, use a basic shader for windlight. - // TODO: find a better fallback method for software skinning. - sVertexProgram->unbind(); - } - } - - gGL.getTexUnit(0)->activate(); -} - -void LLDrawPoolAvatar::beginRiggedSimple() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectSimpleWaterProgram; - } - else - { - sVertexProgram = &gSkinnedObjectSimpleProgram; - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectSimpleNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectSimpleNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sDiffuseChannel = 0; - sVertexProgram->bind(); - } -} - -void LLDrawPoolAvatar::endRiggedSimple() -{ - LLVertexBuffer::unbind(); - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sVertexProgram->unbind(); - sVertexProgram = nullptr; - } -} - -void LLDrawPoolAvatar::beginRiggedAlpha() -{ - beginRiggedSimple(); -} - -void LLDrawPoolAvatar::endRiggedAlpha() -{ - endRiggedSimple(); -} - - -void LLDrawPoolAvatar::beginRiggedFullbrightAlpha() -{ - beginRiggedFullbright(); -} - -void LLDrawPoolAvatar::endRiggedFullbrightAlpha() -{ - endRiggedFullbright(); -} - -void LLDrawPoolAvatar::beginRiggedGlow() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectEmissiveWaterProgram; - } - else - { - sVertexProgram = &gSkinnedObjectEmissiveProgram; - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectEmissiveNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectEmissiveNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sDiffuseChannel = 0; - sVertexProgram->bind(); - - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, LLPipeline::sRenderDeferred ? 2.2f : 1.1f); - } -} - -void LLDrawPoolAvatar::endRiggedGlow() -{ - endRiggedFullbright(); -} - -void LLDrawPoolAvatar::beginRiggedFullbright() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; - } - else - { - if (LLPipeline::sRenderDeferred) - { - sVertexProgram = &gDeferredSkinnedFullbrightProgram; - } - else - { - sVertexProgram = &gSkinnedObjectFullbrightProgram; - } - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectFullbrightNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectFullbrightNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sDiffuseChannel = 0; - sVertexProgram->bind(); - - if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - } - else - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - } - } -} - -void LLDrawPoolAvatar::endRiggedFullbright() -{ - LLVertexBuffer::unbind(); - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sVertexProgram->unbind(); - sVertexProgram = nullptr; - } -} - -void LLDrawPoolAvatar::beginRiggedShinySimple() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectShinySimpleWaterProgram; - } - else - { - sVertexProgram = &gSkinnedObjectShinySimpleProgram; - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectShinyNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectShinyNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); - } -} - -void LLDrawPoolAvatar::endRiggedShinySimple() -{ - LLVertexBuffer::unbind(); - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); - sVertexProgram->unbind(); - sVertexProgram = nullptr; - } -} - -void LLDrawPoolAvatar::beginRiggedFullbrightShiny() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectFullbrightShinyWaterProgram; - } - else - { - if (LLPipeline::sRenderDeferred) - { - sVertexProgram = &gDeferredSkinnedFullbrightShinyProgram; - } - else - { - sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; - } - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectFullbrightShinyNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectFullbrightShinyNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); - - if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - } - else - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - } - } -} - -void LLDrawPoolAvatar::endRiggedFullbrightShiny() -{ - LLVertexBuffer::unbind(); - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); - sVertexProgram->unbind(); - sVertexProgram = nullptr; - } -} - - -void LLDrawPoolAvatar::beginDeferredRiggedSimple() -{ - sVertexProgram = &gDeferredSkinnedDiffuseProgram; - sDiffuseChannel = 0; - sVertexProgram->bind(); -} - -void LLDrawPoolAvatar::endDeferredRiggedSimple() -{ - LLVertexBuffer::unbind(); - sVertexProgram->unbind(); - sVertexProgram = nullptr; -} - -void LLDrawPoolAvatar::beginDeferredRiggedBump() -{ - sVertexProgram = &gDeferredSkinnedBumpProgram; - sVertexProgram->bind(); - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); -} - -void LLDrawPoolAvatar::endDeferredRiggedBump() -{ - LLVertexBuffer::unbind(); - sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); - sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sVertexProgram->unbind(); - normal_channel = -1; - sDiffuseChannel = 0; - sVertexProgram = nullptr; -} - -void LLDrawPoolAvatar::beginDeferredRiggedMaterial(S32 pass) -{ - if (pass == 1 || - pass == 5 || - pass == 9 || - pass == 13) - { //skip alpha passes - return; - } - sVertexProgram = &gDeferredMaterialProgram[pass+LLMaterial::SHADER_COUNT]; - - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &(gDeferredMaterialWaterProgram[pass+LLMaterial::SHADER_COUNT]); - } - - sVertexProgram->bind(); - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); - specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); -} - -void LLDrawPoolAvatar::endDeferredRiggedMaterial(S32 pass) -{ - if (pass == 1 || - pass == 5 || - pass == 9 || - pass == 13) - { - return; - } - - LLVertexBuffer::unbind(); - sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); - sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); - sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sVertexProgram->unbind(); - normal_channel = -1; - sDiffuseChannel = 0; - sVertexProgram = nullptr; -} - -void LLDrawPoolAvatar::beginDeferredSkinned() -{ - sShaderLevel = mVertexShaderLevel; - sVertexProgram = &gDeferredAvatarProgram; - sRenderingSkinned = TRUE; - - sVertexProgram->bind(); - sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); - - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - gGL.getTexUnit(0)->activate(); -} - -void LLDrawPoolAvatar::endDeferredSkinned() -{ - // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done - sRenderingSkinned = FALSE; - sVertexProgram->unbind(); - - sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - - sShaderLevel = mVertexShaderLevel; - - gGL.getTexUnit(0)->activate(); -} - -static LLTrace::BlockTimerStatHandle FTM_RENDER_AVATARS("renderAvatars"); - - -void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_AVATARS); - - if (pass == -1) - { - for (S32 i = 1; i < getNumPasses(); i++) - { //skip foot shadows - prerender(); - beginRenderPass(i); - renderAvatars(single_avatar, i); - endRenderPass(i); - } - - return; - } - - if (mDrawFace.empty() && !single_avatar) - { - return; - } - - LLVOAvatar *avatarp; - - if (single_avatar) - { - avatarp = single_avatar; - } - else - { - const LLFace *facep = mDrawFace[0]; - if (!facep->getDrawable()) - { - return; - } - avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); - } - - if (avatarp->isDead() || avatarp->mDrawable.isNull()) - { - return; - } - - if (!single_avatar && !avatarp->isFullyLoaded() ) - { - if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0)) - { - // debug code to draw a sphere in place of avatar - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); - gGL.setColorMask(true, true); - LLVector3 pos = avatarp->getPositionAgent(); - gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f); - - gGL.pushMatrix(); - gGL.translatef((F32)(pos.mV[VX]), - (F32)(pos.mV[VY]), - (F32)(pos.mV[VZ])); - gGL.scalef(0.15f, 0.15f, 0.3f); - - gSphere.renderGGL(); - - gGL.popMatrix(); - gGL.setColorMask(true, false); - } - // don't render please - return; - } - - BOOL impostor = avatarp->isImpostor() && !single_avatar; - - if (impostor && pass != 0) - { //don't draw anything but the impostor for impostored avatars - return; - } - - if (pass == 0 && !impostor && LLPipeline::sUnderWaterRender) - { //don't draw foot shadows under water - return; - } - - if (pass == 0) - { - if (!LLPipeline::sReflectionRender) - { - LLVOAvatar::sNumVisibleAvatars++; - } - - if (impostor) - { - if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete()) - { - if (normal_channel > -1) - { - avatarp->mImpostor.bindTexture(2, normal_channel); - } - if (specular_channel > -1) - { - avatarp->mImpostor.bindTexture(1, specular_channel); - } - } - avatarp->renderImpostor(avatarp->getMutedAVColor(), sDiffuseChannel); - } - return; - } - - if (pass == 1) - { - // render rigid meshes (eyeballs) first - avatarp->renderRigid(); - return; - } - - if (pass == 3) - { - if (is_deferred_render) - { - renderDeferredRiggedSimple(avatarp); - } - else - { - renderRiggedSimple(avatarp); - - if (LLPipeline::sRenderDeferred) - { //render "simple" materials - renderRigged(avatarp, RIGGED_MATERIAL); - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK); - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE); - renderRigged(avatarp, RIGGED_NORMMAP); - renderRigged(avatarp, RIGGED_NORMMAP_MASK); - renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); - renderRigged(avatarp, RIGGED_SPECMAP); - renderRigged(avatarp, RIGGED_SPECMAP_MASK); - renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE); - renderRigged(avatarp, RIGGED_NORMSPEC); - renderRigged(avatarp, RIGGED_NORMSPEC_MASK); - renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE); - } - } - return; - } - - if (pass == 4) - { - if (is_deferred_render) - { - renderDeferredRiggedBump(avatarp); - } - else - { - renderRiggedFullbright(avatarp); - } - - return; - } - - if (is_deferred_render && pass >= 5 && pass <= 21) - { - S32 p = pass-5; - - if (p != 1 && - p != 5 && - p != 9 && - p != 13) - { - renderDeferredRiggedMaterial(avatarp, p); - } - return; - } - - - - - if (pass == 5) - { - renderRiggedShinySimple(avatarp); - - return; - } - - if (pass == 6) - { - renderRiggedFullbrightShiny(avatarp); - return; - } - - if (pass >= 7 && pass < 13) - { - if (pass == 7) - { - renderRiggedAlpha(avatarp); - - if (LLPipeline::sRenderDeferred && !is_post_deferred_render) - { //render transparent materials under water - LLGLEnable blend(GL_BLEND); - - gGL.setColorMask(true, true); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA, - LLRender::BF_ZERO, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA); - renderRigged(avatarp, RIGGED_SPECMAP_BLEND); - renderRigged(avatarp, RIGGED_NORMMAP_BLEND); - renderRigged(avatarp, RIGGED_NORMSPEC_BLEND); - gGL.setSceneBlendType(LLRender::BT_ALPHA); // <alchemy/> - gGL.setColorMask(true, false); - } - return; - } - - if (pass == 8) - { - renderRiggedFullbrightAlpha(avatarp); - return; - } - - if (LLPipeline::sRenderDeferred && is_post_deferred_render) - { - S32 p = 0; - switch (pass) - { - case 9: p = 1; break; - case 10: p = 5; break; - case 11: p = 9; break; - case 12: p = 13; break; - } - - { - LLGLEnable blend(GL_BLEND); - renderDeferredRiggedMaterial(avatarp, p); - } - return; - } - else if (pass == 9) - { - renderRiggedGlow(avatarp); - return; - } - } - - if (pass == 13) - { - renderRiggedGlow(avatarp); - - return; - } - - if ((sShaderLevel >= SHADER_LEVEL_CLOTH)) - { - LLMatrix4 rot_mat; - LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat); - static const LLMatrix4 cfr(OGL_TO_CFR_ROTATION); - rot_mat *= cfr; - - LLVector4 wind; - wind.setVec(avatarp->mWindVec); - wind.mV[VW] = 0; - wind = wind * rot_mat; - wind.mV[VW] = avatarp->mWindVec.mV[VW]; - - sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV); - F32 phase = -1.f * (avatarp->mRipplePhase); - - F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f); - LLVector4 sin_params(freq, freq, freq, phase); - sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV); - - LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f); - gravity = gravity * rot_mat; - sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV); - } - - if( !single_avatar || (avatarp == single_avatar) ) - { - avatarp->renderSkinned(); - } -} - -void LLDrawPoolAvatar::getRiggedGeometry( - LLFace* face, - LLPointer<LLVertexBuffer>& buffer, - U32 data_mask, - const LLMeshSkinInfo* skin, - LLVolume* volume, - const LLVolumeFace& vol_face) -{ - face->setGeomIndex(0); - face->setIndicesIndex(0); - - //rigged faces do not batch textures - face->setTextureIndex(255); - - if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable()) - { - // make a new buffer - if (sShaderLevel > 0) - { - buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB); - } - else - { - buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB); - } - - if (!buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true)) - { - LL_WARNS("LLDrawPoolAvatar") << "Failed to allocate Vertex Buffer to " - << vol_face.mNumVertices << " vertices and " - << vol_face.mNumIndices << " indices" << LL_ENDL; - // allocate dummy triangle - buffer->allocateBuffer(1, 3, true); - memset((U8*)buffer->getMappedData(), 0, buffer->getSize()); - memset((U8*)buffer->getMappedIndices(), 0, buffer->getIndicesSize()); - } - } - else - { - //resize existing buffer - if(!buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices)) - { - LL_WARNS("LLDrawPoolAvatar") << "Failed to resize Vertex Buffer to " - << vol_face.mNumVertices << " vertices and " - << vol_face.mNumIndices << " indices" << LL_ENDL; - // allocate dummy triangle - buffer->resizeBuffer(1, 3); - memset((U8*)buffer->getMappedData(), 0, buffer->getSize()); - memset((U8*)buffer->getMappedIndices(), 0, buffer->getIndicesSize()); - } - } - - face->setSize(buffer->getNumVerts(), buffer->getNumIndices()); - face->setVertexBuffer(buffer); - - U16 offset = 0; - - LLMatrix4a mat_vert_inv = skin->mBindShapeMatrix; - mat_vert_inv.invert(); - mat_vert_inv.transpose(); - - const F32* m = mat_vert_inv.getF32ptr(); - F32 mat3[] = - { m[0], m[1], m[2], - m[4], m[5], m[6], - m[8], m[9], m[10] }; - - LLMatrix3 mat_normal(mat3); - - //let getGeometryVolume know if alpha should override shiny - U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture()); - - if (type == LLDrawPool::POOL_ALPHA) - { - face->setPoolType(LLDrawPool::POOL_ALPHA); - } - else - { - face->setPoolType(LLDrawPool::POOL_AVATAR); - } - - //LL_INFOS() << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << LL_ENDL; - - // Let getGeometryVolume know if a texture matrix is in play - if (face->mTextureMatrix) - { - face->setState(LLFace::TEXTURE_ANIM); - } - else - { - face->clearState(LLFace::TEXTURE_ANIM); - } - LLMatrix4 mat_vert(skin->mBindShapeMatrix.getF32ptr()); - face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); - - buffer->flush(); -} - -void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( - LLVOAvatar* avatar, - LLFace* face, - const LLMeshSkinInfo* skin, - LLVolume* volume, - const LLVolumeFace& vol_face) -{ - LLVector4a* weights = vol_face.mWeights; - if (!weights) - { - return; - } - // FIXME ugly const cast - LLSkinningUtil::scrubInvalidJoints(avatar, const_cast<LLMeshSkinInfo*>(skin)); - - LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer(); - LLDrawable* drawable = face->getDrawable(); - - if (drawable->getVOVolume() && drawable->getVOVolume()->isNoLOD()) - { - return; - } - - U32 data_mask = face->getRiggedVertexBufferDataMask(); - - if (!vol_face.mWeightsScrubbed) - { - LLSkinningUtil::scrubSkinWeights(weights, vol_face.mNumVertices, skin); - vol_face.mWeightsScrubbed = TRUE; - } - - if (buffer.isNull() || - buffer->getTypeMask() != data_mask || - buffer->getNumVerts() != vol_face.mNumVertices || - buffer->getNumIndices() != vol_face.mNumIndices || - (drawable && drawable->isState(LLDrawable::REBUILD_ALL))) - { - if (drawable && drawable->isState(LLDrawable::REBUILD_ALL)) - { //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* facep = drawable->getFace(i); - U32 face_data_mask = facep->getRiggedVertexBufferDataMask(); - if (face_data_mask) - { - LLPointer<LLVertexBuffer> cur_buffer = facep->getVertexBuffer(); - const LLVolumeFace& cur_vol_face = volume->getVolumeFace(i); - getRiggedGeometry(facep, cur_buffer, face_data_mask, skin, volume, cur_vol_face); - } - } - drawable->clearState(LLDrawable::REBUILD_ALL); - - buffer = face->getVertexBuffer(); - } - else - { //just rebuild this face - getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face); - } - } - - if (buffer.isNull() || - buffer->getNumVerts() != vol_face.mNumVertices || - buffer->getNumIndices() != vol_face.mNumIndices) - { - // Allocation failed - return; - } - - if (!buffer.isNull() && - sShaderLevel <= 0 && - face->mLastSkinTime < avatar->getLastSkinTime()) - { - //perform software vertex skinning for this face - LLStrider<LLVector3> position; - LLStrider<LLVector3> normal; - - bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - buffer->getVertexStrider(position); - - if (has_normal) - { - buffer->getNormalStrider(normal); - } - - LLVector4a* pos = (LLVector4a*) position.get(); - - LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; - - //build matrix palette - LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = LLSkinningUtil::getMeshJointCount(skin); - LLSkinningUtil::initSkinningMatrixPalette(mat, count, skin, avatar); - LLSkinningUtil::checkSkinWeights(weights, buffer->getNumVerts(), skin); - - const U32 max_joints = LLSkinningUtil::getMaxJointCount(); - for (S32 j = 0; j < buffer->getNumVerts(); ++j) - { - LLMatrix4a final_mat; - LLSkinningUtil::getPerVertexSkinMatrix(weights[j], mat, false, final_mat, max_joints); - - const LLVector4a& v = vol_face.mPositions[j]; - - LLVector4a dst; - skin->mBindShapeMatrix.affineTransform(v, dst); - final_mat.affineTransform(dst, dst); - pos[j] = dst; - - if (norm) - { - const LLVector4a& n = vol_face.mNormals[j]; - skin->mBindShapeMatrix.rotate(n, dst); - final_mat.rotate(dst, dst); - dst.normalize3fast(); - norm[j] = dst; - } - } - } -} - -void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) -{ - if (!avatar->shouldRenderRigged()) - { - return; - } - - stop_glerror(); - - for (LLFace* face : mRiggedFace[type]) - { - S32 offset = face->getIndicesStart(); - U32 count = face->getIndicesCount(); - - U16 start = face->getGeomStart(); - U16 end = start + face->getGeomCount()-1; - - LLDrawable* drawable = face->getDrawable(); - if (!drawable) - { - continue; - } - - LLVOVolume* vobj = drawable->getVOVolume(); - - if (!vobj) - { - continue; - } - - LLVolume* volume = vobj->getVolume(); - S32 te = face->getTEOffset(); - - if (!volume || volume->getNumVolumeFaces() <= te || !volume->isMeshAssetLoaded()) - { - continue; - } - - const LLMeshSkinInfo* skin = vobj->getSkinInfo(); - if (!skin) - { - continue; - } - - //stop_glerror(); - - //const LLVolumeFace& vol_face = volume->getVolumeFace(te); - //updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); - - //stop_glerror(); - - U32 data_mask = LLFace::getRiggedDataMask(type); - - LLVertexBuffer* buff = face->getVertexBuffer(); - - const LLTextureEntry* tex_entry = face->getTextureEntry(); - LLMaterial* mat = tex_entry ? tex_entry->getMaterialParams().get() : nullptr; - - if (LLDrawPoolAvatar::sShadowPass >= 0) - { - bool is_alpha_blend = false; - bool is_alpha_mask = false; - - LLViewerTexture* tex = face->getTexture(LLRender::DIFFUSE_MAP); - if (tex) - { - if (tex->getIsAlphaMask(-1.f, -1.f)) - { - is_alpha_mask = true; - } - } - - if (tex) - { - LLGLenum image_format = tex->getPrimaryFormat(); - if (!is_alpha_mask && (image_format == GL_RGBA || image_format == GL_ALPHA)) - { - is_alpha_blend = true; - } - } - - if (tex_entry) - { - if (tex_entry->getAlpha() <= 0.99f) - { - is_alpha_blend = true; - } - } - - if (mat) - { - switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaMode())) - { - case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: - { - is_alpha_mask = true; - is_alpha_blend = false; - } - break; - - case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: - { - is_alpha_blend = true; - is_alpha_mask = false; - } - break; - - case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: - case LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT: - case LLMaterial::DIFFUSE_ALPHA_MODE_NONE: - default: - is_alpha_blend = false; - is_alpha_mask = false; - break; - } - } - - // if this is alpha mask content and we're doing opaques or a non-alpha-mask shadow pass... - if (is_alpha_mask && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_MASK)) - { - return; - } - - // if this is alpha blend content and we're doing opaques or a non-alpha-blend shadow pass... - if (is_alpha_blend && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_BLEND)) - { - return; - } - - // if this is opaque content and we're skipping opaques... - if (!is_alpha_mask && !is_alpha_blend && LLDrawPoolAvatar::sSkipOpaque) - { - return; - } - } - - if (buff) - { - if (sShaderLevel > 0) - { - auto& mesh_cache = avatar->getRiggedMatrixCache(); - const auto& mesh_id = skin->mMeshID; - const auto& rigged_matrix_data_iter = mesh_cache.find(mesh_id); - if (rigged_matrix_data_iter != mesh_cache.cend() && (!avatar->isSelf() || !avatar->isEditingAppearance())) - { - LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, - rigged_matrix_data_iter->second.first, - FALSE, - (GLfloat*)rigged_matrix_data_iter->second.second.data()); - - stop_glerror(); - } - else - { - // upload matrix palette to shader - LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = LLSkinningUtil::getMeshJointCount(skin); - LLSkinningUtil::initSkinningMatrixPalette(mat, count, skin, avatar); - - stop_glerror(); - - std::vector<F32> mp; - mp.reserve(count * 12); - - for (U32 i = 0; i < count; ++i) - { - F32* m = (F32*) mat[i].getF32ptr(); - - U32 idx = i * 12; - - mp[idx + 0] = m[0]; - mp[idx + 1] = m[1]; - mp[idx + 2] = m[2]; - mp[idx + 3] = m[12]; - - mp[idx + 4] = m[4]; - mp[idx + 5] = m[5]; - mp[idx + 6] = m[6]; - mp[idx + 7] = m[13]; - - mp[idx + 8] = m[8]; - mp[idx + 9] = m[9]; - mp[idx + 10] = m[10]; - mp[idx + 11] = m[14]; - } - LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, - count, - FALSE, - (GLfloat*) mp.data()); - mesh_cache.emplace(mesh_id, std::make_pair(count, std::move(mp))); - stop_glerror(); - } - } - else - { - data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; - } - - /*if (glow) - { - gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow()); - }*/ - - if (mat) - { - //order is important here LLRender::DIFFUSE_MAP should be last, because it changes - //(gGL).mCurrTextureUnitIndex - LLViewerTexture* specular = nullptr; - if (LLPipeline::sImpostorRender && avatar->isVisuallyMuted()) - { - specular = LLViewerTextureManager::findFetchedTexture(gBlackSquareID, TEX_LIST_STANDARD); - } - else - { - specular = face->getViewerObject()->getTESpecularMap(face->getTEOffset()); - } - - gGL.getTexUnit(specular_channel)->bind(specular); - gGL.getTexUnit(normal_channel)->bind(face->getViewerObject()->getTENormalMap(face->getTEOffset())); - gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(), false, true); - - static const LLColor4 alpha[4] = - { - {0.00f,0.00f,0.00f,0.00f}, - {0.25f,0.25f,0.25f,0.25f}, - {0.50f,0.50f,0.50f,0.50f}, - {0.75f,0.75f,0.75f,0.75f}, - }; - - LLColor4 specColor = alpha[tex_entry->getShiny() & TEM_SHINY_MASK]; - F32 env = specColor.mV[0]; - - if (!mat->getSpecularID().isNull()) - { - const auto& spec_light_col = mat->getSpecularLightColor(); - specColor.mV[0] = spec_light_col.mV[0]; - specColor.mV[1] = spec_light_col.mV[1]; - specColor.mV[2] = spec_light_col.mV[2]; - specColor.mV[3] = mat->getSpecularLightExponent(); - env = mat->getEnvironmentIntensity(); - } - - BOOL fullbright = tex_entry->getFullbright(); - - sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f); - sVertexProgram->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specColor.mV); - sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env); - - if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()); - } - else - { - sVertexProgram->setMinimumAlpha(0.f); - } - - for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) - { - LLViewerTexture* tex = face->getTexture(i); - if (tex) - { - tex->addTextureStats(avatar->getPixelArea()); - } - } - } - else - { - gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); - sVertexProgram->setMinimumAlpha(0.f); - if (normal_channel > -1) - { - LLDrawPoolBump::bindBumpMap(face, normal_channel); - } - } - - if (face->mTextureMatrix && vobj->mTexAnimMode) - { - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix); - buff->setBuffer(data_mask); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } - else - { - buff->setBuffer(data_mask); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); - } - - gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES); - } - } -} - -void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_DEFERRED_SIMPLE); -} - -void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_DEFERRED_BUMP); -} - -void LLDrawPoolAvatar::renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass) -{ - renderRigged(avatar, pass); -} - -static LLTrace::BlockTimerStatHandle FTM_RIGGED_VBO("Rigged VBO"); - -void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) -{ - LL_RECORD_BLOCK_TIME(FTM_RIGGED_VBO); - - //update rigged vertex buffers - for (auto& type : mRiggedFace) - { - for (LLFace* face : type) - { - LLDrawable* drawable = face->getDrawable(); - if (!drawable) - { - continue; - } - - LLVOVolume* vobj = drawable->getVOVolume(); - - if (!vobj || vobj->isNoLOD()) - { - continue; - } - - LLVolume* volume = vobj->getVolume(); - S32 te = face->getTEOffset(); - - if (!volume || volume->getNumVolumeFaces() <= te) - { - continue; - } - - const LLMeshSkinInfo* skin = vobj->getSkinInfo(); - if (!skin) - { - continue; - } - - stop_glerror(); - - const LLVolumeFace& vol_face = volume->getVolumeFace(te); - updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); - } - } -} - -void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_SIMPLE); -} - -void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_FULLBRIGHT); -} - - -void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_SHINY); -} - -void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY); -} - -void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) -{ - if (!mRiggedFace[RIGGED_ALPHA].empty()) - { - LLGLEnable blend(GL_BLEND); - - gGL.setColorMask(true, true); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA, - LLRender::BF_ZERO, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - - renderRigged(avatar, RIGGED_ALPHA); - gGL.setSceneBlendType(LLRender::BT_ALPHA); // <alchemy/> - gGL.setColorMask(true, false); - } -} - -void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) -{ - if (!mRiggedFace[RIGGED_FULLBRIGHT_ALPHA].empty()) - { - LLGLEnable blend(GL_BLEND); - - gGL.setColorMask(true, true); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA, - LLRender::BF_ZERO, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - - renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); - gGL.setSceneBlendType(LLRender::BT_ALPHA); // <alchemy/> - gGL.setColorMask(true, false); - } -} - -void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) -{ - if (!mRiggedFace[RIGGED_GLOW].empty()) - { - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.flush(); - - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - gGL.setSceneBlendType(LLRender::BT_ADD); - - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.setColorMask(false, true); - - renderRigged(avatar, RIGGED_GLOW, true); - - gGL.setColorMask(true, false); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } -} - - - -//----------------------------------------------------------------------------- -// getDebugTexture() -//----------------------------------------------------------------------------- -LLViewerTexture *LLDrawPoolAvatar::getDebugTexture() -{ - if (mReferences.empty()) - { - return nullptr; - } - LLFace *face = mReferences[0]; - if (!face->getDrawable()) - { - return nullptr; - } - const LLViewerObject *objectp = face->getDrawable()->getVObj(); - - // Avatar should always have at least 1 (maybe 3?) TE's. - return objectp->getTEImage(0); -} - - -LLColor3 LLDrawPoolAvatar::getDebugColor() const -{ - return LLColor3(0.f, 1.f, 0.f); -} - -void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type) -{ - llassert (facep->isState(LLFace::RIGGED)); - llassert(getType() == LLDrawPool::POOL_AVATAR); - if (facep->getPool() && facep->getPool() != this) - { - LL_ERRS() << "adding rigged face that's already in another pool" << LL_ENDL; - } - if (type >= NUM_RIGGED_PASSES) - { - LL_ERRS() << "Invalid rigged face type." << LL_ENDL; - } - if (facep->getRiggedIndex(type) != -1) - { - LL_ERRS() << "Tried to add a rigged face that's referenced elsewhere." << LL_ENDL; - } - - facep->setRiggedIndex(type, mRiggedFace[type].size()); - facep->setPool(this); - mRiggedFace[type].push_back(facep); - - facep->mShinyInAlpha = type == RIGGED_DEFERRED_SIMPLE || type == RIGGED_DEFERRED_BUMP || type == RIGGED_FULLBRIGHT_SHINY || type == RIGGED_SHINY; -} - -void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep) -{ - llassert (facep->isState(LLFace::RIGGED)); - llassert(getType() == LLDrawPool::POOL_AVATAR); - if (facep->getPool() != this) - { - LL_ERRS() << "Tried to remove a rigged face from the wrong pool" << LL_ENDL; - } - facep->setPool(nullptr); - - for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) - { - S32 index = facep->getRiggedIndex(i); - - if (index > -1) - { - if (mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep) - { - facep->setRiggedIndex(i,-1); - mRiggedFace[i].erase(mRiggedFace[i].begin()+index); - for (U32 j = index; j < mRiggedFace[i].size(); ++j) - { //bump indexes down for faces referenced after erased face - mRiggedFace[i][j]->setRiggedIndex(i, j); - } - } - else - { - LL_ERRS() << "Face reference data corrupt for rigged type " << i - << ((mRiggedFace[i].size() <= index) ? "; wrong index (out of bounds)" : (mRiggedFace[i][index] != facep) ? "; wrong face pointer" : "") - << LL_ENDL; - } - } - } -} - -LLVertexBufferAvatar::LLVertexBufferAvatar() -: LLVertexBuffer(sDataMask, - GL_STREAM_DRAW_ARB) //avatars are always stream draw due to morph targets -{ - -} - - +/** + * @file lldrawpoolavatar.cpp + * @brief LLDrawPoolAvatar class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lldrawpoolavatar.h" +#include "llskinningutil.h" +#include "llrender.h" + +#include "llvoavatar.h" +#include "m3math.h" +#include "llmatrix4a.h" + +#include "llagent.h" //for gAgent.needsRenderAvatar() +#include "lldrawable.h" +#include "lldrawpoolbump.h" +#include "llface.h" +#include "llmeshrepository.h" +#include "llsky.h" +#include "llviewercamera.h" +#include "llviewerregion.h" +#include "noise.h" +#include "pipeline.h" +#include "llviewershadermgr.h" +#include "llvovolume.h" +#include "llvolume.h" +#include "llappviewer.h" +#include "llrendersphere.h" +#include "llviewerpartsim.h" +#include "llviewercontrol.h" // for gSavedSettings +#include "llviewertexturelist.h" + +#include <glm/mat3x3.hpp> +#include <glm/mat4x4.hpp> +#include <glm/gtc/matrix_inverse.hpp> +#include <glm/gtc/type_ptr.hpp> + +static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; +static U32 sBufferUsage = GL_STREAM_DRAW_ARB; +static U32 sShaderLevel = 0; + +LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = nullptr; +BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; +BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; +S32 LLDrawPoolAvatar::sShadowPass = -1; +S32 LLDrawPoolAvatar::sDiffuseChannel = 0; +F32 LLDrawPoolAvatar::sMinimumAlpha = 0.2f; + +LLUUID gBlackSquareID; + +static bool is_deferred_render = false; +static bool is_post_deferred_render = false; + +extern BOOL gUseGLPick; + +F32 CLOTHING_GRAVITY_EFFECT = 0.7f; +F32 CLOTHING_ACCEL_FORCE_FACTOR = 0.2f; + +// Format for gAGPVertices +// vertex format for bumpmapping: +// vertices 12 +// pad 4 +// normals 12 +// pad 4 +// texcoords0 8 +// texcoords1 8 +// total 48 +// +// for no bumpmapping +// vertices 12 +// texcoords 8 +// normals 12 +// total 32 +// + +S32 AVATAR_OFFSET_POS = 0; +S32 AVATAR_OFFSET_NORMAL = 16; +S32 AVATAR_OFFSET_TEX0 = 32; +S32 AVATAR_OFFSET_TEX1 = 40; +S32 AVATAR_VERTEX_BYTES = 48; + +static BOOL sRenderingSkinned = FALSE; +S32 normal_channel = -1; +S32 specular_channel = -1; +S32 cube_channel = -1; + +static LLTrace::BlockTimerStatHandle FTM_SHADOW_AVATAR("Avatar Shadow"); + +LLDrawPoolAvatar::LLDrawPoolAvatar() : + LLFacePool(POOL_AVATAR) +{ +} + +LLDrawPoolAvatar::~LLDrawPoolAvatar() +{ + if (!isDead()) + { + LL_WARNS() << "Destroying avatar drawpool that still contains faces" << LL_ENDL; + } +} + +// virtual +BOOL LLDrawPoolAvatar::isDead() +{ + if (!LLFacePool::isDead()) + { + return FALSE; + } + + for (auto& face : mRiggedFace) + { + if (!face.empty()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// instancePool() +//----------------------------------------------------------------------------- +LLDrawPool *LLDrawPoolAvatar::instancePool() +{ + return new LLDrawPoolAvatar(); +} + + +S32 LLDrawPoolAvatar::getVertexShaderLevel() const +{ + return (S32) LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); +} + +void LLDrawPoolAvatar::prerender() +{ + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); + + sShaderLevel = mVertexShaderLevel; + + if (sShaderLevel > 0) + { + sBufferUsage = GL_DYNAMIC_DRAW_ARB; + } + else + { + sBufferUsage = GL_STREAM_DRAW_ARB; + } + + if (!mDrawFace.empty()) + { + const LLFace *facep = mDrawFace[0]; + if (facep && facep->getDrawable()) + { + LLVOAvatar* avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); + updateRiggedVertexBuffers(avatarp); + } + } +} + +LLMatrix4& LLDrawPoolAvatar::getModelView() +{ + static LLMatrix4 ret; + + ret.initRows(LLVector4(gGLModelView+0), + LLVector4(gGLModelView+4), + LLVector4(gGLModelView+8), + LLVector4(gGLModelView+12)); + + return ret; +} + +//----------------------------------------------------------------------------- +// render() +//----------------------------------------------------------------------------- + + + +void LLDrawPoolAvatar::beginDeferredPass(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + + sSkipTransparent = TRUE; + is_deferred_render = true; + + if (LLPipeline::sImpostorRender) + { //impostor pass does not have rigid or impostor rendering + pass += 2; + } + + switch (pass) + { + case 0: + beginDeferredImpostor(); + break; + case 1: + beginDeferredRigid(); + break; + case 2: + beginDeferredSkinned(); + break; + case 3: + beginDeferredRiggedSimple(); + break; + case 4: + beginDeferredRiggedBump(); + break; + default: + beginDeferredRiggedMaterial(pass-5); + break; + } +} + +void LLDrawPoolAvatar::endDeferredPass(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + + sSkipTransparent = FALSE; + is_deferred_render = false; + + if (LLPipeline::sImpostorRender) + { + pass += 2; + } + + switch (pass) + { + case 0: + endDeferredImpostor(); + break; + case 1: + endDeferredRigid(); + break; + case 2: + endDeferredSkinned(); + break; + case 3: + endDeferredRiggedSimple(); + break; + case 4: + endDeferredRiggedBump(); + break; + default: + endDeferredRiggedMaterial(pass-5); + break; + } +} + +void LLDrawPoolAvatar::renderDeferred(S32 pass) +{ + render(pass); +} + +S32 LLDrawPoolAvatar::getNumPostDeferredPasses() +{ + return 10; +} + +void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) +{ + switch (pass) + { + case 0: + beginPostDeferredAlpha(); + break; + case 1: + beginRiggedFullbright(); + break; + case 2: + beginRiggedFullbrightShiny(); + break; + case 3: + beginDeferredRiggedAlpha(); + break; + case 4: + beginRiggedFullbrightAlpha(); + break; + case 9: + beginRiggedGlow(); + break; + default: + beginDeferredRiggedMaterialAlpha(pass-5); + break; + } +} + +void LLDrawPoolAvatar::beginPostDeferredAlpha() +{ + sSkipOpaque = TRUE; + sShaderLevel = mVertexShaderLevel; + sVertexProgram = &gDeferredAvatarAlphaProgram; + sRenderingSkinned = TRUE; + + gPipeline.bindDeferredShader(*sVertexProgram); + + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); + + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); +} + +void LLDrawPoolAvatar::beginDeferredRiggedAlpha() +{ + sVertexProgram = &gDeferredSkinnedAlphaProgram; + gPipeline.bindDeferredShader(*sVertexProgram); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + gPipeline.enableLightsDynamic(); +} + +void LLDrawPoolAvatar::beginDeferredRiggedMaterialAlpha(S32 pass) +{ + switch (pass) + { + case 0: pass = 1; break; + case 1: pass = 5; break; + case 2: pass = 9; break; + default: pass = 13; break; + } + + pass += LLMaterial::SHADER_COUNT; + + sVertexProgram = &gDeferredMaterialProgram[pass]; + + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &(gDeferredMaterialWaterProgram[pass]); + } + + gPipeline.bindDeferredShader(*sVertexProgram); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); + specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + gPipeline.enableLightsDynamic(); +} + +void LLDrawPoolAvatar::endDeferredRiggedAlpha() +{ + LLVertexBuffer::unbind(); + gPipeline.unbindDeferredShader(*sVertexProgram); + sDiffuseChannel = 0; + normal_channel = -1; + specular_channel = -1; + sVertexProgram = nullptr; +} + +void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) +{ + switch (pass) + { + case 0: + endPostDeferredAlpha(); + break; + case 1: + endRiggedFullbright(); + break; + case 2: + endRiggedFullbrightShiny(); + break; + case 3: + endDeferredRiggedAlpha(); + break; + case 4: + endRiggedFullbrightAlpha(); + break; + case 5: + endRiggedGlow(); + break; + default: + endDeferredRiggedAlpha(); + break; + } +} + +void LLDrawPoolAvatar::endPostDeferredAlpha() +{ + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done + sRenderingSkinned = FALSE; + sSkipOpaque = FALSE; + + gPipeline.unbindDeferredShader(*sVertexProgram); + sDiffuseChannel = 0; + sShaderLevel = mVertexShaderLevel; +} + +void LLDrawPoolAvatar::renderPostDeferred(S32 pass) +{ + static const S32 actual_pass[] = + { //map post deferred pass numbers to what render() expects + 2, //skinned + 4, // rigged fullbright + 6, //rigged fullbright shiny + 7, //rigged alpha + 8, //rigged fullbright alpha + 9, //rigged material alpha 1 + 10,//rigged material alpha 2 + 11,//rigged material alpha 3 + 12,//rigged material alpha 4 + 13, //rigged glow + }; + + S32 p = actual_pass[pass]; + + if (LLPipeline::sImpostorRender) + { //HACK for impostors so actual pass ends up being proper pass + p -= 2; + } + + is_post_deferred_render = true; + render(p); + is_post_deferred_render = false; +} + + +S32 LLDrawPoolAvatar::getNumShadowPasses() +{ + // avatars opaque, avatar alpha, avatar alpha mask, alpha attachments, alpha mask attachments, opaque attachments... + return NUM_SHADOW_PASSES; +} + +void LLDrawPoolAvatar::beginShadowPass(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); + + if (pass == SHADOW_PASS_AVATAR_OPAQUE) + { + sVertexProgram = &gDeferredAvatarShadowProgram; + + if ((sShaderLevel > 0)) // for hardware blending + { + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + } + + gGL.diffuseColor4f(1,1,1,1); + } + else if (pass == SHADOW_PASS_AVATAR_ALPHA_BLEND) + { + sVertexProgram = &gDeferredAvatarAlphaShadowProgram; + + // bind diffuse tex so we can reference the alpha channel... + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + + if ((sShaderLevel > 0)) // for hardware blending + { + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + } + + gGL.diffuseColor4f(1,1,1,1); + } + else if (pass == SHADOW_PASS_AVATAR_ALPHA_MASK) + { + sVertexProgram = &gDeferredAvatarAlphaMaskShadowProgram; + + // bind diffuse tex so we can reference the alpha channel... + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + + if ((sShaderLevel > 0)) // for hardware blending + { + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + } + + gGL.diffuseColor4f(1,1,1,1); + } + else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND) + { + sVertexProgram = &gDeferredAttachmentAlphaShadowProgram; + + // bind diffuse tex so we can reference the alpha channel... + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + + if ((sShaderLevel > 0)) // for hardware blending + { + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + } + + gGL.diffuseColor4f(1,1,1,1); + } + else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK) + { + sVertexProgram = &gDeferredAttachmentAlphaMaskShadowProgram; + + // bind diffuse tex so we can reference the alpha channel... + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + + if ((sShaderLevel > 0)) // for hardware blending + { + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + } + + gGL.diffuseColor4f(1,1,1,1); + } + else // SHADOW_PASS_ATTACHMENT_OPAQUE + { + sVertexProgram = &gDeferredAttachmentShadowProgram; + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sVertexProgram->bind(); + } +} + +void LLDrawPoolAvatar::endShadowPass(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); + + if (pass == SHADOW_PASS_ATTACHMENT_OPAQUE) + { + LLVertexBuffer::unbind(); + } + + if (sShaderLevel > 0) + { + sVertexProgram->unbind(); + } + sVertexProgram = nullptr; + sRenderingSkinned = FALSE; + LLDrawPoolAvatar::sShadowPass = -1; +} + +void LLDrawPoolAvatar::renderShadow(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); + + if (mDrawFace.empty()) + { + return; + } + + const LLFace *facep = mDrawFace[0]; + if (!facep->getDrawable()) + { + return; + } + LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); + + if (avatarp->isDead() || avatarp->isUIAvatar() || avatarp->mDrawable.isNull()) + { + return; + } + + BOOL impostor = avatarp->isImpostor(); + if (impostor) + { + return; + } + + LLDrawPoolAvatar::sShadowPass = pass; + + if (pass == SHADOW_PASS_AVATAR_OPAQUE) + { + LLDrawPoolAvatar::sSkipTransparent = true; + avatarp->renderSkinned(); + LLDrawPoolAvatar::sSkipTransparent = false; + } + else if (pass == SHADOW_PASS_AVATAR_ALPHA_BLEND) + { + LLDrawPoolAvatar::sSkipOpaque = true; + avatarp->renderSkinned(); + LLDrawPoolAvatar::sSkipOpaque = false; + } + else if (pass == SHADOW_PASS_AVATAR_ALPHA_MASK) + { + LLDrawPoolAvatar::sSkipOpaque = true; + avatarp->renderSkinned(); + LLDrawPoolAvatar::sSkipOpaque = false; + } + else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND) // rigged alpha + { + LLDrawPoolAvatar::sSkipOpaque = true; + renderRigged(avatarp, RIGGED_MATERIAL_ALPHA); + renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE); + renderRigged(avatarp, RIGGED_ALPHA); + renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA); + renderRigged(avatarp, RIGGED_GLOW); + renderRigged(avatarp, RIGGED_SPECMAP_BLEND); + renderRigged(avatarp, RIGGED_NORMMAP_BLEND); + renderRigged(avatarp, RIGGED_NORMSPEC_BLEND); + LLDrawPoolAvatar::sSkipOpaque = false; + } + else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK) // rigged alpha mask + { + LLDrawPoolAvatar::sSkipOpaque = true; + renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK); + renderRigged(avatarp, RIGGED_NORMMAP_MASK); + renderRigged(avatarp, RIGGED_SPECMAP_MASK); + renderRigged(avatarp, RIGGED_NORMSPEC_MASK); + renderRigged(avatarp, RIGGED_GLOW); + LLDrawPoolAvatar::sSkipOpaque = false; + } + else // rigged opaque (SHADOW_PASS_ATTACHMENT_OPAQUE + { + LLDrawPoolAvatar::sSkipTransparent = true; + renderRigged(avatarp, RIGGED_MATERIAL); + renderRigged(avatarp, RIGGED_SPECMAP); + renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE); + renderRigged(avatarp, RIGGED_NORMMAP); + renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); + renderRigged(avatarp, RIGGED_NORMSPEC); + renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE); + renderRigged(avatarp, RIGGED_SIMPLE); + renderRigged(avatarp, RIGGED_FULLBRIGHT); + renderRigged(avatarp, RIGGED_SHINY); + renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY); + renderRigged(avatarp, RIGGED_GLOW); + renderRigged(avatarp, RIGGED_DEFERRED_BUMP); + renderRigged(avatarp, RIGGED_DEFERRED_SIMPLE); + LLDrawPoolAvatar::sSkipTransparent = false; + } +} + +S32 LLDrawPoolAvatar::getNumPasses() +{ + if (LLPipeline::sImpostorRender) + { + return 8; + } + else + { + return 10; + } +} + + +S32 LLDrawPoolAvatar::getNumDeferredPasses() +{ + if (LLPipeline::sImpostorRender) + { + return 19; + } + else + { + return 21; + } +} + + +void LLDrawPoolAvatar::render(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + if (LLPipeline::sImpostorRender) + { + renderAvatars(nullptr, pass+2); + return; + } + + renderAvatars(nullptr, pass); // render all avatars +} + +void LLDrawPoolAvatar::beginRenderPass(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + //reset vertex buffer mappings + LLVertexBuffer::unbind(); + + if (LLPipeline::sImpostorRender) + { //impostor render does not have impostors or rigid rendering + pass += 2; + } + + switch (pass) + { + case 0: + beginImpostor(); + break; + case 1: + beginRigid(); + break; + case 2: + beginSkinned(); + break; + case 3: + beginRiggedSimple(); + break; + case 4: + beginRiggedFullbright(); + break; + case 5: + beginRiggedShinySimple(); + break; + case 6: + beginRiggedFullbrightShiny(); + break; + case 7: + beginRiggedAlpha(); + break; + case 8: + beginRiggedFullbrightAlpha(); + break; + case 9: + beginRiggedGlow(); + break; + } + + if (pass == 0) + { //make sure no stale colors are left over from a previous render + gGL.diffuseColor4f(1,1,1,1); + } +} + +void LLDrawPoolAvatar::endRenderPass(S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + + if (LLPipeline::sImpostorRender) + { + pass += 2; + } + + switch (pass) + { + case 0: + endImpostor(); + break; + case 1: + endRigid(); + break; + case 2: + endSkinned(); + break; + case 3: + endRiggedSimple(); + break; + case 4: + endRiggedFullbright(); + break; + case 5: + endRiggedShinySimple(); + break; + case 6: + endRiggedFullbrightShiny(); + break; + case 7: + endRiggedAlpha(); + break; + case 8: + endRiggedFullbrightAlpha(); + break; + case 9: + endRiggedGlow(); + break; + } +} + +void LLDrawPoolAvatar::beginImpostor() +{ + if (!LLPipeline::sReflectionRender) + { + LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); + LLVOAvatar::sNumVisibleAvatars = 0; + } + + if (LLGLSLShader::sNoFixedFunction) + { + gImpostorProgram.bind(); + gImpostorProgram.setMinimumAlpha(0.01f); + } + + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + sDiffuseChannel = 0; +} + +void LLDrawPoolAvatar::endImpostor() +{ + if (LLGLSLShader::sNoFixedFunction) + { + gImpostorProgram.unbind(); + } + gPipeline.enableLightsDynamic(); +} + +void LLDrawPoolAvatar::beginRigid() +{ + if (gPipeline.canUseVertexShaders()) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectAlphaMaskNoColorWaterProgram; + } + else + { + sVertexProgram = &gObjectAlphaMaskNoColorProgram; + } + + if (sVertexProgram != nullptr) + { //eyeballs render with the specular shader + sVertexProgram->bind(); + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); + } + } + else + { + sVertexProgram = nullptr; + } +} + +void LLDrawPoolAvatar::endRigid() +{ + sShaderLevel = mVertexShaderLevel; + if (sVertexProgram != nullptr) + { + sVertexProgram->unbind(); + } +} + +void LLDrawPoolAvatar::beginDeferredImpostor() +{ + if (!LLPipeline::sReflectionRender) + { + LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); + LLVOAvatar::sNumVisibleAvatars = 0; + } + + sVertexProgram = &gDeferredImpostorProgram; + specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sVertexProgram->bind(); + sVertexProgram->setMinimumAlpha(0.01f); +} + +void LLDrawPoolAvatar::endDeferredImpostor() +{ + sShaderLevel = mVertexShaderLevel; + sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); + sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + gPipeline.unbindDeferredShader(*sVertexProgram); + sVertexProgram = nullptr; + sDiffuseChannel = 0; +} + +void LLDrawPoolAvatar::beginDeferredRigid() +{ + sVertexProgram = &gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sVertexProgram->bind(); + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); +} + +void LLDrawPoolAvatar::endDeferredRigid() +{ + sShaderLevel = mVertexShaderLevel; + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sVertexProgram->unbind(); + gGL.getTexUnit(0)->activate(); +} + + +void LLDrawPoolAvatar::beginSkinned() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gAvatarWaterProgram; + sShaderLevel = llmin((U32) 1, sShaderLevel); + } + else + { + sVertexProgram = &gAvatarProgram; + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectAlphaMaskNoColorWaterProgram; + } + else + { + sVertexProgram = &gObjectAlphaMaskNoColorProgram; + } + } + + if (sShaderLevel > 0) // for hardware blending + { + sRenderingSkinned = TRUE; + + sVertexProgram->bind(); + sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); + gGL.getTexUnit(0)->activate(); + } + else + { + if(gPipeline.canUseVertexShaders()) + { + // software skinning, use a basic shader for windlight. + // TODO: find a better fallback method for software skinning. + sVertexProgram->bind(); + } + } + + if (LLGLSLShader::sNoFixedFunction) + { + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); + } +} + +void LLDrawPoolAvatar::endSkinned() +{ + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done + if (sShaderLevel > 0) + { + sRenderingSkinned = FALSE; + sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); + gGL.getTexUnit(0)->activate(); + sVertexProgram->unbind(); + sShaderLevel = mVertexShaderLevel; + } + else + { + if(gPipeline.canUseVertexShaders()) + { + // software skinning, use a basic shader for windlight. + // TODO: find a better fallback method for software skinning. + sVertexProgram->unbind(); + } + } + + gGL.getTexUnit(0)->activate(); +} + +void LLDrawPoolAvatar::beginRiggedSimple() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectSimpleWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectSimpleProgram; + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectSimpleNonIndexedWaterProgram; + } + else + { + sVertexProgram = &gObjectSimpleNonIndexedProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sDiffuseChannel = 0; + sVertexProgram->bind(); + } +} + +void LLDrawPoolAvatar::endRiggedSimple() +{ + LLVertexBuffer::unbind(); + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->unbind(); + sVertexProgram = nullptr; + } +} + +void LLDrawPoolAvatar::beginRiggedAlpha() +{ + beginRiggedSimple(); +} + +void LLDrawPoolAvatar::endRiggedAlpha() +{ + endRiggedSimple(); +} + + +void LLDrawPoolAvatar::beginRiggedFullbrightAlpha() +{ + beginRiggedFullbright(); +} + +void LLDrawPoolAvatar::endRiggedFullbrightAlpha() +{ + endRiggedFullbright(); +} + +void LLDrawPoolAvatar::beginRiggedGlow() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectEmissiveWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectEmissiveProgram; + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectEmissiveNonIndexedWaterProgram; + } + else + { + sVertexProgram = &gObjectEmissiveNonIndexedProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sDiffuseChannel = 0; + sVertexProgram->bind(); + + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, LLPipeline::sRenderDeferred ? 2.2f : 1.1f); + } +} + +void LLDrawPoolAvatar::endRiggedGlow() +{ + endRiggedFullbright(); +} + +void LLDrawPoolAvatar::beginRiggedFullbright() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; + } + else + { + if (LLPipeline::sRenderDeferred) + { + sVertexProgram = &gDeferredSkinnedFullbrightProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightProgram; + } + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectFullbrightNonIndexedWaterProgram; + } + else + { + sVertexProgram = &gObjectFullbrightNonIndexedProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sDiffuseChannel = 0; + sVertexProgram->bind(); + + if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) + { + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); + } + else + { + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + } + } +} + +void LLDrawPoolAvatar::endRiggedFullbright() +{ + LLVertexBuffer::unbind(); + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->unbind(); + sVertexProgram = nullptr; + } +} + +void LLDrawPoolAvatar::beginRiggedShinySimple() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectShinySimpleWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectShinySimpleProgram; + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectShinyNonIndexedWaterProgram; + } + else + { + sVertexProgram = &gObjectShinyNonIndexedProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->bind(); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); + } +} + +void LLDrawPoolAvatar::endRiggedShinySimple() +{ + LLVertexBuffer::unbind(); + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); + sVertexProgram->unbind(); + sVertexProgram = nullptr; + } +} + +void LLDrawPoolAvatar::beginRiggedFullbrightShiny() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightShinyWaterProgram; + } + else + { + if (LLPipeline::sRenderDeferred) + { + sVertexProgram = &gDeferredSkinnedFullbrightShinyProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; + } + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectFullbrightShinyNonIndexedWaterProgram; + } + else + { + sVertexProgram = &gObjectFullbrightShinyNonIndexedProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->bind(); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); + + if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) + { + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); + } + else + { + sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + } + } +} + +void LLDrawPoolAvatar::endRiggedFullbrightShiny() +{ + LLVertexBuffer::unbind(); + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel); + sVertexProgram->unbind(); + sVertexProgram = nullptr; + } +} + + +void LLDrawPoolAvatar::beginDeferredRiggedSimple() +{ + sVertexProgram = &gDeferredSkinnedDiffuseProgram; + sDiffuseChannel = 0; + sVertexProgram->bind(); +} + +void LLDrawPoolAvatar::endDeferredRiggedSimple() +{ + LLVertexBuffer::unbind(); + sVertexProgram->unbind(); + sVertexProgram = nullptr; +} + +void LLDrawPoolAvatar::beginDeferredRiggedBump() +{ + sVertexProgram = &gDeferredSkinnedBumpProgram; + sVertexProgram->bind(); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); +} + +void LLDrawPoolAvatar::endDeferredRiggedBump() +{ + LLVertexBuffer::unbind(); + sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sVertexProgram->unbind(); + normal_channel = -1; + sDiffuseChannel = 0; + sVertexProgram = nullptr; +} + +void LLDrawPoolAvatar::beginDeferredRiggedMaterial(S32 pass) +{ + if (pass == 1 || + pass == 5 || + pass == 9 || + pass == 13) + { //skip alpha passes + return; + } + sVertexProgram = &gDeferredMaterialProgram[pass+LLMaterial::SHADER_COUNT]; + + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &(gDeferredMaterialWaterProgram[pass+LLMaterial::SHADER_COUNT]); + } + + sVertexProgram->bind(); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); + specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); +} + +void LLDrawPoolAvatar::endDeferredRiggedMaterial(S32 pass) +{ + if (pass == 1 || + pass == 5 || + pass == 9 || + pass == 13) + { + return; + } + + LLVertexBuffer::unbind(); + sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sVertexProgram->unbind(); + normal_channel = -1; + sDiffuseChannel = 0; + sVertexProgram = nullptr; +} + +void LLDrawPoolAvatar::beginDeferredSkinned() +{ + sShaderLevel = mVertexShaderLevel; + sVertexProgram = &gDeferredAvatarProgram; + sRenderingSkinned = TRUE; + + sVertexProgram->bind(); + sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); + + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + gGL.getTexUnit(0)->activate(); +} + +void LLDrawPoolAvatar::endDeferredSkinned() +{ + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done + sRenderingSkinned = FALSE; + sVertexProgram->unbind(); + + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + + sShaderLevel = mVertexShaderLevel; + + gGL.getTexUnit(0)->activate(); +} + +static LLTrace::BlockTimerStatHandle FTM_RENDER_AVATARS("renderAvatars"); + + +void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) +{ + LL_RECORD_BLOCK_TIME(FTM_RENDER_AVATARS); + + if (pass == -1) + { + for (S32 i = 1; i < getNumPasses(); i++) + { //skip foot shadows + prerender(); + beginRenderPass(i); + renderAvatars(single_avatar, i); + endRenderPass(i); + } + + return; + } + + if (mDrawFace.empty() && !single_avatar) + { + return; + } + + LLVOAvatar *avatarp; + + if (single_avatar) + { + avatarp = single_avatar; + } + else + { + const LLFace *facep = mDrawFace[0]; + if (!facep->getDrawable()) + { + return; + } + avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); + } + + if (avatarp->isDead() || avatarp->mDrawable.isNull()) + { + return; + } + + if (!single_avatar && !avatarp->isFullyLoaded() ) + { + if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0)) + { + // debug code to draw a sphere in place of avatar + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); + gGL.setColorMask(true, true); + LLVector3 pos = avatarp->getPositionAgent(); + gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f); + + gGL.pushMatrix(); + gGL.translatef((F32)(pos.mV[VX]), + (F32)(pos.mV[VY]), + (F32)(pos.mV[VZ])); + gGL.scalef(0.15f, 0.15f, 0.3f); + + gSphere.renderGGL(); + + gGL.popMatrix(); + gGL.setColorMask(true, false); + } + // don't render please + return; + } + + BOOL impostor = avatarp->isImpostor() && !single_avatar; + + if (impostor && pass != 0) + { //don't draw anything but the impostor for impostored avatars + return; + } + + if (pass == 0 && !impostor && LLPipeline::sUnderWaterRender) + { //don't draw foot shadows under water + return; + } + + if (pass == 0) + { + if (!LLPipeline::sReflectionRender) + { + LLVOAvatar::sNumVisibleAvatars++; + } + + if (impostor) + { + if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete()) + { + if (normal_channel > -1) + { + avatarp->mImpostor.bindTexture(2, normal_channel); + } + if (specular_channel > -1) + { + avatarp->mImpostor.bindTexture(1, specular_channel); + } + } + avatarp->renderImpostor(avatarp->getMutedAVColor(), sDiffuseChannel); + } + return; + } + + if (pass == 1) + { + // render rigid meshes (eyeballs) first + avatarp->renderRigid(); + return; + } + + if (pass == 3) + { + if (is_deferred_render) + { + renderDeferredRiggedSimple(avatarp); + } + else + { + renderRiggedSimple(avatarp); + + if (LLPipeline::sRenderDeferred) + { //render "simple" materials + renderRigged(avatarp, RIGGED_MATERIAL); + renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK); + renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE); + renderRigged(avatarp, RIGGED_NORMMAP); + renderRigged(avatarp, RIGGED_NORMMAP_MASK); + renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); + renderRigged(avatarp, RIGGED_SPECMAP); + renderRigged(avatarp, RIGGED_SPECMAP_MASK); + renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE); + renderRigged(avatarp, RIGGED_NORMSPEC); + renderRigged(avatarp, RIGGED_NORMSPEC_MASK); + renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE); + } + } + return; + } + + if (pass == 4) + { + if (is_deferred_render) + { + renderDeferredRiggedBump(avatarp); + } + else + { + renderRiggedFullbright(avatarp); + } + + return; + } + + if (is_deferred_render && pass >= 5 && pass <= 21) + { + S32 p = pass-5; + + if (p != 1 && + p != 5 && + p != 9 && + p != 13) + { + renderDeferredRiggedMaterial(avatarp, p); + } + return; + } + + + + + if (pass == 5) + { + renderRiggedShinySimple(avatarp); + + return; + } + + if (pass == 6) + { + renderRiggedFullbrightShiny(avatarp); + return; + } + + if (pass >= 7 && pass < 13) + { + if (pass == 7) + { + renderRiggedAlpha(avatarp); + + if (LLPipeline::sRenderDeferred && !is_post_deferred_render) + { //render transparent materials under water + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + renderRigged(avatarp, RIGGED_MATERIAL_ALPHA); + renderRigged(avatarp, RIGGED_SPECMAP_BLEND); + renderRigged(avatarp, RIGGED_NORMMAP_BLEND); + renderRigged(avatarp, RIGGED_NORMSPEC_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); // <alchemy/> + gGL.setColorMask(true, false); + } + return; + } + + if (pass == 8) + { + renderRiggedFullbrightAlpha(avatarp); + return; + } + + if (LLPipeline::sRenderDeferred && is_post_deferred_render) + { + S32 p = 0; + switch (pass) + { + case 9: p = 1; break; + case 10: p = 5; break; + case 11: p = 9; break; + case 12: p = 13; break; + } + + { + LLGLEnable blend(GL_BLEND); + renderDeferredRiggedMaterial(avatarp, p); + } + return; + } + else if (pass == 9) + { + renderRiggedGlow(avatarp); + return; + } + } + + if (pass == 13) + { + renderRiggedGlow(avatarp); + + return; + } + + if ((sShaderLevel >= SHADER_LEVEL_CLOTH)) + { + LLMatrix4 rot_mat; + LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat); + static const LLMatrix4 cfr(OGL_TO_CFR_ROTATION); + rot_mat *= cfr; + + LLVector4 wind; + wind.setVec(avatarp->mWindVec); + wind.mV[VW] = 0; + wind = wind * rot_mat; + wind.mV[VW] = avatarp->mWindVec.mV[VW]; + + sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV); + F32 phase = -1.f * (avatarp->mRipplePhase); + + F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f); + LLVector4 sin_params(freq, freq, freq, phase); + sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV); + + LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f); + gravity = gravity * rot_mat; + sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV); + } + + if( !single_avatar || (avatarp == single_avatar) ) + { + avatarp->renderSkinned(); + } +} + +void LLDrawPoolAvatar::getRiggedGeometry( + LLFace* face, + LLPointer<LLVertexBuffer>& buffer, + U32 data_mask, + const LLMeshSkinInfo* skin, + LLVolume* volume, + const LLVolumeFace& vol_face) +{ + face->setGeomIndex(0); + face->setIndicesIndex(0); + + //rigged faces do not batch textures + face->setTextureIndex(255); + + if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable()) + { + // make a new buffer + if (sShaderLevel > 0) + { + buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB); + } + else + { + buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB); + } + + if (!buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true)) + { + LL_WARNS("LLDrawPoolAvatar") << "Failed to allocate Vertex Buffer to " + << vol_face.mNumVertices << " vertices and " + << vol_face.mNumIndices << " indices" << LL_ENDL; + // allocate dummy triangle + buffer->allocateBuffer(1, 3, true); + memset((U8*)buffer->getMappedData(), 0, buffer->getSize()); + memset((U8*)buffer->getMappedIndices(), 0, buffer->getIndicesSize()); + } + } + else + { + //resize existing buffer + if(!buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices)) + { + LL_WARNS("LLDrawPoolAvatar") << "Failed to resize Vertex Buffer to " + << vol_face.mNumVertices << " vertices and " + << vol_face.mNumIndices << " indices" << LL_ENDL; + // allocate dummy triangle + buffer->resizeBuffer(1, 3); + memset((U8*)buffer->getMappedData(), 0, buffer->getSize()); + memset((U8*)buffer->getMappedIndices(), 0, buffer->getIndicesSize()); + } + } + + face->setSize(buffer->getNumVerts(), buffer->getNumIndices()); + face->setVertexBuffer(buffer); + + U16 offset = 0; + + LLMatrix4a mat_vert_inv = skin->mBindShapeMatrix; + mat_vert_inv.invert(); + mat_vert_inv.transpose(); + + const F32* m = mat_vert_inv.getF32ptr(); + F32 mat3[] = + { m[0], m[1], m[2], + m[4], m[5], m[6], + m[8], m[9], m[10] }; + + LLMatrix3 mat_normal(mat3); + + //let getGeometryVolume know if alpha should override shiny + U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture()); + + if (type == LLDrawPool::POOL_ALPHA) + { + face->setPoolType(LLDrawPool::POOL_ALPHA); + } + else + { + face->setPoolType(LLDrawPool::POOL_AVATAR); + } + + //LL_INFOS() << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << LL_ENDL; + + // Let getGeometryVolume know if a texture matrix is in play + if (face->mTextureMatrix) + { + face->setState(LLFace::TEXTURE_ANIM); + } + else + { + face->clearState(LLFace::TEXTURE_ANIM); + } + LLMatrix4 mat_vert(skin->mBindShapeMatrix.getF32ptr()); + face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); + + buffer->flush(); +} + +void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( + LLVOAvatar* avatar, + LLFace* face, + const LLMeshSkinInfo* skin, + LLVolume* volume, + const LLVolumeFace& vol_face) +{ + LLVector4a* weights = vol_face.mWeights; + if (!weights) + { + return; + } + // FIXME ugly const cast + LLSkinningUtil::scrubInvalidJoints(avatar, const_cast<LLMeshSkinInfo*>(skin)); + + LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer(); + LLDrawable* drawable = face->getDrawable(); + + if (drawable->getVOVolume() && drawable->getVOVolume()->isNoLOD()) + { + return; + } + + U32 data_mask = face->getRiggedVertexBufferDataMask(); + + if (!vol_face.mWeightsScrubbed) + { + LLSkinningUtil::scrubSkinWeights(weights, vol_face.mNumVertices, skin); + vol_face.mWeightsScrubbed = TRUE; + } + + if (buffer.isNull() || + buffer->getTypeMask() != data_mask || + buffer->getNumVerts() != vol_face.mNumVertices || + buffer->getNumIndices() != vol_face.mNumIndices || + (drawable && drawable->isState(LLDrawable::REBUILD_ALL))) + { + if (drawable && drawable->isState(LLDrawable::REBUILD_ALL)) + { //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* facep = drawable->getFace(i); + U32 face_data_mask = facep->getRiggedVertexBufferDataMask(); + if (face_data_mask) + { + LLPointer<LLVertexBuffer> cur_buffer = facep->getVertexBuffer(); + const LLVolumeFace& cur_vol_face = volume->getVolumeFace(i); + getRiggedGeometry(facep, cur_buffer, face_data_mask, skin, volume, cur_vol_face); + } + } + drawable->clearState(LLDrawable::REBUILD_ALL); + + buffer = face->getVertexBuffer(); + } + else + { //just rebuild this face + getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face); + } + } + + if (buffer.isNull() || + buffer->getNumVerts() != vol_face.mNumVertices || + buffer->getNumIndices() != vol_face.mNumIndices) + { + // Allocation failed + return; + } + + if (!buffer.isNull() && + sShaderLevel <= 0 && + face->mLastSkinTime < avatar->getLastSkinTime()) + { + //perform software vertex skinning for this face + LLStrider<LLVector3> position; + LLStrider<LLVector3> normal; + + bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + buffer->getVertexStrider(position); + + if (has_normal) + { + buffer->getNormalStrider(normal); + } + + LLVector4a* pos = (LLVector4a*) position.get(); + + LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; + + //build matrix palette + LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + U32 count = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette(mat, count, skin, avatar); + LLSkinningUtil::checkSkinWeights(weights, buffer->getNumVerts(), skin); + + const U32 max_joints = LLSkinningUtil::getMaxJointCount(); + for (S32 j = 0; j < buffer->getNumVerts(); ++j) + { + LLMatrix4a final_mat; + LLSkinningUtil::getPerVertexSkinMatrix(weights[j], mat, false, final_mat, max_joints); + + const LLVector4a& v = vol_face.mPositions[j]; + + LLVector4a dst; + skin->mBindShapeMatrix.affineTransform(v, dst); + final_mat.affineTransform(dst, dst); + pos[j] = dst; + + if (norm) + { + const LLVector4a& n = vol_face.mNormals[j]; + skin->mBindShapeMatrix.rotate(n, dst); + final_mat.rotate(dst, dst); + dst.normalize3fast(); + norm[j] = dst; + } + } + } +} + +void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) +{ + if (!avatar->shouldRenderRigged()) + { + return; + } + + stop_glerror(); + + for (LLFace* face : mRiggedFace[type]) + { + S32 offset = face->getIndicesStart(); + U32 count = face->getIndicesCount(); + + U16 start = face->getGeomStart(); + U16 end = start + face->getGeomCount()-1; + + LLDrawable* drawable = face->getDrawable(); + if (!drawable) + { + continue; + } + + LLVOVolume* vobj = drawable->getVOVolume(); + + if (!vobj) + { + continue; + } + + LLVolume* volume = vobj->getVolume(); + S32 te = face->getTEOffset(); + + if (!volume || volume->getNumVolumeFaces() <= te || !volume->isMeshAssetLoaded()) + { + continue; + } + + const LLMeshSkinInfo* skin = vobj->getSkinInfo(); + if (!skin) + { + continue; + } + + //stop_glerror(); + + //const LLVolumeFace& vol_face = volume->getVolumeFace(te); + //updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); + + //stop_glerror(); + + U32 data_mask = LLFace::getRiggedDataMask(type); + + LLVertexBuffer* buff = face->getVertexBuffer(); + + const LLTextureEntry* tex_entry = face->getTextureEntry(); + LLMaterial* mat = tex_entry ? tex_entry->getMaterialParams().get() : nullptr; + + if (LLDrawPoolAvatar::sShadowPass >= 0) + { + bool is_alpha_blend = false; + bool is_alpha_mask = false; + + LLViewerTexture* tex = face->getTexture(LLRender::DIFFUSE_MAP); + if (tex) + { + if (tex->getIsAlphaMask(-1.f, -1.f)) + { + is_alpha_mask = true; + } + } + + if (tex) + { + LLGLenum image_format = tex->getPrimaryFormat(); + if (!is_alpha_mask && (image_format == GL_RGBA || image_format == GL_ALPHA)) + { + is_alpha_blend = true; + } + } + + if (tex_entry) + { + if (tex_entry->getAlpha() <= 0.99f) + { + is_alpha_blend = true; + } + } + + if (mat) + { + switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaMode())) + { + case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: + { + is_alpha_mask = true; + is_alpha_blend = false; + } + break; + + case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: + { + is_alpha_blend = true; + is_alpha_mask = false; + } + break; + + case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: + case LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT: + case LLMaterial::DIFFUSE_ALPHA_MODE_NONE: + default: + is_alpha_blend = false; + is_alpha_mask = false; + break; + } + } + + // if this is alpha mask content and we're doing opaques or a non-alpha-mask shadow pass... + if (is_alpha_mask && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_MASK)) + { + return; + } + + // if this is alpha blend content and we're doing opaques or a non-alpha-blend shadow pass... + if (is_alpha_blend && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_BLEND)) + { + return; + } + + // if this is opaque content and we're skipping opaques... + if (!is_alpha_mask && !is_alpha_blend && LLDrawPoolAvatar::sSkipOpaque) + { + return; + } + } + + if (buff) + { + if (sShaderLevel > 0) + { + auto& mesh_cache = avatar->getRiggedMatrixCache(); + const auto& mesh_id = skin->mMeshID; + const auto& rigged_matrix_data_iter = mesh_cache.find(mesh_id); + if (rigged_matrix_data_iter != mesh_cache.cend() && (!avatar->isSelf() || !avatar->isEditingAppearance())) + { + LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + rigged_matrix_data_iter->second.first, + FALSE, + (GLfloat*)rigged_matrix_data_iter->second.second.data()); + + stop_glerror(); + } + else + { + // upload matrix palette to shader + LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; + U32 count = LLSkinningUtil::getMeshJointCount(skin); + LLSkinningUtil::initSkinningMatrixPalette(mat, count, skin, avatar); + + stop_glerror(); + + std::vector<F32> mp; + mp.reserve(count * 12); + + for (U32 i = 0; i < count; ++i) + { + F32* m = (F32*) mat[i].getF32ptr(); + + U32 idx = i * 12; + + mp[idx + 0] = m[0]; + mp[idx + 1] = m[1]; + mp[idx + 2] = m[2]; + mp[idx + 3] = m[12]; + + mp[idx + 4] = m[4]; + mp[idx + 5] = m[5]; + mp[idx + 6] = m[6]; + mp[idx + 7] = m[13]; + + mp[idx + 8] = m[8]; + mp[idx + 9] = m[9]; + mp[idx + 10] = m[10]; + mp[idx + 11] = m[14]; + } + LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + count, + FALSE, + (GLfloat*) mp.data()); + mesh_cache.emplace(mesh_id, std::make_pair(count, std::move(mp))); + stop_glerror(); + } + } + else + { + data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; + } + + /*if (glow) + { + gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow()); + }*/ + + if (mat) + { + //order is important here LLRender::DIFFUSE_MAP should be last, because it changes + //(gGL).mCurrTextureUnitIndex + LLViewerTexture* specular = nullptr; + if (LLPipeline::sImpostorRender && avatar->isVisuallyMuted()) + { + specular = LLViewerTextureManager::findFetchedTexture(gBlackSquareID, TEX_LIST_STANDARD); + } + else + { + specular = face->getViewerObject()->getTESpecularMap(face->getTEOffset()); + } + + gGL.getTexUnit(specular_channel)->bind(specular); + gGL.getTexUnit(normal_channel)->bind(face->getViewerObject()->getTENormalMap(face->getTEOffset())); + gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(), false, true); + + static const LLColor4 alpha[4] = + { + {0.00f,0.00f,0.00f,0.00f}, + {0.25f,0.25f,0.25f,0.25f}, + {0.50f,0.50f,0.50f,0.50f}, + {0.75f,0.75f,0.75f,0.75f}, + }; + + LLColor4 specColor = alpha[tex_entry->getShiny() & TEM_SHINY_MASK]; + F32 env = specColor.mV[0]; + + if (!mat->getSpecularID().isNull()) + { + const auto& spec_light_col = mat->getSpecularLightColor(); + specColor.mV[0] = spec_light_col.mV[0]; + specColor.mV[1] = spec_light_col.mV[1]; + specColor.mV[2] = spec_light_col.mV[2]; + specColor.mV[3] = mat->getSpecularLightExponent(); + env = mat->getEnvironmentIntensity(); + } + + BOOL fullbright = tex_entry->getFullbright(); + + sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f); + sVertexProgram->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specColor.mV); + sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env); + + if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()); + } + else + { + sVertexProgram->setMinimumAlpha(0.f); + } + + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + LLViewerTexture* tex = face->getTexture(i); + if (tex) + { + tex->addTextureStats(avatar->getPixelArea()); + } + } + } + else + { + gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); + sVertexProgram->setMinimumAlpha(0.f); + if (normal_channel > -1) + { + LLDrawPoolBump::bindBumpMap(face, normal_channel); + } + } + + if (face->mTextureMatrix && vobj->mTexAnimMode) + { + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix); + buff->setBuffer(data_mask); + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + else + { + buff->setBuffer(data_mask); + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + + gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES); + } + } +} + +void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_DEFERRED_SIMPLE); +} + +void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_DEFERRED_BUMP); +} + +void LLDrawPoolAvatar::renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass) +{ + renderRigged(avatar, pass); +} + +static LLTrace::BlockTimerStatHandle FTM_RIGGED_VBO("Rigged VBO"); + +void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) +{ + LL_RECORD_BLOCK_TIME(FTM_RIGGED_VBO); + + //update rigged vertex buffers + for (auto& type : mRiggedFace) + { + for (LLFace* face : type) + { + LLDrawable* drawable = face->getDrawable(); + if (!drawable) + { + continue; + } + + LLVOVolume* vobj = drawable->getVOVolume(); + + if (!vobj || vobj->isNoLOD()) + { + continue; + } + + LLVolume* volume = vobj->getVolume(); + S32 te = face->getTEOffset(); + + if (!volume || volume->getNumVolumeFaces() <= te) + { + continue; + } + + const LLMeshSkinInfo* skin = vobj->getSkinInfo(); + if (!skin) + { + continue; + } + + stop_glerror(); + + const LLVolumeFace& vol_face = volume->getVolumeFace(te); + updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); + } + } +} + +void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_SIMPLE); +} + +void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_FULLBRIGHT); +} + + +void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_SHINY); +} + +void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY); +} + +void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) +{ + if (!mRiggedFace[RIGGED_ALPHA].empty()) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + renderRigged(avatar, RIGGED_ALPHA); + gGL.setSceneBlendType(LLRender::BT_ALPHA); // <alchemy/> + gGL.setColorMask(true, false); + } +} + +void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) +{ + if (!mRiggedFace[RIGGED_FULLBRIGHT_ALPHA].empty()) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); + gGL.setSceneBlendType(LLRender::BT_ALPHA); // <alchemy/> + gGL.setColorMask(true, false); + } +} + +void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) +{ + if (!mRiggedFace[RIGGED_GLOW].empty()) + { + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.flush(); + + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.setColorMask(false, true); + + renderRigged(avatar, RIGGED_GLOW, true); + + gGL.setColorMask(true, false); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } +} + + + +//----------------------------------------------------------------------------- +// getDebugTexture() +//----------------------------------------------------------------------------- +LLViewerTexture *LLDrawPoolAvatar::getDebugTexture() +{ + if (mReferences.empty()) + { + return nullptr; + } + LLFace *face = mReferences[0]; + if (!face->getDrawable()) + { + return nullptr; + } + const LLViewerObject *objectp = face->getDrawable()->getVObj(); + + // Avatar should always have at least 1 (maybe 3?) TE's. + return objectp->getTEImage(0); +} + + +LLColor3 LLDrawPoolAvatar::getDebugColor() const +{ + return LLColor3(0.f, 1.f, 0.f); +} + +void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type) +{ + llassert (facep->isState(LLFace::RIGGED)); + llassert(getType() == LLDrawPool::POOL_AVATAR); + if (facep->getPool() && facep->getPool() != this) + { + LL_ERRS() << "adding rigged face that's already in another pool" << LL_ENDL; + } + if (type >= NUM_RIGGED_PASSES) + { + LL_ERRS() << "Invalid rigged face type." << LL_ENDL; + } + if (facep->getRiggedIndex(type) != -1) + { + LL_ERRS() << "Tried to add a rigged face that's referenced elsewhere." << LL_ENDL; + } + + facep->setRiggedIndex(type, mRiggedFace[type].size()); + facep->setPool(this); + mRiggedFace[type].push_back(facep); + + facep->mShinyInAlpha = type == RIGGED_DEFERRED_SIMPLE || type == RIGGED_DEFERRED_BUMP || type == RIGGED_FULLBRIGHT_SHINY || type == RIGGED_SHINY; +} + +void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep) +{ + llassert (facep->isState(LLFace::RIGGED)); + llassert(getType() == LLDrawPool::POOL_AVATAR); + if (facep->getPool() != this) + { + LL_ERRS() << "Tried to remove a rigged face from the wrong pool" << LL_ENDL; + } + facep->setPool(nullptr); + + for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) + { + S32 index = facep->getRiggedIndex(i); + + if (index > -1) + { + if (mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep) + { + facep->setRiggedIndex(i,-1); + mRiggedFace[i].erase(mRiggedFace[i].begin()+index); + for (U32 j = index; j < mRiggedFace[i].size(); ++j) + { //bump indexes down for faces referenced after erased face + mRiggedFace[i][j]->setRiggedIndex(i, j); + } + } + else + { + LL_ERRS() << "Face reference data corrupt for rigged type " << i + << ((mRiggedFace[i].size() <= index) ? "; wrong index (out of bounds)" : (mRiggedFace[i][index] != facep) ? "; wrong face pointer" : "") + << LL_ENDL; + } + } + } +} + +LLVertexBufferAvatar::LLVertexBufferAvatar() +: LLVertexBuffer(sDataMask, + GL_STREAM_DRAW_ARB) //avatars are always stream draw due to morph targets +{ + +} + + diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index eb72b5fcac847978c17c0bb288e06c50aeeed321..8aa41dece874761edc0bff8c7ed625340566032b 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -91,9 +91,9 @@ private: U32 te; LLMaterialID materialID; - template <typename H> - friend H AbslHashValue(H h, const TEMaterialPair& m) { - return H::combine(std::move(h), m.materialID, m.te); + template <typename H> + friend H AbslHashValue(H h, const TEMaterialPair& m) { + return H::combine(std::move(h), m.materialID, m.te); } bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 755093a40ce97b1f75a9794ac0626d1c50de131a..ec639333ec25e87826c64dc983081a55492ba0b9 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1,4163 +1,4163 @@ -/** - * @file llspatialpartition.cpp - * @brief LLSpatialGroup class implementation and supporting functions - * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llspatialpartition.h" - -#include "llappviewer.h" -#include "llcallstack.h" -#include "lltexturecache.h" -#include "lltexturefetch.h" -#include "llimageworker.h" -#include "llviewerwindow.h" -#include "llviewerobjectlist.h" -#include "llvovolume.h" -#include "llvolume.h" -#include "llvolumeoctree.h" -#include "llviewercamera.h" -#include "llface.h" -#include "llfloatertools.h" -#include "llviewercontrol.h" -#include "llviewerregion.h" -#include "llcamera.h" -#include "pipeline.h" -#include "llmeshrepository.h" -#include "llrender.h" -#include "lloctree.h" -#include "llphysicsshapebuilderutil.h" -#include "llvoavatar.h" -#include "llvolumemgr.h" -#include "llviewershadermgr.h" -#include "llcontrolavatar.h" -#include "llfloaterreg.h" // <alchemy/> - -//#pragma optimize("", off) - -static LLTrace::BlockTimerStatHandle FTM_FRUSTUM_CULL("Frustum Culling"); -static LLTrace::BlockTimerStatHandle FTM_CULL_REBOUND("Cull Rebound Partition"); - -extern bool gShiftFrame; - -static U32 sZombieGroups = 0; -U32 LLSpatialGroup::sNodeCount = 0; - -BOOL LLSpatialGroup::sNoDelete = FALSE; - -static F32 sLastMaxTexPriority = 1.f; -static F32 sCurMaxTexPriority = 1.f; - -BOOL LLSpatialPartition::sTeleportRequested = FALSE; - -//static counter for frame to switch LOD on - -void sg_assert(BOOL expr) -{ -#if LL_OCTREE_PARANOIA_CHECK - if (!expr) - { - LL_ERRS() << "Octree invalid!" << LL_ENDL; - } -#endif -} - -//returns: -// 0 if sphere and AABB are not intersecting -// 1 if they are -// 2 if AABB is entirely inside sphere - -S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3& pos, const F32 &rad) -{ - S32 ret = 2; - - LLVector3 min = center - size; - LLVector3 max = center + size; - for (U32 i = 0; i < 3; i++) - { - if (min.mV[i] > pos.mV[i] + rad || - max.mV[i] < pos.mV[i] - rad) - { //totally outside - return 0; - } - - if (min.mV[i] < pos.mV[i] - rad || - max.mV[i] > pos.mV[i] + rad) - { //intersecting - ret = 1; - } - } - - return ret; -} - -LLSpatialGroup::~LLSpatialGroup() -{ - /*if (sNoDelete) - { - LL_ERRS() << "Illegal deletion of LLSpatialGroup!" << LL_ENDL; - }*/ - - if (gDebugGL) - { - gPipeline.checkReferences(this); - } - - if (hasState(DEAD)) - { - sZombieGroups--; - } - - sNodeCount--; - - clearDrawMap(); -} - -void LLSpatialGroup::clearDrawMap() -{ - mDrawMap.clear(); -} - -BOOL LLSpatialGroup::isHUDGroup() -{ - return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ; -} - -void LLSpatialGroup::validate() -{ - ll_assert_aligned(this,64); -#if LL_OCTREE_PARANOIA_CHECK - - sg_assert(!isState(DIRTY)); - sg_assert(!isDead()); - - LLVector4a myMin; - myMin.setSub(mBounds[0], mBounds[1]); - LLVector4a myMax; - myMax.setAdd(mBounds[0], mBounds[1]); - - validateDrawMap(); - - for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) - { - LLDrawable* drawable = *i; - sg_assert(drawable->getSpatialGroup() == this); - if (drawable->getSpatialBridge()) - { - sg_assert(drawable->getSpatialBridge() == getSpatialPartition()->asBridge()); - } - - /*if (drawable->isSpatialBridge()) - { - LLSpatialPartition* part = drawable->asPartition(); - if (!part) - { - LL_ERRS() << "Drawable reports it is a spatial bridge but not a partition." << LL_ENDL; - } - LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); - group->validate(); - }*/ - } - - for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i) - { - LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0); - - group->validate(); - - //ensure all children are enclosed in this node - LLVector4a center = group->mBounds[0]; - LLVector4a size = group->mBounds[1]; - - LLVector4a min; - min.setSub(center, size); - LLVector4a max; - max.setAdd(center, size); - - for (U32 j = 0; j < 3; j++) - { - sg_assert(min[j] >= myMin[j]-0.02f); - sg_assert(max[j] <= myMax[j]+0.02f); - } - } - -#endif -} - -void LLSpatialGroup::validateDrawMap() -{ -#if LL_OCTREE_PARANOIA_CHECK - for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i) - { - LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; - for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) - { - LLDrawInfo& params = **j; - - params.validate(); - } - } -#endif -} - -BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) -{ - drawablep->updateSpatialExtents(); - - OctreeNode* parent = mOctreeNode->getOctParent(); - - if (mOctreeNode->isInside(drawablep->getPositionGroup()) && - (mOctreeNode->contains(drawablep->getEntry()) || - (drawablep->getBinRadius() > mOctreeNode->getSize()[0] && - parent && parent->getElementCount() >= gOctreeMaxCapacity))) - { - unbound(); - setState(OBJECT_DIRTY); - //setState(GEOM_DIRTY); - return TRUE; - } - - return FALSE; -} - - -BOOL LLSpatialGroup::addObject(LLDrawable *drawablep) -{ - if(!drawablep) - { - return FALSE; - } - { - drawablep->setGroup(this); - setState(OBJECT_DIRTY | GEOM_DIRTY); - setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); - gPipeline.markRebuild(this, TRUE); - if (drawablep->isSpatialBridge()) - { - mBridgeList.push_back((LLSpatialBridge*) drawablep); - } - if (drawablep->getRadius() > 1.f) - { - setState(IMAGE_DIRTY); - } - } - - return TRUE; -} - -void LLSpatialGroup::rebuildGeom() -{ - if (!isDead()) - { - getSpatialPartition()->rebuildGeom(this); - - if (hasState(LLSpatialGroup::MESH_DIRTY)) - { - gPipeline.markMeshDirty(this); - } - } -} - -void LLSpatialGroup::rebuildMesh() -{ - if (!isDead()) - { - getSpatialPartition()->rebuildMesh(this); - } -} - -static LLTrace::BlockTimerStatHandle FTM_REBUILD_VBO("VBO Rebuilt"); -static LLTrace::BlockTimerStatHandle FTM_ADD_GEOMETRY_COUNT("Add Geometry"); -static LLTrace::BlockTimerStatHandle FTM_CREATE_VB("Create VB"); -static LLTrace::BlockTimerStatHandle FTM_GET_GEOMETRY("Get Geometry"); - -void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) -{ - if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY)) - { - return; - } - - if (group->changeLOD()) - { - group->mLastUpdateDistance = group->mDistance; - group->mLastUpdateViewAngle = group->mViewAngle; - } - - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VBO); - - group->clearDrawMap(); - - //get geometry count - U32 index_count = 0; - U32 vertex_count = 0; - - { - LL_RECORD_BLOCK_TIME(FTM_ADD_GEOMETRY_COUNT); - addGeometryCount(group, vertex_count, index_count); - } - - if (vertex_count > 0 && index_count > 0) - { //create vertex buffer containing volume geometry for this node - { - LL_RECORD_BLOCK_TIME(FTM_CREATE_VB); - group->mBuilt = 1.f; - if (group->mVertexBuffer.isNull() || - !group->mVertexBuffer->isWriteable() || - (group->mBufferUsage != (U32)group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) - { - group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); - if (!group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true)) - { - LL_WARNS() << "Failed to allocate Vertex Buffer on rebuild to " - << vertex_count << " vertices and " - << index_count << " indices" << LL_ENDL; - group->mVertexBuffer = NULL; - group->mBufferMap.clear(); - } - stop_glerror(); - } - else - { - if (!group->mVertexBuffer->resizeBuffer(vertex_count, index_count)) - { - // Is likely to cause a crash. If this gets triggered find a way to avoid it (don't forget to reset face) - LL_WARNS() << "Failed to resize Vertex Buffer on rebuild to " - << vertex_count << " vertices and " - << index_count << " indices" << LL_ENDL; - group->mVertexBuffer = NULL; - group->mBufferMap.clear(); - } - stop_glerror(); - } - } - - if (group->mVertexBuffer) - { - LL_RECORD_BLOCK_TIME(FTM_GET_GEOMETRY); - getGeometry(group); - } - } - else - { - group->mVertexBuffer = NULL; - group->mBufferMap.clear(); - } - - group->mLastUpdateTime = gFrameTimeSeconds; - group->clearState(LLSpatialGroup::GEOM_DIRTY); -} - - -void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group) -{ - -} - -LLSpatialGroup* LLSpatialGroup::getParent() -{ - return (LLSpatialGroup*)LLViewerOctreeGroup::getParent(); - } - -BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) - { - if(!drawablep) - { - return FALSE; - } - - unbound(); - if (mOctreeNode && !from_octree) - { - drawablep->setGroup(NULL); - } - else - { - drawablep->setGroup(NULL); - setState(GEOM_DIRTY); - gPipeline.markRebuild(this, TRUE); - - if (drawablep->isSpatialBridge()) - { - for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i) - { - if (*i == drawablep) - { - mBridgeList.erase(i); - break; - } - } - } - - if (getElementCount() == 0) - { //delete draw map on last element removal since a rebuild might never happen - clearDrawMap(); - } - } - return TRUE; -} - -void LLSpatialGroup::shift(const LLVector4a &offset) -{ - LLVector4a t = mOctreeNode->getCenter(); - t.add(offset); - mOctreeNode->setCenter(t); - mOctreeNode->updateMinMax(); - mBounds[0].add(offset); - mExtents[0].add(offset); - mExtents[1].add(offset); - mObjectBounds[0].add(offset); - mObjectExtents[0].add(offset); - mObjectExtents[1].add(offset); - - if (!getSpatialPartition()->mRenderByGroup && - getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TREE && - getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && - getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE) - { - setState(GEOM_DIRTY); - gPipeline.markRebuild(this, TRUE); - } -} - -class LLSpatialSetState : public OctreeTraveler -{ -public: - U32 mState; - LLSpatialSetState(U32 state) : mState(state) { } - void visit(const OctreeNode* branch) final override { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } -}; - -class LLSpatialSetStateDiff final : public LLSpatialSetState -{ -public: - LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { } - - void traverse(const OctreeNode* n) override - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (!group->hasState(mState)) - { - OctreeTraveler::traverse(n); - } - } -}; - -void LLSpatialGroup::setState(U32 state, S32 mode) -{ - llassert(state <= LLSpatialGroup::STATE_MASK); - - if (mode > STATE_MODE_SINGLE) - { - if (mode == STATE_MODE_DIFF) - { - LLSpatialSetStateDiff setter(state); - setter.traverse(mOctreeNode); - } - else - { - LLSpatialSetState setter(state); - setter.traverse(mOctreeNode); - } - } - else - { - mState |= state; - } -} - -class LLSpatialClearState : public OctreeTraveler -{ -public: - U32 mState; - LLSpatialClearState(U32 state) : mState(state) { } - void visit(const OctreeNode* branch) final override { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } -}; - -class LLSpatialClearStateDiff final : public LLSpatialClearState -{ -public: - LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { } - - void traverse(const OctreeNode* n) override - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (group->hasState(mState)) - { - OctreeTraveler::traverse(n); - } - } -}; - -void LLSpatialGroup::clearState(U32 state, S32 mode) -{ - llassert(state <= LLSpatialGroup::STATE_MASK); - - if (mode > STATE_MODE_SINGLE) - { - if (mode == STATE_MODE_DIFF) - { - LLSpatialClearStateDiff clearer(state); - clearer.traverse(mOctreeNode); - } - else - { - LLSpatialClearState clearer(state); - clearer.traverse(mOctreeNode); - } - } - else - { - mState &= ~state; - } -} - -//====================================== -// Octree Listener Implementation -//====================================== - -LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLOcclusionCullingGroup(node, part), - mObjectBoxSize(1.f), - mGeometryBytes(0), - mSurfaceArea(0.f), - mBuilt(0.f), - mVertexBuffer(NULL), - mBufferUsage(part->mBufferUsage), - mDistance(0.f), - mDepth(0.f), - mLastUpdateDistance(-1.f), - mLastUpdateTime(gFrameTimeSeconds) -{ - ll_assert_aligned(this,16); - - sNodeCount++; - - mViewAngle.splat(0.f); - mLastUpdateViewAngle.splat(-1.f); - - sg_assert(mOctreeNode->getListenerCount() == 0); - setState(SG_INITIAL_STATE_MASK); - gPipeline.markRebuild(this, TRUE); - - mRadius = 1; - mPixelArea = 1024.f; -} - -void LLSpatialGroup::updateDistance(LLCamera &camera) -{ - if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) - { - LL_WARNS() << "Attempted to update distance for camera other than world camera!" << LL_ENDL; - return; - } - - if (gShiftFrame) - { - return; - } - -#if !LL_RELEASE_FOR_DOWNLOAD - if (hasState(LLSpatialGroup::OBJECT_DIRTY)) - { - LL_ERRS() << "Spatial group dirty on distance update." << LL_ENDL; - } -#endif - if (!isEmpty()) - { - mRadius = getSpatialPartition()->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : - (F32) mOctreeNode->getSize().getLength3().getF32(); - mDistance = getSpatialPartition()->calcDistance(this, camera); - mPixelArea = getSpatialPartition()->calcPixelArea(this, camera); - } -} - -F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) -{ - LLVector4a eye; - LLVector4a origin; - origin.load3(camera.getOrigin().mV); - - eye.setSub(group->mObjectBounds[0], origin); - - F32 dist = 0.f; - - if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end()) - { - LLVector4a v = eye; - - dist = eye.getLength3().getF32(); - eye.normalize3fast(); - - if (!group->hasState(LLSpatialGroup::ALPHA_DIRTY)) - { - if (!group->getSpatialPartition()->isBridge()) - { - LLVector4a view_angle = eye; - - LLVector4a diff; - diff.setSub(view_angle, group->mLastUpdateViewAngle); - - if (diff.getLength3().getF32() > 0.64f) - { - group->mViewAngle = view_angle; - group->mLastUpdateViewAngle = view_angle; - //for occasional alpha sorting within the group - //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, - //not setting this node to dirty would be a very good thing - group->setState(LLSpatialGroup::ALPHA_DIRTY); - gPipeline.markRebuild(group, FALSE); - } - } - } - - //calculate depth of node for alpha sorting - - LLVector3 at = camera.getAtAxis(); - - LLVector4a ata; - ata.load3(at.mV); - - LLVector4a t = ata; - //front of bounding box - t.mul(0.25f); - t.mul(group->mObjectBounds[1]); - v.sub(t); - - group->mDepth = v.dot3(ata).getF32(); - } - else - { - dist = eye.getLength3().getF32(); - } - - LL_DEBUGS("RiggedBox") << "calcDistance, group " << group << " camera " << origin << " obj bounds " - << group->mObjectBounds[0] << ", " << group->mObjectBounds[1] - << " dist " << dist << " radius " << group->mRadius << LL_ENDL; - - if (dist < 16.f) - { - dist /= 16.f; - dist *= dist; - dist *= 16.f; - } - - return dist; -} - -F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) -{ - return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); -} - -F32 LLSpatialGroup::getUpdateUrgency() const -{ - if (!isVisible()) - { - return 0.f; - } - else - { - F32 time = gFrameTimeSeconds-mLastUpdateTime+4.f; - return time + (mObjectBounds[1].dot3(mObjectBounds[1]).getF32()+1.f)/mDistance; - } -} - -BOOL LLSpatialGroup::changeLOD() -{ - if (hasState(ALPHA_DIRTY | OBJECT_DIRTY)) - { - //a rebuild is going to happen, update distance and LoD - return TRUE; - } - - if (getSpatialPartition()->mSlopRatio > 0.f) - { - F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius)); - - // MAINT-8264 - this check is not robust if it needs to work - // for bounding boxes much larger than the actual enclosed - // objects, and using distance to box center is also - // problematic. Consider the case that you have a large box - // where the enclosed object is in one corner. As you zoom in - // on the corner, the object gets much closer to the camera, - // but the distance to the box center changes very little, and - // an LOD change will not trigger, so object LOD gets "stuck" - // at a too-low value. In the case of the above JIRA, the box - // was large only due to another error, so this logic did not - // need to be changed. - - if (fabsf(ratio) >= getSpatialPartition()->mSlopRatio) - { - LL_DEBUGS("RiggedBox") << "changeLOD true because of ratio compare " - << fabsf(ratio) << " " << getSpatialPartition()->mSlopRatio << LL_ENDL; - LL_DEBUGS("RiggedBox") << "sg " << this << "\nmDistance " << mDistance - << " mLastUpdateDistance " << mLastUpdateDistance - << " mRadius " << mRadius - << " fab ratio " << fabsf(ratio) - << " slop " << getSpatialPartition()->mSlopRatio << LL_ENDL; - - return TRUE; - } - - if (mDistance > mRadius*2.f) - { - return FALSE; - } - } - - if (needsUpdate()) - { - return TRUE; - } - - return FALSE; -} - -void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry) -{ - addObject((LLDrawable*)entry->getDrawable()); - unbound(); - setState(OBJECT_DIRTY); -} - -void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry) -{ - removeObject((LLDrawable*)entry->getDrawable(), TRUE); - LLViewerOctreeGroup::handleRemoval(node, entry); -} - -void LLSpatialGroup::handleDestruction(const TreeNode* node) -{ - if(isDead()) - { - return; - } - setState(DEAD); - - for (element_iter i = getDataBegin(), i_end = getDataEnd(); i != i_end; ++i) - { - LLViewerOctreeEntry* entry = *i; - - if (entry->getGroup() == this) - { - if(entry->hasDrawable()) - { - ((LLDrawable*)entry->getDrawable())->setGroup(NULL); - } - } - } - - clearDrawMap(); - mVertexBuffer = NULL; - mBufferMap.clear(); - sZombieGroups++; - mOctreeNode = NULL; -} - -void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) -{ - if (child->getListenerCount() == 0) - { - new LLSpatialGroup(child, getSpatialPartition()); - } - else - { - OCT_ERRS << "LLSpatialGroup redundancy detected." << LL_ENDL; - } - - unbound(); - - assert_states_valid(this); -} - -void LLSpatialGroup::destroyGL(bool keep_occlusion) -{ - setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); - - if (!keep_occlusion) - { //going to need a rebuild - gPipeline.markRebuild(this, TRUE); - } - - mLastUpdateTime = gFrameTimeSeconds; - mVertexBuffer = NULL; - mBufferMap.clear(); - - clearDrawMap(); - - if (!keep_occlusion) - { - releaseOcclusionQueryObjectNames(); - } - - - for (LLSpatialGroup::element_iter i = getDataBegin(), i_end = getDataEnd(); i != i_end; ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - for (S32 j = 0; j < drawable->getNumFaces(); j++) - { - LLFace* facep = drawable->getFace(j); - if (facep) - { - facep->clearVertexBuffer(); - } - } - } -} - -//============================================== - -LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage, LLViewerRegion* regionp) -: mBridge(NULL), mRenderByGroup(render_by_group) -{ - mRegionp = regionp; - mPartitionType = LLViewerRegion::PARTITION_NONE; - mVertexDataMask = data_mask; - mBufferUsage = buffer_usage; - mDepthMask = FALSE; - mSlopRatio = 0.25f; - mInfiniteFarClip = FALSE; - - new LLSpatialGroup(mOctree, this); -} - -LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) -{ - drawablep->updateSpatialExtents(); - - //keep drawable from being garbage collected - LLPointer<LLDrawable> ptr = drawablep; - - if(!drawablep->getGroup()) - { - assert_octree_valid(mOctree); - mOctree->insert(drawablep->getEntry()); - assert_octree_valid(mOctree); - } - - LLSpatialGroup* group = drawablep->getSpatialGroup(); - llassert(group != NULL); - - if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING)) - { - group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); - } - - return group; -} - -BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) -{ - if (!curp->removeObject(drawablep)) - { - OCT_ERRS << "Failed to remove drawable from octree!" << LL_ENDL; - } - else - { - drawablep->setGroup(NULL); - } - - assert_octree_valid(mOctree); - - return TRUE; -} - -void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate) -{ - // sanity check submitted by open source user bushing Spatula - // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne) - if (!drawablep) - { - OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << LL_ENDL; - return; - } - - BOOL was_visible = curp ? curp->isVisible() : FALSE; - - if (curp && curp->getSpatialPartition() != this) - { - //keep drawable from being garbage collected - LLPointer<LLDrawable> ptr = drawablep; - if (curp->getSpatialPartition()->remove(drawablep, curp)) - { - put(drawablep, was_visible); - return; - } - else - { - OCT_ERRS << "Drawable lost between spatial partitions on outbound transition." << LL_ENDL; - } - } - - if (curp && curp->updateInGroup(drawablep, immediate)) - { - // Already updated, don't need to do anything - assert_octree_valid(mOctree); - return; - } - - //keep drawable from being garbage collected - LLPointer<LLDrawable> ptr = drawablep; - if (curp && !remove(drawablep, curp)) - { - OCT_ERRS << "Move couldn't find existing spatial group!" << LL_ENDL; - } - - put(drawablep, was_visible); -} - -class LLSpatialShift final : public OctreeTraveler -{ -public: - const LLVector4a& mOffset; - - LLSpatialShift(const LLVector4a& offset) : mOffset(offset) { } - - void visit(const OctreeNode* branch) override - { - ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); - } -}; - -void LLSpatialPartition::shift(const LLVector4a &offset) -{ //shift octree node bounding boxes by offset - LLSpatialShift shifter(offset); - shifter.traverse(mOctree); -} - -class LLOctreeCull : public LLViewerOctreeCull -{ -public: - LLOctreeCull(LLCamera* camera) : LLViewerOctreeCull(camera) {} - - bool earlyFail(LLViewerOctreeGroup* base_group) override - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - group->checkOcclusion(); - - if (group->getOctreeNode()->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - gPipeline.markOccluder(group); - return true; - } - - return false; - } - - S32 frustumCheck(const LLViewerOctreeGroup* group) override - { - S32 res = AABBInFrustumNoFarClipGroupBounds(group); - if (res != 0) - { - res = llmin(res, AABBSphereIntersectGroupExtents(group)); - } - return res; - } - - S32 frustumCheckObjects(const LLViewerOctreeGroup* group) override - { - S32 res = AABBInFrustumNoFarClipObjectBounds(group); - if (res != 0) - { - res = llmin(res, AABBSphereIntersectObjectExtents(group)); - } - return res; - } - - void processGroup(LLViewerOctreeGroup* base_group) override - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - if (group->needsUpdate() || - group->getVisible(LLViewerCamera::sCurCameraID) < LLDrawable::getCurrentFrame() - 1) - { - group->doOcclusion(mCamera); - } - gPipeline.markNotCulled(group, *mCamera); - } -}; - -class LLOctreeCullNoFarClip final : public LLOctreeCull -{ -public: - LLOctreeCullNoFarClip(LLCamera* camera) - : LLOctreeCull(camera) { } - - S32 frustumCheck(const LLViewerOctreeGroup* group) override - { - return AABBInFrustumNoFarClipGroupBounds(group); - } - - S32 frustumCheckObjects(const LLViewerOctreeGroup* group) override - { - S32 res = AABBInFrustumNoFarClipObjectBounds(group); - return res; - } -}; - -class LLOctreeCullShadow : public LLOctreeCull -{ -public: - LLOctreeCullShadow(LLCamera* camera) - : LLOctreeCull(camera) { } - - S32 frustumCheck(const LLViewerOctreeGroup* group) final override - { - return AABBInFrustumGroupBounds(group); - } - - S32 frustumCheckObjects(const LLViewerOctreeGroup* group) final override - { - return AABBInFrustumObjectBounds(group); - } -}; - -class LLOctreeCullVisExtents final: public LLOctreeCullShadow -{ -public: - LLOctreeCullVisExtents(LLCamera* camera, LLVector4a& min, LLVector4a& max) - : LLOctreeCullShadow(camera), mEmpty(TRUE), mMin(min), mMax(max) { } - - bool earlyFail(LLViewerOctreeGroup* base_group) override - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - - if (group->getOctreeNode()->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - return true; - } - - return false; - } - - void traverse(const OctreeNode* n) override - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (earlyFail(group)) - { - return; - } - - if ((mRes && group->hasState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || - mRes == 2) - { //don't need to do frustum check - OctreeTraveler::traverse(n); - } - else - { - mRes = frustumCheck(group); - - if (mRes) - { //at least partially in, run on down - OctreeTraveler::traverse(n); - } - - mRes = 0; - } - } - - void processGroup(LLViewerOctreeGroup* base_group) override - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - - llassert(!group->hasState(LLSpatialGroup::DIRTY) && !group->isEmpty()); - - if (mRes < 2) - { - if (AABBInFrustumObjectBounds(group) > 0) - { - mEmpty = FALSE; - const LLVector4a* exts = group->getObjectExtents(); - update_min_max(mMin, mMax, exts[0]); - update_min_max(mMin, mMax, exts[1]); - } - } - else - { - mEmpty = FALSE; - const LLVector4a* exts = group->getExtents(); - update_min_max(mMin, mMax, exts[0]); - update_min_max(mMin, mMax, exts[1]); - } - } - - BOOL mEmpty; - LLVector4a& mMin; - LLVector4a& mMax; -}; - -class LLOctreeCullDetectVisible final: public LLOctreeCullShadow -{ -public: - LLOctreeCullDetectVisible(LLCamera* camera) - : LLOctreeCullShadow(camera), mResult(FALSE) { } - - bool earlyFail(LLViewerOctreeGroup* base_group) override - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - - if (mResult || //already found a node, don't check any more - (group->getOctreeNode()->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isOcclusionState(LLSpatialGroup::OCCLUDED))) - { - return true; - } - - return false; - } - - void processGroup(LLViewerOctreeGroup* base_group) override - { - if (base_group->isVisible()) - { - mResult = TRUE; - } - } - - BOOL mResult; -}; - -class LLOctreeSelect final : public LLOctreeCull -{ -public: - LLOctreeSelect(LLCamera* camera, std::vector<LLDrawable*>* results) - : LLOctreeCull(camera), mResults(results) { } - - bool earlyFail(LLViewerOctreeGroup* group) override { return false; } - void preprocess(LLViewerOctreeGroup* group) override { } - - void processGroup(LLViewerOctreeGroup* base_group) override - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - OctreeNode* branch = group->getOctreeNode(); - - for (OctreeNode::const_element_iter i = branch->getDataBegin(), i_end = branch->getDataEnd(); i != i_end; ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - if (!drawable->isDead()) - { - if (drawable->isSpatialBridge()) - { - drawable->setVisible(*mCamera, mResults, TRUE); - } - else - { - mResults->push_back(drawable); - } - } - } - } - - std::vector<LLDrawable*>* mResults; -}; - -void drawBox(const LLVector3& c, const LLVector3& r) -{ - LLVertexBuffer::unbind(); - - gGL.begin(LLRender::TRIANGLE_STRIP); - //left front - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); - //right front - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); - //right back - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); - //left back - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); - //left front - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); - gGL.end(); - - //bottom - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); - gGL.end(); - - //top - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); - gGL.end(); -} - -void drawBox(const LLVector4a& c, const LLVector4a& r) -{ - drawBox(reinterpret_cast<const LLVector3&>(c), reinterpret_cast<const LLVector3&>(r)); -} - -void drawBoxOutline(const LLVector3& pos, const LLVector3& size) -{ - - llassert(pos.isFinite()); - llassert(size.isFinite()); - - llassert(!llisnan(pos.mV[0])); - llassert(!llisnan(pos.mV[1])); - llassert(!llisnan(pos.mV[2])); - - llassert(!llisnan(size.mV[0])); - llassert(!llisnan(size.mV[1])); - llassert(!llisnan(size.mV[2])); - - LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); - LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); - LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); - LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1)); - - gGL.begin(LLRender::LINES); - - //top - gGL.vertex3fv((pos+v1).mV); - gGL.vertex3fv((pos+v2).mV); - gGL.vertex3fv((pos+v2).mV); - gGL.vertex3fv((pos+v3).mV); - gGL.vertex3fv((pos+v3).mV); - gGL.vertex3fv((pos+v4).mV); - gGL.vertex3fv((pos+v4).mV); - gGL.vertex3fv((pos+v1).mV); - - //bottom - gGL.vertex3fv((pos-v1).mV); - gGL.vertex3fv((pos-v2).mV); - gGL.vertex3fv((pos-v2).mV); - gGL.vertex3fv((pos-v3).mV); - gGL.vertex3fv((pos-v3).mV); - gGL.vertex3fv((pos-v4).mV); - gGL.vertex3fv((pos-v4).mV); - gGL.vertex3fv((pos-v1).mV); - - //right - gGL.vertex3fv((pos+v1).mV); - gGL.vertex3fv((pos-v3).mV); - - gGL.vertex3fv((pos+v4).mV); - gGL.vertex3fv((pos-v2).mV); - - //left - gGL.vertex3fv((pos+v2).mV); - gGL.vertex3fv((pos-v4).mV); - - gGL.vertex3fv((pos+v3).mV); - gGL.vertex3fv((pos-v1).mV); - - gGL.end(); -} - -void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size) -{ - drawBoxOutline(reinterpret_cast<const LLVector3&>(pos), reinterpret_cast<const LLVector3&>(size)); -} - -class LLOctreeDirty final : public OctreeTraveler -{ -public: - LLOctreeDirty(bool no_rebuild) : mNoRebuild(no_rebuild){} - - void visit(const OctreeNode* state) override - { - LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); - group->destroyGL(); - - for (LLSpatialGroup::element_iter i = group->getDataBegin(), i_end = group->getDataEnd(); i != i_end; ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - if (drawable->getVObj().notNull()) - { - drawable->getVObj()->resetVertexBuffers(); - } - if (!mNoRebuild && drawable->getVObj().notNull() && !group->getSpatialPartition()->mRenderByGroup) - { - gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE); - } - } - - for (LLSpatialBridge* bridge : group->mBridgeList) - { - traverse(bridge->mOctree); - } - } - -private: - BOOL mNoRebuild; -}; - -void LLSpatialPartition::restoreGL() -{ -} - -void LLSpatialPartition::resetVertexBuffers() -{ - LLOctreeDirty dirty(sTeleportRequested); - dirty.traverse(mOctree); -} - -BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) -{ - LLVector4a visMina, visMaxa; - visMina.load3(visMin.mV); - visMaxa.load3(visMax.mV); - - { - LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); - LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); - group->rebound(); - } - - LLOctreeCullVisExtents vis(&camera, visMina, visMaxa); - vis.traverse(mOctree); - - visMin.set(visMina.getF32ptr()); - visMax.set(visMaxa.getF32ptr()); - return vis.mEmpty; -} - -BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera) -{ - LLOctreeCullDetectVisible vis(&camera); - vis.traverse(mOctree); - return vis.mResult; -} - -S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select) -{ -#if LL_OCTREE_PARANOIA_CHECK - ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); -#endif - { - LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); - LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); - group->rebound(); - } - -#if LL_OCTREE_PARANOIA_CHECK - ((LLSpatialGroup*)mOctree->getListener(0))->validate(); -#endif - - LLOctreeSelect selecter(&camera, results); - selecter.traverse(mOctree); - - return 0; - } - -S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion) -{ -#if LL_OCTREE_PARANOIA_CHECK - ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); -#endif - { - LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); - LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); - group->rebound(); - } - -#if LL_OCTREE_PARANOIA_CHECK - ((LLSpatialGroup*)mOctree->getListener(0))->validate(); -#endif - - if (LLPipeline::sShadowRender) - { - LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); - LLOctreeCullShadow culler(&camera); - culler.traverse(mOctree); - } - else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) - { - LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); - LLOctreeCullNoFarClip culler(&camera); - culler.traverse(mOctree); - } - else - { - LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); - LLOctreeCull culler(&camera); - culler.traverse(mOctree); - } - - return 0; -} - -void pushVerts(LLDrawInfo* params, U32 mask) -{ - LLRenderPass::applyModelMatrix(*params); - params->mVertexBuffer->setBuffer(mask); - params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES, - params->mStart, params->mEnd, params->mCount, params->mOffset); -} - -void pushVerts(LLSpatialGroup* group, U32 mask) -{ - for (auto& pair : group->mDrawMap) - { - for (LLDrawInfo* params : pair.second) - { - pushVerts(params, mask); - } - } -} - -void pushVerts(LLFace* face, U32 mask) -{ - if (face) - { - llassert(face->verify()); - - LLVertexBuffer* buffer = face->getVertexBuffer(); - - if (buffer && (face->getGeomCount() >= 3)) - { - buffer->setBuffer(mask); - U16 start = face->getGeomStart(); - U16 end = start + face->getGeomCount()-1; - U32 count = face->getIndicesCount(); - U16 offset = face->getIndicesStart(); - buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); - } - } -} - -void pushVerts(LLDrawable* drawable, U32 mask) -{ - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - pushVerts(drawable->getFace(i), mask); - } -} - -void pushVerts(LLVolume* volume) -{ - LLVertexBuffer::unbind(); - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = volume->getVolumeFace(i); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mNumVertices, face.mPositions, NULL, face.mNumIndices, face.mIndices); - } -} - -void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) -{ - if (buffer) - { - buffer->setBuffer(mask); - buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); - } -} - -void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true) -{ - if (group->getSpatialPartition()->mRenderByGroup) - { - if (!group->mDrawMap.empty()) - { - LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); - LLRenderPass::applyModelMatrix(*params); - - if (push_alpha) - { - pushBufferVerts(group->mVertexBuffer, mask); - } - - for (auto& buff_pair : group->mBufferMap) - { - for (auto& buff_tex_pair : buff_pair.second) - { - for (LLVertexBuffer* buff : buff_tex_pair.second) - { - pushBufferVerts(buff, mask); - } - } - } - } - } - /*else - { - //const LLVector4a* bounds = group->getBounds(); - //drawBox(bounds[0], bounds[1]); - }*/ -} - -void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) -{ - LLDrawInfo* params = NULL; - - static const std::array<LLColor4, 7> colors {{ - LLColor4::green, - LLColor4::green1, - LLColor4::green2, - LLColor4::green3, - LLColor4::green4, - LLColor4::green5, - LLColor4::green6 - }}; - - U32 col = 0; - - for (auto& i : group->mDrawMap) - { - for (auto& j : i.second) - { - params = j; - LLRenderPass::applyModelMatrix(*params); - gGL.diffuseColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f); - params->mVertexBuffer->setBuffer(mask); - params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES, - params->mStart, params->mEnd, params->mCount, params->mOffset); - col = (col+1)%colors.size(); - } - } -} - -void renderOctree(LLSpatialGroup* group) -{ - //render solid object bounding box, color - //coded by buffer usage and activity - gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); - LLVector4 col; - if (group->mBuilt > 0.f) - { - group->mBuilt -= 2.f * gFrameIntervalSeconds.value(); - if (group->mBufferUsage == GL_STATIC_DRAW_ARB) - { - col.setVec(1.0f, 0, 0, group->mBuilt*0.5f); - } - else - { - col.setVec(0.1f,0.1f,1,0.1f); - //col.setVec(1.0f, 1.0f, 0, sinf(group->mBuilt*3.14159f)*0.5f); - } - - if (group->mBufferUsage != GL_STATIC_DRAW_ARB) - { - LLGLDepthTest gl_depth(FALSE, FALSE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - gGL.diffuseColor4f(1,0,0,group->mBuilt); - gGL.flush(); - gGL.setLineWidth(5.f); - - const LLVector4a* bounds = group->getObjectBounds(); - drawBoxOutline(bounds[0], bounds[1]); - gGL.flush(); - gGL.setLineWidth(1.f); - gGL.flush(); - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - if (!group->getSpatialPartition()->isBridge()) - { - gGL.pushMatrix(); - LLVector3 trans = drawable->getRegion()->getOriginAgent(); - gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); - } - - for (S32 j = 0; j < drawable->getNumFaces(); j++) - { - LLFace* face = drawable->getFace(j); - if (face && face->getVertexBuffer()) - { - if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f) - { - gGL.diffuseColor4f(0, 1, 0, group->mBuilt); - } - else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f) - { - gGL.diffuseColor4f(1, 0, 0, group->mBuilt); - } - else - { - continue; - } - - face->getVertexBuffer()->setBuffer(LLVertexBuffer::MAP_VERTEX); - //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f, - // (face->mExtents[1]-face->mExtents[0])*0.5f); - face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart()); - } - } - - if (!group->getSpatialPartition()->isBridge()) - { - gGL.popMatrix(); - } - } - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - gGL.diffuseColor4f(1,1,1,1); - } - } - else - { - if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->isEmpty() - && group->getSpatialPartition()->mRenderByGroup) - { - col.setVec(0.8f, 0.4f, 0.1f, 0.1f); - } - else - { - col.setVec(0.1f, 0.1f, 1.f, 0.1f); - } - } - - gGL.diffuseColor4fv(col.mV); - LLVector4a fudge; - fudge.splat(0.001f); - - //LLVector4a size = group->mObjectBounds[1]; - //size.mul(1.01f); - //size.add(fudge); - - //{ - // LLGLDepthTest depth(GL_TRUE, GL_FALSE); - // drawBox(group->mObjectBounds[0], fudge); - //} - - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - //if (group->mBuilt <= 0.f) - { - //draw opaque outline - //gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], 1.f); - //drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); - - gGL.diffuseColor4f(0,1,1,1); - - const LLVector4a* bounds = group->getBounds(); - drawBoxOutline(bounds[0], bounds[1]); - - //draw bounding box for draw info - /*if (group->getSpatialPartition()->mRenderByGroup) - { - gGL.diffuseColor4f(1.0f, 0.75f, 0.25f, 0.6f); - for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) - { - for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) - { - LLDrawInfo* draw_info = *j; - LLVector4a center; - center.setAdd(draw_info->mExtents[1], draw_info->mExtents[0]); - center.mul(0.5f); - LLVector4a size; - size.setSub(draw_info->mExtents[1], draw_info->mExtents[0]); - size.mul(0.5f); - drawBoxOutline(center, size); - } - } - }*/ - } - -// LLSpatialGroup::OctreeNode* node = group->mOctreeNode; -// gGL.diffuseColor4f(0,1,0,1); -// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize())); -} - -std::set<LLSpatialGroup*> visible_selected_groups; - -void renderVisibility(LLSpatialGroup* group, LLCamera* camera) -{ - /*LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - LLGLEnable cull(GL_CULL_FACE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);*/ - - /*BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && - !group->isEmpty(); - - - if (render_objects) - { - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - - LLGLDisable blend(GL_BLEND); - gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f); - pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false); - - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - gGL.setLineWidth(4.f); - gGL.diffuseColor4f(0.f, 0.5f, 0.f, 1.f); - pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false); - gGL.setLineWidth(1.f); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - bool selected = false; - - for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) - { - LLDrawable* drawable = *iter; - if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) - { - selected = true; - break; - } - } - - if (selected) - { //store for rendering occlusion volume as overlay - visible_selected_groups.insert(group); - } - }*/ - - /*if (render_objects) - { - LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); - gGL.diffuseColor4f(0, 0.5f, 0, 0.5f); - pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); - } - - { - LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL); - - if (render_objects) - { - gGL.diffuseColor4f(0.f, 0.5f, 0.f,1.f); - pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); - } - - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - if (render_objects) - { - gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f); - pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); - - bool selected = false; - - for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) - { - LLDrawable* drawable = *iter; - if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) - { - selected = true; - break; - } - } - - if (selected) - { //store for rendering occlusion volume as overlay - visible_selected_groups.insert(group); - } - } - }*/ -} - -void renderXRay(LLSpatialGroup* group, LLCamera* camera) -{ - BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && - !group->isEmpty(); - - if (render_objects) - { - pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false); - - bool selected = false; - - for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) - { - LLDrawable* drawable = (LLDrawable*)(*iter)->getDrawable(); - if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) - { - selected = true; - break; - } - } - - if (selected) - { //store for rendering occlusion volume as overlay - - if (!group->getSpatialPartition()->isBridge()) - { - visible_selected_groups.insert(group); - } - else - { - visible_selected_groups.insert(group->getSpatialPartition()->asBridge()->getSpatialGroup()); - } - } - } -} - -void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color) -{ - gGL.color4fv(color.mV); - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); - gGL.vertex3fv((position + LLVector3(size, 0.f, 0.f)).mV); - gGL.vertex3fv((position - LLVector3(0.f, size, 0.f)).mV); - gGL.vertex3fv((position + LLVector3(0.f, size, 0.f)).mV); - gGL.vertex3fv((position - LLVector3(0.f, 0.f, size)).mV); - gGL.vertex3fv((position + LLVector3(0.f, 0.f, size)).mV); - } - gGL.end(); -} - -void renderUpdateType(LLDrawable* drawablep) -{ - LLViewerObject* vobj = drawablep->getVObj(); - if (!vobj || OUT_UNKNOWN == vobj->getLastUpdateType()) - { - return; - } - LLGLEnable blend(GL_BLEND); - switch (vobj->getLastUpdateType()) - { - case OUT_FULL: - gGL.diffuseColor4f(0,1,0,0.5f); - break; - case OUT_TERSE_IMPROVED: - gGL.diffuseColor4f(0,1,1,0.5f); - break; - case OUT_FULL_COMPRESSED: - if (vobj->getLastUpdateCached()) - { - gGL.diffuseColor4f(1,0,0,0.5f); - } - else - { - gGL.diffuseColor4f(1,1,0,0.5f); - } - break; - case OUT_FULL_CACHED: - gGL.diffuseColor4f(0,0,1,0.5f); - break; - default: - LL_WARNS() << "Unknown update_type " << vobj->getLastUpdateType() << LL_ENDL; - break; - }; - S32 num_faces = drawablep->getNumFaces(); - if (num_faces) - { - for (S32 i = 0; i < num_faces; ++i) - { - pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); - } - } -} - -void renderComplexityDisplay(LLDrawable* drawablep) -{ - LLViewerObject* vobj = drawablep->getVObj(); - if (!vobj) - { - return; - } - - LLVOVolume *voVol = vobj->asVolume();; - - if (!voVol) - { - return; - } - - if (!voVol->isRoot()) - { - return; - } - - LLVOVolume::texture_cost_t textures; - F32 cost = (F32) voVol->getRenderCost(textures); - - // add any child volumes - LLViewerObject::const_child_list_t children = voVol->getChildren(); - for (const auto& iter : children) - { - const LLViewerObject *child = iter; - const LLVOVolume *child_volume = dynamic_cast<const LLVOVolume*>(child); - if (child_volume) - { - cost += child_volume->getRenderCost(textures); - } - } - - // add texture cost - for (auto& texture : textures) - { - // add the cost of each individual texture in the linkset - cost += texture.second; - } - - F32 cost_max = (F32) LLVOVolume::getRenderComplexityMax(); - - - - // allow user to set a static color scale - if (gSavedSettings.getS32("RenderComplexityStaticMax") > 0) - { - cost_max = gSavedSettings.getS32("RenderComplexityStaticMax"); - } - - F32 cost_ratio = cost / cost_max; - - // cap cost ratio at 1.0f in case cost_max is at a low threshold - cost_ratio = cost_ratio > 1.0f ? 1.0f : cost_ratio; - - LLGLEnable blend(GL_BLEND); - - LLColor4 color; - const LLColor4 color_min = gSavedSettings.getColor4("RenderComplexityColorMin"); - const LLColor4 color_mid = gSavedSettings.getColor4("RenderComplexityColorMid"); - const LLColor4 color_max = gSavedSettings.getColor4("RenderComplexityColorMax"); - - if (cost_ratio < 0.5f) - { - color = color_min * (1 - cost_ratio * 2) + color_mid * (cost_ratio * 2); - } - else - { - color = color_mid * (1 - (cost_ratio - 0.5) * 2) + color_max * ((cost_ratio - 0.5) * 2); - } - - LLSD color_val = color.getValue(); - - // don't highlight objects below the threshold - if (cost > gSavedSettings.getS32("RenderComplexityThreshold")) - { - gGL.diffuseColor4f(color[0],color[1],color[2],0.5f); - - - S32 num_faces = drawablep->getNumFaces(); - if (num_faces) - { - for (S32 i = 0; i < num_faces; ++i) - { - pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); - } - } - LLViewerObject::const_child_list_t children = voVol->getChildren(); - for (const auto& iter : children) - { - const LLViewerObject *child = iter; - if (child) - { - num_faces = child->getNumFaces(); - if (num_faces) - { - for (S32 i = 0; i < num_faces; ++i) - { - pushVerts(child->mDrawable->getFace(i), LLVertexBuffer::MAP_VERTEX); - } - } - } - } - } - - voVol->setDebugText(llformat("%4.0f", cost)); -} - -void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) -{ - if (set_color) - { - if (drawable->isSpatialBridge()) - { - gGL.diffuseColor4f(1,0.5f,0,1); // orange - } - else if (drawable->getVOVolume()) - { - if (drawable->isRoot()) - { - gGL.diffuseColor4f(1,1,0,1); // yellow - } - else - { - gGL.diffuseColor4f(0,1,0,1); // green - } - } - else if (drawable->getVObj()) - { - switch (drawable->getVObj()->getPCode()) - { - case LLViewerObject::LL_VO_SURFACE_PATCH: - gGL.diffuseColor4f(0,1,1,1); // cyan - break; - case LLViewerObject::LL_VO_CLOUDS: - // no longer used - break; - case LLViewerObject::LL_VO_PART_GROUP: - case LLViewerObject::LL_VO_HUD_PART_GROUP: - gGL.diffuseColor4f(0,0,1,1); // blue - break; - case LLViewerObject::LL_VO_VOID_WATER: - case LLViewerObject::LL_VO_WATER: - gGL.diffuseColor4f(0,0.5f,1,1); // medium blue - break; - case LL_PCODE_LEGACY_TREE: - gGL.diffuseColor4f(0,0.5f,0,1); // dark green - break; - default: - auto avatar = drawable->getVObj()->asAvatar(); - if (avatar->isControlAvatar()) - { - LLControlAvatar* cav = static_cast<LLControlAvatar*>(avatar); - bool has_pos_constraint = (cav->mPositionConstraintFixup != LLVector3()); - bool has_scale_constraint = (cav->mScaleConstraintFixup != 1.0f); - if (has_pos_constraint || has_scale_constraint) - { - gGL.diffuseColor4f(1,0,0,1); - } - else - { - gGL.diffuseColor4f(0,1,0.5,1); - } - } - else - { - gGL.diffuseColor4f(1,0,1,1); // magenta - } - break; - } - } - else - { - gGL.diffuseColor4f(1,0,0,1); - } - } - - const LLVector4a* ext; - LLVector4a pos, size; - - if (drawable->getVOVolume()) - { - //render face bounding boxes - for (S32 i = 0; i < drawable->getNumFaces(); i++) - { - LLFace* facep = drawable->getFace(i); - if (facep) - { - ext = facep->mExtents; - - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - - drawBoxOutline(pos,size); - } - } - } - - //render drawable bounding box - ext = drawable->getSpatialExtents(); - - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - - LLViewerObject* vobj = drawable->getVObj(); - if (vobj && vobj->onActiveList()) - { - gGL.flush(); - gGL.setLineWidth(llmax(4.f*sinf(gFrameTimeSeconds*2.f)+1.f, 1.f)); - //gGL.setLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f)); - stop_glerror(); - drawBoxOutline(pos,size); - gGL.flush(); - gGL.setLineWidth(1.f); - } - else - { - drawBoxOutline(pos,size); - } -} - -void renderNormals(LLDrawable* drawablep) -{ - LLVertexBuffer::unbind(); - - LLVOVolume* vol = drawablep->getVOVolume(); - if (vol) - { - LLVolume* volume = vol->getVolume(); - gGL.pushMatrix(); - gGL.multMatrix((F32*) vol->getRelativeXform().mMatrix); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLVector4a scale(gSavedSettings.getF32("RenderDebugNormalScale")); - - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = volume->getVolumeFace(i); - - for (S32 j = 0; j < face.mNumVertices; ++j) - { - gGL.begin(LLRender::LINES); - LLVector4a n,p; - - n.setMul(face.mNormals[j], scale); - p.setAdd(face.mPositions[j], n); - - gGL.diffuseColor4f(1,1,1,1); - gGL.vertex3fv(face.mPositions[j].getF32ptr()); - gGL.vertex3fv(p.getF32ptr()); - - if (face.mTangents) - { - n.setMul(face.mTangents[j], scale); - p.setAdd(face.mPositions[j], n); - - gGL.diffuseColor4f(0,1,1,1); - gGL.vertex3fv(face.mPositions[j].getF32ptr()); - gGL.vertex3fv(p.getF32ptr()); - } - gGL.end(); - } - } - - gGL.popMatrix(); - } -} - -S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& scale) -{ - const S32 DEFAULT_DETAIL = 1; - const F32 LARGE_THRESHOLD = 5.f; - const F32 MEGA_THRESHOLD = 25.f; - - S32 detail = DEFAULT_DETAIL; - F32 avg_scale = (scale[0]+scale[1]+scale[2])/3.f; - - if (avg_scale > LARGE_THRESHOLD) - { - detail += 1; - if (avg_scale > MEGA_THRESHOLD) - { - detail += 1; - } - } - - return detail; -} - -void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLColor4& line_color) -{ - LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); - LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); - - const LLVector3 center(0,0,0); - const LLVector3 size(0.25f,0.25f,0.25f); - - if (decomp) - { - if (!decomp->mBaseHullMesh.empty()) - { - gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions, decomp->mBaseHullMesh.mNormals); - } - else - { - gMeshRepo.buildPhysicsMesh(*decomp); - gGL.diffuseColor4f(0,1,1,1); - drawBoxOutline(center, size); - } - - } - else - { - gGL.diffuseColor3f(1,0,1); - drawBoxOutline(center, size); - } -} - -void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColor4& line_color) -{ - gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); - LLGLEnable offset(GL_POLYGON_OFFSET_LINE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glPolygonOffset(3.f, 3.f); - gGL.setLineWidth(3.f); - gGL.diffuseColor4fv(line_color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); - gGL.setLineWidth(1.f); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -} - -void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) -{ - U8 physics_type = volume->getPhysicsShapeType(); - - if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE || volume->isFlexible()) - { - return; - } - - //not allowed to return at this point without rendering *something* - - F32 threshold = gSavedSettings.getF32("ObjectCostHighThreshold"); - F32 cost = volume->getObjectCost(); - - LLColor4 low = gSavedSettings.getColor4("ObjectCostLowColor"); - LLColor4 mid = gSavedSettings.getColor4("ObjectCostMidColor"); - LLColor4 high = gSavedSettings.getColor4("ObjectCostHighColor"); - - F32 normalizedCost = 1.f - exp( -(cost / threshold) ); - - LLColor4 color; - if ( normalizedCost <= 0.5f ) - { - color = lerp( low, mid, 2.f * normalizedCost ); - } - else - { - color = lerp( mid, high, 2.f * ( normalizedCost - 0.5f ) ); - } - - LLColor4 line_color = color*0.5f; - - U32 data_mask = LLVertexBuffer::MAP_VERTEX; - - LLVolumeParams volume_params = volume->getVolume()->getParams(); - - LLPhysicsVolumeParams physics_params(volume_params, - physics_type == LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); - - LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification physics_spec; - LLPhysicsShapeBuilderUtil::determinePhysicsShape(physics_params, volume->getScale(), physics_spec); - - U32 type = physics_spec.getType(); - - LLVector3 center(0,0,0); - LLVector3 size(0.25f,0.25f,0.25f); - - gGL.pushMatrix(); - gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); - - if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH) - { - LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); - LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); - - if (decomp) - { //render a physics based mesh - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - if (!decomp->mHull.empty()) - { //decomposition exists, use that - - if (decomp->mMesh.empty()) - { - gMeshRepo.buildPhysicsMesh(*decomp); - } - - for (auto& i : decomp->mMesh) - { - render_hull(i, color, line_color); - } - } - else if (!decomp->mPhysicsShapeMesh.empty()) - { - //decomp has physics mesh, render that mesh - gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); - - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - gGL.diffuseColor4fv(line_color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - else - { //no mesh or decomposition, render base hull - renderMeshBaseHull(volume, data_mask, color, line_color); - - if (decomp->mPhysicsShapeMesh.empty()) - { - //attempt to fetch physics shape mesh if available - gMeshRepo.fetchPhysicsShape(mesh_id); - } - } - } - else - { - gGL.diffuseColor3f(1,1,0); - drawBoxOutline(center, size); - } - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_CONVEX || - type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) - { - if (volume->isMesh()) - { - renderMeshBaseHull(volume, data_mask, color, line_color); - } - else - { - LLVolumeParams volume_params = volume->getVolume()->getParams(); - S32 detail = get_physics_detail(volume_params, volume->getScale()); - LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); - - if (!phys_volume->mHullPoints) - { //build convex hull - std::vector<LLVector3> pos; - std::vector<U16> index; - - S32 index_offset = 0; - - for (S32 i = 0; i < phys_volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = phys_volume->getVolumeFace(i); - if (index_offset + face.mNumVertices > 65535) - { - continue; - } - - for (S32 j = 0; j < face.mNumVertices; ++j) - { - pos.emplace_back(face.mPositions[j].getF32ptr()); - } - - for (S32 j = 0; j < face.mNumIndices; ++j) - { - index.push_back(face.mIndices[j]+index_offset); - } - - index_offset += face.mNumVertices; - } - - if (!pos.empty() && !index.empty()) - { - LLCDMeshData mesh; - mesh.mIndexBase = &index[0]; - mesh.mVertexBase = pos[0].mV; - mesh.mNumVertices = pos.size(); - mesh.mVertexStrideBytes = 12; - mesh.mIndexStrideBytes = 6; - mesh.mIndexType = LLCDMeshData::INT_16; - - mesh.mNumTriangles = index.size()/3; - - LLCDMeshData res; - - LLConvexDecomposition::getInstance()->generateSingleHullMeshFromMesh( &mesh, &res ); - - //copy res into phys_volume - phys_volume->mHullPoints = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*res.mNumVertices); - phys_volume->mNumHullPoints = res.mNumVertices; - - S32 idx_size = (res.mNumTriangles*3*2+0xF) & ~0xF; - phys_volume->mHullIndices = (U16*) ll_aligned_malloc_16(idx_size); - phys_volume->mNumHullIndices = res.mNumTriangles*3; - - const F32* v = res.mVertexBase; - - for (S32 i = 0; i < res.mNumVertices; ++i) - { - F32* p = (F32*) ((U8*)v+i*res.mVertexStrideBytes); - phys_volume->mHullPoints[i].load3(p); - } - - if (res.mIndexType == LLCDMeshData::INT_16) - { - for (S32 i = 0; i < res.mNumTriangles; ++i) - { - U16* idx = (U16*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); - - phys_volume->mHullIndices[i*3+0] = idx[0]; - phys_volume->mHullIndices[i*3+1] = idx[1]; - phys_volume->mHullIndices[i*3+2] = idx[2]; - } - } - else - { - for (S32 i = 0; i < res.mNumTriangles; ++i) - { - U32* idx = (U32*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); - - phys_volume->mHullIndices[i*3+0] = (U16) idx[0]; - phys_volume->mHullIndices[i*3+1] = (U16) idx[1]; - phys_volume->mHullIndices[i*3+2] = (U16) idx[2]; - } - } - } - } - - if (phys_volume->mHullPoints && phys_volume->mHullIndices && phys_volume->mNumHullPoints > 0 && phys_volume->mNumHullIndices > 0) - { - //render hull - - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - gGL.diffuseColor4fv(line_color.mV); - LLVertexBuffer::unbind(); - - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); - - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); - - gGL.diffuseColor4fv(color.mV); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); - - } - else - { - gGL.diffuseColor4f(1,0,1,1); - drawBoxOutline(center, size); - } - - LLPrimitive::sVolumeManager->unrefVolume(phys_volume); - } - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX) - { - LLVector3 center = physics_spec.getCenter(); - LLVector3 scale = physics_spec.getScale(); - LLVector3 vscale = volume->getScale()*2.f; - scale.set(scale[0]/vscale[0], scale[1]/vscale[1], scale[2]/vscale[2]); - - gGL.diffuseColor4fv(color.mV); - drawBox(center, scale); - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE) - { - LLVolumeParams volume_params; - volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE ); - volume_params.setBeginAndEndS( 0.f, 1.f ); - volume_params.setBeginAndEndT( 0.f, 1.f ); - volume_params.setRatio ( 1, 1 ); - volume_params.setShear ( 0, 0 ); - LLVolume* sphere = LLPrimitive::sVolumeManager->refVolume(volume_params, 3); - - gGL.diffuseColor4fv(color.mV); - pushVerts(sphere); - LLPrimitive::sVolumeManager->unrefVolume(sphere); - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER) - { - LLVolumeParams volume_params; - volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); - volume_params.setBeginAndEndS( 0.f, 1.f ); - volume_params.setBeginAndEndT( 0.f, 1.f ); - volume_params.setRatio ( 1, 1 ); - volume_params.setShear ( 0, 0 ); - LLVolume* cylinder = LLPrimitive::sVolumeManager->refVolume(volume_params, 3); - - gGL.diffuseColor4fv(color.mV); - pushVerts(cylinder); - LLPrimitive::sVolumeManager->unrefVolume(cylinder); - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_MESH) - { - LLVolumeParams volume_params = volume->getVolume()->getParams(); - S32 detail = get_physics_detail(volume_params, volume->getScale()); - - LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - gGL.diffuseColor4fv(line_color.mV); - pushVerts(phys_volume); - - gGL.diffuseColor4fv(color.mV); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - pushVerts(phys_volume); - LLPrimitive::sVolumeManager->unrefVolume(phys_volume); - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) - { - LLVolumeParams volume_params = volume->getVolume()->getParams(); - S32 detail = get_physics_detail(volume_params, volume->getScale()); - - LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); - - if (phys_volume->mHullPoints && phys_volume->mHullIndices) - { - gGL.diffuseColor4fv(line_color.mV); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); - - gGL.diffuseColor4fv(color.mV); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); - } - else - { - gGL.diffuseColor3f(1,0,1); - drawBoxOutline(center, size); - gMeshRepo.buildHull(volume_params, detail); - } - LLPrimitive::sVolumeManager->unrefVolume(phys_volume); - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SCULPT) - { - //TODO: implement sculpted prim physics display - } - else - { - LL_ERRS() << "Unhandled type" << LL_ENDL; - } - - gGL.popMatrix(); -} - -void renderPhysicsShapes(LLSpatialGroup* group) -{ - for (OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - - if (drawable->isSpatialBridge()) - { - LLSpatialBridge* bridge = drawable->asPartition()->asBridge(); - - if (bridge) - { - gGL.pushMatrix(); - gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); - bridge->renderPhysicsShapes(); - gGL.popMatrix(); - } - } - else - { - LLVOVolume* volume = drawable->getVOVolume(); - if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE ) - { - if (!group->getSpatialPartition()->isBridge()) - { - gGL.pushMatrix(); - LLVector3 trans = drawable->getRegion()->getOriginAgent(); - gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); - renderPhysicsShape(drawable, volume); - gGL.popMatrix(); - } - else - { - renderPhysicsShape(drawable, volume); - } - } - else - { - LLViewerObject* object = drawable->getVObj(); - if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) - { - gGL.pushMatrix(); - gGL.multMatrix((F32*) object->getRegion()->mRenderMatrix.mMatrix); - //push face vertices for terrain - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* face = drawable->getFace(i); - if (face) - { - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff) - { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - buff->setBuffer(LLVertexBuffer::MAP_VERTEX); - gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); - buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); - - gGL.diffuseColor3f(0.2f, 1.f, 0.3f); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); - } - } - } - gGL.popMatrix(); - } - } - } - } -} - -void renderTexturePriority(LLDrawable* drawable) -{ - for (int face=0; face<drawable->getNumFaces(); ++face) - { - LLFace *facep = drawable->getFace(face); - - LLVector4 cold(0,0,0.25f); - LLVector4 hot(1,0.25f,0.25f); - - LLVector4 boost_cold(0,0,0,0); - LLVector4 boost_hot(0,1,0,1); - - LLGLDisable blend(GL_BLEND); - - //LLViewerTexture* imagep = facep->getTexture(); - //if (imagep) - if (facep) - { - - //F32 vsize = imagep->mMaxVirtualSize; - F32 vsize = facep->getPixelArea(); - - if (vsize > sCurMaxTexPriority) - { - sCurMaxTexPriority = vsize; - } - - F32 t = vsize/sLastMaxTexPriority; - - LLVector4 col = lerp(cold, hot, t); - gGL.diffuseColor4fv(col.mV); - } - //else - //{ - // gGL.diffuseColor4f(1,0,1,1); - //} - - LLVector4a center; - center.setAdd(facep->mExtents[1],facep->mExtents[0]); - center.mul(0.5f); - LLVector4a size; - size.setSub(facep->mExtents[1],facep->mExtents[0]); - size.mul(0.5f); - size.add(LLVector4a(0.01f)); - drawBox(center, size); - - /*S32 boost = imagep->getBoostLevel(); - if (boost>LLGLTexture::BOOST_NONE) - { - F32 t = (F32) boost / (F32) (LLGLTexture::BOOST_MAX_LEVEL-1); - LLVector4 col = lerp(boost_cold, boost_hot, t); - LLGLEnable blend_on(GL_BLEND); - gGL.blendFunc(GL_SRC_ALPHA, GL_ONE); - gGL.diffuseColor4fv(col.mV); - drawBox(center, size); - gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - }*/ - } -} - -void renderPoints(LLDrawable* drawablep) -{ - LLGLDepthTest depth(GL_FALSE, GL_FALSE); - if (drawablep->getNumFaces()) - { - gGL.begin(LLRender::POINTS); - gGL.diffuseColor3f(1,1,1); - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace * face = drawablep->getFace(i); - if (face) - { - gGL.vertex3fv(face->mCenterLocal.mV); - } - } - gGL.end(); - } -} - -void renderTextureAnim(LLDrawInfo* params) -{ - if (!params->mTextureMatrix) - { - return; - } - - LLGLEnable blend(GL_BLEND); - gGL.diffuseColor4f(1,1,0,0.5f); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); -} - -void renderBatchSize(LLDrawInfo* params) -{ - LLGLEnable offset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.f, 1.f); - if (params->mDebugColor == LLColor4U::black) - { - params->mDebugColor = LLColor4U(ll_rand(255), ll_rand(255), ll_rand(255), 255U); - } - gGL.diffuseColor4ubv((U8*)params->mDebugColor.mV); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); -} - -void renderShadowFrusta(LLDrawInfo* params) -{ - LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_ADD); - - LLVector4a center; - center.setAdd(params->mExtents[1], params->mExtents[0]); - center.mul(0.5f); - LLVector4a size; - size.setSub(params->mExtents[1],params->mExtents[0]); - size.mul(0.5f); - - if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size)) - { - gGL.diffuseColor3f(1,0,0); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size)) - { - gGL.diffuseColor3f(0,1,0); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size)) - { - gGL.diffuseColor3f(0,0,1); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size)) - { - gGL.diffuseColor3f(1,0,1); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - - gGL.setSceneBlendType(LLRender::BT_ALPHA); -} - -void renderTexelDensity(LLDrawable* drawable) -{ - if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF - || LLViewerTexture::sCheckerBoardImagep.isNull()) - { - return; - } - - LLGLEnable _(GL_BLEND); - //gObjectFullbrightProgram.bind(); - - LLMatrix4 checkerboard_matrix; - S32 discard_level = -1; - - for (S32 f = 0; f < drawable->getNumFaces(); f++) - { - LLFace* facep = drawable->getFace(f); - LLVertexBuffer* buffer = facep->getVertexBuffer(); - LLViewerTexture* texturep = facep->getTexture(); - - if (texturep == NULL) continue; - - switch(LLViewerTexture::sDebugTexelsMode) - { - case LLViewerTexture::DEBUG_TEXELS_CURRENT: - discard_level = -1; - break; - case LLViewerTexture::DEBUG_TEXELS_DESIRED: - { - LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); - discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; - break; - } - default: - case LLViewerTexture::DEBUG_TEXELS_FULL: - discard_level = 0; - break; - } - - checkerboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); - - gGL.getTexUnit(0)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadMatrix((GLfloat*)&checkerboard_matrix.mMatrix); - - if (buffer && (facep->getGeomCount() >= 3)) - { - buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); - U16 start = facep->getGeomStart(); - U16 end = start + facep->getGeomCount()-1; - U32 count = facep->getIndicesCount(); - U16 offset = facep->getIndicesStart(); - buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); - } - - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } - - //S32 num_textures = llmax(1, (S32)params->mTextureList.size()); - - //for (S32 i = 0; i < num_textures; i++) - //{ - // LLViewerTexture* texturep = params->mTextureList.empty() ? params->mTexture.get() : params->mTextureList[i].get(); - // if (texturep == NULL) continue; - - // LLMatrix4 checkboard_matrix; - // S32 discard_level = -1; - // switch(LLViewerTexture::sDebugTexelsMode) - // { - // case LLViewerTexture::DEBUG_TEXELS_CURRENT: - // discard_level = -1; - // break; - // case LLViewerTexture::DEBUG_TEXELS_DESIRED: - // { - // LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); - // discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; - // break; - // } - // default: - // case LLViewerTexture::DEBUG_TEXELS_FULL: - // discard_level = 0; - // break; - // } - - // checkboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); - // gGL.getTexUnit(i)->activate(); - - // glMatrixMode(GL_TEXTURE); - // glPushMatrix(); - // glLoadIdentity(); - // //gGL.matrixMode(LLRender::MM_TEXTURE); - // glLoadMatrixf((GLfloat*) checkboard_matrix.mMatrix); - - // gGL.getTexUnit(i)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); - - // pushVerts(params, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL ); - - // glPopMatrix(); - // glMatrixMode(GL_MODELVIEW); - // //gGL.matrixMode(LLRender::MM_MODELVIEW); - //} -} - - -void renderLights(LLDrawable* drawablep) -{ - if (!drawablep->isLight()) - { - return; - } - - if (drawablep->getNumFaces()) - { - LLGLEnable blend(GL_BLEND); - gGL.diffuseColor4f(0,1,1,0.5f); - - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace * face = drawablep->getFace(i); - if (face) - { - pushVerts(face, LLVertexBuffer::MAP_VERTEX); - } - } - - const LLVector4a* ext = drawablep->getSpatialExtents(); - - LLVector4a pos; - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - LLVector4a size; - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - - { - LLGLDepthTest depth(GL_FALSE, GL_TRUE); - gGL.diffuseColor4f(1,1,1,1); - drawBoxOutline(pos, size); - } - - gGL.diffuseColor4f(1,1,0,1); - F32 rad = drawablep->getVOVolume()->getLightRadius(); - drawBoxOutline(pos, LLVector4a(rad)); - } -} - -class LLRenderOctreeRaycast final : public LLOctreeTriangleRayIntersect -{ -public: - - - LLRenderOctreeRaycast(const LLVector4a& start, const LLVector4a& dir, F32* closest_t) - : LLOctreeTriangleRayIntersect(start, dir, NULL, closest_t, NULL, NULL, NULL, NULL) - { - - } - - void visit(const LLOctreeNode<LLVolumeTriangle>* branch) override - { - LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0); - - LLVector3 center, size; - - if (branch->isEmpty()) - { - gGL.diffuseColor3f(1.f,0.2f,0.f); - center.set(branch->getCenter().getF32ptr()); - size.set(branch->getSize().getF32ptr()); - } - else - { - gGL.diffuseColor3f(0.75f, 1.f, 0.f); - center.set(vl->mBounds[0].getF32ptr()); - size.set(vl->mBounds[1].getF32ptr()); - } - - drawBoxOutline(center, size); - - for (U32 i = 0; i < 2; i++) - { - LLGLDepthTest depth(GL_TRUE, GL_FALSE, i == 1 ? GL_LEQUAL : GL_GREATER); - - if (i == 1) - { - gGL.diffuseColor4f(0,1,1,0.5f); - } - else - { - gGL.diffuseColor4f(0,0.5f,0.5f, 0.25f); - drawBoxOutline(center, size); - } - - if (i == 1) - { - gGL.flush(); - gGL.setLineWidth(3.f); - } - - gGL.begin(LLRender::TRIANGLES); - for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); - iter != branch->getDataEnd(); - ++iter) - { - const LLVolumeTriangle* tri = *iter; - - gGL.vertex3fv(tri->mV[0]->getF32ptr()); - gGL.vertex3fv(tri->mV[1]->getF32ptr()); - gGL.vertex3fv(tri->mV[2]->getF32ptr()); - } - gGL.end(); - - if (i == 1) - { - gGL.flush(); - gGL.setLineWidth(1.f); - } - } - } -}; - -void renderRaycast(LLDrawable* drawablep) -{ - if (drawablep->getNumFaces()) - { - LLGLEnable blend(GL_BLEND); - gGL.diffuseColor4f(0,1,1,0.5f); - - if (drawablep->getVOVolume()) - { - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - //pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX); - //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - LLVOVolume* vobj = drawablep->getVOVolume(); - LLVolume* volume = vobj->getVolume(); - - bool transform = true; - if (drawablep->isState(LLDrawable::RIGGED)) - { - volume = vobj->getRiggedVolume(); - transform = false; - } - - if (volume) - { - LLVector3 trans = drawablep->getRegion()->getOriginAgent(); - - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = volume->getVolumeFace(i); - - gGL.pushMatrix(); - gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); - gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); - - LLVector4a start, end; - if (transform) - { - LLVector3 v_start(gDebugRaycastStart.getF32ptr()); - LLVector3 v_end(gDebugRaycastEnd.getF32ptr()); - - v_start = vobj->agentPositionToVolume(v_start); - v_end = vobj->agentPositionToVolume(v_end); - - start.load3(v_start.mV); - end.load3(v_end.mV); - } - else - { - start = gDebugRaycastStart; - end = gDebugRaycastEnd; - } - - LLVector4a dir; - dir.setSub(end, start); - - gGL.flush(); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - { - //render face positions - gGL.diffuseColor4f(0.f, 1.f, 1.f, 0.5f); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mNumVertices, face.mPositions, NULL, face.mNumIndices, face.mIndices); - } - - if (!volume->isUnique()) - { - F32 t = 1.f; - - if (!face.mOctree) - { - ((LLVolumeFace*) &face)->createOctree(); - } - - LLRenderOctreeRaycast render(start, dir, &t); - - render.traverse(face.mOctree); - } - - gGL.popMatrix(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - } - } - else if (drawablep->isAvatar()) - { - if (drawablep->getVObj() == gDebugRaycastObject) - { - LLGLDepthTest depth(GL_FALSE); - LLVOAvatar* av = (LLVOAvatar*) drawablep->getVObj().get(); - av->renderCollisionVolumes(); - } - } - - if (drawablep->getVObj() == gDebugRaycastObject) - { - // draw intersection point - gGL.pushMatrix(); - gGL.loadMatrix(gGLModelView); - LLVector3 translate(gDebugRaycastIntersection.getF32ptr()); - gGL.translatef(translate.mV[0], translate.mV[1], translate.mV[2]); - LLCoordFrame orient; - LLVector4a debug_binormal; - - debug_binormal.setCross3(gDebugRaycastNormal, gDebugRaycastTangent); - debug_binormal.mul(gDebugRaycastTangent.getF32ptr()[3]); - - LLVector3 normal(gDebugRaycastNormal.getF32ptr()); - LLVector3 binormal(debug_binormal.getF32ptr()); - - orient.lookDir(normal, binormal); - LLMatrix4 rotation; - orient.getRotMatrixToParent(rotation); - gGL.multMatrix((float*)rotation.mMatrix); - - gGL.diffuseColor4f(1,0,0,0.5f); - drawBox(LLVector3(0, 0, 0), LLVector3(0.1f, 0.022f, 0.022f)); - gGL.diffuseColor4f(0,1,0,0.5f); - drawBox(LLVector3(0, 0, 0), LLVector3(0.021f, 0.1f, 0.021f)); - gGL.diffuseColor4f(0,0,1,0.5f); - drawBox(LLVector3(0, 0, 0), LLVector3(0.02f, 0.02f, 0.1f)); - gGL.popMatrix(); - - // draw bounding box of prim - const LLVector4a* ext = drawablep->getSpatialExtents(); - - LLVector4a pos; - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - LLVector4a size; - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - - LLGLDepthTest depth(GL_FALSE, GL_TRUE); - gGL.diffuseColor4f(0,0.5f,0.5f,1); - drawBoxOutline(pos, size); - } - } -} - - -void renderAvatarCollisionVolumes(LLVOAvatar* avatar) -{ - avatar->renderCollisionVolumes(); -} - -void renderAvatarBones(LLVOAvatar* avatar) -{ - avatar->renderBones(); -} - -void renderAgentTarget(LLVOAvatar* avatar) -{ - // render these for self only (why, i don't know) - if (avatar->isSelf()) - { - renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); - renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f)); - renderCrossHairs(avatar->mRoot->getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); - renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f)); - } -} - -class LLOctreeRenderNonOccluded final : public OctreeTraveler -{ -public: - LLCamera* mCamera; - LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {} - - void traverse(const OctreeNode* node) override - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) - { - node->accept(this); - stop_glerror(); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - stop_glerror(); - } - - //draw tight fit bounding boxes for spatial group - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) - { - group->rebuildGeom(); - group->rebuildMesh(); - - renderOctree(group); - stop_glerror(); - } - - //render visibility wireframe - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) - { - group->rebuildGeom(); - group->rebuildMesh(); - - gGL.flush(); - gGL.pushMatrix(); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - renderVisibility(group, mCamera); - stop_glerror(); - gGLLastMatrix = NULL; - gGL.popMatrix(); - gGL.diffuseColor4f(1,1,1,1); - } - } - } - - void visit(const OctreeNode* branch) override - { - LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - const LLVector4a* bounds = group->getBounds(); - if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) - { - return; - } - - LLGLDisable stencil(GL_STENCIL_TEST); - - group->rebuildGeom(); - group->rebuildMesh(); - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) - { - if (!group->isEmpty()) - { - gGL.diffuseColor3f(0,0,1); - const LLVector4a* obj_bounds = group->getObjectBounds(); - drawBoxOutline(obj_bounds[0], obj_bounds[1]); - } - } - - for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) - { - renderBoundingBox(drawable); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_NORMALS)) - { - renderNormals(drawable); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BUILD_QUEUE)) - { - if (drawable->isState(LLDrawable::IN_REBUILD_Q2)) - { - gGL.diffuseColor4f(0.6f, 0.6f, 0.1f, 1.f); - const LLVector4a* ext = drawable->getSpatialExtents(); - LLVector4a center; - center.setAdd(ext[0], ext[1]); - center.mul(0.5f); - LLVector4a size; - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - drawBoxOutline(center, size); - } - } - - if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - renderTexturePriority(drawable); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS)) - { - renderPoints(drawable); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LIGHTS)) - { - renderLights(drawable); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) - { - renderRaycast(drawable); - } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_UPDATE_TYPE)) - { - renderUpdateType(drawable); - } - if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY)) - { - renderComplexityDisplay(drawable); - } - if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) - { - renderTexelDensity(drawable); - } - - LLVOAvatar* avatar = drawable->getVObj()->asAvatar(); - - if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)) - { - renderAvatarCollisionVolumes(avatar); - } - - if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_JOINTS)) - { - renderAvatarBones(avatar); - } - - if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET)) - { - renderAgentTarget(avatar); - } - - if (gDebugGL) - { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* facep = drawable->getFace(i); - if (facep) - { - U8 index = facep->getTextureIndex(); - if (facep->mDrawInfo) - { - if (index < 255) - { - if (facep->mDrawInfo->mTextureList.size() <= index) - { - LL_ERRS() << "Face texture index out of bounds." << LL_ENDL; - } - else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) - { - LL_ERRS() << "Face texture index incorrect." << LL_ENDL; - } - } - } - } - } - } - } - - for (auto& i : group->mDrawMap) - { - LLSpatialGroup::drawmap_elem_t& draw_vec = i.second; - for (auto& j : draw_vec) - { - LLDrawInfo* draw_info = j; - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_ANIM)) - { - renderTextureAnim(draw_info); - } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BATCH_SIZE)) - { - renderBatchSize(draw_info); - } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) - { - renderShadowFrusta(draw_info); - } - } - } - } -}; - -class LLOctreeRenderXRay final : public OctreeTraveler -{ -public: - LLCamera* mCamera; - LLOctreeRenderXRay(LLCamera* camera): mCamera(camera) {} - - void traverse(const OctreeNode* node) override - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) - { - node->accept(this); - stop_glerror(); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - stop_glerror(); - } - - //render visibility wireframe - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) - { - group->rebuildGeom(); - group->rebuildMesh(); - - gGL.flush(); - gGL.pushMatrix(); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - renderXRay(group, mCamera); - stop_glerror(); - gGLLastMatrix = NULL; - gGL.popMatrix(); - } - } - } - - void visit(const OctreeNode* node) override {} - -}; - -class LLOctreeRenderPhysicsShapes final : public OctreeTraveler -{ -public: - LLCamera* mCamera; - LLOctreeRenderPhysicsShapes(LLCamera* camera): mCamera(camera) {} - - void traverse(const OctreeNode* node) override - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) - { - node->accept(this); - stop_glerror(); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - stop_glerror(); - } - - group->rebuildGeom(); - group->rebuildMesh(); - - renderPhysicsShapes(group); - } - } - - void visit(const OctreeNode* branch) override - { - - } -}; - -class LLOctreePushBBoxVerts final : public OctreeTraveler -{ -public: - LLCamera* mCamera; - LLOctreePushBBoxVerts(LLCamera* camera): mCamera(camera) {} - - void traverse(const OctreeNode* node) override - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (!mCamera || mCamera->AABBInFrustum(bounds[0], bounds[1])) - { - node->accept(this); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - } - } - } - - void visit(const OctreeNode* branch) override - { - LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) - { - return; - } - - for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - renderBoundingBox(drawable, FALSE); - } - } -}; - -void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) -{ - LLOctreePushBBoxVerts pusher(camera); - pusher.traverse(mOctree); -} - -class LLOctreeStateCheck final : public OctreeTraveler -{ -public: - U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS]; - - LLOctreeStateCheck() - { - for (unsigned int& i : mInheritedMask) - { - i = 0; - } - } - - void traverse(const OctreeNode* node) override - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - node->accept(this); - - - U32 temp[LLViewerCamera::NUM_CAMERAS]; - - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - temp[i] = mInheritedMask[i]; - mInheritedMask[i] |= group->mOcclusionState[i] & LLSpatialGroup::OCCLUDED; - } - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - } - - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - mInheritedMask[i] = temp[i]; - } - } - - - void visit(const OctreeNode* state) override - { - LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); - - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - if (mInheritedMask[i] && !(group->mOcclusionState[i] & mInheritedMask[i])) - { - LL_ERRS() << "Spatial group failed inherited mask test." << LL_ENDL; - } - } - - if (group->hasState(LLSpatialGroup::DIRTY)) - { - assert_parent_state(group, LLSpatialGroup::DIRTY); - } - } - - void assert_parent_state(LLSpatialGroup* group, U32 state) - { - LLSpatialGroup* parent = group->getParent(); - while (parent) - { - if (!parent->hasState(state)) - { - LL_ERRS() << "Spatial group failed parent state check." << LL_ENDL; - } - parent = parent->getParent(); - } - } -}; - - -void LLSpatialPartition::renderPhysicsShapes() -{ - LLSpatialBridge* bridge = asBridge(); - LLCamera* camera = LLViewerCamera::getInstance(); - - if (bridge) - { - camera = NULL; - } - - gGL.flush(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.setLineWidth(3.f); - LLOctreeRenderPhysicsShapes render_physics(camera); - render_physics.traverse(mOctree); - gGL.flush(); - gGL.setLineWidth(1.f); -} - -void LLSpatialPartition::renderDebug() -{ - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | - LLPipeline::RENDER_DEBUG_OCCLUSION | - LLPipeline::RENDER_DEBUG_LIGHTS | - LLPipeline::RENDER_DEBUG_BATCH_SIZE | - LLPipeline::RENDER_DEBUG_UPDATE_TYPE | - LLPipeline::RENDER_DEBUG_BBOXES | - LLPipeline::RENDER_DEBUG_NORMALS | - LLPipeline::RENDER_DEBUG_POINTS | - LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | - LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | - LLPipeline::RENDER_DEBUG_RAYCAST | - LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | - LLPipeline::RENDER_DEBUG_AVATAR_JOINTS | - LLPipeline::RENDER_DEBUG_AGENT_TARGET | - //LLPipeline::RENDER_DEBUG_BUILD_QUEUE | - LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | - LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY | - LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) - { - return; - } - - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.bind(); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - //sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds); - sLastMaxTexPriority = (F32) LLViewerCamera::getInstance()->getScreenPixelArea(); - sCurMaxTexPriority = 0.f; - } - - LLGLDisable cullface(GL_CULL_FACE); - LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gPipeline.disableLights(); - - LLSpatialBridge* bridge = asBridge(); - LLCamera* camera = LLViewerCamera::getInstance(); - - if (bridge) - { - camera = NULL; - } - - LLOctreeStateCheck checker; - checker.traverse(mOctree); - - LLOctreeRenderNonOccluded render_debug(camera); - render_debug.traverse(mOctree); - - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) - { - { - LLGLEnable cull(GL_CULL_FACE); - - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - gGL.diffuseColor4f(0.5f, 0.0f, 0, 0.25f); - - LLGLEnable offset(GL_POLYGON_OFFSET_LINE); - glPolygonOffset(-1.f, -1.f); - - LLOctreeRenderXRay xray(camera); - xray.traverse(mOctree); - - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - } - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.unbind(); - } -} - -void LLSpatialGroup::drawObjectBox(LLColor4 col) -{ - gGL.diffuseColor4fv(col.mV); - LLVector4a size; - size = mObjectBounds[1]; - size.mul(1.01f); - size.add(LLVector4a(0.001f)); - drawBox(mObjectBounds[0], size); -} - -bool LLSpatialPartition::isHUDPartition() -{ - return mPartitionType == LLViewerRegion::PARTITION_HUD ; -} - -BOOL LLSpatialPartition::isVisible(const LLVector3& v) -{ - if (!LLViewerCamera::getInstance()->sphereInFrustum(v, 4.0f)) - { - return FALSE; - } - - return TRUE; -} - -LL_ALIGN_PREFIX(16) -class LLOctreeIntersect : public LLOctreeTraveler<LLViewerOctreeEntry> -{ -public: - LL_ALIGN_16(LLVector4a mStart); - LL_ALIGN_16(LLVector4a mEnd); - - S32 *mFaceHit; - LLVector4a *mIntersection; - LLVector2 *mTexCoord; - LLVector4a *mNormal; - LLVector4a *mTangent; - LLDrawable* mHit; - BOOL mPickTransparent; - BOOL mPickRigged; - - LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, - S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) - : mStart(start), - mEnd(end), - mFaceHit(face_hit), - mIntersection(intersection), - mTexCoord(tex_coord), - mNormal(normal), - mTangent(tangent), - mHit(NULL), - mPickTransparent(pick_transparent), - mPickRigged(pick_rigged) - { - } - - void visit(const OctreeNode* branch) override - { - for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) - { - check(*i); - } - } - - virtual LLDrawable* check(const OctreeNode* node) - { - node->accept(this); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - const OctreeNode* child = node->getChild(i); - LLVector3 res; - - LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0); - - LLVector4a size; - LLVector4a center; - - const LLVector4a* bounds = group->getBounds(); - size = bounds[1]; - center = bounds[0]; - - LLVector4a local_start = mStart; - LLVector4a local_end = mEnd; - - if (group->getSpatialPartition()->isBridge()) - { - LLMatrix4a local_matrix4a(group->getSpatialPartition()->asBridge()->mDrawable->getRenderMatrix()); - local_matrix4a.invert(); - - local_matrix4a.affineTransform(mStart, local_start); - local_matrix4a.affineTransform(mEnd, local_end); - } - - if (LLLineSegmentBoxIntersect(local_start, local_end, center, size)) - { - check(child); - } - } - - return mHit; - } - - virtual bool check(LLViewerOctreeEntry* entry) - { - LLDrawable* drawable = (LLDrawable*)entry->getDrawable(); - - if (!drawable || !gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible()) - { - return false; - } - - if (drawable->isSpatialBridge()) - { - LLSpatialPartition *part = drawable->asPartition(); - LLSpatialBridge* bridge = part->asBridge(); - if (bridge && gPipeline.hasRenderType(bridge->mDrawableType)) - { - check(part->mOctree); - } - } - else - { - LLViewerObject* vobj = drawable->getVObj(); - - if (vobj) - { - LLVector4a intersection; - bool skip_check = false; - if (vobj->isAvatar()) - { - LLVOAvatar* avatar = (LLVOAvatar*) vobj; - if ((mPickRigged) || ((avatar->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) - { - LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent); - if (hit) - { - mEnd = intersection; - if (mIntersection) - { - *mIntersection = intersection; - } - - mHit = hit->mDrawable; - skip_check = true; - } - - } - } - - if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent)) - { - mEnd = intersection; // shorten ray so we only find CLOSER hits - if (mIntersection) - { - *mIntersection = intersection; - } - - mHit = vobj->mDrawable; - } - } - } - - return false; - } -} LL_ALIGN_POSTFIX(16); - -LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - BOOL pick_transparent, - BOOL pick_rigged, - S32* face_hit, // return the face hit - LLVector4a* intersection, // return the intersection point - LLVector2* tex_coord, // return the texture coordinates of the intersection point - LLVector4a* normal, // return the surface normal at the intersection point - LLVector4a* tangent // return the surface tangent at the intersection point - ) - -{ - LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent); - LLDrawable* drawable = intersect.check(mOctree); - - return drawable; -} - -LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, - LLViewerTexture* texture, LLVertexBuffer* buffer, - bool selected, - BOOL fullbright, U8 bump, BOOL particle, F32 part_size) -: LLTrace::MemTrackable<LLDrawInfo, 16>("LLDrawInfo"), - mVertexBuffer(buffer), - mTexture(texture), - mTextureMatrix(NULL), - mModelMatrix(NULL), - mStart(start), - mEnd(end), - mCount(count), - mOffset(offset), - mFullbright(fullbright), - mBump(bump), - mShiny(0), - mParticle(particle), - mPartSize(part_size), - mVSize(0.f), - mGroup(NULL), - mFace(NULL), - mDistance(0.f), - mDrawMode(LLRender::TRIANGLES), - mMaterial(NULL), - mShaderMask(0), - mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA), - mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA), - mHasGlow(FALSE), - mSpecColor(1.0f, 1.0f, 1.0f, 0.5f), - mEnvIntensity(0.0f), - mAlphaMaskCutoff(0.5f), - mDiffuseAlphaMode(0), - mSelected(selected) -{ - mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); -} - -LLDrawInfo::~LLDrawInfo() -{ - /*if (LLSpatialGroup::sNoDelete) - { - LL_ERRS() << "LLDrawInfo deleted illegally!" << LL_ENDL; - }*/ - - if (mFace) - { - mFace->setDrawInfo(NULL); - } - - if (gDebugGL) - { - gPipeline.checkReferences(this); - } -} - -void LLDrawInfo::validate() -{ - mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); -} - -LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) -{ - return new LLVertexBuffer(type_mask, usage); -} - -LLCullResult::LLCullResult() -{ - mVisibleGroupsAllocated = 0; - mAlphaGroupsAllocated = 0; - mOcclusionGroupsAllocated = 0; - mDrawableGroupsAllocated = 0; - mVisibleListAllocated = 0; - mVisibleBridgeAllocated = 0; - - mVisibleGroups.clear(); - mVisibleGroups.push_back(NULL); - mVisibleGroupsEnd = &mVisibleGroups[0]; - mAlphaGroups.clear(); - mAlphaGroups.push_back(NULL); - mAlphaGroupsEnd = &mAlphaGroups[0]; - mOcclusionGroups.clear(); - mOcclusionGroups.push_back(NULL); - mOcclusionGroupsEnd = &mOcclusionGroups[0]; - mDrawableGroups.clear(); - mDrawableGroups.push_back(NULL); - mDrawableGroupsEnd = &mDrawableGroups[0]; - mVisibleList.clear(); - mVisibleList.push_back(NULL); - mVisibleListEnd = &mVisibleList[0]; - mVisibleBridge.clear(); - mVisibleBridge.push_back(NULL); - mVisibleBridgeEnd = &mVisibleBridge[0]; - - for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) - { - mRenderMap[i].clear(); - mRenderMap[i].push_back(NULL); - mRenderMapEnd[i] = &mRenderMap[i][0]; - mRenderMapAllocated[i] = 0; - mRenderMapSize[i] = 0; - } - - clear(); -} - -template <class T, class V> -void LLCullResult::pushBack(T& head, U32& count, V* val) -{ - head[count] = val; - head.push_back(NULL); - count++; -} - -void LLCullResult::clear() -{ - mVisibleGroupsSize = 0; - mVisibleGroupsEnd = &mVisibleGroups[0]; - - mAlphaGroupsSize = 0; - mAlphaGroupsEnd = &mAlphaGroups[0]; - - mOcclusionGroupsSize = 0; - mOcclusionGroupsEnd = &mOcclusionGroups[0]; - - mDrawableGroupsSize = 0; - mDrawableGroupsEnd = &mDrawableGroups[0]; - - mVisibleListSize = 0; - mVisibleListEnd = &mVisibleList[0]; - - mVisibleBridgeSize = 0; - mVisibleBridgeEnd = &mVisibleBridge[0]; - - - for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) - { - for (U32 j = 0; j < mRenderMapSize[i]; j++) - { - mRenderMap[i][j] = 0; - } - mRenderMapSize[i] = 0; - mRenderMapEnd[i] = &(mRenderMap[i][0]); - } -} - -LLCullResult::sg_iterator LLCullResult::beginVisibleGroups() -{ - return &mVisibleGroups[0]; -} - -LLCullResult::sg_iterator LLCullResult::endVisibleGroups() -{ - return mVisibleGroupsEnd; -} - -LLCullResult::sg_iterator LLCullResult::beginAlphaGroups() -{ - return &mAlphaGroups[0]; -} - -LLCullResult::sg_iterator LLCullResult::endAlphaGroups() -{ - return mAlphaGroupsEnd; -} - -LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() -{ - return &mOcclusionGroups[0]; -} - -LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() -{ - return mOcclusionGroupsEnd; -} - -LLCullResult::sg_iterator LLCullResult::beginDrawableGroups() -{ - return &mDrawableGroups[0]; -} - -LLCullResult::sg_iterator LLCullResult::endDrawableGroups() -{ - return mDrawableGroupsEnd; -} - -LLCullResult::drawable_iterator LLCullResult::beginVisibleList() -{ - return &mVisibleList[0]; -} - -LLCullResult::drawable_iterator LLCullResult::endVisibleList() -{ - return mVisibleListEnd; -} - -LLCullResult::bridge_iterator LLCullResult::beginVisibleBridge() -{ - return &mVisibleBridge[0]; -} - -LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() -{ - return mVisibleBridgeEnd; -} - -LLCullResult::drawinfo_iterator LLCullResult::beginRenderMap(U32 type) -{ - return &mRenderMap[type][0]; -} - -LLCullResult::drawinfo_iterator LLCullResult::endRenderMap(U32 type) -{ - return mRenderMapEnd[type]; -} - -void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) -{ - if (mVisibleGroupsSize < mVisibleGroupsAllocated) - { - mVisibleGroups[mVisibleGroupsSize] = group; - } - else - { - pushBack(mVisibleGroups, mVisibleGroupsAllocated, group); - } - ++mVisibleGroupsSize; - mVisibleGroupsEnd = &mVisibleGroups[mVisibleGroupsSize]; -} - -void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) -{ - if (mAlphaGroupsSize < mAlphaGroupsAllocated) - { - mAlphaGroups[mAlphaGroupsSize] = group; - } - else - { - pushBack(mAlphaGroups, mAlphaGroupsAllocated, group); - } - ++mAlphaGroupsSize; - mAlphaGroupsEnd = &mAlphaGroups[mAlphaGroupsSize]; -} - -void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) -{ - if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) - { - mOcclusionGroups[mOcclusionGroupsSize] = group; - } - else - { - pushBack(mOcclusionGroups, mOcclusionGroupsAllocated, group); - } - ++mOcclusionGroupsSize; - mOcclusionGroupsEnd = &mOcclusionGroups[mOcclusionGroupsSize]; -} - -void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) -{ - if (mDrawableGroupsSize < mDrawableGroupsAllocated) - { - mDrawableGroups[mDrawableGroupsSize] = group; - } - else - { - pushBack(mDrawableGroups, mDrawableGroupsAllocated, group); - } - ++mDrawableGroupsSize; - mDrawableGroupsEnd = &mDrawableGroups[mDrawableGroupsSize]; -} - -void LLCullResult::pushDrawable(LLDrawable* drawable) -{ - if (mVisibleListSize < mVisibleListAllocated) - { - mVisibleList[mVisibleListSize] = drawable; - } - else - { - pushBack(mVisibleList, mVisibleListAllocated, drawable); - } - ++mVisibleListSize; - mVisibleListEnd = &mVisibleList[mVisibleListSize]; -} - -void LLCullResult::pushBridge(LLSpatialBridge* bridge) -{ - if (mVisibleBridgeSize < mVisibleBridgeAllocated) - { - mVisibleBridge[mVisibleBridgeSize] = bridge; - } - else - { - pushBack(mVisibleBridge, mVisibleBridgeAllocated, bridge); - } - ++mVisibleBridgeSize; - mVisibleBridgeEnd = &mVisibleBridge[mVisibleBridgeSize]; -} - -void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) -{ - if (mRenderMapSize[type] < mRenderMapAllocated[type]) - { - mRenderMap[type][mRenderMapSize[type]] = draw_info; - } - else - { - pushBack(mRenderMap[type], mRenderMapAllocated[type], draw_info); - } - ++mRenderMapSize[type]; - mRenderMapEnd[type] = &(mRenderMap[type][mRenderMapSize[type]]); -} - - -void LLCullResult::assertDrawMapsEmpty() -{ - for (unsigned int i : mRenderMapSize) - { - if (i != 0) - { - LL_ERRS() << "Stale LLDrawInfo's in LLCullResult!" << LL_ENDL; - } - } -} - +/** + * @file llspatialpartition.cpp + * @brief LLSpatialGroup class implementation and supporting functions + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llspatialpartition.h" + +#include "llappviewer.h" +#include "llcallstack.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" +#include "llimageworker.h" +#include "llviewerwindow.h" +#include "llviewerobjectlist.h" +#include "llvovolume.h" +#include "llvolume.h" +#include "llvolumeoctree.h" +#include "llviewercamera.h" +#include "llface.h" +#include "llfloatertools.h" +#include "llviewercontrol.h" +#include "llviewerregion.h" +#include "llcamera.h" +#include "pipeline.h" +#include "llmeshrepository.h" +#include "llrender.h" +#include "lloctree.h" +#include "llphysicsshapebuilderutil.h" +#include "llvoavatar.h" +#include "llvolumemgr.h" +#include "llviewershadermgr.h" +#include "llcontrolavatar.h" +#include "llfloaterreg.h" // <alchemy/> + +//#pragma optimize("", off) + +static LLTrace::BlockTimerStatHandle FTM_FRUSTUM_CULL("Frustum Culling"); +static LLTrace::BlockTimerStatHandle FTM_CULL_REBOUND("Cull Rebound Partition"); + +extern bool gShiftFrame; + +static U32 sZombieGroups = 0; +U32 LLSpatialGroup::sNodeCount = 0; + +BOOL LLSpatialGroup::sNoDelete = FALSE; + +static F32 sLastMaxTexPriority = 1.f; +static F32 sCurMaxTexPriority = 1.f; + +BOOL LLSpatialPartition::sTeleportRequested = FALSE; + +//static counter for frame to switch LOD on + +void sg_assert(BOOL expr) +{ +#if LL_OCTREE_PARANOIA_CHECK + if (!expr) + { + LL_ERRS() << "Octree invalid!" << LL_ENDL; + } +#endif +} + +//returns: +// 0 if sphere and AABB are not intersecting +// 1 if they are +// 2 if AABB is entirely inside sphere + +S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3& pos, const F32 &rad) +{ + S32 ret = 2; + + LLVector3 min = center - size; + LLVector3 max = center + size; + for (U32 i = 0; i < 3; i++) + { + if (min.mV[i] > pos.mV[i] + rad || + max.mV[i] < pos.mV[i] - rad) + { //totally outside + return 0; + } + + if (min.mV[i] < pos.mV[i] - rad || + max.mV[i] > pos.mV[i] + rad) + { //intersecting + ret = 1; + } + } + + return ret; +} + +LLSpatialGroup::~LLSpatialGroup() +{ + /*if (sNoDelete) + { + LL_ERRS() << "Illegal deletion of LLSpatialGroup!" << LL_ENDL; + }*/ + + if (gDebugGL) + { + gPipeline.checkReferences(this); + } + + if (hasState(DEAD)) + { + sZombieGroups--; + } + + sNodeCount--; + + clearDrawMap(); +} + +void LLSpatialGroup::clearDrawMap() +{ + mDrawMap.clear(); +} + +BOOL LLSpatialGroup::isHUDGroup() +{ + return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ; +} + +void LLSpatialGroup::validate() +{ + ll_assert_aligned(this,64); +#if LL_OCTREE_PARANOIA_CHECK + + sg_assert(!isState(DIRTY)); + sg_assert(!isDead()); + + LLVector4a myMin; + myMin.setSub(mBounds[0], mBounds[1]); + LLVector4a myMax; + myMax.setAdd(mBounds[0], mBounds[1]); + + validateDrawMap(); + + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) + { + LLDrawable* drawable = *i; + sg_assert(drawable->getSpatialGroup() == this); + if (drawable->getSpatialBridge()) + { + sg_assert(drawable->getSpatialBridge() == getSpatialPartition()->asBridge()); + } + + /*if (drawable->isSpatialBridge()) + { + LLSpatialPartition* part = drawable->asPartition(); + if (!part) + { + LL_ERRS() << "Drawable reports it is a spatial bridge but not a partition." << LL_ENDL; + } + LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); + group->validate(); + }*/ + } + + for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i) + { + LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0); + + group->validate(); + + //ensure all children are enclosed in this node + LLVector4a center = group->mBounds[0]; + LLVector4a size = group->mBounds[1]; + + LLVector4a min; + min.setSub(center, size); + LLVector4a max; + max.setAdd(center, size); + + for (U32 j = 0; j < 3; j++) + { + sg_assert(min[j] >= myMin[j]-0.02f); + sg_assert(max[j] <= myMax[j]+0.02f); + } + } + +#endif +} + +void LLSpatialGroup::validateDrawMap() +{ +#if LL_OCTREE_PARANOIA_CHECK + for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i) + { + LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; + for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + { + LLDrawInfo& params = **j; + + params.validate(); + } + } +#endif +} + +BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) +{ + drawablep->updateSpatialExtents(); + + OctreeNode* parent = mOctreeNode->getOctParent(); + + if (mOctreeNode->isInside(drawablep->getPositionGroup()) && + (mOctreeNode->contains(drawablep->getEntry()) || + (drawablep->getBinRadius() > mOctreeNode->getSize()[0] && + parent && parent->getElementCount() >= gOctreeMaxCapacity))) + { + unbound(); + setState(OBJECT_DIRTY); + //setState(GEOM_DIRTY); + return TRUE; + } + + return FALSE; +} + + +BOOL LLSpatialGroup::addObject(LLDrawable *drawablep) +{ + if(!drawablep) + { + return FALSE; + } + { + drawablep->setGroup(this); + setState(OBJECT_DIRTY | GEOM_DIRTY); + setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); + gPipeline.markRebuild(this, TRUE); + if (drawablep->isSpatialBridge()) + { + mBridgeList.push_back((LLSpatialBridge*) drawablep); + } + if (drawablep->getRadius() > 1.f) + { + setState(IMAGE_DIRTY); + } + } + + return TRUE; +} + +void LLSpatialGroup::rebuildGeom() +{ + if (!isDead()) + { + getSpatialPartition()->rebuildGeom(this); + + if (hasState(LLSpatialGroup::MESH_DIRTY)) + { + gPipeline.markMeshDirty(this); + } + } +} + +void LLSpatialGroup::rebuildMesh() +{ + if (!isDead()) + { + getSpatialPartition()->rebuildMesh(this); + } +} + +static LLTrace::BlockTimerStatHandle FTM_REBUILD_VBO("VBO Rebuilt"); +static LLTrace::BlockTimerStatHandle FTM_ADD_GEOMETRY_COUNT("Add Geometry"); +static LLTrace::BlockTimerStatHandle FTM_CREATE_VB("Create VB"); +static LLTrace::BlockTimerStatHandle FTM_GET_GEOMETRY("Get Geometry"); + +void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) +{ + if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY)) + { + return; + } + + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + group->mLastUpdateViewAngle = group->mViewAngle; + } + + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VBO); + + group->clearDrawMap(); + + //get geometry count + U32 index_count = 0; + U32 vertex_count = 0; + + { + LL_RECORD_BLOCK_TIME(FTM_ADD_GEOMETRY_COUNT); + addGeometryCount(group, vertex_count, index_count); + } + + if (vertex_count > 0 && index_count > 0) + { //create vertex buffer containing volume geometry for this node + { + LL_RECORD_BLOCK_TIME(FTM_CREATE_VB); + group->mBuilt = 1.f; + if (group->mVertexBuffer.isNull() || + !group->mVertexBuffer->isWriteable() || + (group->mBufferUsage != (U32)group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) + { + group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); + if (!group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true)) + { + LL_WARNS() << "Failed to allocate Vertex Buffer on rebuild to " + << vertex_count << " vertices and " + << index_count << " indices" << LL_ENDL; + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + stop_glerror(); + } + else + { + if (!group->mVertexBuffer->resizeBuffer(vertex_count, index_count)) + { + // Is likely to cause a crash. If this gets triggered find a way to avoid it (don't forget to reset face) + LL_WARNS() << "Failed to resize Vertex Buffer on rebuild to " + << vertex_count << " vertices and " + << index_count << " indices" << LL_ENDL; + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + stop_glerror(); + } + } + + if (group->mVertexBuffer) + { + LL_RECORD_BLOCK_TIME(FTM_GET_GEOMETRY); + getGeometry(group); + } + } + else + { + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + + group->mLastUpdateTime = gFrameTimeSeconds; + group->clearState(LLSpatialGroup::GEOM_DIRTY); +} + + +void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group) +{ + +} + +LLSpatialGroup* LLSpatialGroup::getParent() +{ + return (LLSpatialGroup*)LLViewerOctreeGroup::getParent(); + } + +BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) + { + if(!drawablep) + { + return FALSE; + } + + unbound(); + if (mOctreeNode && !from_octree) + { + drawablep->setGroup(NULL); + } + else + { + drawablep->setGroup(NULL); + setState(GEOM_DIRTY); + gPipeline.markRebuild(this, TRUE); + + if (drawablep->isSpatialBridge()) + { + for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i) + { + if (*i == drawablep) + { + mBridgeList.erase(i); + break; + } + } + } + + if (getElementCount() == 0) + { //delete draw map on last element removal since a rebuild might never happen + clearDrawMap(); + } + } + return TRUE; +} + +void LLSpatialGroup::shift(const LLVector4a &offset) +{ + LLVector4a t = mOctreeNode->getCenter(); + t.add(offset); + mOctreeNode->setCenter(t); + mOctreeNode->updateMinMax(); + mBounds[0].add(offset); + mExtents[0].add(offset); + mExtents[1].add(offset); + mObjectBounds[0].add(offset); + mObjectExtents[0].add(offset); + mObjectExtents[1].add(offset); + + if (!getSpatialPartition()->mRenderByGroup && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TREE && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE) + { + setState(GEOM_DIRTY); + gPipeline.markRebuild(this, TRUE); + } +} + +class LLSpatialSetState : public OctreeTraveler +{ +public: + U32 mState; + LLSpatialSetState(U32 state) : mState(state) { } + void visit(const OctreeNode* branch) final override { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } +}; + +class LLSpatialSetStateDiff final : public LLSpatialSetState +{ +public: + LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { } + + void traverse(const OctreeNode* n) override + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (!group->hasState(mState)) + { + OctreeTraveler::traverse(n); + } + } +}; + +void LLSpatialGroup::setState(U32 state, S32 mode) +{ + llassert(state <= LLSpatialGroup::STATE_MASK); + + if (mode > STATE_MODE_SINGLE) + { + if (mode == STATE_MODE_DIFF) + { + LLSpatialSetStateDiff setter(state); + setter.traverse(mOctreeNode); + } + else + { + LLSpatialSetState setter(state); + setter.traverse(mOctreeNode); + } + } + else + { + mState |= state; + } +} + +class LLSpatialClearState : public OctreeTraveler +{ +public: + U32 mState; + LLSpatialClearState(U32 state) : mState(state) { } + void visit(const OctreeNode* branch) final override { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } +}; + +class LLSpatialClearStateDiff final : public LLSpatialClearState +{ +public: + LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { } + + void traverse(const OctreeNode* n) override + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (group->hasState(mState)) + { + OctreeTraveler::traverse(n); + } + } +}; + +void LLSpatialGroup::clearState(U32 state, S32 mode) +{ + llassert(state <= LLSpatialGroup::STATE_MASK); + + if (mode > STATE_MODE_SINGLE) + { + if (mode == STATE_MODE_DIFF) + { + LLSpatialClearStateDiff clearer(state); + clearer.traverse(mOctreeNode); + } + else + { + LLSpatialClearState clearer(state); + clearer.traverse(mOctreeNode); + } + } + else + { + mState &= ~state; + } +} + +//====================================== +// Octree Listener Implementation +//====================================== + +LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLOcclusionCullingGroup(node, part), + mObjectBoxSize(1.f), + mGeometryBytes(0), + mSurfaceArea(0.f), + mBuilt(0.f), + mVertexBuffer(NULL), + mBufferUsage(part->mBufferUsage), + mDistance(0.f), + mDepth(0.f), + mLastUpdateDistance(-1.f), + mLastUpdateTime(gFrameTimeSeconds) +{ + ll_assert_aligned(this,16); + + sNodeCount++; + + mViewAngle.splat(0.f); + mLastUpdateViewAngle.splat(-1.f); + + sg_assert(mOctreeNode->getListenerCount() == 0); + setState(SG_INITIAL_STATE_MASK); + gPipeline.markRebuild(this, TRUE); + + mRadius = 1; + mPixelArea = 1024.f; +} + +void LLSpatialGroup::updateDistance(LLCamera &camera) +{ + if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) + { + LL_WARNS() << "Attempted to update distance for camera other than world camera!" << LL_ENDL; + return; + } + + if (gShiftFrame) + { + return; + } + +#if !LL_RELEASE_FOR_DOWNLOAD + if (hasState(LLSpatialGroup::OBJECT_DIRTY)) + { + LL_ERRS() << "Spatial group dirty on distance update." << LL_ENDL; + } +#endif + if (!isEmpty()) + { + mRadius = getSpatialPartition()->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : + (F32) mOctreeNode->getSize().getLength3().getF32(); + mDistance = getSpatialPartition()->calcDistance(this, camera); + mPixelArea = getSpatialPartition()->calcPixelArea(this, camera); + } +} + +F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) +{ + LLVector4a eye; + LLVector4a origin; + origin.load3(camera.getOrigin().mV); + + eye.setSub(group->mObjectBounds[0], origin); + + F32 dist = 0.f; + + if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end()) + { + LLVector4a v = eye; + + dist = eye.getLength3().getF32(); + eye.normalize3fast(); + + if (!group->hasState(LLSpatialGroup::ALPHA_DIRTY)) + { + if (!group->getSpatialPartition()->isBridge()) + { + LLVector4a view_angle = eye; + + LLVector4a diff; + diff.setSub(view_angle, group->mLastUpdateViewAngle); + + if (diff.getLength3().getF32() > 0.64f) + { + group->mViewAngle = view_angle; + group->mLastUpdateViewAngle = view_angle; + //for occasional alpha sorting within the group + //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, + //not setting this node to dirty would be a very good thing + group->setState(LLSpatialGroup::ALPHA_DIRTY); + gPipeline.markRebuild(group, FALSE); + } + } + } + + //calculate depth of node for alpha sorting + + LLVector3 at = camera.getAtAxis(); + + LLVector4a ata; + ata.load3(at.mV); + + LLVector4a t = ata; + //front of bounding box + t.mul(0.25f); + t.mul(group->mObjectBounds[1]); + v.sub(t); + + group->mDepth = v.dot3(ata).getF32(); + } + else + { + dist = eye.getLength3().getF32(); + } + + LL_DEBUGS("RiggedBox") << "calcDistance, group " << group << " camera " << origin << " obj bounds " + << group->mObjectBounds[0] << ", " << group->mObjectBounds[1] + << " dist " << dist << " radius " << group->mRadius << LL_ENDL; + + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } + + return dist; +} + +F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) +{ + return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); +} + +F32 LLSpatialGroup::getUpdateUrgency() const +{ + if (!isVisible()) + { + return 0.f; + } + else + { + F32 time = gFrameTimeSeconds-mLastUpdateTime+4.f; + return time + (mObjectBounds[1].dot3(mObjectBounds[1]).getF32()+1.f)/mDistance; + } +} + +BOOL LLSpatialGroup::changeLOD() +{ + if (hasState(ALPHA_DIRTY | OBJECT_DIRTY)) + { + //a rebuild is going to happen, update distance and LoD + return TRUE; + } + + if (getSpatialPartition()->mSlopRatio > 0.f) + { + F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius)); + + // MAINT-8264 - this check is not robust if it needs to work + // for bounding boxes much larger than the actual enclosed + // objects, and using distance to box center is also + // problematic. Consider the case that you have a large box + // where the enclosed object is in one corner. As you zoom in + // on the corner, the object gets much closer to the camera, + // but the distance to the box center changes very little, and + // an LOD change will not trigger, so object LOD gets "stuck" + // at a too-low value. In the case of the above JIRA, the box + // was large only due to another error, so this logic did not + // need to be changed. + + if (fabsf(ratio) >= getSpatialPartition()->mSlopRatio) + { + LL_DEBUGS("RiggedBox") << "changeLOD true because of ratio compare " + << fabsf(ratio) << " " << getSpatialPartition()->mSlopRatio << LL_ENDL; + LL_DEBUGS("RiggedBox") << "sg " << this << "\nmDistance " << mDistance + << " mLastUpdateDistance " << mLastUpdateDistance + << " mRadius " << mRadius + << " fab ratio " << fabsf(ratio) + << " slop " << getSpatialPartition()->mSlopRatio << LL_ENDL; + + return TRUE; + } + + if (mDistance > mRadius*2.f) + { + return FALSE; + } + } + + if (needsUpdate()) + { + return TRUE; + } + + return FALSE; +} + +void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry) +{ + addObject((LLDrawable*)entry->getDrawable()); + unbound(); + setState(OBJECT_DIRTY); +} + +void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry) +{ + removeObject((LLDrawable*)entry->getDrawable(), TRUE); + LLViewerOctreeGroup::handleRemoval(node, entry); +} + +void LLSpatialGroup::handleDestruction(const TreeNode* node) +{ + if(isDead()) + { + return; + } + setState(DEAD); + + for (element_iter i = getDataBegin(), i_end = getDataEnd(); i != i_end; ++i) + { + LLViewerOctreeEntry* entry = *i; + + if (entry->getGroup() == this) + { + if(entry->hasDrawable()) + { + ((LLDrawable*)entry->getDrawable())->setGroup(NULL); + } + } + } + + clearDrawMap(); + mVertexBuffer = NULL; + mBufferMap.clear(); + sZombieGroups++; + mOctreeNode = NULL; +} + +void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) +{ + if (child->getListenerCount() == 0) + { + new LLSpatialGroup(child, getSpatialPartition()); + } + else + { + OCT_ERRS << "LLSpatialGroup redundancy detected." << LL_ENDL; + } + + unbound(); + + assert_states_valid(this); +} + +void LLSpatialGroup::destroyGL(bool keep_occlusion) +{ + setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); + + if (!keep_occlusion) + { //going to need a rebuild + gPipeline.markRebuild(this, TRUE); + } + + mLastUpdateTime = gFrameTimeSeconds; + mVertexBuffer = NULL; + mBufferMap.clear(); + + clearDrawMap(); + + if (!keep_occlusion) + { + releaseOcclusionQueryObjectNames(); + } + + + for (LLSpatialGroup::element_iter i = getDataBegin(), i_end = getDataEnd(); i != i_end; ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + for (S32 j = 0; j < drawable->getNumFaces(); j++) + { + LLFace* facep = drawable->getFace(j); + if (facep) + { + facep->clearVertexBuffer(); + } + } + } +} + +//============================================== + +LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage, LLViewerRegion* regionp) +: mBridge(NULL), mRenderByGroup(render_by_group) +{ + mRegionp = regionp; + mPartitionType = LLViewerRegion::PARTITION_NONE; + mVertexDataMask = data_mask; + mBufferUsage = buffer_usage; + mDepthMask = FALSE; + mSlopRatio = 0.25f; + mInfiniteFarClip = FALSE; + + new LLSpatialGroup(mOctree, this); +} + +LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) +{ + drawablep->updateSpatialExtents(); + + //keep drawable from being garbage collected + LLPointer<LLDrawable> ptr = drawablep; + + if(!drawablep->getGroup()) + { + assert_octree_valid(mOctree); + mOctree->insert(drawablep->getEntry()); + assert_octree_valid(mOctree); + } + + LLSpatialGroup* group = drawablep->getSpatialGroup(); + llassert(group != NULL); + + if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING)) + { + group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); + } + + return group; +} + +BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) +{ + if (!curp->removeObject(drawablep)) + { + OCT_ERRS << "Failed to remove drawable from octree!" << LL_ENDL; + } + else + { + drawablep->setGroup(NULL); + } + + assert_octree_valid(mOctree); + + return TRUE; +} + +void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate) +{ + // sanity check submitted by open source user bushing Spatula + // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne) + if (!drawablep) + { + OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << LL_ENDL; + return; + } + + BOOL was_visible = curp ? curp->isVisible() : FALSE; + + if (curp && curp->getSpatialPartition() != this) + { + //keep drawable from being garbage collected + LLPointer<LLDrawable> ptr = drawablep; + if (curp->getSpatialPartition()->remove(drawablep, curp)) + { + put(drawablep, was_visible); + return; + } + else + { + OCT_ERRS << "Drawable lost between spatial partitions on outbound transition." << LL_ENDL; + } + } + + if (curp && curp->updateInGroup(drawablep, immediate)) + { + // Already updated, don't need to do anything + assert_octree_valid(mOctree); + return; + } + + //keep drawable from being garbage collected + LLPointer<LLDrawable> ptr = drawablep; + if (curp && !remove(drawablep, curp)) + { + OCT_ERRS << "Move couldn't find existing spatial group!" << LL_ENDL; + } + + put(drawablep, was_visible); +} + +class LLSpatialShift final : public OctreeTraveler +{ +public: + const LLVector4a& mOffset; + + LLSpatialShift(const LLVector4a& offset) : mOffset(offset) { } + + void visit(const OctreeNode* branch) override + { + ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); + } +}; + +void LLSpatialPartition::shift(const LLVector4a &offset) +{ //shift octree node bounding boxes by offset + LLSpatialShift shifter(offset); + shifter.traverse(mOctree); +} + +class LLOctreeCull : public LLViewerOctreeCull +{ +public: + LLOctreeCull(LLCamera* camera) : LLViewerOctreeCull(camera) {} + + bool earlyFail(LLViewerOctreeGroup* base_group) override + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + group->checkOcclusion(); + + if (group->getOctreeNode()->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + gPipeline.markOccluder(group); + return true; + } + + return false; + } + + S32 frustumCheck(const LLViewerOctreeGroup* group) override + { + S32 res = AABBInFrustumNoFarClipGroupBounds(group); + if (res != 0) + { + res = llmin(res, AABBSphereIntersectGroupExtents(group)); + } + return res; + } + + S32 frustumCheckObjects(const LLViewerOctreeGroup* group) override + { + S32 res = AABBInFrustumNoFarClipObjectBounds(group); + if (res != 0) + { + res = llmin(res, AABBSphereIntersectObjectExtents(group)); + } + return res; + } + + void processGroup(LLViewerOctreeGroup* base_group) override + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + if (group->needsUpdate() || + group->getVisible(LLViewerCamera::sCurCameraID) < LLDrawable::getCurrentFrame() - 1) + { + group->doOcclusion(mCamera); + } + gPipeline.markNotCulled(group, *mCamera); + } +}; + +class LLOctreeCullNoFarClip final : public LLOctreeCull +{ +public: + LLOctreeCullNoFarClip(LLCamera* camera) + : LLOctreeCull(camera) { } + + S32 frustumCheck(const LLViewerOctreeGroup* group) override + { + return AABBInFrustumNoFarClipGroupBounds(group); + } + + S32 frustumCheckObjects(const LLViewerOctreeGroup* group) override + { + S32 res = AABBInFrustumNoFarClipObjectBounds(group); + return res; + } +}; + +class LLOctreeCullShadow : public LLOctreeCull +{ +public: + LLOctreeCullShadow(LLCamera* camera) + : LLOctreeCull(camera) { } + + S32 frustumCheck(const LLViewerOctreeGroup* group) final override + { + return AABBInFrustumGroupBounds(group); + } + + S32 frustumCheckObjects(const LLViewerOctreeGroup* group) final override + { + return AABBInFrustumObjectBounds(group); + } +}; + +class LLOctreeCullVisExtents final: public LLOctreeCullShadow +{ +public: + LLOctreeCullVisExtents(LLCamera* camera, LLVector4a& min, LLVector4a& max) + : LLOctreeCullShadow(camera), mEmpty(TRUE), mMin(min), mMax(max) { } + + bool earlyFail(LLViewerOctreeGroup* base_group) override + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + if (group->getOctreeNode()->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + return true; + } + + return false; + } + + void traverse(const OctreeNode* n) override + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (earlyFail(group)) + { + return; + } + + if ((mRes && group->hasState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || + mRes == 2) + { //don't need to do frustum check + OctreeTraveler::traverse(n); + } + else + { + mRes = frustumCheck(group); + + if (mRes) + { //at least partially in, run on down + OctreeTraveler::traverse(n); + } + + mRes = 0; + } + } + + void processGroup(LLViewerOctreeGroup* base_group) override + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + llassert(!group->hasState(LLSpatialGroup::DIRTY) && !group->isEmpty()); + + if (mRes < 2) + { + if (AABBInFrustumObjectBounds(group) > 0) + { + mEmpty = FALSE; + const LLVector4a* exts = group->getObjectExtents(); + update_min_max(mMin, mMax, exts[0]); + update_min_max(mMin, mMax, exts[1]); + } + } + else + { + mEmpty = FALSE; + const LLVector4a* exts = group->getExtents(); + update_min_max(mMin, mMax, exts[0]); + update_min_max(mMin, mMax, exts[1]); + } + } + + BOOL mEmpty; + LLVector4a& mMin; + LLVector4a& mMax; +}; + +class LLOctreeCullDetectVisible final: public LLOctreeCullShadow +{ +public: + LLOctreeCullDetectVisible(LLCamera* camera) + : LLOctreeCullShadow(camera), mResult(FALSE) { } + + bool earlyFail(LLViewerOctreeGroup* base_group) override + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + if (mResult || //already found a node, don't check any more + (group->getOctreeNode()->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isOcclusionState(LLSpatialGroup::OCCLUDED))) + { + return true; + } + + return false; + } + + void processGroup(LLViewerOctreeGroup* base_group) override + { + if (base_group->isVisible()) + { + mResult = TRUE; + } + } + + BOOL mResult; +}; + +class LLOctreeSelect final : public LLOctreeCull +{ +public: + LLOctreeSelect(LLCamera* camera, std::vector<LLDrawable*>* results) + : LLOctreeCull(camera), mResults(results) { } + + bool earlyFail(LLViewerOctreeGroup* group) override { return false; } + void preprocess(LLViewerOctreeGroup* group) override { } + + void processGroup(LLViewerOctreeGroup* base_group) override + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + OctreeNode* branch = group->getOctreeNode(); + + for (OctreeNode::const_element_iter i = branch->getDataBegin(), i_end = branch->getDataEnd(); i != i_end; ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + if (!drawable->isDead()) + { + if (drawable->isSpatialBridge()) + { + drawable->setVisible(*mCamera, mResults, TRUE); + } + else + { + mResults->push_back(drawable); + } + } + } + } + + std::vector<LLDrawable*>* mResults; +}; + +void drawBox(const LLVector3& c, const LLVector3& r) +{ + LLVertexBuffer::unbind(); + + gGL.begin(LLRender::TRIANGLE_STRIP); + //left front + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); + //right front + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); + //right back + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); + //left back + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); + //left front + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); + gGL.end(); + + //bottom + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); + gGL.end(); + + //top + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); + gGL.end(); +} + +void drawBox(const LLVector4a& c, const LLVector4a& r) +{ + drawBox(reinterpret_cast<const LLVector3&>(c), reinterpret_cast<const LLVector3&>(r)); +} + +void drawBoxOutline(const LLVector3& pos, const LLVector3& size) +{ + + llassert(pos.isFinite()); + llassert(size.isFinite()); + + llassert(!llisnan(pos.mV[0])); + llassert(!llisnan(pos.mV[1])); + llassert(!llisnan(pos.mV[2])); + + llassert(!llisnan(size.mV[0])); + llassert(!llisnan(size.mV[1])); + llassert(!llisnan(size.mV[2])); + + LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); + LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); + LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); + LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1)); + + gGL.begin(LLRender::LINES); + + //top + gGL.vertex3fv((pos+v1).mV); + gGL.vertex3fv((pos+v2).mV); + gGL.vertex3fv((pos+v2).mV); + gGL.vertex3fv((pos+v3).mV); + gGL.vertex3fv((pos+v3).mV); + gGL.vertex3fv((pos+v4).mV); + gGL.vertex3fv((pos+v4).mV); + gGL.vertex3fv((pos+v1).mV); + + //bottom + gGL.vertex3fv((pos-v1).mV); + gGL.vertex3fv((pos-v2).mV); + gGL.vertex3fv((pos-v2).mV); + gGL.vertex3fv((pos-v3).mV); + gGL.vertex3fv((pos-v3).mV); + gGL.vertex3fv((pos-v4).mV); + gGL.vertex3fv((pos-v4).mV); + gGL.vertex3fv((pos-v1).mV); + + //right + gGL.vertex3fv((pos+v1).mV); + gGL.vertex3fv((pos-v3).mV); + + gGL.vertex3fv((pos+v4).mV); + gGL.vertex3fv((pos-v2).mV); + + //left + gGL.vertex3fv((pos+v2).mV); + gGL.vertex3fv((pos-v4).mV); + + gGL.vertex3fv((pos+v3).mV); + gGL.vertex3fv((pos-v1).mV); + + gGL.end(); +} + +void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size) +{ + drawBoxOutline(reinterpret_cast<const LLVector3&>(pos), reinterpret_cast<const LLVector3&>(size)); +} + +class LLOctreeDirty final : public OctreeTraveler +{ +public: + LLOctreeDirty(bool no_rebuild) : mNoRebuild(no_rebuild){} + + void visit(const OctreeNode* state) override + { + LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); + group->destroyGL(); + + for (LLSpatialGroup::element_iter i = group->getDataBegin(), i_end = group->getDataEnd(); i != i_end; ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + if (drawable->getVObj().notNull()) + { + drawable->getVObj()->resetVertexBuffers(); + } + if (!mNoRebuild && drawable->getVObj().notNull() && !group->getSpatialPartition()->mRenderByGroup) + { + gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE); + } + } + + for (LLSpatialBridge* bridge : group->mBridgeList) + { + traverse(bridge->mOctree); + } + } + +private: + BOOL mNoRebuild; +}; + +void LLSpatialPartition::restoreGL() +{ +} + +void LLSpatialPartition::resetVertexBuffers() +{ + LLOctreeDirty dirty(sTeleportRequested); + dirty.traverse(mOctree); +} + +BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) +{ + LLVector4a visMina, visMaxa; + visMina.load3(visMin.mV); + visMaxa.load3(visMax.mV); + + { + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); + } + + LLOctreeCullVisExtents vis(&camera, visMina, visMaxa); + vis.traverse(mOctree); + + visMin.set(visMina.getF32ptr()); + visMax.set(visMaxa.getF32ptr()); + return vis.mEmpty; +} + +BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera) +{ + LLOctreeCullDetectVisible vis(&camera); + vis.traverse(mOctree); + return vis.mResult; +} + +S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select) +{ +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); +#endif + { + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); + } + +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->validate(); +#endif + + LLOctreeSelect selecter(&camera, results); + selecter.traverse(mOctree); + + return 0; + } + +S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion) +{ +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); +#endif + { + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); + } + +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->validate(); +#endif + + if (LLPipeline::sShadowRender) + { + LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); + LLOctreeCullShadow culler(&camera); + culler.traverse(mOctree); + } + else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) + { + LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); + LLOctreeCullNoFarClip culler(&camera); + culler.traverse(mOctree); + } + else + { + LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); + LLOctreeCull culler(&camera); + culler.traverse(mOctree); + } + + return 0; +} + +void pushVerts(LLDrawInfo* params, U32 mask) +{ + LLRenderPass::applyModelMatrix(*params); + params->mVertexBuffer->setBuffer(mask); + params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES, + params->mStart, params->mEnd, params->mCount, params->mOffset); +} + +void pushVerts(LLSpatialGroup* group, U32 mask) +{ + for (auto& pair : group->mDrawMap) + { + for (LLDrawInfo* params : pair.second) + { + pushVerts(params, mask); + } + } +} + +void pushVerts(LLFace* face, U32 mask) +{ + if (face) + { + llassert(face->verify()); + + LLVertexBuffer* buffer = face->getVertexBuffer(); + + if (buffer && (face->getGeomCount() >= 3)) + { + buffer->setBuffer(mask); + U16 start = face->getGeomStart(); + U16 end = start + face->getGeomCount()-1; + U32 count = face->getIndicesCount(); + U16 offset = face->getIndicesStart(); + buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + } +} + +void pushVerts(LLDrawable* drawable, U32 mask) +{ + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + pushVerts(drawable->getFace(i), mask); + } +} + +void pushVerts(LLVolume* volume) +{ + LLVertexBuffer::unbind(); + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mNumVertices, face.mPositions, NULL, face.mNumIndices, face.mIndices); + } +} + +void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) +{ + if (buffer) + { + buffer->setBuffer(mask); + buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); + } +} + +void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true) +{ + if (group->getSpatialPartition()->mRenderByGroup) + { + if (!group->mDrawMap.empty()) + { + LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); + LLRenderPass::applyModelMatrix(*params); + + if (push_alpha) + { + pushBufferVerts(group->mVertexBuffer, mask); + } + + for (auto& buff_pair : group->mBufferMap) + { + for (auto& buff_tex_pair : buff_pair.second) + { + for (LLVertexBuffer* buff : buff_tex_pair.second) + { + pushBufferVerts(buff, mask); + } + } + } + } + } + /*else + { + //const LLVector4a* bounds = group->getBounds(); + //drawBox(bounds[0], bounds[1]); + }*/ +} + +void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) +{ + LLDrawInfo* params = NULL; + + static const std::array<LLColor4, 7> colors {{ + LLColor4::green, + LLColor4::green1, + LLColor4::green2, + LLColor4::green3, + LLColor4::green4, + LLColor4::green5, + LLColor4::green6 + }}; + + U32 col = 0; + + for (auto& i : group->mDrawMap) + { + for (auto& j : i.second) + { + params = j; + LLRenderPass::applyModelMatrix(*params); + gGL.diffuseColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f); + params->mVertexBuffer->setBuffer(mask); + params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES, + params->mStart, params->mEnd, params->mCount, params->mOffset); + col = (col+1)%colors.size(); + } + } +} + +void renderOctree(LLSpatialGroup* group) +{ + //render solid object bounding box, color + //coded by buffer usage and activity + gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); + LLVector4 col; + if (group->mBuilt > 0.f) + { + group->mBuilt -= 2.f * gFrameIntervalSeconds.value(); + if (group->mBufferUsage == GL_STATIC_DRAW_ARB) + { + col.setVec(1.0f, 0, 0, group->mBuilt*0.5f); + } + else + { + col.setVec(0.1f,0.1f,1,0.1f); + //col.setVec(1.0f, 1.0f, 0, sinf(group->mBuilt*3.14159f)*0.5f); + } + + if (group->mBufferUsage != GL_STATIC_DRAW_ARB) + { + LLGLDepthTest gl_depth(FALSE, FALSE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + gGL.diffuseColor4f(1,0,0,group->mBuilt); + gGL.flush(); + gGL.setLineWidth(5.f); + + const LLVector4a* bounds = group->getObjectBounds(); + drawBoxOutline(bounds[0], bounds[1]); + gGL.flush(); + gGL.setLineWidth(1.f); + gGL.flush(); + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + if (!group->getSpatialPartition()->isBridge()) + { + gGL.pushMatrix(); + LLVector3 trans = drawable->getRegion()->getOriginAgent(); + gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); + } + + for (S32 j = 0; j < drawable->getNumFaces(); j++) + { + LLFace* face = drawable->getFace(j); + if (face && face->getVertexBuffer()) + { + if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f) + { + gGL.diffuseColor4f(0, 1, 0, group->mBuilt); + } + else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f) + { + gGL.diffuseColor4f(1, 0, 0, group->mBuilt); + } + else + { + continue; + } + + face->getVertexBuffer()->setBuffer(LLVertexBuffer::MAP_VERTEX); + //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f, + // (face->mExtents[1]-face->mExtents[0])*0.5f); + face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart()); + } + } + + if (!group->getSpatialPartition()->isBridge()) + { + gGL.popMatrix(); + } + } + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.diffuseColor4f(1,1,1,1); + } + } + else + { + if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->isEmpty() + && group->getSpatialPartition()->mRenderByGroup) + { + col.setVec(0.8f, 0.4f, 0.1f, 0.1f); + } + else + { + col.setVec(0.1f, 0.1f, 1.f, 0.1f); + } + } + + gGL.diffuseColor4fv(col.mV); + LLVector4a fudge; + fudge.splat(0.001f); + + //LLVector4a size = group->mObjectBounds[1]; + //size.mul(1.01f); + //size.add(fudge); + + //{ + // LLGLDepthTest depth(GL_TRUE, GL_FALSE); + // drawBox(group->mObjectBounds[0], fudge); + //} + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + //if (group->mBuilt <= 0.f) + { + //draw opaque outline + //gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], 1.f); + //drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); + + gGL.diffuseColor4f(0,1,1,1); + + const LLVector4a* bounds = group->getBounds(); + drawBoxOutline(bounds[0], bounds[1]); + + //draw bounding box for draw info + /*if (group->getSpatialPartition()->mRenderByGroup) + { + gGL.diffuseColor4f(1.0f, 0.75f, 0.25f, 0.6f); + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + LLDrawInfo* draw_info = *j; + LLVector4a center; + center.setAdd(draw_info->mExtents[1], draw_info->mExtents[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(draw_info->mExtents[1], draw_info->mExtents[0]); + size.mul(0.5f); + drawBoxOutline(center, size); + } + } + }*/ + } + +// LLSpatialGroup::OctreeNode* node = group->mOctreeNode; +// gGL.diffuseColor4f(0,1,0,1); +// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize())); +} + +std::set<LLSpatialGroup*> visible_selected_groups; + +void renderVisibility(LLSpatialGroup* group, LLCamera* camera) +{ + /*LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + LLGLEnable cull(GL_CULL_FACE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);*/ + + /*BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && + !group->isEmpty(); + + + if (render_objects) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + + LLGLDisable blend(GL_BLEND); + gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false); + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.setLineWidth(4.f); + gGL.diffuseColor4f(0.f, 0.5f, 0.f, 1.f); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false); + gGL.setLineWidth(1.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + bool selected = false; + + for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) + { + LLDrawable* drawable = *iter; + if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) + { + selected = true; + break; + } + } + + if (selected) + { //store for rendering occlusion volume as overlay + visible_selected_groups.insert(group); + } + }*/ + + /*if (render_objects) + { + LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.diffuseColor4f(0, 0.5f, 0, 0.5f); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); + } + + { + LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL); + + if (render_objects) + { + gGL.diffuseColor4f(0.f, 0.5f, 0.f,1.f); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); + } + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + if (render_objects) + { + gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); + + bool selected = false; + + for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) + { + LLDrawable* drawable = *iter; + if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) + { + selected = true; + break; + } + } + + if (selected) + { //store for rendering occlusion volume as overlay + visible_selected_groups.insert(group); + } + } + }*/ +} + +void renderXRay(LLSpatialGroup* group, LLCamera* camera) +{ + BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && + !group->isEmpty(); + + if (render_objects) + { + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false); + + bool selected = false; + + for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) + { + LLDrawable* drawable = (LLDrawable*)(*iter)->getDrawable(); + if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) + { + selected = true; + break; + } + } + + if (selected) + { //store for rendering occlusion volume as overlay + + if (!group->getSpatialPartition()->isBridge()) + { + visible_selected_groups.insert(group); + } + else + { + visible_selected_groups.insert(group->getSpatialPartition()->asBridge()->getSpatialGroup()); + } + } + } +} + +void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color) +{ + gGL.color4fv(color.mV); + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); + gGL.vertex3fv((position + LLVector3(size, 0.f, 0.f)).mV); + gGL.vertex3fv((position - LLVector3(0.f, size, 0.f)).mV); + gGL.vertex3fv((position + LLVector3(0.f, size, 0.f)).mV); + gGL.vertex3fv((position - LLVector3(0.f, 0.f, size)).mV); + gGL.vertex3fv((position + LLVector3(0.f, 0.f, size)).mV); + } + gGL.end(); +} + +void renderUpdateType(LLDrawable* drawablep) +{ + LLViewerObject* vobj = drawablep->getVObj(); + if (!vobj || OUT_UNKNOWN == vobj->getLastUpdateType()) + { + return; + } + LLGLEnable blend(GL_BLEND); + switch (vobj->getLastUpdateType()) + { + case OUT_FULL: + gGL.diffuseColor4f(0,1,0,0.5f); + break; + case OUT_TERSE_IMPROVED: + gGL.diffuseColor4f(0,1,1,0.5f); + break; + case OUT_FULL_COMPRESSED: + if (vobj->getLastUpdateCached()) + { + gGL.diffuseColor4f(1,0,0,0.5f); + } + else + { + gGL.diffuseColor4f(1,1,0,0.5f); + } + break; + case OUT_FULL_CACHED: + gGL.diffuseColor4f(0,0,1,0.5f); + break; + default: + LL_WARNS() << "Unknown update_type " << vobj->getLastUpdateType() << LL_ENDL; + break; + }; + S32 num_faces = drawablep->getNumFaces(); + if (num_faces) + { + for (S32 i = 0; i < num_faces; ++i) + { + pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); + } + } +} + +void renderComplexityDisplay(LLDrawable* drawablep) +{ + LLViewerObject* vobj = drawablep->getVObj(); + if (!vobj) + { + return; + } + + LLVOVolume *voVol = vobj->asVolume();; + + if (!voVol) + { + return; + } + + if (!voVol->isRoot()) + { + return; + } + + LLVOVolume::texture_cost_t textures; + F32 cost = (F32) voVol->getRenderCost(textures); + + // add any child volumes + LLViewerObject::const_child_list_t children = voVol->getChildren(); + for (const auto& iter : children) + { + const LLViewerObject *child = iter; + const LLVOVolume *child_volume = dynamic_cast<const LLVOVolume*>(child); + if (child_volume) + { + cost += child_volume->getRenderCost(textures); + } + } + + // add texture cost + for (auto& texture : textures) + { + // add the cost of each individual texture in the linkset + cost += texture.second; + } + + F32 cost_max = (F32) LLVOVolume::getRenderComplexityMax(); + + + + // allow user to set a static color scale + if (gSavedSettings.getS32("RenderComplexityStaticMax") > 0) + { + cost_max = gSavedSettings.getS32("RenderComplexityStaticMax"); + } + + F32 cost_ratio = cost / cost_max; + + // cap cost ratio at 1.0f in case cost_max is at a low threshold + cost_ratio = cost_ratio > 1.0f ? 1.0f : cost_ratio; + + LLGLEnable blend(GL_BLEND); + + LLColor4 color; + const LLColor4 color_min = gSavedSettings.getColor4("RenderComplexityColorMin"); + const LLColor4 color_mid = gSavedSettings.getColor4("RenderComplexityColorMid"); + const LLColor4 color_max = gSavedSettings.getColor4("RenderComplexityColorMax"); + + if (cost_ratio < 0.5f) + { + color = color_min * (1 - cost_ratio * 2) + color_mid * (cost_ratio * 2); + } + else + { + color = color_mid * (1 - (cost_ratio - 0.5) * 2) + color_max * ((cost_ratio - 0.5) * 2); + } + + LLSD color_val = color.getValue(); + + // don't highlight objects below the threshold + if (cost > gSavedSettings.getS32("RenderComplexityThreshold")) + { + gGL.diffuseColor4f(color[0],color[1],color[2],0.5f); + + + S32 num_faces = drawablep->getNumFaces(); + if (num_faces) + { + for (S32 i = 0; i < num_faces; ++i) + { + pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); + } + } + LLViewerObject::const_child_list_t children = voVol->getChildren(); + for (const auto& iter : children) + { + const LLViewerObject *child = iter; + if (child) + { + num_faces = child->getNumFaces(); + if (num_faces) + { + for (S32 i = 0; i < num_faces; ++i) + { + pushVerts(child->mDrawable->getFace(i), LLVertexBuffer::MAP_VERTEX); + } + } + } + } + } + + voVol->setDebugText(llformat("%4.0f", cost)); +} + +void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) +{ + if (set_color) + { + if (drawable->isSpatialBridge()) + { + gGL.diffuseColor4f(1,0.5f,0,1); // orange + } + else if (drawable->getVOVolume()) + { + if (drawable->isRoot()) + { + gGL.diffuseColor4f(1,1,0,1); // yellow + } + else + { + gGL.diffuseColor4f(0,1,0,1); // green + } + } + else if (drawable->getVObj()) + { + switch (drawable->getVObj()->getPCode()) + { + case LLViewerObject::LL_VO_SURFACE_PATCH: + gGL.diffuseColor4f(0,1,1,1); // cyan + break; + case LLViewerObject::LL_VO_CLOUDS: + // no longer used + break; + case LLViewerObject::LL_VO_PART_GROUP: + case LLViewerObject::LL_VO_HUD_PART_GROUP: + gGL.diffuseColor4f(0,0,1,1); // blue + break; + case LLViewerObject::LL_VO_VOID_WATER: + case LLViewerObject::LL_VO_WATER: + gGL.diffuseColor4f(0,0.5f,1,1); // medium blue + break; + case LL_PCODE_LEGACY_TREE: + gGL.diffuseColor4f(0,0.5f,0,1); // dark green + break; + default: + auto avatar = drawable->getVObj()->asAvatar(); + if (avatar->isControlAvatar()) + { + LLControlAvatar* cav = static_cast<LLControlAvatar*>(avatar); + bool has_pos_constraint = (cav->mPositionConstraintFixup != LLVector3()); + bool has_scale_constraint = (cav->mScaleConstraintFixup != 1.0f); + if (has_pos_constraint || has_scale_constraint) + { + gGL.diffuseColor4f(1,0,0,1); + } + else + { + gGL.diffuseColor4f(0,1,0.5,1); + } + } + else + { + gGL.diffuseColor4f(1,0,1,1); // magenta + } + break; + } + } + else + { + gGL.diffuseColor4f(1,0,0,1); + } + } + + const LLVector4a* ext; + LLVector4a pos, size; + + if (drawable->getVOVolume()) + { + //render face bounding boxes + for (S32 i = 0; i < drawable->getNumFaces(); i++) + { + LLFace* facep = drawable->getFace(i); + if (facep) + { + ext = facep->mExtents; + + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + + drawBoxOutline(pos,size); + } + } + } + + //render drawable bounding box + ext = drawable->getSpatialExtents(); + + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + + LLViewerObject* vobj = drawable->getVObj(); + if (vobj && vobj->onActiveList()) + { + gGL.flush(); + gGL.setLineWidth(llmax(4.f*sinf(gFrameTimeSeconds*2.f)+1.f, 1.f)); + //gGL.setLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f)); + stop_glerror(); + drawBoxOutline(pos,size); + gGL.flush(); + gGL.setLineWidth(1.f); + } + else + { + drawBoxOutline(pos,size); + } +} + +void renderNormals(LLDrawable* drawablep) +{ + LLVertexBuffer::unbind(); + + LLVOVolume* vol = drawablep->getVOVolume(); + if (vol) + { + LLVolume* volume = vol->getVolume(); + gGL.pushMatrix(); + gGL.multMatrix((F32*) vol->getRelativeXform().mMatrix); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLVector4a scale(gSavedSettings.getF32("RenderDebugNormalScale")); + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + + for (S32 j = 0; j < face.mNumVertices; ++j) + { + gGL.begin(LLRender::LINES); + LLVector4a n,p; + + n.setMul(face.mNormals[j], scale); + p.setAdd(face.mPositions[j], n); + + gGL.diffuseColor4f(1,1,1,1); + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); + + if (face.mTangents) + { + n.setMul(face.mTangents[j], scale); + p.setAdd(face.mPositions[j], n); + + gGL.diffuseColor4f(0,1,1,1); + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); + } + gGL.end(); + } + } + + gGL.popMatrix(); + } +} + +S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& scale) +{ + const S32 DEFAULT_DETAIL = 1; + const F32 LARGE_THRESHOLD = 5.f; + const F32 MEGA_THRESHOLD = 25.f; + + S32 detail = DEFAULT_DETAIL; + F32 avg_scale = (scale[0]+scale[1]+scale[2])/3.f; + + if (avg_scale > LARGE_THRESHOLD) + { + detail += 1; + if (avg_scale > MEGA_THRESHOLD) + { + detail += 1; + } + } + + return detail; +} + +void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLColor4& line_color) +{ + LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); + LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); + + const LLVector3 center(0,0,0); + const LLVector3 size(0.25f,0.25f,0.25f); + + if (decomp) + { + if (!decomp->mBaseHullMesh.empty()) + { + gGL.diffuseColor4fv(color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions, decomp->mBaseHullMesh.mNormals); + } + else + { + gMeshRepo.buildPhysicsMesh(*decomp); + gGL.diffuseColor4f(0,1,1,1); + drawBoxOutline(center, size); + } + + } + else + { + gGL.diffuseColor3f(1,0,1); + drawBoxOutline(center, size); + } +} + +void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColor4& line_color) +{ + gGL.diffuseColor4fv(color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); + LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glPolygonOffset(3.f, 3.f); + gGL.setLineWidth(3.f); + gGL.diffuseColor4fv(line_color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); + gGL.setLineWidth(1.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +} + +void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) +{ + U8 physics_type = volume->getPhysicsShapeType(); + + if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE || volume->isFlexible()) + { + return; + } + + //not allowed to return at this point without rendering *something* + + F32 threshold = gSavedSettings.getF32("ObjectCostHighThreshold"); + F32 cost = volume->getObjectCost(); + + LLColor4 low = gSavedSettings.getColor4("ObjectCostLowColor"); + LLColor4 mid = gSavedSettings.getColor4("ObjectCostMidColor"); + LLColor4 high = gSavedSettings.getColor4("ObjectCostHighColor"); + + F32 normalizedCost = 1.f - exp( -(cost / threshold) ); + + LLColor4 color; + if ( normalizedCost <= 0.5f ) + { + color = lerp( low, mid, 2.f * normalizedCost ); + } + else + { + color = lerp( mid, high, 2.f * ( normalizedCost - 0.5f ) ); + } + + LLColor4 line_color = color*0.5f; + + U32 data_mask = LLVertexBuffer::MAP_VERTEX; + + LLVolumeParams volume_params = volume->getVolume()->getParams(); + + LLPhysicsVolumeParams physics_params(volume_params, + physics_type == LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + + LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification physics_spec; + LLPhysicsShapeBuilderUtil::determinePhysicsShape(physics_params, volume->getScale(), physics_spec); + + U32 type = physics_spec.getType(); + + LLVector3 center(0,0,0); + LLVector3 size(0.25f,0.25f,0.25f); + + gGL.pushMatrix(); + gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); + + if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH) + { + LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); + LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); + + if (decomp) + { //render a physics based mesh + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + if (!decomp->mHull.empty()) + { //decomposition exists, use that + + if (decomp->mMesh.empty()) + { + gMeshRepo.buildPhysicsMesh(*decomp); + } + + for (auto& i : decomp->mMesh) + { + render_hull(i, color, line_color); + } + } + else if (!decomp->mPhysicsShapeMesh.empty()) + { + //decomp has physics mesh, render that mesh + gGL.diffuseColor4fv(color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.diffuseColor4fv(line_color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + else + { //no mesh or decomposition, render base hull + renderMeshBaseHull(volume, data_mask, color, line_color); + + if (decomp->mPhysicsShapeMesh.empty()) + { + //attempt to fetch physics shape mesh if available + gMeshRepo.fetchPhysicsShape(mesh_id); + } + } + } + else + { + gGL.diffuseColor3f(1,1,0); + drawBoxOutline(center, size); + } + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_CONVEX || + type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) + { + if (volume->isMesh()) + { + renderMeshBaseHull(volume, data_mask, color, line_color); + } + else + { + LLVolumeParams volume_params = volume->getVolume()->getParams(); + S32 detail = get_physics_detail(volume_params, volume->getScale()); + LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); + + if (!phys_volume->mHullPoints) + { //build convex hull + std::vector<LLVector3> pos; + std::vector<U16> index; + + S32 index_offset = 0; + + for (S32 i = 0; i < phys_volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = phys_volume->getVolumeFace(i); + if (index_offset + face.mNumVertices > 65535) + { + continue; + } + + for (S32 j = 0; j < face.mNumVertices; ++j) + { + pos.emplace_back(face.mPositions[j].getF32ptr()); + } + + for (S32 j = 0; j < face.mNumIndices; ++j) + { + index.push_back(face.mIndices[j]+index_offset); + } + + index_offset += face.mNumVertices; + } + + if (!pos.empty() && !index.empty()) + { + LLCDMeshData mesh; + mesh.mIndexBase = &index[0]; + mesh.mVertexBase = pos[0].mV; + mesh.mNumVertices = pos.size(); + mesh.mVertexStrideBytes = 12; + mesh.mIndexStrideBytes = 6; + mesh.mIndexType = LLCDMeshData::INT_16; + + mesh.mNumTriangles = index.size()/3; + + LLCDMeshData res; + + LLConvexDecomposition::getInstance()->generateSingleHullMeshFromMesh( &mesh, &res ); + + //copy res into phys_volume + phys_volume->mHullPoints = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*res.mNumVertices); + phys_volume->mNumHullPoints = res.mNumVertices; + + S32 idx_size = (res.mNumTriangles*3*2+0xF) & ~0xF; + phys_volume->mHullIndices = (U16*) ll_aligned_malloc_16(idx_size); + phys_volume->mNumHullIndices = res.mNumTriangles*3; + + const F32* v = res.mVertexBase; + + for (S32 i = 0; i < res.mNumVertices; ++i) + { + F32* p = (F32*) ((U8*)v+i*res.mVertexStrideBytes); + phys_volume->mHullPoints[i].load3(p); + } + + if (res.mIndexType == LLCDMeshData::INT_16) + { + for (S32 i = 0; i < res.mNumTriangles; ++i) + { + U16* idx = (U16*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); + + phys_volume->mHullIndices[i*3+0] = idx[0]; + phys_volume->mHullIndices[i*3+1] = idx[1]; + phys_volume->mHullIndices[i*3+2] = idx[2]; + } + } + else + { + for (S32 i = 0; i < res.mNumTriangles; ++i) + { + U32* idx = (U32*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); + + phys_volume->mHullIndices[i*3+0] = (U16) idx[0]; + phys_volume->mHullIndices[i*3+1] = (U16) idx[1]; + phys_volume->mHullIndices[i*3+2] = (U16) idx[2]; + } + } + } + } + + if (phys_volume->mHullPoints && phys_volume->mHullIndices && phys_volume->mNumHullPoints > 0 && phys_volume->mNumHullIndices > 0) + { + //render hull + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + gGL.diffuseColor4fv(line_color.mV); + LLVertexBuffer::unbind(); + + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); + + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + + gGL.diffuseColor4fv(color.mV); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + + } + else + { + gGL.diffuseColor4f(1,0,1,1); + drawBoxOutline(center, size); + } + + LLPrimitive::sVolumeManager->unrefVolume(phys_volume); + } + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX) + { + LLVector3 center = physics_spec.getCenter(); + LLVector3 scale = physics_spec.getScale(); + LLVector3 vscale = volume->getScale()*2.f; + scale.set(scale[0]/vscale[0], scale[1]/vscale[1], scale[2]/vscale[2]); + + gGL.diffuseColor4fv(color.mV); + drawBox(center, scale); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE) + { + LLVolumeParams volume_params; + volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE ); + volume_params.setBeginAndEndS( 0.f, 1.f ); + volume_params.setBeginAndEndT( 0.f, 1.f ); + volume_params.setRatio ( 1, 1 ); + volume_params.setShear ( 0, 0 ); + LLVolume* sphere = LLPrimitive::sVolumeManager->refVolume(volume_params, 3); + + gGL.diffuseColor4fv(color.mV); + pushVerts(sphere); + LLPrimitive::sVolumeManager->unrefVolume(sphere); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER) + { + LLVolumeParams volume_params; + volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); + volume_params.setBeginAndEndS( 0.f, 1.f ); + volume_params.setBeginAndEndT( 0.f, 1.f ); + volume_params.setRatio ( 1, 1 ); + volume_params.setShear ( 0, 0 ); + LLVolume* cylinder = LLPrimitive::sVolumeManager->refVolume(volume_params, 3); + + gGL.diffuseColor4fv(color.mV); + pushVerts(cylinder); + LLPrimitive::sVolumeManager->unrefVolume(cylinder); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_MESH) + { + LLVolumeParams volume_params = volume->getVolume()->getParams(); + S32 detail = get_physics_detail(volume_params, volume->getScale()); + + LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + gGL.diffuseColor4fv(line_color.mV); + pushVerts(phys_volume); + + gGL.diffuseColor4fv(color.mV); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + pushVerts(phys_volume); + LLPrimitive::sVolumeManager->unrefVolume(phys_volume); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) + { + LLVolumeParams volume_params = volume->getVolume()->getParams(); + S32 detail = get_physics_detail(volume_params, volume->getScale()); + + LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); + + if (phys_volume->mHullPoints && phys_volume->mHullIndices) + { + gGL.diffuseColor4fv(line_color.mV); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + + gGL.diffuseColor4fv(color.mV); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mNumHullPoints, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + } + else + { + gGL.diffuseColor3f(1,0,1); + drawBoxOutline(center, size); + gMeshRepo.buildHull(volume_params, detail); + } + LLPrimitive::sVolumeManager->unrefVolume(phys_volume); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SCULPT) + { + //TODO: implement sculpted prim physics display + } + else + { + LL_ERRS() << "Unhandled type" << LL_ENDL; + } + + gGL.popMatrix(); +} + +void renderPhysicsShapes(LLSpatialGroup* group) +{ + for (OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + + if (drawable->isSpatialBridge()) + { + LLSpatialBridge* bridge = drawable->asPartition()->asBridge(); + + if (bridge) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + bridge->renderPhysicsShapes(); + gGL.popMatrix(); + } + } + else + { + LLVOVolume* volume = drawable->getVOVolume(); + if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE ) + { + if (!group->getSpatialPartition()->isBridge()) + { + gGL.pushMatrix(); + LLVector3 trans = drawable->getRegion()->getOriginAgent(); + gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); + renderPhysicsShape(drawable, volume); + gGL.popMatrix(); + } + else + { + renderPhysicsShape(drawable, volume); + } + } + else + { + LLViewerObject* object = drawable->getVObj(); + if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*) object->getRegion()->mRenderMatrix.mMatrix); + //push face vertices for terrain + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* face = drawable->getFace(i); + if (face) + { + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + + gGL.diffuseColor3f(0.2f, 1.f, 0.3f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + } + } + } + gGL.popMatrix(); + } + } + } + } +} + +void renderTexturePriority(LLDrawable* drawable) +{ + for (int face=0; face<drawable->getNumFaces(); ++face) + { + LLFace *facep = drawable->getFace(face); + + LLVector4 cold(0,0,0.25f); + LLVector4 hot(1,0.25f,0.25f); + + LLVector4 boost_cold(0,0,0,0); + LLVector4 boost_hot(0,1,0,1); + + LLGLDisable blend(GL_BLEND); + + //LLViewerTexture* imagep = facep->getTexture(); + //if (imagep) + if (facep) + { + + //F32 vsize = imagep->mMaxVirtualSize; + F32 vsize = facep->getPixelArea(); + + if (vsize > sCurMaxTexPriority) + { + sCurMaxTexPriority = vsize; + } + + F32 t = vsize/sLastMaxTexPriority; + + LLVector4 col = lerp(cold, hot, t); + gGL.diffuseColor4fv(col.mV); + } + //else + //{ + // gGL.diffuseColor4f(1,0,1,1); + //} + + LLVector4a center; + center.setAdd(facep->mExtents[1],facep->mExtents[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(facep->mExtents[1],facep->mExtents[0]); + size.mul(0.5f); + size.add(LLVector4a(0.01f)); + drawBox(center, size); + + /*S32 boost = imagep->getBoostLevel(); + if (boost>LLGLTexture::BOOST_NONE) + { + F32 t = (F32) boost / (F32) (LLGLTexture::BOOST_MAX_LEVEL-1); + LLVector4 col = lerp(boost_cold, boost_hot, t); + LLGLEnable blend_on(GL_BLEND); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE); + gGL.diffuseColor4fv(col.mV); + drawBox(center, size); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + }*/ + } +} + +void renderPoints(LLDrawable* drawablep) +{ + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + if (drawablep->getNumFaces()) + { + gGL.begin(LLRender::POINTS); + gGL.diffuseColor3f(1,1,1); + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace * face = drawablep->getFace(i); + if (face) + { + gGL.vertex3fv(face->mCenterLocal.mV); + } + } + gGL.end(); + } +} + +void renderTextureAnim(LLDrawInfo* params) +{ + if (!params->mTextureMatrix) + { + return; + } + + LLGLEnable blend(GL_BLEND); + gGL.diffuseColor4f(1,1,0,0.5f); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); +} + +void renderBatchSize(LLDrawInfo* params) +{ + LLGLEnable offset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.f, 1.f); + if (params->mDebugColor == LLColor4U::black) + { + params->mDebugColor = LLColor4U(ll_rand(255), ll_rand(255), ll_rand(255), 255U); + } + gGL.diffuseColor4ubv((U8*)params->mDebugColor.mV); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); +} + +void renderShadowFrusta(LLDrawInfo* params) +{ + LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLVector4a center; + center.setAdd(params->mExtents[1], params->mExtents[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(params->mExtents[1],params->mExtents[0]); + size.mul(0.5f); + + if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size)) + { + gGL.diffuseColor3f(1,0,0); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); + } + if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size)) + { + gGL.diffuseColor3f(0,1,0); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); + } + if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size)) + { + gGL.diffuseColor3f(0,0,1); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); + } + if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size)) + { + gGL.diffuseColor3f(1,0,1); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); + } + + gGL.setSceneBlendType(LLRender::BT_ALPHA); +} + +void renderTexelDensity(LLDrawable* drawable) +{ + if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF + || LLViewerTexture::sCheckerBoardImagep.isNull()) + { + return; + } + + LLGLEnable _(GL_BLEND); + //gObjectFullbrightProgram.bind(); + + LLMatrix4 checkerboard_matrix; + S32 discard_level = -1; + + for (S32 f = 0; f < drawable->getNumFaces(); f++) + { + LLFace* facep = drawable->getFace(f); + LLVertexBuffer* buffer = facep->getVertexBuffer(); + LLViewerTexture* texturep = facep->getTexture(); + + if (texturep == NULL) continue; + + switch(LLViewerTexture::sDebugTexelsMode) + { + case LLViewerTexture::DEBUG_TEXELS_CURRENT: + discard_level = -1; + break; + case LLViewerTexture::DEBUG_TEXELS_DESIRED: + { + LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); + discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + break; + } + default: + case LLViewerTexture::DEBUG_TEXELS_FULL: + discard_level = 0; + break; + } + + checkerboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + + gGL.getTexUnit(0)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((GLfloat*)&checkerboard_matrix.mMatrix); + + if (buffer && (facep->getGeomCount() >= 3)) + { + buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + U16 start = facep->getGeomStart(); + U16 end = start + facep->getGeomCount()-1; + U32 count = facep->getIndicesCount(); + U16 offset = facep->getIndicesStart(); + buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + + //S32 num_textures = llmax(1, (S32)params->mTextureList.size()); + + //for (S32 i = 0; i < num_textures; i++) + //{ + // LLViewerTexture* texturep = params->mTextureList.empty() ? params->mTexture.get() : params->mTextureList[i].get(); + // if (texturep == NULL) continue; + + // LLMatrix4 checkboard_matrix; + // S32 discard_level = -1; + // switch(LLViewerTexture::sDebugTexelsMode) + // { + // case LLViewerTexture::DEBUG_TEXELS_CURRENT: + // discard_level = -1; + // break; + // case LLViewerTexture::DEBUG_TEXELS_DESIRED: + // { + // LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); + // discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + // break; + // } + // default: + // case LLViewerTexture::DEBUG_TEXELS_FULL: + // discard_level = 0; + // break; + // } + + // checkboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + // gGL.getTexUnit(i)->activate(); + + // glMatrixMode(GL_TEXTURE); + // glPushMatrix(); + // glLoadIdentity(); + // //gGL.matrixMode(LLRender::MM_TEXTURE); + // glLoadMatrixf((GLfloat*) checkboard_matrix.mMatrix); + + // gGL.getTexUnit(i)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + + // pushVerts(params, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL ); + + // glPopMatrix(); + // glMatrixMode(GL_MODELVIEW); + // //gGL.matrixMode(LLRender::MM_MODELVIEW); + //} +} + + +void renderLights(LLDrawable* drawablep) +{ + if (!drawablep->isLight()) + { + return; + } + + if (drawablep->getNumFaces()) + { + LLGLEnable blend(GL_BLEND); + gGL.diffuseColor4f(0,1,1,0.5f); + + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace * face = drawablep->getFace(i); + if (face) + { + pushVerts(face, LLVertexBuffer::MAP_VERTEX); + } + } + + const LLVector4a* ext = drawablep->getSpatialExtents(); + + LLVector4a pos; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + + { + LLGLDepthTest depth(GL_FALSE, GL_TRUE); + gGL.diffuseColor4f(1,1,1,1); + drawBoxOutline(pos, size); + } + + gGL.diffuseColor4f(1,1,0,1); + F32 rad = drawablep->getVOVolume()->getLightRadius(); + drawBoxOutline(pos, LLVector4a(rad)); + } +} + +class LLRenderOctreeRaycast final : public LLOctreeTriangleRayIntersect +{ +public: + + + LLRenderOctreeRaycast(const LLVector4a& start, const LLVector4a& dir, F32* closest_t) + : LLOctreeTriangleRayIntersect(start, dir, NULL, closest_t, NULL, NULL, NULL, NULL) + { + + } + + void visit(const LLOctreeNode<LLVolumeTriangle>* branch) override + { + LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0); + + LLVector3 center, size; + + if (branch->isEmpty()) + { + gGL.diffuseColor3f(1.f,0.2f,0.f); + center.set(branch->getCenter().getF32ptr()); + size.set(branch->getSize().getF32ptr()); + } + else + { + gGL.diffuseColor3f(0.75f, 1.f, 0.f); + center.set(vl->mBounds[0].getF32ptr()); + size.set(vl->mBounds[1].getF32ptr()); + } + + drawBoxOutline(center, size); + + for (U32 i = 0; i < 2; i++) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE, i == 1 ? GL_LEQUAL : GL_GREATER); + + if (i == 1) + { + gGL.diffuseColor4f(0,1,1,0.5f); + } + else + { + gGL.diffuseColor4f(0,0.5f,0.5f, 0.25f); + drawBoxOutline(center, size); + } + + if (i == 1) + { + gGL.flush(); + gGL.setLineWidth(3.f); + } + + gGL.begin(LLRender::TRIANGLES); + for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); + iter != branch->getDataEnd(); + ++iter) + { + const LLVolumeTriangle* tri = *iter; + + gGL.vertex3fv(tri->mV[0]->getF32ptr()); + gGL.vertex3fv(tri->mV[1]->getF32ptr()); + gGL.vertex3fv(tri->mV[2]->getF32ptr()); + } + gGL.end(); + + if (i == 1) + { + gGL.flush(); + gGL.setLineWidth(1.f); + } + } + } +}; + +void renderRaycast(LLDrawable* drawablep) +{ + if (drawablep->getNumFaces()) + { + LLGLEnable blend(GL_BLEND); + gGL.diffuseColor4f(0,1,1,0.5f); + + if (drawablep->getVOVolume()) + { + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + //pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); + + bool transform = true; + if (drawablep->isState(LLDrawable::RIGGED)) + { + volume = vobj->getRiggedVolume(); + transform = false; + } + + if (volume) + { + LLVector3 trans = drawablep->getRegion()->getOriginAgent(); + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + + gGL.pushMatrix(); + gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); + gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); + + LLVector4a start, end; + if (transform) + { + LLVector3 v_start(gDebugRaycastStart.getF32ptr()); + LLVector3 v_end(gDebugRaycastEnd.getF32ptr()); + + v_start = vobj->agentPositionToVolume(v_start); + v_end = vobj->agentPositionToVolume(v_end); + + start.load3(v_start.mV); + end.load3(v_end.mV); + } + else + { + start = gDebugRaycastStart; + end = gDebugRaycastEnd; + } + + LLVector4a dir; + dir.setSub(end, start); + + gGL.flush(); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + { + //render face positions + gGL.diffuseColor4f(0.f, 1.f, 1.f, 0.5f); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mNumVertices, face.mPositions, NULL, face.mNumIndices, face.mIndices); + } + + if (!volume->isUnique()) + { + F32 t = 1.f; + + if (!face.mOctree) + { + ((LLVolumeFace*) &face)->createOctree(); + } + + LLRenderOctreeRaycast render(start, dir, &t); + + render.traverse(face.mOctree); + } + + gGL.popMatrix(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } + } + else if (drawablep->isAvatar()) + { + if (drawablep->getVObj() == gDebugRaycastObject) + { + LLGLDepthTest depth(GL_FALSE); + LLVOAvatar* av = (LLVOAvatar*) drawablep->getVObj().get(); + av->renderCollisionVolumes(); + } + } + + if (drawablep->getVObj() == gDebugRaycastObject) + { + // draw intersection point + gGL.pushMatrix(); + gGL.loadMatrix(gGLModelView); + LLVector3 translate(gDebugRaycastIntersection.getF32ptr()); + gGL.translatef(translate.mV[0], translate.mV[1], translate.mV[2]); + LLCoordFrame orient; + LLVector4a debug_binormal; + + debug_binormal.setCross3(gDebugRaycastNormal, gDebugRaycastTangent); + debug_binormal.mul(gDebugRaycastTangent.getF32ptr()[3]); + + LLVector3 normal(gDebugRaycastNormal.getF32ptr()); + LLVector3 binormal(debug_binormal.getF32ptr()); + + orient.lookDir(normal, binormal); + LLMatrix4 rotation; + orient.getRotMatrixToParent(rotation); + gGL.multMatrix((float*)rotation.mMatrix); + + gGL.diffuseColor4f(1,0,0,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.1f, 0.022f, 0.022f)); + gGL.diffuseColor4f(0,1,0,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.021f, 0.1f, 0.021f)); + gGL.diffuseColor4f(0,0,1,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.02f, 0.02f, 0.1f)); + gGL.popMatrix(); + + // draw bounding box of prim + const LLVector4a* ext = drawablep->getSpatialExtents(); + + LLVector4a pos; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + + LLGLDepthTest depth(GL_FALSE, GL_TRUE); + gGL.diffuseColor4f(0,0.5f,0.5f,1); + drawBoxOutline(pos, size); + } + } +} + + +void renderAvatarCollisionVolumes(LLVOAvatar* avatar) +{ + avatar->renderCollisionVolumes(); +} + +void renderAvatarBones(LLVOAvatar* avatar) +{ + avatar->renderBones(); +} + +void renderAgentTarget(LLVOAvatar* avatar) +{ + // render these for self only (why, i don't know) + if (avatar->isSelf()) + { + renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); + renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f)); + renderCrossHairs(avatar->mRoot->getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); + renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f)); + } +} + +class LLOctreeRenderNonOccluded final : public OctreeTraveler +{ +public: + LLCamera* mCamera; + LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {} + + void traverse(const OctreeNode* node) override + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) + { + node->accept(this); + stop_glerror(); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + stop_glerror(); + } + + //draw tight fit bounding boxes for spatial group + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) + { + group->rebuildGeom(); + group->rebuildMesh(); + + renderOctree(group); + stop_glerror(); + } + + //render visibility wireframe + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { + group->rebuildGeom(); + group->rebuildMesh(); + + gGL.flush(); + gGL.pushMatrix(); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + renderVisibility(group, mCamera); + stop_glerror(); + gGLLastMatrix = NULL; + gGL.popMatrix(); + gGL.diffuseColor4f(1,1,1,1); + } + } + } + + void visit(const OctreeNode* branch) override + { + LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); + const LLVector4a* bounds = group->getBounds(); + if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) + { + return; + } + + LLGLDisable stencil(GL_STENCIL_TEST); + + group->rebuildGeom(); + group->rebuildMesh(); + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) + { + if (!group->isEmpty()) + { + gGL.diffuseColor3f(0,0,1); + const LLVector4a* obj_bounds = group->getObjectBounds(); + drawBoxOutline(obj_bounds[0], obj_bounds[1]); + } + } + + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) + { + renderBoundingBox(drawable); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_NORMALS)) + { + renderNormals(drawable); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BUILD_QUEUE)) + { + if (drawable->isState(LLDrawable::IN_REBUILD_Q2)) + { + gGL.diffuseColor4f(0.6f, 0.6f, 0.1f, 1.f); + const LLVector4a* ext = drawable->getSpatialExtents(); + LLVector4a center; + center.setAdd(ext[0], ext[1]); + center.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + drawBoxOutline(center, size); + } + } + + if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + renderTexturePriority(drawable); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS)) + { + renderPoints(drawable); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LIGHTS)) + { + renderLights(drawable); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + renderRaycast(drawable); + } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_UPDATE_TYPE)) + { + renderUpdateType(drawable); + } + if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY)) + { + renderComplexityDisplay(drawable); + } + if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + renderTexelDensity(drawable); + } + + LLVOAvatar* avatar = drawable->getVObj()->asAvatar(); + + if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)) + { + renderAvatarCollisionVolumes(avatar); + } + + if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_JOINTS)) + { + renderAvatarBones(avatar); + } + + if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET)) + { + renderAgentTarget(avatar); + } + + if (gDebugGL) + { + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* facep = drawable->getFace(i); + if (facep) + { + U8 index = facep->getTextureIndex(); + if (facep->mDrawInfo) + { + if (index < 255) + { + if (facep->mDrawInfo->mTextureList.size() <= index) + { + LL_ERRS() << "Face texture index out of bounds." << LL_ENDL; + } + else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) + { + LL_ERRS() << "Face texture index incorrect." << LL_ENDL; + } + } + } + } + } + } + } + + for (auto& i : group->mDrawMap) + { + LLSpatialGroup::drawmap_elem_t& draw_vec = i.second; + for (auto& j : draw_vec) + { + LLDrawInfo* draw_info = j; + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_ANIM)) + { + renderTextureAnim(draw_info); + } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BATCH_SIZE)) + { + renderBatchSize(draw_info); + } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + renderShadowFrusta(draw_info); + } + } + } + } +}; + +class LLOctreeRenderXRay final : public OctreeTraveler +{ +public: + LLCamera* mCamera; + LLOctreeRenderXRay(LLCamera* camera): mCamera(camera) {} + + void traverse(const OctreeNode* node) override + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) + { + node->accept(this); + stop_glerror(); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + stop_glerror(); + } + + //render visibility wireframe + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { + group->rebuildGeom(); + group->rebuildMesh(); + + gGL.flush(); + gGL.pushMatrix(); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + renderXRay(group, mCamera); + stop_glerror(); + gGLLastMatrix = NULL; + gGL.popMatrix(); + } + } + } + + void visit(const OctreeNode* node) override {} + +}; + +class LLOctreeRenderPhysicsShapes final : public OctreeTraveler +{ +public: + LLCamera* mCamera; + LLOctreeRenderPhysicsShapes(LLCamera* camera): mCamera(camera) {} + + void traverse(const OctreeNode* node) override + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) + { + node->accept(this); + stop_glerror(); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + stop_glerror(); + } + + group->rebuildGeom(); + group->rebuildMesh(); + + renderPhysicsShapes(group); + } + } + + void visit(const OctreeNode* branch) override + { + + } +}; + +class LLOctreePushBBoxVerts final : public OctreeTraveler +{ +public: + LLCamera* mCamera; + LLOctreePushBBoxVerts(LLCamera* camera): mCamera(camera) {} + + void traverse(const OctreeNode* node) override + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustum(bounds[0], bounds[1])) + { + node->accept(this); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + } + } + + void visit(const OctreeNode* branch) override + { + LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) + { + return; + } + + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + renderBoundingBox(drawable, FALSE); + } + } +}; + +void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) +{ + LLOctreePushBBoxVerts pusher(camera); + pusher.traverse(mOctree); +} + +class LLOctreeStateCheck final : public OctreeTraveler +{ +public: + U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS]; + + LLOctreeStateCheck() + { + for (unsigned int& i : mInheritedMask) + { + i = 0; + } + } + + void traverse(const OctreeNode* node) override + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + node->accept(this); + + + U32 temp[LLViewerCamera::NUM_CAMERAS]; + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + temp[i] = mInheritedMask[i]; + mInheritedMask[i] |= group->mOcclusionState[i] & LLSpatialGroup::OCCLUDED; + } + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mInheritedMask[i] = temp[i]; + } + } + + + void visit(const OctreeNode* state) override + { + LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + if (mInheritedMask[i] && !(group->mOcclusionState[i] & mInheritedMask[i])) + { + LL_ERRS() << "Spatial group failed inherited mask test." << LL_ENDL; + } + } + + if (group->hasState(LLSpatialGroup::DIRTY)) + { + assert_parent_state(group, LLSpatialGroup::DIRTY); + } + } + + void assert_parent_state(LLSpatialGroup* group, U32 state) + { + LLSpatialGroup* parent = group->getParent(); + while (parent) + { + if (!parent->hasState(state)) + { + LL_ERRS() << "Spatial group failed parent state check." << LL_ENDL; + } + parent = parent->getParent(); + } + } +}; + + +void LLSpatialPartition::renderPhysicsShapes() +{ + LLSpatialBridge* bridge = asBridge(); + LLCamera* camera = LLViewerCamera::getInstance(); + + if (bridge) + { + camera = NULL; + } + + gGL.flush(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.setLineWidth(3.f); + LLOctreeRenderPhysicsShapes render_physics(camera); + render_physics.traverse(mOctree); + gGL.flush(); + gGL.setLineWidth(1.f); +} + +void LLSpatialPartition::renderDebug() +{ + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | + LLPipeline::RENDER_DEBUG_OCCLUSION | + LLPipeline::RENDER_DEBUG_LIGHTS | + LLPipeline::RENDER_DEBUG_BATCH_SIZE | + LLPipeline::RENDER_DEBUG_UPDATE_TYPE | + LLPipeline::RENDER_DEBUG_BBOXES | + LLPipeline::RENDER_DEBUG_NORMALS | + LLPipeline::RENDER_DEBUG_POINTS | + LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | + LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | + LLPipeline::RENDER_DEBUG_RAYCAST | + LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | + LLPipeline::RENDER_DEBUG_AVATAR_JOINTS | + LLPipeline::RENDER_DEBUG_AGENT_TARGET | + //LLPipeline::RENDER_DEBUG_BUILD_QUEUE | + LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | + LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY | + LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + return; + } + + if (LLGLSLShader::sNoFixedFunction) + { + gDebugProgram.bind(); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + //sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds); + sLastMaxTexPriority = (F32) LLViewerCamera::getInstance()->getScreenPixelArea(); + sCurMaxTexPriority = 0.f; + } + + LLGLDisable cullface(GL_CULL_FACE); + LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gPipeline.disableLights(); + + LLSpatialBridge* bridge = asBridge(); + LLCamera* camera = LLViewerCamera::getInstance(); + + if (bridge) + { + camera = NULL; + } + + LLOctreeStateCheck checker; + checker.traverse(mOctree); + + LLOctreeRenderNonOccluded render_debug(camera); + render_debug.traverse(mOctree); + + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { + { + LLGLEnable cull(GL_CULL_FACE); + + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.diffuseColor4f(0.5f, 0.0f, 0, 0.25f); + + LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(-1.f, -1.f); + + LLOctreeRenderXRay xray(camera); + xray.traverse(mOctree); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } + if (LLGLSLShader::sNoFixedFunction) + { + gDebugProgram.unbind(); + } +} + +void LLSpatialGroup::drawObjectBox(LLColor4 col) +{ + gGL.diffuseColor4fv(col.mV); + LLVector4a size; + size = mObjectBounds[1]; + size.mul(1.01f); + size.add(LLVector4a(0.001f)); + drawBox(mObjectBounds[0], size); +} + +bool LLSpatialPartition::isHUDPartition() +{ + return mPartitionType == LLViewerRegion::PARTITION_HUD ; +} + +BOOL LLSpatialPartition::isVisible(const LLVector3& v) +{ + if (!LLViewerCamera::getInstance()->sphereInFrustum(v, 4.0f)) + { + return FALSE; + } + + return TRUE; +} + +LL_ALIGN_PREFIX(16) +class LLOctreeIntersect : public LLOctreeTraveler<LLViewerOctreeEntry> +{ +public: + LL_ALIGN_16(LLVector4a mStart); + LL_ALIGN_16(LLVector4a mEnd); + + S32 *mFaceHit; + LLVector4a *mIntersection; + LLVector2 *mTexCoord; + LLVector4a *mNormal; + LLVector4a *mTangent; + LLDrawable* mHit; + BOOL mPickTransparent; + BOOL mPickRigged; + + LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, + S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + : mStart(start), + mEnd(end), + mFaceHit(face_hit), + mIntersection(intersection), + mTexCoord(tex_coord), + mNormal(normal), + mTangent(tangent), + mHit(NULL), + mPickTransparent(pick_transparent), + mPickRigged(pick_rigged) + { + } + + void visit(const OctreeNode* branch) override + { + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + { + check(*i); + } + } + + virtual LLDrawable* check(const OctreeNode* node) + { + node->accept(this); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + const OctreeNode* child = node->getChild(i); + LLVector3 res; + + LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0); + + LLVector4a size; + LLVector4a center; + + const LLVector4a* bounds = group->getBounds(); + size = bounds[1]; + center = bounds[0]; + + LLVector4a local_start = mStart; + LLVector4a local_end = mEnd; + + if (group->getSpatialPartition()->isBridge()) + { + LLMatrix4a local_matrix4a(group->getSpatialPartition()->asBridge()->mDrawable->getRenderMatrix()); + local_matrix4a.invert(); + + local_matrix4a.affineTransform(mStart, local_start); + local_matrix4a.affineTransform(mEnd, local_end); + } + + if (LLLineSegmentBoxIntersect(local_start, local_end, center, size)) + { + check(child); + } + } + + return mHit; + } + + virtual bool check(LLViewerOctreeEntry* entry) + { + LLDrawable* drawable = (LLDrawable*)entry->getDrawable(); + + if (!drawable || !gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible()) + { + return false; + } + + if (drawable->isSpatialBridge()) + { + LLSpatialPartition *part = drawable->asPartition(); + LLSpatialBridge* bridge = part->asBridge(); + if (bridge && gPipeline.hasRenderType(bridge->mDrawableType)) + { + check(part->mOctree); + } + } + else + { + LLViewerObject* vobj = drawable->getVObj(); + + if (vobj) + { + LLVector4a intersection; + bool skip_check = false; + if (vobj->isAvatar()) + { + LLVOAvatar* avatar = (LLVOAvatar*) vobj; + if ((mPickRigged) || ((avatar->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) + { + LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent); + if (hit) + { + mEnd = intersection; + if (mIntersection) + { + *mIntersection = intersection; + } + + mHit = hit->mDrawable; + skip_check = true; + } + + } + } + + if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent)) + { + mEnd = intersection; // shorten ray so we only find CLOSER hits + if (mIntersection) + { + *mIntersection = intersection; + } + + mHit = vobj->mDrawable; + } + } + } + + return false; + } +} LL_ALIGN_POSTFIX(16); + +LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + BOOL pick_transparent, + BOOL pick_rigged, + S32* face_hit, // return the face hit + LLVector4a* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point + ) + +{ + LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent); + LLDrawable* drawable = intersect.check(mOctree); + + return drawable; +} + +LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, + LLViewerTexture* texture, LLVertexBuffer* buffer, + bool selected, + BOOL fullbright, U8 bump, BOOL particle, F32 part_size) +: LLTrace::MemTrackable<LLDrawInfo, 16>("LLDrawInfo"), + mVertexBuffer(buffer), + mTexture(texture), + mTextureMatrix(NULL), + mModelMatrix(NULL), + mStart(start), + mEnd(end), + mCount(count), + mOffset(offset), + mFullbright(fullbright), + mBump(bump), + mShiny(0), + mParticle(particle), + mPartSize(part_size), + mVSize(0.f), + mGroup(NULL), + mFace(NULL), + mDistance(0.f), + mDrawMode(LLRender::TRIANGLES), + mMaterial(NULL), + mShaderMask(0), + mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA), + mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA), + mHasGlow(FALSE), + mSpecColor(1.0f, 1.0f, 1.0f, 0.5f), + mEnvIntensity(0.0f), + mAlphaMaskCutoff(0.5f), + mDiffuseAlphaMode(0), + mSelected(selected) +{ + mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); +} + +LLDrawInfo::~LLDrawInfo() +{ + /*if (LLSpatialGroup::sNoDelete) + { + LL_ERRS() << "LLDrawInfo deleted illegally!" << LL_ENDL; + }*/ + + if (mFace) + { + mFace->setDrawInfo(NULL); + } + + if (gDebugGL) + { + gPipeline.checkReferences(this); + } +} + +void LLDrawInfo::validate() +{ + mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); +} + +LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) +{ + return new LLVertexBuffer(type_mask, usage); +} + +LLCullResult::LLCullResult() +{ + mVisibleGroupsAllocated = 0; + mAlphaGroupsAllocated = 0; + mOcclusionGroupsAllocated = 0; + mDrawableGroupsAllocated = 0; + mVisibleListAllocated = 0; + mVisibleBridgeAllocated = 0; + + mVisibleGroups.clear(); + mVisibleGroups.push_back(NULL); + mVisibleGroupsEnd = &mVisibleGroups[0]; + mAlphaGroups.clear(); + mAlphaGroups.push_back(NULL); + mAlphaGroupsEnd = &mAlphaGroups[0]; + mOcclusionGroups.clear(); + mOcclusionGroups.push_back(NULL); + mOcclusionGroupsEnd = &mOcclusionGroups[0]; + mDrawableGroups.clear(); + mDrawableGroups.push_back(NULL); + mDrawableGroupsEnd = &mDrawableGroups[0]; + mVisibleList.clear(); + mVisibleList.push_back(NULL); + mVisibleListEnd = &mVisibleList[0]; + mVisibleBridge.clear(); + mVisibleBridge.push_back(NULL); + mVisibleBridgeEnd = &mVisibleBridge[0]; + + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + mRenderMap[i].clear(); + mRenderMap[i].push_back(NULL); + mRenderMapEnd[i] = &mRenderMap[i][0]; + mRenderMapAllocated[i] = 0; + mRenderMapSize[i] = 0; + } + + clear(); +} + +template <class T, class V> +void LLCullResult::pushBack(T& head, U32& count, V* val) +{ + head[count] = val; + head.push_back(NULL); + count++; +} + +void LLCullResult::clear() +{ + mVisibleGroupsSize = 0; + mVisibleGroupsEnd = &mVisibleGroups[0]; + + mAlphaGroupsSize = 0; + mAlphaGroupsEnd = &mAlphaGroups[0]; + + mOcclusionGroupsSize = 0; + mOcclusionGroupsEnd = &mOcclusionGroups[0]; + + mDrawableGroupsSize = 0; + mDrawableGroupsEnd = &mDrawableGroups[0]; + + mVisibleListSize = 0; + mVisibleListEnd = &mVisibleList[0]; + + mVisibleBridgeSize = 0; + mVisibleBridgeEnd = &mVisibleBridge[0]; + + + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + for (U32 j = 0; j < mRenderMapSize[i]; j++) + { + mRenderMap[i][j] = 0; + } + mRenderMapSize[i] = 0; + mRenderMapEnd[i] = &(mRenderMap[i][0]); + } +} + +LLCullResult::sg_iterator LLCullResult::beginVisibleGroups() +{ + return &mVisibleGroups[0]; +} + +LLCullResult::sg_iterator LLCullResult::endVisibleGroups() +{ + return mVisibleGroupsEnd; +} + +LLCullResult::sg_iterator LLCullResult::beginAlphaGroups() +{ + return &mAlphaGroups[0]; +} + +LLCullResult::sg_iterator LLCullResult::endAlphaGroups() +{ + return mAlphaGroupsEnd; +} + +LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() +{ + return &mOcclusionGroups[0]; +} + +LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() +{ + return mOcclusionGroupsEnd; +} + +LLCullResult::sg_iterator LLCullResult::beginDrawableGroups() +{ + return &mDrawableGroups[0]; +} + +LLCullResult::sg_iterator LLCullResult::endDrawableGroups() +{ + return mDrawableGroupsEnd; +} + +LLCullResult::drawable_iterator LLCullResult::beginVisibleList() +{ + return &mVisibleList[0]; +} + +LLCullResult::drawable_iterator LLCullResult::endVisibleList() +{ + return mVisibleListEnd; +} + +LLCullResult::bridge_iterator LLCullResult::beginVisibleBridge() +{ + return &mVisibleBridge[0]; +} + +LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() +{ + return mVisibleBridgeEnd; +} + +LLCullResult::drawinfo_iterator LLCullResult::beginRenderMap(U32 type) +{ + return &mRenderMap[type][0]; +} + +LLCullResult::drawinfo_iterator LLCullResult::endRenderMap(U32 type) +{ + return mRenderMapEnd[type]; +} + +void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) +{ + if (mVisibleGroupsSize < mVisibleGroupsAllocated) + { + mVisibleGroups[mVisibleGroupsSize] = group; + } + else + { + pushBack(mVisibleGroups, mVisibleGroupsAllocated, group); + } + ++mVisibleGroupsSize; + mVisibleGroupsEnd = &mVisibleGroups[mVisibleGroupsSize]; +} + +void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) +{ + if (mAlphaGroupsSize < mAlphaGroupsAllocated) + { + mAlphaGroups[mAlphaGroupsSize] = group; + } + else + { + pushBack(mAlphaGroups, mAlphaGroupsAllocated, group); + } + ++mAlphaGroupsSize; + mAlphaGroupsEnd = &mAlphaGroups[mAlphaGroupsSize]; +} + +void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) +{ + if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) + { + mOcclusionGroups[mOcclusionGroupsSize] = group; + } + else + { + pushBack(mOcclusionGroups, mOcclusionGroupsAllocated, group); + } + ++mOcclusionGroupsSize; + mOcclusionGroupsEnd = &mOcclusionGroups[mOcclusionGroupsSize]; +} + +void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) +{ + if (mDrawableGroupsSize < mDrawableGroupsAllocated) + { + mDrawableGroups[mDrawableGroupsSize] = group; + } + else + { + pushBack(mDrawableGroups, mDrawableGroupsAllocated, group); + } + ++mDrawableGroupsSize; + mDrawableGroupsEnd = &mDrawableGroups[mDrawableGroupsSize]; +} + +void LLCullResult::pushDrawable(LLDrawable* drawable) +{ + if (mVisibleListSize < mVisibleListAllocated) + { + mVisibleList[mVisibleListSize] = drawable; + } + else + { + pushBack(mVisibleList, mVisibleListAllocated, drawable); + } + ++mVisibleListSize; + mVisibleListEnd = &mVisibleList[mVisibleListSize]; +} + +void LLCullResult::pushBridge(LLSpatialBridge* bridge) +{ + if (mVisibleBridgeSize < mVisibleBridgeAllocated) + { + mVisibleBridge[mVisibleBridgeSize] = bridge; + } + else + { + pushBack(mVisibleBridge, mVisibleBridgeAllocated, bridge); + } + ++mVisibleBridgeSize; + mVisibleBridgeEnd = &mVisibleBridge[mVisibleBridgeSize]; +} + +void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) +{ + if (mRenderMapSize[type] < mRenderMapAllocated[type]) + { + mRenderMap[type][mRenderMapSize[type]] = draw_info; + } + else + { + pushBack(mRenderMap[type], mRenderMapAllocated[type], draw_info); + } + ++mRenderMapSize[type]; + mRenderMapEnd[type] = &(mRenderMap[type][mRenderMapSize[type]]); +} + + +void LLCullResult::assertDrawMapsEmpty() +{ + for (unsigned int i : mRenderMapSize) + { + if (i != 0) + { + LL_ERRS() << "Stale LLDrawInfo's in LLCullResult!" << LL_ENDL; + } + } +} + diff --git a/indra/newview/llviewerbuildconfig.h.in b/indra/newview/llviewerbuildconfig.h.in index a66a358cd2ffb5aed7356b32ccb3a5f949b14b43..ea5d2e8a50f5e7ac1775d8d65f4bd510a6ecbfb7 100644 --- a/indra/newview/llviewerbuildconfig.h.in +++ b/indra/newview/llviewerbuildconfig.h.in @@ -1,50 +1,50 @@ -/** - * @file llviewerbuildconfig.h - * @brief Viewer build-time config options. - * @author Rye Mutt <rye@alchemyviewer.org> - * - * $LicenseInfo:firstyear=2019&license=viewerlgpl$ - * Alchemy Viewer Source Code - * Copyright (C) 2019, Rye Mutt <rye@alchemyviewer.org> - * - * 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 - * - * $/LicenseInfo$ - */ - -#ifndef LL_LLVIEWERBUILDCONFIG_H -#define LL_LLVIEWERBUILDCONFIG_H - -// Build Configuration -#define LLBUILD_CONFIG "@CMAKE_BUILD_TYPE@" - -// Version Information -#define LL_VIEWER_CHANNEL "@VIEWER_CHANNEL@" -#define LL_VIEWER_VERSION_MAJOR @VIEWER_VERSION_MAJOR@ -#define LL_VIEWER_VERSION_MINOR @VIEWER_VERSION_MINOR@ -#define LL_VIEWER_VERSION_PATCH @VIEWER_VERSION_PATCH@ -#define LL_VIEWER_VERSION_BUILD @VIEWER_VERSION_REVISION@ - -// Graphics Utils -#cmakedefine01 USE_NVAPI - -// Audio Engines -#cmakedefine01 USE_FMODSTUDIO -#cmakedefine01 USE_OPENAL - -// Media Plugins -#cmakedefine01 LIBVLCPLUGIN - +/** + * @file llviewerbuildconfig.h + * @brief Viewer build-time config options. + * @author Rye Mutt <rye@alchemyviewer.org> + * + * $LicenseInfo:firstyear=2019&license=viewerlgpl$ + * Alchemy Viewer Source Code + * Copyright (C) 2019, Rye Mutt <rye@alchemyviewer.org> + * + * 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 + * + * $/LicenseInfo$ + */ + +#ifndef LL_LLVIEWERBUILDCONFIG_H +#define LL_LLVIEWERBUILDCONFIG_H + +// Build Configuration +#define LLBUILD_CONFIG "@CMAKE_BUILD_TYPE@" + +// Version Information +#define LL_VIEWER_CHANNEL "@VIEWER_CHANNEL@" +#define LL_VIEWER_VERSION_MAJOR @VIEWER_VERSION_MAJOR@ +#define LL_VIEWER_VERSION_MINOR @VIEWER_VERSION_MINOR@ +#define LL_VIEWER_VERSION_PATCH @VIEWER_VERSION_PATCH@ +#define LL_VIEWER_VERSION_BUILD @VIEWER_VERSION_REVISION@ + +// Graphics Utils +#cmakedefine01 USE_NVAPI + +// Audio Engines +#cmakedefine01 USE_FMODSTUDIO +#cmakedefine01 USE_OPENAL + +// Media Plugins +#cmakedefine01 LIBVLCPLUGIN + #endif // LL_LLVIEWERBUILDCONFIG_H \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/floater_group_profile.xml b/indra/newview/skins/default/xui/en/floater_group_profile.xml index 9a2e6d47e51602f46e1fbb4052aabbf000ae2694..481f10adffa6198f8e070287113febe2a28e4e85 100644 --- a/indra/newview/skins/default/xui/en/floater_group_profile.xml +++ b/indra/newview/skins/default/xui/en/floater_group_profile.xml @@ -1,27 +1,27 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - positioning="cascading" - can_close="true" - can_resize="true" - height="580" - min_height="350" - min_width="260" - layout="topleft" - name="floater_group_profile" - save_rect="true" - title="GROUP" - width="370"> - <panel - class="panel_group_info_sidetray" - name="panel_group_info_sidetray" - filename="panel_group_info_sidetray.xml" - label="Group Profile" - font="SansSerifBold" - follows="all" - layout="topleft" - min_height="350" - left="1" - right="-1" - top="0" - bottom="-8"/> -</floater> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + positioning="cascading" + can_close="true" + can_resize="true" + height="580" + min_height="350" + min_width="260" + layout="topleft" + name="floater_group_profile" + save_rect="true" + title="GROUP" + width="370"> + <panel + class="panel_group_info_sidetray" + name="panel_group_info_sidetray" + filename="panel_group_info_sidetray.xml" + label="Group Profile" + font="SansSerifBold" + follows="all" + layout="topleft" + min_height="350" + left="1" + right="-1" + top="0" + bottom="-8"/> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_legacy_profile.xml b/indra/newview/skins/default/xui/en/floater_legacy_profile.xml index 04c755c72f2b13953fc18e715df4381040b24f92..f8d259c1f79043ef5ac57706c66e046d7723823c 100644 --- a/indra/newview/skins/default/xui/en/floater_legacy_profile.xml +++ b/indra/newview/skins/default/xui/en/floater_legacy_profile.xml @@ -1,27 +1,27 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - positioning="cascading" - can_close="true" - can_resize="true" - height="580" - min_height="350" - min_width="260" - layout="topleft" - name="floater_legacy_profile" - save_rect="true" - title="PROFILE" - width="370"> - <panel - class="panel_profile_legacy_sidetray" - name="panel_profile_legacy_sidetray" - filename="panel_profile_legacy_sidetray.xml" - label="Profile" - font="SansSerifBold" - follows="all" - layout="topleft" - min_height="350" - left="1" - right="-1" - top="0" - bottom="-8"/> -</floater> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + positioning="cascading" + can_close="true" + can_resize="true" + height="580" + min_height="350" + min_width="260" + layout="topleft" + name="floater_legacy_profile" + save_rect="true" + title="PROFILE" + width="370"> + <panel + class="panel_profile_legacy_sidetray" + name="panel_profile_legacy_sidetray" + filename="panel_profile_legacy_sidetray.xml" + label="Profile" + font="SansSerifBold" + follows="all" + layout="topleft" + min_height="350" + left="1" + right="-1" + top="0" + bottom="-8"/> +</floater> diff --git a/indra/newview/skins/default/xui/en/panel_people_friends.xml b/indra/newview/skins/default/xui/en/panel_people_friends.xml index 283b93c2980adaa8473af930c3a0b549c50c7769..3e707aed4f10549eb3639f5d3121e6ff2eba135d 100644 --- a/indra/newview/skins/default/xui/en/panel_people_friends.xml +++ b/indra/newview/skins/default/xui/en/panel_people_friends.xml @@ -1,154 +1,154 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> - -<panel - background_opaque="true" - background_visible="true" - bg_alpha_color="DkGray" - bg_opaque_color="DkGray" - height="350" - follows="all" - label="FRIENDS" - layout="topleft" - left="0" - help_topic="people_friends_tab" - name="friends_panel" - width="330" - top="0"> - <panel - follows="left|top|right" - height="27" - label="bottom_panel" - layout="topleft" - left="0" - name="friends_buttons_panel" - right="-1" - top="0"> - <filter_editor - follows="left|top|right" - height="23" - layout="topleft" - left="6" - label="Filter People" - max_length_chars="300" - name="friends_filter_input" - text_pad_left="10" - top="4" - width="177" /> - <button - commit_callback.function="People.Gear" - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="8" - name="gear_btn" - tool_tip="Actions on selected person" - top="3" - width="31" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Conv_toolbar_sort" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - menu_filename="menu_people_friends_view.xml" - menu_position="bottomleft" - name="friends_view_btn" - tool_tip="View/sort options" - top_delta="0" - width="31" /> - <button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - name="friends_add_btn" - tool_tip="Offer friendship to a resident" - top_delta="0" - width="31"> - <commit_callback - function="People.AddFriendWizard" /> - </button> - <dnd_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TrashItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - left_pad="2" - layout="topleft" - name="friends_del_btn" - tool_tip="Remove selected person as a friend" - top_delta="0" - width="31"> - <commit_callback - function="People.DelFriend" /> - </dnd_button> - </panel> - <accordion - background_visible="true" - bg_alpha_color="DkGray2" - bg_opaque_color="DkGray2" - follows="all" - height="322" - layout="topleft" - left="2" - name="friends_accordion" - right="-1" - top_pad="2"> - <accordion_tab - layout="topleft" - height="172" - min_height="150" - name="tab_online" - title="Online"> - <avatar_list - allow_select="true" - follows="all" - height="172" - layout="topleft" - left="0" - multi_select="true" - name="avatars_online" - show_permissions_granted="true" - top="0" - width="307" /> - </accordion_tab> - <accordion_tab - layout="topleft" - height="173" - name="tab_all" - title="All"> - <avatar_list - allow_select="true" - follows="all" - height="173" - layout="topleft" - left="0" - multi_select="true" - name="avatars_all" - show_permissions_granted="true" - top="0" - width="307" /> - </accordion_tab> - </accordion> - <text - follows="top|left|right" - height="350" - left="13" - name="no_friends_help_text" - right="-13" - top="2" - wrap="true" /> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + +<panel + background_opaque="true" + background_visible="true" + bg_alpha_color="DkGray" + bg_opaque_color="DkGray" + height="350" + follows="all" + label="FRIENDS" + layout="topleft" + left="0" + help_topic="people_friends_tab" + name="friends_panel" + width="330" + top="0"> + <panel + follows="left|top|right" + height="27" + label="bottom_panel" + layout="topleft" + left="0" + name="friends_buttons_panel" + right="-1" + top="0"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="6" + label="Filter People" + max_length_chars="300" + name="friends_filter_input" + text_pad_left="10" + top="4" + width="177" /> + <button + commit_callback.function="People.Gear" + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="8" + name="gear_btn" + tool_tip="Actions on selected person" + top="3" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + menu_filename="menu_people_friends_view.xml" + menu_position="bottomleft" + name="friends_view_btn" + tool_tip="View/sort options" + top_delta="0" + width="31" /> + <button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="friends_add_btn" + tool_tip="Offer friendship to a resident" + top_delta="0" + width="31"> + <commit_callback + function="People.AddFriendWizard" /> + </button> + <dnd_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + left_pad="2" + layout="topleft" + name="friends_del_btn" + tool_tip="Remove selected person as a friend" + top_delta="0" + width="31"> + <commit_callback + function="People.DelFriend" /> + </dnd_button> + </panel> + <accordion + background_visible="true" + bg_alpha_color="DkGray2" + bg_opaque_color="DkGray2" + follows="all" + height="322" + layout="topleft" + left="2" + name="friends_accordion" + right="-1" + top_pad="2"> + <accordion_tab + layout="topleft" + height="172" + min_height="150" + name="tab_online" + title="Online"> + <avatar_list + allow_select="true" + follows="all" + height="172" + layout="topleft" + left="0" + multi_select="true" + name="avatars_online" + show_permissions_granted="true" + top="0" + width="307" /> + </accordion_tab> + <accordion_tab + layout="topleft" + height="173" + name="tab_all" + title="All"> + <avatar_list + allow_select="true" + follows="all" + height="173" + layout="topleft" + left="0" + multi_select="true" + name="avatars_all" + show_permissions_granted="true" + top="0" + width="307" /> + </accordion_tab> + </accordion> + <text + follows="top|left|right" + height="350" + left="13" + name="no_friends_help_text" + right="-13" + top="2" + wrap="true" /> </panel> \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_people_groups.xml b/indra/newview/skins/default/xui/en/panel_people_groups.xml index 7e38a1c487e9f7f8218aa73d587796e31abc1033..9842c9d28a5a8f843e1edacb33db18cdca8ce4c6 100644 --- a/indra/newview/skins/default/xui/en/panel_people_groups.xml +++ b/indra/newview/skins/default/xui/en/panel_people_groups.xml @@ -1,126 +1,126 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> - -<panel - background_opaque="true" - background_visible="true" - bg_alpha_color="DkGray" - bg_opaque_color="DkGray" - height="350" - follows="all" - label="GROUPS" - layout="topleft" - left="0" - help_topic="people_groups_tab" - name="groups_panel" - width="330" - top="0"> - <!-- - *NOTE: no_groups_msg & group_list attributes are not defined as translatable in VLT. See EXT-5931 - Values are set from appropriate strings at the top of file via LLPeoplePanel::postBuild() - --> - <panel - follows="left|top|right" - height="27" - label="bottom_panel" - layout="topleft" - left="0" - name="groups_buttons_panel" - right="-1" - top="0"> - <filter_editor - follows="left|top|right" - height="23" - layout="topleft" - left="6" - label="Filter Groups" - max_length_chars="300" - name="groups_filter_input" - text_pad_left="10" - top="4" - width="177" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="8" - name="groups_gear_btn" - tool_tip="Actions on selected group" - top="3" - width="31" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Conv_toolbar_sort" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - menu_filename="menu_people_groups_view.xml" - menu_position="bottomleft" - name="groups_view_btn" - tool_tip="View/sort options" - top_delta="0" - width="31" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - menu_filename="menu_group_plus.xml" - menu_position="bottomleft" - name="plus_btn" - tool_tip="Join group/Create new group" - top_delta="0" - width="31"> - <validate_callback - function="People.Group.Plus.Validate" /> - </menu_button> - <dnd_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TrashItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - left_pad="2" - layout="topleft" - name="minus_btn" - tool_tip="Leave selected group" - top_delta="0" - width="31"> - <commit_callback - function="People.Group.Minus" /> - </dnd_button> - </panel> - <text - type="string" - length="1" - follows="left|top|right" - height="14" - layout="topleft" - right="-10" - top_pad="4" - left="3" - use_ellipses="true" - name="groupcount"> - You belong to [COUNT] groups, and can join [REMAINING] more. - </text> - <group_list - allow_select="true" - follows="all" - height="302" - layout="topleft" - left="3" - name="group_list" - right="-2" - top_pad="4" /> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + +<panel + background_opaque="true" + background_visible="true" + bg_alpha_color="DkGray" + bg_opaque_color="DkGray" + height="350" + follows="all" + label="GROUPS" + layout="topleft" + left="0" + help_topic="people_groups_tab" + name="groups_panel" + width="330" + top="0"> + <!-- + *NOTE: no_groups_msg & group_list attributes are not defined as translatable in VLT. See EXT-5931 + Values are set from appropriate strings at the top of file via LLPeoplePanel::postBuild() + --> + <panel + follows="left|top|right" + height="27" + label="bottom_panel" + layout="topleft" + left="0" + name="groups_buttons_panel" + right="-1" + top="0"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="6" + label="Filter Groups" + max_length_chars="300" + name="groups_filter_input" + text_pad_left="10" + top="4" + width="177" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="8" + name="groups_gear_btn" + tool_tip="Actions on selected group" + top="3" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + menu_filename="menu_people_groups_view.xml" + menu_position="bottomleft" + name="groups_view_btn" + tool_tip="View/sort options" + top_delta="0" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + menu_filename="menu_group_plus.xml" + menu_position="bottomleft" + name="plus_btn" + tool_tip="Join group/Create new group" + top_delta="0" + width="31"> + <validate_callback + function="People.Group.Plus.Validate" /> + </menu_button> + <dnd_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + left_pad="2" + layout="topleft" + name="minus_btn" + tool_tip="Leave selected group" + top_delta="0" + width="31"> + <commit_callback + function="People.Group.Minus" /> + </dnd_button> + </panel> + <text + type="string" + length="1" + follows="left|top|right" + height="14" + layout="topleft" + right="-10" + top_pad="4" + left="3" + use_ellipses="true" + name="groupcount"> + You belong to [COUNT] groups, and can join [REMAINING] more. + </text> + <group_list + allow_select="true" + follows="all" + height="302" + layout="topleft" + left="3" + name="group_list" + right="-2" + top_pad="4" /> </panel> \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_people_nearby.xml b/indra/newview/skins/default/xui/en/panel_people_nearby.xml index 9de58f74d473735369338973be8a6a505ff80439..9a1b75a1c38a8ef1cebbfa8700c9010af8be0e74 100644 --- a/indra/newview/skins/default/xui/en/panel_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/panel_people_nearby.xml @@ -1,152 +1,152 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> - -<panel - background_opaque="true" - background_visible="true" - bg_alpha_color="DkGray" - bg_opaque_color="DkGray" - height="350" - follows="all" - label="NEARBY" - layout="topleft" - left="2" - help_topic="people_nearby_tab" - name="nearby_panel" - width="330" - top="0"> - <panel - follows="left|top|right" - height="27" - label="bottom_panel" - layout="topleft" - left="2" - name="nearby_buttons_panel" - right="-1" - top="0"> - <filter_editor - follows="left|top|right" - height="23" - layout="topleft" - left="1" - label="Filter People" - max_length_chars="300" - name="nearby_filter_input" - text_pad_left="10" - top="4" - width="178" /> - <button - commit_callback.function="People.Gear" - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="7" - name="gear_btn" - tool_tip="Actions on selected person" - top="3" - width="31" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Conv_toolbar_sort" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - menu_filename="menu_people_nearby_view.xml" - menu_position="bottomleft" - name="nearby_view_btn" - tool_tip="View/sort options" - top_delta="0" - width="31" /> - <button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - name="add_friend_btn" - tool_tip="Offer friendship to a resident" - top_delta="0" - width="31"> - <commit_callback - function="People.AddFriend" /> - </button> - <dnd_button - enabled="false" - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TrashItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - left_pad="2" - layout="topleft" - name="friends_del_btn" - tool_tip="Remove selected person as a friend" - top_delta="0" - width="31"> - <commit_callback - function="People.DelFriend" /> - </dnd_button> - </panel> - <layout_stack - clip="false" - follows="all" - height="325" - layout="topleft" - left="0" - mouse_opaque="false" - orientation="vertical" - right="-1" - top_pad="0"> - <layout_panel - height="142" - layout="topleft" - min_dim="100" - mouse_opaque="false" - name="Net Map Panel" - user_resize="true" - visibility_control="NearbyListShowMap" - width="313"> - <net_map - bg_color="NetMapBackgroundColor" - follows="all" - height="140" - layout="topleft" - left="3" - mouse_opaque="false" - name="Net Map" - right="-1" - top="4" /> - </layout_panel> - <layout_panel - height="213" - layout="topleft" - min_dim="100" - mouse_opaque="false" - right="-1" - user_resize="true"> - <avatar_list - show_distance="true" - allow_select="true" - follows="all" - height="211" - ignore_online_status="true" - layout="topleft" - left="3" - keep_one_selected="false" - multi_select="true" - name="avatar_list" - right="-1" - top="2" /> - </layout_panel> - </layout_stack> -</panel> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + +<panel + background_opaque="true" + background_visible="true" + bg_alpha_color="DkGray" + bg_opaque_color="DkGray" + height="350" + follows="all" + label="NEARBY" + layout="topleft" + left="2" + help_topic="people_nearby_tab" + name="nearby_panel" + width="330" + top="0"> + <panel + follows="left|top|right" + height="27" + label="bottom_panel" + layout="topleft" + left="2" + name="nearby_buttons_panel" + right="-1" + top="0"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="1" + label="Filter People" + max_length_chars="300" + name="nearby_filter_input" + text_pad_left="10" + top="4" + width="178" /> + <button + commit_callback.function="People.Gear" + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="7" + name="gear_btn" + tool_tip="Actions on selected person" + top="3" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + menu_filename="menu_people_nearby_view.xml" + menu_position="bottomleft" + name="nearby_view_btn" + tool_tip="View/sort options" + top_delta="0" + width="31" /> + <button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="add_friend_btn" + tool_tip="Offer friendship to a resident" + top_delta="0" + width="31"> + <commit_callback + function="People.AddFriend" /> + </button> + <dnd_button + enabled="false" + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + left_pad="2" + layout="topleft" + name="friends_del_btn" + tool_tip="Remove selected person as a friend" + top_delta="0" + width="31"> + <commit_callback + function="People.DelFriend" /> + </dnd_button> + </panel> + <layout_stack + clip="false" + follows="all" + height="325" + layout="topleft" + left="0" + mouse_opaque="false" + orientation="vertical" + right="-1" + top_pad="0"> + <layout_panel + height="142" + layout="topleft" + min_dim="100" + mouse_opaque="false" + name="Net Map Panel" + user_resize="true" + visibility_control="NearbyListShowMap" + width="313"> + <net_map + bg_color="NetMapBackgroundColor" + follows="all" + height="140" + layout="topleft" + left="3" + mouse_opaque="false" + name="Net Map" + right="-1" + top="4" /> + </layout_panel> + <layout_panel + height="213" + layout="topleft" + min_dim="100" + mouse_opaque="false" + right="-1" + user_resize="true"> + <avatar_list + show_distance="true" + allow_select="true" + follows="all" + height="211" + ignore_online_status="true" + layout="topleft" + left="3" + keep_one_selected="false" + multi_select="true" + name="avatar_list" + right="-1" + top="2" /> + </layout_panel> + </layout_stack> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_people_recent.xml b/indra/newview/skins/default/xui/en/panel_people_recent.xml index 40b171a9c8a0bc4526229aceb59f7713ffe7f05c..49506d5a818a1c15c95911df24878b4afa519245 100644 --- a/indra/newview/skins/default/xui/en/panel_people_recent.xml +++ b/indra/newview/skins/default/xui/en/panel_people_recent.xml @@ -1,111 +1,111 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> - -<panel - background_opaque="true" - background_visible="true" - bg_alpha_color="DkGray" - bg_opaque_color="DkGray" - follows="all" - height="350" - label="RECENT" - layout="topleft" - left="0" - help_topic="people_recent_tab" - name="recent_panel" - width="330" - top="0"> - <panel - follows="left|top|right" - height="27" - label="bottom_panel" - layout="topleft" - left="0" - name="recent_buttons_panel" - right="-1" - top="0"> - <filter_editor - follows="left|top|right" - height="23" - layout="topleft" - left="6" - label="Filter People" - max_length_chars="300" - name="recent_filter_input" - text_pad_left="10" - top="4" - width="177" /> - <button - commit_callback.function="People.Gear" - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="8" - name="gear_btn" - tool_tip="Actions on selected person" - top="3" - width="31" /> - <menu_button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Conv_toolbar_sort" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - menu_filename="menu_people_recent_view.xml" - menu_position="bottomleft" - name="recent_view_btn" - tool_tip="View/sort options" - top_delta="0" - width="31" /> - <button - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="2" - name="add_friend_btn" - tool_tip="Offer friendship to a resident" - top_delta="0" - width="31"> - <commit_callback - function="People.AddFriend" /> - </button> - <dnd_button - enabled="false" - follows="right" - height="25" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="TrashItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - left_pad="2" - layout="topleft" - name="friends_del_btn" - tool_tip="Remove selected person as a friend" - top_delta="0" - width="31"> - <commit_callback - function="People.DelFriend" /> - </dnd_button> - </panel> - <avatar_list - allow_select="true" - follows="all" - height="320" - layout="topleft" - left="3" - multi_select="true" - name="avatar_list" - show_last_interaction_time="true" - right="-2" - top_pad="4" /> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + +<panel + background_opaque="true" + background_visible="true" + bg_alpha_color="DkGray" + bg_opaque_color="DkGray" + follows="all" + height="350" + label="RECENT" + layout="topleft" + left="0" + help_topic="people_recent_tab" + name="recent_panel" + width="330" + top="0"> + <panel + follows="left|top|right" + height="27" + label="bottom_panel" + layout="topleft" + left="0" + name="recent_buttons_panel" + right="-1" + top="0"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="6" + label="Filter People" + max_length_chars="300" + name="recent_filter_input" + text_pad_left="10" + top="4" + width="177" /> + <button + commit_callback.function="People.Gear" + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="8" + name="gear_btn" + tool_tip="Actions on selected person" + top="3" + width="31" /> + <menu_button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + menu_filename="menu_people_recent_view.xml" + menu_position="bottomleft" + name="recent_view_btn" + tool_tip="View/sort options" + top_delta="0" + width="31" /> + <button + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="2" + name="add_friend_btn" + tool_tip="Offer friendship to a resident" + top_delta="0" + width="31"> + <commit_callback + function="People.AddFriend" /> + </button> + <dnd_button + enabled="false" + follows="right" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="TrashItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + left_pad="2" + layout="topleft" + name="friends_del_btn" + tool_tip="Remove selected person as a friend" + top_delta="0" + width="31"> + <commit_callback + function="People.DelFriend" /> + </dnd_button> + </panel> + <avatar_list + allow_select="true" + follows="all" + height="320" + layout="topleft" + left="3" + multi_select="true" + name="avatar_list" + show_last_interaction_time="true" + right="-2" + top_pad="4" /> </panel> \ No newline at end of file