Compare commits
140 Commits
sv-1.8.7.8
...
sv-1.8.7.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a652cb4f0a | ||
|
|
16b8980d28 | ||
|
|
841a55c266 | ||
|
|
2aa6adfd46 | ||
|
|
bac0b3d745 | ||
|
|
b08b597397 | ||
|
|
25cb81221e | ||
|
|
4f5749878f | ||
|
|
2aa3ba4d36 | ||
|
|
6a2421e2e7 | ||
|
|
e78061b077 | ||
|
|
379f97e15a | ||
|
|
2afd2c500b | ||
|
|
0c3e144547 | ||
|
|
842d1b8d93 | ||
|
|
5c2c2a8c01 | ||
|
|
61f0837114 | ||
|
|
aa95d8fe3d | ||
|
|
a52c4779c8 | ||
|
|
1ece0e6051 | ||
|
|
6a56d048c0 | ||
|
|
e34999b6a9 | ||
|
|
103b2c0f33 | ||
|
|
2fe45cb8c2 | ||
|
|
64a44d6c1b | ||
|
|
3073a175d7 | ||
|
|
3b550c3a93 | ||
|
|
1d2c0cb8c6 | ||
|
|
2f369299c5 | ||
|
|
e65b513562 | ||
|
|
6959b688be | ||
|
|
7db999d801 | ||
|
|
703ad01c8b | ||
|
|
199879aea8 | ||
|
|
eefa0f07a7 | ||
|
|
6e6fb44bdb | ||
|
|
0892d14933 | ||
|
|
400da6ec92 | ||
|
|
18539831d1 | ||
|
|
9548270306 | ||
|
|
44aec1384a | ||
|
|
42139835d5 | ||
|
|
49f0f8e28f | ||
|
|
36b75b2398 | ||
|
|
9a53824d6d | ||
|
|
a9e2672820 | ||
|
|
138cf5d4f8 | ||
|
|
4b2e358783 | ||
|
|
851b3659ee | ||
|
|
27d4e05f2b | ||
|
|
deade4438d | ||
|
|
deafc6814d | ||
|
|
1fd6e91c68 | ||
|
|
67126ab494 | ||
|
|
e3318fb0d2 | ||
|
|
e9d28ee5c1 | ||
|
|
2ffc99aecf | ||
|
|
450afff50b | ||
|
|
570b0d3c5b | ||
|
|
09daa2a865 | ||
|
|
e97837e103 | ||
|
|
84add2d864 | ||
|
|
4c224def62 | ||
|
|
2242a1d101 | ||
|
|
b957c0930d | ||
|
|
f7434711ad | ||
|
|
5f0b23edd7 | ||
|
|
2eff62ad0d | ||
|
|
686795618a | ||
|
|
5c8c5a2c45 | ||
|
|
d98b99f7b3 | ||
|
|
8d472a9c7b | ||
|
|
3747d79143 | ||
|
|
910a5557ab | ||
|
|
8163448a6c | ||
|
|
ac0e93dcad | ||
|
|
ed420c3645 | ||
|
|
b872860443 | ||
|
|
992f4c7b5d | ||
|
|
8f15478ba4 | ||
|
|
1c371e7be6 | ||
|
|
937c80f694 | ||
|
|
15bd41bd71 | ||
|
|
b9156b7955 | ||
|
|
623a484ae3 | ||
|
|
2ace698101 | ||
|
|
34e0c722e7 | ||
|
|
82ee06a6bd | ||
|
|
584ee8fffe | ||
|
|
d80d232ee5 | ||
|
|
de47736038 | ||
|
|
0da16e6034 | ||
|
|
6c9a156610 | ||
|
|
1726c27078 | ||
|
|
64b43a47b5 | ||
|
|
8005a58ed5 | ||
|
|
d1d42701f5 | ||
|
|
c57fceff17 | ||
|
|
265336463d | ||
|
|
3ba1c88672 | ||
|
|
90e6afe159 | ||
|
|
3209507b6c | ||
|
|
fa97d8497a | ||
|
|
a687273d57 | ||
|
|
28f13b806c | ||
|
|
f1342d7bb8 | ||
|
|
c3428c6d57 | ||
|
|
0efddbd9ff | ||
|
|
be0aba4bfa | ||
|
|
c3f03b6bbf | ||
|
|
e15839a2cb | ||
|
|
e0efbd7d26 | ||
|
|
8e57288819 | ||
|
|
107f512545 | ||
|
|
14dc348179 | ||
|
|
eccbd98d79 | ||
|
|
a5115aa69e | ||
|
|
327574db7c | ||
|
|
8b4a29cbd3 | ||
|
|
544feee19f | ||
|
|
bee60da089 | ||
|
|
c466b44143 | ||
|
|
27222d524c | ||
|
|
b99e2cbbdd | ||
|
|
a5bdc24a14 | ||
|
|
0b6d94f202 | ||
|
|
bf5035388b | ||
|
|
640c136bcc | ||
|
|
6ebd2eef00 | ||
|
|
c954d02125 | ||
|
|
a34414849c | ||
|
|
c1ffb1b332 | ||
|
|
d06448cdfd | ||
|
|
117ef68916 | ||
|
|
83b384ab97 | ||
|
|
5ee5ba473b | ||
|
|
4055af4afd | ||
|
|
65dad7acfd | ||
|
|
a21927e510 | ||
|
|
094c948a87 |
2
Pipfile
2
Pipfile
@@ -8,7 +8,7 @@ name = "pypi"
|
||||
[packages]
|
||||
llbase = "*"
|
||||
certifi = "*"
|
||||
autobuild = {hg = "https://bitbucket.org/alchemyviewer/autobuild-1.1"}
|
||||
autobuild = {git = "https://git.alchemyviewer.org/alchemy/autobuild.git"}
|
||||
|
||||
[requires]
|
||||
python_version = "2.7"
|
||||
|
||||
@@ -678,9 +678,11 @@
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>e19b664ad8cf9e7f4a7bf649d28faa76</string>
|
||||
<string>1b278ff2535f428ea6536683d096fdd0</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>https://bitbucket.org/SingularityViewer/libraries/downloads/dullahan-1.1.1320_73.1.12+gee4b49f+chromium-73.0.3683.75-windows-191102212.tar.bz2</string>
|
||||
<string>https://pkg.alchemyviewer.org/repository/autobuild-external/dullahan/windows/dullahan-1.3.201911222116_78.3.7_gea7ef34_chromium-78.0.3904.108-windows-2.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
@@ -690,18 +692,18 @@
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>414190fd1ce3876ee3efc682b06ae65c</string>
|
||||
<string>b9346fea7643b10308c7bd9a769ef5f7</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>http://depot.alchemyviewer.org/pub/packages/windows64/msvc-1920/dullahan-1.1.1320_73.1.12-gee4b49f-chromium-73.0.3683.75-windows64-190871757.tar.bz2</string>
|
||||
<string>https://pkg.alchemyviewer.org/repository/autobuild-external/dullahan/windows64/dullahan-1.3.201911222103_78.3.7_gea7ef34_chromium-78.0.3904.108-windows64-2.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.1.1320_73.1.12+gee4b49f+chromium-73.0.3683.75</string>
|
||||
<string>1.3.201911222103_78.3.7_gea7ef34_chromium-78.0.3904.108</string>
|
||||
</map>
|
||||
<key>elfio</key>
|
||||
<map>
|
||||
@@ -816,7 +818,7 @@
|
||||
<key>fmodstudio</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>FMOD Studio, copyright (c) Firelight Technologies Pty, Ltd., 2012-2019.</string>
|
||||
<string>FMOD Studio, Copyright (c) Firelight Technologies Pty Ltd.</string>
|
||||
<key>description</key>
|
||||
<string>FMOD Studio audio system library</string>
|
||||
<key>license</key>
|
||||
@@ -874,11 +876,11 @@
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>54dbd41322a08a1fc333ca6d96af5502</string>
|
||||
<string>ccd495598894c8e2e541a348015ee3f0</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>/opt/devel/secondlife/pkg/fmodstudio-2.00.02.191991250-linux64-191991250.tar.bz2</string>
|
||||
<string>/opt/devel/fmodstudio-2.00.07.200182252-linux64-200182252.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
@@ -888,11 +890,11 @@
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>e0e87e0423fa42e4d2997b47b92eac6e</string>
|
||||
<string>d32efb193ffcd73bcba4875ddfd17bf0</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/windows/fmodstudio-2.00.03.192211030-windows-192211030.tar.bz2</string>
|
||||
<string>https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/windows/fmodstudio-2.00.07.4-windows-4.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
@@ -902,18 +904,18 @@
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c2e55e1bfef7e066a0e40867a64b4cce</string>
|
||||
<string>0604fd6b53ceaf14ce04d0de1bea51b8</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/windows64/fmodstudio-2.00.03.192211029-windows64-192211029.tar.bz2</string>
|
||||
<string>https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/windows64/fmodstudio-2.00.07.4-windows64-4.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.00.03.192211300</string>
|
||||
<string>2.00.07.4</string>
|
||||
</map>
|
||||
<key>fonts</key>
|
||||
<map>
|
||||
@@ -996,7 +998,7 @@
|
||||
<key>freetype</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright 2006-2017 by David Turner, Robert Wilhelm, and Werner Lemberg.</string>
|
||||
<string>Copyright 2006-2018 by David Turner, Robert Wilhelm, and Werner Lemberg.</string>
|
||||
<key>description</key>
|
||||
<string>Font rendering library</string>
|
||||
<key>license</key>
|
||||
@@ -2506,7 +2508,7 @@
|
||||
<key>vlc-bin</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (C) 1998-2016 VLC authors and VideoLAN</string>
|
||||
<string>Copyright (C) 1998-2020 VLC authors and VideoLAN</string>
|
||||
<key>license</key>
|
||||
<string>GPL2</string>
|
||||
<key>license_file</key>
|
||||
@@ -2544,9 +2546,9 @@
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>add560654a53cb1c554044a4fac3c718</string>
|
||||
<string>3ff1d097e4f9b8f864a639aff974a506</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12144/71458/vlc_bin-2.2.8.511703-windows-511703.tar.bz2</string>
|
||||
<string>https://pkg.alchemyviewer.org/repository/autobuild-external/vlc-bin/windows/vlc_bin-3.0.8.189-windows-189.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
@@ -2556,16 +2558,16 @@
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>94bf04b49acc1e1bf2c06e2232f8a083</string>
|
||||
<string>b890b109b526cc6ad211eadefed83316</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12145/71463/vlc_bin-2.2.8.511703-windows64-511703.tar.bz2</string>
|
||||
<string>https://pkg.alchemyviewer.org/repository/autobuild-external/vlc-bin/windows64/vlc_bin-3.0.8.189-windows64-189.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.2.8.511703</string>
|
||||
<string>3.0.8.189</string>
|
||||
</map>
|
||||
<key>xmlrpc-epi</key>
|
||||
<map>
|
||||
|
||||
@@ -13,10 +13,6 @@ include(LLCommon)
|
||||
# set up platform specific lists of files that need to be copied
|
||||
###################################################################
|
||||
if(WINDOWS)
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
||||
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
|
||||
include(InstallRequiredSystemLibrariesAL)
|
||||
|
||||
set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}/Debug")
|
||||
set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}/RelWithDebInfo")
|
||||
set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}/Release")
|
||||
@@ -96,26 +92,6 @@ if(WINDOWS)
|
||||
list(APPEND release_files fmod.dll)
|
||||
endif (USE_FMODSTUDIO)
|
||||
|
||||
foreach(redistfullfile IN LISTS CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
|
||||
get_filename_component(redistfilepath ${redistfullfile} DIRECTORY )
|
||||
get_filename_component(redistfilename ${redistfullfile} NAME)
|
||||
copy_if_different(
|
||||
${redistfilepath}
|
||||
"${SHARED_LIB_STAGING_DIR_RELEASE}"
|
||||
out_targets
|
||||
${redistfilename}
|
||||
)
|
||||
set(third_party_targets ${third_party_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${redistfilepath}
|
||||
"${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}"
|
||||
out_targets
|
||||
${redistfilename}
|
||||
)
|
||||
set(third_party_targets ${third_party_targets} ${out_targets})
|
||||
endforeach()
|
||||
|
||||
elseif(DARWIN)
|
||||
set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}/Debug/Resources")
|
||||
set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/Resources")
|
||||
|
||||
@@ -1,741 +0,0 @@
|
||||
# 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)
|
||||
if(MSVC_VERSION EQUAL 1920)
|
||||
# VS2019 named this differently prior to update 1.
|
||||
set(MSVC_REDIST_NAME VC141)
|
||||
endif()
|
||||
elseif(MSVC_TOOLSET_VERSION EQUAL 141)
|
||||
set(MSVC_REDIST_NAME VC141)
|
||||
set(_MSVC_DLL_VERSION 140)
|
||||
set(_MSVC_IDE_VERSION 15)
|
||||
if(MSVC_VERSION EQUAL 1910)
|
||||
# VS2017 named this differently prior to update 3.
|
||||
set(MSVC_REDIST_NAME VC150)
|
||||
endif()
|
||||
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)
|
||||
@@ -132,7 +132,7 @@ class LL_COMMON_API AIArgs
|
||||
// Add another replacement.
|
||||
AIArgs& operator()(char const* key, std::string const& replacement) { mArgs[key] = replacement; return *this; }
|
||||
// The destructor may not throw.
|
||||
~AIArgs() throw() { }
|
||||
~AIArgs() noexcept { }
|
||||
|
||||
// Accessor.
|
||||
LLStringUtil::format_map_t const& operator*() const { return mArgs; }
|
||||
@@ -193,7 +193,7 @@ class LL_COMMON_API Line
|
||||
Line(std::string const& xml_desc, AIArgs const& args, bool newline = false) : mNewline(newline), mXmlDesc(xml_desc), mArgs(args), mType(normal) { }
|
||||
Line(Prefix const& prefix, bool newline = false) : mNewline(newline), mXmlDesc("AIPrefix"), mArgs("[PREFIX]", prefix.str()), mType(prefix.type()) { }
|
||||
// The destructor may not throw.
|
||||
~Line() throw() { }
|
||||
~Line() noexcept { }
|
||||
|
||||
// Prepend a newline before this line.
|
||||
void set_newline(void) { mNewline = true; }
|
||||
@@ -225,7 +225,7 @@ class LL_COMMON_API Error : public std::exception
|
||||
typedef std::deque<Line> lines_type;
|
||||
|
||||
// The destructor may not throw.
|
||||
~Error() throw() { }
|
||||
~Error() noexcept { }
|
||||
|
||||
// Accessors.
|
||||
lines_type const& lines(void) const { return mLines; }
|
||||
@@ -267,7 +267,7 @@ class LL_COMMON_API ErrorCode : public Error
|
||||
|
||||
public:
|
||||
// The destructor may not throw.
|
||||
~ErrorCode() throw() { }
|
||||
~ErrorCode() noexcept { }
|
||||
|
||||
// Accessor.
|
||||
int getCode(void) const { return mCode; }
|
||||
|
||||
@@ -412,7 +412,7 @@ public:
|
||||
std::runtime_error(what),
|
||||
mData(data)
|
||||
{}
|
||||
virtual ~LLErrorEvent() throw() {}
|
||||
virtual ~LLErrorEvent() noexcept {}
|
||||
|
||||
LLSD getData() const { return mData; }
|
||||
|
||||
|
||||
@@ -381,10 +381,9 @@ std::string LLSDArgsMapper::formatlist(const LLSD& list)
|
||||
{
|
||||
std::ostringstream out;
|
||||
const char* delim = "";
|
||||
for (LLSD::array_const_iterator li(list.beginArray()), lend(list.endArray());
|
||||
li != lend; ++li)
|
||||
for (auto const& entry : list.array())
|
||||
{
|
||||
out << delim << li->asString();
|
||||
out << delim << entry.asString();
|
||||
delim = ", ";
|
||||
}
|
||||
return out.str();
|
||||
@@ -494,10 +493,9 @@ struct LLEventDispatcher::MapParamsDispatchEntry: public LLEventDispatcher::Para
|
||||
{
|
||||
// Build the set of all param keys, then delete the ones that are
|
||||
// optional. What's left are the ones that are required.
|
||||
for (LLSD::array_const_iterator pi(params.beginArray()), pend(params.endArray());
|
||||
pi != pend; ++pi)
|
||||
for (auto const& entry : params.array())
|
||||
{
|
||||
mRequired[pi->asString()] = LLSD();
|
||||
mRequired[entry.asString()] = LLSD();
|
||||
}
|
||||
|
||||
if (defaults.isArray() || defaults.isUndefined())
|
||||
|
||||
@@ -54,6 +54,7 @@ std::string LLFile::strerr(int errn)
|
||||
{
|
||||
char buffer[256];
|
||||
strerror_s(buffer, errn); // infers sizeof(buffer) -- love it!
|
||||
buffer[255] = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -281,6 +282,11 @@ int LLFile::rename_nowarn(const std::string& filename, const std::string& newnam
|
||||
int rc = _wrename(utf16filename.c_str(),utf16newname.c_str());
|
||||
#else
|
||||
int rc = ::rename(filename.c_str(),newname.c_str());
|
||||
if (rc == -1 && errno == EXDEV)
|
||||
{
|
||||
rc = std::system(("mv '" + filename + "' '" + newname + '\'').data());
|
||||
errno = 0;
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -126,9 +126,9 @@ public:
|
||||
virtual Date asDate() const { return LLDate(); }
|
||||
virtual URI asURI() const { return LLURI(); }
|
||||
virtual const Binary& asBinary() const { static const std::vector<U8> empty; return empty; }
|
||||
|
||||
virtual const String& asStringRef() const { static const std::string empty; return empty; }
|
||||
|
||||
virtual const String& asStringRef() const { static const std::string empty; return empty; }
|
||||
|
||||
virtual bool has(const String&) const { return false; }
|
||||
virtual LLSD get(const String&) const { return LLSD(); }
|
||||
virtual LLSD getKeys() const { return LLSD::emptyArray(); }
|
||||
@@ -140,10 +140,14 @@ public:
|
||||
virtual void erase(Integer) { }
|
||||
virtual const LLSD& ref(Integer) const { return undef(); }
|
||||
|
||||
virtual LLSD::map_const_iterator beginMap() const { return endMap(); }
|
||||
virtual LLSD::map_const_iterator endMap() const { static const std::map<String, LLSD> empty; return empty.end(); }
|
||||
virtual LLSD::array_const_iterator beginArray() const { return endArray(); }
|
||||
virtual LLSD::array_const_iterator endArray() const { static const std::vector<LLSD> empty; return empty.end(); }
|
||||
virtual const std::map<String, LLSD>& map() const { static const std::map<String, LLSD> empty; return empty; }
|
||||
virtual std::map<String, LLSD>& map() { static std::map<String, LLSD> empty; return empty; }
|
||||
LLSD::map_const_iterator beginMap() const { return map().begin(); }
|
||||
LLSD::map_const_iterator endMap() const { return map().end(); }
|
||||
virtual const std::vector<LLSD>& array() const { static const std::vector<LLSD> empty; return empty; }
|
||||
virtual std::vector<LLSD>& array() { static std::vector<LLSD> empty; return empty; }
|
||||
LLSD::array_const_iterator beginArray() const { return array().begin(); }
|
||||
LLSD::array_const_iterator endArray() const { return array().end(); }
|
||||
|
||||
virtual void dumpStats() const;
|
||||
virtual void calcStats(S32 type_counts[], S32 share_counts[]) const;
|
||||
@@ -183,10 +187,11 @@ namespace
|
||||
public:
|
||||
ImplBase(DataRef value) : mValue(value) { }
|
||||
|
||||
virtual LLSD::Type type() const { return T; }
|
||||
LLSD::Type type() const override { return T; }
|
||||
|
||||
using LLSD::Impl::assign; // Unhiding base class virtuals...
|
||||
virtual void assign(LLSD::Impl*& var, DataRef value) {
|
||||
void assign(LLSD::Impl*& var, DataRef value) override
|
||||
{
|
||||
if (shared())
|
||||
{
|
||||
Impl::assign(var, value);
|
||||
@@ -199,16 +204,16 @@ namespace
|
||||
};
|
||||
|
||||
|
||||
class ImplBoolean
|
||||
class ImplBoolean final
|
||||
: public ImplBase<LLSD::TypeBoolean, LLSD::Boolean>
|
||||
{
|
||||
public:
|
||||
ImplBoolean(LLSD::Boolean v) : Base(v) { }
|
||||
|
||||
virtual LLSD::Boolean asBoolean() const { return mValue; }
|
||||
virtual LLSD::Integer asInteger() const { return mValue ? 1 : 0; }
|
||||
virtual LLSD::Real asReal() const { return mValue ? 1 : 0; }
|
||||
virtual LLSD::String asString() const;
|
||||
LLSD::Boolean asBoolean() const override { return mValue; }
|
||||
LLSD::Integer asInteger() const override { return mValue ? 1 : 0; }
|
||||
LLSD::Real asReal() const override { return mValue ? 1 : 0; }
|
||||
LLSD::String asString() const override;
|
||||
};
|
||||
|
||||
LLSD::String ImplBoolean::asString() const
|
||||
@@ -220,32 +225,32 @@ namespace
|
||||
{ return mValue ? "true" : ""; }
|
||||
|
||||
|
||||
class ImplInteger
|
||||
class ImplInteger final
|
||||
: public ImplBase<LLSD::TypeInteger, LLSD::Integer>
|
||||
{
|
||||
public:
|
||||
ImplInteger(LLSD::Integer v) : Base(v) { }
|
||||
|
||||
virtual LLSD::Boolean asBoolean() const { return mValue != 0; }
|
||||
virtual LLSD::Integer asInteger() const { return mValue; }
|
||||
virtual LLSD::Real asReal() const { return mValue; }
|
||||
virtual LLSD::String asString() const;
|
||||
LLSD::Boolean asBoolean() const override { return mValue != 0; }
|
||||
LLSD::Integer asInteger() const override { return mValue; }
|
||||
LLSD::Real asReal() const override { return mValue; }
|
||||
LLSD::String asString() const override;
|
||||
};
|
||||
|
||||
LLSD::String ImplInteger::asString() const
|
||||
{ return llformat("%d", mValue); }
|
||||
|
||||
|
||||
class ImplReal
|
||||
class ImplReal final
|
||||
: public ImplBase<LLSD::TypeReal, LLSD::Real>
|
||||
{
|
||||
public:
|
||||
ImplReal(LLSD::Real v) : Base(v) { }
|
||||
|
||||
virtual LLSD::Boolean asBoolean() const;
|
||||
virtual LLSD::Integer asInteger() const;
|
||||
virtual LLSD::Real asReal() const { return mValue; }
|
||||
virtual LLSD::String asString() const;
|
||||
LLSD::Boolean asBoolean() const override;
|
||||
LLSD::Integer asInteger() const override;
|
||||
LLSD::Real asReal() const override { return mValue; }
|
||||
LLSD::String asString() const override;
|
||||
};
|
||||
|
||||
LLSD::Boolean ImplReal::asBoolean() const
|
||||
@@ -258,21 +263,21 @@ namespace
|
||||
{ return llformat("%lg", mValue); }
|
||||
|
||||
|
||||
class ImplString
|
||||
class ImplString final
|
||||
: public ImplBase<LLSD::TypeString, LLSD::String, const LLSD::String&>
|
||||
{
|
||||
public:
|
||||
ImplString(const LLSD::String& v) : Base(v) { }
|
||||
|
||||
virtual LLSD::Boolean asBoolean() const { return !mValue.empty(); }
|
||||
virtual LLSD::Integer asInteger() const;
|
||||
virtual LLSD::Real asReal() const;
|
||||
virtual LLSD::String asString() const { return mValue; }
|
||||
virtual LLSD::UUID asUUID() const { return LLUUID(mValue); }
|
||||
virtual LLSD::Date asDate() const { return LLDate(mValue); }
|
||||
virtual LLSD::URI asURI() const { return LLURI(mValue); }
|
||||
virtual int size() const { return mValue.size(); }
|
||||
virtual const LLSD::String& asStringRef() const { return mValue; }
|
||||
LLSD::Boolean asBoolean() const override { return !mValue.empty(); }
|
||||
LLSD::Integer asInteger() const override;
|
||||
LLSD::Real asReal() const override;
|
||||
LLSD::String asString() const override { return mValue; }
|
||||
LLSD::UUID asUUID() const override { return LLUUID(mValue); }
|
||||
LLSD::Date asDate() const override { return LLDate(mValue); }
|
||||
LLSD::URI asURI() const override { return LLURI(mValue); }
|
||||
int size() const override { return mValue.size(); }
|
||||
const LLSD::String& asStringRef() const override { return mValue; }
|
||||
};
|
||||
|
||||
LLSD::Integer ImplString::asInteger() const
|
||||
@@ -302,18 +307,18 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
class ImplUUID
|
||||
class ImplUUID final
|
||||
: public ImplBase<LLSD::TypeUUID, LLSD::UUID, const LLSD::UUID&>
|
||||
{
|
||||
public:
|
||||
ImplUUID(const LLSD::UUID& v) : Base(v) { }
|
||||
|
||||
virtual LLSD::String asString() const{ return mValue.asString(); }
|
||||
virtual LLSD::UUID asUUID() const { return mValue; }
|
||||
LLSD::String asString() const override { return mValue.asString(); }
|
||||
LLSD::UUID asUUID() const override { return mValue; }
|
||||
};
|
||||
|
||||
|
||||
class ImplDate
|
||||
class ImplDate final
|
||||
: public ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&>
|
||||
{
|
||||
public:
|
||||
@@ -321,41 +326,42 @@ namespace
|
||||
: ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&>(v)
|
||||
{ }
|
||||
|
||||
virtual LLSD::Integer asInteger() const
|
||||
LLSD::Integer asInteger() const override
|
||||
{
|
||||
return (LLSD::Integer)(mValue.secondsSinceEpoch());
|
||||
}
|
||||
virtual LLSD::Real asReal() const
|
||||
LLSD::Real asReal() const override
|
||||
{
|
||||
return mValue.secondsSinceEpoch();
|
||||
}
|
||||
virtual LLSD::String asString() const{ return mValue.asString(); }
|
||||
virtual LLSD::Date asDate() const { return mValue; }
|
||||
|
||||
LLSD::String asString() const override { return mValue.asString(); }
|
||||
LLSD::Date asDate() const override { return mValue; }
|
||||
};
|
||||
|
||||
|
||||
class ImplURI
|
||||
class ImplURI final
|
||||
: public ImplBase<LLSD::TypeURI, LLSD::URI, const LLSD::URI&>
|
||||
{
|
||||
public:
|
||||
ImplURI(const LLSD::URI& v) : Base(v) { }
|
||||
|
||||
virtual LLSD::String asString() const{ return mValue.asString(); }
|
||||
virtual LLSD::URI asURI() const { return mValue; }
|
||||
LLSD::String asString() const override { return mValue.asString(); }
|
||||
LLSD::URI asURI() const override { return mValue; }
|
||||
};
|
||||
|
||||
|
||||
class ImplBinary
|
||||
class ImplBinary final
|
||||
: public ImplBase<LLSD::TypeBinary, LLSD::Binary, const LLSD::Binary&>
|
||||
{
|
||||
public:
|
||||
ImplBinary(const LLSD::Binary& v) : Base(v) { }
|
||||
|
||||
virtual const LLSD::Binary& asBinary() const{ return mValue; }
|
||||
const LLSD::Binary& asBinary() const override { return mValue; }
|
||||
};
|
||||
|
||||
|
||||
class ImplMap : public LLSD::Impl
|
||||
class ImplMap final : public LLSD::Impl
|
||||
{
|
||||
private:
|
||||
typedef std::map<LLSD::String, LLSD> DataMap;
|
||||
@@ -368,33 +374,31 @@ namespace
|
||||
public:
|
||||
ImplMap() { }
|
||||
|
||||
virtual ImplMap& makeMap(LLSD::Impl*&);
|
||||
ImplMap& makeMap(LLSD::Impl*&) override;
|
||||
|
||||
virtual LLSD::Type type() const { return LLSD::TypeMap; }
|
||||
LLSD::Type type() const override { return LLSD::TypeMap; }
|
||||
|
||||
virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
|
||||
LLSD::Boolean asBoolean() const override { return !mData.empty(); }
|
||||
|
||||
virtual bool has(const LLSD::String&) const;
|
||||
bool has(const LLSD::String&) const override;
|
||||
|
||||
using LLSD::Impl::get; // Unhiding get(LLSD::Integer)
|
||||
using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
|
||||
using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
|
||||
virtual LLSD get(const LLSD::String&) const;
|
||||
virtual LLSD getKeys() const;
|
||||
LLSD get(const LLSD::String&) const override;
|
||||
LLSD getKeys() const override;
|
||||
void insert(const LLSD::String& k, const LLSD& v);
|
||||
virtual void erase(const LLSD::String&);
|
||||
void erase(const LLSD::String&) override;
|
||||
LLSD& ref(const LLSD::String&);
|
||||
virtual const LLSD& ref(const LLSD::String&) const;
|
||||
const LLSD& ref(const LLSD::String&) const override;
|
||||
|
||||
virtual int size() const { return mData.size(); }
|
||||
int size() const override { return mData.size(); }
|
||||
|
||||
LLSD::map_iterator beginMap() { return mData.begin(); }
|
||||
LLSD::map_iterator endMap() { return mData.end(); }
|
||||
virtual LLSD::map_const_iterator beginMap() const { return mData.begin(); }
|
||||
virtual LLSD::map_const_iterator endMap() const { return mData.end(); }
|
||||
DataMap& map() final override { return mData; }
|
||||
const DataMap& map() const final override { return mData; }
|
||||
|
||||
virtual void dumpStats() const;
|
||||
virtual void calcStats(S32 type_counts[], S32 share_counts[]) const;
|
||||
void dumpStats() const override;
|
||||
void calcStats(S32 type_counts[], S32 share_counts[]) const override;
|
||||
};
|
||||
|
||||
ImplMap& ImplMap::makeMap(LLSD::Impl*& var)
|
||||
@@ -481,7 +485,7 @@ namespace
|
||||
{
|
||||
//std::cout << " " << (*iter).first << ": " << (*iter).second << std::endl;
|
||||
Impl::calcStats((*iter).second, type_counts, share_counts);
|
||||
iter++;
|
||||
++iter;
|
||||
}
|
||||
|
||||
// Add in the values for this map
|
||||
@@ -489,7 +493,7 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
class ImplArray : public LLSD::Impl
|
||||
class ImplArray final : public LLSD::Impl
|
||||
{
|
||||
private:
|
||||
typedef std::vector<LLSD> DataVector;
|
||||
@@ -502,32 +506,28 @@ namespace
|
||||
public:
|
||||
ImplArray() { }
|
||||
|
||||
virtual ImplArray& makeArray(Impl*&);
|
||||
ImplArray& makeArray(Impl*&) override;
|
||||
|
||||
virtual LLSD::Type type() const { return LLSD::TypeArray; }
|
||||
LLSD::Type type() const override { return LLSD::TypeArray; }
|
||||
|
||||
virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
|
||||
LLSD::Boolean asBoolean() const override { return !mData.empty(); }
|
||||
|
||||
using LLSD::Impl::get; // Unhiding get(LLSD::String)
|
||||
using LLSD::Impl::erase; // Unhiding erase(LLSD::String)
|
||||
using LLSD::Impl::ref; // Unhiding ref(LLSD::String)
|
||||
virtual int size() const;
|
||||
virtual LLSD get(LLSD::Integer) const;
|
||||
int size() const override;
|
||||
LLSD get(LLSD::Integer) const override;
|
||||
void set(LLSD::Integer, const LLSD&);
|
||||
void insert(LLSD::Integer, const LLSD&);
|
||||
LLSD& append(const LLSD&);
|
||||
virtual void erase(LLSD::Integer);
|
||||
void erase(LLSD::Integer) override;
|
||||
LLSD& ref(LLSD::Integer);
|
||||
virtual const LLSD& ref(LLSD::Integer) const;
|
||||
const LLSD& ref(LLSD::Integer) const override;
|
||||
|
||||
LLSD::array_iterator beginArray() { return mData.begin(); }
|
||||
LLSD::array_iterator endArray() { return mData.end(); }
|
||||
LLSD::reverse_array_iterator rbeginArray() { return mData.rbegin(); }
|
||||
LLSD::reverse_array_iterator rendArray() { return mData.rend(); }
|
||||
virtual LLSD::array_const_iterator beginArray() const { return mData.begin(); }
|
||||
virtual LLSD::array_const_iterator endArray() const { return mData.end(); }
|
||||
DataVector& array() final override { return mData; }
|
||||
const DataVector& array() const final override { return mData; }
|
||||
|
||||
virtual void calcStats(S32 type_counts[], S32 share_counts[]) const;
|
||||
void calcStats(S32 type_counts[], S32 share_counts[]) const override;
|
||||
};
|
||||
|
||||
ImplArray& ImplArray::makeArray(Impl*& var)
|
||||
@@ -631,7 +631,7 @@ namespace
|
||||
while (iter != endArray())
|
||||
{ // Add values for all items held in the array
|
||||
Impl::calcStats((*iter), type_counts, share_counts);
|
||||
iter++;
|
||||
++iter;
|
||||
}
|
||||
|
||||
// Add in the values for this array
|
||||
@@ -703,7 +703,7 @@ void LLSD::Impl::assign(Impl*& var, const Impl* other)
|
||||
|
||||
void LLSD::Impl::assignUndefined(Impl*& var)
|
||||
{
|
||||
reset(var, 0);
|
||||
reset(var, nullptr);
|
||||
}
|
||||
|
||||
void LLSD::Impl::assign(Impl*& var, LLSD::Boolean v)
|
||||
@@ -779,7 +779,7 @@ void LLSD::Impl::calcStats(S32 type_counts[], S32 share_counts[]) const
|
||||
S32 tp = S32(type());
|
||||
if (0 <= tp && tp < LLSD::TypeLLSDNumTypes)
|
||||
{
|
||||
type_counts[tp]++;
|
||||
type_counts[tp]++;
|
||||
if (shared())
|
||||
{
|
||||
share_counts[tp]++;
|
||||
@@ -813,10 +813,10 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
LLSD::LLSD() : impl(0) { ALLOC_LLSD_OBJECT; }
|
||||
LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, 0); }
|
||||
LLSD::LLSD() : impl(nullptr) { ALLOC_LLSD_OBJECT; }
|
||||
LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, nullptr); }
|
||||
|
||||
LLSD::LLSD(const LLSD& other) : impl(0) { ALLOC_LLSD_OBJECT; assign(other); }
|
||||
LLSD::LLSD(const LLSD& other) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(other); }
|
||||
void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); }
|
||||
|
||||
|
||||
@@ -825,17 +825,17 @@ void LLSD::clear() { Impl::assignUndefined(impl); }
|
||||
LLSD::Type LLSD::type() const { return safe(impl).type(); }
|
||||
|
||||
// Scalar Constructors
|
||||
LLSD::LLSD(Boolean v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(Integer v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(Real v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const UUID& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const String& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const Date& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const URI& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const Binary& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(Boolean v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(Integer v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(Real v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const UUID& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const String& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const Date& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const URI& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const Binary& v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
|
||||
// Convenience Constructors
|
||||
LLSD::LLSD(F32 v) : impl(0) { ALLOC_LLSD_OBJECT; assign((Real)v); }
|
||||
LLSD::LLSD(F32 v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign((Real)v); }
|
||||
|
||||
// Scalar Assignment
|
||||
void LLSD::assign(Boolean v) { safe(impl).assign(impl, v); }
|
||||
@@ -860,7 +860,7 @@ const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); }
|
||||
const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); }
|
||||
|
||||
// const char * helpers
|
||||
LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
LLSD::LLSD(const char* v) : impl(nullptr) { ALLOC_LLSD_OBJECT; assign(v); }
|
||||
void LLSD::assign(const char* v)
|
||||
{
|
||||
if(v) assign(std::string(v));
|
||||
@@ -927,7 +927,7 @@ static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat)
|
||||
// sStorage will point to the result of the last call. This will actually
|
||||
// be one leak, but since this is used only when running under the
|
||||
// debugger, it should not be an issue.
|
||||
static char *sStorage = NULL;
|
||||
static char *sStorage = nullptr;
|
||||
delete[] sStorage;
|
||||
std::string out_string;
|
||||
{
|
||||
@@ -957,18 +957,24 @@ const char *LLSD::dump(const LLSD &llsd)
|
||||
return llsd_dump(llsd, false);
|
||||
}
|
||||
|
||||
LLSD::map_iterator LLSD::beginMap() { return makeMap(impl).beginMap(); }
|
||||
LLSD::map_iterator LLSD::endMap() { return makeMap(impl).endMap(); }
|
||||
LLSD::map_const_iterator LLSD::beginMap() const { return safe(impl).beginMap(); }
|
||||
LLSD::map_const_iterator LLSD::endMap() const { return safe(impl).endMap(); }
|
||||
std::map<LLSD::String, LLSD>& LLSD::map() { return makeMap(impl).map(); }
|
||||
const std::map<LLSD::String, LLSD>& LLSD::map() const { return safe(impl).map(); }
|
||||
|
||||
LLSD::array_iterator LLSD::beginArray() { return makeArray(impl).beginArray(); }
|
||||
LLSD::array_iterator LLSD::endArray() { return makeArray(impl).endArray(); }
|
||||
LLSD::array_const_iterator LLSD::beginArray() const{ return safe(impl).beginArray(); }
|
||||
LLSD::array_const_iterator LLSD::endArray() const { return safe(impl).endArray(); }
|
||||
LLSD::map_iterator LLSD::beginMap() { return map().begin(); }
|
||||
LLSD::map_iterator LLSD::endMap() { return map().end(); }
|
||||
LLSD::map_const_iterator LLSD::beginMap() const { return map().cbegin(); }
|
||||
LLSD::map_const_iterator LLSD::endMap() const { return map().cend(); }
|
||||
|
||||
LLSD::reverse_array_iterator LLSD::rbeginArray() { return makeArray(impl).rbeginArray(); }
|
||||
LLSD::reverse_array_iterator LLSD::rendArray() { return makeArray(impl).rendArray(); }
|
||||
std::vector<LLSD>& LLSD::array() { return makeArray(impl).array(); }
|
||||
const std::vector<LLSD>& LLSD::array() const { return safe(impl).array(); }
|
||||
|
||||
LLSD::array_iterator LLSD::beginArray() { return array().begin(); }
|
||||
LLSD::array_iterator LLSD::endArray() { return array().end(); }
|
||||
LLSD::array_const_iterator LLSD::beginArray() const{ return array().cbegin(); }
|
||||
LLSD::array_const_iterator LLSD::endArray() const { return array().cend(); }
|
||||
|
||||
LLSD::reverse_array_iterator LLSD::rbeginArray() { return array().rbegin(); }
|
||||
LLSD::reverse_array_iterator LLSD::rendArray() { return array().rend(); }
|
||||
|
||||
namespace llsd
|
||||
{
|
||||
|
||||
@@ -320,6 +320,8 @@ public:
|
||||
typedef std::map<String, LLSD>::iterator map_iterator;
|
||||
typedef std::map<String, LLSD>::const_iterator map_const_iterator;
|
||||
|
||||
std::map<String, LLSD>& map();
|
||||
const std::map<String, LLSD>& map() const;
|
||||
map_iterator beginMap();
|
||||
map_iterator endMap();
|
||||
map_const_iterator beginMap() const;
|
||||
@@ -329,6 +331,8 @@ public:
|
||||
typedef std::vector<LLSD>::const_iterator array_const_iterator;
|
||||
typedef std::vector<LLSD>::reverse_iterator reverse_array_iterator;
|
||||
|
||||
std::vector<LLSD>& array();
|
||||
const std::vector<LLSD>& array() const;
|
||||
array_iterator beginArray();
|
||||
array_iterator endArray();
|
||||
array_const_iterator beginArray() const;
|
||||
|
||||
@@ -79,6 +79,17 @@ LLSD LlsdFromJson(const nlohmann::json &val)
|
||||
return result;
|
||||
}
|
||||
|
||||
LLSD LlsdFromJsonString(const std::string& str)
|
||||
{
|
||||
auto json = nlohmann::json::parse(str, nullptr, false);
|
||||
if (json.is_discarded())
|
||||
{
|
||||
LL_WARNS() << "Cannot parse invalid json string:\n" << str << LL_ENDL;
|
||||
return LLSD();
|
||||
}
|
||||
return LlsdFromJson(json);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
nlohmann::json LlsdToJson(const LLSD &val)
|
||||
{
|
||||
@@ -111,9 +122,9 @@ nlohmann::json LlsdToJson(const LLSD &val)
|
||||
}
|
||||
break;
|
||||
case LLSD::TypeArray:
|
||||
for (LLSD::array_const_iterator it = val.beginArray(); it != val.endArray(); ++it)
|
||||
for (auto const& entry : val.array())
|
||||
{
|
||||
result.push_back(LlsdToJson(*it));
|
||||
result.push_back(LlsdToJson(entry));
|
||||
}
|
||||
break;
|
||||
case LLSD::TypeBinary:
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
/// For maps and arrays child entries will be converted and added to the structure.
|
||||
/// Order is preserved for an array but not for objects.
|
||||
LLSD LlsdFromJson(const nlohmann::json &val);
|
||||
LLSD LlsdFromJsonString(const std::string& body);
|
||||
|
||||
/// Convert an LLSD object into Parsed JSON object maintaining member names and
|
||||
/// array indexs.
|
||||
|
||||
@@ -267,12 +267,10 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI
|
||||
}
|
||||
else if (sd.isArray())
|
||||
{
|
||||
for (LLSD::array_const_iterator it = sd.beginArray();
|
||||
it != sd.endArray();
|
||||
++it)
|
||||
for (auto const& entry : sd.array())
|
||||
{
|
||||
stack.push_back(make_pair(std::string(), true));
|
||||
readSDValues(cb, *it, stack);
|
||||
readSDValues(cb, entry, stack);
|
||||
stack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1322,13 +1322,11 @@ S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32
|
||||
{
|
||||
ostr << post << pre << "[";
|
||||
bool need_comma = false;
|
||||
auto iter = data.beginArray();
|
||||
auto end = data.endArray();
|
||||
for(; iter != end; ++iter)
|
||||
for (const auto& entry : data.array())
|
||||
{
|
||||
if(need_comma) ostr << ",";
|
||||
if (need_comma) ostr << ",";
|
||||
need_comma = true;
|
||||
format_count += format_impl(*iter, ostr, options, level + 1);
|
||||
format_count += format_impl(entry, ostr, options, level + 1);
|
||||
}
|
||||
ostr << "]";
|
||||
break;
|
||||
@@ -1461,11 +1459,9 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option
|
||||
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)
|
||||
for (const auto& entry : data.array())
|
||||
{
|
||||
format_count += format(*iter, ostr);
|
||||
format_count += format(entry, ostr);
|
||||
}
|
||||
ostr.put(']');
|
||||
break;
|
||||
|
||||
@@ -116,11 +116,9 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
|
||||
else
|
||||
{
|
||||
ostr << pre << "<array>" << post;
|
||||
LLSD::array_const_iterator iter = data.beginArray();
|
||||
LLSD::array_const_iterator end = data.endArray();
|
||||
for(; iter != end; ++iter)
|
||||
for (const auto& entry : data.array())
|
||||
{
|
||||
format_count += format_impl(*iter, ostr, options, level + 1);
|
||||
format_count += format_impl(entry, ostr, options, level + 1);
|
||||
}
|
||||
ostr << pre << "</array>" << post;
|
||||
}
|
||||
|
||||
@@ -891,9 +891,9 @@ LLSD llsd_clone(LLSD value, LLSD filter)
|
||||
break;
|
||||
case LLSD::TypeArray:
|
||||
clone = LLSD::emptyArray();
|
||||
for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
|
||||
for (auto const& entry : value.array())
|
||||
{
|
||||
clone.append(llsd_clone(*ita, filter));
|
||||
clone.append(llsd_clone(entry, filter));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -943,9 +943,9 @@ LLSD llsd_shallow(LLSD value, LLSD filter)
|
||||
else if (value.isArray())
|
||||
{
|
||||
shallow = LLSD::emptyArray();
|
||||
for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
|
||||
for (auto const& entry : value.array())
|
||||
{
|
||||
shallow.append(*ita);
|
||||
shallow.append(entry);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1340,7 +1340,8 @@ void LLStringUtil::formatNumber(std::string& numStr, std::string decimals)
|
||||
// std::locale() throws if the locale is unknown! (EXT-7926)
|
||||
try
|
||||
{
|
||||
strStream.imbue(std::locale(sLocale.c_str()));
|
||||
std::locale locale(sLocale.c_str());
|
||||
strStream.imbue(locale);
|
||||
} catch (const std::exception &)
|
||||
{
|
||||
LL_WARNS_ONCE("Locale") << "Cannot set locale to " << sLocale << LL_ENDL;
|
||||
|
||||
@@ -243,7 +243,7 @@ public:
|
||||
bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; }
|
||||
std::size_t length() const { return mString.length(); }
|
||||
// The destructor may not throw.
|
||||
~LLFormatMapString() throw() { }
|
||||
~LLFormatMapString() noexcept { }
|
||||
|
||||
private:
|
||||
std::string mString;
|
||||
|
||||
@@ -1274,7 +1274,7 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
|
||||
const S32 UNCOMPRESS_BUFFER_SIZE = 32768;
|
||||
BOOL retval = FALSE;
|
||||
gzFile src = NULL;
|
||||
U8 buffer[UNCOMPRESS_BUFFER_SIZE];
|
||||
std::array<U8, UNCOMPRESS_BUFFER_SIZE> buffer;
|
||||
LLFILE *dst = NULL;
|
||||
S32 bytes = 0;
|
||||
tmpfile = dstfile + ".t";
|
||||
@@ -1288,8 +1288,8 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
|
||||
if (! dst) goto err;
|
||||
do
|
||||
{
|
||||
bytes = gzread(src, buffer, UNCOMPRESS_BUFFER_SIZE);
|
||||
size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst);
|
||||
bytes = gzread(src, buffer.data(), buffer.size());
|
||||
size_t nwrit = fwrite(buffer.data(), sizeof(U8), bytes, dst);
|
||||
if (nwrit < (size_t) bytes)
|
||||
{
|
||||
LL_WARNS() << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << LL_ENDL;
|
||||
@@ -1311,7 +1311,7 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
|
||||
const S32 COMPRESS_BUFFER_SIZE = 32768;
|
||||
std::string tmpfile;
|
||||
BOOL retval = FALSE;
|
||||
U8 buffer[COMPRESS_BUFFER_SIZE];
|
||||
std::array<U8, COMPRESS_BUFFER_SIZE> buffer;
|
||||
gzFile dst = NULL;
|
||||
LLFILE *src = NULL;
|
||||
S32 bytes = 0;
|
||||
@@ -1325,9 +1325,9 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
|
||||
src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */
|
||||
if (! src) goto err;
|
||||
|
||||
while ((bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE, src)) > 0)
|
||||
while ((bytes = (S32)fread(buffer.data(), sizeof(U8), buffer.size(), src)) > 0)
|
||||
{
|
||||
if (gzwrite(dst, buffer, bytes) <= 0)
|
||||
if (gzwrite(dst, buffer.data(), bytes) <= 0)
|
||||
{
|
||||
LL_WARNS() << "gzwrite failed: " << gzerror(dst, NULL) << LL_ENDL;
|
||||
goto err;
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include "llsdutil_math.h"
|
||||
#include "message.h"
|
||||
#include "u64.h"
|
||||
#include "llregionflags.h"
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
|
||||
static const F32 SOME_BIG_NUMBER = 1000.0f;
|
||||
static const F32 SOME_BIG_NEG_NUMBER = -1000.0f;
|
||||
@@ -742,8 +744,8 @@ void LLParcel::unpackMessage(LLMessageSystem* msg)
|
||||
void LLParcel::packAccessEntries(LLMessageSystem* msg,
|
||||
const std::map<LLUUID,LLAccessEntry>& list)
|
||||
{
|
||||
access_map_const_iterator cit = list.begin();
|
||||
access_map_const_iterator end = list.end();
|
||||
LLAccessEntry::map::const_iterator cit = list.begin();
|
||||
LLAccessEntry::map::const_iterator end = list.end();
|
||||
|
||||
if (cit == end)
|
||||
{
|
||||
@@ -794,9 +796,28 @@ void LLParcel::unpackAccessEntries(LLMessageSystem* msg,
|
||||
}
|
||||
|
||||
|
||||
void LLParcel::unpackExperienceEntries(LLMessageSystem* msg, U32 type)
|
||||
{
|
||||
LLUUID id;
|
||||
|
||||
S32 i;
|
||||
S32 count = msg->getNumberOfBlocksFast(_PREHASH_List);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
|
||||
|
||||
if (id.notNull())
|
||||
{
|
||||
mExperienceKeys[id] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLParcel::expirePasses(S32 now)
|
||||
{
|
||||
access_map_iterator itor = mAccessList.begin();
|
||||
LLAccessEntry::map::iterator itor = mAccessList.begin();
|
||||
while (itor != mAccessList.end())
|
||||
{
|
||||
const LLAccessEntry& entry = (*itor).second;
|
||||
@@ -886,7 +907,7 @@ BOOL LLParcel::addToAccessList(const LLUUID& agent_id, S32 time)
|
||||
// Can't add owner to these lists
|
||||
return FALSE;
|
||||
}
|
||||
access_map_iterator itor = mAccessList.begin();
|
||||
LLAccessEntry::map::iterator itor = mAccessList.begin();
|
||||
while (itor != mAccessList.end())
|
||||
{
|
||||
const LLAccessEntry& entry = (*itor).second;
|
||||
@@ -931,7 +952,7 @@ BOOL LLParcel::addToBanList(const LLUUID& agent_id, S32 time)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
access_map_iterator itor = mBanList.begin();
|
||||
LLAccessEntry::map::iterator itor = mBanList.begin();
|
||||
while (itor != mBanList.end())
|
||||
{
|
||||
const LLAccessEntry& entry = (*itor).second;
|
||||
@@ -970,7 +991,7 @@ BOOL remove_from_access_array(std::map<LLUUID,LLAccessEntry>* list,
|
||||
const LLUUID& agent_id)
|
||||
{
|
||||
BOOL removed = FALSE;
|
||||
access_map_iterator itor = list->begin();
|
||||
LLAccessEntry::map::iterator itor = list->begin();
|
||||
while (itor != list->end())
|
||||
{
|
||||
const LLAccessEntry& entry = (*itor).second;
|
||||
@@ -1091,7 +1112,7 @@ void LLParcel::startSale(const LLUUID& buyer_id, BOOL is_buyer_group)
|
||||
mSaleTimerExpires.start();
|
||||
mSaleTimerExpires.setTimerExpirySec(U64Microseconds(DEFAULT_USEC_SALE_TIMEOUT));
|
||||
mStatus = OS_LEASE_PENDING;
|
||||
mClaimDate = time(NULL);
|
||||
mClaimDate = time(nullptr);
|
||||
setAuctionID(0);
|
||||
// clear the autoreturn whenever land changes hands
|
||||
setCleanOtherTime(0);
|
||||
@@ -1313,3 +1334,58 @@ LLParcel::ECategory category_ui_string_to_category(const std::string& s)
|
||||
// is a distinct option from "None" and "Other"
|
||||
return LLParcel::C_ANY;
|
||||
}
|
||||
|
||||
LLAccessEntry::map LLParcel::getExperienceKeysByType(U32 type) const
|
||||
{
|
||||
LLAccessEntry::map access;
|
||||
LLAccessEntry entry;
|
||||
xp_type_map_t::const_iterator it = mExperienceKeys.begin();
|
||||
for(/**/; it != mExperienceKeys.end(); ++it)
|
||||
{
|
||||
if(it->second == type)
|
||||
{
|
||||
entry.mID = it->first;
|
||||
access[entry.mID] = entry;
|
||||
}
|
||||
}
|
||||
return access;
|
||||
}
|
||||
|
||||
void LLParcel::clearExperienceKeysByType(U32 type)
|
||||
{
|
||||
xp_type_map_t::iterator it = mExperienceKeys.begin();
|
||||
while(it != mExperienceKeys.end())
|
||||
{
|
||||
if(it->second == type)
|
||||
{
|
||||
mExperienceKeys.erase(it++);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLParcel::setExperienceKeyType(const LLUUID& experience_key, U32 type)
|
||||
{
|
||||
if (type == EXPERIENCE_KEY_TYPE_NONE)
|
||||
{
|
||||
mExperienceKeys.erase(experience_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (countExperienceKeyType(type) < PARCEL_MAX_EXPERIENCE_LIST)
|
||||
{
|
||||
mExperienceKeys[experience_key] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U32 LLParcel::countExperienceKeyType(U32 type)
|
||||
{
|
||||
return std::count_if(
|
||||
boost::begin(mExperienceKeys | boost::adaptors::map_values),
|
||||
boost::end(mExperienceKeys | boost::adaptors::map_values),
|
||||
std::bind2nd(std::equal_to<U32>(), type));
|
||||
}
|
||||
|
||||
@@ -60,6 +60,9 @@ const S32 PARCEL_MAX_ACCESS_LIST = 300;
|
||||
//for access/ban lists.
|
||||
const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;
|
||||
|
||||
// Maximum number of experiences
|
||||
const S32 PARCEL_MAX_EXPERIENCE_LIST = 24;
|
||||
|
||||
// Weekly charge for listing a parcel in the directory
|
||||
const S32 PARCEL_DIRECTORY_FEE = 30;
|
||||
|
||||
@@ -141,9 +144,11 @@ class LLSD;
|
||||
class LLAccessEntry
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::map<LLUUID,LLAccessEntry> map;
|
||||
|
||||
LLAccessEntry()
|
||||
: mID(),
|
||||
mTime(0),
|
||||
: mTime(0),
|
||||
mFlags(0)
|
||||
{}
|
||||
|
||||
@@ -152,8 +157,6 @@ public:
|
||||
U32 mFlags; // Not used - currently should always be zero
|
||||
};
|
||||
|
||||
typedef std::map<LLUUID,LLAccessEntry>::iterator access_map_iterator;
|
||||
typedef std::map<LLUUID,LLAccessEntry>::const_iterator access_map_const_iterator;
|
||||
|
||||
class LLParcel
|
||||
{
|
||||
@@ -331,6 +334,9 @@ public:
|
||||
void unpackAccessEntries(LLMessageSystem* msg,
|
||||
std::map<LLUUID,LLAccessEntry>* list);
|
||||
|
||||
void unpackExperienceEntries(LLMessageSystem* msg, U32 type);
|
||||
|
||||
|
||||
void setAABBMin(const LLVector3& min) { mAABBMin = min; }
|
||||
void setAABBMax(const LLVector3& max) { mAABBMax = max; }
|
||||
|
||||
@@ -707,6 +713,17 @@ public:
|
||||
std::map<LLUUID,LLAccessEntry> mTempBanList;
|
||||
std::map<LLUUID,LLAccessEntry> mTempAccessList;
|
||||
|
||||
typedef std::map<LLUUID, U32> xp_type_map_t;
|
||||
|
||||
void setExperienceKeyType(const LLUUID& experience_key, U32 type);
|
||||
U32 countExperienceKeyType(U32 type);
|
||||
U32 getExperienceKeyType(const LLUUID& experience_key)const;
|
||||
LLAccessEntry::map getExperienceKeysByType(U32 type)const;
|
||||
void clearExperienceKeysByType(U32 type);
|
||||
|
||||
private:
|
||||
xp_type_map_t mExperienceKeys;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,31 +1,25 @@
|
||||
/**
|
||||
* @file llparcelflags.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2002-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -97,8 +91,10 @@ const U32 PF_DEFAULT = PF_ALLOW_FLY
|
||||
| PF_USE_ESTATE_VOICE_CHAN;
|
||||
|
||||
// Access list flags
|
||||
const U32 AL_ACCESS = (1 << 0);
|
||||
const U32 AL_BAN = (1 << 1);
|
||||
const U32 AL_ACCESS = (1 << 0);
|
||||
const U32 AL_BAN = (1 << 1);
|
||||
const U32 AL_ALLOW_EXPERIENCE = (1 << 3);
|
||||
const U32 AL_BLOCK_EXPERIENCE = (1 << 4);
|
||||
//const U32 AL_RENTER = (1 << 2);
|
||||
|
||||
// Block access return values. BA_ALLOWED is the only success case
|
||||
|
||||
@@ -103,9 +103,9 @@ LLSD LLSettingsBase::combineSDMaps(const LLSD &settings, const LLSD &other) cons
|
||||
break;
|
||||
case LLSD::TypeArray:
|
||||
newSettings[key_name] = LLSD::emptyArray();
|
||||
for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
|
||||
for (auto const& entry : value.array())
|
||||
{
|
||||
newSettings[key_name].append(*ita);
|
||||
newSettings[key_name].append(entry);
|
||||
}
|
||||
break;
|
||||
//case LLSD::TypeInteger:
|
||||
@@ -137,9 +137,9 @@ LLSD LLSettingsBase::combineSDMaps(const LLSD &settings, const LLSD &other) cons
|
||||
break;
|
||||
case LLSD::TypeArray:
|
||||
newSettings[key_name] = LLSD::emptyArray();
|
||||
for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
|
||||
for (auto const& entry : value.array())
|
||||
{
|
||||
newSettings[key_name].append(*ita);
|
||||
newSettings[key_name].append(entry);
|
||||
}
|
||||
break;
|
||||
//case LLSD::TypeInteger:
|
||||
|
||||
@@ -240,16 +240,16 @@ bool LLSettingsDay::initialize(bool validate_frames)
|
||||
{
|
||||
mDayTracks[i].clear();
|
||||
LLSD curtrack = tracks[i];
|
||||
for (LLSD::array_const_iterator it = curtrack.beginArray(); it != curtrack.endArray(); ++it)
|
||||
for (const auto& entry : curtrack.array())
|
||||
{
|
||||
LLSettingsBase::TrackPosition keyframe = LLSettingsBase::TrackPosition((*it)[SETTING_KEYKFRAME].asReal());
|
||||
LLSettingsBase::TrackPosition keyframe = LLSettingsBase::TrackPosition(entry[SETTING_KEYKFRAME].asReal());
|
||||
keyframe = llclamp(keyframe, 0.0f, 1.0f);
|
||||
LLSettingsBase::ptr_t setting;
|
||||
|
||||
|
||||
if ((*it).has(SETTING_KEYNAME))
|
||||
if (entry.has(SETTING_KEYNAME))
|
||||
{
|
||||
std::string key_name = (*it)[SETTING_KEYNAME];
|
||||
std::string key_name = entry[SETTING_KEYNAME];
|
||||
if (i == TRACK_WATER)
|
||||
{
|
||||
setting = used[key_name];
|
||||
@@ -469,36 +469,36 @@ namespace
|
||||
|
||||
S32 framecount(0);
|
||||
|
||||
for (LLSD::array_iterator track = value.beginArray(); track != value.endArray(); ++track)
|
||||
for (auto& entry : value.array())
|
||||
{
|
||||
S32 index = 0;
|
||||
while (index < (*track).size())
|
||||
while (index < entry.size())
|
||||
{
|
||||
LLSD& elem = (*track)[index];
|
||||
LLSD& elem = entry[index];
|
||||
|
||||
++framecount;
|
||||
if (index >= LLSettingsDay::FRAME_MAX)
|
||||
{
|
||||
(*track).erase(index);
|
||||
entry.erase(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!elem.has(LLSettingsDay::SETTING_KEYKFRAME))
|
||||
{
|
||||
(*track).erase(index);
|
||||
entry.erase(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!elem[LLSettingsDay::SETTING_KEYKFRAME].isReal())
|
||||
{
|
||||
(*track).erase(index);
|
||||
entry.erase(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!elem.has(LLSettingsDay::SETTING_KEYNAME) &&
|
||||
!elem.has(LLSettingsDay::SETTING_KEYID))
|
||||
{
|
||||
(*track).erase(index);
|
||||
entry.erase(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +425,7 @@ public:
|
||||
}
|
||||
|
||||
void accept(oct_traveler* visitor) { visitor->visit(this); }
|
||||
virtual bool isLeaf() const { return mChildCount == 0; }
|
||||
bool isLeaf() const { return mChildCount == 0; }
|
||||
|
||||
U32 getElementCount() const { return mData.size(); }
|
||||
bool isEmpty() const { return mData.size() == 0; }
|
||||
@@ -498,7 +498,7 @@ public:
|
||||
return node;
|
||||
}
|
||||
|
||||
virtual bool insert(T* data)
|
||||
bool insert(T* data) override
|
||||
{
|
||||
OctreeGuard::checkGuarded(this);
|
||||
if (data == NULL || data->getBinIndex() != -1)
|
||||
@@ -537,7 +537,7 @@ public:
|
||||
OctreeStats::getInstance()->realloc(old_cap,mData.capacity());
|
||||
#endif
|
||||
|
||||
BaseType::insert(data);
|
||||
this->notifyAddition(data);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -593,7 +593,7 @@ public:
|
||||
OctreeStats::getInstance()->realloc(old_cap,mData.capacity());
|
||||
#endif
|
||||
|
||||
BaseType::insert(data);
|
||||
this->notifyAddition(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -708,7 +708,7 @@ public:
|
||||
checkAlive();
|
||||
}
|
||||
|
||||
bool remove(T* data)
|
||||
bool remove(T* data) final override
|
||||
{
|
||||
OctreeGuard::checkGuarded(this);
|
||||
S32 i = data->getBinIndex();
|
||||
@@ -849,10 +849,9 @@ public:
|
||||
|
||||
if (!silent)
|
||||
{
|
||||
for (U32 i = 0; i < this->getListenerCount(); i++)
|
||||
for (auto& entry : this->mListeners)
|
||||
{
|
||||
oct_listener* listener = getOctListener(i);
|
||||
listener->handleChildAddition(this, child);
|
||||
((oct_listener*)entry.get())->handleChildAddition(this, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -861,16 +860,17 @@ public:
|
||||
{
|
||||
OctreeGuard::checkGuarded(this);
|
||||
|
||||
for (U32 i = 0; i < this->getListenerCount(); i++)
|
||||
oct_node* child = getChild(index);
|
||||
|
||||
for (auto& entry : this->mListeners)
|
||||
{
|
||||
oct_listener* listener = getOctListener(i);
|
||||
listener->handleChildRemoval(this, getChild(index));
|
||||
((oct_listener*)entry.get())->handleChildRemoval(this, child);
|
||||
}
|
||||
|
||||
if (destroy)
|
||||
{
|
||||
mChild[index]->destroy();
|
||||
delete mChild[index];
|
||||
child->destroy();
|
||||
delete child;
|
||||
}
|
||||
|
||||
--mChildCount;
|
||||
@@ -1012,7 +1012,7 @@ public:
|
||||
}
|
||||
|
||||
// LLOctreeRoot::insert
|
||||
bool insert(T* data)
|
||||
bool insert(T* data) final override
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
|
||||
@@ -44,7 +44,6 @@ public:
|
||||
virtual void handleInsertion(const LLTreeNode<T>* node, T* data) = 0;
|
||||
virtual void handleRemoval(const LLTreeNode<T>* node, T* data) = 0;
|
||||
virtual void handleDestruction(const LLTreeNode<T>* node) = 0;
|
||||
virtual void handleStateChange(const LLTreeNode<T>* node) = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -53,11 +52,15 @@ class LLTreeNode
|
||||
public:
|
||||
virtual ~LLTreeNode();
|
||||
|
||||
virtual bool insert(T* data);
|
||||
virtual bool remove(T* data);
|
||||
virtual void notifyRemoval(T* data);
|
||||
virtual U32 getListenerCount() { return mListeners.size(); }
|
||||
virtual LLTreeListener<T>* getListener(U32 index) const
|
||||
virtual bool insert(T* data) = 0;
|
||||
virtual bool remove(T* data) = 0;
|
||||
bool notifyAddition(T* data);
|
||||
void notifyRemoval(T* data);
|
||||
U32 getListenerCount() const
|
||||
{
|
||||
return mListeners.size();
|
||||
}
|
||||
LLTreeListener<T>* getListener(U32 index) const
|
||||
{
|
||||
if(index < mListeners.size())
|
||||
{
|
||||
@@ -65,7 +68,10 @@ public:
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
virtual void addListener(LLTreeListener<T>* listener) { mListeners.push_back(listener); }
|
||||
void addListener(LLTreeListener<T>* listener)
|
||||
{
|
||||
mListeners.push_back(listener);
|
||||
}
|
||||
|
||||
protected:
|
||||
void destroyListeners()
|
||||
@@ -97,7 +103,7 @@ LLTreeNode<T>::~LLTreeNode()
|
||||
};
|
||||
|
||||
template <class T>
|
||||
bool LLTreeNode<T>::insert(T* data)
|
||||
bool LLTreeNode<T>::notifyAddition(T* data)
|
||||
{
|
||||
for (U32 i = 0; i < mListeners.size(); i++)
|
||||
{
|
||||
@@ -106,12 +112,6 @@ bool LLTreeNode<T>::insert(T* data)
|
||||
return true;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
bool LLTreeNode<T>::remove(T* data)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void LLTreeNode<T>::notifyRemoval(T* data)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ class LLVolumeParams;
|
||||
class LLProfile;
|
||||
class LLPath;
|
||||
|
||||
template <class T> class LLOctreeNode;
|
||||
template <class T> class LLOctreeRoot;
|
||||
|
||||
class LLVolumeFace;
|
||||
class LLVolume;
|
||||
@@ -964,7 +964,7 @@ public:
|
||||
// vertices per joint.
|
||||
LLJointRiggingInfoTab mJointRiggingInfoTab;
|
||||
|
||||
LLOctreeNode<LLVolumeTriangle>* mOctree;
|
||||
LLOctreeRoot<LLVolumeTriangle>* mOctree;
|
||||
|
||||
//whether or not face has been cache optimized
|
||||
BOOL mOptimized;
|
||||
|
||||
@@ -112,14 +112,13 @@ public:
|
||||
}
|
||||
|
||||
//LISTENER FUNCTIONS
|
||||
virtual void handleChildAddition(const LLOctreeNode<LLVolumeTriangle>* parent,
|
||||
LLOctreeNode<LLVolumeTriangle>* child);
|
||||
virtual void handleStateChange(const LLTreeNode<LLVolumeTriangle>* node) { }
|
||||
virtual void handleChildRemoval(const LLOctreeNode<LLVolumeTriangle>* parent,
|
||||
const LLOctreeNode<LLVolumeTriangle>* child) { }
|
||||
virtual void handleInsertion(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) { }
|
||||
virtual void handleRemoval(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) { }
|
||||
virtual void handleDestruction(const LLTreeNode<LLVolumeTriangle>* node) { }
|
||||
void handleChildAddition(const LLOctreeNode<LLVolumeTriangle>* parent,
|
||||
LLOctreeNode<LLVolumeTriangle>* child) final override;
|
||||
void handleChildRemoval(const LLOctreeNode<LLVolumeTriangle>* parent,
|
||||
const LLOctreeNode<LLVolumeTriangle>* child) final override { }
|
||||
void handleInsertion(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) final override { }
|
||||
void handleRemoval(const LLTreeNode<LLVolumeTriangle>* node, LLVolumeTriangle* tri) final override { }
|
||||
void handleDestruction(const LLTreeNode<LLVolumeTriangle>* node) final override { }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@@ -45,6 +45,7 @@ set(llmessage_SOURCE_FILES
|
||||
llclassifiedflags.cpp
|
||||
lldatapacker.cpp
|
||||
lldispatcher.cpp
|
||||
llexperiencecache.cpp
|
||||
llfiltersd2xmlrpc.cpp
|
||||
llhost.cpp
|
||||
llhttpclient.cpp
|
||||
@@ -133,11 +134,13 @@ set(llmessage_HEADER_FILES
|
||||
llcipher.h
|
||||
llcircuit.h
|
||||
llclassifiedflags.h
|
||||
llcororesponder.h
|
||||
llcurl.h
|
||||
lldatapacker.h
|
||||
lldbstrings.h
|
||||
lldispatcher.h
|
||||
lleventflags.h
|
||||
llexperiencecache.h
|
||||
llfiltersd2xmlrpc.h
|
||||
llfollowcamparams.h
|
||||
llhost.h
|
||||
|
||||
63
indra/llmessage/llcororesponder.h
Normal file
63
indra/llmessage/llcororesponder.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* @file llcororesponder.h
|
||||
* @brief A responder purposed to call coro functions, to ease transition to LLCoro
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
*
|
||||
* Copyright (C) 2020, Liru Færs
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include "llhttpclient.h"
|
||||
|
||||
struct LLCoroResponderBase : public LLHTTPClient::ResponderWithCompleted
|
||||
{
|
||||
const AIHTTPReceivedHeaders& getHeaders() const { return mReceivedHeaders; }
|
||||
const LLSD& getContent() const { return mContent; }
|
||||
|
||||
char const* getName() const override final { return "LLCoroResponder"; }
|
||||
protected:
|
||||
LLCoroResponderBase() {}
|
||||
};
|
||||
|
||||
struct LLCoroResponder final : public LLCoroResponderBase
|
||||
{
|
||||
typedef std::function<void(const LLCoroResponder&)> cb_t;
|
||||
LLCoroResponder(const cb_t& cb) : mCB(cb) {}
|
||||
void httpCompleted() override { mCB(*this); }
|
||||
private:
|
||||
const cb_t mCB;
|
||||
};
|
||||
|
||||
struct LLCoroResponderRaw final : public LLCoroResponderBase
|
||||
{
|
||||
typedef std::function<void(const LLCoroResponderRaw&, const std::string&)> cb_t;
|
||||
LLCoroResponderRaw(const cb_t& cb) : mCB(cb) {}
|
||||
void completedRaw(const LLChannelDescriptors& channels, const buffer_ptr_t& buffer) override
|
||||
{
|
||||
std::string content;
|
||||
decode_raw_body(channels, buffer, content);
|
||||
mCB(*this, content);
|
||||
}
|
||||
private:
|
||||
const cb_t mCB;
|
||||
};
|
||||
|
||||
921
indra/llmessage/llexperiencecache.cpp
Normal file
921
indra/llmessage/llexperiencecache.cpp
Normal file
@@ -0,0 +1,921 @@
|
||||
/**
|
||||
* @file llexperiencecache.cpp
|
||||
* @brief llexperiencecache and related class definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#include "llexperiencecache.h"
|
||||
|
||||
#include "llavatarname.h"
|
||||
#include "llcororesponder.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "lleventfilter.h"
|
||||
#include "lldir.h"
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
|
||||
//=========================================================================
|
||||
namespace LLExperienceCacheImpl
|
||||
{
|
||||
void mapKeys(const LLSD& legacyKeys);
|
||||
F64 getErrorRetryDeltaTime(S32 status, const AIHTTPReceivedHeaders& headers);
|
||||
bool maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age);
|
||||
|
||||
static const std::string PRIVATE_KEY = "private_id";
|
||||
static const std::string EXPERIENCE_ID = "public_id";
|
||||
|
||||
static const std::string MAX_AGE("max-age");
|
||||
static const boost::char_separator<char> EQUALS_SEPARATOR("=");
|
||||
static const boost::char_separator<char> COMMA_SEPARATOR(",");
|
||||
|
||||
// *TODO$: this seems to be tied to mapKeys which is used by bootstrap.... but I don't think that bootstrap is used.
|
||||
typedef std::map<LLUUID, LLUUID> KeyMap;
|
||||
KeyMap privateToPublicKeyMap;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
const std::string LLExperienceCache::PRIVATE_KEY = "private_id";
|
||||
const std::string LLExperienceCache::MISSING = "DoesNotExist";
|
||||
|
||||
const std::string LLExperienceCache::AGENT_ID = "agent_id";
|
||||
const std::string LLExperienceCache::GROUP_ID = "group_id";
|
||||
const std::string LLExperienceCache::EXPERIENCE_ID = "public_id";
|
||||
const std::string LLExperienceCache::NAME = "name";
|
||||
const std::string LLExperienceCache::PROPERTIES = "properties";
|
||||
const std::string LLExperienceCache::EXPIRES = "expiration";
|
||||
const std::string LLExperienceCache::DESCRIPTION = "description";
|
||||
const std::string LLExperienceCache::QUOTA = "quota";
|
||||
const std::string LLExperienceCache::MATURITY = "maturity";
|
||||
const std::string LLExperienceCache::METADATA = "extended_metadata";
|
||||
const std::string LLExperienceCache::SLURL = "slurl";
|
||||
|
||||
// should be in sync with experience-api/experiences/models.py
|
||||
const int LLExperienceCache::PROPERTY_INVALID = 1 << 0;
|
||||
const int LLExperienceCache::PROPERTY_PRIVILEGED = 1 << 3;
|
||||
const int LLExperienceCache::PROPERTY_GRID = 1 << 4;
|
||||
const int LLExperienceCache::PROPERTY_PRIVATE = 1 << 5;
|
||||
const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6;
|
||||
const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7;
|
||||
|
||||
// default values
|
||||
const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0;
|
||||
const S32 LLExperienceCache::DEFAULT_QUOTA = 128; // this is megabytes
|
||||
const int LLExperienceCache::SEARCH_PAGE_SIZE = 30;
|
||||
|
||||
//=========================================================================
|
||||
LLExperienceCache::LLExperienceCache():
|
||||
mShutdown(false)
|
||||
{
|
||||
}
|
||||
|
||||
LLExperienceCache::~LLExperienceCache()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LLExperienceCache::initSingleton()
|
||||
{
|
||||
mCacheFileName = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml");
|
||||
|
||||
LL_INFOS("ExperienceCache") << "Loading " << mCacheFileName << LL_ENDL;
|
||||
llifstream cache_stream(mCacheFileName.c_str());
|
||||
|
||||
if (cache_stream.is_open())
|
||||
{
|
||||
cache_stream >> (*this);
|
||||
}
|
||||
}
|
||||
|
||||
void LLExperienceCache::cleanup()
|
||||
{
|
||||
LL_INFOS("ExperienceCache") << "Saving " << mCacheFileName << LL_ENDL;
|
||||
|
||||
llofstream cache_stream(mCacheFileName.c_str());
|
||||
if (cache_stream.is_open())
|
||||
{
|
||||
cache_stream << (*this);
|
||||
}
|
||||
mShutdown = true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void LLExperienceCache::importFile(std::istream& istr)
|
||||
{
|
||||
LLSD data;
|
||||
S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr);
|
||||
if (parse_count < 1) return;
|
||||
|
||||
LLSD experiences = data["experiences"];
|
||||
|
||||
LLUUID public_key;
|
||||
for (const auto& it : experiences.map())
|
||||
{
|
||||
public_key.set(it.first);
|
||||
mCache[public_key] = it.second;
|
||||
}
|
||||
|
||||
LL_DEBUGS("ExperienceCache") << "importFile() loaded " << mCache.size() << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLExperienceCache::exportFile(std::ostream& ostr) const
|
||||
{
|
||||
LLSD experiences;
|
||||
|
||||
cache_t::const_iterator it = mCache.begin();
|
||||
for (; it != mCache.end(); ++it)
|
||||
{
|
||||
if (!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() ||
|
||||
it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID))
|
||||
continue;
|
||||
|
||||
experiences[it->first.asString()] = it->second;
|
||||
}
|
||||
|
||||
LLSD data;
|
||||
data["experiences"] = experiences;
|
||||
|
||||
LLSDSerialize::toPrettyXML(data, ostr);
|
||||
}
|
||||
|
||||
// *TODO$: Rider: This method does not seem to be used... it may be useful in testing.
|
||||
void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration)
|
||||
{
|
||||
LLExperienceCacheImpl::mapKeys(legacyKeys);
|
||||
for (auto experience : legacyKeys.array())
|
||||
{
|
||||
if (experience.has(EXPERIENCE_ID))
|
||||
{
|
||||
if (!experience.has(EXPIRES))
|
||||
{
|
||||
experience[EXPIRES] = initialExpiration;
|
||||
}
|
||||
processExperience(experience[EXPERIENCE_ID].asUUID(), experience);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("ExperienceCache")
|
||||
<< "Skipping bootstrap entry which is missing " << EXPERIENCE_ID
|
||||
<< LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_if_not_found)
|
||||
{
|
||||
if (private_key.isNull())
|
||||
return LLUUID::null;
|
||||
|
||||
LLExperienceCacheImpl::KeyMap::const_iterator it = LLExperienceCacheImpl::privateToPublicKeyMap.find(private_key);
|
||||
if (it == LLExperienceCacheImpl::privateToPublicKeyMap.end())
|
||||
{
|
||||
if (null_if_not_found)
|
||||
{
|
||||
return LLUUID::null;
|
||||
}
|
||||
return private_key;
|
||||
}
|
||||
LL_WARNS("LLExperience") << "converted private key " << private_key << " to experience_id " << it->second << LL_ENDL;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& experience)
|
||||
{
|
||||
LL_INFOS("ExperienceCache") << "Processing experience \"" << experience[NAME] << "\" with key " << public_key.asString() << LL_ENDL;
|
||||
|
||||
mCache[public_key]=experience;
|
||||
LLSD & row = mCache[public_key];
|
||||
|
||||
if(row.has(EXPIRES))
|
||||
{
|
||||
row[EXPIRES] = row[EXPIRES].asReal() + LLFrameTimer::getTotalSeconds();
|
||||
}
|
||||
|
||||
if(row.has(EXPERIENCE_ID))
|
||||
{
|
||||
mPendingQueue.erase(row[EXPERIENCE_ID].asUUID());
|
||||
}
|
||||
|
||||
//signal
|
||||
signal_map_t::iterator sig_it = mSignalMap.find(public_key);
|
||||
if (sig_it != mSignalMap.end())
|
||||
{
|
||||
signal_ptr signal = sig_it->second;
|
||||
(*signal)(experience);
|
||||
|
||||
mSignalMap.erase(public_key);
|
||||
}
|
||||
}
|
||||
|
||||
const LLExperienceCache::cache_t& LLExperienceCache::getCached()
|
||||
{
|
||||
return mCache;
|
||||
}
|
||||
|
||||
void LLExperienceCache::requestExperiencesCoro(const LLCoroResponder& responder, RequestQueue_t requests)
|
||||
{
|
||||
//LL_INFOS("requestExperiencesCoro") << "url: " << url << LL_ENDL;
|
||||
|
||||
LLSD result = responder.getContent();
|
||||
auto status = responder.getStatus();
|
||||
|
||||
if (!responder.isGoodStatus(status))
|
||||
{
|
||||
F64 now = LLFrameTimer::getTotalSeconds();
|
||||
|
||||
auto headers = responder.getHeaders();
|
||||
// build dummy entries for the failed requests
|
||||
for (auto request : requests)
|
||||
{
|
||||
LLSD exp = get(request);
|
||||
//leave the properties alone if we already have a cache entry for this xp
|
||||
if (exp.isUndefined())
|
||||
{
|
||||
exp[PROPERTIES] = PROPERTY_INVALID;
|
||||
}
|
||||
exp[EXPIRES] = now + LLExperienceCacheImpl::getErrorRetryDeltaTime(status, headers);
|
||||
exp[EXPERIENCE_ID] = request;
|
||||
exp["key_type"] = EXPERIENCE_ID;
|
||||
exp["uuid"] = request;
|
||||
exp["error"] = status;
|
||||
exp[QUOTA] = DEFAULT_QUOTA;
|
||||
|
||||
processExperience(request, exp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD experiences = result["experience_keys"];
|
||||
|
||||
for (const auto& row : experiences.array())
|
||||
{
|
||||
LLUUID public_key = row[EXPERIENCE_ID].asUUID();
|
||||
|
||||
LL_DEBUGS("ExperienceCache") << "Received result for " << public_key
|
||||
<< " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL;
|
||||
|
||||
processExperience(public_key, row);
|
||||
}
|
||||
|
||||
LLSD error_ids = result["error_ids"];
|
||||
|
||||
for (const auto& err : error_ids.array())
|
||||
{
|
||||
LLUUID id = err.asUUID();
|
||||
LLSD exp;
|
||||
exp[EXPIRES] = DEFAULT_EXPIRATION;
|
||||
exp[EXPERIENCE_ID] = id;
|
||||
exp[PROPERTIES] = PROPERTY_INVALID;
|
||||
exp[MISSING] = true;
|
||||
exp[QUOTA] = DEFAULT_QUOTA;
|
||||
|
||||
processExperience(id, exp);
|
||||
LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLExperienceCache::requestExperiences()
|
||||
{
|
||||
if (mCapability == nullptr)
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string urlBase = mCapability("GetExperienceInfo");
|
||||
if (urlBase.empty())
|
||||
{
|
||||
LL_DEBUGS("ExperienceCache") << "No Experience capability." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (*urlBase.rbegin() != '/')
|
||||
{
|
||||
urlBase += "/";
|
||||
}
|
||||
urlBase += "id/";
|
||||
|
||||
|
||||
F64 now = LLFrameTimer::getTotalSeconds();
|
||||
|
||||
const U32 EXP_URL_SEND_THRESHOLD = 3000;
|
||||
constexpr U32 EXP_PAGE_SIZE = EXP_URL_SEND_THRESHOLD / UUID_STR_LENGTH;
|
||||
|
||||
std::ostringstream ostr;
|
||||
ostr << urlBase << "?page_size=" << EXP_PAGE_SIZE;
|
||||
RequestQueue_t requests;
|
||||
|
||||
while (!mRequestQueue.empty())
|
||||
{
|
||||
RequestQueue_t::iterator it = mRequestQueue.begin();
|
||||
LLUUID key = (*it);
|
||||
mRequestQueue.erase(it);
|
||||
requests.insert(key);
|
||||
|
||||
ostr << "&" << EXPERIENCE_ID << "=" << key.asString();
|
||||
mPendingQueue[key] = now;
|
||||
|
||||
if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD))
|
||||
{ // request is placed in the coprocedure pool for the ExpCache cache. Throttling is done by the pool itself.
|
||||
LLHTTPClient::get(ostr.str(), new LLCoroResponder(
|
||||
boost::bind(&LLExperienceCache::requestExperiencesCoro, this, _1, requests) ));
|
||||
|
||||
ostr.str(std::string());
|
||||
ostr << urlBase << "?page_size=" << EXP_PAGE_SIZE;
|
||||
requests.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool LLExperienceCache::isRequestPending(const LLUUID& public_key)
|
||||
{
|
||||
bool isPending = false;
|
||||
const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
|
||||
|
||||
PendingQueue_t::const_iterator it = mPendingQueue.find(public_key);
|
||||
|
||||
if(it != mPendingQueue.end())
|
||||
{
|
||||
F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;
|
||||
isPending = (it->second > expire_time);
|
||||
}
|
||||
|
||||
return isPending;
|
||||
}
|
||||
|
||||
void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t queryfn)
|
||||
{
|
||||
mCapability = queryfn;
|
||||
}
|
||||
|
||||
|
||||
void LLExperienceCache::idleCoro()
|
||||
{
|
||||
const F32 SECS_BETWEEN_REQUESTS = 0.5f;
|
||||
const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds
|
||||
|
||||
{
|
||||
static LLFrameTimer sRequestTimer;
|
||||
if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) return;
|
||||
|
||||
if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT))
|
||||
{
|
||||
eraseExpired();
|
||||
}
|
||||
|
||||
if (!mRequestQueue.empty())
|
||||
{
|
||||
requestExperiences();
|
||||
}
|
||||
}
|
||||
|
||||
// The coroutine system will likely be shut down by the time we get to this point
|
||||
// (or at least no further cycling will occur on it since the user has decided to quit.)
|
||||
}
|
||||
|
||||
void LLExperienceCache::erase(const LLUUID& key)
|
||||
{
|
||||
cache_t::iterator it = mCache.find(key);
|
||||
|
||||
if(it != mCache.end())
|
||||
{
|
||||
mCache.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void LLExperienceCache::eraseExpired()
|
||||
{
|
||||
F64 now = LLFrameTimer::getTotalSeconds();
|
||||
cache_t::iterator it = mCache.begin();
|
||||
while (it != mCache.end())
|
||||
{
|
||||
cache_t::iterator cur = it;
|
||||
LLSD& exp = cur->second;
|
||||
++it;
|
||||
|
||||
//LL_INFOS("ExperienceCache") << "Testing experience \"" << exp[NAME] << "\" with exp time " << exp[EXPIRES].asReal() << "(now = " << now << ")" << LL_ENDL;
|
||||
|
||||
if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now)
|
||||
{
|
||||
if(!exp.has(EXPERIENCE_ID))
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ;
|
||||
mCache.erase(cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLUUID id = exp[EXPERIENCE_ID].asUUID();
|
||||
LLUUID private_key = exp.has(LLExperienceCache::PRIVATE_KEY) ? exp[LLExperienceCache::PRIVATE_KEY].asUUID():LLUUID::null;
|
||||
if(private_key.notNull() || !exp.has("DoesNotExist"))
|
||||
{
|
||||
fetch(id, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ;
|
||||
mCache.erase(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/)
|
||||
{
|
||||
if(!key.isNull() && !isRequestPending(key) && (refresh || mCache.find(key)==mCache.end()))
|
||||
{
|
||||
LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL;
|
||||
|
||||
mRequestQueue.insert(key);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLExperienceCache::insert(const LLSD& experience_data)
|
||||
{
|
||||
if(experience_data.has(EXPERIENCE_ID))
|
||||
{
|
||||
processExperience(experience_data[EXPERIENCE_ID].asUUID(), experience_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << ": Ignoring cache insert of experience which is missing " << EXPERIENCE_ID << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
const LLSD& LLExperienceCache::get(const LLUUID& key)
|
||||
{
|
||||
static const LLSD empty;
|
||||
|
||||
if(key.isNull())
|
||||
return empty;
|
||||
cache_t::const_iterator it = mCache.find(key);
|
||||
|
||||
if (it != mCache.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
fetch(key);
|
||||
|
||||
return empty;
|
||||
}
|
||||
|
||||
void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::ExperienceGetFn_t slot)
|
||||
{
|
||||
if(key.isNull())
|
||||
return;
|
||||
|
||||
cache_t::const_iterator it = mCache.find(key);
|
||||
if (it != mCache.end())
|
||||
{
|
||||
// ...name already exists in cache, fire callback now
|
||||
callback_signal_t signal;
|
||||
signal.connect(slot);
|
||||
|
||||
signal(it->second);
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(key);
|
||||
|
||||
signal_ptr signal = boost::make_shared<callback_signal_t>();
|
||||
|
||||
std::pair<signal_map_t::iterator, bool> result = mSignalMap.insert(signal_map_t::value_type(key, signal));
|
||||
if (!result.second)
|
||||
signal = (*result.first).second;
|
||||
signal->connect(slot);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void LLExperienceCache::fetchAssociatedExperience(const LLUUID& objectId, const LLUUID& itemId, std::string url, ExperienceGetFn_t fn)
|
||||
{
|
||||
if (mCapability == nullptr)
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (url.empty())
|
||||
{
|
||||
url = mCapability("GetMetadata");
|
||||
|
||||
if (url.empty())
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "No Metadata capability." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LLSD fields;
|
||||
fields.append("experience");
|
||||
LLSD data;
|
||||
data["object-id"] = objectId;
|
||||
data["item-id"] = itemId;
|
||||
data["fields"] = fields;
|
||||
|
||||
LLHTTPClient::post(url, data, new LLCoroResponder(
|
||||
boost::bind(&LLExperienceCache::fetchAssociatedExperienceCoro, this, _1, fn)));
|
||||
}
|
||||
|
||||
void LLExperienceCache::fetchAssociatedExperienceCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn)
|
||||
{
|
||||
LLSD result = responder.getContent();
|
||||
auto status = responder.getStatus();
|
||||
|
||||
if (!responder.isGoodStatus(status) || !result.has("experience"))
|
||||
{
|
||||
LLSD failure;
|
||||
if (!status)
|
||||
{
|
||||
failure["error"] = status;
|
||||
failure["message"] = responder.getReason();
|
||||
}
|
||||
else
|
||||
{
|
||||
failure["error"] = -1;
|
||||
failure["message"] = "no experience";
|
||||
}
|
||||
if (fn != nullptr)
|
||||
fn(failure);
|
||||
return;
|
||||
}
|
||||
|
||||
LLUUID expId = result["experience"].asUUID();
|
||||
get(expId, fn);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void LLExperienceCache::findExperienceByName(const std::string text, int page, ExperienceGetFn_t fn)
|
||||
{
|
||||
if (mCapability == nullptr)
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream url;
|
||||
|
||||
url << mCapability("FindExperienceByName") << "?page=" << page << "&page_size=" << SEARCH_PAGE_SIZE << "&query=" << LLURI::escape(text);
|
||||
|
||||
LLHTTPClient::get(url.str(), new LLCoroResponder(
|
||||
boost::bind(&LLExperienceCache::findExperienceByNameCoro, this, _1, fn)));
|
||||
}
|
||||
|
||||
void LLExperienceCache::findExperienceByNameCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn)
|
||||
{
|
||||
LLSD result = responder.getContent();
|
||||
|
||||
if (!responder.isGoodStatus(responder.getStatus()))
|
||||
{
|
||||
fn(LLSD());
|
||||
return;
|
||||
}
|
||||
|
||||
const LLSD& experiences = result["experience_keys"];
|
||||
for (const auto& it : experiences.array())
|
||||
{
|
||||
insert(it);
|
||||
}
|
||||
|
||||
fn(result);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void LLExperienceCache::getGroupExperiences(const LLUUID &groupId, ExperienceGetFn_t fn)
|
||||
{
|
||||
if (mCapability == nullptr)
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// search for experiences owned by the current group
|
||||
std::string url = mCapability("GroupExperiences");
|
||||
if (url.empty())
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "No Group Experiences capability" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
url += "?" + groupId.asString();
|
||||
|
||||
LLHTTPClient::get(url, new LLCoroResponder(
|
||||
boost::bind(&LLExperienceCache::getGroupExperiencesCoro, this, _1, fn)));
|
||||
}
|
||||
|
||||
void LLExperienceCache::getGroupExperiencesCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn)
|
||||
{
|
||||
LLSD result = responder.getContent();
|
||||
|
||||
if (!responder.isGoodStatus(responder.getStatus()))
|
||||
{
|
||||
fn(LLSD());
|
||||
return;
|
||||
}
|
||||
|
||||
const LLSD& experienceIds = result["experience_ids"];
|
||||
fn(experienceIds);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void LLExperienceCache::getRegionExperiences(CapabilityQuery_t regioncaps, ExperienceGetFn_t fn)
|
||||
{
|
||||
regionExperiences(regioncaps, LLSD(), false, fn);
|
||||
}
|
||||
|
||||
void LLExperienceCache::setRegionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, ExperienceGetFn_t fn)
|
||||
{
|
||||
regionExperiences(regioncaps, experiences, true, fn);
|
||||
}
|
||||
|
||||
void LLExperienceCache::regionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, bool update, ExperienceGetFn_t fn)
|
||||
{
|
||||
// search for experiences owned by the current group
|
||||
std::string url = regioncaps("RegionExperiences");
|
||||
if (url.empty())
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
auto httpRequest = new LLCoroResponder(
|
||||
boost::bind(&LLExperienceCache::regionExperiencesCoro, this, _1, fn));
|
||||
|
||||
LLSD result;
|
||||
if (update)
|
||||
LLHTTPClient::post(url, experiences, httpRequest);
|
||||
else
|
||||
LLHTTPClient::get(url, httpRequest);
|
||||
}
|
||||
|
||||
void LLExperienceCache::regionExperiencesCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn)
|
||||
{
|
||||
LLSD result = responder.getContent();
|
||||
|
||||
if (!responder.isGoodStatus(responder.getStatus()))
|
||||
{
|
||||
// fn(LLSD());
|
||||
return;
|
||||
}
|
||||
|
||||
fn(result);
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void LLExperienceCache::getExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn)
|
||||
{
|
||||
if (mCapability == nullptr)
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = mCapability("ExperiencePreferences") + "?" + experienceId.asString();
|
||||
|
||||
LLHTTPClient::get(url, new LLCoroResponder(
|
||||
boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, fn)));
|
||||
}
|
||||
|
||||
void LLExperienceCache::setExperiencePermission(const LLUUID &experienceId, const std::string &permission, ExperienceGetFn_t fn)
|
||||
{
|
||||
if (mCapability == nullptr)
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = mCapability("ExperiencePreferences");
|
||||
if (url.empty())
|
||||
return;
|
||||
LLSD permData;
|
||||
LLSD data;
|
||||
permData["permission"] = permission;
|
||||
data[experienceId.asString()] = permData;
|
||||
|
||||
LLHTTPClient::put(url, data, new LLCoroResponder(
|
||||
boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, fn)));
|
||||
}
|
||||
|
||||
void LLExperienceCache::forgetExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn)
|
||||
{
|
||||
if (mCapability == nullptr)
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = mCapability("ExperiencePreferences") + "?" + experienceId.asString();
|
||||
LLHTTPClient::del(url, new LLCoroResponder(
|
||||
boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, fn)));
|
||||
}
|
||||
|
||||
void LLExperienceCache::experiencePermissionCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn)
|
||||
{
|
||||
// search for experiences owned by the current group
|
||||
|
||||
LLSD result = responder.getContent();
|
||||
|
||||
if (responder.isGoodStatus(responder.getStatus()))
|
||||
{
|
||||
fn(result);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void LLExperienceCache::getExperienceAdmin(const LLUUID &experienceId, ExperienceGetFn_t fn)
|
||||
{
|
||||
if (mCapability == nullptr)
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = mCapability("IsExperienceAdmin");
|
||||
if (url.empty())
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
url += "?experience_id=" + experienceId.asString();
|
||||
|
||||
LLHTTPClient::get(url, new LLCoroResponder(
|
||||
boost::bind(fn, boost::bind(&LLCoroResponder::getContent, _1))));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void LLExperienceCache::updateExperience(LLSD updateData, ExperienceGetFn_t fn)
|
||||
{
|
||||
if (mCapability == nullptr)
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = mCapability("UpdateExperience");
|
||||
if (url.empty())
|
||||
{
|
||||
LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
updateData.erase(LLExperienceCache::QUOTA);
|
||||
updateData.erase(LLExperienceCache::EXPIRES);
|
||||
updateData.erase(LLExperienceCache::AGENT_ID);
|
||||
|
||||
LLHTTPClient::post(url, updateData, new LLCoroResponder(
|
||||
boost::bind(fn, boost::bind(&LLCoroResponder::getContent, _1))));
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void LLExperienceCacheImpl::mapKeys(const LLSD& legacyKeys)
|
||||
{
|
||||
for (const auto& exp : legacyKeys.array())
|
||||
{
|
||||
if (exp.has(LLExperienceCacheImpl::EXPERIENCE_ID) && exp.has(LLExperienceCacheImpl::PRIVATE_KEY))
|
||||
{
|
||||
LLExperienceCacheImpl::privateToPublicKeyMap[exp[LLExperienceCacheImpl::PRIVATE_KEY].asUUID()] =
|
||||
exp[LLExperienceCacheImpl::EXPERIENCE_ID].asUUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return time to retry a request that generated an error, based on
|
||||
// error type and headers. Return value is seconds-since-epoch.
|
||||
F64 LLExperienceCacheImpl::getErrorRetryDeltaTime(S32 status, const AIHTTPReceivedHeaders& headers)
|
||||
{
|
||||
// Retry-After takes priority
|
||||
std::string retry_afters;
|
||||
if (headers.getFirstValue("retry-after", retry_afters))
|
||||
{
|
||||
LLSD retry_after(retry_afters);
|
||||
// We only support the delta-seconds type
|
||||
S32 delta_seconds = retry_after.asInteger();
|
||||
if (delta_seconds > 0)
|
||||
{
|
||||
// ...valid delta-seconds
|
||||
return F64(delta_seconds);
|
||||
}
|
||||
}
|
||||
|
||||
// If no Retry-After, look for Cache-Control max-age
|
||||
// Allow the header to override the default
|
||||
std::string cache_control;
|
||||
if (headers.getFirstValue("cache-control", cache_control))
|
||||
{
|
||||
S32 max_age = 0;
|
||||
if (LLExperienceCacheImpl::maxAgeFromCacheControl(cache_control, &max_age))
|
||||
{
|
||||
LL_WARNS("ExperienceCache")
|
||||
<< "got EXPIRES from headers, max_age " << max_age
|
||||
<< LL_ENDL;
|
||||
return (F64)max_age;
|
||||
}
|
||||
}
|
||||
|
||||
// No information in header, make a guess
|
||||
if (status == 503)
|
||||
{
|
||||
// ...service unavailable, retry soon
|
||||
const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min
|
||||
return SERVICE_UNAVAILABLE_DELAY;
|
||||
}
|
||||
else if (status == 499)
|
||||
{
|
||||
// ...we were probably too busy, retry quickly
|
||||
const F64 BUSY_DELAY = 10.0; // 10 seconds
|
||||
return BUSY_DELAY;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...other unexpected error
|
||||
const F64 DEFAULT_DELAY = 3600.0; // 1 hour
|
||||
return DEFAULT_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLExperienceCacheImpl::maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age)
|
||||
{
|
||||
// Split the string on "," to get a list of directives
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer directives(cache_control, COMMA_SEPARATOR);
|
||||
|
||||
tokenizer::iterator token_it = directives.begin();
|
||||
for ( ; token_it != directives.end(); ++token_it)
|
||||
{
|
||||
// Tokens may have leading or trailing whitespace
|
||||
std::string token = *token_it;
|
||||
LLStringUtil::trim(token);
|
||||
|
||||
if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
|
||||
{
|
||||
// ...this token starts with max-age, so let's chop it up by "="
|
||||
tokenizer subtokens(token, EQUALS_SEPARATOR);
|
||||
tokenizer::iterator subtoken_it = subtokens.begin();
|
||||
|
||||
// Must have a token
|
||||
if (subtoken_it == subtokens.end()) return false;
|
||||
std::string subtoken = *subtoken_it;
|
||||
|
||||
// Must exactly equal "max-age"
|
||||
LLStringUtil::trim(subtoken);
|
||||
if (subtoken != MAX_AGE) return false;
|
||||
|
||||
// Must have another token
|
||||
++subtoken_it;
|
||||
if (subtoken_it == subtokens.end()) return false;
|
||||
subtoken = *subtoken_it;
|
||||
|
||||
// Must be a valid integer
|
||||
// *NOTE: atoi() returns 0 for invalid values, so we have to
|
||||
// check the string first.
|
||||
// *TODO: Do servers ever send "0000" for zero? We don't handle it
|
||||
LLStringUtil::trim(subtoken);
|
||||
if (subtoken == "0")
|
||||
{
|
||||
*max_age = 0;
|
||||
return true;
|
||||
}
|
||||
S32 val = atoi( subtoken.c_str() );
|
||||
if (val > 0 && val < S32_MAX)
|
||||
{
|
||||
*max_age = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
181
indra/llmessage/llexperiencecache.h
Normal file
181
indra/llmessage/llexperiencecache.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* @file llexperiencecache.h
|
||||
* @brief Caches information relating to experience keys
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef LL_LLEXPERIENCECACHE_H
|
||||
#define LL_LLEXPERIENCECACHE_H
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llframetimer.h"
|
||||
#include "llsd.h"
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
struct LLCoroResponder;
|
||||
class LLSD;
|
||||
class LLUUID;
|
||||
|
||||
|
||||
class LLExperienceCache final : public LLSingleton < LLExperienceCache >
|
||||
{
|
||||
friend class LLSingleton<LLExperienceCache>;
|
||||
LLExperienceCache();
|
||||
|
||||
public:
|
||||
typedef std::function<std::string(const std::string &)> CapabilityQuery_t;
|
||||
typedef std::function<void(const LLSD &)> ExperienceGetFn_t;
|
||||
|
||||
void idleCoro();
|
||||
void setCapabilityQuery(CapabilityQuery_t queryfn);
|
||||
void cleanup();
|
||||
|
||||
//-------------------------------------------
|
||||
// Cache methods
|
||||
void erase(const LLUUID& key);
|
||||
bool fetch(const LLUUID& key, bool refresh = false);
|
||||
void insert(const LLSD& experience_data);
|
||||
const LLSD& get(const LLUUID& key);
|
||||
void get(const LLUUID& key, ExperienceGetFn_t slot); // If name information is in cache, callback will be called immediately.
|
||||
|
||||
bool isRequestPending(const LLUUID& public_key);
|
||||
|
||||
//-------------------------------------------
|
||||
void fetchAssociatedExperience(const LLUUID& objectId, const LLUUID& itemId, ExperienceGetFn_t fn) { fetchAssociatedExperience(objectId, itemId, LLStringUtil::null, fn); }
|
||||
void fetchAssociatedExperience(const LLUUID& objectId, const LLUUID& itemId, std::string url, ExperienceGetFn_t fn);
|
||||
void findExperienceByName(const std::string text, int page, ExperienceGetFn_t fn);
|
||||
void getGroupExperiences(const LLUUID &groupId, ExperienceGetFn_t fn);
|
||||
|
||||
// the Get/Set Region Experiences take a CapabilityQuery to get the capability since
|
||||
// the region being queried may not be the region that the agent is standing on.
|
||||
void getRegionExperiences(CapabilityQuery_t regioncaps, ExperienceGetFn_t fn);
|
||||
void setRegionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, ExperienceGetFn_t fn);
|
||||
|
||||
void getExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn);
|
||||
void setExperiencePermission(const LLUUID &experienceId, const std::string &permission, ExperienceGetFn_t fn);
|
||||
void forgetExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn);
|
||||
|
||||
void getExperienceAdmin(const LLUUID &experienceId, ExperienceGetFn_t fn);
|
||||
|
||||
void updateExperience(LLSD updateData, ExperienceGetFn_t fn);
|
||||
//-------------------------------------------
|
||||
static const std::string NAME; // "name"
|
||||
static const std::string EXPERIENCE_ID; // "public_id"
|
||||
static const std::string AGENT_ID; // "agent_id"
|
||||
static const std::string GROUP_ID; // "group_id"
|
||||
static const std::string PROPERTIES; // "properties"
|
||||
static const std::string EXPIRES; // "expiration"
|
||||
static const std::string DESCRIPTION; // "description"
|
||||
static const std::string QUOTA; // "quota"
|
||||
static const std::string MATURITY; // "maturity"
|
||||
static const std::string METADATA; // "extended_metadata"
|
||||
static const std::string SLURL; // "slurl"
|
||||
|
||||
static const std::string MISSING; // "DoesNotExist"
|
||||
|
||||
// should be in sync with experience-api/experiences/models.py
|
||||
static const int PROPERTY_INVALID; // 1 << 0
|
||||
static const int PROPERTY_PRIVILEGED; // 1 << 3
|
||||
static const int PROPERTY_GRID; // 1 << 4
|
||||
static const int PROPERTY_PRIVATE; // 1 << 5
|
||||
static const int PROPERTY_DISABLED; // 1 << 6
|
||||
static const int PROPERTY_SUSPENDED; // 1 << 7
|
||||
|
||||
private:
|
||||
virtual ~LLExperienceCache();
|
||||
|
||||
void initSingleton() override;
|
||||
|
||||
// Callback types for get()
|
||||
typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t;
|
||||
typedef boost::shared_ptr<callback_signal_t> signal_ptr;
|
||||
// May have multiple callbacks for a single ID, which are
|
||||
// represented as multiple slots bound to the signal.
|
||||
// Avoid copying signals via pointers.
|
||||
typedef std::map<LLUUID, signal_ptr> signal_map_t;
|
||||
typedef std::map<LLUUID, LLSD> cache_t;
|
||||
|
||||
typedef uuid_set_t RequestQueue_t;
|
||||
typedef std::map<LLUUID, F64> PendingQueue_t;
|
||||
|
||||
//--------------------------------------------
|
||||
static const std::string PRIVATE_KEY; // "private_id"
|
||||
|
||||
// default values
|
||||
static const F64 DEFAULT_EXPIRATION; // 600.0
|
||||
static const S32 DEFAULT_QUOTA; // 128 this is megabytes
|
||||
static const int SEARCH_PAGE_SIZE;
|
||||
|
||||
//--------------------------------------------
|
||||
void processExperience(const LLUUID& public_key, const LLSD& experience);
|
||||
|
||||
//--------------------------------------------
|
||||
cache_t mCache;
|
||||
signal_map_t mSignalMap;
|
||||
RequestQueue_t mRequestQueue;
|
||||
PendingQueue_t mPendingQueue;
|
||||
|
||||
LLFrameTimer mEraseExpiredTimer; // Periodically clean out expired entries from the cache
|
||||
CapabilityQuery_t mCapability;
|
||||
std::string mCacheFileName;
|
||||
bool mShutdown;
|
||||
|
||||
void eraseExpired();
|
||||
void requestExperiencesCoro(const LLCoroResponder& responder, RequestQueue_t);
|
||||
void requestExperiences();
|
||||
|
||||
void fetchAssociatedExperienceCoro(const LLCoroResponder& responder, ExperienceGetFn_t);
|
||||
void findExperienceByNameCoro(const LLCoroResponder& responder, ExperienceGetFn_t);
|
||||
void getGroupExperiencesCoro(const LLCoroResponder& responder, ExperienceGetFn_t);
|
||||
void regionExperiences(CapabilityQuery_t regioncaps, const LLSD& experiences, bool update, ExperienceGetFn_t fn);
|
||||
void regionExperiencesCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn);
|
||||
void experiencePermissionCoro(const LLCoroResponder& responder, ExperienceGetFn_t fn);
|
||||
|
||||
void bootstrap(const LLSD& legacyKeys, int initialExpiration);
|
||||
void exportFile(std::ostream& ostr) const;
|
||||
void importFile(std::istream& istr);
|
||||
|
||||
//
|
||||
const cache_t& getCached();
|
||||
|
||||
// maps an experience private key to the experience id
|
||||
LLUUID getExperienceId(const LLUUID& private_key, bool null_if_not_found=false);
|
||||
|
||||
//=====================================================================
|
||||
inline friend std::ostream &operator << (std::ostream &os, const LLExperienceCache &cache)
|
||||
{
|
||||
cache.exportFile(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
inline friend std::istream &operator >> (std::istream &is, LLExperienceCache &cache)
|
||||
{
|
||||
cache.importFile(is);
|
||||
return is;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LL_LLEXPERIENCECACHE_H
|
||||
@@ -168,19 +168,20 @@ const U32 ESTATE_ACCESS_ALL = ESTATE_ACCESS_ALLOWED_AGENTS
|
||||
| ESTATE_ACCESS_BANNED_AGENTS
|
||||
| ESTATE_ACCESS_MANAGERS;
|
||||
|
||||
// for EstateOwnerRequest, estateaccessdelta message
|
||||
const U32 ESTATE_ACCESS_APPLY_TO_ALL_ESTATES = 1 << 0;
|
||||
const U32 ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES = 1 << 1;
|
||||
// for EstateOwnerRequest, estateaccessdelta, estateexperiencedelta messages
|
||||
const U32 ESTATE_ACCESS_APPLY_TO_ALL_ESTATES = 1U << 0;
|
||||
const U32 ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES = 1U << 1;
|
||||
|
||||
const U32 ESTATE_ACCESS_ALLOWED_AGENT_ADD = 1 << 2;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_AGENT_REMOVE = 1 << 3;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_GROUP_ADD = 1 << 4;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_GROUP_REMOVE = 1 << 5;
|
||||
const U32 ESTATE_ACCESS_BANNED_AGENT_ADD = 1 << 6;
|
||||
const U32 ESTATE_ACCESS_BANNED_AGENT_REMOVE = 1 << 7;
|
||||
const U32 ESTATE_ACCESS_MANAGER_ADD = 1 << 8;
|
||||
const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1 << 9;
|
||||
const U32 ESTATE_ACCESS_NO_REPLY = 1 << 10;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_AGENT_ADD = 1U << 2;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_AGENT_REMOVE = 1U << 3;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_GROUP_ADD = 1U << 4;
|
||||
const U32 ESTATE_ACCESS_ALLOWED_GROUP_REMOVE = 1U << 5;
|
||||
const U32 ESTATE_ACCESS_BANNED_AGENT_ADD = 1U << 6;
|
||||
const U32 ESTATE_ACCESS_BANNED_AGENT_REMOVE = 1U << 7;
|
||||
const U32 ESTATE_ACCESS_MANAGER_ADD = 1U << 8;
|
||||
const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1U << 9;
|
||||
const U32 ESTATE_ACCESS_NO_REPLY = 1U << 10;
|
||||
const U32 ESTATE_ACCESS_FAILED_BAN_ESTATE_MANAGER = 1U << 11;
|
||||
|
||||
const S32 ESTATE_MAX_MANAGERS = 15;
|
||||
const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access, banned
|
||||
@@ -191,6 +192,26 @@ const U32 SWD_OTHERS_LAND_ONLY = (1 << 0);
|
||||
const U32 SWD_ALWAYS_RETURN_OBJECTS = (1 << 1);
|
||||
const U32 SWD_SCRIPTED_ONLY = (1 << 2);
|
||||
|
||||
// Controls experience key validity in the estate
|
||||
const U32 EXPERIENCE_KEY_TYPE_NONE = 0;
|
||||
const U32 EXPERIENCE_KEY_TYPE_BLOCKED = 1;
|
||||
const U32 EXPERIENCE_KEY_TYPE_ALLOWED = 2;
|
||||
const U32 EXPERIENCE_KEY_TYPE_TRUSTED = 3;
|
||||
|
||||
const U32 EXPERIENCE_KEY_TYPE_FIRST = EXPERIENCE_KEY_TYPE_BLOCKED;
|
||||
const U32 EXPERIENCE_KEY_TYPE_LAST = EXPERIENCE_KEY_TYPE_TRUSTED;
|
||||
|
||||
//
|
||||
const U32 ESTATE_EXPERIENCE_TRUSTED_ADD = 1U << 2;
|
||||
const U32 ESTATE_EXPERIENCE_TRUSTED_REMOVE = 1U << 3;
|
||||
const U32 ESTATE_EXPERIENCE_ALLOWED_ADD = 1U << 4;
|
||||
const U32 ESTATE_EXPERIENCE_ALLOWED_REMOVE = 1U << 5;
|
||||
const U32 ESTATE_EXPERIENCE_BLOCKED_ADD = 1U << 6;
|
||||
const U32 ESTATE_EXPERIENCE_BLOCKED_REMOVE = 1U << 7;
|
||||
|
||||
const S32 ESTATE_MAX_EXPERIENCE_IDS = 8;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1393,6 +1393,8 @@ char const* const _PREHASH_AppearanceVersion = LLMessageStringTable::getInstance
|
||||
char const* const _PREHASH_CofVersion = LLMessageStringTable::getInstance()->getString("CofVersion");
|
||||
char const* const _PREHASH_AppearanceHover = LLMessageStringTable::getInstance()->getString("AppearanceHover");
|
||||
char const* const _PREHASH_HoverHeight = LLMessageStringTable::getInstance()->getString("HoverHeight");
|
||||
char const* const _PREHASH_Experience = LLMessageStringTable::getInstance()->getString("Experience");
|
||||
char const* const _PREHASH_ExperienceID = LLMessageStringTable::getInstance()->getString("ExperienceID");
|
||||
|
||||
// <FS:CR> Aurora Sim
|
||||
char const* const _PREHASH_RegionSizeX = LLMessageStringTable::getInstance()->getString("RegionSizeX");
|
||||
|
||||
@@ -1393,6 +1393,8 @@ extern char const* const _PREHASH_AppearanceVersion;
|
||||
extern char const* const _PREHASH_CofVersion;
|
||||
extern char const* const _PREHASH_AppearanceHover;
|
||||
extern char const* const _PREHASH_HoverHeight;
|
||||
extern char const* const _PREHASH_Experience;
|
||||
extern char const* const _PREHASH_ExperienceID;
|
||||
|
||||
// <FS:CR> Aurora Sim
|
||||
extern char const* const _PREHASH_RegionSizeX;
|
||||
|
||||
@@ -623,12 +623,14 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie
|
||||
return result;
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
|
||||
void LLPluginClassMedia::scrollEvent(int x, int y, int clicks_x, int clicks_y, MASK modifiers)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
|
||||
|
||||
message.setValueS32("x", x);
|
||||
message.setValueS32("y", y);
|
||||
message.setValueS32("clicks_x", clicks_x);
|
||||
message.setValueS32("clicks_y", clicks_y);
|
||||
message.setValue("modifiers", translateModifiers(modifiers));
|
||||
|
||||
sendMessage(message);
|
||||
@@ -711,9 +713,9 @@ void LLPluginClassMedia::sendPickFileResponse(const std::vector<std::string> fil
|
||||
}
|
||||
|
||||
LLSD file_list = LLSD::emptyArray();
|
||||
for (std::vector<std::string>::const_iterator in_iter = files.begin(); in_iter != files.end(); ++in_iter)
|
||||
for (const auto& file : files)
|
||||
{
|
||||
file_list.append(LLSD::String(*in_iter));
|
||||
file_list.append(LLSD::String(file));
|
||||
}
|
||||
message.setValueLLSD("file_list", file_list);
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
void setAutoScale(bool auto_scale);
|
||||
void setZoomFactor(F64 zoom_factor) { mZoomFactor = zoom_factor; }
|
||||
|
||||
void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
|
||||
void setBackgroundColor(const LLColor4& color) { mBackgroundColor = color; };
|
||||
|
||||
void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
|
||||
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
|
||||
bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
|
||||
|
||||
void scrollEvent(int x, int y, MASK modifiers);
|
||||
void scrollEvent(int x, int y, int clicks_x, int clicks_y, MASK modifiers);
|
||||
|
||||
// enable/disable media plugin debugging messages and info spam
|
||||
void enableMediaPluginDebugging( bool enable );
|
||||
|
||||
@@ -37,6 +37,7 @@ set(llui_SOURCE_FILES
|
||||
lldraghandle.cpp
|
||||
lleditmenuhandler.cpp
|
||||
llfiltereditor.cpp
|
||||
llflatlistview.cpp
|
||||
llfloater.cpp
|
||||
llflyoutbutton.cpp
|
||||
llfocusmgr.cpp
|
||||
@@ -116,6 +117,7 @@ set(llui_HEADER_FILES
|
||||
lldraghandle.h
|
||||
lleditmenuhandler.h
|
||||
llfiltereditor.h
|
||||
llflatlistview.h
|
||||
llfloater.h
|
||||
llflyoutbutton.h
|
||||
llfocusmgr.h
|
||||
|
||||
@@ -26,12 +26,14 @@ const std::array<const std::string, LFIDBearer::COUNT> LFIDBearer::sMenuStrings
|
||||
{
|
||||
"menu_avs_list.xml" // 0
|
||||
, "menu_groups_list.xml" // 1
|
||||
, "menu_objects_list.xml" // 2 // Singu TODO
|
||||
, "menu_objects_list.xml" // 2
|
||||
, "menu_experiences.xml" // 3
|
||||
};
|
||||
std::array<LLMenuGL*, LFIDBearer::COUNT> LFIDBearer::sMenus {};
|
||||
|
||||
const LFIDBearer* LFIDBearer::sActive = nullptr;
|
||||
LFIDBearer::Type LFIDBearer::sActiveType = LFIDBearer::AVATAR;
|
||||
uuid_vec_t LFIDBearer::sActiveIDs {};
|
||||
|
||||
void LFIDBearer::buildMenus()
|
||||
{
|
||||
|
||||
@@ -34,25 +34,26 @@ struct LFIDBearer
|
||||
AVATAR = 0,
|
||||
GROUP,
|
||||
OBJECT,
|
||||
EXPERIENCE,
|
||||
COUNT
|
||||
};
|
||||
|
||||
virtual ~LFIDBearer() { if (sActive == this) sActive = nullptr; }
|
||||
virtual LLUUID getStringUUIDSelectedItem() const = 0;
|
||||
virtual uuid_vec_t getSelectedIDs() const { return { getStringUUIDSelectedItem() }; }
|
||||
virtual S32 getNumSelected() const { return getStringUUIDSelectedItem().notNull(); }
|
||||
virtual Type getSelectedType() const { return AVATAR; }
|
||||
|
||||
template<typename T> static const T* getActive() { return static_cast<const T*>(sActive); }
|
||||
static LLUUID getActiveSelectedID() { return sActive->getStringUUIDSelectedItem(); }
|
||||
static uuid_vec_t getActiveSelectedIDs() { return sActive->getSelectedIDs(); }
|
||||
static S32 getActiveNumSelected() { return sActive->getNumSelected(); }
|
||||
static const LLUUID& getActiveSelectedID() { return sActiveIDs.empty() ? LLUUID::null : sActiveIDs[0]; }
|
||||
static const uuid_vec_t& getActiveSelectedIDs() { return sActiveIDs; }
|
||||
static size_t getActiveNumSelected() { return sActiveIDs.size(); }
|
||||
static const Type& getActiveType() { return sActiveType; }
|
||||
|
||||
void setActive() const
|
||||
{
|
||||
sActive = this;
|
||||
sActiveType = getSelectedType();
|
||||
sActiveIDs = getSelectedIDs();
|
||||
//sActiveIDs or even some kinda hybrid map, if Type is MULTIPLE fill the vals? and remove a buncha virtual functions?
|
||||
}
|
||||
|
||||
@@ -68,4 +69,5 @@ protected:
|
||||
private:
|
||||
static const LFIDBearer* sActive;
|
||||
static Type sActiveType;
|
||||
static uuid_vec_t sActiveIDs;
|
||||
};
|
||||
|
||||
@@ -446,8 +446,7 @@ void LLComboBox::setLabel(const LLStringExplicit& name)
|
||||
|
||||
if (!mAllowTextEntry)
|
||||
{
|
||||
mButton->setLabelUnselected(name);
|
||||
mButton->setLabelSelected(name);
|
||||
mButton->setLabel(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,9 +464,7 @@ void LLComboBox::updateLabel()
|
||||
// the combo button label.
|
||||
if (!mAllowTextEntry)
|
||||
{
|
||||
std::string label = getSelectedItemLabel();
|
||||
mButton->setLabelUnselected(label);
|
||||
mButton->setLabelSelected(label);
|
||||
mButton->setLabel(getSelectedItemLabel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,13 +510,16 @@ void LLComboBox::onFocusLost()
|
||||
|
||||
void LLComboBox::setButtonVisible(BOOL visible)
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
|
||||
|
||||
mButton->setVisible(visible);
|
||||
if (mTextEntry)
|
||||
{
|
||||
LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
|
||||
if (visible)
|
||||
{
|
||||
text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
|
||||
S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
|
||||
}
|
||||
//mTextEntry->setRect(text_entry_rect);
|
||||
mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
|
||||
@@ -558,18 +558,21 @@ S32 LLComboBox::getCurrentIndex() const
|
||||
|
||||
void LLComboBox::updateLayout()
|
||||
{
|
||||
static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
|
||||
LLRect rect = getLocalRect();
|
||||
if (mAllowTextEntry)
|
||||
{
|
||||
S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton");
|
||||
mButton->setRect(LLRect( getRect().getWidth() - llmax(8,mArrowImage->getWidth()) - 2 * shadow_size,
|
||||
S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
|
||||
S32 shadow_size = drop_shadow_button;
|
||||
mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size,
|
||||
rect.mTop, rect.mRight, rect.mBottom));
|
||||
mButton->setTabStop(FALSE);
|
||||
mButton->setHAlign(LLFontGL::HCENTER);
|
||||
|
||||
if (!mTextEntry)
|
||||
{
|
||||
LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
|
||||
text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * shadow_size;
|
||||
text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
|
||||
// clear label on button
|
||||
std::string cur_label = mButton->getLabelSelected();
|
||||
mTextEntry = new LLLineEditor(std::string("combo_text_entry"),
|
||||
@@ -718,6 +721,7 @@ void LLComboBox::showList()
|
||||
mList->setVisible(TRUE);
|
||||
|
||||
setUseBoundingRect(TRUE);
|
||||
// updateBoundingRect();
|
||||
}
|
||||
|
||||
void LLComboBox::hideList()
|
||||
@@ -744,6 +748,7 @@ void LLComboBox::hideList()
|
||||
{
|
||||
gFocusMgr.setTopCtrl(NULL);
|
||||
}
|
||||
// updateBoundingRect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1029,9 +1034,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor)
|
||||
|
||||
void LLComboBox::updateSelection()
|
||||
{
|
||||
if(mSuppressAutoComplete) {
|
||||
return;
|
||||
}
|
||||
if(mSuppressAutoComplete) return;
|
||||
|
||||
LLWString left_wstring = mTextEntry->getWText().substr(0, mTextEntry->getCursor());
|
||||
// user-entered portion of string, based on assumption that any selected
|
||||
@@ -1242,3 +1245,25 @@ BOOL LLComboBox::selectItemRange( S32 first, S32 last )
|
||||
return mList->selectItemRange(first, last);
|
||||
}
|
||||
|
||||
|
||||
/* Singu Note: This isn't very necessary for now, let's not bother.
|
||||
static LLRegisterWidget<LLIconsComboBox> register_icons_combo_box("icons_combo_box");
|
||||
|
||||
LLIconsComboBox::Params::Params()
|
||||
: icon_column("icon_column", ICON_COLUMN),
|
||||
label_column("label_column", LABEL_COLUMN)
|
||||
{}
|
||||
|
||||
LLIconsComboBox::LLIconsComboBox(const LLIconsComboBox::Params& p)
|
||||
: LLComboBox(p),
|
||||
mIconColumnIndex(p.icon_column),
|
||||
mLabelColumnIndex(p.label_column)
|
||||
{}
|
||||
|
||||
const std::string LLIconsComboBox::getSelectedItemLabel(S32 column) const
|
||||
{
|
||||
mButton->setImageOverlay(LLComboBox::getSelectedItemLabel(mIconColumnIndex), mButton->getImageOverlayHAlign());
|
||||
|
||||
return LLComboBox::getSelectedItemLabel(mLabelColumnIndex);
|
||||
}
|
||||
*/
|
||||
|
||||
1464
indra/llui/llflatlistview.cpp
Normal file
1464
indra/llui/llflatlistview.cpp
Normal file
File diff suppressed because it is too large
Load Diff
540
indra/llui/llflatlistview.h
Normal file
540
indra/llui/llflatlistview.h
Normal file
@@ -0,0 +1,540 @@
|
||||
/**
|
||||
* @file llflatlistview.h
|
||||
* @brief LLFlatListView base class and extension to support messages for several cases of an empty list.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLFLATLISTVIEW_H
|
||||
#define LL_LLFLATLISTVIEW_H
|
||||
|
||||
#include "llpanel.h"
|
||||
#include "llscrollcontainer.h"
|
||||
#include "lltextbox.h"
|
||||
|
||||
|
||||
/**
|
||||
* LLFlatListView represents a flat list ui control that operates on items in a form of LLPanel's.
|
||||
* LLSD can be associated with each added item, it can keep data from an item in digested form.
|
||||
* Associated LLSD's can be of any type (singular, a map etc.).
|
||||
* Items (LLPanel's subclasses) can be of different height.
|
||||
* The list is LLPanel created in itself and grows in height while new items are added.
|
||||
*
|
||||
* The control can manage selection of its items when the flag "allow_select" is set. Also ability to select
|
||||
* multiple items (by using CTRL) is enabled through setting the flag "multi_select" - if selection is not allowed that flag
|
||||
* is ignored. The option "keep_one_selected" forces at least one item to be selected at any time (only for mouse events on items)
|
||||
* since any item of the list was selected.
|
||||
*
|
||||
* Examples of using this control are presented in Picks panel (My Profile and Profile View), where this control is used to
|
||||
* manage the list of pick items.
|
||||
*
|
||||
* ASSUMPTIONS AND STUFF
|
||||
* - NULL pointers and undefined LLSD's are not accepted by any method of this class unless specified otherwise
|
||||
* - Order of returned selected items are not guaranteed
|
||||
* - The control assumes that all items being added are unique.
|
||||
*/
|
||||
class LLFlatListView : public LLScrollContainer, public LLEditMenuHandler
|
||||
{
|
||||
LOG_CLASS(LLFlatListView);
|
||||
public:
|
||||
|
||||
/**
|
||||
* Abstract comparator for comparing flat list items in a form of LLPanel
|
||||
*/
|
||||
class ItemComparator
|
||||
{
|
||||
public:
|
||||
ItemComparator() {};
|
||||
virtual ~ItemComparator() {};
|
||||
|
||||
/** Returns true if item1 < item2, false otherwise */
|
||||
virtual bool compare(const LLPanel* item1, const LLPanel* item2) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents reverse comparator which acts as a decorator for a comparator that need to be reversed
|
||||
*/
|
||||
class ItemReverseComparator : public ItemComparator
|
||||
{
|
||||
public:
|
||||
ItemReverseComparator(const ItemComparator& comparator) : mComparator(comparator) {};
|
||||
virtual ~ItemReverseComparator() {};
|
||||
|
||||
bool compare(const LLPanel* item1, const LLPanel* item2) const override
|
||||
{
|
||||
return mComparator.compare(item2, item1);
|
||||
}
|
||||
|
||||
private:
|
||||
const ItemComparator& mComparator;
|
||||
};
|
||||
|
||||
|
||||
struct Params : public LLInitParam::Block<Params, LLScrollContainer::Params>
|
||||
{
|
||||
/** turning on/off selection support */
|
||||
Optional<bool> allow_select;
|
||||
|
||||
/** turning on/off multiple selection (works while clicking and holding CTRL)*/
|
||||
Optional<bool> multi_select;
|
||||
|
||||
/** don't allow to deselect all selected items (for mouse events on items only) */
|
||||
Optional<bool> keep_one_selected;
|
||||
|
||||
/** try to keep selection visible after reshape */
|
||||
Optional<bool> keep_selection_visible_on_reshape;
|
||||
|
||||
/** padding between items */
|
||||
Optional<U32> item_pad;
|
||||
|
||||
/** textbox with info message when list is empty*/
|
||||
Optional<LLTextBox::Params> no_items_text;
|
||||
|
||||
Params();
|
||||
};
|
||||
|
||||
// disable traversal when finding widget to hand focus off to
|
||||
/*virtual*/ BOOL canFocusChildren() const override { return FALSE; }
|
||||
|
||||
/**
|
||||
* Connects callback to signal called when Return key is pressed.
|
||||
*/
|
||||
boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); }
|
||||
|
||||
/** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */
|
||||
void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override;
|
||||
|
||||
/** Returns full rect of child panel */
|
||||
const LLRect& getItemsRect() const;
|
||||
|
||||
LLRect getRequiredRect() override { return getItemsRect(); }
|
||||
|
||||
/** Returns distance between items */
|
||||
const S32 getItemsPad() const { return mItemPad; }
|
||||
|
||||
/**
|
||||
* Adds and item and LLSD value associated with it to the list at specified position
|
||||
* @return true if the item was added, false otherwise
|
||||
*/
|
||||
virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM, bool rearrange = true);
|
||||
|
||||
/**
|
||||
* Insert item_to_add along with associated value to the list right after the after_item.
|
||||
* @return true if the item was successfully added, false otherwise
|
||||
*/
|
||||
virtual bool insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value = LLUUID::null);
|
||||
|
||||
/**
|
||||
* Remove specified item
|
||||
* @return true if the item was removed, false otherwise
|
||||
*/
|
||||
virtual bool removeItem(LLPanel* item, bool rearrange = true);
|
||||
|
||||
/**
|
||||
* Remove an item specified by value
|
||||
* @return true if the item was removed, false otherwise
|
||||
*/
|
||||
virtual bool removeItemByValue(const LLSD& value, bool rearrange = true);
|
||||
|
||||
/**
|
||||
* Remove an item specified by uuid
|
||||
* @return true if the item was removed, false otherwise
|
||||
*/
|
||||
virtual bool removeItemByUUID(const LLUUID& uuid, bool rearrange = true);
|
||||
|
||||
/**
|
||||
* Get an item by value
|
||||
* @return the item as LLPanel if associated with value, NULL otherwise
|
||||
*/
|
||||
virtual LLPanel* getItemByValue(const LLSD& value) const;
|
||||
|
||||
/**
|
||||
* Check for item by value in list
|
||||
* @return bool whether item exists by value or not
|
||||
*/
|
||||
virtual bool valueExists(const LLSD& value) const;
|
||||
|
||||
template<class T>
|
||||
T* getTypedItemByValue(const LLSD& value) const
|
||||
{
|
||||
return dynamic_cast<T*>(getItemByValue(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Select or deselect specified item based on select
|
||||
* @return true if succeed, false otherwise
|
||||
*/
|
||||
virtual bool selectItem(LLPanel* item, bool select = true);
|
||||
|
||||
/**
|
||||
* Select or deselect an item by associated value based on select
|
||||
* @return true if succeed, false otherwise
|
||||
*/
|
||||
virtual bool selectItemByValue(const LLSD& value, bool select = true);
|
||||
|
||||
/**
|
||||
* Select or deselect an item by associated uuid based on select
|
||||
* @return true if succeed, false otherwise
|
||||
*/
|
||||
virtual bool selectItemByUUID(const LLUUID& uuid, bool select = true);
|
||||
|
||||
/**
|
||||
* Get all panels stored in the list.
|
||||
*/
|
||||
virtual void getItems(std::vector<LLPanel*>& items) const;
|
||||
|
||||
/**
|
||||
* Get all items values.
|
||||
*/
|
||||
virtual void getValues(std::vector<LLSD>& values) const;
|
||||
|
||||
/**
|
||||
* Get LLSD associated with the first selected item
|
||||
*/
|
||||
virtual LLSD getSelectedValue() const;
|
||||
|
||||
/**
|
||||
* Get LLSD's associated with selected items.
|
||||
* @param selected_values std::vector being populated with LLSD associated with selected items
|
||||
*/
|
||||
virtual void getSelectedValues(std::vector<LLSD>& selected_values) const;
|
||||
|
||||
|
||||
/**
|
||||
* Get LLUUID associated with selected item
|
||||
* @return LLUUID if such was associated with selected item
|
||||
*/
|
||||
virtual LLUUID getSelectedUUID() const;
|
||||
|
||||
/**
|
||||
* Get LLUUIDs associated with selected items
|
||||
* @param selected_uuids An std::vector being populated with LLUUIDs associated with selected items
|
||||
*/
|
||||
virtual void getSelectedUUIDs(uuid_vec_t& selected_uuids) const;
|
||||
|
||||
/** Get the top selected item */
|
||||
virtual LLPanel* getSelectedItem() const;
|
||||
|
||||
/**
|
||||
* Get selected items
|
||||
* @param selected_items An std::vector being populated with pointers to selected items
|
||||
*/
|
||||
virtual void getSelectedItems(std::vector<LLPanel*>& selected_items) const;
|
||||
|
||||
|
||||
/**
|
||||
* Resets selection of items.
|
||||
*
|
||||
* It calls onCommit callback if setCommitOnSelectionChange(bool b) was called with "true"
|
||||
* argument for current Flat List.
|
||||
* @param no_commit_on_deselection - if true onCommit callback will not be called
|
||||
*/
|
||||
virtual void resetSelection(bool no_commit_on_deselection = false);
|
||||
|
||||
/**
|
||||
* Sets comment text which will be shown in the list is it is empty.
|
||||
*
|
||||
* Textbox to hold passed text is created while this method is called at the first time.
|
||||
*
|
||||
* @param comment_text - string to be shown as a comment.
|
||||
*/
|
||||
void setNoItemsCommentText( const std::string& comment_text);
|
||||
|
||||
/** Turn on/off multiple selection support */
|
||||
void setAllowMultipleSelection(bool allow) { mMultipleSelection = allow; }
|
||||
|
||||
/** Turn on/off selection support */
|
||||
void setAllowSelection(bool can_select) { mAllowSelection = can_select; }
|
||||
|
||||
/** Sets flag whether onCommit should be fired if selection was changed */
|
||||
// FIXME: this should really be a separate signal, since "Commit" implies explicit user action, and selection changes can happen more indirectly.
|
||||
void setCommitOnSelectionChange(bool b) { mCommitOnSelectionChange = b; }
|
||||
|
||||
/** Get number of selected items in the list */
|
||||
U32 numSelected() const {return mSelectedItemPairs.size(); }
|
||||
|
||||
/** Get number of (visible) items in the list */
|
||||
U32 size(const bool only_visible_items = true) const;
|
||||
|
||||
/** Removes all items from the list */
|
||||
void clear() override;
|
||||
|
||||
/**
|
||||
* Removes all items that can be detached from the list but doesn't destroy
|
||||
* them, caller responsible to manage items after they are detached.
|
||||
* Detachable item should accept "detach" action via notify() method,
|
||||
* where it disconnect all callbacks, does other valuable routines and
|
||||
* return 1.
|
||||
*/
|
||||
void detachItems(std::vector<LLPanel*>& detached_items);
|
||||
|
||||
/**
|
||||
* Set comparator to use for future sorts.
|
||||
*
|
||||
* This class does NOT manage lifetime of the comparator
|
||||
* but assumes that the comparator is always alive.
|
||||
*/
|
||||
void setComparator(const ItemComparator* comp) { mItemComparator = comp; }
|
||||
void sort();
|
||||
|
||||
bool updateValue(const LLSD& old_value, const LLSD& new_value);
|
||||
|
||||
void scrollToShowFirstSelectedItem();
|
||||
|
||||
void selectFirstItem ();
|
||||
void selectLastItem ();
|
||||
|
||||
S32 notify(const LLSD& info) override;
|
||||
|
||||
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); // <singu> Old-style
|
||||
|
||||
virtual ~LLFlatListView();
|
||||
protected:
|
||||
|
||||
/** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
|
||||
typedef std::pair<LLPanel*, LLSD> item_pair_t;
|
||||
|
||||
typedef std::list<item_pair_t*> pairs_list_t;
|
||||
typedef pairs_list_t::iterator pairs_iterator_t;
|
||||
typedef pairs_list_t::const_iterator pairs_const_iterator_t;
|
||||
|
||||
/** An adapter for a ItemComparator */
|
||||
struct ComparatorAdaptor
|
||||
{
|
||||
ComparatorAdaptor(const ItemComparator& comparator) : mComparator(comparator) {};
|
||||
|
||||
bool operator()(const item_pair_t* item_pair1, const item_pair_t* item_pair2) const
|
||||
{
|
||||
return mComparator.compare(item_pair1->first, item_pair2->first);
|
||||
}
|
||||
|
||||
const ItemComparator& mComparator;
|
||||
};
|
||||
|
||||
|
||||
friend class LLUICtrlFactory;
|
||||
LLFlatListView(const std::string& name, const LLRect& rect, bool opaque, const LLColor4& color, const S32& item_pad, bool allow_select, bool multi_select, bool keep_one_selected, bool keep_selection_visible_on_reshape, const std::string& no_items_text);
|
||||
|
||||
/** Manage selection on mouse events */
|
||||
void onItemMouseClick(item_pair_t* item_pair, MASK mask);
|
||||
|
||||
void onItemRightMouseClick(item_pair_t* item_pair, MASK mask);
|
||||
|
||||
/**
|
||||
* Updates position of items.
|
||||
* It does not take into account invisible items.
|
||||
*/
|
||||
virtual void rearrangeItems();
|
||||
|
||||
virtual item_pair_t* getItemPair(LLPanel* item) const;
|
||||
|
||||
virtual item_pair_t* getItemPair(const LLSD& value) const;
|
||||
|
||||
virtual bool selectItemPair(item_pair_t* item_pair, bool select);
|
||||
|
||||
virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection);
|
||||
|
||||
BOOL canSelectAll() const override;
|
||||
void selectAll() override;
|
||||
|
||||
virtual bool isSelected(item_pair_t* item_pair) const;
|
||||
|
||||
virtual bool removeItemPair(item_pair_t* item_pair, bool rearrange);
|
||||
|
||||
bool addItemPairs(pairs_list_t panel_list, bool rearrange = true);
|
||||
|
||||
/**
|
||||
* Notify parent about changed size of internal controls with "size_changes" action
|
||||
*
|
||||
* Size includes Items Rect width and either Items Rect height or comment text height.
|
||||
* Comment text height is included if comment text is set and visible.
|
||||
* List border size is also included into notified size.
|
||||
*/
|
||||
void notifyParentItemsRectChanged();
|
||||
|
||||
BOOL handleKeyHere(KEY key, MASK mask) override;
|
||||
|
||||
BOOL postBuild() override;
|
||||
|
||||
void onFocusReceived() override;
|
||||
|
||||
void onFocusLost() override;
|
||||
|
||||
void draw() override;
|
||||
|
||||
LLRect getLastSelectedItemRect();
|
||||
|
||||
void ensureSelectedVisible();
|
||||
|
||||
private:
|
||||
|
||||
void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;}
|
||||
|
||||
void setNoItemsCommentVisible(bool visible) const;
|
||||
|
||||
protected:
|
||||
|
||||
/** Comparator to use when sorting the list. */
|
||||
const ItemComparator* mItemComparator;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
LLPanel* mItemsPanel;
|
||||
|
||||
S32 mItemsNoScrollWidth;
|
||||
|
||||
S32 mBorderThickness;
|
||||
|
||||
/** Items padding */
|
||||
S32 mItemPad;
|
||||
|
||||
/** Selection support flag */
|
||||
bool mAllowSelection;
|
||||
|
||||
/** Multiselection support flag, ignored if selection is not supported */
|
||||
bool mMultipleSelection;
|
||||
|
||||
/**
|
||||
* Flag specified whether onCommit be called if selection is changed in the list.
|
||||
*
|
||||
* Can be ignored in the resetSelection() method.
|
||||
* @see resetSelection()
|
||||
*/
|
||||
bool mCommitOnSelectionChange;
|
||||
|
||||
bool mKeepOneItemSelected;
|
||||
|
||||
bool mIsConsecutiveSelection;
|
||||
|
||||
bool mKeepSelectionVisibleOnReshape;
|
||||
|
||||
/** All pairs of the list */
|
||||
pairs_list_t mItemPairs;
|
||||
|
||||
/** Selected pairs for faster access */
|
||||
pairs_list_t mSelectedItemPairs;
|
||||
|
||||
/**
|
||||
* Rectangle contained previous size of items parent notified last time.
|
||||
* Is used to reduce amount of parentNotify() calls if size was not changed.
|
||||
*/
|
||||
LLRect mPrevNotifyParentRect;
|
||||
|
||||
LLTextBox* mNoItemsCommentTextbox;
|
||||
|
||||
LLViewBorder* mSelectedItemsBorder;
|
||||
|
||||
commit_signal_t mOnReturnSignal;
|
||||
};
|
||||
|
||||
/**
|
||||
* Extends LLFlatListView functionality to show different messages when there are no items in the
|
||||
* list depend on whether they are filtered or not.
|
||||
*
|
||||
* Class provides one message per case of empty list.
|
||||
* It also provides protected updateNoItemsMessage() method to be called each time when derived list
|
||||
* is changed to update base mNoItemsCommentTextbox value.
|
||||
*
|
||||
* It is implemented to avoid duplication of this functionality in concrete implementations of the
|
||||
* lists. It is intended to be used as a base class for lists which should support two different
|
||||
* messages for empty state. Can be improved to support more than two messages via state-to-message map.
|
||||
*/
|
||||
class LLFlatListViewEx : public LLFlatListView
|
||||
{
|
||||
public:
|
||||
LOG_CLASS(LLFlatListViewEx);
|
||||
|
||||
struct Params : public LLInitParam::Block<Params, LLFlatListView::Params>
|
||||
{
|
||||
/**
|
||||
* Contains a message for empty list when it does not contain any items at all.
|
||||
*/
|
||||
Optional<std::string> no_items_msg;
|
||||
|
||||
/**
|
||||
* Contains a message for empty list when its items are removed by filtering.
|
||||
*/
|
||||
Optional<std::string> no_filtered_items_msg;
|
||||
Params();
|
||||
};
|
||||
|
||||
// *WORKAROUND: two methods to overload appropriate Params due to localization issue:
|
||||
// no_items_msg & no_filtered_items_msg attributes are not defined as translatable in VLT. See EXT-5931
|
||||
void setNoItemsMsg(const std::string& msg) { mNoItemsMsg = msg; }
|
||||
void setNoFilteredItemsMsg(const std::string& msg) { mNoFilteredItemsMsg = msg; }
|
||||
|
||||
bool getForceShowingUnmatchedItems();
|
||||
|
||||
void setForceShowingUnmatchedItems(bool show);
|
||||
|
||||
/**
|
||||
* Sets up new filter string and filters the list.
|
||||
*/
|
||||
void setFilterSubString(const std::string& filter_str);
|
||||
std::string getFilterSubString() const { return mFilterSubString; }
|
||||
|
||||
/**
|
||||
* Filters the list, rearranges and notifies parent about shape changes.
|
||||
* Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration.
|
||||
*/
|
||||
void filterItems();
|
||||
|
||||
/**
|
||||
* Returns true if last call of filterItems() found at least one matching item
|
||||
*/
|
||||
bool hasMatchedItems();
|
||||
|
||||
protected:
|
||||
LLFlatListViewEx(const Params& p);
|
||||
|
||||
/**
|
||||
* Applies a message for empty list depend on passed argument.
|
||||
*
|
||||
* @param filter_string - if is not empty, message for filtered items will be set, otherwise for
|
||||
* completely empty list. Value of filter string will be passed as search_term in SLURL.
|
||||
*/
|
||||
void updateNoItemsMessage(const std::string& filter_string);
|
||||
|
||||
/**
|
||||
* Applies visibility acording to action and LLFlatListView settings.
|
||||
*
|
||||
* @param item - item we are changing
|
||||
* @param item - action - parameters to determin visibility from
|
||||
*/
|
||||
void updateItemVisibility(LLPanel* item, const LLSD &action);
|
||||
|
||||
private:
|
||||
std::string mNoFilteredItemsMsg;
|
||||
std::string mNoItemsMsg;
|
||||
std::string mFilterSubString;
|
||||
/**
|
||||
* Show list items that don't match current filter
|
||||
*/
|
||||
bool mForceShowingUnmatchedItems;
|
||||
/**
|
||||
* True if last call of filterItems() found at least one matching item
|
||||
*/
|
||||
bool mHasMatchedItems;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llscrollbar.cpp
|
||||
* @brief Scrollbar UI widget
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -46,6 +40,7 @@
|
||||
#include "llwindow.h"
|
||||
#include "llcontrol.h"
|
||||
#include "llrender.h"
|
||||
#include "lluictrlfactory.h"
|
||||
|
||||
LLScrollbar::LLScrollbar(
|
||||
const std::string& name, LLRect rect,
|
||||
@@ -402,7 +397,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
|
||||
}
|
||||
|
||||
getWindow()->setCursor(UI_CURSOR_ARROW);
|
||||
LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL;
|
||||
LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL;
|
||||
handled = TRUE;
|
||||
}
|
||||
else
|
||||
@@ -414,7 +409,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
|
||||
if( !handled )
|
||||
{
|
||||
getWindow()->setCursor(UI_CURSOR_ARROW);
|
||||
LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL;
|
||||
LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL;
|
||||
handled = TRUE;
|
||||
}
|
||||
|
||||
@@ -468,6 +463,13 @@ BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask)
|
||||
return handled;
|
||||
}
|
||||
|
||||
BOOL LLScrollbar::handleDoubleClick(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
// just treat a double click as a second click
|
||||
return handleMouseDown(x, y, mask);
|
||||
}
|
||||
|
||||
|
||||
void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent)
|
||||
{
|
||||
if (width == getRect().getWidth() && height == getRect().getHeight()) return;
|
||||
@@ -509,7 +511,6 @@ void LLScrollbar::draw()
|
||||
mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLSmoothInterpolation::getInterpolant(0.05f));
|
||||
}
|
||||
|
||||
|
||||
// Draw background and thumb.
|
||||
LLUIImage* rounded_rect_imagep = LLUI::getUIImage("Rounded_Square");
|
||||
|
||||
@@ -525,6 +526,9 @@ void LLScrollbar::draw()
|
||||
}
|
||||
else
|
||||
{
|
||||
// Thumb
|
||||
LLRect outline_rect = mThumbRect;
|
||||
outline_rect.stretch(2);
|
||||
// Background
|
||||
rounded_rect_imagep->drawSolid(mOrientation == HORIZONTAL ? SCROLLBAR_SIZE : 0,
|
||||
mOrientation == VERTICAL ? SCROLLBAR_SIZE : 0,
|
||||
@@ -532,9 +536,6 @@ void LLScrollbar::draw()
|
||||
mOrientation == VERTICAL ? getRect().getHeight() - 2 * SCROLLBAR_SIZE : getRect().getHeight(),
|
||||
mTrackColor);
|
||||
|
||||
// Thumb
|
||||
LLRect outline_rect = mThumbRect;
|
||||
outline_rect.stretch(2);
|
||||
|
||||
if (gFocusMgr.getKeyboardFocus() == this)
|
||||
{
|
||||
@@ -636,3 +637,8 @@ void LLScrollbar::onLineDownBtnPressed( const LLSD& data )
|
||||
{
|
||||
changeLine( mStepSize, TRUE );
|
||||
}
|
||||
|
||||
void LLScrollbar::setThickness(S32 thickness)
|
||||
{
|
||||
mThickness = thickness < 0 ? SCROLLBAR_SIZE : thickness;
|
||||
}
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llscrollbar.h
|
||||
* @brief Scrollbar UI widget
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -36,6 +30,7 @@
|
||||
#include "stdtypes.h"
|
||||
#include "lluictrl.h"
|
||||
#include "v4color.h"
|
||||
#include "llbutton.h"
|
||||
|
||||
//
|
||||
// Constants
|
||||
@@ -59,6 +54,7 @@ public:
|
||||
callback_t change_callback,
|
||||
S32 step_size = 1);
|
||||
|
||||
public:
|
||||
virtual ~LLScrollbar();
|
||||
|
||||
virtual void setValue(const LLSD& value);
|
||||
@@ -67,6 +63,7 @@ public:
|
||||
virtual BOOL handleKeyHere(KEY key, MASK mask);
|
||||
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
|
||||
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
|
||||
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
|
||||
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
|
||||
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
|
||||
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
|
||||
@@ -104,6 +101,9 @@ public:
|
||||
void onLineUpBtnPressed(const LLSD& data);
|
||||
void onLineDownBtnPressed(const LLSD& data);
|
||||
|
||||
S32 getThickness() const { return mThickness; }
|
||||
void setThickness(S32 thickness);
|
||||
|
||||
void setTrackColor( const LLColor4& color ) { mTrackColor = color; }
|
||||
void setThumbColor( const LLColor4& color ) { mThumbColor = color; }
|
||||
void setHighlightColor( const LLColor4& color ) { mHighlightColor = color; }
|
||||
@@ -145,5 +145,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // LL_SCROLLBAR_H
|
||||
|
||||
@@ -218,6 +218,15 @@ BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LLScrollContainer::handleUnicodeCharHere(llwchar uni_char)
|
||||
{
|
||||
if (mScrolledView && mScrolledView->handleUnicodeCharHere(uni_char))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
|
||||
{
|
||||
// Give event to my child views - they may have scroll bars
|
||||
@@ -262,7 +271,6 @@ BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,
|
||||
EAcceptance* accept,
|
||||
std::string& tooltip_msg)
|
||||
{
|
||||
//S32 scrollbar_size = SCROLLBAR_SIZE;
|
||||
// Scroll folder view if needed. Never accepts a drag or drop.
|
||||
*accept = ACCEPT_NO;
|
||||
BOOL handled = autoScroll(x, y);
|
||||
@@ -413,6 +421,7 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLScrollContainer::draw()
|
||||
{
|
||||
S32 scrollbar_size = SCROLLBAR_SIZE;
|
||||
@@ -525,7 +534,7 @@ bool LLScrollContainer::addChild(LLView* view, S32 tab_group)
|
||||
|
||||
void LLScrollContainer::updateScroll()
|
||||
{
|
||||
if (!mScrolledView)
|
||||
if (!getVisible() || !mScrolledView)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -626,6 +635,7 @@ LLRect LLScrollContainer::getVisibleContentRect()
|
||||
visible_rect.translate(-contents_rect.mLeft, -contents_rect.mBottom);
|
||||
return visible_rect;
|
||||
}
|
||||
|
||||
LLRect LLScrollContainer::getContentWindowRect()
|
||||
{
|
||||
updateScroll();
|
||||
@@ -729,6 +739,13 @@ S32 LLScrollContainer::getBorderWidth() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LLScrollContainer::setSize(S32 size)
|
||||
{
|
||||
mSize = size;
|
||||
mScrollbar[VERTICAL]->setThickness(size);
|
||||
mScrollbar[HORIZONTAL]->setThickness(size);
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLXMLNodePtr LLScrollContainer::getXML(bool save_children) const
|
||||
{
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llscrollcontainer.h
|
||||
* @brief LLScrollContainer class header file.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -78,7 +72,7 @@ public:
|
||||
void setReserveScrollCorner( BOOL b ) { mReserveScrollCorner = b; }
|
||||
LLRect getVisibleContentRect();
|
||||
LLRect getContentWindowRect();
|
||||
const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; }
|
||||
virtual const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; }
|
||||
void pageUp(S32 overlap = 0);
|
||||
void pageDown(S32 overlap = 0);
|
||||
void goToTop();
|
||||
@@ -90,6 +84,7 @@ public:
|
||||
// LLView functionality
|
||||
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
|
||||
virtual BOOL handleKeyHere(KEY key, MASK mask);
|
||||
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
|
||||
virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
|
||||
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
|
||||
EDragAndDropType cargo_type,
|
||||
@@ -105,9 +100,14 @@ public:
|
||||
virtual LLXMLNodePtr getXML(bool save_children) const;
|
||||
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
|
||||
|
||||
S32 getSize() const { return mSize; }
|
||||
void setSize(S32 thickness);
|
||||
|
||||
protected:
|
||||
LLView* mScrolledView;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
// internal scrollbar handlers
|
||||
virtual void scrollHorizontal( S32 new_pos );
|
||||
virtual void scrollVertical( S32 new_pos );
|
||||
@@ -117,7 +117,6 @@ public:
|
||||
private:
|
||||
|
||||
LLScrollbar* mScrollbar[SCROLLBAR_COUNT];
|
||||
LLView* mScrolledView;
|
||||
S32 mSize;
|
||||
BOOL mIsOpaque;
|
||||
LLColor4 mBackgroundColor;
|
||||
|
||||
@@ -2712,39 +2712,20 @@ void LLScrollListCtrl::setScrollListParameters(LLXMLNodePtr node)
|
||||
node->getAttributeString("menu_file", menu);
|
||||
if (!menu.empty()) setContextMenu(menu);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
BOOL multi_select = false;
|
||||
node->getAttributeBOOL("multi_select", multi_select);
|
||||
BOOL draw_border = true;
|
||||
node->getAttributeBOOL("draw_border", draw_border);
|
||||
BOOL draw_heading = false;
|
||||
node->getAttributeBOOL("draw_heading", draw_heading);
|
||||
S32 search_column = 0;
|
||||
node->getAttributeS32("search_column", search_column);
|
||||
S32 sort_column = -1;
|
||||
node->getAttributeS32("sort_column", sort_column);
|
||||
BOOL sort_ascending = true;
|
||||
node->getAttributeBOOL("sort_ascending", sort_ascending);
|
||||
|
||||
LLScrollListCtrl* scroll_list = new LLScrollListCtrl("scroll_list", rect, NULL, multi_select, draw_border, draw_heading);
|
||||
|
||||
if (node->hasAttribute("heading_height"))
|
||||
{
|
||||
S32 heading_height;
|
||||
node->getAttributeS32("heading_height", heading_height);
|
||||
scroll_list->setHeadingHeight(heading_height);
|
||||
setHeadingHeight(heading_height);
|
||||
}
|
||||
|
||||
scroll_list->setScrollListParameters(node);
|
||||
scroll_list->initFromXML(node, parent);
|
||||
scroll_list->setSearchColumn(search_column);
|
||||
S32 search_column = 0;
|
||||
node->getAttributeS32("search_column", search_column);
|
||||
BOOL sort_ascending = true;
|
||||
node->getAttributeBOOL("sort_ascending", sort_ascending);
|
||||
|
||||
setSearchColumn(search_column);
|
||||
|
||||
LLSD columns;
|
||||
S32 index = 0;
|
||||
@@ -2755,7 +2736,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
|
||||
{
|
||||
if (child->hasName("column") || child->hasName("columns") || child->hasName(kidcolumn) || child->hasName(kidcolumns))
|
||||
{
|
||||
std::string labelname("");
|
||||
std::string labelname;
|
||||
if (child->getAttributeString("label", labelname))
|
||||
columns[index]["label"] = labelname;
|
||||
else if (child->getAttributeString("image", labelname))
|
||||
@@ -2778,9 +2759,9 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
|
||||
}
|
||||
else // Singu Note: if a scroll list does not provide sort_direction, provide sort_ascending to sort as expected
|
||||
{
|
||||
bool sort_ascending = true;
|
||||
child->getAttribute_bool("sort_ascending", sort_ascending);
|
||||
columns[index]["sort_ascending"] = sort_ascending;
|
||||
bool col_sort_ascending = sort_ascending;
|
||||
child->getAttribute_bool("sort_ascending", col_sort_ascending);
|
||||
columns[index]["sort_ascending"] = col_sort_ascending;
|
||||
}
|
||||
|
||||
S32 columnwidth = -1;
|
||||
@@ -2806,12 +2787,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
|
||||
++index;
|
||||
}
|
||||
}
|
||||
scroll_list->setColumnHeadings(columns);
|
||||
|
||||
if (sort_column >= 0)
|
||||
{
|
||||
scroll_list->sortByColumnIndex(sort_column, sort_ascending);
|
||||
}
|
||||
setColumnHeadings(columns);
|
||||
|
||||
const std::string kidrow(nodename + "row");
|
||||
const std::string kidrows(nodename + "rows");
|
||||
@@ -2856,18 +2832,46 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
|
||||
}
|
||||
}
|
||||
if(explicit_column)
|
||||
scroll_list->addElement(row);
|
||||
addElement(row);
|
||||
else
|
||||
{
|
||||
LLSD entry_id;
|
||||
if(id_found)
|
||||
entry_id = id;
|
||||
scroll_list->addSimpleElement(value,ADD_BOTTOM,entry_id);
|
||||
addSimpleElement(value,ADD_BOTTOM,entry_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scroll_list->setCommentText(node->getTextContents());
|
||||
S32 sort_column = -1;
|
||||
node->getAttributeS32("sort_column", sort_column);
|
||||
if (sort_column >= 0)
|
||||
{
|
||||
sortByColumnIndex(sort_column, sort_ascending);
|
||||
}
|
||||
|
||||
setCommentText(node->getTextContents());
|
||||
}
|
||||
|
||||
// static
|
||||
LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
BOOL multi_select = false;
|
||||
node->getAttributeBOOL("multi_select", multi_select);
|
||||
|
||||
BOOL draw_border = true;
|
||||
node->getAttributeBOOL("draw_border", draw_border);
|
||||
|
||||
BOOL draw_heading = false;
|
||||
node->getAttributeBOOL("draw_heading", draw_heading);
|
||||
|
||||
LLScrollListCtrl* scroll_list = new LLScrollListCtrl("scroll_list", rect, NULL, multi_select, draw_border, draw_heading);
|
||||
|
||||
scroll_list->setScrollListParameters(node);
|
||||
scroll_list->initFromXML(node, parent);
|
||||
return scroll_list;
|
||||
}
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ public:
|
||||
virtual S32 getFirstSelectedIndex() const;
|
||||
std::vector<LLScrollListItem*> getAllSelected() const;
|
||||
uuid_vec_t getSelectedIDs() const override final; //Helper. Much like getAllSelected, but just provides a LLUUID vec
|
||||
S32 getNumSelected() const override final;
|
||||
S32 getNumSelected() const;
|
||||
LLScrollListItem* getLastSelectedItem() const { return mLastSelected; }
|
||||
|
||||
// iterate over all items
|
||||
|
||||
@@ -1896,3 +1896,8 @@ void LLTabContainer::commitHoveredButton(S32 x, S32 y)
|
||||
}
|
||||
}
|
||||
|
||||
S32 LLTabContainer::getTotalTabWidth() const
|
||||
{
|
||||
return mTotalTabWidth;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ public:
|
||||
S32 getIndexForPanel(LLPanel* panel);
|
||||
S32 getPanelIndexByTitle(const std::string& title);
|
||||
LLPanel* getPanelByName(const std::string& name);
|
||||
S32 getTotalTabWidth() const;
|
||||
void setCurrentTabName(const std::string& name);
|
||||
|
||||
void selectFirstTab();
|
||||
|
||||
@@ -387,6 +387,7 @@ static LFIDBearer::Type get_type_from_url(const std::string& url)
|
||||
auto type = url.substr(pos + 5, 5);
|
||||
return type == "agent" ? LFIDBearer::AVATAR
|
||||
: type == "group" ? LFIDBearer::GROUP
|
||||
: type == "experience" ? LFIDBearer::EXPERIENCE
|
||||
: LFIDBearer::OBJECT;
|
||||
}
|
||||
return LFIDBearer::NONE;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "lltrans.h"
|
||||
//#include "lluicolortable.h"
|
||||
#include "message.h"
|
||||
#include "llexperiencecache.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/format.hpp> // <alchemy/>
|
||||
@@ -1492,13 +1493,65 @@ std::string LLUrlEntryEmail::getUrl(const std::string &string) const
|
||||
return escapeUrl(string);
|
||||
}
|
||||
|
||||
LLUrlEntryExperienceProfile::LLUrlEntryExperienceProfile()
|
||||
{
|
||||
mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/\\w+\\S*",
|
||||
boost::regex::perl|boost::regex::icase);
|
||||
mIcon = "Generic_Experience";
|
||||
mMenuName = "menu_url_experience.xml";
|
||||
}
|
||||
|
||||
std::string LLUrlEntryExperienceProfile::getLabel(const std::string& url, const LLUrlLabelCallback& cb)
|
||||
{
|
||||
if (!gCacheName)
|
||||
{
|
||||
// probably at the login screen, use short string for layout
|
||||
return LLTrans::getString("LoadingData");
|
||||
}
|
||||
|
||||
std::string experience_id_string = getIDStringFromUrl(url);
|
||||
if (experience_id_string.empty())
|
||||
{
|
||||
// something went wrong, just give raw url
|
||||
return unescapeUrl(url);
|
||||
}
|
||||
|
||||
LLUUID experience_id(experience_id_string);
|
||||
if (experience_id.isNull())
|
||||
{
|
||||
return LLTrans::getString("ExperienceNameNull");
|
||||
}
|
||||
|
||||
const LLSD& experience_details = LLExperienceCache::instance().get(experience_id);
|
||||
if (!experience_details.isUndefined())
|
||||
{
|
||||
std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString();
|
||||
return experience_name_string.empty() ? LLTrans::getString("ExperienceNameUntitled") : experience_name_string;
|
||||
}
|
||||
|
||||
addObserver(experience_id_string, url, cb);
|
||||
LLExperienceCache::instance().get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1));
|
||||
return LLTrans::getString("LoadingData");
|
||||
|
||||
}
|
||||
|
||||
void LLUrlEntryExperienceProfile::onExperienceDetails(const LLSD& experience_details)
|
||||
{
|
||||
std::string name = experience_details[LLExperienceCache::NAME].asString();
|
||||
if(name.empty())
|
||||
{
|
||||
name = LLTrans::getString("ExperienceNameUntitled");
|
||||
}
|
||||
callObservers(experience_details[LLExperienceCache::EXPERIENCE_ID].asString(), name, LLStringUtil::null);
|
||||
}
|
||||
|
||||
// <alchemy>
|
||||
//
|
||||
// LLUrlEntryJIRA describes a Jira Issue Tracker entry
|
||||
//
|
||||
LLUrlEntryJira::LLUrlEntryJira()
|
||||
{
|
||||
mPattern = boost::regex("((?:ALCH|SV|BUG|CHOP|FIRE|MAINT|OPEN|SCR|STORM|SVC|VWR|WEB)-\\d+)",
|
||||
mPattern = boost::regex("(\\b(?:ALCH|SV|BUG|CHOP|FIRE|MAINT|OPEN|SCR|STORM|SVC|VWR|WEB)-\\d+)",
|
||||
boost::regex::perl);
|
||||
mMenuName = "menu_url_http.xml";
|
||||
mTooltip = LLTrans::getString("TooltipHttpUrl");
|
||||
@@ -1522,7 +1575,7 @@ std::string LLUrlEntryJira::getUrl(const std::string &url) const
|
||||
(url.find("SV") != std::string::npos) ?
|
||||
"https://singularityviewer.atlassian.net/browse/%1%" :
|
||||
(url.find("FIRE") != std::string::npos) ?
|
||||
"http://jira.phoenixviewer.com/browse/%1%" :
|
||||
"https://jira.firestormviewer.com/browse/%1%" :
|
||||
"http://jira.secondlife.com/browse/%1%"
|
||||
) % url).str();
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ protected:
|
||||
///
|
||||
/// LLUrlEntryHTTP Describes generic http: and https: Urls
|
||||
///
|
||||
class LLUrlEntryHTTP : public LLUrlEntryBase
|
||||
class LLUrlEntryHTTP final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryHTTP();
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
///
|
||||
/// LLUrlEntryHTTPLabel Describes generic http: and https: Urls with custom labels
|
||||
///
|
||||
class LLUrlEntryHTTPLabel : public LLUrlEntryBase
|
||||
class LLUrlEntryHTTPLabel final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryHTTPLabel();
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
///
|
||||
/// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
|
||||
///
|
||||
class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase
|
||||
class LLUrlEntryHTTPNoProtocol final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryHTTPNoProtocol();
|
||||
@@ -166,7 +166,7 @@ public:
|
||||
std::string getTooltip(const std::string &url) const override;
|
||||
};
|
||||
|
||||
class LLUrlEntryInvalidSLURL : public LLUrlEntryBase
|
||||
class LLUrlEntryInvalidSLURL final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryInvalidSLURL();
|
||||
@@ -180,7 +180,7 @@ public:
|
||||
///
|
||||
/// LLUrlEntrySLURL Describes http://slurl.com/... Urls
|
||||
///
|
||||
class LLUrlEntrySLURL : public LLUrlEntryBase
|
||||
class LLUrlEntrySLURL final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntrySLURL();
|
||||
@@ -205,7 +205,7 @@ public:
|
||||
///
|
||||
/// LLUrlEntrySeconlifeURLs Describes *secondlife.com and *lindenlab.com Urls
|
||||
///
|
||||
class LLUrlEntrySimpleSecondlifeURL : public LLUrlEntrySecondlifeURL
|
||||
class LLUrlEntrySimpleSecondlifeURL final : public LLUrlEntrySecondlifeURL
|
||||
{
|
||||
public:
|
||||
LLUrlEntrySimpleSecondlifeURL();
|
||||
@@ -281,7 +281,7 @@ private:
|
||||
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
|
||||
/// that displays the full display name + user name for an avatar
|
||||
/// such as "James Linden (james.linden)"
|
||||
class LLUrlEntryAgentCompleteName : public LLUrlEntryAgentName
|
||||
class LLUrlEntryAgentCompleteName final : public LLUrlEntryAgentName
|
||||
{
|
||||
public:
|
||||
LLUrlEntryAgentCompleteName();
|
||||
@@ -289,7 +289,7 @@ private:
|
||||
/*virtual*/ std::string getName(const LLAvatarName& avatar_name) override;
|
||||
};
|
||||
|
||||
class LLUrlEntryAgentLegacyName : public LLUrlEntryAgentName
|
||||
class LLUrlEntryAgentLegacyName final : public LLUrlEntryAgentName
|
||||
{
|
||||
public:
|
||||
LLUrlEntryAgentLegacyName();
|
||||
@@ -302,7 +302,7 @@ private:
|
||||
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
|
||||
/// that displays the just the display name for an avatar
|
||||
/// such as "James Linden"
|
||||
class LLUrlEntryAgentDisplayName : public LLUrlEntryAgentName
|
||||
class LLUrlEntryAgentDisplayName final : public LLUrlEntryAgentName
|
||||
{
|
||||
public:
|
||||
LLUrlEntryAgentDisplayName();
|
||||
@@ -315,7 +315,7 @@ private:
|
||||
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
|
||||
/// that displays the just the display name for an avatar
|
||||
/// such as "james.linden"
|
||||
class LLUrlEntryAgentUserName : public LLUrlEntryAgentName
|
||||
class LLUrlEntryAgentUserName final : public LLUrlEntryAgentName
|
||||
{
|
||||
public:
|
||||
LLUrlEntryAgentUserName();
|
||||
@@ -323,11 +323,25 @@ private:
|
||||
/*virtual*/ std::string getName(const LLAvatarName& avatar_name) override;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryExperienceProfile Describes a Second Life experience profile Url, e.g.,
|
||||
/// secondlife:///app/experience/0e346d8b-4433-4d66-a6b0-fd37083abc4c/profile
|
||||
/// that displays the experience name
|
||||
class LLUrlEntryExperienceProfile final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryExperienceProfile();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) override;
|
||||
private:
|
||||
void onExperienceDetails(const LLSD& experience_details);
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
|
||||
/// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
|
||||
///
|
||||
class LLUrlEntryGroup : public LLUrlEntryBase
|
||||
class LLUrlEntryGroup final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryGroup();
|
||||
@@ -342,7 +356,7 @@ private:
|
||||
/// LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
|
||||
/// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
|
||||
///
|
||||
class LLUrlEntryInventory : public LLUrlEntryBase
|
||||
class LLUrlEntryInventory final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryInventory();
|
||||
@@ -354,7 +368,7 @@ private:
|
||||
/// LLUrlEntryObjectIM Describes a Second Life inspector for the object Url, e.g.,
|
||||
/// secondlife:///app/objectim/7bcd7864-da6b-e43f-4486-91d28a28d95b?name=Object&owner=3de548e1-57be-cfea-2b78-83ae3ad95998&slurl=Danger!%20Danger!/200/200/30/&groupowned=1
|
||||
///
|
||||
class LLUrlEntryObjectIM : public LLUrlEntryBase
|
||||
class LLUrlEntryObjectIM final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryObjectIM();
|
||||
@@ -367,7 +381,7 @@ private:
|
||||
/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
|
||||
/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
|
||||
///
|
||||
class LLUrlEntryParcel : public LLUrlEntryBase
|
||||
class LLUrlEntryParcel final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
struct LLParcelData
|
||||
@@ -414,7 +428,7 @@ private:
|
||||
/// LLUrlEntryPlace Describes a Second Life location Url, e.g.,
|
||||
/// secondlife://Ahern/50/50/50
|
||||
///
|
||||
class LLUrlEntryPlace : public LLUrlEntryBase
|
||||
class LLUrlEntryPlace final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryPlace();
|
||||
@@ -426,7 +440,7 @@ public:
|
||||
/// LLUrlEntryRegion Describes a Second Life location Url, e.g.,
|
||||
/// secondlife:///app/region/Ahern/128/128/0
|
||||
///
|
||||
class LLUrlEntryRegion : public LLUrlEntryBase
|
||||
class LLUrlEntryRegion final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryRegion();
|
||||
@@ -438,7 +452,7 @@ public:
|
||||
/// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
|
||||
/// secondlife:///app/teleport/Ahern/50/50/50/
|
||||
///
|
||||
class LLUrlEntryTeleport : public LLUrlEntryBase
|
||||
class LLUrlEntryTeleport final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryTeleport();
|
||||
@@ -450,7 +464,7 @@ public:
|
||||
/// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts
|
||||
/// with secondlife:// (used as a catch-all for cases not matched above)
|
||||
///
|
||||
class LLUrlEntrySL : public LLUrlEntryBase
|
||||
class LLUrlEntrySL final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntrySL();
|
||||
@@ -461,7 +475,7 @@ public:
|
||||
/// LLUrlEntrySLLabel Describes a generic SLURL, e.g., a Url that starts
|
||||
/// with secondlife:// with the ability to specify a custom label.
|
||||
///
|
||||
class LLUrlEntrySLLabel : public LLUrlEntryBase
|
||||
class LLUrlEntrySLLabel final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntrySLLabel();
|
||||
@@ -475,7 +489,7 @@ public:
|
||||
/// LLUrlEntryWorldMap Describes a Second Life worldmap Url, e.g.,
|
||||
/// secondlife:///app/worldmap/Ahern/50/50/50
|
||||
///
|
||||
class LLUrlEntryWorldMap : public LLUrlEntryBase
|
||||
class LLUrlEntryWorldMap final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryWorldMap();
|
||||
@@ -486,7 +500,7 @@ public:
|
||||
///
|
||||
/// LLUrlEntryNoLink lets us turn of URL detection with <nolink>...</nolink> tags
|
||||
///
|
||||
class LLUrlEntryNoLink : public LLUrlEntryBase
|
||||
class LLUrlEntryNoLink final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryNoLink();
|
||||
@@ -498,7 +512,7 @@ public:
|
||||
///
|
||||
/// LLUrlEntryIcon describes an icon with <icon>...</icon> tags
|
||||
///
|
||||
class LLUrlEntryIcon : public LLUrlEntryBase
|
||||
class LLUrlEntryIcon final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryIcon();
|
||||
@@ -510,7 +524,7 @@ public:
|
||||
///
|
||||
/// LLUrlEntryEmail Describes a generic mailto: Urls
|
||||
///
|
||||
class LLUrlEntryEmail : public LLUrlEntryBase
|
||||
class LLUrlEntryEmail final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryEmail();
|
||||
@@ -522,7 +536,7 @@ public:
|
||||
///
|
||||
/// LLUrlEntryJira describes a Jira Issue
|
||||
///
|
||||
class LLUrlEntryJira : public LLUrlEntryBase
|
||||
class LLUrlEntryJira final : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryJira();
|
||||
|
||||
@@ -73,6 +73,7 @@ LLUrlRegistry::LLUrlRegistry()
|
||||
registerUrl(new LLUrlEntryObjectIM());
|
||||
registerUrl(new LLUrlEntryPlace());
|
||||
registerUrl(new LLUrlEntryInventory());
|
||||
registerUrl(new LLUrlEntryExperienceProfile());
|
||||
//LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern,
|
||||
//so it should be registered in the end of list
|
||||
registerUrl(new LLUrlEntrySL());
|
||||
|
||||
@@ -355,6 +355,10 @@ typedef enum e_lscript_state_event_type
|
||||
LSTT_REMOTE_DATA,
|
||||
LSTT_HTTP_RESPONSE,
|
||||
LSTT_HTTP_REQUEST,
|
||||
LSTT_EXPERMISSIONS,
|
||||
LSTT_TRANSACTION_RESULT,
|
||||
LSTT_PATH_UPDATE,
|
||||
LSTT_EXPERMISSIONS_DENIED,
|
||||
LSTT_EOF,
|
||||
|
||||
LSTT_STATE_BEGIN = LSTT_STATE_ENTRY,
|
||||
@@ -397,7 +401,11 @@ const U64 LSCRIPTStateBitField[LSTT_EOF] =
|
||||
0x0000000040000000, // LSTT_OBJECT_REZ
|
||||
0x0000000080000000, // LSTT_REMOTE_DATA
|
||||
0x0000000100000000LL, // LSTT_HTTP_RESPOSE
|
||||
0x0000000200000000LL // LSTT_HTTP_REQUEST
|
||||
0x0000000200000000LL, // LSTT_HTTP_REQUEST
|
||||
0x0000000400000000LL, // LSTT_EXPERMISSIONS
|
||||
0x0000000800000000LL, // LSTT_TRANSACTION_RESULT
|
||||
0x0000001000000000LL, // LSTT_PATH_UPDATE
|
||||
0x0000002000000000LL, //LSTT_EXPERMISSIONS_DENIED
|
||||
};
|
||||
|
||||
inline S32 get_event_handler_jump_position(U64 bit_field, LSCRIPTStateEventType type)
|
||||
@@ -511,6 +519,7 @@ typedef enum e_lscript_runtime_faults
|
||||
LSRF_TOO_MANY_LISTENS,
|
||||
LSRF_NESTING_LISTS,
|
||||
LSRF_CLI,
|
||||
LSRF_INVALID_STATE,
|
||||
LSRF_EOF
|
||||
} LSCRIPTRunTimeFaults;
|
||||
|
||||
@@ -551,10 +560,10 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =
|
||||
(0x1 << 10),// SCRIPT_PERMISSION_TRACK_CAMERA
|
||||
(0x1 << 11),// SCRIPT_PERMISSION_CONTROL_CAMERA
|
||||
(0x1 << 12),// SCRIPT_PERMISSION_TELEPORT
|
||||
(0x1 << 13),// SCRIPT_PERMISSION_EXPERIENCE,
|
||||
(0x1 << 14),// SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT,
|
||||
(0x1 << 15),// SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS,
|
||||
(0x1 << 16),// SCRIPT_PERMISSION_RETURN_OBJECTS,
|
||||
(0x1 << 13),// SCRIPT_PERMISSION_EXPERIENCE
|
||||
(0x1 << 14),// SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT
|
||||
(0x1 << 15),// SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS
|
||||
(0x1 << 16),// SCRIPT_PERMISSION_RETURN_OBJECTS
|
||||
};
|
||||
|
||||
// http_request string constants
|
||||
|
||||
@@ -685,6 +685,23 @@ void parse_string();
|
||||
"STATUS_INTERNAL_ERROR" { count(); yylval.ival = LSL_STATUS_INTERNAL_ERROR; return(INTEGER_CONSTANT); }
|
||||
"STATUS_WHITELIST_FAILED" { count(); yylval.ival = LSL_STATUS_WHITELIST_FAILED; return(INTEGER_CONSTANT); }
|
||||
|
||||
"XP_ERROR_NONE" { const char* sval= "no error"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_THROTTLED" { const char* sval= "exceeded throttle"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_EXPERIENCES_DISABLED" { const char* sval= "experiences are disabled"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_INVALID_PARAMETERS" { const char* sval= "invalid parameters"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_NOT_PERMITTED" { const char* sval= "operation not permitted"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_NO_EXPERIENCE" { const char* sval= "script not associated with an experience";yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_NOT_FOUND" { const char* sval= "not found"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_INVALID_EXPERIENCE" { const char* sval= "invalid experience"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_EXPERIENCE_DISABLED" { const char* sval= "experience is disabled"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_EXPERIENCE_SUSPENDED" { const char* sval= "experience is suspended"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_UNKNOWN_ERROR" { const char* sval= "unknown error"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_QUOTA_EXCEEDED" { const char* sval= "experience data quota exceeded"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_STORE_DISABLED" { const char* sval= "key-value store is disabled"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_STORAGE_EXCEPTION" { const char* sval= "key-value store communication failed"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_KEY_NOT_FOUND" { const char* sval= "key doesn't exist"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
"XP_ERROR_RETRY_UPDATE" { const char* sval= "retry update"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
|
||||
|
||||
"PROFILE_SCRIPT_NONE" { count(); yylval.ival = LSL_PROFILE_SCRIPT_NONE; return(INTEGER_CONSTANT); }
|
||||
"PROFILE_SCRIPT_MEMORY" { count(); yylval.ival = LSL_PROFILE_SCRIPT_MEMORY; return(INTEGER_CONSTANT); }
|
||||
|
||||
|
||||
@@ -179,6 +179,8 @@
|
||||
%type <event> money
|
||||
%type <event> email
|
||||
%type <event> run_time_permissions
|
||||
%type <event> experience_permissions
|
||||
%type <event> experience_permissions_denied
|
||||
%type <event> inventory
|
||||
%type <event> attach
|
||||
%type <event> dataserver
|
||||
@@ -787,6 +789,16 @@ event
|
||||
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
| experience_permissions compound_statement
|
||||
{
|
||||
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
| experience_permissions_denied compound_statement
|
||||
{
|
||||
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
| inventory compound_statement
|
||||
{
|
||||
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
|
||||
@@ -1039,6 +1051,28 @@ run_time_permissions
|
||||
}
|
||||
;
|
||||
|
||||
experience_permissions
|
||||
: EXPERIENCE_PERMISSIONS '(' LLKEY IDENTIFIER ')'
|
||||
{
|
||||
LLScriptIdentifier *id1 = new LLScriptIdentifier(gLine, gColumn, $4);
|
||||
gAllocationManager->addAllocation(id1);
|
||||
$$ = new LLScriptEXPEvent(gLine, gColumn, id1);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
;
|
||||
|
||||
experience_permissions_denied
|
||||
: EXPERIENCE_PERMISSIONS_DENIED '(' LLKEY IDENTIFIER ',' INTEGER IDENTIFIER ')'
|
||||
{
|
||||
LLScriptIdentifier *id1 = new LLScriptIdentifier(gLine, gColumn, $4);
|
||||
gAllocationManager->addAllocation(id1);
|
||||
LLScriptIdentifier *id2 = new LLScriptIdentifier(gLine, gColumn, $7);
|
||||
gAllocationManager->addAllocation(id2);
|
||||
$$ = new LLScriptEXPDeniedEvent(gLine, gColumn, id1, id2);
|
||||
gAllocationManager->addAllocation($$);
|
||||
}
|
||||
;
|
||||
|
||||
inventory
|
||||
: INVENTORY '(' INTEGER IDENTIFIER ')'
|
||||
{
|
||||
|
||||
@@ -3712,6 +3712,155 @@ S32 LLScriptNoSensorEvent::getSize()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LLScriptEXPEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
|
||||
{
|
||||
if (gErrorToText.getErrors())
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch(pass)
|
||||
{
|
||||
case LSCP_PRETTY_PRINT:
|
||||
case LSCP_EMIT_ASSEMBLY:
|
||||
fdotabs(fp, tabs, tabsize);
|
||||
fprintf(fp, "experience_permissions( key ");
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, " )\n");
|
||||
break;
|
||||
case LSCP_SCOPE_PASS1:
|
||||
checkForDuplicateHandler(fp, this, scope, "experience_permissions");
|
||||
if (scope->checkEntry(mName->mName))
|
||||
{
|
||||
gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY);
|
||||
}
|
||||
break;
|
||||
case LSCP_RESOURCE:
|
||||
{
|
||||
// we're just tryng to determine how much space the variable needs
|
||||
if (mName->mScopeEntry)
|
||||
{
|
||||
mName->mScopeEntry->mOffset = (S32)count;
|
||||
mName->mScopeEntry->mSize = 4;
|
||||
count += mName->mScopeEntry->mSize;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LSCP_EMIT_BYTE_CODE:
|
||||
{
|
||||
#ifdef LSL_INCLUDE_DEBUG_INFO
|
||||
char name[] = "experience_permissions";
|
||||
chunk->addBytes(name, strlen(name) + 1);
|
||||
chunk->addBytes(mName->mName, strlen(mName->mName) + 1);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case LSCP_EMIT_CIL_ASSEMBLY:
|
||||
fdotabs(fp, tabs, tabsize);
|
||||
fprintf(fp, "experience_permissions( valuetype [ScriptTypes]LindenLab.SecondLife.Key ");
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, " )");
|
||||
break;
|
||||
default:
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
S32 LLScriptEXPEvent::getSize()
|
||||
{
|
||||
// key = 4
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
void LLScriptEXPDeniedEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
|
||||
{
|
||||
if (gErrorToText.getErrors())
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch(pass)
|
||||
{
|
||||
case LSCP_PRETTY_PRINT:
|
||||
case LSCP_EMIT_ASSEMBLY:
|
||||
fdotabs(fp, tabs, tabsize);
|
||||
fprintf(fp, "experience_permissions_denied( key ");
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, ", integer ");
|
||||
mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, " )\n");
|
||||
break;
|
||||
case LSCP_SCOPE_PASS1:
|
||||
checkForDuplicateHandler(fp, this, scope, "experience_permissions_denied");
|
||||
if (scope->checkEntry(mName->mName))
|
||||
{
|
||||
gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY);
|
||||
}
|
||||
if (scope->checkEntry(mReason->mName))
|
||||
{
|
||||
gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
mReason->mScopeEntry = scope->addEntry(mReason->mName, LIT_VARIABLE, LST_INTEGER);
|
||||
}
|
||||
break;
|
||||
case LSCP_RESOURCE:
|
||||
{
|
||||
// we're just trying to determine how much space the variable needs
|
||||
if (mName->mScopeEntry)
|
||||
{
|
||||
mName->mScopeEntry->mOffset = (S32)count;
|
||||
mName->mScopeEntry->mSize = 4;
|
||||
count += mName->mScopeEntry->mSize;
|
||||
|
||||
mReason->mScopeEntry->mOffset = (S32)count;
|
||||
mReason->mScopeEntry->mSize = 4;
|
||||
count += mReason->mScopeEntry->mSize;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LSCP_EMIT_BYTE_CODE:
|
||||
{
|
||||
#ifdef LSL_INCLUDE_DEBUG_INFO
|
||||
char name[] = "experience_permissions_denied";
|
||||
chunk->addBytes(name, strlen(name) + 1);
|
||||
chunk->addBytes(mName->mName, strlen(mName->mName) + 1);
|
||||
chunk->addBytes(mReason->mName, strlen(mReason->mName) + 1);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case LSCP_EMIT_CIL_ASSEMBLY:
|
||||
fdotabs(fp, tabs, tabsize);
|
||||
fprintf(fp, "experience_permissions_denied( valuetype [ScriptTypes]LindenLab.SecondLife.Key ");
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, ", int32 ");
|
||||
mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
fprintf(fp, " )");
|
||||
break;
|
||||
default:
|
||||
mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
S32 LLScriptEXPDeniedEvent::getSize()
|
||||
{
|
||||
// key = 4 + integer
|
||||
return LSCRIPTDataSize[LST_KEY]+LSCRIPTDataSize[LST_INTEGER];
|
||||
}
|
||||
|
||||
void LLScriptAtTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
|
||||
{
|
||||
if (gErrorToText.getErrors())
|
||||
@@ -8577,6 +8726,7 @@ void LLScriptReturn::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa
|
||||
}
|
||||
}
|
||||
prunearg = TRUE;
|
||||
break;
|
||||
case LSCP_TYPE:
|
||||
// if there is a return expression, it must be promotable to the return type of the function
|
||||
if (mExpression)
|
||||
@@ -9775,7 +9925,13 @@ void LLScriptEventHandler::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom
|
||||
mScopeEntry->mFunctionArgs.addType(LST_STRING);
|
||||
mScopeEntry->mFunctionArgs.addType(LST_STRING);
|
||||
break;
|
||||
|
||||
case LSTT_EXPERMISSIONS:
|
||||
mScopeEntry->mFunctionArgs.addType(LST_KEY);
|
||||
break;
|
||||
case LSTT_EXPERMISSIONS_DENIED:
|
||||
mScopeEntry->mFunctionArgs.addType(LST_KEY);
|
||||
mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -633,6 +633,39 @@ public:
|
||||
LLScriptIdentifier *mRTPermissions;
|
||||
};
|
||||
|
||||
class LLScriptEXPEvent : public LLScriptEvent
|
||||
{
|
||||
public:
|
||||
LLScriptEXPEvent(S32 line, S32 col, LLScriptIdentifier *name)
|
||||
: LLScriptEvent(line, col, LSTT_EXPERMISSIONS), mName(name)
|
||||
{
|
||||
}
|
||||
|
||||
~LLScriptEXPEvent() {}
|
||||
|
||||
void recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata);
|
||||
S32 getSize();
|
||||
|
||||
LLScriptIdentifier *mName;
|
||||
};
|
||||
|
||||
class LLScriptEXPDeniedEvent : public LLScriptEvent
|
||||
{
|
||||
public:
|
||||
LLScriptEXPDeniedEvent(S32 line, S32 col, LLScriptIdentifier *name, LLScriptIdentifier *reason)
|
||||
: LLScriptEvent(line, col, LSTT_EXPERMISSIONS_DENIED), mName(name), mReason(reason)
|
||||
{
|
||||
}
|
||||
|
||||
~LLScriptEXPDeniedEvent() {}
|
||||
|
||||
void recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata);
|
||||
S32 getSize();
|
||||
|
||||
LLScriptIdentifier *mName;
|
||||
LLScriptIdentifier *mReason;
|
||||
};
|
||||
|
||||
class LLScriptChatEvent : public LLScriptEvent
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -181,6 +181,7 @@ set(viewer_SOURCE_FILES
|
||||
lleventinfo.cpp
|
||||
lleventnotifier.cpp
|
||||
lleventpoll.cpp
|
||||
llexperiencelog.cpp
|
||||
llexternaleditor.cpp
|
||||
llface.cpp
|
||||
llfasttimerview.cpp
|
||||
@@ -221,6 +222,9 @@ set(viewer_SOURCE_FILES
|
||||
llfloatereditui.cpp
|
||||
llfloaterenvsettings.cpp
|
||||
llfloaterevent.cpp
|
||||
llfloaterexperiencepicker.cpp
|
||||
llfloaterexperienceprofile.cpp
|
||||
llfloaterexperiences.cpp
|
||||
llfloaterexploreanimations.cpp
|
||||
llfloaterexploresounds.cpp
|
||||
llfloaterfeed.cpp
|
||||
@@ -320,6 +324,7 @@ set(viewer_SOURCE_FILES
|
||||
llhudtext.cpp
|
||||
llhudview.cpp
|
||||
llimpanel.cpp
|
||||
llimprocessing.cpp
|
||||
llimview.cpp
|
||||
llinventoryactions.cpp
|
||||
llinventorybridge.cpp
|
||||
@@ -382,11 +387,16 @@ set(viewer_SOURCE_FILES
|
||||
llpaneldisplay.cpp
|
||||
llpaneleditwearable.cpp
|
||||
llpanelevent.cpp
|
||||
llpanelexperiencelisteditor.cpp
|
||||
llpanelexperiencelog.cpp
|
||||
llpanelexperiencepicker.cpp
|
||||
llpanelexperiences.cpp
|
||||
llpanelface.cpp
|
||||
llpanelgeneral.cpp
|
||||
llpanelgroup.cpp
|
||||
llpanelgroupbulk.cpp
|
||||
llpanelgroupbulkban.cpp
|
||||
llpanelgroupexperiences.cpp
|
||||
llpanelgroupgeneral.cpp
|
||||
llpanelgroupinvite.cpp
|
||||
llpanelgrouplandmoney.cpp
|
||||
@@ -715,6 +725,7 @@ set(viewer_HEADER_FILES
|
||||
lleventinfo.h
|
||||
lleventnotifier.h
|
||||
lleventpoll.h
|
||||
llexperiencelog.h
|
||||
llexternaleditor.h
|
||||
llface.h
|
||||
llfasttimerview.h
|
||||
@@ -755,6 +766,9 @@ set(viewer_HEADER_FILES
|
||||
llfloatereditui.h
|
||||
llfloaterenvsettings.h
|
||||
llfloaterevent.h
|
||||
llfloaterexperiencepicker.h
|
||||
llfloaterexperienceprofile.h
|
||||
llfloaterexperiences.h
|
||||
llfloaterexploreanimations.h
|
||||
llfloaterexploresounds.h
|
||||
llfloaterfeed.h
|
||||
@@ -854,6 +868,7 @@ set(viewer_HEADER_FILES
|
||||
llhudtext.h
|
||||
llhudview.h
|
||||
llimpanel.h
|
||||
llimprocessing.h
|
||||
llimview.h
|
||||
llinventorybridge.h
|
||||
llinventoryclipboard.h
|
||||
@@ -916,12 +931,17 @@ set(viewer_HEADER_FILES
|
||||
llpaneldisplay.h
|
||||
llpaneleditwearable.h
|
||||
llpanelevent.h
|
||||
llpanelexperiencelisteditor.h
|
||||
llpanelexperiencelog.h
|
||||
llpanelexperiencepicker.h
|
||||
llpanelexperiences.h
|
||||
llpanelface.h
|
||||
llpanelgeneral.h
|
||||
llpanelgroup.h
|
||||
llpanelgroupbulk.h
|
||||
llpanelgroupbulkban.h
|
||||
llpanelgroupbulkimpl.h
|
||||
llpanelgroupexperiences.h
|
||||
llpanelgroupgeneral.h
|
||||
llpanelgroupinvite.h
|
||||
llpanelgrouplandmoney.h
|
||||
@@ -1433,6 +1453,7 @@ endif (OPENAL)
|
||||
|
||||
if (USE_FMODSTUDIO)
|
||||
list(APPEND LLSTARTUP_COMPILE_DEFINITIONS "LL_FMODSTUDIO=1")
|
||||
set_source_files_properties(llpanellogin.cpp PROPERTIES COMPILE_DEFINITIONS "LL_FMODSTUDIO=1")
|
||||
endif (USE_FMODSTUDIO)
|
||||
|
||||
set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_DEFINITIONS "${LLSTARTUP_COMPILE_DEFINITIONS}")
|
||||
|
||||
@@ -14,457 +14,300 @@
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "NACLantispam.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llagent.h"
|
||||
#include "llavataractions.h"
|
||||
#include "llcallbacklist.h" // For idle cleaning
|
||||
#include "llnotificationsutil.h"
|
||||
#include "lltrans.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
class NACLAntiSpamQueue
|
||||
{
|
||||
friend class NACLAntiSpamRegistry;
|
||||
public:
|
||||
const U32& getAmount() const { return mAmount; }
|
||||
const U32& getTime() const { return mTime; }
|
||||
protected:
|
||||
NACLAntiSpamQueue(const U32& time, const U32& amount) : mTime(time), mAmount(amount) {}
|
||||
void setAmount(const U32& amount) { mAmount = amount; }
|
||||
void setTime(const U32& time) { mTime = time; }
|
||||
void block(const LLUUID& source) { mEntries[source.asString()].block(); }
|
||||
void reset() { mEntries.clear(); }
|
||||
// Returns 0 if unblocked/disabled, 1 if check results in a new block, 2 if by an existing block
|
||||
U8 check(const LLUUID& source, const U32& multiplier)
|
||||
{
|
||||
const auto key = source.asString();
|
||||
auto it = mEntries.find(key);
|
||||
if (it != mEntries.end())
|
||||
return it->second.blockIfNeeded(mAmount * multiplier, mTime);
|
||||
mEntries[key]; // Default construct an Entry
|
||||
return 0U;
|
||||
}
|
||||
void idle()
|
||||
{
|
||||
// Clean out old unblocked entries
|
||||
const auto time_limit = mTime + 1; // One second after time has gone up, the next offense would reset anyway
|
||||
for (auto it = mEntries.begin(); it != mEntries.end();)
|
||||
{
|
||||
const auto& entry = it->second;
|
||||
if (entry.getBlocked() || entry.withinBlockTime(time_limit))
|
||||
++it;
|
||||
else it = mEntries.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
class Entry
|
||||
{
|
||||
friend class NACLAntiSpamQueue;
|
||||
protected:
|
||||
void reset() { updateTime(); mAmount = 1; mBlocked = false; }
|
||||
const U32& getAmount() const { return mAmount; }
|
||||
const std::time_t& getTime() const { return mTime; }
|
||||
void updateTime() { mTime = time(nullptr); }
|
||||
void block() { mBlocked = true; }
|
||||
bool withinBlockTime(const U32& time_limit) const { return (time(nullptr) - mTime) <= time_limit; }
|
||||
U8 blockIfNeeded(const U32& amount, const U32& time_limit)
|
||||
{
|
||||
if (mBlocked) return 2U; // Already blocked
|
||||
if (withinBlockTime(time_limit))
|
||||
{
|
||||
if (++mAmount > amount)
|
||||
{
|
||||
block();
|
||||
return 1U;
|
||||
}
|
||||
}
|
||||
else reset(); // Enough time has passed to forgive or not already in list
|
||||
return 0U;
|
||||
}
|
||||
bool getBlocked() const { return mBlocked; }
|
||||
private:
|
||||
U32 mAmount = 1;
|
||||
std::time_t mTime = time(nullptr);
|
||||
bool mBlocked = false;
|
||||
};
|
||||
boost::unordered_map<std::string, Entry> mEntries;
|
||||
U32 mAmount, mTime;
|
||||
};
|
||||
|
||||
bool can_block(const LLUUID& id)
|
||||
{
|
||||
if (id.isNull() || gAgent.getID() == id) return false; //Can't block system or self.
|
||||
if (const LLViewerObject* obj = gObjectList.findObject(id)) //From an object,
|
||||
return !obj->permYouOwner(); //not own object.
|
||||
if (id.isNull() || gAgentID == id) return false; // Can't block system or self.
|
||||
if (const LLViewerObject* obj = gObjectList.findObject(id)) // From an object,
|
||||
return !obj->permYouOwner(); // not own object.
|
||||
return true;
|
||||
}
|
||||
|
||||
U32 NACLAntiSpamRegistry::globalAmount;
|
||||
U32 NACLAntiSpamRegistry::globalTime;
|
||||
bool NACLAntiSpamRegistry::bGlobalQueue;
|
||||
NACLAntiSpamQueue* NACLAntiSpamRegistry::queues[NACLAntiSpamRegistry::QUEUE_MAX] = {0};
|
||||
boost::unordered_map<std::string,NACLAntiSpamQueueEntry*> NACLAntiSpamRegistry::globalEntries;
|
||||
boost::unordered_map<std::string,NACLAntiSpamQueueEntry*>::iterator NACLAntiSpamRegistry::it2;
|
||||
bool is_collision_sound(const std::string& sound)
|
||||
{
|
||||
// The following sounds will be ignored for purposes of spam protection. They have been gathered from wiki documentation of frequent official sounds.
|
||||
const std::array<const std::string, 29> COLLISION_SOUNDS = {
|
||||
"dce5fdd4-afe4-4ea1-822f-dd52cac46b08",
|
||||
"51011582-fbca-4580-ae9e-1a5593f094ec",
|
||||
"68d62208-e257-4d0c-bbe2-20c9ea9760bb",
|
||||
"75872e8c-bc39-451b-9b0b-042d7ba36cba",
|
||||
"6a45ba0b-5775-4ea8-8513-26008a17f873",
|
||||
"992a6d1b-8c77-40e0-9495-4098ce539694",
|
||||
"2de4da5a-faf8-46be-bac6-c4d74f1e5767",
|
||||
"6e3fb0f7-6d9c-42ca-b86b-1122ff562d7d",
|
||||
"14209133-4961-4acc-9649-53fc38ee1667",
|
||||
"bc4a4348-cfcc-4e5e-908e-8a52a8915fe6",
|
||||
"9e5c1297-6eed-40c0-825a-d9bcd86e3193",
|
||||
"e534761c-1894-4b61-b20c-658a6fb68157",
|
||||
"8761f73f-6cf9-4186-8aaa-0948ed002db1",
|
||||
"874a26fd-142f-4173-8c5b-890cd846c74d",
|
||||
"0e24a717-b97e-4b77-9c94-b59a5a88b2da",
|
||||
"75cf3ade-9a5b-4c4d-bb35-f9799bda7fb2",
|
||||
"153c8bf7-fb89-4d89-b263-47e58b1b4774",
|
||||
"55c3e0ce-275a-46fa-82ff-e0465f5e8703",
|
||||
"24babf58-7156-4841-9a3f-761bdbb8e237",
|
||||
"aca261d8-e145-4610-9e20-9eff990f2c12",
|
||||
"0642fba6-5dcf-4d62-8e7b-94dbb529d117",
|
||||
"25a863e8-dc42-4e8a-a357-e76422ace9b5",
|
||||
"9538f37c-456e-4047-81be-6435045608d4",
|
||||
"8c0f84c3-9afd-4396-b5f5-9bca2c911c20",
|
||||
"be582e5d-b123-41a2-a150-454c39e961c8",
|
||||
"c70141d4-ba06-41ea-bcbc-35ea81cb8335",
|
||||
"7d1826f4-24c4-4aac-8c2e-eff45df37783",
|
||||
"063c97d3-033a-4e9b-98d8-05c8074922cb",
|
||||
"00000000-0000-0000-0000-000000000120"
|
||||
};
|
||||
|
||||
// The following sounds will be ignored for purposes of spam protection. They have been gathered from wiki documentation of frequent official sounds.
|
||||
const std::string COLLISION_SOUNDS[] ={"dce5fdd4-afe4-4ea1-822f-dd52cac46b08","51011582-fbca-4580-ae9e-1a5593f094ec","68d62208-e257-4d0c-bbe2-20c9ea9760bb","75872e8c-bc39-451b-9b0b-042d7ba36cba","6a45ba0b-5775-4ea8-8513-26008a17f873","992a6d1b-8c77-40e0-9495-4098ce539694","2de4da5a-faf8-46be-bac6-c4d74f1e5767","6e3fb0f7-6d9c-42ca-b86b-1122ff562d7d","14209133-4961-4acc-9649-53fc38ee1667","bc4a4348-cfcc-4e5e-908e-8a52a8915fe6","9e5c1297-6eed-40c0-825a-d9bcd86e3193","e534761c-1894-4b61-b20c-658a6fb68157","8761f73f-6cf9-4186-8aaa-0948ed002db1","874a26fd-142f-4173-8c5b-890cd846c74d","0e24a717-b97e-4b77-9c94-b59a5a88b2da","75cf3ade-9a5b-4c4d-bb35-f9799bda7fb2","153c8bf7-fb89-4d89-b263-47e58b1b4774","55c3e0ce-275a-46fa-82ff-e0465f5e8703","24babf58-7156-4841-9a3f-761bdbb8e237","aca261d8-e145-4610-9e20-9eff990f2c12","0642fba6-5dcf-4d62-8e7b-94dbb529d117","25a863e8-dc42-4e8a-a357-e76422ace9b5","9538f37c-456e-4047-81be-6435045608d4","8c0f84c3-9afd-4396-b5f5-9bca2c911c20","be582e5d-b123-41a2-a150-454c39e961c8","c70141d4-ba06-41ea-bcbc-35ea81cb8335","7d1826f4-24c4-4aac-8c2e-eff45df37783","063c97d3-033a-4e9b-98d8-05c8074922cb","00000000-0000-0000-0000-000000000120"};
|
||||
const int COLLISION_SOUNDS_SIZE=29;
|
||||
|
||||
// NaClAntiSpamQueueEntry
|
||||
|
||||
NACLAntiSpamQueueEntry::NACLAntiSpamQueueEntry()
|
||||
{
|
||||
entryTime=0;
|
||||
entryAmount=0;
|
||||
blocked=false;
|
||||
for (const auto& collision : COLLISION_SOUNDS)
|
||||
if (collision == sound)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
void NACLAntiSpamQueueEntry::clearEntry()
|
||||
{
|
||||
entryTime=0;
|
||||
entryAmount=0;
|
||||
blocked=false;
|
||||
}
|
||||
U32 NACLAntiSpamQueueEntry::getEntryAmount() const
|
||||
{
|
||||
return entryAmount;
|
||||
}
|
||||
U32 NACLAntiSpamQueueEntry::getEntryTime() const
|
||||
{
|
||||
return entryTime;
|
||||
}
|
||||
void NACLAntiSpamQueueEntry::updateEntryAmount()
|
||||
{
|
||||
entryAmount++;
|
||||
}
|
||||
void NACLAntiSpamQueueEntry::updateEntryTime()
|
||||
{
|
||||
entryTime=time(0);
|
||||
}
|
||||
void NACLAntiSpamQueueEntry::setBlocked()
|
||||
{
|
||||
blocked=true;
|
||||
}
|
||||
bool NACLAntiSpamQueueEntry::getBlocked() const
|
||||
{
|
||||
return blocked;
|
||||
}
|
||||
|
||||
// NaClAntiSpamQueue
|
||||
|
||||
NACLAntiSpamQueue::NACLAntiSpamQueue(U32 time, U32 amount)
|
||||
{
|
||||
queueTime=time;
|
||||
queueAmount=amount;
|
||||
}
|
||||
void NACLAntiSpamQueue::setAmount(U32 amount)
|
||||
{
|
||||
queueAmount=amount;
|
||||
}
|
||||
void NACLAntiSpamQueue::setTime(U32 time)
|
||||
{
|
||||
queueTime=time;
|
||||
}
|
||||
U32 NACLAntiSpamQueue::getAmount() const
|
||||
{
|
||||
return queueAmount;
|
||||
}
|
||||
U32 NACLAntiSpamQueue::getTime() const
|
||||
{
|
||||
return queueTime;
|
||||
}
|
||||
void NACLAntiSpamQueue::clearEntries()
|
||||
{
|
||||
for(it = entries.begin(); it != entries.end(); it++)
|
||||
{
|
||||
it->second->clearEntry();
|
||||
}
|
||||
}
|
||||
void NACLAntiSpamQueue::purgeEntries()
|
||||
{
|
||||
for(it = entries.begin(); it != entries.end(); it++)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
entries.clear();
|
||||
}
|
||||
void NACLAntiSpamQueue::blockEntry(LLUUID& source)
|
||||
{
|
||||
it=entries.find(source.asString());
|
||||
if(it == entries.end())
|
||||
{
|
||||
entries[source.asString()]=new NACLAntiSpamQueueEntry();
|
||||
}
|
||||
entries[source.asString()]->setBlocked();
|
||||
}
|
||||
int NACLAntiSpamQueue::checkEntry(LLUUID& name, U32 multiplier)
|
||||
// Returns 0 if unblocked/disabled, 1 if check results in a new block, 2 if by an existing block
|
||||
{
|
||||
static LLCachedControl<bool> enabled(gSavedSettings,"AntiSpamEnabled",false);
|
||||
if(!enabled) return 0;
|
||||
it=entries.find(name.asString());
|
||||
if(it != entries.end())
|
||||
{
|
||||
if(it->second->getBlocked()) return 2;
|
||||
U32 eTime=it->second->getEntryTime();
|
||||
U32 currentTime=time(0);
|
||||
if((currentTime-eTime) <= queueTime)
|
||||
{
|
||||
it->second->updateEntryAmount();
|
||||
U32 eAmount=it->second->getEntryAmount();
|
||||
if(eAmount > (queueAmount*multiplier))
|
||||
{
|
||||
it->second->setBlocked();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second->clearEntry();
|
||||
it->second->updateEntryAmount();
|
||||
it->second->updateEntryTime();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//LL_DEBUGS() << "[antispam] New queue entry:" << name.asString() << LL_ENDL;
|
||||
entries[name.asString()]=new NACLAntiSpamQueueEntry();
|
||||
entries[name.asString()]->updateEntryAmount();
|
||||
entries[name.asString()]->updateEntryTime();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// NaClAntiSpamRegistry
|
||||
|
||||
static const char* QUEUE_NAME[NACLAntiSpamRegistry::QUEUE_MAX] = {
|
||||
"Chat",
|
||||
"Inventory",
|
||||
"Instant Message",
|
||||
"calling card",
|
||||
"sound",
|
||||
"Sound Preload",
|
||||
"Script Dialog",
|
||||
"Teleport"};
|
||||
constexpr std::array<const char*, NACLAntiSpamRegistry::QUEUE_MAX> QUEUE_NAME = {
|
||||
"Chat",
|
||||
"Inventory",
|
||||
"Instant Message",
|
||||
"calling card",
|
||||
"sound",
|
||||
"Sound Preload",
|
||||
"Script Dialog",
|
||||
"Teleport"
|
||||
};
|
||||
|
||||
NACLAntiSpamRegistry::NACLAntiSpamRegistry(U32 time, U32 amount)
|
||||
NACLAntiSpamRegistry::NACLAntiSpamRegistry()
|
||||
{
|
||||
globalTime=time;
|
||||
globalAmount=amount;
|
||||
static LLCachedControl<bool> _NACL_AntiSpamGlobalQueue(gSavedSettings,"_NACL_AntiSpamGlobalQueue");
|
||||
bGlobalQueue=_NACL_AntiSpamGlobalQueue;
|
||||
for(int queue = 0; queue < QUEUE_MAX; ++queue)
|
||||
auto control = gSavedSettings.getControl("_NACL_AntiSpamTime");
|
||||
const U32 time = control->get().asInteger();
|
||||
mConnections[0] = control->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamTimeChanged, _2));
|
||||
|
||||
control = gSavedSettings.getControl("_NACL_AntiSpamAmount");
|
||||
const U32 amount = control->get().asInteger();
|
||||
mConnections[1] = control->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamAmountChanged, _2));
|
||||
|
||||
control = gSavedSettings.getControl("_NACL_AntiSpamGlobalQueue");
|
||||
mConnections[2] = control->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamGlobalQueueChanged, _2));
|
||||
initializeQueues(control->get(), time, amount);
|
||||
}
|
||||
|
||||
void NACLAntiSpamRegistry::initializeQueues(bool global, const U32& time, const U32& amount)
|
||||
{
|
||||
if (global) // If Global, initialize global queue
|
||||
mGlobalQueue.reset(new NACLAntiSpamQueue(time, amount));
|
||||
else
|
||||
{
|
||||
queues[queue] = new NACLAntiSpamQueue(time,amount);
|
||||
mQueues.reset(new std::array<NACLAntiSpamQueue, QUEUE_MAX>{{
|
||||
NACLAntiSpamQueue(time, amount), // QUEUE_CHAT
|
||||
NACLAntiSpamQueue(time, amount), // QUEUE_INVENTORY
|
||||
NACLAntiSpamQueue(time, amount), // QUEUE_IM
|
||||
NACLAntiSpamQueue(time, amount), // QUEUE_CALLING_CARD
|
||||
NACLAntiSpamQueue(time, amount), // QUEUE_SOUND
|
||||
NACLAntiSpamQueue(time, amount), // QUEUE_SOUND_PRELOAD
|
||||
NACLAntiSpamQueue(time, amount), // QUEUE_SCRIPT_DIALOG
|
||||
NACLAntiSpamQueue(time, amount) // QUEUE_TELEPORT
|
||||
}});
|
||||
}
|
||||
}
|
||||
//static
|
||||
const char* NACLAntiSpamRegistry::getQueueName(U32 queue_id)
|
||||
|
||||
constexpr const char* getQueueName(const NACLAntiSpamRegistry::Type& name)
|
||||
{
|
||||
if(queue_id >= QUEUE_MAX)
|
||||
return "Unknown";
|
||||
return QUEUE_NAME[queue_id];
|
||||
return name >= QUEUE_NAME.size() ? "Unknown" : QUEUE_NAME[name];
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::registerQueues(U32 time, U32 amount)
|
||||
{
|
||||
globalTime=time;
|
||||
globalAmount=amount;
|
||||
static LLCachedControl<bool> _NACL_AntiSpamGlobalQueue(gSavedSettings,"_NACL_AntiSpamGlobalQueue");
|
||||
bGlobalQueue=_NACL_AntiSpamGlobalQueue;
|
||||
for(int queue = 0; queue < QUEUE_MAX; ++queue)
|
||||
{
|
||||
queues[queue] = new NACLAntiSpamQueue(time,amount);
|
||||
}
|
||||
}
|
||||
//static
|
||||
/*void NACLAntiSpamRegistry::registerQueue(U32 name, U32 time, U32 amount)
|
||||
{
|
||||
it=queues.find(name);
|
||||
if(it == queues.end())
|
||||
{
|
||||
queues[name]=new NACLAntiSpamQueue(time,amount);
|
||||
}
|
||||
}*/
|
||||
//static
|
||||
void NACLAntiSpamRegistry::setRegisteredQueueTime(U32 name, U32 time)
|
||||
{
|
||||
if(name >= QUEUE_MAX || queues[name] == 0)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to set time of antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
queues[name]->setTime(time);
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::setRegisteredQueueAmount(U32 name, U32 amount)
|
||||
{
|
||||
if(name >= QUEUE_MAX || queues[name] == 0)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to set amount for antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
queues[name]->setAmount(amount);
|
||||
}
|
||||
//static
|
||||
|
||||
void NACLAntiSpamRegistry::setAllQueueTimes(U32 time)
|
||||
{
|
||||
globalTime=time;
|
||||
for(int queue = 0; queue < QUEUE_MAX; ++queue)
|
||||
if( queues[queue] )
|
||||
queues[queue]->setTime(time);
|
||||
if (mGlobalQueue) mGlobalQueue->setTime(time);
|
||||
else for(auto& queue : *mQueues) queue.setTime(time);
|
||||
}
|
||||
//static
|
||||
|
||||
void NACLAntiSpamRegistry::setAllQueueAmounts(U32 amount)
|
||||
{
|
||||
globalAmount=amount;
|
||||
for(int queue = 0; queue < QUEUE_MAX; ++queue)
|
||||
if (mGlobalQueue) mGlobalQueue->setAmount(amount);
|
||||
else for (U8 queue = 0U; queue < QUEUE_MAX; ++queue)
|
||||
{
|
||||
if(!queues[queue]) continue;
|
||||
if(queue == QUEUE_SOUND || queue == QUEUE_SOUND_PRELOAD)
|
||||
queues[queue]->setAmount(amount*5);
|
||||
auto& q = (*mQueues)[queue];
|
||||
if (queue == QUEUE_SOUND || queue == QUEUE_SOUND_PRELOAD)
|
||||
q.setAmount(amount*5);
|
||||
else
|
||||
queues[queue]->setAmount(amount);
|
||||
q.setAmount(amount);
|
||||
}
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::clearRegisteredQueue(U32 name)
|
||||
|
||||
void NACLAntiSpamRegistry::blockOnQueue(const Type& name, const LLUUID& source)
|
||||
{
|
||||
if(name >= QUEUE_MAX || queues[name] == 0)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to clear antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
queues[name]->clearEntries();
|
||||
if (name >= QUEUE_MAX)
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was outside of the reasonable range of queues. Queue: " << getQueueName(name) << LL_ENDL;
|
||||
else (mGlobalQueue ? *mGlobalQueue : (*mQueues)[name]).block(source);
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::purgeRegisteredQueue(U32 name)
|
||||
{
|
||||
if(name >= QUEUE_MAX || queues[name] == 0)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to purge antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
queues[name]->purgeEntries();
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::blockOnQueue(U32 name, LLUUID& source)
|
||||
{
|
||||
if(bGlobalQueue)
|
||||
{
|
||||
NACLAntiSpamRegistry::blockGlobalEntry(source);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(name >= QUEUE_MAX || queues[name] == 0)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to use a antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
queues[name]->blockEntry(source);
|
||||
}
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::blockGlobalEntry(LLUUID& source)
|
||||
{
|
||||
it2=globalEntries.find(source.asString());
|
||||
if(it2 == globalEntries.end())
|
||||
{
|
||||
globalEntries[source.asString()]=new NACLAntiSpamQueueEntry();
|
||||
}
|
||||
globalEntries[source.asString()]->setBlocked();
|
||||
}
|
||||
//static
|
||||
bool NACLAntiSpamRegistry::checkQueue(U32 name, LLUUID& source, U32 multiplier)
|
||||
|
||||
bool NACLAntiSpamRegistry::checkQueue(const Type& name, const LLUUID& source, const LFIDBearer::Type& type, const U32& multiplier)
|
||||
//returns true if blocked
|
||||
{
|
||||
if (name >= QUEUE_MAX)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to check antispam queue that was outside of the reasonable range of queues. Queue: " << getQueueName(name) << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!can_block(source)) return false;
|
||||
|
||||
int result;
|
||||
if(bGlobalQueue)
|
||||
auto& queue = mGlobalQueue ? *mGlobalQueue : (*mQueues)[name];
|
||||
const auto result = queue.check(source, multiplier);
|
||||
if (!result) return false; // Safe
|
||||
|
||||
if (result != 2 // Not previously blocked
|
||||
&& gSavedSettings.getBOOL("AntiSpamNotify")) // and Just blocked!
|
||||
{
|
||||
result=NACLAntiSpamRegistry::checkGlobalEntry(source,multiplier);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(name >= QUEUE_MAX || queues[name] == 0)
|
||||
{
|
||||
LL_ERRS("AntiSpam") << "CODE BUG: Attempting to check antispam queue that was outside of the reasonable range of queues or not created. Queue: " << getQueueName(name) << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
result=queues[name]->checkEntry(source,multiplier);
|
||||
}
|
||||
if(result == 0) //Safe
|
||||
return false;
|
||||
else if(result == 2) //Previously blocked
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else //Just blocked!
|
||||
{
|
||||
if(gSavedSettings.getBOOL("AntiSpamNotify"))
|
||||
{
|
||||
LLSD args;
|
||||
args["SOURCE"] = source.asString().c_str();
|
||||
args["TYPE"] = LLTrans::getString(getQueueName(name));
|
||||
args["AMOUNT"] = boost::lexical_cast<std::string>(multiplier * queues[name]->getAmount());
|
||||
args["TIME"] = boost::lexical_cast<std::string>(queues[name]->getTime());
|
||||
LLNotificationsUtil::add("AntiSpamBlock", args);
|
||||
}
|
||||
return true;
|
||||
const std::string get_slurl_for(const LLUUID& id, const LFIDBearer::Type& type);
|
||||
const auto slurl = get_slurl_for(source, type);
|
||||
LLSD args;
|
||||
args["SOURCE"] = slurl.empty() ? source.asString() : slurl;
|
||||
args["TYPE"] = LLTrans::getString(getQueueName(name));
|
||||
args["AMOUNT"] = (LLSD::Integer)(multiplier * queue.getAmount());
|
||||
args["TIME"] = (LLSD::Integer)queue.getTime();
|
||||
LLNotificationsUtil::add("AntiSpamBlock", args);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Global queue stoof
|
||||
//static
|
||||
void NACLAntiSpamRegistry::setGlobalQueue(bool value)
|
||||
void NACLAntiSpamRegistry::idle()
|
||||
{
|
||||
NACLAntiSpamRegistry::purgeAllQueues();
|
||||
bGlobalQueue=value;
|
||||
if (mGlobalQueue) mGlobalQueue->idle();
|
||||
else for (auto& queue : *mQueues) queue.idle();
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::setGlobalAmount(U32 amount)
|
||||
|
||||
void NACLAntiSpamRegistry::resetQueues()
|
||||
{
|
||||
globalAmount=amount;
|
||||
if (mGlobalQueue) mGlobalQueue->reset();
|
||||
else for (auto& queue : *mQueues) queue.reset();
|
||||
|
||||
LL_INFOS() << "AntiSpam Queues Reset" << LL_ENDL;
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::setGlobalTime(U32 time)
|
||||
{
|
||||
globalTime=time;
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::clearAllQueues()
|
||||
{
|
||||
if(bGlobalQueue)
|
||||
NACLAntiSpamRegistry::clearGlobalEntries();
|
||||
else
|
||||
for(int queue = 0; queue < QUEUE_MAX; ++queue)
|
||||
{
|
||||
if(queues[queue]) queues[queue]->clearEntries();
|
||||
}
|
||||
}
|
||||
//static
|
||||
|
||||
void NACLAntiSpamRegistry::purgeAllQueues()
|
||||
{
|
||||
if(bGlobalQueue)
|
||||
NACLAntiSpamRegistry::purgeGlobalEntries();
|
||||
// Note: These resets are upon the unique_ptr, not the Queue itself!
|
||||
if (mGlobalQueue)
|
||||
mGlobalQueue.reset();
|
||||
else
|
||||
for(int queue = 0; queue < QUEUE_MAX; ++queue)
|
||||
{
|
||||
if(queues[queue]) queues[queue]->purgeEntries();
|
||||
}
|
||||
LL_INFOS() << "AntiSpam Queues Purged" << LL_ENDL;
|
||||
}
|
||||
//static
|
||||
int NACLAntiSpamRegistry::checkGlobalEntry(LLUUID& name, U32 multiplier)
|
||||
{
|
||||
static LLCachedControl<bool> enabled(gSavedSettings,"AntiSpamEnabled",false);
|
||||
if(!enabled) return 0;
|
||||
it2=globalEntries.find(name.asString());
|
||||
if(it2 != globalEntries.end())
|
||||
{
|
||||
if(it2->second->getBlocked()) return 2;
|
||||
U32 eTime=it2->second->getEntryTime();
|
||||
U32 currentTime=time(0);
|
||||
if((currentTime-eTime) <= globalTime)
|
||||
{
|
||||
it2->second->updateEntryAmount();
|
||||
U32 eAmount=it2->second->getEntryAmount();
|
||||
if(eAmount > (globalAmount*multiplier))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
it2->second->clearEntry();
|
||||
it2->second->updateEntryAmount();
|
||||
it2->second->updateEntryTime();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
globalEntries[name.asString()]=new NACLAntiSpamQueueEntry();
|
||||
globalEntries[name.asString()]->updateEntryAmount();
|
||||
globalEntries[name.asString()]->updateEntryTime();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::clearGlobalEntries()
|
||||
{
|
||||
for(it2 = globalEntries.begin(); it2 != globalEntries.end(); it2++)
|
||||
{
|
||||
it2->second->clearEntry();
|
||||
}
|
||||
}
|
||||
//static
|
||||
void NACLAntiSpamRegistry::purgeGlobalEntries()
|
||||
{
|
||||
for(it2 = globalEntries.begin(); it2 != globalEntries.end(); it2++)
|
||||
{
|
||||
delete it2->second;
|
||||
it2->second = 0;
|
||||
}
|
||||
globalEntries.clear();
|
||||
mQueues.reset();
|
||||
}
|
||||
|
||||
//Handlers
|
||||
//static
|
||||
// Handlers
|
||||
// static
|
||||
void NACLAntiSpamRegistry::startup()
|
||||
{
|
||||
auto onAntiSpamToggle = [](const LLControlVariable*, const LLSD& value) {
|
||||
if (value.asBoolean()) instance();
|
||||
else deleteSingleton();
|
||||
};
|
||||
auto control = gSavedSettings.getControl("AntiSpamEnabled");
|
||||
control->getSignal()->connect(onAntiSpamToggle);
|
||||
onAntiSpamToggle(control, control->get());
|
||||
}
|
||||
|
||||
// static
|
||||
bool NACLAntiSpamRegistry::handleNaclAntiSpamGlobalQueueChanged(const LLSD& newvalue)
|
||||
{
|
||||
setGlobalQueue(newvalue.asBoolean());
|
||||
if (instanceExists())
|
||||
{
|
||||
auto& inst = instance();
|
||||
inst.purgeAllQueues();
|
||||
inst.initializeQueues(newvalue.asBoolean(), gSavedSettings.getU32("_NACL_AntiSpamTime"), gSavedSettings.getU32("_NACL_AntiSpamAmount"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//static
|
||||
bool NACLAntiSpamRegistry::handleNaclAntiSpamTimeChanged(const LLSD& newvalue)
|
||||
{
|
||||
setAllQueueTimes(newvalue.asInteger());
|
||||
if (auto inst = getIfExists()) inst->setAllQueueTimes(newvalue.asInteger());
|
||||
return true;
|
||||
}
|
||||
//static
|
||||
bool NACLAntiSpamRegistry::handleNaclAntiSpamAmountChanged(const LLSD& newvalue)
|
||||
{
|
||||
setAllQueueAmounts(newvalue.asInteger());
|
||||
if (auto inst = getIfExists()) inst->setAllQueueAmounts(newvalue.asInteger());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,72 +13,22 @@
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
*/
|
||||
|
||||
#ifndef NACLANTISPAM_H
|
||||
#define NACLANTISPAM_H
|
||||
#pragma once
|
||||
#include <boost/signals2/connection.hpp>
|
||||
#include <boost/unordered/unordered_map.hpp>
|
||||
#include "stdtypes.h"
|
||||
#include "lfidbearer.h"
|
||||
#include "lluuid.h"
|
||||
class NACLAntiSpamQueueEntry
|
||||
|
||||
class NACLAntiSpamQueue;
|
||||
class NACLAntiSpamRegistry final : public LLSingleton<NACLAntiSpamRegistry>
|
||||
{
|
||||
friend class NACLAntiSpamQueue;
|
||||
friend class NACLAntiSpamRegistry;
|
||||
protected:
|
||||
NACLAntiSpamQueueEntry();
|
||||
void clearEntry();
|
||||
U32 getEntryAmount() const;
|
||||
U32 getEntryTime() const;
|
||||
void updateEntryAmount();
|
||||
void updateEntryTime();
|
||||
bool getBlocked() const;
|
||||
void setBlocked();
|
||||
private:
|
||||
U32 entryAmount;
|
||||
U32 entryTime;
|
||||
bool blocked;
|
||||
};
|
||||
class NACLAntiSpamQueue
|
||||
{
|
||||
friend class NACLAntiSpamRegistry;
|
||||
friend class LLSingleton<NACLAntiSpamRegistry>;
|
||||
NACLAntiSpamRegistry();
|
||||
public:
|
||||
U32 getAmount() const;
|
||||
U32 getTime() const;
|
||||
protected:
|
||||
NACLAntiSpamQueue(U32 time, U32 amount);
|
||||
void setAmount(U32 amount);
|
||||
void setTime(U32 time);
|
||||
void clearEntries();
|
||||
void purgeEntries();
|
||||
void blockEntry(LLUUID& source);
|
||||
int checkEntry(LLUUID& source, U32 multiplier);
|
||||
private:
|
||||
boost::unordered_map<std::string,NACLAntiSpamQueueEntry*> entries;
|
||||
boost::unordered_map<std::string,NACLAntiSpamQueueEntry*>::iterator it;
|
||||
U32 queueAmount;
|
||||
U32 queueTime;
|
||||
};
|
||||
class NACLAntiSpamRegistry
|
||||
{
|
||||
public:
|
||||
NACLAntiSpamRegistry(U32 time=2, U32 amount=10);
|
||||
static void registerQueues(U32 time=2, U32 amount=10);
|
||||
// static void registerQueue(U32 name, U32 time, U32 amount);
|
||||
static void setRegisteredQueueTime(U32 name, U32 time);
|
||||
static void setRegisteredQueueAmount(U32 name,U32 amount);
|
||||
static void setAllQueueTimes(U32 amount);
|
||||
static void setAllQueueAmounts(U32 time);
|
||||
static bool checkQueue(U32 name, LLUUID& source, U32 multiplier=1);
|
||||
static bool handleNaclAntiSpamGlobalQueueChanged(const LLSD& newvalue);
|
||||
static bool handleNaclAntiSpamTimeChanged(const LLSD& newvalue);
|
||||
static bool handleNaclAntiSpamAmountChanged(const LLSD& newvalue);
|
||||
static void clearRegisteredQueue(U32 name);
|
||||
static void purgeRegisteredQueue(U32 name);
|
||||
static void clearAllQueues();
|
||||
static void purgeAllQueues();
|
||||
static void setGlobalQueue(bool value);
|
||||
static void setGlobalAmount(U32 amount);
|
||||
static void setGlobalTime(U32 time);
|
||||
static void blockOnQueue(U32 name,LLUUID& owner_id);
|
||||
enum {
|
||||
static void startup();
|
||||
|
||||
enum Type : U8 {
|
||||
QUEUE_CHAT,
|
||||
QUEUE_INVENTORY,
|
||||
QUEUE_IM,
|
||||
@@ -89,22 +39,19 @@ public:
|
||||
QUEUE_TELEPORT,
|
||||
QUEUE_MAX
|
||||
};
|
||||
bool checkQueue(const Type& name, const LLUUID& source, const LFIDBearer::Type& type = LFIDBearer::AVATAR, const U32& multiplier = 1);
|
||||
void blockOnQueue(const Type& name, const LLUUID& owner_id);
|
||||
void idle();
|
||||
void resetQueues();
|
||||
private:
|
||||
static const char* getQueueName(U32 queue_id);
|
||||
static NACLAntiSpamQueue* queues[QUEUE_MAX];
|
||||
static boost::unordered_map<std::string,NACLAntiSpamQueueEntry*> globalEntries;
|
||||
static boost::unordered_map<std::string,NACLAntiSpamQueueEntry*>::iterator it2;
|
||||
static U32 globalTime;
|
||||
static U32 globalAmount;
|
||||
static bool bGlobalQueue;
|
||||
|
||||
static int checkGlobalEntry(LLUUID& source, U32 multiplier);
|
||||
static void clearGlobalEntries();
|
||||
static void purgeGlobalEntries();
|
||||
static void blockGlobalEntry(LLUUID& source);
|
||||
void setAllQueueTimes(U32 amount);
|
||||
void setAllQueueAmounts(U32 time);
|
||||
void purgeAllQueues();
|
||||
void initializeQueues(bool global, const U32& time, const U32& amount);
|
||||
static bool handleNaclAntiSpamGlobalQueueChanged(const LLSD& newvalue);
|
||||
static bool handleNaclAntiSpamTimeChanged(const LLSD& newvalue);
|
||||
static bool handleNaclAntiSpamAmountChanged(const LLSD& newvalue);
|
||||
std::unique_ptr<std::array<NACLAntiSpamQueue, QUEUE_MAX>> mQueues;
|
||||
std::unique_ptr<NACLAntiSpamQueue> mGlobalQueue;
|
||||
std::array<boost::signals2::scoped_connection, 3> mConnections;
|
||||
};
|
||||
|
||||
extern const std::string COLLISION_SOUNDS[];
|
||||
extern const int COLLISION_SOUNDS_SIZE;
|
||||
|
||||
#endif //NACLANTISPAM_H
|
||||
|
||||
@@ -117,6 +117,9 @@ void ALFloaterRegionTracker::refresh()
|
||||
{
|
||||
saved_selected_values.push_back(item->getValue().asString());
|
||||
}
|
||||
S32 saved_scroll_pos = mRegionScrollList->getScrollPos();
|
||||
auto sort_column_name = mRegionScrollList->getSortColumnName();
|
||||
auto sort_asending = mRegionScrollList->getSortAscending();
|
||||
mRegionScrollList->deleteAllItems();
|
||||
|
||||
const std::string& cur_region_name = gAgent.getRegion()->getName();
|
||||
@@ -172,8 +175,11 @@ void ALFloaterRegionTracker::refresh()
|
||||
mRegionScrollList->addRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
mRegionScrollList->sortByColumn(sort_column_name, sort_asending);
|
||||
if (!saved_selected_values.empty())
|
||||
mRegionScrollList->selectMultiple(saved_selected_values);
|
||||
mRegionScrollList->setScrollPos(saved_scroll_pos);
|
||||
}
|
||||
|
||||
BOOL ALFloaterRegionTracker::tick()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<array>
|
||||
|
||||
<map>
|
||||
<key>default_grids_version</key><string>22</string>
|
||||
<key>default_grids_version</key><string>23</string>
|
||||
</map>
|
||||
|
||||
<!-- Second Life -->
|
||||
@@ -11,7 +11,7 @@
|
||||
<key>gridname</key><string>Second Life</string>
|
||||
<key>platform</key><string>SecondLife</string>
|
||||
<key>loginuri</key><string>https://login.agni.lindenlab.com/cgi-bin/login.cgi</string>
|
||||
<key>loginpage</key><string>http://viewer-login.agni.lindenlab.com/</string>
|
||||
<key>loginpage</key><string>https://viewer-splash.secondlife.com/</string>
|
||||
<key>helperuri</key><string>https://secondlife.com/helpers/</string>
|
||||
<key>website</key><string>http://secondlife.com/</string>
|
||||
<key>support</key><string>http://secondlife.com/support/</string>
|
||||
@@ -26,7 +26,7 @@
|
||||
<key>gridnick</key><string>secondlife_beta</string>
|
||||
<key>gridname</key><string>Second Life BETA</string>
|
||||
<key>helperuri</key><string>http://aditi-secondlife.webdev.lindenlab.com/helpers/</string>
|
||||
<key>loginpage</key><string>http://viewer-login.agni.lindenlab.com/</string>
|
||||
<key>loginpage</key><string>https://viewer-splash.secondlife.com/</string>
|
||||
<key>loginuri</key><string>https://login.aditi.lindenlab.com/cgi-bin/login.cgi</string>
|
||||
<key>password</key><string>http://secondlife.com/account/request.php</string>
|
||||
<key>platform</key><string>SecondLife</string>
|
||||
|
||||
@@ -1052,5 +1052,28 @@
|
||||
<map/>
|
||||
<key>llGetMaxScaleFactor</key>
|
||||
<map/>
|
||||
<!-- Experience Tools new functions -->
|
||||
<key>llAgentInExperience</key>
|
||||
<map/>
|
||||
<key>llGetExperienceDetails</key>
|
||||
<map/>
|
||||
<key>llRequestExperiencePermissions</key>
|
||||
<map/>
|
||||
<key>llReadKeyValue</key>
|
||||
<map/>
|
||||
<key>llCreateKeyValue</key>
|
||||
<map/>
|
||||
<key>llUpdateKeyValue</key>
|
||||
<map/>
|
||||
<key>llDeleteKeyValue</key>
|
||||
<map/>
|
||||
<key>llDataSizeKeyValue</key>
|
||||
<map/>
|
||||
<key>llKeysKeyValue</key>
|
||||
<map/>
|
||||
<key>llKeyCountKeyValue</key>
|
||||
<map/>
|
||||
<key>llGetExperienceErrorMessage</key>
|
||||
<map/>
|
||||
</map>
|
||||
</llsd>
|
||||
|
||||
@@ -2556,6 +2556,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<!-- Standard SL options (To my knowledge) -->
|
||||
<key>CrashHostUrl</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string />
|
||||
</map>
|
||||
<key>AFKTimeout</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -7500,6 +7511,54 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<integer>0</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterExperiencePickerRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Rectangle for experience picker floater</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Rect</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<integer>300</integer>
|
||||
<integer>600</integer>
|
||||
<integer>800</integer>
|
||||
<integer>700</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterExperienceProfileRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Rectangle for experience profile floaters</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Rect</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<integer>377</integer>
|
||||
<integer>650</integer>
|
||||
<integer>345</integer>
|
||||
<integer>128</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterExperiencesRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Rectangle for experiences floater</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Rect</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<integer>300</integer>
|
||||
<integer>600</integer>
|
||||
<integer>700</integer>
|
||||
<integer>700</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterFindRect2</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -8257,7 +8316,7 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<array>
|
||||
<integer>0</integer>
|
||||
<integer>512</integer>
|
||||
<integer>480</integer>
|
||||
<integer>500</integer>
|
||||
<integer>0</integer>
|
||||
</array>
|
||||
</map>
|
||||
@@ -11677,17 +11736,6 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>344</integer>
|
||||
</map>
|
||||
<key>RevokePermsOnStandUp</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When enabled, revokes any permission granted to an object you don't own and from which your avatar is standing up</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>PickerContextOpacity</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -14579,6 +14627,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RevokePermsOnStandUp</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When enabled, revokes any permission granted to an object you don't own and from which your avatar is standing up</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RevokePermsOnStopAnimation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
||||
@@ -565,6 +565,17 @@
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>AlchemyDisableSimCamConstraint</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Disable the push the simulator applies when camera collides with objects</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>AscentFlyAlwaysEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -1164,6 +1175,17 @@ Changing this setting only affects new text.</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>LiruUseMarkedColor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether or not to use the color of marks done on radar and minimap to color tags and chat from those individuals</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>OBJExportNotifyFailed</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -1622,6 +1644,19 @@ Changing this setting only affects new text.</string>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>ToolbarVisibleExperiences</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether or not the button for the experiences floater is on the toolbar</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<boolean>0</boolean>
|
||||
<key>IsCOA</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>ToolbarVisibleFastTimers</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
||||
@@ -70,7 +70,10 @@ LLPrefsAscentChat::LLPrefsAscentChat()
|
||||
}
|
||||
|
||||
childSetEnabled("reset_antispam", started);
|
||||
getChild<LLUICtrl>("reset_antispam")->setCommitCallback(boost::bind(NACLAntiSpamRegistry::purgeAllQueues));
|
||||
getChild<LLUICtrl>("reset_antispam")->setCommitCallback([](LLUICtrl* ctrl, const LLSD& param) {
|
||||
if (auto inst = NACLAntiSpamRegistry::getIfExists())
|
||||
inst->resetQueues();
|
||||
});
|
||||
|
||||
getChild<LLUICtrl>("autoreplace")->setCommitCallback(boost::bind(LLFloaterAutoReplaceSettings::showInstance, LLSD()));
|
||||
getChild<LLUICtrl>("KeywordsOn")->setCommitCallback(boost::bind(&LLPrefsAscentChat::onCommitKeywords, this, _1));
|
||||
|
||||
@@ -438,6 +438,12 @@ NVIDIA GTX 770 .*NVIDIA .*GTX *77.* 3 1
|
||||
NVIDIA GTX 780 .*NVIDIA .*GTX *78.* 3 1
|
||||
NVIDIA GTX 970 .*NVIDIA .*GTX *97.* 3 1
|
||||
NVIDIA GTX 980 .*NVIDIA .*GTX *98.* 3 1
|
||||
NVIDIA GTX 1050 .*NVIDIA.*GTX 105.* 3 1
|
||||
NVIDIA GTX 1060 .*NVIDIA.*GTX 106.* 3 1
|
||||
NVIDIA GTX 1070 .*NVIDIA.*GTX 107.* 3 1
|
||||
NVIDIA GTX 1080 .*NVIDIA.*GTX 108.* 3 1
|
||||
NVIDIA GTX 1650 .*NVIDIA.*GTX 165.* 3 1
|
||||
NVIDIA GTX 1660 .*NVIDIA.*GTX 166.* 3 1
|
||||
NVIDIA GTX TITAN .*NVIDIA .*GTX *TITAN.* 3 1
|
||||
NVIDIA GeForce/Quadro RTX .*(GeForce|Quadro) .*RTX.* 3 1
|
||||
NVIDIA RTX TITAN .*NVIDIA .*RTX.*TITAN.* 3 1
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "Singularity Viewer Installer"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" "A viewer for the meta-verse!"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "${VENDORSTR}"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright © 2010-2019, ${VENDORSTR}"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright © 2010-2020, ${VENDORSTR}"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "${APPNAME} Installer"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductVersion" "${VERSION_LONG}"
|
||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${VERSION_LONG}"
|
||||
@@ -410,19 +410,40 @@ Section "Viewer"
|
||||
;This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py
|
||||
%%INSTALL_FILES%%
|
||||
|
||||
;Create temp dir and set out dir to it
|
||||
CreateDirectory "$TEMP\AlchemyInst"
|
||||
SetOutPath "$TEMP\AlchemyInst"
|
||||
|
||||
;Download LibVLC
|
||||
!ifdef WIN64_BIN_BUILD
|
||||
NSISdl::download "http://download.videolan.org/pub/videolan/vlc/2.2.8/win64/vlc-2.2.8-win64.7z" "$INSTDIR\libvlc.7z"
|
||||
NSISdl::download "http://download.videolan.org/pub/videolan/vlc/3.0.8/win64/vlc-3.0.8-win64.7z" "$TEMP\AlchemyInst\libvlc.7z"
|
||||
!else
|
||||
NSISdl::download "http://download.videolan.org/pub/videolan/vlc/2.2.8/win32/vlc-2.2.8-win32.7z" "$INSTDIR\libvlc.7z"
|
||||
NSISdl::download "http://download.videolan.org/pub/videolan/vlc/3.0.8/win32/vlc-3.0.8-win32.7z" "$TEMP\AlchemyInst\libvlc.7z"
|
||||
!endif
|
||||
Nsis7z::Extract "$INSTDIR\libvlc.7z"
|
||||
Rename "$INSTDIR\vlc-2.2.8\libvlc.dll" "$INSTDIR\llplugin\libvlc.dll"
|
||||
Rename "$INSTDIR\vlc-2.2.8\libvlccore.dll" "$INSTDIR\llplugin\libvlccore.dll"
|
||||
Rename "$INSTDIR\vlc-2.2.8\plugins" "$INSTDIR\llplugin\plugins"
|
||||
RMDir /r "$INSTDIR\vlc-2.2.8"
|
||||
Delete "$INSTDIR\libvlc.7z"
|
||||
|
||||
Nsis7z::ExtractWithDetails "$TEMP\AlchemyInst\libvlc.7z" "Unpacking media plugins %s..."
|
||||
Rename "$TEMP\AlchemyInst\vlc-3.0.8\libvlc.dll" "$INSTDIR\llplugin\libvlc.dll"
|
||||
Rename "$TEMP\AlchemyInst\vlc-3.0.8\libvlccore.dll" "$INSTDIR\llplugin\libvlccore.dll"
|
||||
Rename "$TEMP\AlchemyInst\vlc-3.0.8\plugins" "$INSTDIR\llplugin\plugins"
|
||||
|
||||
;Download and install VC redist
|
||||
!ifdef WIN64_BIN_BUILD
|
||||
NSISdl::download "https://aka.ms/vs/16/release/vc_redist.x64.exe" "$TEMP\AlchemyInst\vc_redist_16.x64.exe"
|
||||
ExecWait "$TEMP\AlchemyInst\vc_redist_16.x64.exe /install /passive /norestart"
|
||||
|
||||
NSISdl::download "https://aka.ms/highdpimfc2013x64enu" "$TEMP\AlchemyInst\vc_redist_12.x64.exe"
|
||||
ExecWait "$TEMP\AlchemyInst\vc_redist_12.x64.exe /install /passive /norestart"
|
||||
!else
|
||||
NSISdl::download "https://aka.ms/vs/16/release/vc_redist.x86.exe" "$TEMP\AlchemyInst\vc_redist_16.x86.exe"
|
||||
ExecWait "$TEMP\AlchemyInst\vc_redist_16.x86.exe /install /passive /norestart"
|
||||
|
||||
NSISdl::download "https://aka.ms/highdpimfc2013x86enu" "$TEMP\AlchemyInst\vc_redist_12.x86.exe"
|
||||
ExecWait "$TEMP\AlchemyInst\vc_redist_12.x86.exe /install /passive /norestart"
|
||||
!endif
|
||||
|
||||
;Remove temp dir and reset out to inst dir
|
||||
RMDir /r "$TEMP\AlchemyInst\"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
;Pass the installer's language to the client to use as a default
|
||||
StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)"
|
||||
|
||||
|
||||
@@ -80,13 +80,21 @@ BOOL JCFloaterAreaSearch::postBuild()
|
||||
mResultList = getChild<LLScrollListCtrl>("result_list");
|
||||
mResultList->setDoubleClickCallback(boost::bind(&JCFloaterAreaSearch::onDoubleClick,this));
|
||||
mResultList->sortByColumn("Name", TRUE);
|
||||
auto tp = getChild<LLButton>("TP");
|
||||
auto look = getChild<LLButton>("Look");
|
||||
mResultList->setCommitOnSelectionChange(true);
|
||||
mResultList->setCommitCallback([=](LLUICtrl* ctrl, const LLSD& param){
|
||||
bool enabled = mResultList->getNumSelected() == 1;
|
||||
tp->setEnabled(enabled);
|
||||
look->setEnabled(enabled);
|
||||
});
|
||||
|
||||
mCounterText = getChild<LLTextBox>("counter");
|
||||
|
||||
getChild<LLButton>("Refresh")->setClickedCallback(boost::bind(&JCFloaterAreaSearch::onRefresh,this));
|
||||
getChild<LLButton>("Stop")->setClickedCallback(boost::bind(&JCFloaterAreaSearch::onStop,this));
|
||||
getChild<LLButton>("TP")->setClickedCallback(boost::bind(&JCFloaterAreaSearch::teleportToSelected, this));
|
||||
getChild<LLButton>("Look")->setClickedCallback(boost::bind(&JCFloaterAreaSearch::lookAtSelected, this));
|
||||
tp->setClickedCallback(boost::bind(&JCFloaterAreaSearch::teleportToSelected, this));
|
||||
look->setClickedCallback(boost::bind(&JCFloaterAreaSearch::lookAtSelected, this));
|
||||
|
||||
getChild<LLFilterEditor>("Name query chunk")->setCommitCallback(boost::bind(&JCFloaterAreaSearch::onCommitLine,this,_1,_2,LIST_OBJECT_NAME));
|
||||
getChild<LLFilterEditor>("Description query chunk")->setCommitCallback(boost::bind(&JCFloaterAreaSearch::onCommitLine,this,_1,_2,LIST_OBJECT_DESC));
|
||||
|
||||
@@ -56,6 +56,20 @@ public:
|
||||
|
||||
void results();
|
||||
static void processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data);
|
||||
struct ObjectData
|
||||
{
|
||||
LLUUID id;
|
||||
std::string name;
|
||||
std::string desc;
|
||||
LLUUID owner_id;
|
||||
LLUUID group_id;
|
||||
};
|
||||
|
||||
const ObjectData* getObjectData(const LLUUID& id) const
|
||||
{
|
||||
const auto& it = mCachedObjects.find(id);
|
||||
return it != mCachedObjects.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -84,14 +98,6 @@ private:
|
||||
LLViewerRegion* mLastRegion;
|
||||
bool mStopped;
|
||||
|
||||
struct ObjectData
|
||||
{
|
||||
LLUUID id;
|
||||
std::string name;
|
||||
std::string desc;
|
||||
LLUUID owner_id;
|
||||
LLUUID group_id;
|
||||
};
|
||||
uuid_set_t mPendingObjects;
|
||||
boost::unordered_map<LLUUID, ObjectData> mCachedObjects;
|
||||
|
||||
|
||||
@@ -32,49 +32,38 @@ LFFloaterInvPanel::LFFloaterInvPanel(const LLSD& cat, const std::string& name, L
|
||||
: LLInstanceTracker<LFFloaterInvPanel, LLSD>(cat)
|
||||
{
|
||||
// Setup the floater first
|
||||
mPanel = new LLInventoryPanel("inv_panel", LLInventoryPanel::DEFAULT_SORT_ORDER, cat, LLRect(), model ? model : &gInventory, true);
|
||||
const auto& title = name.empty() ? gInventory.getCategory(mPanel->getRootFolderID())->getName() : name;
|
||||
|
||||
// Figure out a unique name for our rect control
|
||||
const auto rect_control = llformat("FloaterInv%sRect", boost::algorithm::erase_all_copy(title, " ").data());
|
||||
|
||||
bool existed = gSavedSettings.controlExists(rect_control);
|
||||
if (existed) // Set our initial rect to the stored control
|
||||
setRectControl(rect_control);
|
||||
auto mPanel = new LLInventoryPanel("inv_panel", LLInventoryPanel::DEFAULT_SORT_ORDER, cat, LLRect(), model ? model : &gInventory, true);
|
||||
|
||||
// Load from XUI
|
||||
mCommitCallbackRegistrar.add("InvPanel.Search", boost::bind(&LLInventoryPanel::setFilterSubString, boost::ref(mPanel), _2));
|
||||
mCommitCallbackRegistrar.add("InvPanel.Search", boost::bind(&LLInventoryPanel::setFilterSubString, mPanel, _2));
|
||||
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inv_panel.xml");
|
||||
|
||||
// Now set the title
|
||||
const auto& title = name.empty() ? gInventory.getCategory(mPanel->getRootFolderID())->getName() : name;
|
||||
setTitle(title);
|
||||
|
||||
// If we haven't existed before, create and set our rect control now
|
||||
if (!existed)
|
||||
// Figure out a unique name for our rect control
|
||||
const auto rect_control = llformat("FloaterInv%sRect", boost::algorithm::erase_all_copy(title, " ").data());
|
||||
if (!gSavedSettings.controlExists(rect_control)) // If we haven't existed before, create it
|
||||
{
|
||||
S32 left, top;
|
||||
gFloaterView->getNewFloaterPosition(&left, &top);
|
||||
LLRect rect = getRect();
|
||||
rect.translate(left - rect.mLeft, top - rect.mTop);
|
||||
setRect(rect);
|
||||
gSavedSettings.declareRect(rect_control, rect, "Rectangle for " + title + " window");
|
||||
setRectControl(rect_control);
|
||||
}
|
||||
setRectControl(rect_control);
|
||||
applyRectControl(); // Set our initial rect to the stored (or just created) control
|
||||
|
||||
// Now take care of the children
|
||||
LLPanel* panel = getChild<LLPanel>("placeholder_panel");
|
||||
mPanel->setRect(panel->getRect());
|
||||
mPanel->setOrigin(0, 0);
|
||||
mPanel->postBuild();
|
||||
mPanel->setFollows(FOLLOWS_ALL);
|
||||
mPanel->setEnabled(true);
|
||||
mPanel->removeBorder();
|
||||
addChild(mPanel);
|
||||
removeChild(panel);
|
||||
}
|
||||
|
||||
LFFloaterInvPanel::~LFFloaterInvPanel()
|
||||
{
|
||||
delete mPanel;
|
||||
panel->addChild(mPanel);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -101,15 +90,18 @@ void LFFloaterInvPanel::closeAll()
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LFFloaterInvPanel::handleKeyHere(KEY key, MASK mask)
|
||||
{
|
||||
if (!mPanel->hasFocus() && mask == MASK_NONE && (key == KEY_RETURN || key == KEY_DOWN))
|
||||
if (mask == MASK_NONE && (key == KEY_RETURN || key == KEY_DOWN))
|
||||
{
|
||||
mPanel->setFocus(true);
|
||||
if (LLFolderView* root = mPanel->getRootFolder())
|
||||
root->scrollToShowSelection();
|
||||
return true;
|
||||
auto& mPanel = *getChild<LLInventoryPanel>("inv_panel");
|
||||
if (!mPanel.hasFocus())
|
||||
{
|
||||
mPanel.setFocus(true);
|
||||
if (LLFolderView* root = mPanel.getRootFolder())
|
||||
root->scrollToShowSelection();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return LLFloater::handleKeyHere(key, mask);
|
||||
|
||||
@@ -18,18 +18,16 @@
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef LFFLOATERINVPANEL_H
|
||||
#define LFFLOATERINVPANEL_H
|
||||
#pragma once
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "llinstancetracker.h"
|
||||
#include "llsdutil.h"
|
||||
|
||||
|
||||
class LFFloaterInvPanel : public LLFloater, public LLInstanceTracker<LFFloaterInvPanel, LLSD>
|
||||
class LFFloaterInvPanel final : public LLFloater, public LLInstanceTracker<LFFloaterInvPanel, LLSD>
|
||||
{
|
||||
LFFloaterInvPanel(const LLSD& cat, const std::string& name = LLStringUtil::null, class LLInventoryModel* model = nullptr);
|
||||
~LFFloaterInvPanel();
|
||||
|
||||
public:
|
||||
static void show(const LLSD& cat, const std::string& name = LLStringUtil::null, LLInventoryModel* model = nullptr); // Show the floater for cat (create with other params if necessary)
|
||||
@@ -42,10 +40,5 @@ public:
|
||||
}
|
||||
static void closeAll(); // Called when not allowed to have inventory open
|
||||
|
||||
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
|
||||
|
||||
private:
|
||||
class LLInventoryPanel* mPanel;
|
||||
BOOL handleKeyHere(KEY key, MASK mask) override;
|
||||
};
|
||||
|
||||
#endif //LFFLOATERINVPANEL_H
|
||||
|
||||
@@ -38,11 +38,14 @@
|
||||
#include "llanimationstates.h"
|
||||
#include "llcallingcard.h"
|
||||
#include "llcapabilitylistener.h"
|
||||
#include "llcororesponder.h"
|
||||
#include "llconsole.h"
|
||||
#include "llenvmanager.h"
|
||||
#include "llfirstuse.h"
|
||||
#include "llfloatercamera.h"
|
||||
#include "llfloatertools.h"
|
||||
#include "llfloaterpostcard.h"
|
||||
#include "llfloaterpreference.h"
|
||||
#include "llgroupactions.h"
|
||||
#include "llgroupmgr.h"
|
||||
#include "llhomelocationresponder.h"
|
||||
@@ -184,10 +187,10 @@ public:
|
||||
LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId);
|
||||
virtual ~LLTeleportRequestViaLandmark();
|
||||
|
||||
virtual bool canRestartTeleport();
|
||||
bool canRestartTeleport() override;
|
||||
|
||||
virtual void startTeleport();
|
||||
virtual void restartTeleport();
|
||||
void startTeleport() override;
|
||||
void restartTeleport() override;
|
||||
|
||||
protected:
|
||||
inline const LLUUID &getLandmarkId() const {return mLandmarkId;};
|
||||
@@ -196,15 +199,15 @@ private:
|
||||
LLUUID mLandmarkId;
|
||||
};
|
||||
|
||||
class LLTeleportRequestViaLure : public LLTeleportRequestViaLandmark
|
||||
class LLTeleportRequestViaLure final : public LLTeleportRequestViaLandmark
|
||||
{
|
||||
public:
|
||||
LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike);
|
||||
virtual ~LLTeleportRequestViaLure();
|
||||
|
||||
virtual bool canRestartTeleport();
|
||||
bool canRestartTeleport() override;
|
||||
|
||||
virtual void startTeleport();
|
||||
void startTeleport() override;
|
||||
|
||||
protected:
|
||||
inline BOOL isLureGodLike() const {return mIsLureGodLike;};
|
||||
@@ -219,10 +222,10 @@ public:
|
||||
LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal);
|
||||
virtual ~LLTeleportRequestViaLocation();
|
||||
|
||||
virtual bool canRestartTeleport();
|
||||
bool canRestartTeleport() override;
|
||||
|
||||
virtual void startTeleport();
|
||||
virtual void restartTeleport();
|
||||
void startTeleport() override;
|
||||
void restartTeleport() override;
|
||||
|
||||
protected:
|
||||
inline const LLVector3d &getPosGlobal() const {return mPosGlobal;};
|
||||
@@ -232,16 +235,16 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation
|
||||
class LLTeleportRequestViaLocationLookAt final : public LLTeleportRequestViaLocation
|
||||
{
|
||||
public:
|
||||
LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal);
|
||||
virtual ~LLTeleportRequestViaLocationLookAt();
|
||||
|
||||
virtual bool canRestartTeleport();
|
||||
bool canRestartTeleport() override;
|
||||
|
||||
virtual void startTeleport();
|
||||
virtual void restartTeleport();
|
||||
void startTeleport() override;
|
||||
void restartTeleport() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -258,12 +261,12 @@ const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f;
|
||||
std::map<std::string, std::string> LLAgent::sTeleportErrorMessages;
|
||||
std::map<std::string, std::string> LLAgent::sTeleportProgressMessages;
|
||||
|
||||
class LLAgentFriendObserver : public LLFriendObserver
|
||||
class LLAgentFriendObserver final : public LLFriendObserver
|
||||
{
|
||||
public:
|
||||
LLAgentFriendObserver() {}
|
||||
virtual ~LLAgentFriendObserver() {}
|
||||
virtual void changed(U32 mask);
|
||||
LLAgentFriendObserver() = default;
|
||||
virtual ~LLAgentFriendObserver() = default;
|
||||
void changed(U32 mask) override;
|
||||
};
|
||||
|
||||
void LLAgentFriendObserver::changed(U32 mask)
|
||||
@@ -293,7 +296,7 @@ bool LLAgent::isActionAllowed(const LLSD& sdname)
|
||||
{
|
||||
bool allow_agent_voice = false;
|
||||
LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel();
|
||||
if (channel != NULL)
|
||||
if (channel != nullptr)
|
||||
{
|
||||
if (channel->getSessionName().empty() && channel->getSessionID().isNull())
|
||||
{
|
||||
@@ -908,7 +911,7 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
|
||||
if (mRegionp)
|
||||
{
|
||||
// NaCl - Antispam Registry
|
||||
NACLAntiSpamRegistry::purgeAllQueues();
|
||||
if (auto antispam = NACLAntiSpamRegistry::getIfExists()) antispam->resetQueues();
|
||||
// NaCl End
|
||||
|
||||
// We've changed regions, we're now going to change our agent coordinate frame.
|
||||
@@ -1613,12 +1616,14 @@ void LLAgent::startAutoPilotGlobal(
|
||||
mAutoPilotFlyOnStop = FALSE;
|
||||
}
|
||||
|
||||
if (distance > 30.0 && mAutoPilotAllowFlying)
|
||||
bool follow = mAutoPilotBehaviorName == "Follow";
|
||||
|
||||
if (!follow && distance > 30.0 && mAutoPilotAllowFlying)
|
||||
{
|
||||
setFlying(TRUE);
|
||||
}
|
||||
|
||||
if ( distance > 1.f &&
|
||||
if (!follow && distance > 1.f &&
|
||||
mAutoPilotAllowFlying &&
|
||||
heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f))
|
||||
{
|
||||
@@ -1728,6 +1733,14 @@ void LLAgent::stopAutoPilot(BOOL user_cancel)
|
||||
mAutoPilotFinishedCallback(!user_cancel && dist_vec_squared(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < (mAutoPilotStopDistance * mAutoPilotStopDistance), mAutoPilotCallbackData);
|
||||
mAutoPilotFinishedCallback = NULL;
|
||||
}
|
||||
|
||||
// Sit response during follow pilot, now complete, resume follow
|
||||
if (!user_cancel && mAutoPilotBehaviorName == "Sit" && mLeaderID.notNull())
|
||||
{
|
||||
startFollowPilot(mLeaderID, true, gSavedSettings.getF32("SinguFollowDistance"));
|
||||
return;
|
||||
}
|
||||
|
||||
mLeaderID = LLUUID::null;
|
||||
mAutoPilotNoProgressFrameCount = 0;
|
||||
|
||||
@@ -1739,6 +1752,8 @@ void LLAgent::stopAutoPilot(BOOL user_cancel)
|
||||
LLNotificationsUtil::add("CancelledSit");
|
||||
else if (mAutoPilotBehaviorName == "Attach")
|
||||
LLNotificationsUtil::add("CancelledAttach");
|
||||
else if (mAutoPilotBehaviorName == "Follow")
|
||||
LLNotificationsUtil::add("CancelledFollow");
|
||||
else
|
||||
LLNotificationsUtil::add("Cancelled");
|
||||
}
|
||||
@@ -1746,32 +1761,104 @@ void LLAgent::stopAutoPilot(BOOL user_cancel)
|
||||
}
|
||||
|
||||
|
||||
bool LLAgent::getAutoPilotNoProgress() const
|
||||
{
|
||||
return mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped;
|
||||
}
|
||||
|
||||
// Returns necessary agent pitch and yaw changes, radians.
|
||||
//-----------------------------------------------------------------------------
|
||||
// autoPilot()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLAgent::autoPilot(F32 *delta_yaw)
|
||||
{
|
||||
if (mAutoPilot)
|
||||
if (mAutoPilot && isAgentAvatarValid())
|
||||
{
|
||||
bool follow = !mLeaderID.isNull(); //mAutoPilotBehaviorName == "Follow";
|
||||
U8 follow = mAutoPilotBehaviorName == "Follow";
|
||||
if (follow)
|
||||
{
|
||||
LLViewerObject* object = gObjectList.findObject(mLeaderID);
|
||||
if (!object)
|
||||
llassert(mLeaderID.notNull());
|
||||
const auto old_pos = mAutoPilotTargetGlobal;
|
||||
if (auto object = gObjectList.findObject(mLeaderID))
|
||||
{
|
||||
mAutoPilotBehaviorName.clear(); // Nothing left to follow pilot
|
||||
stopAutoPilot();
|
||||
return;
|
||||
}
|
||||
mAutoPilotTargetGlobal = object->getPositionGlobal();
|
||||
if (const auto& av = object->asAvatar()) // Fly if avatar target is flying
|
||||
setFlying(av->mInAir);
|
||||
}
|
||||
|
||||
if (!isAgentAvatarValid()) return;
|
||||
mAutoPilotTargetGlobal = object->getPositionGlobal();
|
||||
if (const auto& av = object->asAvatar()) // Fly if avatar target is flying
|
||||
{
|
||||
setFlying(av->mInAir);
|
||||
if (av->isSitting() && (!rlv_handler_t::isEnabled() || !gRlvHandler.hasBehaviour(RLV_BHVR_SIT)))
|
||||
{
|
||||
if (auto seat = av->getParent())
|
||||
{
|
||||
if (gAgentAvatarp->getParent() == seat)
|
||||
{
|
||||
mAutoPilotNoProgressFrameCount = 0; // We may have incremented this before making it here, reset it
|
||||
return; // We're seated with them, nothing more to do
|
||||
}
|
||||
else if (!getAutoPilotNoProgress())
|
||||
{
|
||||
void handle_object_sit(LLViewerObject*, const LLVector3&);
|
||||
handle_object_sit(static_cast<LLViewerObject*>(seat), LLVector3::zero);
|
||||
follow = 2; // Indicate ground sitting is okay if we can't make it
|
||||
}
|
||||
else return; // If the server just wouldn't let us sit there, we won't be moving, exit here
|
||||
}
|
||||
else // Ground sit, but only if near enough
|
||||
{
|
||||
if (dist_vec(av->getPositionAgent(), getPositionAgent()) <= mAutoPilotStopDistance) // We're close enough, sit.
|
||||
{
|
||||
if (!gAgentAvatarp->isSittingAvatarOnGround())
|
||||
setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
|
||||
mAutoPilotNoProgressFrameCount = 0; // Ground Sit may have incremented this, reset it now
|
||||
return; // We're already sitting on the ground, we have nothing to do
|
||||
}
|
||||
else // We're not close enough yet
|
||||
{
|
||||
if (/*!gAgentAvatarp->isSitting() && */ // RLV takes care of sitting check for us inside standUp
|
||||
getAutoPilotNoProgress()) // Only stand up if we haven't exhausted our no progress frames
|
||||
standUp(); // Unsit if need be, so we can move
|
||||
follow = 2; // Indicate we want to groundsit
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dist_vec(av->getPositionAgent(), getPositionAgent()) <= mAutoPilotStopDistance)
|
||||
{
|
||||
follow = 3; // We're close enough, indicate no walking
|
||||
}
|
||||
|
||||
if (!follow && gAgentAvatarp->mInAir && mAutoPilotAllowFlying)
|
||||
if (gAgentAvatarp->isSitting()) // Leader isn't sitting, standUp if needed
|
||||
{
|
||||
standUp();
|
||||
mAutoPilotNoProgressFrameCount = 0; // Ground Sit may have incremented this, reset it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // We might still have a valid avatar pos
|
||||
{
|
||||
const LLVector3d& get_av_pos(const LLUUID & id);
|
||||
auto pos = get_av_pos(mLeaderID);
|
||||
if (pos.isExactlyZero()) // Default constructed or invalid from server
|
||||
{
|
||||
// Wait for them for more follow pilot
|
||||
return;
|
||||
}
|
||||
standUp(); // Leader not rendered, we mustn't be sitting
|
||||
mAutoPilotNoProgressFrameCount = 0; // Ground Sit may have incremented this, reset it
|
||||
mAutoPilotTargetGlobal = pos;
|
||||
setFlying(true); // Should we fly here? Altitude is often invalid...
|
||||
|
||||
if (dist_vec(mAutoPilotTargetGlobal, getPositionGlobal()) <= mAutoPilotStopDistance)
|
||||
{
|
||||
follow = 3; // We're close enough, indicate no walking
|
||||
}
|
||||
}
|
||||
if (old_pos != mAutoPilotTargetGlobal) // Reset if position changes
|
||||
mAutoPilotNoProgressFrameCount = 0;
|
||||
}
|
||||
|
||||
if (follow % 2 == 0 && gAgentAvatarp->mInAir && mAutoPilotAllowFlying)
|
||||
{
|
||||
setFlying(TRUE);
|
||||
}
|
||||
@@ -1783,12 +1870,15 @@ void LLAgent::autoPilot(F32 *delta_yaw)
|
||||
|
||||
F32 target_dist = direction.magVec();
|
||||
|
||||
if (!follow && target_dist >= mAutoPilotTargetDist)
|
||||
if (follow % 2 == 0 && target_dist >= mAutoPilotTargetDist)
|
||||
{
|
||||
mAutoPilotNoProgressFrameCount++;
|
||||
if (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped)
|
||||
if (getAutoPilotNoProgress())
|
||||
{
|
||||
stopAutoPilot();
|
||||
if (follow) // Well, we tried to reach them, let's just ground sit for now.
|
||||
setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
|
||||
else
|
||||
stopAutoPilot();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1830,6 +1920,7 @@ void LLAgent::autoPilot(F32 *delta_yaw)
|
||||
}
|
||||
|
||||
*delta_yaw = yaw;
|
||||
if (follow == 3) return; // We're close enough, all we need to do is turn
|
||||
|
||||
// Compute when to start slowing down
|
||||
F32 slow_distance;
|
||||
@@ -2501,15 +2592,11 @@ void LLAgent::onAnimStop(const LLUUID& id)
|
||||
}
|
||||
else if (id == ANIM_AGENT_AWAY)
|
||||
{
|
||||
// clearAFK();
|
||||
// [RLVa:KB] - Checked: 2010-05-03 (RLVa-1.2.0g) | Added: RLVa-1.1.0g
|
||||
#ifdef RLV_EXTENSION_CMD_ALLOWIDLE
|
||||
if (!gRlvHandler.hasBehaviour(RLV_BHVR_ALLOWIDLE))
|
||||
clearAFK();
|
||||
#else
|
||||
clearAFK();
|
||||
#endif // RLV_EXTENSION_CMD_ALLOWIDLE
|
||||
// [/RLVa:KB]
|
||||
// clearAFK();
|
||||
}
|
||||
else if (id == ANIM_AGENT_STANDUP)
|
||||
{
|
||||
@@ -2580,7 +2667,7 @@ bool LLAgent::canAccessMaturityInRegion( U64 region_handle ) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLAgent::canAccessMaturityAtGlobal( LLVector3d pos_global ) const
|
||||
bool LLAgent::canAccessMaturityAtGlobal(const LLVector3d& pos_global ) const
|
||||
{
|
||||
U64 region_handle = to_region_handle_global( pos_global.mdV[0], pos_global.mdV[1] );
|
||||
return canAccessMaturityInRegion( region_handle );
|
||||
@@ -2627,7 +2714,7 @@ int LLAgent::convertTextToMaturity(char text)
|
||||
return LLAgentAccess::convertTextToMaturity(text);
|
||||
}
|
||||
|
||||
class LLMaturityPreferencesResponder : public LLHTTPClient::ResponderWithResult
|
||||
class LLMaturityPreferencesResponder final : public LLHTTPClient::ResponderWithResult
|
||||
{
|
||||
LOG_CLASS(LLMaturityPreferencesResponder);
|
||||
public:
|
||||
@@ -2635,12 +2722,10 @@ public:
|
||||
virtual ~LLMaturityPreferencesResponder();
|
||||
|
||||
protected:
|
||||
virtual void httpSuccess();
|
||||
virtual void httpFailure();
|
||||
|
||||
/*virtual*/ char const* getName(void) const { return "LLMaturityPreferencesResponder"; }
|
||||
protected:
|
||||
void httpSuccess() override;
|
||||
void httpFailure() override;
|
||||
|
||||
char const* getName() const override { return "LLMaturityPreferencesResponder"; }
|
||||
private:
|
||||
U8 parseMaturityFromServerResponse(const LLSD &pContent) const;
|
||||
|
||||
@@ -2841,7 +2926,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
|
||||
boost::intrusive_ptr<LLHTTPClient::ResponderWithResult> responderPtr = boost::intrusive_ptr<LLHTTPClient::ResponderWithResult>(new LLMaturityPreferencesResponder(this, pPreferredMaturity, mLastKnownResponseMaturity));
|
||||
|
||||
// If we don't have a region, report it as an error
|
||||
if (getRegion() == NULL)
|
||||
if (getRegion() == nullptr)
|
||||
{
|
||||
responderPtr->failureResult(0U, "region is not defined", LLSD());
|
||||
}
|
||||
@@ -3118,24 +3203,27 @@ void LLAgent::sendAnimationRequests(const uuid_vec_t &anim_ids, EAnimRequest req
|
||||
msg->addUUIDFast(_PREHASH_AgentID, getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
|
||||
|
||||
for (U32 i = 0; i < anim_ids.size(); i++)
|
||||
for (auto anim_id : anim_ids)
|
||||
{
|
||||
if (anim_ids[i].isNull())
|
||||
if (anim_id.isNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
msg->nextBlockFast(_PREHASH_AnimationList);
|
||||
msg->addUUIDFast(_PREHASH_AnimID, (anim_ids[i]) );
|
||||
msg->addUUIDFast(_PREHASH_AnimID, anim_id);
|
||||
msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE);
|
||||
num_valid_anims++;
|
||||
}
|
||||
if (!num_valid_anims)
|
||||
{
|
||||
msg->clearMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList);
|
||||
msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0);
|
||||
if (num_valid_anims)
|
||||
{
|
||||
sendReliableMessage();
|
||||
}
|
||||
msg->addBinaryDataFast(_PREHASH_TypeData, nullptr, 0);
|
||||
|
||||
sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request)
|
||||
@@ -3156,7 +3244,7 @@ void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request)
|
||||
msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE);
|
||||
|
||||
msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList);
|
||||
msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0);
|
||||
msg->addBinaryDataFast(_PREHASH_TypeData, nullptr, 0);
|
||||
sendReliableMessage();
|
||||
}
|
||||
|
||||
@@ -3180,7 +3268,7 @@ void LLAgent::sendAnimationStateReset()
|
||||
msg->addBOOLFast(_PREHASH_StartAnim, FALSE);
|
||||
|
||||
msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList);
|
||||
msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0);
|
||||
msg->addBinaryDataFast(_PREHASH_TypeData, nullptr, 0);
|
||||
sendReliableMessage();
|
||||
}
|
||||
|
||||
@@ -3419,8 +3507,8 @@ void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **)
|
||||
// Remove the group if it already exists remove it and add the new data to pick up changes.
|
||||
LLGroupData gd;
|
||||
gd.mID = group_id;
|
||||
std::vector<LLGroupData>::iterator found_it = std::find(gAgent.mGroups.begin(), gAgent.mGroups.end(), gd);
|
||||
if (found_it != gAgent.mGroups.end())
|
||||
auto found_it = std::find(gAgent.mGroups.cbegin(), gAgent.mGroups.cend(), gd);
|
||||
if (found_it != gAgent.mGroups.cend())
|
||||
{
|
||||
gAgent.mGroups.erase(found_it);
|
||||
if (gAgent.getGroupID() == group_id)
|
||||
@@ -3446,12 +3534,12 @@ void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **)
|
||||
}
|
||||
}
|
||||
|
||||
class LLAgentDropGroupViewerNode : public LLHTTPNode
|
||||
class LLAgentDropGroupViewerNode final : public LLHTTPNode
|
||||
{
|
||||
virtual void post(
|
||||
void post(
|
||||
LLHTTPNode::ResponsePtr response,
|
||||
const LLSD& context,
|
||||
const LLSD& input) const
|
||||
const LLSD& input) const override
|
||||
{
|
||||
|
||||
if (
|
||||
@@ -3478,11 +3566,8 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
|
||||
|
||||
//there is only one set of data in the AgentData block
|
||||
LLSD agent_data = body["AgentData"][0];
|
||||
LLUUID agent_id;
|
||||
LLUUID group_id;
|
||||
|
||||
agent_id = agent_data["AgentID"].asUUID();
|
||||
group_id = agent_data["GroupID"].asUUID();
|
||||
LLUUID agent_id = agent_data["AgentID"].asUUID();
|
||||
LLUUID group_id = agent_data["GroupID"].asUUID();
|
||||
|
||||
if (agent_id != gAgentID)
|
||||
{
|
||||
@@ -3497,8 +3582,8 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
|
||||
// and add the new data to pick up changes.
|
||||
LLGroupData gd;
|
||||
gd.mID = group_id;
|
||||
std::vector<LLGroupData>::iterator found_it = std::find(gAgent.mGroups.begin(), gAgent.mGroups.end(), gd);
|
||||
if (found_it != gAgent.mGroups.end())
|
||||
auto found_it = std::find(gAgent.mGroups.cbegin(), gAgent.mGroups.cend(), gd);
|
||||
if (found_it != gAgent.mGroups.cend())
|
||||
{
|
||||
gAgent.mGroups.erase(found_it);
|
||||
if (gAgent.getGroupID() == group_id)
|
||||
@@ -3569,8 +3654,8 @@ void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **)
|
||||
{
|
||||
need_floater_update = true;
|
||||
// Remove the group if it already exists remove it and add the new data to pick up changes.
|
||||
std::vector<LLGroupData>::iterator found_it = std::find(gAgent.mGroups.begin(), gAgent.mGroups.end(), group);
|
||||
if (found_it != gAgent.mGroups.end())
|
||||
auto found_it = std::find(gAgent.mGroups.cbegin(), gAgent.mGroups.cend(), group);
|
||||
if (found_it != gAgent.mGroups.cend())
|
||||
{
|
||||
gAgent.mGroups.erase(found_it);
|
||||
}
|
||||
@@ -3584,12 +3669,12 @@ void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **)
|
||||
|
||||
}
|
||||
|
||||
class LLAgentGroupDataUpdateViewerNode : public LLHTTPNode
|
||||
class LLAgentGroupDataUpdateViewerNode final : public LLHTTPNode
|
||||
{
|
||||
virtual void post(
|
||||
void post(
|
||||
LLHTTPNode::ResponsePtr response,
|
||||
const LLSD& context,
|
||||
const LLSD& input) const
|
||||
const LLSD& input) const override
|
||||
{
|
||||
LLSD body = input["body"];
|
||||
if(body.has("body"))
|
||||
@@ -3629,8 +3714,8 @@ class LLAgentGroupDataUpdateViewerNode : public LLHTTPNode
|
||||
{
|
||||
need_floater_update = true;
|
||||
// Remove the group if it already exists remove it and add the new data to pick up changes.
|
||||
std::vector<LLGroupData>::iterator found_it = std::find(gAgent.mGroups.begin(), gAgent.mGroups.end(), group);
|
||||
if (found_it != gAgent.mGroups.end())
|
||||
auto found_it = std::find(gAgent.mGroups.cbegin(), gAgent.mGroups.cend(), group);
|
||||
if (found_it != gAgent.mGroups.cend())
|
||||
{
|
||||
gAgent.mGroups.erase(found_it);
|
||||
}
|
||||
@@ -3831,7 +3916,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
|
||||
return;
|
||||
}
|
||||
|
||||
if (gAgentAvatarp->isEditingAppearance())
|
||||
if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance())
|
||||
{
|
||||
// ignore baked textures when in customize mode
|
||||
return;
|
||||
@@ -3962,6 +4047,7 @@ void LLAgent::clearVisualParams(void *data)
|
||||
// protected
|
||||
bool LLAgent::teleportCore(bool is_local)
|
||||
{
|
||||
LL_INFOS("Teleport") << "In teleport core!" << LL_ENDL;
|
||||
if ((TELEPORT_NONE != mTeleportState) && (mTeleportState != TELEPORT_PENDING))
|
||||
{
|
||||
LL_WARNS() << "Attempt to teleport when already teleporting." << LL_ENDL;
|
||||
@@ -3979,7 +4065,7 @@ bool LLAgent::teleportCore(bool is_local)
|
||||
// Stop all animation before actual teleporting
|
||||
if (isAgentAvatarValid())
|
||||
{
|
||||
for ( LLVOAvatar::AnimIterator anim_it= gAgentAvatarp->mPlayingAnimations.begin();
|
||||
for ( auto anim_it= gAgentAvatarp->mPlayingAnimations.begin();
|
||||
anim_it != gAgentAvatarp->mPlayingAnimations.end();
|
||||
++anim_it)
|
||||
{
|
||||
@@ -3998,8 +4084,7 @@ bool LLAgent::teleportCore(bool is_local)
|
||||
LLFloaterWorldMap::hide();
|
||||
|
||||
// hide land floater too - it'll be out of date
|
||||
if (LLFloaterLand::findInstance())
|
||||
LLFloaterLand::hideInstance();
|
||||
if (LLFloaterLand::findInstance()) LLFloaterLand::hideInstance();
|
||||
|
||||
LLViewerParcelMgr::getInstance()->deselectLand();
|
||||
LLViewerMediaFocus::getInstance()->clearFocus();
|
||||
@@ -4773,7 +4858,7 @@ void LLAgent::sendAgentSetAppearance()
|
||||
// This means the baked texture IDs on the server will be untouched.
|
||||
// Once all textures are baked, another AvatarAppearance message will be sent to update the TEs
|
||||
msg->nextBlockFast(_PREHASH_ObjectData);
|
||||
gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, NULL, 0);
|
||||
gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, nullptr, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -4796,9 +4881,7 @@ void LLAgent::sendAgentSetAppearance()
|
||||
}
|
||||
|
||||
LL_INFOS() << "Avatar XML num VisualParams transmitted = " << transmitted_params << LL_ENDL;
|
||||
if(transmitted_params < 218) {
|
||||
LLNotificationsUtil::add("SGIncompleteAppearance");
|
||||
}
|
||||
if (transmitted_params < 218) LLNotificationsUtil::add("SGIncompleteAppearance");
|
||||
sendReliableMessage();
|
||||
}
|
||||
|
||||
@@ -4813,8 +4896,96 @@ void LLAgent::sendAgentDataUpdateRequest()
|
||||
|
||||
void LLAgent::sendAgentUserInfoRequest()
|
||||
{
|
||||
if(getID().isNull())
|
||||
std::string cap;
|
||||
|
||||
if (getID().isNull())
|
||||
return; // not logged in
|
||||
|
||||
if (mRegionp)
|
||||
cap = mRegionp->getCapability("UserInfo");
|
||||
|
||||
if (!cap.empty())
|
||||
{
|
||||
LLHTTPClient::get(cap, new LLCoroResponder(
|
||||
boost::bind(&LLAgent::requestAgentUserInfoCoro, this, _1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sendAgentUserInfoRequestMessage();
|
||||
}
|
||||
}
|
||||
|
||||
void LLAgent::requestAgentUserInfoCoro(const LLCoroResponder& responder)
|
||||
{
|
||||
const auto& result = responder.getContent();
|
||||
const auto& status = responder.getStatus();
|
||||
|
||||
if (!responder.isGoodStatus(status))
|
||||
{
|
||||
LL_WARNS("UserInfo") << "Failed to get user information: " << result["message"] << "Status " << status << " Reason: " << responder.getReason() << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
bool im_via_email;
|
||||
bool is_verified_email;
|
||||
std::string email;
|
||||
std::string dir_visibility;
|
||||
|
||||
im_via_email = result["im_via_email"].asBoolean();
|
||||
is_verified_email = result["is_verified"].asBoolean();
|
||||
email = result["email"].asString();
|
||||
dir_visibility = result["directory_visibility"].asString();
|
||||
|
||||
// TODO: This should probably be changed. I'm not entirely comfortable
|
||||
// having LLAgent interact directly with the UI in this way.
|
||||
LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email, is_verified_email);
|
||||
LLFloaterPostcard::updateUserInfo(email);
|
||||
}
|
||||
|
||||
void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility)
|
||||
{
|
||||
std::string cap;
|
||||
|
||||
if (getID().isNull())
|
||||
return; // not logged in
|
||||
|
||||
if (mRegionp)
|
||||
cap = mRegionp->getCapability("UserInfo");
|
||||
|
||||
if (!cap.empty())
|
||||
{
|
||||
LLSD body(LLSDMap
|
||||
("dir_visibility", LLSD::String(directory_visibility))
|
||||
("im_via_email", LLSD::Boolean(im_via_email)));
|
||||
LLHTTPClient::post(cap, body, new LLCoroResponder(
|
||||
boost::bind(&LLAgent::updateAgentUserInfoCoro, this, _1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sendAgentUpdateUserInfoMessage(im_via_email, directory_visibility);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAgent::updateAgentUserInfoCoro(const LLCoroResponder& responder)
|
||||
{
|
||||
const auto& result = responder.getContent();
|
||||
const auto& status = responder.getStatus();
|
||||
|
||||
if (!responder.isGoodStatus(status))
|
||||
{
|
||||
LL_WARNS("UserInfo") << "Failed to set user information." << LL_ENDL;
|
||||
}
|
||||
else if (!result["success"].asBoolean())
|
||||
{
|
||||
LL_WARNS("UserInfo") << "Failed to set user information: " << result["message"] << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
// deprecated:
|
||||
// May be removed when UserInfo cap propagates to all simhosts in grid
|
||||
void LLAgent::sendAgentUserInfoRequestMessage()
|
||||
{
|
||||
gMessageSystem->newMessageFast(_PREHASH_UserInfoRequest);
|
||||
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID());
|
||||
@@ -4822,6 +4993,21 @@ void LLAgent::sendAgentUserInfoRequest()
|
||||
sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAgent::sendAgentUpdateUserInfoMessage(bool im_via_email, const std::string& directory_visibility)
|
||||
{
|
||||
gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo);
|
||||
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID());
|
||||
gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID());
|
||||
gMessageSystem->nextBlockFast(_PREHASH_UserData);
|
||||
gMessageSystem->addBOOLFast(_PREHASH_IMViaEMail, im_via_email);
|
||||
gMessageSystem->addString("DirectoryVisibility", directory_visibility);
|
||||
gAgent.sendReliableMessage();
|
||||
|
||||
}
|
||||
// end deprecated
|
||||
//------
|
||||
|
||||
void LLAgent::observeFriends()
|
||||
{
|
||||
if(!mFriendObserver)
|
||||
@@ -4889,18 +5075,6 @@ const void LLAgent::getTeleportSourceSLURL(LLSLURL& slurl) const
|
||||
slurl = *mTeleportSourceSLURL;
|
||||
}
|
||||
|
||||
void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility )
|
||||
{
|
||||
gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo);
|
||||
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
|
||||
gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID());
|
||||
gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID());
|
||||
gMessageSystem->nextBlockFast(_PREHASH_UserData);
|
||||
gMessageSystem->addBOOLFast(_PREHASH_IMViaEMail, im_via_email);
|
||||
gMessageSystem->addString("DirectoryVisibility", directory_visibility);
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAgent::dumpGroupInfo()
|
||||
{
|
||||
LL_INFOS() << "group " << mGroupName << LL_ENDL;
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
#ifndef LL_LLAGENT_H
|
||||
#define LL_LLAGENT_H
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "indra_constants.h"
|
||||
#include "llevent.h" // LLObservable base class
|
||||
#include "llagentconstants.h"
|
||||
@@ -46,7 +44,6 @@
|
||||
#include "llinventorymodel.h"
|
||||
#include "v3dmath.h"
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
@@ -70,6 +67,7 @@ class LLAgentAccess;
|
||||
class LLSLURL;
|
||||
class LLSimInfo;
|
||||
class LLTeleportRequest;
|
||||
struct LLCoroResponder;
|
||||
|
||||
typedef boost::shared_ptr<LLTeleportRequest> LLTeleportRequestPtr;
|
||||
|
||||
@@ -100,7 +98,7 @@ struct LLGroupData
|
||||
//------------------------------------------------------------------------
|
||||
// LLAgent
|
||||
//------------------------------------------------------------------------
|
||||
class LLAgent : public LLOldEvents::LLObservable
|
||||
class LLAgent final : public LLOldEvents::LLObservable
|
||||
{
|
||||
LOG_CLASS(LLAgent);
|
||||
|
||||
@@ -248,7 +246,7 @@ public:
|
||||
void changeParcels(); // called by LLViewerParcelMgr when we cross a parcel boundary
|
||||
|
||||
// Register a boost callback to be called when the agent changes parcels
|
||||
typedef boost::function<void()> parcel_changed_callback_t;
|
||||
typedef std::function<void()> parcel_changed_callback_t;
|
||||
boost::signals2::connection addParcelChangedCallback(parcel_changed_callback_t);
|
||||
|
||||
private:
|
||||
@@ -593,13 +591,14 @@ public:
|
||||
public:
|
||||
BOOL getAutoPilot() const { return mAutoPilot; }
|
||||
LLVector3d getAutoPilotTargetGlobal() const { return mAutoPilotTargetGlobal; }
|
||||
LLUUID getAutoPilotLeaderID() const { return mLeaderID; }
|
||||
const LLUUID& getAutoPilotLeaderID() const { return mLeaderID; }
|
||||
F32 getAutoPilotStopDistance() const { return mAutoPilotStopDistance; }
|
||||
F32 getAutoPilotTargetDist() const { return mAutoPilotTargetDist; }
|
||||
BOOL getAutoPilotUseRotation() const { return mAutoPilotUseRotation; }
|
||||
LLVector3 getAutoPilotTargetFacing() const { return mAutoPilotTargetFacing; }
|
||||
F32 getAutoPilotRotationThreshold() const { return mAutoPilotRotationThreshold; }
|
||||
std::string getAutoPilotBehaviorName() const { return mAutoPilotBehaviorName; }
|
||||
const std::string& getAutoPilotBehaviorName() const { return mAutoPilotBehaviorName; }
|
||||
bool getAutoPilotNoProgress() const;
|
||||
|
||||
void startAutoPilotGlobal(const LLVector3d &pos_global,
|
||||
const std::string& behavior_name = std::string(),
|
||||
@@ -785,7 +784,7 @@ public:
|
||||
void requestEnterGodMode();
|
||||
void requestLeaveGodMode();
|
||||
|
||||
typedef boost::function<void (U8)> god_level_change_callback_t;
|
||||
typedef std::function<void (U8)> god_level_change_callback_t;
|
||||
typedef boost::signals2::signal<void (U8)> god_level_change_signal_t;
|
||||
typedef boost::signals2::connection god_level_change_slot_t;
|
||||
|
||||
@@ -807,7 +806,7 @@ public:
|
||||
bool canAccessMature() const;
|
||||
bool canAccessAdult() const;
|
||||
bool canAccessMaturityInRegion( U64 region_handle ) const;
|
||||
bool canAccessMaturityAtGlobal( LLVector3d pos_global ) const;
|
||||
bool canAccessMaturityAtGlobal( const LLVector3d& pos_global ) const;
|
||||
bool prefersPG() const;
|
||||
bool prefersMature() const;
|
||||
bool prefersAdult() const;
|
||||
@@ -964,9 +963,17 @@ public:
|
||||
void sendAgentSetAppearance();
|
||||
void sendAgentDataUpdateRequest();
|
||||
void sendAgentUserInfoRequest();
|
||||
// IM to Email and Online visibility
|
||||
|
||||
// IM to Email and Online visibility
|
||||
void sendAgentUpdateUserInfo(bool im_to_email, const std::string& directory_visibility);
|
||||
|
||||
private:
|
||||
void requestAgentUserInfoCoro(const LLCoroResponder& responder);
|
||||
void updateAgentUserInfoCoro(const LLCoroResponder& responder);
|
||||
// DEPRECATED: may be removed when User Info cap propagates
|
||||
void sendAgentUserInfoRequestMessage();
|
||||
void sendAgentUpdateUserInfoMessage(bool im_via_email, const std::string& directory_visibility);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Receive
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
@@ -289,11 +289,6 @@ LLAgentCamera::~LLAgentCamera()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera)
|
||||
{
|
||||
if (gAgent.getAutoPilot())
|
||||
{
|
||||
gAgent.stopAutoPilot(TRUE);
|
||||
}
|
||||
|
||||
LLSelectMgr::getInstance()->unhighlightAll();
|
||||
|
||||
// By popular request, keep land selection while walking around. JC
|
||||
@@ -2517,13 +2512,13 @@ void LLAgentCamera::changeCameraToCustomizeAvatar()
|
||||
gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START);
|
||||
gAgent.setCustomAnim(TRUE);
|
||||
gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE);
|
||||
}
|
||||
LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE);
|
||||
LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE);
|
||||
|
||||
if (turn_motion)
|
||||
{
|
||||
// delay camera animation long enough to play through turn animation
|
||||
setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP);
|
||||
if (turn_motion)
|
||||
{
|
||||
// delay camera animation long enough to play through turn animation
|
||||
setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
// <edit>
|
||||
|
||||
@@ -35,13 +35,12 @@
|
||||
#include "llviewerregion.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Classes for AISv3 support.
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
class AISCommand : public LLHTTPClient::ResponderWithResult
|
||||
class AISCommand final : public LLHTTPClient::ResponderWithCompleted
|
||||
{
|
||||
public:
|
||||
typedef boost::function<void()> command_func_type;
|
||||
@@ -60,35 +59,28 @@ public:
|
||||
(mCommandFunc = func)();
|
||||
}
|
||||
|
||||
char const* getName(void) const
|
||||
char const* getName(void) const override
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
void markComplete()
|
||||
{
|
||||
mRetryPolicy->onSuccess();
|
||||
}
|
||||
|
||||
protected:
|
||||
/* virtual */
|
||||
void httpSuccess()
|
||||
{
|
||||
// Command func holds a reference to self, need to release it
|
||||
// after a success or final failure.
|
||||
mCommandFunc = no_op;
|
||||
AISAPI::InvokeAISCommandCoro(this, getURL(), mTargetId, getContent(), mCompletionFunc, (AISAPI::COMMAND_TYPE)mType);
|
||||
mRetryPolicy->onSuccess();
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void httpFailure()
|
||||
void malformedResponse() { mStatus = HTTP_INTERNAL_ERROR_OTHER; mReason = llformat("Malformed response contents (original code: %d)", mStatus); }
|
||||
|
||||
bool onFailure()
|
||||
{
|
||||
LL_WARNS("Inventory") << dumpResponse() << LL_ENDL;
|
||||
S32 status = getStatus();
|
||||
const AIHTTPReceivedHeaders& headers = getResponseHeaders();
|
||||
mRetryPolicy->onFailure(status, headers);
|
||||
bool retry = mStatus != HTTP_INTERNAL_ERROR_OTHER && mStatus != 410; // We handle these and stop
|
||||
LL_WARNS("Inventory") << "Inventory error: " << dumpResponse() << LL_ENDL;
|
||||
if (retry) mRetryPolicy->onFailure(mStatus, getResponseHeaders());
|
||||
F32 seconds_to_wait;
|
||||
if (mRetryPolicy->shouldRetry(seconds_to_wait))
|
||||
if (retry && mRetryPolicy->shouldRetry(seconds_to_wait))
|
||||
{
|
||||
doAfterInterval(mCommandFunc,seconds_to_wait);
|
||||
}
|
||||
@@ -99,6 +91,13 @@ protected:
|
||||
// *TODO: Notify user? This seems bad.
|
||||
mCommandFunc = no_op;
|
||||
}
|
||||
return retry;
|
||||
}
|
||||
|
||||
protected:
|
||||
void httpCompleted() override
|
||||
{
|
||||
AISAPI::InvokeAISCommandCoro(this, getURL(), mTargetId, getContent(), mCompletionFunc, (AISAPI::COMMAND_TYPE)mType);
|
||||
}
|
||||
|
||||
command_func_type mCommandFunc;
|
||||
@@ -313,31 +312,97 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t
|
||||
boost::intrusive_ptr< AISCommand > responder = new AISCommand(UPDATEITEM, "UpdateItem",itemId, callback);
|
||||
responder->run(boost::bind(&LLHTTPClient::patch, url, updates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0));
|
||||
}
|
||||
void AISAPI::InvokeAISCommandCoro(LLHTTPClient::ResponderWithResult* responder,
|
||||
std::string url,
|
||||
void AISAPI::InvokeAISCommandCoro(AISCommand* responder,
|
||||
std::string url,
|
||||
LLUUID targetId, LLSD result, completion_t callback, COMMAND_TYPE type)
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
|
||||
|
||||
auto status = responder->getStatus();
|
||||
|
||||
if (!responder->isGoodStatus(status) || !result.isMap())
|
||||
{
|
||||
if (!result.isMap())
|
||||
{
|
||||
responder->failureResult(400, "Malformed response contents", result);
|
||||
return;
|
||||
responder->malformedResponse();
|
||||
}
|
||||
((AISCommand*)responder)->markComplete();
|
||||
else if (status == 410) //GONE
|
||||
{
|
||||
// Item does not exist or was already deleted from server.
|
||||
// parent folder is out of sync
|
||||
if (type == REMOVECATEGORY)
|
||||
{
|
||||
LLViewerInventoryCategory *cat = gInventory.getCategory(targetId);
|
||||
if (cat)
|
||||
{
|
||||
LL_WARNS("Inventory") << "Purge failed for '" << cat->getName()
|
||||
<< "' local version:" << cat->getVersion()
|
||||
<< " since folder no longer exists at server. Descendent count: server == " << cat->getDescendentCount()
|
||||
<< ", viewer == " << cat->getViewerDescendentCount()
|
||||
<< LL_ENDL;
|
||||
gInventory.fetchDescendentsOf(cat->getParentUUID());
|
||||
// Note: don't delete folder here - contained items will be deparented (or deleted)
|
||||
// and since we are clearly out of sync we can't be sure we won't get rid of something we need.
|
||||
// For example folder could have been moved or renamed with items intact, let it fetch first.
|
||||
}
|
||||
}
|
||||
else if (type == REMOVEITEM)
|
||||
{
|
||||
LLViewerInventoryItem *item = gInventory.getItem(targetId);
|
||||
if (item)
|
||||
{
|
||||
LL_WARNS("Inventory") << "Purge failed for '" << item->getName()
|
||||
<< "' since item no longer exists at server." << LL_ENDL;
|
||||
gInventory.fetchDescendentsOf(item->getParentUUID());
|
||||
// since item not on the server and exists at viewer, so it needs an update at the least,
|
||||
// so delete it, in worst case item will be refetched with new params.
|
||||
gInventory.onObjectDeletedFromServer(targetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Keep these statuses accounted for in the responder too
|
||||
if (responder->onFailure()) // If we're retrying, exit early.
|
||||
return;
|
||||
}
|
||||
else responder->markComplete();
|
||||
|
||||
gInventory.onAISUpdateReceived("AISCommand", result);
|
||||
|
||||
if (callback && callback != nullptr)
|
||||
{
|
||||
LLUUID id(LLUUID::null);
|
||||
|
||||
if (result.has("category_id") && (type == COPYLIBRARYCATEGORY))
|
||||
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: Catznip-3.7
|
||||
uuid_list_t ids;
|
||||
switch (type)
|
||||
{
|
||||
id = result["category_id"];
|
||||
case COPYLIBRARYCATEGORY:
|
||||
if (result.has("category_id"))
|
||||
{
|
||||
ids.insert(result["category_id"]);
|
||||
}
|
||||
break;
|
||||
case COPYINVENTORY:
|
||||
{
|
||||
AISUpdate::parseUUIDArray(result, "_created_items", ids);
|
||||
AISUpdate::parseUUIDArray(result, "_created_categories", ids);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
callback(id);
|
||||
// If we were feeling daring we'd call LLInventoryCallback::fire for every item but it would take additional work to investigate whether all LLInventoryCallback derived classes
|
||||
// were designed to handle multiple fire calls (with legacy link creation only one would ever fire per link creation) so we'll be cautious and only call for the first one for now
|
||||
// (note that the LL code as written below will always call fire once with the NULL UUID for anything but CopyLibraryCategoryCommand so even the above is an improvement)
|
||||
callback( (!ids.empty()) ? *ids.begin() : LLUUID::null);
|
||||
// [/SL:KB]
|
||||
// LLUUID id(LLUUID::null);
|
||||
//
|
||||
// if (result.has("category_id") && (type == COPYLIBRARYCATEGORY))
|
||||
// {
|
||||
// id = result["category_id"];
|
||||
// }
|
||||
//
|
||||
// callback(id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -374,18 +439,17 @@ void AISUpdate::parseMeta(const LLSD& update)
|
||||
// parse _categories_removed -> mObjectsDeletedIds
|
||||
uuid_list_t cat_ids;
|
||||
parseUUIDArray(update,"_categories_removed",cat_ids);
|
||||
for (uuid_list_t::const_iterator it = cat_ids.begin();
|
||||
it != cat_ids.end(); ++it)
|
||||
for (auto cat_id : cat_ids)
|
||||
{
|
||||
LLViewerInventoryCategory *cat = gInventory.getCategory(*it);
|
||||
LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
|
||||
if(cat)
|
||||
{
|
||||
mCatDescendentDeltas[cat->getParentUUID()]--;
|
||||
mObjectsDeletedIds.insert(*it);
|
||||
mObjectsDeletedIds.insert(cat_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Inventory") << "removed category not found " << *it << LL_ENDL;
|
||||
LL_WARNS("Inventory") << "removed category not found " << cat_id << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,36 +457,34 @@ void AISUpdate::parseMeta(const LLSD& update)
|
||||
uuid_list_t item_ids;
|
||||
parseUUIDArray(update,"_category_items_removed",item_ids);
|
||||
parseUUIDArray(update,"_removed_items",item_ids);
|
||||
for (uuid_list_t::const_iterator it = item_ids.begin();
|
||||
it != item_ids.end(); ++it)
|
||||
for (auto item_id : item_ids)
|
||||
{
|
||||
LLViewerInventoryItem *item = gInventory.getItem(*it);
|
||||
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||
if(item)
|
||||
{
|
||||
mCatDescendentDeltas[item->getParentUUID()]--;
|
||||
mObjectsDeletedIds.insert(*it);
|
||||
mObjectsDeletedIds.insert(item_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Inventory") << "removed item not found " << *it << LL_ENDL;
|
||||
LL_WARNS("Inventory") << "removed item not found " << item_id << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
// parse _broken_links_removed -> mObjectsDeletedIds
|
||||
uuid_list_t broken_link_ids;
|
||||
parseUUIDArray(update,"_broken_links_removed",broken_link_ids);
|
||||
for (uuid_list_t::const_iterator it = broken_link_ids.begin();
|
||||
it != broken_link_ids.end(); ++it)
|
||||
for (auto broken_link_id : broken_link_ids)
|
||||
{
|
||||
LLViewerInventoryItem *item = gInventory.getItem(*it);
|
||||
LLViewerInventoryItem *item = gInventory.getItem(broken_link_id);
|
||||
if(item)
|
||||
{
|
||||
mCatDescendentDeltas[item->getParentUUID()]--;
|
||||
mObjectsDeletedIds.insert(*it);
|
||||
mObjectsDeletedIds.insert(broken_link_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Inventory") << "broken link not found " << *it << LL_ENDL;
|
||||
LL_WARNS("Inventory") << "broken link not found " << broken_link_id << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,11 +734,9 @@ void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uui
|
||||
{
|
||||
if (content.has(name))
|
||||
{
|
||||
for(LLSD::array_const_iterator it = content[name].beginArray(),
|
||||
end = content[name].endArray();
|
||||
it != end; ++it)
|
||||
for (auto& id : content[name].array())
|
||||
{
|
||||
ids.insert((*it).asUUID());
|
||||
ids.insert(id.asUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -766,7 +826,7 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories)
|
||||
|
||||
void AISUpdate::doUpdate()
|
||||
{
|
||||
// Do version/descendent accounting.
|
||||
// Do version/descendant accounting.
|
||||
for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin();
|
||||
catit != mCatDescendentDeltas.end(); ++catit)
|
||||
{
|
||||
@@ -787,7 +847,7 @@ void AISUpdate::doUpdate()
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we have a known descendent count, set that now.
|
||||
// If we have a known descendant count, set that now.
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
|
||||
if (cat)
|
||||
{
|
||||
@@ -824,7 +884,7 @@ void AISUpdate::doUpdate()
|
||||
LLUUID category_id(update_it->first);
|
||||
LLPointer<LLViewerInventoryCategory> new_category = update_it->second;
|
||||
// Since this is a copy of the category *before* the accounting update, above,
|
||||
// we need to transfer back the updated version/descendent count.
|
||||
// we need to transfer back the updated version/descendant count.
|
||||
LLViewerInventoryCategory* curr_cat = gInventory.getCategory(new_category->getUUID());
|
||||
if (!curr_cat)
|
||||
{
|
||||
@@ -868,21 +928,19 @@ void AISUpdate::doUpdate()
|
||||
}
|
||||
|
||||
// DELETE OBJECTS
|
||||
for (uuid_list_t::const_iterator del_it = mObjectsDeletedIds.begin();
|
||||
del_it != mObjectsDeletedIds.end(); ++del_it)
|
||||
for (auto deleted_id : mObjectsDeletedIds)
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "deleted item " << *del_it << LL_ENDL;
|
||||
gInventory.onObjectDeletedFromServer(*del_it, false, false, false);
|
||||
LL_DEBUGS("Inventory") << "deleted item " << deleted_id << LL_ENDL;
|
||||
gInventory.onObjectDeletedFromServer(deleted_id, false, false, false);
|
||||
}
|
||||
|
||||
// TODO - how can we use this version info? Need to be sure all
|
||||
// changes are going through AIS first, or at least through
|
||||
// something with a reliable responder.
|
||||
for (uuid_int_map_t::iterator ucv_it = mCatVersionsUpdated.begin();
|
||||
ucv_it != mCatVersionsUpdated.end(); ++ucv_it)
|
||||
for (auto& ucv_it : mCatVersionsUpdated)
|
||||
{
|
||||
const LLUUID id = ucv_it->first;
|
||||
S32 version = ucv_it->second;
|
||||
const LLUUID id = ucv_it.first;
|
||||
S32 version = ucv_it.second;
|
||||
LLViewerInventoryCategory *cat = gInventory.getCategory(id);
|
||||
LL_DEBUGS("Inventory") << "cat version update " << cat->getName() << " to version " << cat->getVersion() << LL_ENDL;
|
||||
if (cat->getVersion() != version)
|
||||
@@ -898,7 +956,16 @@ void AISUpdate::doUpdate()
|
||||
// inventory COF is maintained on the viewer through calls to
|
||||
// LLInventoryModel::accountForUpdate when a changing operation
|
||||
// is performed. This occasionally gets out of sync however.
|
||||
cat->setVersion(version);
|
||||
if (version != LLViewerInventoryCategory::VERSION_UNKNOWN)
|
||||
{
|
||||
cat->setVersion(version);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We do not account for update if version is UNKNOWN, so we shouldn't rise version
|
||||
// either or viewer will get stuck on descendants count -1, try to refetch folder instead
|
||||
cat->fetch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ private:
|
||||
static std::string getInvCap();
|
||||
static std::string getLibCap();
|
||||
|
||||
static void InvokeAISCommandCoro( LLHTTPClient::ResponderWithResult* responder,
|
||||
static void InvokeAISCommandCoro(class AISCommand* responder,
|
||||
std::string url, LLUUID targetId, LLSD body,
|
||||
completion_t callback, COMMAND_TYPE type);
|
||||
};
|
||||
@@ -84,7 +84,10 @@ public:
|
||||
void parseUpdate(const LLSD& update);
|
||||
void parseMeta(const LLSD& update);
|
||||
void parseContent(const LLSD& update);
|
||||
void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
|
||||
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: Catznip-3.7
|
||||
static void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
|
||||
// [/SL:KB]
|
||||
// void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
|
||||
void parseLink(const LLSD& link_map);
|
||||
void parseItem(const LLSD& link_map);
|
||||
void parseCategory(const LLSD& link_map);
|
||||
|
||||
@@ -4184,7 +4184,7 @@ LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, L
|
||||
// 2) Stuff with requests via makeLink and makeCopy
|
||||
// 3) Call dispatch()
|
||||
// 4) Let the LLPointer go out of scope.
|
||||
class LLCreateLegacyOutfit : public LLBoostFuncInventoryCallbackFireOnce
|
||||
class LLCreateLegacyOutfit final : public LLBoostFuncInventoryCallbackFireOnce
|
||||
{
|
||||
public:
|
||||
LLCreateLegacyOutfit(const LLUUID& folder_id, inventory_func_type fire_func, nullary_func_type destroy_func = no_op) :
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "llagent.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llagentwearables.h"
|
||||
#include "llimprocessing.h"
|
||||
#include "llwindow.h"
|
||||
#include "llviewerstats.h"
|
||||
#include "llmarketplacefunctions.h"
|
||||
@@ -95,6 +96,7 @@
|
||||
// Linden library includes
|
||||
#include "llavatarnamecache.h"
|
||||
#include "lldiriterator.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "llmemory.h"
|
||||
#include "llprimitive.h"
|
||||
@@ -189,6 +191,7 @@
|
||||
#include "llviewerthrottle.h"
|
||||
#include "llparcel.h"
|
||||
#include "llviewerassetstats.h"
|
||||
#include "NACLantispam.h"
|
||||
|
||||
#include "llmainlooprepeater.h"
|
||||
|
||||
@@ -428,27 +431,6 @@ static void ui_audio_callback(const LLUUID& uuid)
|
||||
}
|
||||
}
|
||||
|
||||
void request_initial_instant_messages()
|
||||
{
|
||||
static BOOL requested = FALSE;
|
||||
if (!requested
|
||||
&& gMessageSystem
|
||||
&& LLMuteList::getInstance()->isLoaded()
|
||||
&& isAgentAvatarValid())
|
||||
{
|
||||
// Auto-accepted inventory items may require the avatar object
|
||||
// to build a correct name. Likewise, inventory offers from
|
||||
// muted avatars require the mute list to properly mute.
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
gAgent.sendReliableMessage();
|
||||
requested = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Use these strictly for things that are constructed at startup,
|
||||
// or for things that are performance critical. JC
|
||||
static void settings_to_globals()
|
||||
@@ -2287,7 +2269,9 @@ bool LLAppViewer::initConfiguration()
|
||||
LL_INFOS() << "Loading settings file list" << settings_file_list << LL_ENDL;
|
||||
if (0 == settings_control.loadFromFile(settings_file_list))
|
||||
{
|
||||
LL_ERRS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL;
|
||||
OSMessageBox("Cannot load default configuration file " + settings_file_list + " The installation may be corrupted.",
|
||||
LLStringUtil::null,OSMB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
mSettingsLocationList = settings_control.getLLSD("Locations");
|
||||
@@ -4046,7 +4030,7 @@ void LLAppViewer::idle()
|
||||
// here.
|
||||
{
|
||||
LAZY_FT("request_initial_instant_messages");
|
||||
request_initial_instant_messages();
|
||||
LLIMProcessing::requestOfflineMessages();
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
@@ -4177,6 +4161,7 @@ void LLAppViewer::idle()
|
||||
// floating throughout the various object lists.
|
||||
//
|
||||
idleNameCache();
|
||||
if (gAgent.getRegion()) LLExperienceCache::instance().idleCoro();
|
||||
|
||||
gFrameStats.start(LLFrameStats::IDLE_NETWORK);
|
||||
stop_glerror();
|
||||
@@ -4205,6 +4190,7 @@ void LLAppViewer::idle()
|
||||
|
||||
gIdleCallbacks.callFunctions();
|
||||
gInventory.idleNotifyObservers();
|
||||
if (auto antispam = NACLAntiSpamRegistry::getIfExists()) antispam->idle();
|
||||
}
|
||||
|
||||
// Metrics logging (LLViewerAssetStats, etc.)
|
||||
@@ -4841,6 +4827,12 @@ void LLAppViewer::disconnectViewer()
|
||||
}
|
||||
|
||||
saveNameCache();
|
||||
if (LLExperienceCache::instanceExists())
|
||||
{
|
||||
// TODO: LLExperienceCache::cleanup() logic should be moved to
|
||||
// cleanupSingleton().
|
||||
LLExperienceCache::instance().cleanup();
|
||||
}
|
||||
|
||||
// close inventory interface, close all windows
|
||||
LLPanelMainInventory::cleanup();
|
||||
|
||||
@@ -171,6 +171,7 @@ void LLAssetUploadQueue::request(LLAssetUploadQueueSupplier** supplier)
|
||||
body["item_id"] = data.mItemId;
|
||||
body["is_script_running"] = data.mIsRunning;
|
||||
body["target"] = data.mIsTargetMono? "mono" : "lsl2";
|
||||
body["experience"] = data.mExperienceId;
|
||||
|
||||
std::string url = "";
|
||||
LLViewerObject* object = gObjectList.findObject(data.mTaskId);
|
||||
@@ -194,7 +195,8 @@ void LLAssetUploadQueue::queue(const std::string& filename,
|
||||
const LLUUID& queue_id,
|
||||
U8* script_data,
|
||||
U32 data_size,
|
||||
std::string script_name)
|
||||
std::string script_name,
|
||||
const LLUUID& experience_id)
|
||||
{
|
||||
UploadData data;
|
||||
data.mTaskId = task_id;
|
||||
@@ -206,6 +208,7 @@ void LLAssetUploadQueue::queue(const std::string& filename,
|
||||
data.mData = script_data;
|
||||
data.mDataSize = data_size;
|
||||
data.mScriptName = script_name;
|
||||
data.mExperienceId = experience_id;
|
||||
|
||||
mQueue.push_back(data);
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ public:
|
||||
const LLUUID& queue_id,
|
||||
U8* data,
|
||||
U32 data_size,
|
||||
std::string script_name);
|
||||
std::string script_name,
|
||||
const LLUUID& experience_id);
|
||||
|
||||
bool isEmpty() const {return mQueue.empty();}
|
||||
|
||||
@@ -75,6 +76,7 @@ private:
|
||||
U8* mData;
|
||||
U32 mDataSize;
|
||||
std::string mScriptName;
|
||||
LLUUID mExperienceId;
|
||||
};
|
||||
|
||||
// Ownership of mSupplier passed to currently waiting responder
|
||||
|
||||
@@ -1197,7 +1197,7 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri
|
||||
calling_card_folder_id);
|
||||
|
||||
LLSD args;
|
||||
args["TO_NAME"] = target_name;
|
||||
args["TO_NAME"] = getSLURL(target_id);
|
||||
|
||||
LLSD payload;
|
||||
payload["from_id"] = target_id;
|
||||
|
||||
@@ -293,19 +293,19 @@ bool LLCommandLineParser::parseAndStoreResults(po::command_line_parser& clp)
|
||||
po::basic_parsed_options<char> opts = clp.run();
|
||||
po::store(opts, gVariableMap);
|
||||
}
|
||||
catch(po::error& e)
|
||||
catch (const po::error& e)
|
||||
{
|
||||
LL_WARNS() << "Caught Error:" << e.what() << LL_ENDL;
|
||||
mErrorMsg = e.what();
|
||||
return false;
|
||||
}
|
||||
catch(LLCLPError& e)
|
||||
catch (const LLCLPError& e)
|
||||
{
|
||||
LL_WARNS() << "Caught Error:" << e.what() << LL_ENDL;
|
||||
mErrorMsg = e.what();
|
||||
return false;
|
||||
}
|
||||
catch(LLCLPLastOption&)
|
||||
catch (const LLCLPLastOption&)
|
||||
{
|
||||
// This exception means a token was read after an option
|
||||
// that must be the last option was reached (see url and slurl options)
|
||||
@@ -354,18 +354,58 @@ bool LLCommandLineParser::parseCommandLine(int argc, char **argv)
|
||||
return parseAndStoreResults(clp);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// - Break out this funky parsing logic into separate method
|
||||
// - Unit-test it with tests like LLStringUtil::getTokens() (the command-line
|
||||
// overload that supports quoted tokens)
|
||||
// - Unless this logic offers significant semantic benefits, replace it with
|
||||
// LLStringUtil::getTokens(). This would fix a known bug: you cannot --set a
|
||||
// string-valued variable to the empty string, because empty strings are
|
||||
// eliminated below.
|
||||
|
||||
bool LLCommandLineParser::parseCommandLineString(const std::string& str)
|
||||
{
|
||||
std::string cmd_line_string("");
|
||||
if (!str.empty())
|
||||
{
|
||||
bool add_last_c = true;
|
||||
S32 last_c_pos = str.size() - 1; //don't get out of bounds on pos+1, last char will be processed separately
|
||||
for (S32 pos = 0; pos < last_c_pos; ++pos)
|
||||
{
|
||||
cmd_line_string.append(&str[pos], 1);
|
||||
if (str[pos] == '\\')
|
||||
{
|
||||
cmd_line_string.append("\\", 1);
|
||||
if (str[pos + 1] == '\\')
|
||||
{
|
||||
++pos;
|
||||
add_last_c = (pos != last_c_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (add_last_c)
|
||||
{
|
||||
cmd_line_string.append(&str[last_c_pos], 1);
|
||||
if (str[last_c_pos] == '\\')
|
||||
{
|
||||
cmd_line_string.append("\\", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Split the string content into tokens
|
||||
boost::escaped_list_separator<char> sep("\\", "\r\n ", "\"'");
|
||||
boost::tokenizer< boost::escaped_list_separator<char> > tok(str, sep);
|
||||
const char* escape_chars = "\\";
|
||||
const char* separator_chars = "\r\n ";
|
||||
const char* quote_chars = "\"'";
|
||||
boost::escaped_list_separator<char> sep(escape_chars, separator_chars, quote_chars);
|
||||
boost::tokenizer< boost::escaped_list_separator<char> > tok(cmd_line_string, sep);
|
||||
std::vector<std::string> tokens;
|
||||
// std::copy(tok.begin(), tok.end(), std::back_inserter(tokens));
|
||||
for(boost::tokenizer< boost::escaped_list_separator<char> >::iterator i = tok.begin();
|
||||
i != tok.end();
|
||||
++i)
|
||||
{
|
||||
if(0 != i->size())
|
||||
if(!i->empty())
|
||||
{
|
||||
tokens.push_back(*i);
|
||||
}
|
||||
@@ -386,20 +426,28 @@ bool LLCommandLineParser::parseCommandLineFile(const std::basic_istream < char >
|
||||
|
||||
void LLCommandLineParser::notify()
|
||||
{
|
||||
po::notify(gVariableMap);
|
||||
try
|
||||
{
|
||||
po::notify(gVariableMap);
|
||||
}
|
||||
catch (const LLCLPError& e)
|
||||
{
|
||||
LL_WARNS() << "Caught Error: " << e.what() << LL_ENDL;
|
||||
mErrorMsg = e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void LLCommandLineParser::printOptions() const
|
||||
{
|
||||
for(po::variables_map::iterator i = gVariableMap.begin(); i != gVariableMap.end(); ++i)
|
||||
for (auto& i : gVariableMap)
|
||||
{
|
||||
std::string name = i->first;
|
||||
token_vector_t values = i->second.as<token_vector_t>();
|
||||
std::string name = i.first;
|
||||
token_vector_t values = i.second.as<token_vector_t>();
|
||||
std::ostringstream oss;
|
||||
oss << name << ": ";
|
||||
for(token_vector_t::iterator t_itr = values.begin(); t_itr != values.end(); ++t_itr)
|
||||
for (auto& value : values)
|
||||
{
|
||||
oss << t_itr->c_str() << " ";
|
||||
oss << value.c_str() << " ";
|
||||
}
|
||||
LL_INFOS() << oss.str() << LL_ENDL;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
#include "lltrans.h"
|
||||
|
||||
#include "llselectmgr.h"
|
||||
#include "llexperiencecache.h"
|
||||
|
||||
// *TODO: This should be separated into the script queue, and the floater views of that queue.
|
||||
// There should only be one floater class that can view any queue type
|
||||
@@ -76,12 +77,12 @@
|
||||
struct LLScriptQueueData
|
||||
{
|
||||
LLUUID mQueueID;
|
||||
std::string mScriptName;
|
||||
LLPointer<LLInventoryItem> mItemp;
|
||||
LLUUID mTaskId;
|
||||
LLUUID mItemId;
|
||||
LLScriptQueueData(const LLUUID& q_id, const std::string& name, const LLUUID& task_id, const LLUUID& item_id) :
|
||||
mQueueID(q_id), mScriptName(name), mTaskId(task_id), mItemId(item_id) {}
|
||||
|
||||
LLUUID mExperienceId;
|
||||
LLHost mHost;
|
||||
LLScriptQueueData(const LLUUID& q_id, const LLUUID& task_id, LLInventoryItem* item, const LLHost& host) :
|
||||
mQueueID(q_id), mTaskId(task_id), mItemp(item), mHost(host) {}
|
||||
};
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
@@ -220,7 +221,7 @@ BOOL LLFloaterScriptQueue::nextObject()
|
||||
LL_INFOS() << "LLFloaterScriptQueue::nextObject() - " << count
|
||||
<< " objects left to process." << LL_ENDL;
|
||||
mCurrentObjectID.setNull();
|
||||
if(count > 0)
|
||||
if (count > 0)
|
||||
{
|
||||
successful_start = popNext();
|
||||
}
|
||||
@@ -228,7 +229,7 @@ BOOL LLFloaterScriptQueue::nextObject()
|
||||
<< (successful_start ? "successful" : "unsuccessful")
|
||||
<< LL_ENDL;
|
||||
} while((mObjectIDs.size() > 0) && !successful_start);
|
||||
if(isDone() && !mDone)
|
||||
if (isDone() && !mDone)
|
||||
{
|
||||
mDone = true;
|
||||
getChild<LLScrollListCtrl>("queue output")->addSimpleElement(getString("Done"), ADD_BOTTOM);
|
||||
@@ -245,14 +246,14 @@ BOOL LLFloaterScriptQueue::popNext()
|
||||
// the inventory.
|
||||
BOOL rv = FALSE;
|
||||
S32 count = mObjectIDs.size();
|
||||
if(mCurrentObjectID.isNull() && (count > 0))
|
||||
if (mCurrentObjectID.isNull() && (count > 0))
|
||||
{
|
||||
mCurrentObjectID = mObjectIDs.at(0);
|
||||
LL_INFOS() << "LLFloaterScriptQueue::popNext() - mCurrentID: "
|
||||
<< mCurrentObjectID << LL_ENDL;
|
||||
mObjectIDs.erase(mObjectIDs.begin());
|
||||
LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID);
|
||||
if(obj)
|
||||
if (obj)
|
||||
{
|
||||
LL_INFOS() << "LLFloaterScriptQueue::popNext() requesting inv for "
|
||||
<< mCurrentObjectID << LL_ENDL;
|
||||
@@ -270,35 +271,21 @@ BOOL LLFloaterScriptQueue::startQueue()
|
||||
return nextObject();
|
||||
}
|
||||
|
||||
#if 0 // Singu TODO: Experiences
|
||||
class CompileQueueExperienceResponder : public LLHTTPClient::ResponderWithResult
|
||||
class CompileQueueExperienceResponder final : public LLHTTPClient::ResponderWithResult
|
||||
{
|
||||
const LLUUID mParent;
|
||||
public:
|
||||
CompileQueueExperienceResponder(const LLUUID& parent):mParent(parent)
|
||||
{
|
||||
}
|
||||
CompileQueueExperienceResponder(const LLUUID& parent): mParent(parent) {}
|
||||
|
||||
LLUUID mParent;
|
||||
|
||||
/*virtual*/ void httpSuccess()
|
||||
{
|
||||
sendResult(getContent());
|
||||
}
|
||||
/*virtual*/ void httpFailure()
|
||||
{
|
||||
sendResult(LLSD());
|
||||
}
|
||||
void httpSuccess() override { sendResult(getContent()); }
|
||||
void httpFailure() override { sendResult(LLSD()); }
|
||||
void sendResult(const LLSD& content)
|
||||
{
|
||||
LLFloaterCompileQueue* queue = (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mParent);
|
||||
if(!queue)
|
||||
return;
|
||||
|
||||
queue->experienceIdsReceived(content["experience_ids"]);
|
||||
if (auto queue = static_cast<LLFloaterCompileQueue*>(LLFloaterCompileQueue::findInstance(mParent)))
|
||||
queue->experienceIdsReceived(content["experience_ids"]);
|
||||
}
|
||||
/*virtual*/ char const* getName() const { return "RequiredRubbish"; }
|
||||
char const* getName() const override { return "CompileQueueExperienceResponder"; }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -318,7 +305,7 @@ public:
|
||||
virtual LLAssetUploadQueue* get() const
|
||||
{
|
||||
LLFloaterCompileQueue* queue = (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId);
|
||||
if(NULL == queue)
|
||||
if (NULL == queue)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -328,7 +315,7 @@ public:
|
||||
virtual void log(std::string message) const
|
||||
{
|
||||
LLFloaterCompileQueue* queue = (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId);
|
||||
if(NULL == queue)
|
||||
if (NULL == queue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -363,6 +350,21 @@ LLFloaterCompileQueue::~LLFloaterCompileQueue()
|
||||
{
|
||||
}
|
||||
|
||||
void LLFloaterCompileQueue::experienceIdsReceived(const LLSD& content)
|
||||
{
|
||||
for(LLSD::array_const_iterator it = content.beginArray(); it != content.endArray(); ++it)
|
||||
{
|
||||
mExperienceIds.insert(it->asUUID());
|
||||
}
|
||||
nextObject();
|
||||
}
|
||||
|
||||
BOOL LLFloaterCompileQueue::hasExperience(const LLUUID& id) const
|
||||
{
|
||||
return mExperienceIds.find(id) != mExperienceIds.end();
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
|
||||
LLInventoryObject::object_list_t* inv)
|
||||
{
|
||||
@@ -376,7 +378,7 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
|
||||
LLInventoryObject::object_list_t::const_iterator end = inv->end();
|
||||
for ( ; it != end; ++it)
|
||||
{
|
||||
if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
|
||||
if ((*it)->getType() == LLAssetType::AT_LSL_TEXT)
|
||||
{
|
||||
LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
|
||||
// Check permissions before allowing the user to retrieve data.
|
||||
@@ -397,31 +399,68 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
|
||||
}
|
||||
else
|
||||
{
|
||||
// request all of the assets.
|
||||
uuid_item_map::iterator iter;
|
||||
for(iter = asset_item_map.begin(); iter != asset_item_map.end(); iter++)
|
||||
LLViewerRegion* region = viewer_object->getRegion();
|
||||
std::string url = std::string();
|
||||
if (region)
|
||||
{
|
||||
LLInventoryItem *itemp = iter->second;
|
||||
LLScriptQueueData* datap = new LLScriptQueueData(getID(),
|
||||
itemp->getName(),
|
||||
viewer_object->getID(),
|
||||
itemp->getUUID());
|
||||
url = region->getCapability("GetMetadata");
|
||||
}
|
||||
|
||||
//LL_INFOS() << "ITEM NAME 2: " << names.get(i) << LL_ENDL;
|
||||
gAssetStorage->getInvItemAsset(viewer_object->getRegion()->getHost(),
|
||||
gAgent.getID(),
|
||||
gAgent.getSessionID(),
|
||||
itemp->getPermissions().getOwner(),
|
||||
viewer_object->getID(),
|
||||
itemp->getUUID(),
|
||||
itemp->getAssetUUID(),
|
||||
itemp->getType(),
|
||||
LLFloaterCompileQueue::scriptArrived,
|
||||
(void*)datap);
|
||||
const auto& host = region->getHost();
|
||||
const auto& obj_id = viewer_object->getID();
|
||||
// request all of the assets.
|
||||
for(const auto& pair : asset_item_map)
|
||||
{
|
||||
LLInventoryItem *itemp = pair.second;
|
||||
LLScriptQueueData* datap = new LLScriptQueueData(getID(),
|
||||
obj_id,
|
||||
itemp,
|
||||
host);
|
||||
|
||||
LLExperienceCache::instance().fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(),
|
||||
boost::bind(LLFloaterCompileQueue::requestAsset, datap, _1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterCompileQueue::requestAsset(LLScriptQueueData* datap, const LLSD& experience)
|
||||
{
|
||||
LLFloaterCompileQueue* queue = static_cast<LLFloaterCompileQueue*>(findInstance(datap->mQueueID));
|
||||
if (!queue)
|
||||
{
|
||||
delete datap;
|
||||
return;
|
||||
}
|
||||
|
||||
if (experience.has(LLExperienceCache::EXPERIENCE_ID))
|
||||
{
|
||||
datap->mExperienceId = experience[LLExperienceCache::EXPERIENCE_ID].asUUID();
|
||||
if (!queue->hasExperience(datap->mExperienceId))
|
||||
{
|
||||
std::string buffer = LLTrans::getString("CompileNoExperiencePerm", LLSD::emptyMap()
|
||||
.with("SCRIPT", datap->mItemp->getName())
|
||||
.with("EXPERIENCE", experience[LLExperienceCache::NAME].asString()));
|
||||
|
||||
queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
|
||||
queue->removeItemByItemID(datap->mItemp->getUUID());
|
||||
delete datap;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//LL_INFOS() << "ITEM NAME 2: " << names.get(i) << LL_ENDL;
|
||||
gAssetStorage->getInvItemAsset(datap->mHost,
|
||||
gAgent.getID(),
|
||||
gAgent.getSessionID(),
|
||||
datap->mItemp->getPermissions().getOwner(),
|
||||
datap->mTaskId,
|
||||
datap->mItemp->getUUID(),
|
||||
datap->mItemp->getAssetUUID(),
|
||||
datap->mItemp->getType(),
|
||||
LLFloaterCompileQueue::scriptArrived,
|
||||
(void*)datap);
|
||||
}
|
||||
|
||||
|
||||
// This is the callback for when each script arrives
|
||||
// static
|
||||
@@ -438,9 +477,9 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
||||
LLFloaterCompileQueue* queue = static_cast<LLFloaterCompileQueue*> (LLFloaterScriptQueue::findInstance(data->mQueueID));
|
||||
|
||||
std::string buffer;
|
||||
if(queue && (0 == status))
|
||||
if (queue && (0 == status))
|
||||
{
|
||||
//LL_INFOS() << "ITEM NAME 3: " << data->mScriptName << LL_ENDL;
|
||||
//LL_INFOS() << "ITEM NAME 3: " << data->mItemp->getName() << LL_ENDL;
|
||||
|
||||
// Dump this into a file on the local disk so we can compile it.
|
||||
std::string filename;
|
||||
@@ -454,7 +493,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
||||
if (object)
|
||||
{
|
||||
std::string url = object->getRegion()->getCapability("UpdateScriptTask");
|
||||
if(!url.empty())
|
||||
if (!url.empty())
|
||||
{
|
||||
// Read script source in to buffer.
|
||||
U32 script_size = file.getSize();
|
||||
@@ -462,17 +501,17 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
||||
file.read(script_data, script_size);
|
||||
|
||||
queue->mUploadQueue->queue(filename, data->mTaskId,
|
||||
data->mItemId, is_running, queue->mMono, queue->getID(),
|
||||
script_data, script_size, data->mScriptName);
|
||||
data->mItemp->getUUID(), is_running, queue->mMono, queue->getID(),
|
||||
script_data, script_size, data->mItemp->getName(), data->mExperienceId);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string text = LLTrans::getString("CompileQueueProblemUploading");
|
||||
LLChat chat(text);
|
||||
LLFloaterChat::addChat(chat);
|
||||
buffer = text + LLTrans::getString(":") + ' ' + data->mScriptName;
|
||||
buffer = text + LLTrans::getString(":") + ' ' + data->mItemp->getName();
|
||||
LL_WARNS() << "Problem uploading script asset." << LL_ENDL;
|
||||
if(queue) queue->removeItemByItemID(data->mItemId);
|
||||
if(queue) queue->removeItemByItemID(data->mItemp->getUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,29 +519,29 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
||||
{
|
||||
LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
|
||||
|
||||
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )
|
||||
if ( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )
|
||||
{
|
||||
LLChat chat(LLTrans::getString("CompileQueueScriptNotFound"));
|
||||
LLFloaterChat::addChat(chat);
|
||||
|
||||
buffer = LLTrans::getString("CompileQueueProblemDownloading") + LLTrans::getString(":") + ' ' + data->mScriptName;
|
||||
buffer = LLTrans::getString("CompileQueueProblemDownloading") + LLTrans::getString(":") + ' ' + data->mItemp->getName();
|
||||
}
|
||||
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
|
||||
{
|
||||
LLChat chat(LLTrans::getString("CompileQueueInsufficientPermDownload"));
|
||||
LLFloaterChat::addChat(chat);
|
||||
|
||||
buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + LLTrans::getString(":") + ' ' + data->mScriptName;
|
||||
buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + LLTrans::getString(":") + ' ' + data->mItemp->getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = LLTrans::getString("CompileQueueUnknownFailure") + ' ' + data->mScriptName;
|
||||
buffer = LLTrans::getString("CompileQueueUnknownFailure") + ' ' + data->mItemp->getName();
|
||||
}
|
||||
|
||||
LL_WARNS() << "Problem downloading script asset." << LL_ENDL;
|
||||
if(queue) queue->removeItemByItemID(data->mItemId);
|
||||
if(queue) queue->removeItemByItemID(data->mItemp->getUUID());
|
||||
}
|
||||
if(queue && (buffer.size() > 0))
|
||||
if (queue && (buffer.size() > 0))
|
||||
{
|
||||
queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
|
||||
}
|
||||
@@ -528,7 +567,7 @@ void LLFloaterCompileQueue::saveItemByItemID(const LLUUID& asset_id)
|
||||
{
|
||||
LL_INFOS() << "LLFloaterCompileQueue::saveItemByAssetID()" << LL_ENDL;
|
||||
LLViewerObject* viewer_object = gObjectList.findObject(mCurrentObjectID);
|
||||
if(viewer_object)
|
||||
if (viewer_object)
|
||||
{
|
||||
S32 count = mCurrentScripts.size();
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
@@ -582,7 +621,7 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj,
|
||||
LLInventoryObject::object_list_t::const_iterator end = inv->end();
|
||||
for ( ; it != end; ++it)
|
||||
{
|
||||
if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
|
||||
if ((*it)->getType() == LLAssetType::AT_LSL_TEXT)
|
||||
{
|
||||
LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
|
||||
|
||||
@@ -641,7 +680,7 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj,
|
||||
LLInventoryObject::object_list_t::const_iterator end = inv->end();
|
||||
for ( ; it != end; ++it)
|
||||
{
|
||||
if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
|
||||
if ((*it)->getType() == LLAssetType::AT_LSL_TEXT)
|
||||
{
|
||||
LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
|
||||
|
||||
@@ -716,17 +755,16 @@ void LLFloaterCompileQueue::removeItemByItemID(const LLUUID& asset_id)
|
||||
|
||||
BOOL LLFloaterCompileQueue::startQueue()
|
||||
{
|
||||
/* Singu TODO: Experiences
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
std::string lookup_url=region->getCapability("GetCreatorExperiences");
|
||||
if(!lookup_url.empty())
|
||||
std::string lookup_url = region->getCapability("GetCreatorExperiences");
|
||||
if (!lookup_url.empty())
|
||||
{
|
||||
LLHTTPClient::get(lookup_url, new CompileQueueExperienceResponder(getKey().asUUID()));
|
||||
LLHTTPClient::get(lookup_url, new CompileQueueExperienceResponder(mID));
|
||||
return TRUE;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
return nextObject();
|
||||
}
|
||||
|
||||
@@ -741,7 +779,7 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj,
|
||||
LLInventoryObject::object_list_t::const_iterator end = inv->end();
|
||||
for ( ; it != end; ++it)
|
||||
{
|
||||
if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
|
||||
if ((*it)->getType() == LLAssetType::AT_LSL_TEXT)
|
||||
{
|
||||
LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ protected:
|
||||
|
||||
// Get this instance's ID.
|
||||
const LLUUID& getID() const { return mID; }
|
||||
|
||||
|
||||
protected:
|
||||
// UI
|
||||
LLScrollListCtrl* mMessages;
|
||||
@@ -149,8 +149,8 @@ public:
|
||||
|
||||
LLAssetUploadQueue* getUploadQueue() { return mUploadQueue; }
|
||||
|
||||
void experienceIdsReceived( const LLSD& content );
|
||||
BOOL hasExperience(const LLUUID& id)const;
|
||||
void experienceIdsReceived(const LLSD& content);
|
||||
BOOL hasExperience(const LLUUID& id) const;
|
||||
|
||||
protected:
|
||||
LLFloaterCompileQueue(const std::string& name, const LLRect& rect);
|
||||
@@ -160,6 +160,9 @@ protected:
|
||||
virtual void handleInventory(LLViewerObject* viewer_obj,
|
||||
LLInventoryObject::object_list_t* inv);
|
||||
|
||||
static void requestAsset(struct LLScriptQueueData* datap, const LLSD& experience);
|
||||
|
||||
|
||||
// This is the callback for when each script arrives
|
||||
static void scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
|
||||
LLAssetType::EType type,
|
||||
|
||||
289
indra/newview/llexperiencelog.cpp
Normal file
289
indra/newview/llexperiencelog.cpp
Normal file
@@ -0,0 +1,289 @@
|
||||
/**
|
||||
* @file llexperiencelog.cpp
|
||||
* @brief llexperiencelog implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llexperiencelog.h"
|
||||
|
||||
#include "lldispatcher.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llviewergenericmessage.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "lltrans.h"
|
||||
#include "llerror.h"
|
||||
#include "lldate.h"
|
||||
|
||||
|
||||
class LLExperienceLogDispatchHandler final : public LLDispatchHandler
|
||||
{
|
||||
public:
|
||||
bool operator()(
|
||||
const LLDispatcher* dispatcher,
|
||||
const std::string& key,
|
||||
const LLUUID& invoice,
|
||||
const sparam_t& strings) override
|
||||
{
|
||||
LLSD message;
|
||||
|
||||
sparam_t::const_iterator it = strings.begin();
|
||||
if(it != strings.end()){
|
||||
const std::string& llsdRaw = *it++;
|
||||
std::istringstream llsdData(llsdRaw);
|
||||
if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length()))
|
||||
{
|
||||
LL_WARNS() << "LLExperienceLogDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
|
||||
}
|
||||
}
|
||||
message["public_id"] = invoice;
|
||||
|
||||
// Object Name
|
||||
if(it != strings.end())
|
||||
{
|
||||
message["ObjectName"] = *it++;
|
||||
}
|
||||
|
||||
// parcel Name
|
||||
if(it != strings.end())
|
||||
{
|
||||
message["ParcelName"] = *it++;
|
||||
}
|
||||
message["Count"] = 1;
|
||||
|
||||
LLExperienceLog::instance().handleExperienceMessage(message);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static LLExperienceLogDispatchHandler experience_log_dispatch_handler;
|
||||
|
||||
void LLExperienceLog::handleExperienceMessage(LLSD& message)
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
char daybuf[16];/* Flawfinder: ignore */
|
||||
char time_of_day[16];/* Flawfinder: ignore */
|
||||
strftime(daybuf, 16, "%Y-%m-%d", localtime(&now));
|
||||
strftime(time_of_day, 16, " %H:%M:%S", localtime(&now));
|
||||
message["Time"] = time_of_day;
|
||||
|
||||
std::string day = daybuf;
|
||||
|
||||
if(!mEvents.has(day))
|
||||
{
|
||||
mEvents[day] = LLSD::emptyArray();
|
||||
}
|
||||
LLSD& dayEvents = mEvents[day];
|
||||
if(dayEvents.size() > 0)
|
||||
{
|
||||
LLSD& last = *(dayEvents.rbeginArray());
|
||||
if( last["public_id"].asUUID() == message["public_id"].asUUID()
|
||||
&& last["ObjectName"].asString() == message["ObjectName"].asString()
|
||||
&& last["OwnerID"].asUUID() == message["OwnerID"].asUUID()
|
||||
&& last["ParcelName"].asString() == message["ParcelName"].asString()
|
||||
&& last["Permission"].asInteger() == message["Permission"].asInteger())
|
||||
{
|
||||
last["Count"] = last["Count"].asInteger() + 1;
|
||||
last["Time"] = time_of_day;
|
||||
mSignals(last);
|
||||
return;
|
||||
}
|
||||
}
|
||||
message["Time"] = time_of_day;
|
||||
mEvents[day].append(message);
|
||||
mSignals(message);
|
||||
}
|
||||
|
||||
LLExperienceLog::LLExperienceLog()
|
||||
: mMaxDays(7)
|
||||
, mPageSize(25)
|
||||
, mNotifyNewEvent(false)
|
||||
{
|
||||
}
|
||||
|
||||
void LLExperienceLog::initialize()
|
||||
{
|
||||
loadEvents();
|
||||
if(!gGenericDispatcher.isHandlerPresent("ExperienceEvent"))
|
||||
{
|
||||
gGenericDispatcher.addHandler("ExperienceEvent", &experience_log_dispatch_handler);
|
||||
}
|
||||
}
|
||||
|
||||
std::string LLExperienceLog::getFilename()
|
||||
{
|
||||
return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "experience_events.xml");
|
||||
}
|
||||
|
||||
|
||||
std::string LLExperienceLog::getPermissionString( const LLSD& message, const std::string& base )
|
||||
{
|
||||
std::ostringstream buf;
|
||||
if(message.has("Permission"))
|
||||
{
|
||||
buf << base << message["Permission"].asInteger();
|
||||
std::string entry;
|
||||
if(LLTrans::findString(entry, buf.str()))
|
||||
{
|
||||
buf.str(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if(buf.str().empty())
|
||||
{
|
||||
buf << base << "Unknown";
|
||||
|
||||
buf.str(LLTrans::getString(buf.str(), message));
|
||||
}
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
void LLExperienceLog::notify( LLSD& message )
|
||||
{
|
||||
message["EventType"] = getPermissionString(message, "ExperiencePermission");
|
||||
if(message.has("IsAttachment") && message["IsAttachment"].asBoolean())
|
||||
{
|
||||
LLNotificationsUtil::add("ExperienceEventAttachment", message);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationsUtil::add("ExperienceEvent", message);
|
||||
}
|
||||
message.erase("EventType");
|
||||
}
|
||||
|
||||
void LLExperienceLog::saveEvents()
|
||||
{
|
||||
eraseExpired();
|
||||
std::string filename = getFilename();
|
||||
LLSD settings = LLSD::emptyMap().with("Events", mEvents);
|
||||
|
||||
settings["MaxDays"] = (int)mMaxDays;
|
||||
settings["Notify"] = mNotifyNewEvent;
|
||||
settings["PageSize"] = (int)mPageSize;
|
||||
|
||||
llofstream stream(filename.c_str());
|
||||
LLSDSerialize::toPrettyXML(settings, stream);
|
||||
}
|
||||
|
||||
|
||||
void LLExperienceLog::loadEvents()
|
||||
{
|
||||
LLSD settings = LLSD::emptyMap();
|
||||
|
||||
std::string filename = getFilename();
|
||||
llifstream stream(filename.c_str());
|
||||
LLSDSerialize::fromXMLDocument(settings, stream);
|
||||
|
||||
if(settings.has("MaxDays"))
|
||||
{
|
||||
setMaxDays((U32)settings["MaxDays"].asInteger());
|
||||
}
|
||||
if(settings.has("Notify"))
|
||||
{
|
||||
setNotifyNewEvent(settings["Notify"].asBoolean());
|
||||
}
|
||||
if(settings.has("PageSize"))
|
||||
{
|
||||
setPageSize((U32)settings["PageSize"].asInteger());
|
||||
}
|
||||
mEvents.clear();
|
||||
if(mMaxDays > 0 && settings.has("Events"))
|
||||
{
|
||||
mEvents = settings["Events"];
|
||||
}
|
||||
|
||||
eraseExpired();
|
||||
}
|
||||
|
||||
LLExperienceLog::~LLExperienceLog()
|
||||
{
|
||||
saveEvents();
|
||||
}
|
||||
|
||||
void LLExperienceLog::eraseExpired()
|
||||
{
|
||||
std::vector<std::string> expired;
|
||||
for (const auto& event_pair : mEvents.map())
|
||||
{
|
||||
const std::string& date = event_pair.first;
|
||||
if (isExpired(date))
|
||||
{
|
||||
expired.push_back(date);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& date : expired)
|
||||
{
|
||||
mEvents.erase(date);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLExperienceLog::isExpired(const std::string& date) const
|
||||
{
|
||||
if (date.empty())
|
||||
return true;
|
||||
|
||||
S32 month, day, year = 0;
|
||||
S32 matched = sscanf(date.c_str(), "%d-%d-%d", &year, &month, &day);
|
||||
if (matched != 3) return false;
|
||||
LLDate event_date;
|
||||
event_date.fromYMDHMS(year, month, day);
|
||||
|
||||
return event_date.secondsSinceEpoch() <= (LLDate::now().secondsSinceEpoch() - F64(getMaxDays() * 86400U));
|
||||
}
|
||||
|
||||
const LLSD& LLExperienceLog::getEvents() const
|
||||
{
|
||||
return mEvents;
|
||||
}
|
||||
|
||||
void LLExperienceLog::clear()
|
||||
{
|
||||
mEvents.clear();
|
||||
}
|
||||
|
||||
void LLExperienceLog::setMaxDays( U32 val )
|
||||
{
|
||||
mMaxDays = val;
|
||||
}
|
||||
|
||||
LLExperienceLog::callback_connection_t LLExperienceLog::addUpdateSignal( const callback_slot_t& cb )
|
||||
{
|
||||
return mSignals.connect(cb);
|
||||
}
|
||||
|
||||
void LLExperienceLog::setNotifyNewEvent( bool val )
|
||||
{
|
||||
mNotifyNewEvent = val;
|
||||
if(!val && mNotifyConnection.connected())
|
||||
{
|
||||
mNotifyConnection.disconnect();
|
||||
}
|
||||
else if( val && !mNotifyConnection.connected())
|
||||
{
|
||||
mNotifyConnection = addUpdateSignal(std::function<void(LLSD&)>(LLExperienceLog::notify));
|
||||
}
|
||||
}
|
||||
86
indra/newview/llexperiencelog.h
Normal file
86
indra/newview/llexperiencelog.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @file llexperiencelog.h
|
||||
* @brief llexperiencelog and related class definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef LL_LLEXPERIENCELOG_H
|
||||
#define LL_LLEXPERIENCELOG_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
|
||||
class LLExperienceLog final : public LLSingleton<LLExperienceLog>
|
||||
{
|
||||
friend class LLSingleton<LLExperienceLog>;
|
||||
LLExperienceLog();
|
||||
public:
|
||||
typedef boost::signals2::signal<void(LLSD&)>
|
||||
callback_signal_t;
|
||||
typedef callback_signal_t::slot_type callback_slot_t;
|
||||
typedef boost::signals2::connection callback_connection_t;
|
||||
callback_connection_t addUpdateSignal(const callback_slot_t& cb);
|
||||
|
||||
void initialize();
|
||||
|
||||
U32 getMaxDays() const { return mMaxDays; }
|
||||
void setMaxDays(U32 val);
|
||||
|
||||
bool getNotifyNewEvent() const { return mNotifyNewEvent; }
|
||||
void setNotifyNewEvent(bool val);
|
||||
|
||||
U32 getPageSize() const { return mPageSize; }
|
||||
void setPageSize(U32 val) { mPageSize = val; }
|
||||
|
||||
const LLSD& getEvents()const;
|
||||
void clear();
|
||||
|
||||
virtual ~LLExperienceLog();
|
||||
|
||||
static void notify(LLSD& message);
|
||||
static std::string getFilename();
|
||||
static std::string getPermissionString(const LLSD& message, const std::string& base);
|
||||
bool isExpired(const std::string& date) const;
|
||||
protected:
|
||||
void handleExperienceMessage(LLSD& message);
|
||||
|
||||
|
||||
void loadEvents();
|
||||
void saveEvents();
|
||||
void eraseExpired();
|
||||
|
||||
LLSD mEvents;
|
||||
callback_signal_t mSignals;
|
||||
callback_connection_t mNotifyConnection;
|
||||
U32 mMaxDays;
|
||||
U32 mPageSize;
|
||||
bool mNotifyNewEvent;
|
||||
|
||||
friend class LLExperienceLogDispatchHandler;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // LL_LLEXPERIENCELOG_H
|
||||
@@ -3,38 +3,31 @@
|
||||
* @author James Cook, Ian Wilkes
|
||||
* @brief Implementation of the auction floater.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2004-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llfloaterauction.h"
|
||||
|
||||
#include "lldir.h"
|
||||
#include "llgl.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "llimagetga.h"
|
||||
@@ -46,17 +39,21 @@
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llmimetypes.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llviewertexturelist.h"
|
||||
#include "llviewerparcelmgr.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llviewerdisplay.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llui.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llrender.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llsdutil_math.h"
|
||||
#include "lltrans.h"
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Local function declarations, constants, enums, and typedefs
|
||||
@@ -74,8 +71,8 @@ void auction_tga_upload_done(const LLUUID& asset_id,
|
||||
LLFloaterAuction* LLFloaterAuction::sInstance = NULL;
|
||||
|
||||
// Default constructor
|
||||
LLFloaterAuction::LLFloaterAuction() :
|
||||
LLFloater(std::string("floater_auction")),
|
||||
LLFloaterAuction::LLFloaterAuction()
|
||||
: LLFloater(std::string("floater_auction")),
|
||||
mParcelID(-1)
|
||||
{
|
||||
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_auction.xml");
|
||||
@@ -86,13 +83,13 @@ LLFloaterAuction::LLFloaterAuction() :
|
||||
onCommitControlSetting(gSavedSettings), (void*)"AuctionShowFence");
|
||||
|
||||
childSetAction("snapshot_btn", onClickSnapshot, this);
|
||||
childSetAction("ok_btn", onClickOK, this);
|
||||
childSetAction("ok_btn", onClickStartAuction, this);
|
||||
}
|
||||
|
||||
// Destroys the object
|
||||
LLFloaterAuction::~LLFloaterAuction()
|
||||
{
|
||||
sInstance = NULL;
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -104,12 +101,23 @@ void LLFloaterAuction::show()
|
||||
sInstance->center();
|
||||
sInstance->setFocus(TRUE);
|
||||
}
|
||||
sInstance->initialize();
|
||||
sInstance->open(); /*Flawfinder: ignore*/
|
||||
}
|
||||
|
||||
BOOL LLFloaterAuction::postBuild()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLFloaterAuction::onOpen()
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
void LLFloaterAuction::initialize()
|
||||
{
|
||||
mParcelUpdateCapUrl.clear();
|
||||
|
||||
mParcelp = LLViewerParcelMgr::getInstance()->getParcelSelection();
|
||||
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
|
||||
LLParcel* parcelp = mParcelp->getParcel();
|
||||
@@ -117,28 +125,30 @@ void LLFloaterAuction::initialize()
|
||||
{
|
||||
mParcelHost = region->getHost();
|
||||
mParcelID = parcelp->getLocalID();
|
||||
mParcelUpdateCapUrl = region->getCapability("ParcelPropertiesUpdate");
|
||||
|
||||
childSetText("parcel_text", parcelp->getName());
|
||||
childEnable("snapshot_btn");
|
||||
childEnable("ok_btn");
|
||||
getChild<LLUICtrl>("parcel_text")->setValue(parcelp->getName());
|
||||
getChildView("snapshot_btn")->setEnabled(TRUE);
|
||||
getChildView("ok_btn")->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mParcelHost.invalidate();
|
||||
if(parcelp && parcelp->getForSale())
|
||||
{
|
||||
childSetText("parcel_text", getString("already for sale"));
|
||||
getChild<LLUICtrl>("parcel_text")->setValue(getString("already for sale"));
|
||||
}
|
||||
else
|
||||
{
|
||||
childSetText("parcel_text", LLStringUtil::null);
|
||||
getChild<LLUICtrl>("parcel_text")->setValue(LLStringUtil::null);
|
||||
}
|
||||
mParcelID = -1;
|
||||
childSetEnabled("snapshot_btn", false);
|
||||
childSetEnabled("ok_btn", false);
|
||||
getChildView("snapshot_btn")->setEnabled(false);
|
||||
getChildView("ok_btn")->setEnabled(false);
|
||||
}
|
||||
|
||||
mImageID.setNull();
|
||||
mImage = NULL;
|
||||
mImage = nullptr;
|
||||
}
|
||||
|
||||
void LLFloaterAuction::draw()
|
||||
@@ -147,9 +157,10 @@ void LLFloaterAuction::draw()
|
||||
|
||||
if(!isMinimized() && mImage.notNull())
|
||||
{
|
||||
LLRect rect;
|
||||
if (childGetRect("snapshot_icon", rect))
|
||||
LLView* snapshot_icon = findChild<LLView>("snapshot_icon");
|
||||
if (snapshot_icon)
|
||||
{
|
||||
LLRect rect = snapshot_icon->getRect();
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f));
|
||||
@@ -176,7 +187,7 @@ void LLFloaterAuction::onClickSnapshot(void* data)
|
||||
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw;
|
||||
|
||||
gForceRenderLandFence = self->childGetValue("fence_check").asBoolean();
|
||||
gForceRenderLandFence = self->getChild<LLUICtrl>("fence_check")->getValue().asBoolean();
|
||||
BOOL success = gViewerWindow->rawSnapshot(raw,
|
||||
gViewerWindow->getWindowWidth(),
|
||||
gViewerWindow->getWindowHeight(),
|
||||
@@ -218,13 +229,13 @@ void LLFloaterAuction::onClickSnapshot(void* data)
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterAuction::onClickOK(void* data)
|
||||
void LLFloaterAuction::onClickStartAuction(void* data)
|
||||
{
|
||||
LLFloaterAuction* self = (LLFloaterAuction*)(data);
|
||||
|
||||
if(self->mImageID.notNull())
|
||||
{
|
||||
LLSD parcel_name = self->childGetValue("parcel_text");
|
||||
LLSD parcel_name = self->getChild<LLUICtrl>("parcel_text")->getValue();
|
||||
|
||||
// create the asset
|
||||
std::string* name = new std::string(parcel_name.asString());
|
||||
@@ -257,11 +268,243 @@ void LLFloaterAuction::onClickOK(void* data)
|
||||
msg->sendReliable(self->mParcelHost);
|
||||
|
||||
// clean up floater, and get out
|
||||
self->mImageID.setNull();
|
||||
self->mImage = NULL;
|
||||
self->mParcelID = -1;
|
||||
self->mParcelHost.invalidate();
|
||||
self->close();
|
||||
self->cleanupAndClose();
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterAuction::cleanupAndClose()
|
||||
{
|
||||
mImageID.setNull();
|
||||
mImage = nullptr;
|
||||
mParcelID = -1;
|
||||
mParcelHost.invalidate();
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// static glue
|
||||
void LLFloaterAuction::onClickResetParcel(void* data)
|
||||
{
|
||||
LLFloaterAuction* self = (LLFloaterAuction*)(data);
|
||||
if (self)
|
||||
{
|
||||
self->doResetParcel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reset all the values for the parcel in preparation for a sale
|
||||
void LLFloaterAuction::doResetParcel()
|
||||
{
|
||||
LLParcel* parcelp = mParcelp->getParcel();
|
||||
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
|
||||
|
||||
if (parcelp
|
||||
&& region
|
||||
&& !mParcelUpdateCapUrl.empty())
|
||||
{
|
||||
LLSD body;
|
||||
std::string empty;
|
||||
|
||||
// request new properties update from simulator
|
||||
U32 message_flags = 0x01;
|
||||
body["flags"] = ll_sd_from_U32(message_flags);
|
||||
|
||||
// Set all the default parcel properties for auction
|
||||
body["local_id"] = parcelp->getLocalID();
|
||||
|
||||
U32 parcel_flags = PF_ALLOW_LANDMARK |
|
||||
PF_ALLOW_FLY |
|
||||
PF_CREATE_GROUP_OBJECTS |
|
||||
PF_ALLOW_ALL_OBJECT_ENTRY |
|
||||
PF_ALLOW_GROUP_OBJECT_ENTRY |
|
||||
PF_ALLOW_GROUP_SCRIPTS |
|
||||
PF_RESTRICT_PUSHOBJECT |
|
||||
PF_SOUND_LOCAL |
|
||||
PF_ALLOW_VOICE_CHAT |
|
||||
PF_USE_ESTATE_VOICE_CHAN;
|
||||
|
||||
body["parcel_flags"] = ll_sd_from_U32(parcel_flags);
|
||||
|
||||
// Build a parcel name like "Ahern (128,128) PG 4032m"
|
||||
std::ostringstream parcel_name;
|
||||
LLVector3 center_point( parcelp->getCenterpoint() );
|
||||
center_point.snap(0); // Get rid of fractions
|
||||
parcel_name << region->getName()
|
||||
<< " ("
|
||||
<< (S32) center_point.mV[VX]
|
||||
<< ","
|
||||
<< (S32) center_point.mV[VY]
|
||||
<< ") "
|
||||
<< region->getSimAccessString()
|
||||
<< " "
|
||||
<< parcelp->getArea()
|
||||
<< "m";
|
||||
|
||||
std::string new_name(parcel_name.str());
|
||||
body["name"] = new_name;
|
||||
getChild<LLUICtrl>("parcel_text")->setValue(new_name); // Set name in dialog as well, since it won't get updated otherwise
|
||||
|
||||
body["sale_price"] = (S32) 0;
|
||||
body["description"] = empty;
|
||||
body["music_url"] = empty;
|
||||
body["media_url"] = empty;
|
||||
body["media_desc"] = empty;
|
||||
body["media_type"] = LLMIMETypes::getDefaultMimeType();
|
||||
body["media_width"] = (S32) 0;
|
||||
body["media_height"] = (S32) 0;
|
||||
body["auto_scale"] = (S32) 0;
|
||||
body["media_loop"] = (S32) 0;
|
||||
body["obscure_media"] = (S32) 0; // OBSOLETE - no longer used
|
||||
body["obscure_music"] = (S32) 0; // OBSOLETE - no longer used
|
||||
body["media_id"] = LLUUID::null;
|
||||
body["group_id"] = MAINTENANCE_GROUP_ID; // Use maintenance group
|
||||
body["pass_price"] = (S32) 10; // Defaults to $10
|
||||
body["pass_hours"] = 0.0f;
|
||||
body["category"] = (U8) LLParcel::C_NONE;
|
||||
body["auth_buyer_id"] = LLUUID::null;
|
||||
body["snapshot_id"] = LLUUID::null;
|
||||
body["user_location"] = ll_sd_from_vector3( LLVector3::zero );
|
||||
body["user_look_at"] = ll_sd_from_vector3( LLVector3::zero );
|
||||
body["landing_type"] = (U8) LLParcel::L_DIRECT;
|
||||
|
||||
LL_INFOS() << "Sending parcel update to reset for auction via capability to: "
|
||||
<< mParcelUpdateCapUrl << LL_ENDL;
|
||||
LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::ResponderIgnore());
|
||||
|
||||
// Send a message to clear the object return time
|
||||
LLMessageSystem *msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_ParcelSetOtherCleanTime);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
|
||||
msg->nextBlockFast(_PREHASH_ParcelData);
|
||||
msg->addS32Fast(_PREHASH_LocalID, parcelp->getLocalID());
|
||||
msg->addS32Fast(_PREHASH_OtherCleanTime, 5); // 5 minute object auto-return
|
||||
|
||||
msg->sendReliable(region->getHost());
|
||||
|
||||
// Clear the access lists
|
||||
clearParcelAccessList(parcelp, region, AL_ACCESS);
|
||||
clearParcelAccessList(parcelp, region, AL_BAN);
|
||||
clearParcelAccessList(parcelp, region, AL_ALLOW_EXPERIENCE);
|
||||
clearParcelAccessList(parcelp, region, AL_BLOCK_EXPERIENCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLFloaterAuction::clearParcelAccessList(LLParcel* parcel, LLViewerRegion* region, U32 list)
|
||||
{
|
||||
if (!region || !parcel) return;
|
||||
|
||||
LLUUID transactionUUID;
|
||||
transactionUUID.generate();
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
||||
msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast(_PREHASH_Data);
|
||||
msg->addU32Fast(_PREHASH_Flags, list);
|
||||
msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
|
||||
msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
|
||||
msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id
|
||||
msg->addS32Fast(_PREHASH_Sections, 0); // num_sections
|
||||
|
||||
// pack an empty block since there will be no data
|
||||
msg->nextBlockFast(_PREHASH_List);
|
||||
msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
|
||||
msg->addS32Fast(_PREHASH_Time, 0 );
|
||||
msg->addU32Fast(_PREHASH_Flags, 0 );
|
||||
|
||||
msg->sendReliable( region->getHost() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// static - 'Sell to Anyone' clicked, throw up a confirmation dialog
|
||||
void LLFloaterAuction::onClickSellToAnyone(void* data)
|
||||
{
|
||||
LLFloaterAuction* self = (LLFloaterAuction*)(data);
|
||||
if (self)
|
||||
{
|
||||
LLParcel* parcelp = self->mParcelp->getParcel();
|
||||
|
||||
// Do a confirmation
|
||||
S32 sale_price = parcelp->getArea(); // Selling for L$1 per meter
|
||||
S32 area = parcelp->getArea();
|
||||
|
||||
LLSD args;
|
||||
args["LAND_SIZE"] = llformat("%d", area);
|
||||
args["SALE_PRICE"] = llformat("%d", sale_price);
|
||||
args["NAME"] = LLTrans::getString("Anyone");
|
||||
|
||||
LLNotification::Params params("ConfirmLandSaleChange"); // Re-use existing dialog
|
||||
params.substitutions(args)
|
||||
.functor/*.function*/(boost::bind(&LLFloaterAuction::onSellToAnyoneConfirmed, self, _1, _2));
|
||||
|
||||
params.name("ConfirmLandSaleToAnyoneChange");
|
||||
|
||||
// ask away
|
||||
LLNotifications::instance().add(params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sell confirmation clicked
|
||||
bool LLFloaterAuction::onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response)
|
||||
{
|
||||
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
if (option == 0)
|
||||
{
|
||||
doSellToAnyone();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Reset all the values for the parcel in preparation for a sale
|
||||
void LLFloaterAuction::doSellToAnyone()
|
||||
{
|
||||
LLParcel* parcelp = mParcelp->getParcel();
|
||||
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
|
||||
|
||||
if (parcelp
|
||||
&& region
|
||||
&& !mParcelUpdateCapUrl.empty())
|
||||
{
|
||||
LLSD body;
|
||||
|
||||
// request new properties update from simulator
|
||||
U32 message_flags = 0x01;
|
||||
body["flags"] = ll_sd_from_U32(message_flags);
|
||||
|
||||
// Set all the default parcel properties for auction
|
||||
body["local_id"] = parcelp->getLocalID();
|
||||
|
||||
// Set 'for sale' flag
|
||||
U32 parcel_flags = parcelp->getParcelFlags() | PF_FOR_SALE;
|
||||
// Ensure objects not included
|
||||
parcel_flags &= ~PF_FOR_SALE_OBJECTS;
|
||||
body["parcel_flags"] = ll_sd_from_U32(parcel_flags);
|
||||
|
||||
body["sale_price"] = parcelp->getArea(); // Sell for L$1 per square meter
|
||||
body["auth_buyer_id"] = LLUUID::null; // To anyone
|
||||
|
||||
LL_INFOS() << "Sending parcel update to sell to anyone for L$1 via capability to: "
|
||||
<< mParcelUpdateCapUrl << LL_ENDL;
|
||||
|
||||
LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::ResponderIgnore());
|
||||
|
||||
// clean up floater, and get out
|
||||
cleanupAndClose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,31 +3,25 @@
|
||||
* @author James Cook, Ian Wilkes
|
||||
* @brief llfloaterauction class header file
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2004-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -36,7 +30,7 @@
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "lluuid.h"
|
||||
#include "llmemory.h"
|
||||
#include "llsafehandle.h"
|
||||
#include "llviewertexture.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -45,34 +39,50 @@
|
||||
// Class which holds the functionality to start auctions.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
class LLParcelSelection;
|
||||
class LLParcel;
|
||||
class LLViewerRegion;
|
||||
|
||||
class LLFloaterAuction : public LLFloater
|
||||
class LLFloaterAuction final : public LLFloater
|
||||
{
|
||||
public:
|
||||
// LLFloater interface
|
||||
/*virtual*/ void onClose(bool app_quitting) { setVisible(FALSE); }
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void onOpen() override;
|
||||
/*virtual*/ void onClose(bool app_quitting) override { setVisible(FALSE); }
|
||||
/*virtual*/ void draw() override;
|
||||
|
||||
// LLFloaterAuction interface
|
||||
static void show();
|
||||
|
||||
private:
|
||||
|
||||
LLFloaterAuction();
|
||||
~LLFloaterAuction();
|
||||
|
||||
void initialize();
|
||||
|
||||
static void onClickSnapshot(void* data);
|
||||
static void onClickOK(void* data);
|
||||
static void onClickResetParcel(void* data);
|
||||
static void onClickSellToAnyone(void* data); // Sell to anyone clicked
|
||||
bool onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response); // Sell confirmation clicked
|
||||
static void onClickStartAuction(void* data);
|
||||
|
||||
static LLFloaterAuction* sInstance;
|
||||
/*virtual*/ BOOL postBuild() override;
|
||||
|
||||
void doResetParcel();
|
||||
void doSellToAnyone();
|
||||
void clearParcelAccessList(LLParcel* parcel, LLViewerRegion* region, U32 list);
|
||||
void cleanupAndClose();
|
||||
|
||||
private:
|
||||
|
||||
LLTransactionID mTransactionID;
|
||||
LLAssetID mImageID;
|
||||
LLPointer<LLViewerTexture> mImage;
|
||||
LLSafeHandle<LLParcelSelection> mParcelp;
|
||||
S32 mParcelID;
|
||||
LLHost mParcelHost;
|
||||
|
||||
std::string mParcelUpdateCapUrl; // "ParcelPropertiesUpdate" capability
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -134,8 +134,9 @@ namespace
|
||||
}
|
||||
} //namespace
|
||||
|
||||
const LLColor4* mm_getMarkerColor(const LLUUID& id, bool mark_only = true);
|
||||
LLAvatarListEntry::LLAvatarListEntry(const LLUUID& id, const std::string& name, const LLVector3d& position) :
|
||||
mID(id), mName(name), mPosition(position), mMarked(false), mFocused(false),
|
||||
mID(id), mName(name), mPosition(position), mMarked(mm_getMarkerColor(id)), mFocused(false),
|
||||
mStats(),
|
||||
mActivityType(ACTIVITY_NEW), mActivityTimer(),
|
||||
mIsInList(false), mAge(-1), mTime(time(NULL))
|
||||
@@ -348,7 +349,14 @@ void track_av(const LLUUID& id)
|
||||
}
|
||||
|
||||
static void cmd_profile(const LLAvatarListEntry* entry);
|
||||
static void cmd_toggle_mark(LLAvatarListEntry* entry);
|
||||
static void cmd_toggle_mark(LLAvatarListEntry* entry)
|
||||
{
|
||||
bool mark = !entry->isMarked();
|
||||
void mm_setcolor(LLUUID key, LLColor4 col);
|
||||
void mm_clearMark(const LLUUID & id);
|
||||
mark ? mm_setcolor(entry->getID(), LLColor4::red) : mm_clearMark(entry->getID());
|
||||
entry->setMarked(mark);
|
||||
}
|
||||
static void cmd_ar(const LLAvatarListEntry* entry);
|
||||
static void cmd_teleport(const LLAvatarListEntry* entry);
|
||||
|
||||
@@ -364,15 +372,6 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
class RadarMark : public view_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
{
|
||||
LLFloaterAvatarList::instance().doCommand(cmd_toggle_mark);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class RadarFocus : public view_listener_t
|
||||
{
|
||||
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
|
||||
@@ -415,7 +414,6 @@ void addMenu(view_listener_t* menu, const std::string& name);
|
||||
void add_radar_listeners()
|
||||
{
|
||||
addMenu(new RadarTrack, "Radar.Track");
|
||||
addMenu(new RadarMark, "Radar.Mark");
|
||||
addMenu(new RadarFocus, "Radar.Focus");
|
||||
addMenu(new RadarFocusPrev, "Radar.FocusPrev");
|
||||
addMenu(new RadarFocusNext, "Radar.FocusNext");
|
||||
@@ -779,7 +777,7 @@ void LLFloaterAvatarList::refreshAvatarList()
|
||||
if (entry->isMarked())
|
||||
{
|
||||
mark.value = "X";
|
||||
mark.color = LLColor4::blue;
|
||||
mark.color = *mm_getMarkerColor(av_id);
|
||||
mark.font_style = "BOLD";
|
||||
}
|
||||
element.columns.add(mark);
|
||||
@@ -1449,7 +1447,6 @@ void send_estate_message(const std::string request, const std::vector<std::strin
|
||||
|
||||
static void cmd_append_names(const LLAvatarListEntry* entry, std::string &str, std::string &sep)
|
||||
{ if(!str.empty())str.append(sep);str.append(entry->getName()); }
|
||||
static void cmd_toggle_mark(LLAvatarListEntry* entry) { entry->toggleMark(); }
|
||||
static void cmd_ar(const LLAvatarListEntry* entry) { LLFloaterReporter::showFromObject(entry->getID()); }
|
||||
static void cmd_profile(const LLAvatarListEntry* entry) { LLAvatarActions::showProfile(entry->getID()); }
|
||||
static void cmd_teleport(const LLAvatarListEntry* entry) { gAgent.teleportViaLocation(entry->getPosition()); }
|
||||
|
||||
@@ -124,7 +124,7 @@ enum ACTIVITY_TYPE
|
||||
|
||||
bool isInList() const { return mIsInList; }
|
||||
|
||||
void toggleMark() { mMarked = !mMarked; }
|
||||
void setMarked(bool marked) { mMarked = marked; }
|
||||
|
||||
struct uuidMatch
|
||||
{
|
||||
|
||||
167
indra/newview/llfloaterexperiencepicker.cpp
Normal file
167
indra/newview/llfloaterexperiencepicker.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* @file llfloaterexperiencepicker.cpp
|
||||
* @brief Implementation of llfloaterexperiencepicker
|
||||
* @author dolphin@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfloaterexperiencepicker.h"
|
||||
|
||||
|
||||
#include "lllineeditor.h"
|
||||
//#include "llfloaterreg.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llagent.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llslurl.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llfloaterexperienceprofile.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "lldraghandle.h"
|
||||
#include "llpanelexperiencepicker.h"
|
||||
|
||||
// <singu>
|
||||
LLFloaterExperiencePicker* show_xp_picker(const LLSD& key)
|
||||
{
|
||||
LLFloaterExperiencePicker* floater =
|
||||
LLFloaterExperiencePicker::getInstance(key);
|
||||
if (!floater)
|
||||
{
|
||||
floater = new LLFloaterExperiencePicker(key);
|
||||
}
|
||||
floater->open();
|
||||
return floater;
|
||||
}
|
||||
// </singu>
|
||||
|
||||
LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL close_on_select, filter_list filters, LLView * frustumOrigin )
|
||||
{
|
||||
LLFloaterExperiencePicker* floater = show_xp_picker(key);
|
||||
|
||||
if (floater->mSearchPanel)
|
||||
{
|
||||
floater->mSearchPanel->mSelectionCallback = callback;
|
||||
floater->mSearchPanel->mCloseOnSelect = close_on_select;
|
||||
floater->mSearchPanel->setAllowMultiple(allow_multiple);
|
||||
floater->mSearchPanel->setDefaultFilters();
|
||||
floater->mSearchPanel->addFilters(filters.begin(), filters.end());
|
||||
floater->mSearchPanel->filterContent();
|
||||
}
|
||||
|
||||
if(frustumOrigin)
|
||||
{
|
||||
floater->mFrustumOrigin = frustumOrigin->getHandle();
|
||||
}
|
||||
|
||||
return floater;
|
||||
}
|
||||
|
||||
void LLFloaterExperiencePicker::drawFrustum()
|
||||
{
|
||||
if(mFrustumOrigin.get())
|
||||
{
|
||||
LLView * frustumOrigin = mFrustumOrigin.get();
|
||||
LLRect origin_rect;
|
||||
frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this);
|
||||
// draw context cone connecting color picker with color swatch in parent floater
|
||||
LLRect local_rect = getLocalRect();
|
||||
if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
LLGLEnable<GL_CULL_FACE> cull_face;
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
{
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(local_rect.mRight, local_rect.mTop);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
|
||||
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
|
||||
gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
|
||||
if (gFocusMgr.childHasMouseCapture(getDragHandle()))
|
||||
{
|
||||
mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperiencePicker::draw()
|
||||
{
|
||||
drawFrustum();
|
||||
LLFloater::draw();
|
||||
}
|
||||
|
||||
LLFloaterExperiencePicker::LLFloaterExperiencePicker( const LLSD& key )
|
||||
:LLFloater()
|
||||
,LLInstanceTracker<LLFloaterExperiencePicker, LLUUID>(key.asUUID())
|
||||
,mSearchPanel(nullptr)
|
||||
,mContextConeOpacity(0.f)
|
||||
,mContextConeInAlpha(0.f)
|
||||
,mContextConeOutAlpha(0.f)
|
||||
,mContextConeFadeTime(0.f)
|
||||
{
|
||||
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
|
||||
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
|
||||
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
|
||||
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_experience_search.xml", NULL, false);
|
||||
//buildFromFile("floater_experience_search.xml");
|
||||
}
|
||||
|
||||
LLFloaterExperiencePicker::~LLFloaterExperiencePicker()
|
||||
{
|
||||
gFocusMgr.releaseFocusIfNeeded( this );
|
||||
}
|
||||
|
||||
BOOL LLFloaterExperiencePicker::postBuild()
|
||||
{
|
||||
mSearchPanel = new LLPanelExperiencePicker();
|
||||
addChild(mSearchPanel);
|
||||
mSearchPanel->setOrigin(0, 0);
|
||||
return LLFloater::postBuild();
|
||||
}
|
||||
69
indra/newview/llfloaterexperiencepicker.h
Normal file
69
indra/newview/llfloaterexperiencepicker.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @file llfloaterexperiencepicker.h
|
||||
* @brief Header file for llfloaterexperiencepicker
|
||||
* @author dolphin@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LL_LLFLOATEREXPERIENCEPICKER_H
|
||||
#define LL_LLFLOATEREXPERIENCEPICKER_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "llinstancetracker.h"
|
||||
|
||||
class LLScrollListCtrl;
|
||||
class LLLineEditor;
|
||||
class LLPanelExperiencePicker;
|
||||
|
||||
|
||||
class LLFloaterExperiencePicker : public LLFloater
|
||||
, public LLInstanceTracker<LLFloaterExperiencePicker, LLUUID>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::function<void (const uuid_vec_t&)> select_callback_t;
|
||||
// filter function for experiences, return true if the experience should be hidden.
|
||||
typedef std::function<bool (const LLSD&)> filter_function;
|
||||
typedef std::vector<filter_function> filter_list;
|
||||
|
||||
static LLFloaterExperiencePicker* show( select_callback_t callback, const LLUUID& key, BOOL allow_multiple, BOOL close_on_select, filter_list filters, LLView * frustumOrigin);
|
||||
|
||||
LLFloaterExperiencePicker(const LLSD& key);
|
||||
virtual ~LLFloaterExperiencePicker();
|
||||
|
||||
BOOL postBuild() override;
|
||||
|
||||
void draw() override;
|
||||
private:
|
||||
|
||||
LLPanelExperiencePicker* mSearchPanel;
|
||||
|
||||
void drawFrustum();
|
||||
LLHandle <LLView> mFrustumOrigin;
|
||||
F32 mContextConeOpacity;
|
||||
F32 mContextConeInAlpha;
|
||||
F32 mContextConeOutAlpha;
|
||||
F32 mContextConeFadeTime;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATEREXPERIENCEPICKER_H
|
||||
|
||||
934
indra/newview/llfloaterexperienceprofile.cpp
Normal file
934
indra/newview/llfloaterexperienceprofile.cpp
Normal file
@@ -0,0 +1,934 @@
|
||||
/**
|
||||
* @file llfloaterexperienceprofile.cpp
|
||||
* @brief llfloaterexperienceprofile and related class definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llfloaterexperienceprofile.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llcommandhandler.h"
|
||||
//#include "llexpandabletextbox.h"
|
||||
#include "llexperiencecache.h"
|
||||
//#include "llfloaterreg.h"
|
||||
#include "llgroupactions.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "lllayoutstack.h"
|
||||
#include "lllineeditor.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llslurl.h"
|
||||
#include "lltabcontainer.h"
|
||||
#include "lltextbox.h"
|
||||
#include "lltexteditor.h"
|
||||
#include "lltexturectrl.h"
|
||||
#include "lltrans.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llevents.h"
|
||||
#include "llfloatergroups.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llfloaterreporter.h"
|
||||
#include "llurlaction.h"
|
||||
|
||||
#define XML_PANEL_EXPERIENCE_PROFILE "floater_experienceprofile.xml"
|
||||
#define TF_NAME "experience_title"
|
||||
#define TF_DESC "experience_description"
|
||||
#define TF_SLURL "LocationTextText"
|
||||
#define TF_MRKT "marketplace"
|
||||
#define TF_MATURITY "ContentRatingText"
|
||||
#define TF_OWNER "OwnerText"
|
||||
#define TF_GROUP "GroupText"
|
||||
#define TF_GRID_WIDE "grid_wide"
|
||||
#define TF_PRIVILEGED "privileged"
|
||||
#define EDIT "edit_"
|
||||
|
||||
#define IMG_LOGO "logo"
|
||||
|
||||
#define PNL_TOP "top panel"
|
||||
#define PNL_IMAGE "image_panel"
|
||||
#define PNL_DESC "description panel"
|
||||
#define PNL_LOC "location panel"
|
||||
#define PNL_MRKT "marketplace panel"
|
||||
#define PNL_GROUP "group_panel"
|
||||
#define PNL_PERMS "perm panel"
|
||||
|
||||
#define BTN_ALLOW "allow_btn"
|
||||
#define BTN_BLOCK "block_btn"
|
||||
#define BTN_CANCEL "cancel_btn"
|
||||
#define BTN_CLEAR_LOCATION "clear_btn"
|
||||
#define BTN_EDIT "edit_btn"
|
||||
#define BTN_ENABLE "enable_btn"
|
||||
#define BTN_FORGET "forget_btn"
|
||||
#define BTN_PRIVATE "private_btn"
|
||||
#define BTN_REPORT "report_btn"
|
||||
#define BTN_SAVE "save_btn"
|
||||
#define BTN_SET_GROUP "Group_btn"
|
||||
#define BTN_SET_LOCATION "location_btn"
|
||||
|
||||
|
||||
class LLExperienceHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
LLExperienceHandler() : LLCommandHandler("experience", UNTRUSTED_THROTTLE) { }
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map,
|
||||
LLMediaCtrl* web) override
|
||||
{
|
||||
if (params.size() != 2 || params[1].asString() != "profile")
|
||||
return false;
|
||||
|
||||
LLExperienceCache::instance().get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1));
|
||||
return true;
|
||||
}
|
||||
|
||||
void experienceCallback(const LLSD& experienceDetails)
|
||||
{
|
||||
if (!experienceDetails.has(LLExperienceCache::MISSING))
|
||||
{
|
||||
LLFloaterExperienceProfile::showInstance(experienceDetails[LLExperienceCache::EXPERIENCE_ID].asUUID());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
LLExperienceHandler gExperienceHandler;
|
||||
|
||||
void LLFloaterExperienceProfile::showInstance(const LLSD& data)
|
||||
{
|
||||
bool is_map = data.has("experience_id");
|
||||
LLFloaterExperienceProfile* floater = getInstance(is_map ? data["experience_id"].asUUID() : data.asUUID());
|
||||
if (!floater) floater = new LLFloaterExperienceProfile(data);
|
||||
else if (is_map && data.has("edit_experience") && data["edit_experience"].asBoolean())
|
||||
floater->changeToEdit();
|
||||
floater->open();
|
||||
}
|
||||
|
||||
LLFloaterExperienceProfile::LLFloaterExperienceProfile(const LLSD& data)
|
||||
: LLFloater(), LLInstanceTracker<LLFloaterExperienceProfile, LLUUID>(data.asUUID())
|
||||
, mSaveCompleteAction(NOTHING)
|
||||
, mDirty(false)
|
||||
, mForceClose(false)
|
||||
{
|
||||
if (data.has("experience_id"))
|
||||
{
|
||||
mExperienceId = data["experience_id"].asUUID();
|
||||
mPostEdit = data.has("edit_experience") && data["edit_experience"].asBoolean();
|
||||
}
|
||||
else
|
||||
{
|
||||
mExperienceId = data.asUUID();
|
||||
mPostEdit = false;
|
||||
}
|
||||
LLUICtrlFactory::getInstance()->buildFloater(this, XML_PANEL_EXPERIENCE_PROFILE, NULL, false);
|
||||
//buildFromFile(XML_PANEL_EXPERIENCE_PROFILE);
|
||||
}
|
||||
|
||||
|
||||
LLFloaterExperienceProfile::~LLFloaterExperienceProfile()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BOOL LLFloaterExperienceProfile::postBuild()
|
||||
{
|
||||
|
||||
if (mExperienceId.notNull())
|
||||
{
|
||||
LLExperienceCache::instance().fetch(mExperienceId, true);
|
||||
LLExperienceCache::instance().get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback,
|
||||
getDerivedHandle<LLFloaterExperienceProfile>(), _1));
|
||||
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
LLExperienceCache::instance().getExperienceAdmin(mExperienceId, boost::bind(
|
||||
&LLFloaterExperienceProfile::experienceIsAdmin, getDerivedHandle<LLFloaterExperienceProfile>(), _1));
|
||||
}
|
||||
}
|
||||
|
||||
childSetAction(BTN_EDIT, boost::bind(&LLFloaterExperienceProfile::onClickEdit, this));
|
||||
childSetAction(BTN_ALLOW, boost::bind(&LLFloaterExperienceProfile::onClickPermission, this, "Allow"));
|
||||
childSetAction(BTN_FORGET, boost::bind(&LLFloaterExperienceProfile::onClickForget, this));
|
||||
childSetAction(BTN_BLOCK, boost::bind(&LLFloaterExperienceProfile::onClickPermission, this, "Block"));
|
||||
childSetAction(BTN_CANCEL, boost::bind(&LLFloaterExperienceProfile::onClickCancel, this));
|
||||
childSetAction(BTN_SAVE, boost::bind(&LLFloaterExperienceProfile::onClickSave, this));
|
||||
childSetAction(BTN_SET_LOCATION, boost::bind(&LLFloaterExperienceProfile::onClickLocation, this));
|
||||
childSetAction(BTN_CLEAR_LOCATION, boost::bind(&LLFloaterExperienceProfile::onClickClear, this));
|
||||
childSetAction(BTN_SET_GROUP, boost::bind(&LLFloaterExperienceProfile::onPickGroup, this));
|
||||
childSetAction(BTN_REPORT, boost::bind(&LLFloaterExperienceProfile::onReportExperience, this));
|
||||
|
||||
getChild<LLTextEditor>(EDIT TF_DESC)->setKeystrokeCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this));
|
||||
getChild<LLUICtrl>(EDIT TF_MATURITY)->setCommitCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this));
|
||||
getChild<LLLineEditor>(EDIT TF_MRKT)->setKeystrokeCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this));
|
||||
getChild<LLLineEditor>(EDIT TF_NAME)->setKeystrokeCallback(boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this));
|
||||
|
||||
childSetCommitCallback(EDIT BTN_ENABLE, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), nullptr);
|
||||
childSetCommitCallback(EDIT BTN_PRIVATE, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), nullptr);
|
||||
|
||||
childSetCommitCallback(EDIT IMG_LOGO, boost::bind(&LLFloaterExperienceProfile::onFieldChanged, this), nullptr);
|
||||
|
||||
if (auto logo = findChild<LLTextureCtrl>(IMG_LOGO))
|
||||
{
|
||||
void show_picture(const LLUUID& id, const std::string& name);
|
||||
LLTextBox* name = getChild<LLTextBox>(TF_NAME);
|
||||
std::function<void()> cb = [logo, name]() { show_picture(logo->getImageAssetID(), "Experience Picture: " + name->getText()); };
|
||||
logo->setMouseUpCallback(boost::bind(cb));
|
||||
}
|
||||
|
||||
getChild<LLTextEditor>(EDIT TF_DESC)->setCommitOnFocusLost(TRUE);
|
||||
|
||||
LLEventPumps::instance().obtain("experience_permission").listen(mExperienceId.asString()+"-profile",
|
||||
boost::bind(&LLFloaterExperienceProfile::experiencePermission, getDerivedHandle<LLFloaterExperienceProfile>(this), _1));
|
||||
|
||||
if (mPostEdit && mExperienceId.notNull())
|
||||
{
|
||||
mPostEdit = false;
|
||||
changeToEdit();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::experienceCallback(LLHandle<LLFloaterExperienceProfile> handle, const LLSD& experience )
|
||||
{
|
||||
LLFloaterExperienceProfile* pllpep = handle.get();
|
||||
if (pllpep)
|
||||
{
|
||||
pllpep->refreshExperience(experience);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLFloaterExperienceProfile::experiencePermission( LLHandle<LLFloaterExperienceProfile> handle, const LLSD& permission )
|
||||
{
|
||||
LLFloaterExperienceProfile* pllpep = handle.get();
|
||||
if (pllpep)
|
||||
{
|
||||
pllpep->updatePermission(permission);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterExperienceProfile::onClickEdit()
|
||||
{
|
||||
changeToEdit();
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterExperienceProfile::onClickCancel()
|
||||
{
|
||||
changeToView();
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::onClickSave()
|
||||
{
|
||||
doSave(NOTHING);
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::onClickPermission(const char* perm)
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (!region)
|
||||
return;
|
||||
LLExperienceCache::instance().setExperiencePermission(mExperienceId, perm, boost::bind(
|
||||
&LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterExperienceProfile::onClickForget()
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (!region)
|
||||
return;
|
||||
|
||||
LLExperienceCache::instance().forgetExperiencePermission(mExperienceId, boost::bind(
|
||||
&LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
|
||||
}
|
||||
|
||||
bool LLFloaterExperienceProfile::setMaturityString( U8 maturity, LLTextBox* child, LLComboBox* combo )
|
||||
{
|
||||
//LLStyle::Params style; // Singu Note: Nope.
|
||||
std::string access;
|
||||
if (maturity <= SIM_ACCESS_PG)
|
||||
{
|
||||
//style.image(LLUI::getUIImage(getString("maturity_icon_general"))); // Singu Note: Nope.
|
||||
access = LLTrans::getString("SIM_ACCESS_PG");
|
||||
combo->setCurrentByIndex(2);
|
||||
}
|
||||
else if (maturity <= SIM_ACCESS_MATURE)
|
||||
{
|
||||
//style.image(LLUI::getUIImage(getString("maturity_icon_moderate"))); // Singu Note: Nope.
|
||||
access = LLTrans::getString("SIM_ACCESS_MATURE");
|
||||
combo->setCurrentByIndex(1);
|
||||
}
|
||||
else if (maturity <= SIM_ACCESS_ADULT)
|
||||
{
|
||||
//style.image(LLUI::getUIImage(getString("maturity_icon_adult"))); // Singu Note: Nope.
|
||||
access = LLTrans::getString("SIM_ACCESS_ADULT");
|
||||
combo->setCurrentByIndex(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Singu Note: Nope.
|
||||
child->setText(LLStringUtil::null);
|
||||
|
||||
child->appendImageSegment(style);
|
||||
*/
|
||||
child->setText(access);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience )
|
||||
{
|
||||
mExperienceDetails = experience;
|
||||
mPackage = experience;
|
||||
|
||||
|
||||
LLLayoutPanel* imagePanel = getChild<LLLayoutPanel>(PNL_IMAGE);
|
||||
LLLayoutPanel* descriptionPanel = getChild<LLLayoutPanel>(PNL_DESC);
|
||||
LLLayoutPanel* locationPanel = getChild<LLLayoutPanel>(PNL_LOC);
|
||||
LLLayoutPanel* marketplacePanel = getChild<LLLayoutPanel>(PNL_MRKT);
|
||||
LLLayoutPanel* topPanel = getChild<LLLayoutPanel>(PNL_TOP);
|
||||
|
||||
|
||||
imagePanel->setVisible(FALSE);
|
||||
descriptionPanel->setVisible(FALSE);
|
||||
locationPanel->setVisible(FALSE);
|
||||
marketplacePanel->setVisible(FALSE);
|
||||
topPanel->setVisible(FALSE);
|
||||
|
||||
|
||||
LLTextBox* child = getChild<LLTextBox>(TF_NAME);
|
||||
//child->setText(experience[LLExperienceCache::NAME].asString());
|
||||
child->setValue(experience[LLExperienceCache::EXPERIENCE_ID].asUUID());
|
||||
|
||||
LLLineEditor* linechild = getChild<LLLineEditor>(EDIT TF_NAME);
|
||||
linechild->setText(experience[LLExperienceCache::NAME].asString());
|
||||
|
||||
std::string value = experience[LLExperienceCache::DESCRIPTION].asString();
|
||||
LLTextEditor* exchild = getChild<LLTextEditor>(TF_DESC);
|
||||
exchild->setText(value);
|
||||
descriptionPanel->setVisible(value.length()>0);
|
||||
|
||||
LLTextEditor* edit_child = getChild<LLTextEditor>(EDIT TF_DESC);
|
||||
edit_child->setText(value);
|
||||
|
||||
mLocationSLURL = experience[LLExperienceCache::SLURL].asString();
|
||||
edit_child = getChild<LLTextEditor>(TF_SLURL);
|
||||
bool has_slurl = !mLocationSLURL.empty() && mLocationSLURL != "last";
|
||||
locationPanel->setVisible(has_slurl);
|
||||
if (has_slurl) mLocationSLURL = LLSLURL(mLocationSLURL).getSLURLString();
|
||||
edit_child->setText(mLocationSLURL);
|
||||
|
||||
|
||||
edit_child = getChild<LLTextEditor>(EDIT TF_SLURL);
|
||||
if (has_slurl)
|
||||
{
|
||||
edit_child->setText(mLocationSLURL);
|
||||
}
|
||||
else
|
||||
{
|
||||
edit_child->setText(getString("empty_slurl"));
|
||||
}
|
||||
|
||||
setMaturityString((U8)(experience[LLExperienceCache::MATURITY].asInteger()), getChild<LLTextBox>(TF_MATURITY), getChild<LLComboBox>(EDIT TF_MATURITY));
|
||||
|
||||
LLUUID agent_id = experience[LLExperienceCache::AGENT_ID].asUUID();
|
||||
getChild<LLTextBox>(TF_OWNER)->setValue(agent_id);
|
||||
|
||||
LLUUID id = experience[LLExperienceCache::GROUP_ID].asUUID();
|
||||
bool id_null = id.isNull();
|
||||
if (!id_null)
|
||||
{
|
||||
getChild<LLTextBox>(TF_GROUP)->setValue(id);
|
||||
}
|
||||
getChild<LLLayoutPanel>(PNL_GROUP)->setVisible(!id_null);
|
||||
|
||||
setEditGroup(id);
|
||||
|
||||
getChild<LLButton>(BTN_SET_GROUP)->setEnabled(agent_id == gAgentID);
|
||||
|
||||
LLCheckBoxCtrl* enable = getChild<LLCheckBoxCtrl>(EDIT BTN_ENABLE);
|
||||
S32 properties = mExperienceDetails[LLExperienceCache::PROPERTIES].asInteger();
|
||||
enable->set(!(properties & LLExperienceCache::PROPERTY_DISABLED));
|
||||
|
||||
enable = getChild<LLCheckBoxCtrl>(EDIT BTN_PRIVATE);
|
||||
enable->set(properties & LLExperienceCache::PROPERTY_PRIVATE);
|
||||
|
||||
topPanel->setVisible(TRUE);
|
||||
child=getChild<LLTextBox>(TF_GRID_WIDE);
|
||||
child->setVisible(TRUE);
|
||||
|
||||
if(properties & LLExperienceCache::PROPERTY_GRID)
|
||||
{
|
||||
child->setText(LLTrans::getString("Grid-Scope"));
|
||||
}
|
||||
else
|
||||
{
|
||||
child->setText(LLTrans::getString("Land-Scope"));
|
||||
}
|
||||
|
||||
if (getChild<LLButton>(BTN_EDIT)->getVisible())
|
||||
{
|
||||
topPanel->setVisible(TRUE);
|
||||
}
|
||||
|
||||
if (properties & LLExperienceCache::PROPERTY_PRIVILEGED)
|
||||
{
|
||||
child = getChild<LLTextBox>(TF_PRIVILEGED);
|
||||
child->setVisible(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
LLExperienceCache::instance().getExperiencePermission(mExperienceId, boost::bind(
|
||||
&LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
|
||||
}
|
||||
}
|
||||
|
||||
value=experience[LLExperienceCache::METADATA].asString();
|
||||
if (value.empty())
|
||||
return;
|
||||
|
||||
LLPointer<LLSDParser> parser = new LLSDXMLParser();
|
||||
|
||||
LLSD data;
|
||||
|
||||
std::istringstream is(value);
|
||||
if (LLSDParser::PARSE_FAILURE != parser->parse(is, data, value.size()))
|
||||
{
|
||||
value.clear();
|
||||
if (data.has(TF_MRKT))
|
||||
{
|
||||
value=data[TF_MRKT].asString();
|
||||
|
||||
edit_child = getChild<LLTextEditor>(TF_MRKT);
|
||||
edit_child->setText(value);
|
||||
if(!value.empty())
|
||||
{
|
||||
marketplacePanel->setVisible(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
marketplacePanel->setVisible(FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
marketplacePanel->setVisible(FALSE);
|
||||
}
|
||||
|
||||
linechild = getChild<LLLineEditor>(EDIT TF_MRKT);
|
||||
linechild->setText(value);
|
||||
|
||||
if (data.has(IMG_LOGO))
|
||||
{
|
||||
LLTextureCtrl* logo = getChild<LLTextureCtrl>(IMG_LOGO);
|
||||
|
||||
LLUUID id = data[IMG_LOGO].asUUID();
|
||||
logo->setImageAssetID(id);
|
||||
imagePanel->setVisible(TRUE);
|
||||
|
||||
logo = getChild<LLTextureCtrl>(EDIT IMG_LOGO);
|
||||
logo->setImageAssetID(data[IMG_LOGO].asUUID());
|
||||
|
||||
imagePanel->setVisible(id.notNull());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
marketplacePanel->setVisible(FALSE);
|
||||
imagePanel->setVisible(FALSE);
|
||||
}
|
||||
|
||||
mDirty=false;
|
||||
mForceClose = false;
|
||||
getChild<LLButton>(BTN_SAVE)->setEnabled(mDirty);
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::setPreferences( const LLSD& content )
|
||||
{
|
||||
S32 properties = mExperienceDetails[LLExperienceCache::PROPERTIES].asInteger();
|
||||
if (properties & LLExperienceCache::PROPERTY_PRIVILEGED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const LLSD& experiences = content["experiences"];
|
||||
const LLSD& blocked = content["blocked"];
|
||||
|
||||
|
||||
for(const auto& exp : experiences.array())
|
||||
{
|
||||
if (exp.asUUID()==mExperienceId)
|
||||
{
|
||||
experienceAllowed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for(const auto& exp : blocked.array())
|
||||
{
|
||||
if (exp.asUUID()==mExperienceId)
|
||||
{
|
||||
experienceBlocked();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
experienceForgotten();
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::onFieldChanged()
|
||||
{
|
||||
updatePackage();
|
||||
|
||||
if (!getChild<LLButton>(BTN_EDIT)->getVisible())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mDirty = mPackage.size() != mExperienceDetails.size();
|
||||
if (!mDirty)
|
||||
{
|
||||
LLSD::map_const_iterator st = mExperienceDetails.beginMap();
|
||||
LLSD::map_const_iterator dt = mPackage.beginMap();
|
||||
LLSD::map_const_iterator ste = mExperienceDetails.endMap();
|
||||
LLSD::map_const_iterator dte = mPackage.endMap();
|
||||
for (; st != ste && dt != dte; ++st, ++dt)
|
||||
if (mDirty = st->first != dt->first || st->second.asString() != dt->second.asString())
|
||||
break;
|
||||
}
|
||||
|
||||
getChild<LLButton>(BTN_SAVE)->setEnabled(mDirty);
|
||||
}
|
||||
|
||||
|
||||
BOOL LLFloaterExperienceProfile::canClose()
|
||||
{
|
||||
if (mForceClose || !mDirty)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bring up view-modal dialog: Save changes? Yes, No, Cancel
|
||||
LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLFloaterExperienceProfile::handleSaveChangesDialog, this, _1, _2, CLOSE));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFloaterExperienceProfile::handleSaveChangesDialog( const LLSD& notification, const LLSD& response, PostSaveAction action )
|
||||
{
|
||||
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
switch( option )
|
||||
{
|
||||
case 0: // "Yes"
|
||||
// close after saving
|
||||
doSave( action );
|
||||
break;
|
||||
|
||||
case 1: // "No"
|
||||
if (action != NOTHING)
|
||||
{
|
||||
mForceClose = TRUE;
|
||||
if (action==CLOSE)
|
||||
{
|
||||
close();
|
||||
}
|
||||
else
|
||||
{
|
||||
changeToView();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // "Cancel"
|
||||
default:
|
||||
// If we were quitting, we didn't really mean it.
|
||||
LLAppViewer::instance()->abortQuit();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::doSave( int success_action )
|
||||
{
|
||||
mSaveCompleteAction=success_action;
|
||||
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (!region)
|
||||
return;
|
||||
|
||||
LLExperienceCache::instance().updateExperience(mPackage, boost::bind(
|
||||
&LLFloaterExperienceProfile::experienceUpdateResult,
|
||||
getDerivedHandle<LLFloaterExperienceProfile>(), _1));
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content )
|
||||
{
|
||||
LLUUID id = getExperienceId();
|
||||
|
||||
if (content.has("removed"))
|
||||
{
|
||||
const LLSD& removed = content["removed"];
|
||||
for(const auto& it : removed.map())
|
||||
{
|
||||
const std::string& field = it.first;
|
||||
if (field == LLExperienceCache::EXPERIENCE_ID)
|
||||
{
|
||||
//this message should be removed by the experience api
|
||||
continue;
|
||||
}
|
||||
const LLSD& data = it.second;
|
||||
std::string error_tag = data["error_tag"].asString()+ "ExperienceProfileMessage";
|
||||
LLSD fields;
|
||||
if (LLNotificationTemplates::instance().templateExists(error_tag))
|
||||
{
|
||||
fields["field"] = field;
|
||||
fields["extra_info"] = data["extra_info"];
|
||||
LLNotificationsUtil::add(error_tag, fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
fields["MESSAGE"] = data["en"];
|
||||
LLNotificationsUtil::add("GenericAlert", fields);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!content.has("experience_keys"))
|
||||
{
|
||||
LL_WARNS() << "LLFloaterExperienceProfile::onSaveComplete called with bad content" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
const LLSD& experiences = content["experience_keys"];
|
||||
|
||||
if (experiences.size() == 0)
|
||||
{
|
||||
LL_WARNS() << "LLFloaterExperienceProfile::onSaveComplete called with empty content" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& exp = experiences[0];
|
||||
if (!exp.has(LLExperienceCache::EXPERIENCE_ID) || (exp[LLExperienceCache::EXPERIENCE_ID].asUUID() != id))
|
||||
{
|
||||
LL_WARNS() << "LLFloaterExperienceProfile::onSaveComplete called with unexpected experience id" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
refreshExperience(exp);
|
||||
LLExperienceCache::instance().insert(exp);
|
||||
LLExperienceCache::instance().fetch(id, true);
|
||||
|
||||
if (mSaveCompleteAction == VIEW)
|
||||
{
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("tab_container");
|
||||
tabs->selectTabByName("panel_experience_info");
|
||||
}
|
||||
else if (mSaveCompleteAction == CLOSE)
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::changeToView()
|
||||
{
|
||||
if (mForceClose || !mDirty)
|
||||
{
|
||||
refreshExperience(mExperienceDetails);
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("tab_container");
|
||||
|
||||
tabs->selectTabByName("panel_experience_info");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bring up view-modal dialog: Save changes? Yes, No, Cancel
|
||||
LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLFloaterExperienceProfile::handleSaveChangesDialog, this, _1, _2, VIEW));
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::changeToEdit()
|
||||
{
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("tab_container");
|
||||
|
||||
tabs->selectTabByName("edit_panel_experience_info");
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::onClickLocation()
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
auto child = getChild<LLTextEditor>(EDIT TF_SLURL);
|
||||
mLocationSLURL = LLSLURL(region->getName(), gAgent.getPositionGlobal()).getSLURLString();
|
||||
child->setText(mLocationSLURL);
|
||||
onFieldChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::onClickClear()
|
||||
{
|
||||
auto child = getChild<LLTextEditor>(EDIT TF_SLURL);
|
||||
mLocationSLURL.clear();
|
||||
child->setText(getString("empty_slurl"));
|
||||
onFieldChanged();
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::updatePermission(const LLSD& permission)
|
||||
{
|
||||
if (permission.has("experience"))
|
||||
{
|
||||
if (permission["experience"].asUUID() != mExperienceId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string str = permission[mExperienceId.asString()]["permission"].asString();
|
||||
if (str == "Allow")
|
||||
{
|
||||
experienceAllowed();
|
||||
}
|
||||
else if (str == "Block")
|
||||
{
|
||||
experienceBlocked();
|
||||
}
|
||||
else if (str == "Forget")
|
||||
{
|
||||
experienceForgotten();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setPreferences(permission);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::experienceAllowed()
|
||||
{
|
||||
LLButton* button=getChild<LLButton>(BTN_ALLOW);
|
||||
button->setEnabled(FALSE);
|
||||
|
||||
button=getChild<LLButton>(BTN_FORGET);
|
||||
button->setEnabled(TRUE);
|
||||
|
||||
button=getChild<LLButton>(BTN_BLOCK);
|
||||
button->setEnabled(TRUE);
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::experienceForgotten()
|
||||
{
|
||||
LLButton* button=getChild<LLButton>(BTN_ALLOW);
|
||||
button->setEnabled(TRUE);
|
||||
|
||||
button=getChild<LLButton>(BTN_FORGET);
|
||||
button->setEnabled(FALSE);
|
||||
|
||||
button=getChild<LLButton>(BTN_BLOCK);
|
||||
button->setEnabled(TRUE);
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::experienceBlocked()
|
||||
{
|
||||
LLButton* button=getChild<LLButton>(BTN_ALLOW);
|
||||
button->setEnabled(TRUE);
|
||||
|
||||
button=getChild<LLButton>(BTN_FORGET);
|
||||
button->setEnabled(TRUE);
|
||||
|
||||
button=getChild<LLButton>(BTN_BLOCK);
|
||||
button->setEnabled(FALSE);
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::onClose( bool app_quitting )
|
||||
{
|
||||
LLEventPumps::instance().obtain("experience_permission").stopListening(mExperienceId.asString()+"-profile");
|
||||
LLFloater::onClose(app_quitting);
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::updatePackage()
|
||||
{
|
||||
mPackage[LLExperienceCache::NAME] = getChild<LLLineEditor>(EDIT TF_NAME)->getText();
|
||||
mPackage[LLExperienceCache::DESCRIPTION] = getChild<LLTextEditor>(EDIT TF_DESC)->getText();
|
||||
if (mLocationSLURL.empty())
|
||||
{
|
||||
mPackage[LLExperienceCache::SLURL] = LLStringUtil::null;
|
||||
}
|
||||
else
|
||||
{
|
||||
mPackage[LLExperienceCache::SLURL] = mLocationSLURL;
|
||||
}
|
||||
|
||||
mPackage[LLExperienceCache::MATURITY] = getChild<LLComboBox>(EDIT TF_MATURITY)->getSelectedValue().asInteger();
|
||||
|
||||
LLSD metadata;
|
||||
|
||||
metadata[TF_MRKT] = getChild<LLLineEditor>(EDIT TF_MRKT)->getText();
|
||||
metadata[IMG_LOGO] = getChild<LLTextureCtrl>(EDIT IMG_LOGO)->getImageAssetID();
|
||||
|
||||
LLPointer<LLSDXMLFormatter> formatter = new LLSDXMLFormatter();
|
||||
|
||||
std::ostringstream os;
|
||||
if (formatter->format(metadata, os))
|
||||
{
|
||||
mPackage[LLExperienceCache::METADATA] = os.str();
|
||||
}
|
||||
|
||||
int properties = mPackage[LLExperienceCache::PROPERTIES].asInteger();
|
||||
LLCheckBoxCtrl* enable = getChild<LLCheckBoxCtrl>(EDIT BTN_ENABLE);
|
||||
if (enable->get())
|
||||
{
|
||||
properties &= ~LLExperienceCache::PROPERTY_DISABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
properties |= LLExperienceCache::PROPERTY_DISABLED;
|
||||
}
|
||||
|
||||
enable = getChild<LLCheckBoxCtrl>(EDIT BTN_PRIVATE);
|
||||
if (enable->get())
|
||||
{
|
||||
properties |= LLExperienceCache::PROPERTY_PRIVATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
properties &= ~LLExperienceCache::PROPERTY_PRIVATE;
|
||||
}
|
||||
|
||||
mPackage[LLExperienceCache::PROPERTIES] = properties;
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::onPickGroup()
|
||||
{
|
||||
LLFloater* parent_floater = gFloaterView->getParentFloater(this);
|
||||
|
||||
LLFloaterGroupPicker* widget = LLFloaterGroupPicker::showInstance(gAgent.getID());
|
||||
if (widget)
|
||||
{
|
||||
widget->setSelectGroupCallback(boost::bind(&LLFloaterExperienceProfile::setEditGroup, this, _1));
|
||||
if (parent_floater)
|
||||
{
|
||||
LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget);
|
||||
widget->setOrigin(new_rect.mLeft, new_rect.mBottom);
|
||||
parent_floater->addDependentFloater(widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::setEditGroup( LLUUID group_id )
|
||||
{
|
||||
LLTextBox* child = getChild<LLTextBox>(EDIT TF_GROUP);
|
||||
child->setValue(group_id);
|
||||
mPackage[LLExperienceCache::GROUP_ID] = group_id;
|
||||
onFieldChanged();
|
||||
}
|
||||
|
||||
void LLFloaterExperienceProfile::onReportExperience()
|
||||
{
|
||||
LLFloaterReporter::showFromExperience(mExperienceId);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
bool LLFloaterExperienceProfile::hasPermission(const LLSD& content, const std::string &name, const LLUUID &test)
|
||||
{
|
||||
if (!content.has(name))
|
||||
return false;
|
||||
|
||||
const LLSD& list = content[name];
|
||||
for (const auto& it : list.array())
|
||||
{
|
||||
if (it.asUUID() == test)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void LLFloaterExperienceProfile::experiencePermissionResults(const LLUUID& exprienceId, const LLSD& result)
|
||||
{
|
||||
std::string permission("Forget");
|
||||
if (hasPermission(result, "experiences", exprienceId))
|
||||
permission = "Allow";
|
||||
else if (hasPermission(result, "blocked", exprienceId))
|
||||
permission = "Block";
|
||||
|
||||
LLSD experience;
|
||||
LLSD message;
|
||||
experience["permission"] = permission;
|
||||
message["experience"] = exprienceId;
|
||||
message[exprienceId.asString()] = experience;
|
||||
|
||||
LLEventPumps::instance().obtain("experience_permission").post(message);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void LLFloaterExperienceProfile::experienceIsAdmin(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result)
|
||||
{
|
||||
LLFloaterExperienceProfile* parent = handle.get();
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
bool enabled = true;
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (!region)
|
||||
{
|
||||
enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string url = region->getCapability("UpdateExperience");
|
||||
if (url.empty())
|
||||
enabled = false;
|
||||
}
|
||||
if (enabled && result["status"].asBoolean())
|
||||
{
|
||||
parent->getChild<LLLayoutPanel>(PNL_TOP)->setVisible(TRUE);
|
||||
parent->getChild<LLButton>(BTN_EDIT)->setVisible(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void LLFloaterExperienceProfile::experienceUpdateResult(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result)
|
||||
{
|
||||
LLFloaterExperienceProfile* parent = handle.get();
|
||||
if (parent)
|
||||
{
|
||||
parent->onSaveComplete(result);
|
||||
}
|
||||
}
|
||||
113
indra/newview/llfloaterexperienceprofile.h
Normal file
113
indra/newview/llfloaterexperienceprofile.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @file llfloaterexperienceprofile.h
|
||||
* @brief llfloaterexperienceprofile and related class definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef LL_LLFLOATEREXPERIENCEPROFILE_H
|
||||
#define LL_LLFLOATEREXPERIENCEPROFILE_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "lluuid.h"
|
||||
#include "llsd.h"
|
||||
|
||||
class LLLayoutPanel;
|
||||
class LLTextBox;
|
||||
class LLComboBox;
|
||||
|
||||
class LLFloaterExperienceProfile final : public LLFloater
|
||||
, public LLInstanceTracker<LLFloaterExperienceProfile, LLUUID>
|
||||
{
|
||||
LOG_CLASS(LLFloaterExperienceProfile);
|
||||
public:
|
||||
enum PostSaveAction
|
||||
{
|
||||
NOTHING,
|
||||
CLOSE,
|
||||
VIEW,
|
||||
};
|
||||
|
||||
static void experiencePermissionResults(const LLUUID& exprienceId, const LLSD& result);
|
||||
|
||||
static void showInstance(const LLSD& data);
|
||||
LLFloaterExperienceProfile(const LLSD& data);
|
||||
virtual ~LLFloaterExperienceProfile();
|
||||
|
||||
LLUUID getExperienceId() const { return mExperienceId; }
|
||||
void setPreferences( const LLSD& content );
|
||||
|
||||
|
||||
void refreshExperience(const LLSD& experience);
|
||||
void onSaveComplete( const LLSD& content );
|
||||
BOOL canClose() override;
|
||||
|
||||
void onClose(bool app_quitting) override;
|
||||
protected:
|
||||
void onClickEdit();
|
||||
void onClickPermission(const char* permission);
|
||||
void onClickForget();
|
||||
void onClickCancel();
|
||||
void onClickSave();
|
||||
void onClickLocation();
|
||||
void onClickClear();
|
||||
void onPickGroup();
|
||||
void onFieldChanged();
|
||||
void onReportExperience();
|
||||
|
||||
void setEditGroup(LLUUID group_id);
|
||||
|
||||
void changeToView();
|
||||
void changeToEdit();
|
||||
|
||||
void experienceForgotten();
|
||||
void experienceBlocked();
|
||||
void experienceAllowed();
|
||||
|
||||
static void experienceCallback(LLHandle<LLFloaterExperienceProfile> handle, const LLSD& experience);
|
||||
static bool experiencePermission(LLHandle<LLFloaterExperienceProfile> handle, const LLSD& permission);
|
||||
|
||||
BOOL postBuild() override;
|
||||
bool setMaturityString(U8 maturity, LLTextBox* child, LLComboBox* combo);
|
||||
bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response, PostSaveAction action);
|
||||
void doSave( int success_action );
|
||||
|
||||
void updatePackage();
|
||||
|
||||
void updatePermission( const LLSD& permission );
|
||||
LLUUID mExperienceId;
|
||||
LLSD mExperienceDetails;
|
||||
LLSD mPackage;
|
||||
std::string mLocationSLURL;
|
||||
int mSaveCompleteAction;
|
||||
bool mDirty;
|
||||
bool mForceClose;
|
||||
bool mPostEdit; // edit experience after opening and updating it
|
||||
private:
|
||||
static bool hasPermission(const LLSD& content, const std::string &name, const LLUUID &test);
|
||||
static void experienceIsAdmin(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result);
|
||||
static void experienceUpdateResult(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result);
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATEREXPERIENCEPROFILE_H
|
||||
377
indra/newview/llfloaterexperiences.cpp
Normal file
377
indra/newview/llfloaterexperiences.cpp
Normal file
@@ -0,0 +1,377 @@
|
||||
/**
|
||||
* @file llfloaterexperiences.cpp
|
||||
* @brief LLFloaterExperiences class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llfloaterexperiences.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llcororesponder.h"
|
||||
#include "llevents.h"
|
||||
#include "llexperiencecache.h"
|
||||
#include "llfloaterexperienceprofile.h"
|
||||
#include "llfloaterregioninfo.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llpanelexperiencelog.h"
|
||||
#include "llpanelexperiencepicker.h"
|
||||
#include "llpanelexperiences.h"
|
||||
#include "lltabcontainer.h"
|
||||
#include "lltrans.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
|
||||
#define SHOW_RECENT_TAB (0)
|
||||
LLFloaterExperiences::LLFloaterExperiences(const LLSD& data)
|
||||
:LLFloater(data)
|
||||
{
|
||||
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_experiences.xml", NULL, false);
|
||||
//buildFromFile("floater_experiences.xml");
|
||||
}
|
||||
|
||||
LLPanelExperiences* LLFloaterExperiences::addTab(const std::string& name, bool select)
|
||||
{
|
||||
LLPanelExperiences* newPanel = LLPanelExperiences::create(name);
|
||||
getChild<LLTabContainer>("xp_tabs")->addTabPanel(
|
||||
newPanel,
|
||||
LLTrans::getString(name),
|
||||
select);
|
||||
|
||||
return newPanel;
|
||||
}
|
||||
|
||||
BOOL LLFloaterExperiences::postBuild()
|
||||
{
|
||||
LLPanel* panel = new LLPanelExperiencePicker();
|
||||
getChild<LLTabContainer>("xp_tabs")->addTabPanel(panel, panel->getLabel());
|
||||
addTab("Allowed_Experiences_Tab", true);
|
||||
addTab("Blocked_Experiences_Tab", false);
|
||||
addTab("Admin_Experiences_Tab", false);
|
||||
addTab("Contrib_Experiences_Tab", false);
|
||||
LLPanelExperiences* owned = addTab("Owned_Experiences_Tab", false);
|
||||
owned->setButtonAction("acquire", boost::bind(&LLFloaterExperiences::sendPurchaseRequest, this));
|
||||
owned->enableButton(false);
|
||||
#if SHOW_RECENT_TAB
|
||||
addTab("Recent_Experiences_Tab", false);
|
||||
#endif //SHOW_RECENT_TAB
|
||||
panel = new LLPanelExperienceLog();
|
||||
getChild<LLTabContainer>("xp_tabs")->addTabPanel(panel, panel->getLabel());
|
||||
resizeToTabs();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterExperiences::clearFromRecent(const LLSD& ids)
|
||||
{
|
||||
#if SHOW_RECENT_TAB
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
||||
|
||||
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Recent_Experiences_Tab");
|
||||
if(!tab)
|
||||
return;
|
||||
|
||||
tab->removeExperiences(ids);
|
||||
#endif // SHOW_RECENT_TAB
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::setupRecentTabs()
|
||||
{
|
||||
#if SHOW_RECENT_TAB
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
||||
|
||||
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Recent_Experiences_Tab");
|
||||
if(!tab)
|
||||
return;
|
||||
|
||||
LLSD recent;
|
||||
|
||||
const LLExperienceCache::cache_t& experiences = LLExperienceCache::getCached();
|
||||
|
||||
LLExperienceCache::cache_t::const_iterator it = experiences.begin();
|
||||
while( it != experiences.end() )
|
||||
{
|
||||
if(!it->second.has(LLExperienceCache::MISSING))
|
||||
{
|
||||
recent.append(it->first);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
tab->setExperienceList(recent);
|
||||
#endif // SHOW_RECENT_TAB
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterExperiences::resizeToTabs()
|
||||
{
|
||||
const S32 TAB_WIDTH_PADDING = 16;
|
||||
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
||||
LLRect rect = getRect();
|
||||
if(rect.getWidth() < tabs->getTotalTabWidth() + TAB_WIDTH_PADDING)
|
||||
{
|
||||
rect.mRight = rect.mLeft + tabs->getTotalTabWidth() + TAB_WIDTH_PADDING;
|
||||
}
|
||||
reshape(rect.getWidth(), rect.getHeight(), FALSE);
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::refreshContents()
|
||||
{
|
||||
setupRecentTabs();
|
||||
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
|
||||
if (region)
|
||||
{
|
||||
NameMap_t tabMap;
|
||||
LLHandle<LLFloaterExperiences> handle = getDerivedHandle<LLFloaterExperiences>();
|
||||
|
||||
tabMap["experiences"]="Allowed_Experiences_Tab";
|
||||
tabMap["blocked"]="Blocked_Experiences_Tab";
|
||||
tabMap["experience_ids"]="Owned_Experiences_Tab";
|
||||
|
||||
retrieveExperienceList(region->getCapability("GetExperiences"), handle, tabMap);
|
||||
|
||||
updateInfo("GetAdminExperiences","Admin_Experiences_Tab");
|
||||
updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab");
|
||||
|
||||
retrieveExperienceList(region->getCapability("AgentExperiences"), handle, tabMap,
|
||||
"ExperienceAcquireFailed", boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::onOpen()
|
||||
{
|
||||
LLEventPumps::instance().obtain("experience_permission").stopListening("LLFloaterExperiences");
|
||||
LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences",
|
||||
boost::bind(&LLFloaterExperiences::updatePermissions, this, _1));
|
||||
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if(region)
|
||||
{
|
||||
if(region->capabilitiesReceived())
|
||||
{
|
||||
refreshContents();
|
||||
return;
|
||||
}
|
||||
region->setCapabilitiesReceivedCallback(boost::bind(&LLFloaterExperiences::refreshContents, this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFloaterExperiences::updatePermissions( const LLSD& permission )
|
||||
{
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
||||
LLUUID experience;
|
||||
std::string permission_string;
|
||||
if(permission.has("experience"))
|
||||
{
|
||||
experience = permission["experience"].asUUID();
|
||||
permission_string = permission[experience.asString()]["permission"].asString();
|
||||
|
||||
}
|
||||
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName("Allowed_Experiences_Tab");
|
||||
if(tab)
|
||||
{
|
||||
if(permission.has("experiences"))
|
||||
{
|
||||
tab->setExperienceList(permission["experiences"]);
|
||||
}
|
||||
else if(experience.notNull())
|
||||
{
|
||||
if(permission_string != "Allow")
|
||||
{
|
||||
tab->removeExperience(experience);
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->addExperience(experience);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tab = (LLPanelExperiences*)tabs->getPanelByName("Blocked_Experiences_Tab");
|
||||
if(tab)
|
||||
{
|
||||
if(permission.has("blocked"))
|
||||
{
|
||||
tab->setExperienceList(permission["blocked"]);
|
||||
}
|
||||
else if(experience.notNull())
|
||||
{
|
||||
if(permission_string != "Block")
|
||||
{
|
||||
tab->removeExperience(experience);
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->addExperience(experience);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::onClose( bool app_quitting )
|
||||
{
|
||||
LLEventPumps::instance().obtain("experience_permission").stopListening("LLFloaterExperiences");
|
||||
LLFloater::onClose(app_quitting);
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::checkPurchaseInfo(LLPanelExperiences* panel, const LLSD& content) const
|
||||
{
|
||||
panel->enableButton(content.has("purchase"));
|
||||
|
||||
LLFloaterExperiences::findInstance()->updateInfo("GetAdminExperiences","Admin_Experiences_Tab");
|
||||
LLFloaterExperiences::findInstance()->updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab");
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::checkAndOpen(LLPanelExperiences* panel, const LLSD& content) const
|
||||
{
|
||||
checkPurchaseInfo(panel, content);
|
||||
|
||||
// determine new item
|
||||
const LLSD& response_ids = content["experience_ids"];
|
||||
|
||||
if (mPrepurchaseIds.size() + 1 == response_ids.size())
|
||||
{
|
||||
// we have a new element
|
||||
for (const auto& it : response_ids.array())
|
||||
{
|
||||
LLUUID experience_id = it.asUUID();
|
||||
if (std::find(mPrepurchaseIds.begin(), mPrepurchaseIds.end(), experience_id) == mPrepurchaseIds.end())
|
||||
{
|
||||
// new element found, open it
|
||||
LLSD args;
|
||||
args["experience_id"] = experience_id;
|
||||
args["edit_experience"] = true;
|
||||
LLFloaterExperienceProfile::showInstance(args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::updateInfo(std::string experienceCap, std::string tab)
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (region)
|
||||
{
|
||||
NameMap_t tabMap;
|
||||
LLHandle<LLFloaterExperiences> handle = getDerivedHandle<LLFloaterExperiences>();
|
||||
|
||||
tabMap["experience_ids"] = tab;
|
||||
|
||||
retrieveExperienceList(region->getCapability(experienceCap), handle, tabMap);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::sendPurchaseRequest()
|
||||
{
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
|
||||
if (region)
|
||||
{
|
||||
NameMap_t tabMap;
|
||||
const std::string tab_owned_name = "Owned_Experiences_Tab";
|
||||
LLHandle<LLFloaterExperiences> handle = getDerivedHandle<LLFloaterExperiences>();
|
||||
|
||||
tabMap["experience_ids"] = tab_owned_name;
|
||||
|
||||
// extract ids for experiences that we already have
|
||||
LLTabContainer* tabs = getChild<LLTabContainer>("xp_tabs");
|
||||
LLPanelExperiences* tab_owned = (LLPanelExperiences*)tabs->getPanelByName(tab_owned_name);
|
||||
mPrepurchaseIds.clear();
|
||||
if (tab_owned)
|
||||
{
|
||||
tab_owned->getExperienceIdsList(mPrepurchaseIds);
|
||||
}
|
||||
|
||||
requestNewExperience(region->getCapability("AgentExperiences"), handle, tabMap, "ExperienceAcquireFailed",
|
||||
boost::bind(&LLFloaterExperiences::checkAndOpen, this, _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterExperiences::retrieveExperienceList(const std::string &url,
|
||||
const LLHandle<LLFloaterExperiences> &hparent, const NameMap_t &tabMapping,
|
||||
const std::string &errorNotify, Callback_t cback, bool post)
|
||||
{
|
||||
if (url.empty())
|
||||
{
|
||||
LL_WARNS() << "retrieveExperienceListCoro called with empty capability!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
auto responder = new LLCoroResponder(
|
||||
boost::bind(LLFloaterExperiences::retrieveExperienceListCoro, _1,
|
||||
hparent, tabMapping, errorNotify, cback));
|
||||
|
||||
if (post)
|
||||
LLHTTPClient::post(url, LLSD(), responder);
|
||||
else
|
||||
LLHTTPClient::get(url, responder);
|
||||
}
|
||||
|
||||
void LLFloaterExperiences::retrieveExperienceListCoro(const LLCoroResponder& responder,
|
||||
LLHandle<LLFloaterExperiences> hparent, NameMap_t tabMapping,
|
||||
std::string errorNotify, Callback_t cback)
|
||||
{
|
||||
LLSD result = responder.getContent();
|
||||
|
||||
if (!responder.isGoodStatus(responder.getStatus()))
|
||||
{
|
||||
LLSD subs;
|
||||
subs["ERROR_MESSAGE"] = responder.getReason();
|
||||
LLNotificationsUtil::add(errorNotify, subs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (hparent.isDead())
|
||||
return;
|
||||
|
||||
LLFloaterExperiences* parent = hparent.get();
|
||||
LLTabContainer* tabs = parent->getChild<LLTabContainer>("xp_tabs");
|
||||
|
||||
for (auto& it : tabMapping)
|
||||
{
|
||||
if (result.has(it.first))
|
||||
{
|
||||
LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName(it.second);
|
||||
if (tab)
|
||||
{
|
||||
const LLSD& ids = result[it.first];
|
||||
tab->setExperienceList(ids);
|
||||
if (cback != nullptr)
|
||||
{
|
||||
cback(tab, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
78
indra/newview/llfloaterexperiences.h
Normal file
78
indra/newview/llfloaterexperiences.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file llfloaterexperiences.h
|
||||
* @brief LLFloaterExperiences class definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLFLOATEREXPERIENCES_H
|
||||
#define LL_LLFLOATEREXPERIENCES_H
|
||||
|
||||
#include "llfloater.h"
|
||||
|
||||
class LLPanelExperiences;
|
||||
|
||||
class LLFloaterExperiences final :
|
||||
public LLFloater
|
||||
, public LLFloaterSingleton<LLFloaterExperiences>
|
||||
{
|
||||
friend class LLUISingleton<LLFloaterExperiences, VisibilityPolicy<LLFloater> >;
|
||||
public:
|
||||
LLFloaterExperiences(const LLSD& data);
|
||||
void onClose(bool app_quitting) override;
|
||||
|
||||
void onOpen(/*const LLSD& key*/) override;
|
||||
|
||||
protected:
|
||||
typedef std::map<std::string, std::string> NameMap_t;
|
||||
typedef std::function<void(LLPanelExperiences*, const LLSD&)> Callback_t;
|
||||
|
||||
void clearFromRecent(const LLSD& ids);
|
||||
void resizeToTabs();
|
||||
/*virtual*/ BOOL postBuild() override;
|
||||
void refreshContents();
|
||||
void setupRecentTabs();
|
||||
LLPanelExperiences* addTab(const std::string& name, bool select);
|
||||
|
||||
bool updatePermissions(const LLSD& permission);
|
||||
void sendPurchaseRequest();
|
||||
void checkPurchaseInfo(LLPanelExperiences* panel, const LLSD& content)const;
|
||||
void checkAndOpen(LLPanelExperiences* panel, const LLSD& content) const;
|
||||
void updateInfo(std::string experiences, std::string tab);
|
||||
|
||||
void retrieveExperienceList(const std::string &url, const LLHandle<LLFloaterExperiences> &hparent, const NameMap_t &tabMapping,
|
||||
const std::string &errorNotify = std::string("ErrorMessage"), Callback_t cback = Callback_t(), bool post = false);
|
||||
|
||||
void requestNewExperience(const std::string &url, const LLHandle<LLFloaterExperiences> &hparent, const NameMap_t &tabMapping,
|
||||
const std::string &errorNotify, Callback_t cback)
|
||||
{
|
||||
retrieveExperienceList(url, hparent, tabMapping, errorNotify, cback, true);
|
||||
}
|
||||
|
||||
private:
|
||||
static void retrieveExperienceListCoro(const struct LLCoroResponder& responder, LLHandle<LLFloaterExperiences> hparent,
|
||||
NameMap_t tabMapping, std::string errorNotify, Callback_t cback);
|
||||
uuid_vec_t mPrepurchaseIds;
|
||||
};
|
||||
|
||||
#endif //LL_LLFLOATEREXPERIENCES_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user