summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/labeler.yaml3
-rw-r--r--autobuild.xml60
-rw-r--r--indra/cmake/CMakeLists.txt1
-rw-r--r--indra/cmake/Lualibs.cmake29
-rw-r--r--indra/cmake/Prebuilt.cmake1
-rwxr-xr-xindra/cmake/run_build_test.py12
-rw-r--r--indra/llcommon/CMakeLists.txt5
-rw-r--r--indra/llcommon/fsyspath.h74
-rwxr-xr-x[-rw-r--r--]indra/llcommon/hexdump.h (renamed from indra/test/hexdump.h)15
-rw-r--r--indra/llcommon/llcoros.cpp137
-rw-r--r--indra/llcommon/llcoros.h79
-rw-r--r--indra/llcommon/lleventcoro.cpp53
-rw-r--r--indra/llcommon/lleventdispatcher.h30
-rw-r--r--indra/llcommon/llevents.cpp56
-rw-r--r--indra/llcommon/llevents.h84
-rw-r--r--indra/llcommon/llexception.h3
-rw-r--r--indra/llcommon/llformat.h12
-rw-r--r--indra/llcommon/llinstancetracker.h80
-rw-r--r--indra/llcommon/llleap.cpp59
-rw-r--r--indra/llcommon/llleaplistener.cpp85
-rw-r--r--indra/llcommon/llleaplistener.h29
-rw-r--r--indra/llcommon/llrefcount.h157
-rw-r--r--indra/llcommon/llstring.h2495
-rw-r--r--indra/llcommon/lua_function.cpp984
-rw-r--r--indra/llcommon/lua_function.h259
-rw-r--r--indra/llcommon/lualistener.cpp114
-rw-r--r--indra/llcommon/lualistener.h81
-rw-r--r--indra/llcommon/stringize.h16
-rw-r--r--indra/llcommon/tests/StringVec.h12
-rw-r--r--indra/llcommon/tests/lleventcoro_test.cpp91
-rw-r--r--indra/llcommon/tests/lleventdispatcher_test.cpp6
-rw-r--r--indra/llcommon/tests/lleventfilter_test.cpp12
-rw-r--r--indra/llcommon/tests/llleap_test.cpp4
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp3058
-rw-r--r--indra/llcommon/threadpool.cpp21
-rw-r--r--indra/llcommon/threadpool.h8
-rw-r--r--indra/llcommon/workqueue.cpp9
-rw-r--r--indra/llcommon/workqueue.h5
-rw-r--r--indra/llfilesystem/lldir.cpp1497
-rw-r--r--indra/llfilesystem/lldir.h421
-rw-r--r--indra/llimage/tests/llimageworker_test.cpp178
-rw-r--r--indra/llmessage/llcoproceduremanager.cpp41
-rw-r--r--indra/llprimitive/tests/llgltfmaterial_test.cpp16
-rw-r--r--indra/llui/CMakeLists.txt2
-rw-r--r--indra/llui/llfloaterreglistener.cpp24
-rw-r--r--indra/llui/llfloaterreglistener.h12
-rw-r--r--indra/llui/llluafloater.cpp295
-rw-r--r--indra/llui/llluafloater.h54
-rw-r--r--indra/llui/llmenugl.h1262
-rw-r--r--indra/llui/lltexteditor.cpp4637
-rw-r--r--indra/llui/lltexteditor.h480
-rw-r--r--indra/llwindow/llwindow.h370
-rw-r--r--indra/llwindow/llwindowmacosx-objc.h18
-rw-r--r--indra/llwindow/llwindowmacosx-objc.mm7
-rw-r--r--indra/llwindow/llwindowmacosx.cpp2579
-rw-r--r--indra/llwindow/llwindowmacosx.h342
-rw-r--r--indra/llwindow/llwindowwin32.cpp4091
-rw-r--r--indra/llwindow/llwindowwin32.h364
-rw-r--r--indra/llxml/llcontrol.cpp1832
-rw-r--r--indra/llxml/llcontrol.h614
-rw-r--r--indra/newview/CMakeLists.txt35
-rw-r--r--indra/newview/app_settings/cmd_line.xml28
-rw-r--r--indra/newview/app_settings/settings.xml35
-rw-r--r--indra/newview/llappviewer.cpp7052
-rw-r--r--indra/newview/llfilepicker.cpp2081
-rw-r--r--indra/newview/llfilepicker.h207
-rw-r--r--indra/newview/llfloaterluadebug.cpp155
-rw-r--r--indra/newview/llfloaterluadebug.h72
-rw-r--r--indra/newview/llfloaterluascripts.cpp131
-rw-r--r--indra/newview/llfloaterluascripts.h54
-rw-r--r--indra/newview/llfloatersettingsdebug.cpp726
-rw-r--r--indra/newview/llfloatersettingsdebug.h42
-rw-r--r--indra/newview/llinventoryfunctions.cpp1959
-rw-r--r--indra/newview/llinventoryfunctions.h288
-rw-r--r--indra/newview/llinventorymodel.cpp6699
-rw-r--r--indra/newview/llluamanager.cpp509
-rw-r--r--indra/newview/llluamanager.h124
-rw-r--r--indra/newview/llstartup.cpp5959
-rw-r--r--indra/newview/lltoolplacer.cpp880
-rw-r--r--indra/newview/lltoolplacer.h40
-rw-r--r--indra/newview/lluilistener.cpp16
-rw-r--r--indra/newview/lluilistener.h13
-rw-r--r--indra/newview/llviewercontrollistener.cpp301
-rw-r--r--indra/newview/llviewerfloaterreg.cpp423
-rw-r--r--indra/newview/llviewermenu.cpp12121
-rw-r--r--indra/newview/llviewermenu.h57
-rw-r--r--indra/newview/llviewermenufile.cpp1422
-rw-r--r--indra/newview/llviewermenufile.h78
-rw-r--r--indra/newview/scripts/lua/ErrorQueue.lua34
-rw-r--r--indra/newview/scripts/lua/Floater.lua151
-rw-r--r--indra/newview/scripts/lua/LLDebugSettings.lua24
-rw-r--r--indra/newview/scripts/lua/LLFloaterAbout.lua11
-rw-r--r--indra/newview/scripts/lua/LLGesture.lua23
-rw-r--r--indra/newview/scripts/lua/Queue.lua47
-rw-r--r--indra/newview/scripts/lua/UI.lua16
-rw-r--r--indra/newview/scripts/lua/WaitQueue.lua85
-rw-r--r--indra/newview/scripts/lua/coro.lua67
-rw-r--r--indra/newview/scripts/lua/fiber.lua338
-rw-r--r--indra/newview/scripts/lua/inspect.lua371
-rw-r--r--indra/newview/scripts/lua/leap.lua446
-rw-r--r--indra/newview/scripts/lua/luafloater_demo.xml93
-rw-r--r--indra/newview/scripts/lua/luafloater_gesture_list.xml21
-rw-r--r--indra/newview/scripts/lua/printf.lua19
-rw-r--r--indra/newview/scripts/lua/qtest.lua146
-rw-r--r--indra/newview/scripts/lua/startup.lua101
-rw-r--r--indra/newview/scripts/lua/test_LLFloaterAbout.lua6
-rw-r--r--indra/newview/scripts/lua/test_LLGesture.lua26
-rw-r--r--indra/newview/scripts/lua/test_luafloater_demo.lua77
-rw-r--r--indra/newview/scripts/lua/test_luafloater_demo2.lua39
-rw-r--r--indra/newview/scripts/lua/test_luafloater_gesture_list.lua75
-rw-r--r--indra/newview/scripts/lua/test_luafloater_gesture_list2.lua27
-rw-r--r--indra/newview/scripts/lua/testmod.lua2
-rw-r--r--indra/newview/scripts/lua/util.lua44
-rw-r--r--indra/newview/skins/default/xui/en/floater_lua_debug.xml117
-rw-r--r--indra/newview/skins/default/xui/en/floater_lua_scripts.xml36
-rw-r--r--indra/newview/skins/default/xui/en/floater_settings_debug.xml18
-rw-r--r--indra/newview/skins/default/xui/en/menu_lua_scripts.xml19
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml21
-rw-r--r--indra/newview/tests/llluamanager_test.cpp468
-rwxr-xr-xindra/newview/viewer_manifest.py28
-rw-r--r--indra/test/debug.h79
-rw-r--r--indra/test/io.cpp2212
-rw-r--r--indra/test/lltut.h190
-rw-r--r--indra/test/print.h6
124 files changed, 40424 insertions, 33941 deletions
diff --git a/.github/labeler.yaml b/.github/labeler.yaml
index d31a361baf..6e03801b65 100644
--- a/.github/labeler.yaml
+++ b/.github/labeler.yaml
@@ -76,3 +76,6 @@ c/cpp:
- '**/*.i'
- '**/*.inl'
- '**/*.y'
+
+'team:viewer':
+ - '*'
diff --git a/autobuild.xml b/autobuild.xml
index 13c9e7ec35..0a49fa7cda 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1732,6 +1732,66 @@
<key>name</key>
<string>llphysicsextensions_tpv</string>
</map>
+ <key>luau</key>
+ <map>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>59bf3d96f9df4b6981c406abac5c46ae276f9b15</string>
+ <key>hash_algorithm</key>
+ <string>sha1</string>
+ <key>url</key>
+ <string>https://github.com/secondlife/3p-luau/releases/download/v0.609-9567db9/luau-0.609-9567db9-darwin64-9567db9.tar.zst</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>549516ada483ddf276183f66b0a7c3d01e4ef1aa</string>
+ <key>hash_algorithm</key>
+ <string>sha1</string>
+ <key>url</key>
+ <string>https://github.com/secondlife/3p-luau/releases/download/v0.609-9567db9/luau-0.609-9567db9-linux64-9567db9.tar.zst</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>43e2cc2e6e94299f89655435002864925b640e16</string>
+ <key>hash_algorithm</key>
+ <string>sha1</string>
+ <key>url</key>
+ <string>https://github.com/secondlife/3p-luau/releases/download/v0.609-9567db9/luau-0.609-9567db9-windows64-9567db9.tar.zst</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
+ </map>
+ <key>license</key>
+ <string>MIT</string>
+ <key>license_file</key>
+ <string>LICENSES/luau.txt</string>
+ <key>copyright</key>
+ <string>Copyright (c) 2019-2023 Roblox Corporation, Copyright (c) 1994–2019 Lua.org, PUC-Rio.</string>
+ <key>version</key>
+ <string>0.609-9567db9</string>
+ <key>name</key>
+ <string>luau</string>
+ <key>description</key>
+ <string>Luau is a fast, small, safe, gradually typed embeddable scripting language derived from Lua.</string>
+ </map>
<key>mesa</key>
<map>
<key>platforms</key>
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 05c51c018d..45c56f2d2c 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -44,6 +44,7 @@ set(cmake_SOURCE_FILES
LLTestCommand.cmake
LLWindow.cmake
Linking.cmake
+ Lualibs.cmake
Meshoptimizer.cmake
NDOF.cmake
OPENAL.cmake
diff --git a/indra/cmake/Lualibs.cmake b/indra/cmake/Lualibs.cmake
new file mode 100644
index 0000000000..d66305a8e5
--- /dev/null
+++ b/indra/cmake/Lualibs.cmake
@@ -0,0 +1,29 @@
+# -*- cmake -*-
+
+include_guard()
+
+include(Prebuilt)
+
+add_library( ll::lualibs INTERFACE IMPORTED )
+
+use_system_binary( lualibs )
+
+use_prebuilt_binary(luau)
+
+target_include_directories( ll::lualibs SYSTEM INTERFACE
+ ${LIBS_PREBUILT_DIR}/include
+)
+
+if (WINDOWS)
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/Luau.Ast.lib)
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/Luau.CodeGen.lib)
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/Luau.Compiler.lib)
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/Luau.Config.lib)
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/Luau.VM.lib)
+else ()
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libLuau.CodeGen.a)
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libLuau.Compiler.a)
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libLuau.Config.a)
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libLuau.VM.a)
+ target_link_libraries(ll::lualibs INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libLuau.Ast.a)
+endif ()
diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake
index 634cc15c21..a8c702bfef 100644
--- a/indra/cmake/Prebuilt.cmake
+++ b/indra/cmake/Prebuilt.cmake
@@ -40,6 +40,7 @@ macro (use_prebuilt_binary _binary)
--install-dir=${AUTOBUILD_INSTALL_DIR}
${_binary} ")
endif(DEBUG_PREBUILT)
+ message(STATUS "Installing ${_binary}...")
execute_process(COMMAND "${AUTOBUILD_EXECUTABLE}"
install
--install-dir=${AUTOBUILD_INSTALL_DIR}
diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py
index 940a130a50..ef4d712254 100755
--- a/indra/cmake/run_build_test.py
+++ b/indra/cmake/run_build_test.py
@@ -122,19 +122,17 @@ def main(command, arguments=[], libpath=[], vars={}):
# Make sure we see all relevant output *before* child-process output.
sys.stdout.flush()
try:
- return subprocess.call(command_list)
- except OSError as err:
+ return subprocess.run(command_list).returncode
+ except FileNotFoundError as err:
# If the caller is trying to execute a test program that doesn't
# exist, we want to produce a reasonable error message rather than a
# traceback. This happens when the build is halted by errors, but
# CMake tries to proceed with testing anyway <eyeroll/>. However, do
# NOT attempt to handle any error but "doesn't exist."
- if err.errno != errno.ENOENT:
- raise
# In practice, the pathnames into CMake's build tree are so long as to
# obscure the name of the test program. Just log its basename.
- log.warn("No such program %s; check for preceding build errors" % \
- os.path.basename(command[0]))
+ log.warning("No such program %s; check for preceding build errors" %
+ os.path.basename(command[0]))
# What rc should we simulate for missing executable? Windows produces
# 9009.
return 9009
@@ -152,7 +150,7 @@ def translate_rc(rc):
"""
if rc is None:
return "still running"
-
+
if rc >= 0:
return "terminated with rc %s" % rc
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index c947184dc8..aa0b66f2f4 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -108,6 +108,8 @@ set(llcommon_SOURCE_FILES
lluriparser.cpp
lluuid.cpp
llworkerthread.cpp
+ lua_function.cpp
+ lualistener.cpp
hbxxh.cpp
u64.cpp
threadpool.cpp
@@ -125,6 +127,7 @@ set(llcommon_HEADER_FILES
commoncontrol.h
ctype_workaround.h
fix_macros.h
+ fsyspath.h
function_types.h
indra_constants.h
lazyeventapi.h
@@ -250,6 +253,8 @@ set(llcommon_HEADER_FILES
llwin32headers.h
llwin32headerslean.h
llworkerthread.h
+ lua_function.h
+ lualistener.h
hbxxh.h
lockstatic.h
stdtypes.h
diff --git a/indra/llcommon/fsyspath.h b/indra/llcommon/fsyspath.h
new file mode 100644
index 0000000000..aa4e0132bc
--- /dev/null
+++ b/indra/llcommon/fsyspath.h
@@ -0,0 +1,74 @@
+/**
+ * @file fsyspath.h
+ * @author Nat Goodspeed
+ * @date 2024-04-03
+ * @brief Adapt our UTF-8 std::strings for std::filesystem::path
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Copyright (c) 2024, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_FSYSPATH_H)
+#define LL_FSYSPATH_H
+
+#include <filesystem>
+
+// While std::filesystem::path can be directly constructed from std::string on
+// both Posix and Windows, that's not what we want on Windows. Per
+// https://en.cppreference.com/w/cpp/filesystem/path/path:
+
+// ... the method of conversion to the native character set depends on the
+// character type used by source.
+//
+// * If the source character type is char, the encoding of the source is
+// assumed to be the native narrow encoding (so no conversion takes place on
+// POSIX systems).
+// * If the source character type is char8_t, conversion from UTF-8 to native
+// filesystem encoding is used. (since C++20)
+// * If the source character type is wchar_t, the input is assumed to be the
+// native wide encoding (so no conversion takes places on Windows).
+
+// The trouble is that on Windows, from std::string ("source character type is
+// char"), the "native narrow encoding" isn't UTF-8, so file paths containing
+// non-ASCII characters get mangled.
+//
+// Once we're building with C++20, we could pass a UTF-8 std::string through a
+// vector<char8_t> to engage std::filesystem::path's own UTF-8 conversion. But
+// sigh, as of 2024-04-03 we're not yet there.
+//
+// Anyway, encapsulating the important UTF-8 conversions in our own subclass
+// allows us to migrate forward to C++20 conventions without changing
+// referencing code.
+
+class fsyspath: public std::filesystem::path
+{
+ using super = std::filesystem::path;
+
+public:
+ // default
+ fsyspath() {}
+ // construct from UTF-8 encoded std::string
+ fsyspath(const std::string& path): super(std::filesystem::u8path(path)) {}
+ // construct from UTF-8 encoded const char*
+ fsyspath(const char* path): super(std::filesystem::u8path(path)) {}
+ // construct from existing path
+ fsyspath(const super& path): super(path) {}
+
+ fsyspath& operator=(const super& p) { super::operator=(p); return *this; }
+ fsyspath& operator=(const std::string& p)
+ {
+ super::operator=(std::filesystem::u8path(p));
+ return *this;
+ }
+ fsyspath& operator=(const char* p)
+ {
+ super::operator=(std::filesystem::u8path(p));
+ return *this;
+ }
+
+ // shadow base-class string() method with UTF-8 aware method
+ std::string string() const { return super::u8string(); }
+};
+
+#endif /* ! defined(LL_FSYSPATH_H) */
diff --git a/indra/test/hexdump.h b/indra/llcommon/hexdump.h
index 95f1e297c3..234168cd61 100644..100755
--- a/indra/test/hexdump.h
+++ b/indra/llcommon/hexdump.h
@@ -1,9 +1,9 @@
/**
* @file hexdump.h
* @author Nat Goodspeed
- * @date 2023-09-08
- * @brief Provide hexdump() and hexmix() ostream formatters
- *
+ * @date 2023-10-03
+ * @brief iostream manipulators to stream hex, or string with nonprinting chars
+ *
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Copyright (c) 2023, Linden Research, Inc.
* $/LicenseInfo$
@@ -17,6 +17,9 @@
#include <iostream>
#include <string_view>
+namespace LL
+{
+
// Format a given byte string as 2-digit hex values, no separators
// Usage: std::cout << hexdump(somestring) << ...
class hexdump
@@ -30,6 +33,10 @@ public:
hexdump(reinterpret_cast<const unsigned char*>(data), len)
{}
+ hexdump(const std::vector<unsigned char>& data):
+ hexdump(data.data(), data.size())
+ {}
+
hexdump(const unsigned char* data, size_t len):
mData(data, data + len)
{}
@@ -94,4 +101,6 @@ private:
std::string mData;
};
+} // namespace LL
+
#endif /* ! defined(LL_HEXDUMP_H) */
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 20340397db..1926941d1f 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-06-03
* @brief Implementation for llcoros.
- *
+ *
* $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$
*/
@@ -51,18 +51,19 @@
#endif
// other Linden headers
#include "llapp.h"
-#include "lltimer.h"
-#include "llevents.h"
#include "llerror.h"
-#include "stringize.h"
+#include "llevents.h"
#include "llexception.h"
+#include "llsdutil.h"
+#include "lltimer.h"
+#include "stringize.h"
#if LL_WINDOWS
#include <excpt.h>
#endif
// static
-LLCoros::CoroData& LLCoros::get_CoroData(const std::string& caller)
+LLCoros::CoroData& LLCoros::get_CoroData(const std::string&)
{
CoroData* current{ nullptr };
// be careful about attempted accesses in the final throes of app shutdown
@@ -94,7 +95,7 @@ LLCoros::coro::id LLCoros::get_self()
//static
void LLCoros::set_consuming(bool consuming)
{
- CoroData& data(get_CoroData("set_consuming()"));
+ auto& data(get_CoroData("set_consuming()"));
// DO NOT call this on the main() coroutine.
llassert_always(! data.mName.empty());
data.mConsuming = consuming;
@@ -128,6 +129,15 @@ LLCoros::LLCoros():
// points to it. So initialize it with a no-op deleter.
mCurrent{ [](CoroData*){} }
{
+ auto& llapp{ LLEventPumps::instance().obtain("LLApp") };
+ if (llapp.getListener("LLCoros") == LLBoundListener())
+ {
+ // chain our "LLCoros" pump onto "LLApp" pump: echo events posted to "LLApp"
+ mConn = llapp.listen(
+ "LLCoros",
+ [](const LLSD& event)
+ { return LLEventPumps::instance().obtain("LLCoros").post(event); });
+ }
}
LLCoros::~LLCoros()
@@ -177,26 +187,26 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const
// Until we find an unused name, append a numeric suffix for uniqueness.
while (CoroData::getInstance(name))
{
- name = STRINGIZE(prefix << unique++);
+ name = stringize(prefix, unique++);
}
return name;
}
-/*==========================================================================*|
-bool LLCoros::kill(const std::string& name)
+bool LLCoros::killreq(const std::string& name)
{
- CoroMap::iterator found = mCoros.find(name);
- if (found == mCoros.end())
+ auto found = CoroData::getInstance(name);
+ if (! found)
{
return false;
}
- // Because this is a boost::ptr_map, erasing the map entry also destroys
- // the referenced heap object, in this case the boost::coroutine object,
- // which will terminate the coroutine.
- mCoros.erase(found);
+ // Next time the subject coroutine calls checkStop(), make it terminate.
+ found->mKilledBy = getName();
+ // But if it's waiting for something, notify anyone in a position to poke
+ // it.
+ LLEventPumps::instance().obtain("LLCoros").post(
+ llsd::map("status", "killreq", "coro", name));
return true;
}
-|*==========================================================================*/
//static
std::string LLCoros::getName()
@@ -207,7 +217,7 @@ std::string LLCoros::getName()
//static
std::string LLCoros::logname()
{
- LLCoros::CoroData& data(get_CoroData("logname()"));
+ auto& data(get_CoroData("logname()"));
return data.mName.empty()? data.getKey() : data.mName;
}
@@ -360,7 +370,7 @@ void LLCoros::toplevel(std::string name, callable_t callable)
// Any uncaught exception derived from LLContinueError will be caught
// here and logged. This coroutine will terminate but the rest of the
// viewer will carry on.
- LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
+ LOG_UNHANDLED_EXCEPTION(stringize("coroutine ", name));
}
catch (...)
{
@@ -373,15 +383,24 @@ void LLCoros::toplevel(std::string name, callable_t callable)
}
//static
-void LLCoros::checkStop()
+void LLCoros::checkStop(callable_t cleanup)
{
+ // don't replicate this 'if' test throughout the code below
+ if (! cleanup)
+ {
+ cleanup = {[](){}}; // hey, look, I'm coding in Haskell!
+ }
+
if (wasDeleted())
{
+ cleanup();
LLTHROW(Shutdown("LLCoros was deleted"));
}
- // do this AFTER the check above, because getName() depends on
- // get_CoroData(), which depends on the local_ptr in our instance().
- if (getName().empty())
+
+ // do this AFTER the check above, because get_CoroData() depends on the
+ // local_ptr in our instance().
+ auto& data(get_CoroData("checkStop()"));
+ if (data.mName.empty())
{
// Our Stop exception and its subclasses are intended to stop loitering
// coroutines. Don't throw it from the main coroutine.
@@ -389,19 +408,80 @@ void LLCoros::checkStop()
}
if (LLApp::isStopped())
{
+ cleanup();
LLTHROW(Stopped("viewer is stopped"));
}
if (! LLApp::isRunning())
{
+ cleanup();
LLTHROW(Stopping("viewer is stopping"));
}
+ if (! data.mKilledBy.empty())
+ {
+ // Someone wants to kill this coroutine
+ cleanup();
+ LLTHROW(Killed(stringize("coroutine ", data.mName, " killed by ", data.mKilledBy)));
+ }
+}
+
+LLBoundListener LLCoros::getStopListener(const std::string& caller, LLVoidListener cleanup)
+{
+ if (! cleanup)
+ return {};
+
+ // This overload only responds to viewer shutdown.
+ return LLEventPumps::instance().obtain("LLCoros")
+ .listen(
+ LLEventPump::inventName(caller),
+ [cleanup](const LLSD& event)
+ {
+ auto status{ event["status"].asString() };
+ if (status != "running" && status != "killreq")
+ {
+ cleanup(event);
+ }
+ return false;
+ });
+}
+
+LLBoundListener LLCoros::getStopListener(const std::string& caller,
+ const std::string& cnsmr,
+ LLVoidListener cleanup)
+{
+ if (! cleanup)
+ return {};
+
+ std::string consumer{cnsmr};
+ if (consumer.empty())
+ {
+ consumer = getName();
+ }
+
+ // This overload responds to viewer shutdown and to killreq(consumer).
+ return LLEventPumps::instance().obtain("LLCoros")
+ .listen(
+ LLEventPump::inventName(caller),
+ [consumer, cleanup](const LLSD& event)
+ {
+ auto status{ event["status"].asString() };
+ if (status == "killreq")
+ {
+ if (event["coro"].asString() == consumer)
+ {
+ cleanup(event);
+ }
+ }
+ else if (status != "running")
+ {
+ cleanup(event);
+ }
+ return false;
+ });
}
LLCoros::CoroData::CoroData(const std::string& name):
LLInstanceTracker<CoroData, std::string>(name),
mName(name),
- // don't consume events unless specifically directed
- mConsuming(false),
mCreationTime(LLTimer::getTotalSeconds())
{
}
@@ -414,7 +494,6 @@ LLCoros::CoroData::CoroData(int n):
// empty string as its visible name because some consumers test for that.
LLInstanceTracker<CoroData, std::string>("main" + stringize(n)),
mName(),
- mConsuming(false),
mCreationTime(LLTimer::getTotalSeconds())
{
}
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index 71c1c1c443..61c0fef1c3 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-06-02
* @brief Manage running boost::coroutine instances
- *
+ *
* $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$
*/
@@ -29,17 +29,18 @@
#if ! defined(LL_LLCOROS_H)
#define LL_LLCOROS_H
+#include "llevents.h"
#include "llexception.h"
+#include "llinstancetracker.h"
+#include "llsingleton.h"
+#include "mutex.h"
#include <boost/fiber/fss.hpp>
#include <boost/fiber/future/promise.hpp>
#include <boost/fiber/future/future.hpp>
-#include "mutex.h"
-#include "llsingleton.h"
-#include "llinstancetracker.h"
-#include <boost/function.hpp>
-#include <string>
#include <exception>
+#include <functional>
#include <queue>
+#include <string>
// e.g. #include LLCOROS_MUTEX_HEADER
#define LLCOROS_MUTEX_HEADER <boost/fiber/mutex.hpp>
@@ -101,7 +102,7 @@ public:
/// stuck with the term "coroutine."
typedef boost::fibers::fiber coro;
/// Canonical callable type
- typedef boost::function<void()> callable_t;
+ typedef std::function<void()> callable_t;
/**
* Create and start running a new coroutine with specified name. The name
@@ -143,13 +144,13 @@ public:
std::string launch(const std::string& prefix, const callable_t& callable);
/**
- * Abort a running coroutine by name. Normally, when a coroutine either
+ * Ask the named coroutine to abort. Normally, when a coroutine either
* runs to completion or terminates with an exception, LLCoros quietly
* cleans it up. This is for use only when you must explicitly interrupt
* one prematurely. Returns @c true if the specified name was found and
* still running at the time.
*/
-// bool kill(const std::string& name);
+ bool killreq(const std::string& name);
/**
* From within a coroutine, look up the (tweaked) name string by which
@@ -158,7 +159,7 @@ public:
* LLCoros::launch()).
*/
static std::string getName();
-
+
/**
* rethrow() is called by the thread's main fiber to propagate an
* exception from any coroutine into the main fiber, where it can engage
@@ -251,15 +252,21 @@ public:
/// thrown by checkStop()
// It may sound ironic that Stop is derived from LLContinueError, but the
// point is that LLContinueError is the category of exception that should
- // not immediately crash the viewer. Stop and its subclasses are to notify
- // coroutines that the viewer intends to shut down. The expected response
- // is to terminate the coroutine, rather than abort the viewer.
+ // not immediately crash the viewer. Stop and its subclasses are to tell
+ // coroutines to terminate, e.g. because the viewer is shutting down. We
+ // do not want any such exception to crash the viewer.
struct Stop: public LLContinueError
{
Stop(const std::string& what): LLContinueError(what) {}
};
- /// early stages
+ /// someone wants to kill this specific coroutine
+ struct Killed: public Stop
+ {
+ Killed(const std::string& what): Stop(what) {}
+ };
+
+ /// early shutdown stages
struct Stopping: public Stop
{
Stopping(const std::string& what): Stop(what) {}
@@ -278,9 +285,31 @@ public:
};
/// Call this intermittently if there's a chance your coroutine might
- /// continue running into application shutdown. Throws Stop if LLCoros has
- /// been cleaned up.
- static void checkStop();
+ /// still be running at application shutdown. Throws one of the Stop
+ /// subclasses if the caller needs to terminate. Pass a cleanup function
+ /// if you need to execute that cleanup before terminating.
+ /// Of course, if your cleanup function throws, that will be the exception
+ /// propagated by checkStop().
+ static void checkStop(callable_t cleanup={});
+
+ /// Call getStopListener() at the source end of a queue, promise or other
+ /// resource on which coroutines will wait, so that shutdown can wake up
+ /// consuming coroutines. @a caller should distinguish who's calling. The
+ /// passed @a cleanup function must close the queue, break the promise or
+ /// otherwise cause waiting consumers to wake up in an abnormal way. It's
+ /// advisable to store the returned LLBoundListener in an
+ /// LLTempBoundListener, or otherwise arrange to disconnect it.
+ static LLBoundListener getStopListener(const std::string& caller, LLVoidListener cleanup);
+
+ /// This getStopListener() overload is like the two-argument one, for use
+ /// when we know the name of the only coroutine that will wait on the
+ /// resource in question. Pass @a consumer as the empty string if the
+ /// consumer coroutine is the same as the calling coroutine. Unlike the
+ /// two-argument getStopListener(), this one also responds to
+ /// killreq(target).
+ static LLBoundListener getStopListener(const std::string& caller,
+ const std::string& consumer,
+ LLVoidListener cleanup);
/**
* Aliases for promise and future. An older underlying future implementation
@@ -312,6 +341,8 @@ private:
static CoroData& get_CoroData(const std::string& caller);
void saveException(const std::string& name, std::exception_ptr exc);
+ LLTempBoundListener mConn;
+
struct ExceptionData
{
ExceptionData(const std::string& nm, std::exception_ptr exc):
@@ -335,8 +366,10 @@ private:
// tweaked name of the current coroutine
const std::string mName;
- // set_consuming() state
- bool mConsuming;
+ // set_consuming() state -- don't consume events unless specifically directed
+ bool mConsuming{ false };
+ // killed by which coroutine
+ std::string mKilledBy;
// setStatus() state
std::string mStatus;
F64 mCreationTime; // since epoch
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index e1fc4764f6..d651aae39c 100644
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-04-29
* @brief Implementation for lleventcoro.
- *
+ *
* $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$
*/
@@ -119,7 +119,7 @@ void llcoro::suspendUntilTimeout(float seconds)
// We used to call boost::this_fiber::sleep_for(). But some coroutines
// (e.g. LLExperienceCache::idleCoro()) sit in a suspendUntilTimeout()
// loop, in which case a sleep_for() call risks sleeping through shutdown.
- // So instead, listen for "LLApp" state-changing events -- which
+ // So instead, listen for LLApp state-changing events -- which
// fortunately is handled for us by suspendUntilEventOnWithTimeout().
// Wait for an event on a bogus LLEventPump on which nobody ever posts
// events. Don't make it static because that would force instantiation of
@@ -132,8 +132,8 @@ void llcoro::suspendUntilTimeout(float seconds)
// Timeout is the NORMAL case for this call!
static LLSD timedout;
// Deliver, but ignore, timedout when (as usual) we did not receive any
- // "LLApp" event. The point is that suspendUntilEventOnWithTimeout() will
- // itself throw Stopping when "LLApp" starts broadcasting shutdown events.
+ // LLApp event. The point is that suspendUntilEventOnWithTimeout() will
+ // itself throw Stopping when LLApp starts broadcasting shutdown events.
suspendUntilEventOnWithTimeout(bogus, seconds, timedout);
}
@@ -167,33 +167,26 @@ postAndSuspendSetup(const std::string& callerName,
// "LLApp" were an LLEventMailDrop. But if we ever go there, we'd want to
// notice the pending LLApp status first.
LLBoundListener stopper(
- LLEventPumps::instance().obtain("LLApp").listen(
+ LLCoros::getStopListener(
listenerName,
+ LLCoros::instance().getName(),
[&promise, listenerName](const LLSD& status)
{
- // anything except "running" should wake up the waiting
- // coroutine
- auto& statsd = status["status"];
- if (statsd.asString() != "running")
+ LL_DEBUGS("lleventcoro") << listenerName
+ << " spotted status " << status
+ << ", throwing Stopping" << LL_ENDL;
+ try
+ {
+ promise.set_exception(
+ std::make_exception_ptr(
+ LLCoros::Stopping("status " + stringize(status))));
+ }
+ catch (const boost::fibers::promise_already_satisfied&)
{
- LL_DEBUGS("lleventcoro") << listenerName
- << " spotted status " << statsd
- << ", throwing Stopping" << LL_ENDL;
- try
- {
- promise.set_exception(
- std::make_exception_ptr(
- LLCoros::Stopping("status " + statsd.asString())));
- }
- catch (const boost::fibers::promise_already_satisfied&)
- {
- LL_WARNS("lleventcoro") << listenerName
- << " couldn't throw Stopping "
- "because promise already set" << LL_ENDL;
- }
+ LL_WARNS("lleventcoro") << listenerName
+ << " couldn't throw Stopping "
+ "because promise already set" << LL_ENDL;
}
- // do not consume -- every listener must see status
- return false;
}));
LLBoundListener connection(
replyPump.listen(
diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h
index 4c3c0f3414..35bf9075a0 100644
--- a/indra/llcommon/lleventdispatcher.h
+++ b/indra/llcommon/lleventdispatcher.h
@@ -6,25 +6,25 @@
* useful when you have a single LLEventPump listener on which you can
* request different operations, vs. instantiating a different
* LLEventPump for each such operation.
- *
+ *
* $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$
*/
@@ -201,7 +201,7 @@ public:
template <typename R, class CLASS, typename ARG,
typename = typename std::enable_if<
! std::is_same<typename std::decay<ARG>::type, LLSD>::value
- >::type>
+ >::type>
void add(const std::string& name,
const std::string& desc,
R (CLASS::*method)(ARG))
@@ -213,7 +213,7 @@ public:
template <typename R, class CLASS, typename ARG,
typename = typename std::enable_if<
! std::is_same<typename std::decay<ARG>::type, LLSD>::value
- >::type>
+ >::type>
void add(const std::string& name,
const std::string& desc,
R (CLASS::*method)(ARG) const)
@@ -226,7 +226,7 @@ public:
template <class CLASS, typename ARG,
typename = typename std::enable_if<
! std::is_same<typename std::decay<ARG>::type, LLSD>::value
- >::type>
+ >::type>
void add(const std::string& name,
const std::string& desc,
void (CLASS::*method)(ARG))
@@ -238,7 +238,7 @@ public:
template <class CLASS, typename ARG,
typename = typename std::enable_if<
! std::is_same<typename std::decay<ARG>::type, LLSD>::value
- >::type>
+ >::type>
void add(const std::string& name,
const std::string& desc,
void (CLASS::*method)(ARG) const)
@@ -247,7 +247,7 @@ public:
}
// non-const binary (or more) method
- template <typename R, class CLASS, typename ARG0, typename ARG1, typename... ARGS>
+ template <typename R, class CLASS, typename ARG0, typename ARG1, typename... ARGS>
void add(const std::string& name,
const std::string& desc,
R (CLASS::*method)(ARG0, ARG1, ARGS...))
@@ -256,7 +256,7 @@ public:
}
// const binary (or more) method
- template <typename R, class CLASS, typename ARG0, typename ARG1, typename... ARGS>
+ template <typename R, class CLASS, typename ARG0, typename ARG1, typename... ARGS>
void add(const std::string& name,
const std::string& desc,
R (CLASS::*method)(ARG0, ARG1, ARGS...) const)
@@ -265,7 +265,7 @@ public:
}
// non-const binary (or more) method returning void
- template <class CLASS, typename ARG0, typename ARG1, typename... ARGS>
+ template <class CLASS, typename ARG0, typename ARG1, typename... ARGS>
void add(const std::string& name,
const std::string& desc,
void (CLASS::*method)(ARG0, ARG1, ARGS...))
@@ -274,7 +274,7 @@ public:
}
// const binary (or more) method returning void
- template <class CLASS, typename ARG0, typename ARG1, typename... ARGS>
+ template <class CLASS, typename ARG0, typename ARG1, typename... ARGS>
void add(const std::string& name,
const std::string& desc,
void (CLASS::*method)(ARG0, ARG1, ARGS...) const)
@@ -371,7 +371,7 @@ public:
const InstanceGetter& getter, const LLSD& params,
const LLSD& defaults=LLSD());
- //@}
+ //@}
/// Unregister a callable
bool remove(const std::string& name);
@@ -851,6 +851,8 @@ public:
ARGS&&... args);
virtual ~LLDispatchListener() {}
+ std::string getPumpName() const { return getName(); }
+
private:
bool process(const LLSD& event) const;
void call_one(const LLSD& name, const LLSD& event) const;
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 5b4e69659d..d7870763cc 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-09-12
* @brief Implementation for llevents.
- *
+ *
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -43,6 +43,7 @@
#include <typeinfo>
#include <cmath>
#include <cctype>
+#include <iomanip> // std::quoted
// external library headers
#include <boost/range/iterator_range.hpp>
#if LL_WINDOWS
@@ -54,10 +55,11 @@
#pragma warning (pop)
#endif
// other Linden headers
-#include "stringize.h"
#include "llerror.h"
-#include "llsdutil.h"
+#include "lleventfilter.h"
#include "llexception.h"
+#include "llsdutil.h"
+#include "stringize.h"
#if LL_MSVC
#pragma warning (disable : 4702)
#endif
@@ -71,7 +73,9 @@ LLEventPumps::LLEventPumps():
{ "LLEventStream", [](const std::string& name, bool tweak, const std::string& /*type*/)
{ return new LLEventStream(name, tweak); } },
{ "LLEventMailDrop", [](const std::string& name, bool tweak, const std::string& /*type*/)
- { return new LLEventMailDrop(name, tweak); } }
+ { return new LLEventMailDrop(name, tweak); } },
+ { "LLEventLogProxy", [](const std::string& name, bool tweak, const std::string& /*type*/)
+ { return new LLEventLogProxyFor<LLEventStream>(name, tweak); } }
},
mTypes
{
@@ -186,8 +190,13 @@ bool LLEventPumps::post(const std::string&name, const LLSD&message)
PumpMap::iterator found = mPumpMap.find(name);
if (found == mPumpMap.end())
+ {
+ LL_DEBUGS("LLEventPumps") << "LLEventPump(" << std::quoted(name) << ") not found"
+ << LL_ENDL;
return false;
+ }
+// LL_DEBUGS("LLEventPumps") << "posting to " << name << ": " << message << LL_ENDL;
return (*found).second->post(message);
}
@@ -414,7 +423,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
{
if (!mSignal)
{
- LL_WARNS() << "Can't connect listener" << LL_ENDL;
+ LL_WARNS("LLEventPump") << "Can't connect listener" << LL_ENDL;
// connect will fail, return dummy
return LLBoundListener();
}
@@ -423,8 +432,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
float nodePosition = 1.0;
- // if the supplied name is empty we are not interested in the ordering mechanism
- // and can bypass attempting to find the optimal location to insert the new
+ // if the supplied name is empty we are not interested in the ordering mechanism
+ // and can bypass attempting to find the optimal location to insert the new
// listener. We'll just tack it on to the end.
if (!name.empty()) // should be the same as testing against ANONYMOUS
{
@@ -569,12 +578,12 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// Now that newNode has a value that places it appropriately in mSignal,
// connect it.
LLBoundListener bound = mSignal->connect(nodePosition, listener);
-
+
if (!name.empty())
{ // note that we are not tracking anonymous listeners here either.
- // This means that it is the caller's responsibility to either assign
- // to a TempBoundListerer (scoped_connection) or manually disconnect
- // when done.
+ // This means that it is the caller's responsibility to either assign
+ // to a TempBoundListerer (scoped_connection) or manually disconnect
+ // when done.
mConnections[name] = bound;
}
return bound;
@@ -641,9 +650,9 @@ bool LLEventMailDrop::post(const LLSD& event)
{
// forward the call to our base class
bool posted = LLEventStream::post(event);
-
+
if (!posted)
- { // if the event was not handled we will save it for later so that it can
+ { // if the event was not handled we will save it for later so that it can
// be posted to any future listeners when they attach.
mEventHistory.push_back(event);
}
@@ -733,7 +742,7 @@ void LLReqID::stamp(LLSD& response) const
response["reqid"] = mReqid;
}
-bool sendReply(const LLSD& reply, const LLSD& request, const std::string& replyKey)
+bool sendReply(LLSD reply, const LLSD& request, const std::string& replyKey)
{
// If the original request has no value for replyKey, it's pointless to
// construct or send a reply event: on which LLEventPump should we send
@@ -746,13 +755,10 @@ bool sendReply(const LLSD& reply, const LLSD& request, const std::string& replyK
// Here the request definitely contains replyKey; reasonable to proceed.
- // Copy 'reply' to modify it.
- LLSD newreply(reply);
// Get the ["reqid"] element from request
LLReqID reqID(request);
- // and copy it to 'newreply'.
- reqID.stamp(newreply);
- // Send reply on LLEventPump named in request[replyKey]. Don't forget to
- // send the modified 'newreply' instead of the original 'reply'.
- return LLEventPumps::instance().obtain(request[replyKey]).post(newreply);
+ // and copy it to 'reply'.
+ reqID.stamp(reply);
+ // Send reply on LLEventPump named in request[replyKey].
+ return LLEventPumps::instance().obtain(request[replyKey]).post(reply);
}
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 9a0a6863f0..1fc0f23ecd 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -6,25 +6,25 @@
* https://wiki.lindenlab.com/wiki/Viewer:Messaging/Event_System,
* originally introduced in llnotifications.h. It has nothing
* whatsoever to do with the older system in llevent.h.
- *
+ *
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -39,36 +39,22 @@
#include <deque>
#include <functional>
#if LL_WINDOWS
- #pragma warning (push)
- #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
- #pragma warning (disable : 4264)
+ #pragma warning (push)
+ #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
+ #pragma warning (disable : 4264)
#endif
#include <boost/signals2.hpp>
#if LL_WINDOWS
- #pragma warning (pop)
+ #pragma warning (pop)
#endif
-#include <boost/bind.hpp>
-#include <boost/utility.hpp> // noncopyable
#include <boost/optional/optional.hpp>
-#include <boost/visit_each.hpp>
-#include <boost/ref.hpp> // reference_wrapper
-#include <boost/type_traits/is_pointer.hpp>
-#include <boost/static_assert.hpp>
#include "llsd.h"
#include "llsingleton.h"
#include "lldependencies.h"
-#include "llstl.h"
#include "llexception.h"
#include "llhandle.h"
-/*==========================================================================*|
-// override this to allow binding free functions with more parameters
-#ifndef LLEVENTS_LISTENER_ARITY
-#define LLEVENTS_LISTENER_ARITY 10
-#endif
-|*==========================================================================*/
-
// hack for testing
#ifndef testable
#define testable private
@@ -151,6 +137,8 @@ typedef boost::signals2::signal<bool(const LLSD&), LLStopWhenHandled, float> LL
/// Methods that forward listeners (e.g. constructed with
/// <tt>boost::bind()</tt>) should accept (const LLEventListener&)
typedef LLStandardSignal::slot_type LLEventListener;
+/// Accept a void listener too
+typedef std::function<void(const LLSD&)> LLVoidListener;
/// Result of registering a listener, supports <tt>connected()</tt>,
/// <tt>disconnect()</tt> and <tt>blocked()</tt>
typedef boost::signals2::connection LLBoundListener;
@@ -310,9 +298,9 @@ public:
/**
* Find the named LLEventPump instance. If it exists post the message to it.
* If the pump does not exist, do nothing.
- *
+ *
* returns the result of the LLEventPump::post. If no pump exists returns false.
- *
+ *
* This is syntactically similar to LLEventPumps::instance().post(name, message),
* however if the pump does not already exist it will not be created.
*/
@@ -541,10 +529,10 @@ public:
* instantiate your listener, then passing the same name on each listen()
* call, allows us to optimize away the second and subsequent dependency
* sorts.
- *
- * If name is set to LLEventPump::ANONYMOUS listen will bypass the entire
- * dependency and ordering calculation. In this case, it is critical that
- * the result be assigned to a LLTempBoundListener or the listener is
+ *
+ * If name is set to LLEventPump::ANONYMOUS listen will bypass the entire
+ * dependency and ordering calculation. In this case, it is critical that
+ * the result be assigned to a LLTempBoundListener or the listener is
* manually disconnected when no longer needed since there will be no
* way to later find and disconnect this listener manually.
*/
@@ -607,7 +595,7 @@ protected:
virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&,
const NameList& after,
const NameList& before);
-
+
/// implement the dispatching
std::shared_ptr<LLStandardSignal> mSignal;
@@ -660,21 +648,21 @@ public:
* by all listeners, until some listener consumes it. The caveat is that each
* event *must* eventually reach a listener that will consume it, else the
* queue will grow to arbitrary length.
- *
+ *
* @NOTE: When using an LLEventMailDrop with an LLEventTimeout or
* LLEventFilter attaching the filter downstream, using Timeout's constructor will
- * cause the MailDrop to discharge any of its stored events. The timeout should
- * instead be connected upstream using its listen() method.
+ * cause the MailDrop to discharge any of its stored events. The timeout should
+ * instead be connected upstream using its listen() method.
*/
class LL_COMMON_API LLEventMailDrop : public LLEventStream
{
public:
LLEventMailDrop(const std::string& name, bool tweak = false) : LLEventStream(name, tweak) {}
virtual ~LLEventMailDrop() {}
-
+
/// Post an event to all listeners
virtual bool post(const LLSD& event) override;
-
+
/// Remove any history stored in the mail drop.
void discard();
@@ -689,6 +677,30 @@ private:
};
/*****************************************************************************
+* LLNamedListener
+*****************************************************************************/
+/**
+ * LLNamedListener bundles a concrete LLEventPump subclass with a specific
+ * listener function, with an LLTempBoundListener to ensure that it's
+ * disconnected before destruction.
+ */
+template <class PUMP=LLEventStream>
+class LL_COMMON_API LLNamedListener: PUMP
+{
+ using pump_t = PUMP;
+public:
+ template <typename LISTENER>
+ LLNamedListener(const std::string& name, LISTENER&& listener):
+ pump_t(name, false), // don't tweak the name
+ mConn(pump_t::listen("func", std::forward<LISTENER>(listener)))
+ {}
+
+private:
+ LLTempBoundListener mConn;
+};
+using LLStreamListener = LLNamedListener<>;
+
+/*****************************************************************************
* LLReqID
*****************************************************************************/
/**
@@ -780,7 +792,7 @@ private:
* Before sending the reply event, sendReply() copies the ["reqid"] item from
* the request to the reply.
*/
-LL_COMMON_API bool sendReply(const LLSD& reply, const LLSD& request,
+LL_COMMON_API bool sendReply(LLSD reply, const LLSD& request,
const std::string& replyKey="reply");
#endif /* ! defined(LL_LLEVENTS_H) */
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
index 68e609444e..9e322db86d 100644
--- a/indra/llcommon/llexception.h
+++ b/indra/llcommon/llexception.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2016-06-29
* @brief Types needed for generic exception handling
- *
+ *
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Copyright (c) 2016, Linden Research, Inc.
* $/LicenseInfo$
@@ -12,6 +12,7 @@
#if ! defined(LL_LLEXCEPTION_H)
#define LL_LLEXCEPTION_H
+#include "stdtypes.h"
#include <stdexcept>
#include <boost/exception/exception.hpp>
#include <boost/throw_exception.hpp>
diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h
index 4456a72696..97ea3b7b78 100644
--- a/indra/llcommon/llformat.h
+++ b/indra/llcommon/llformat.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llformat.h
* @date January 2007
* @brief string formatting utility
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
@@ -28,6 +28,8 @@
#ifndef LL_LLFORMAT_H
#define LL_LLFORMAT_H
+#include "llpreprocessor.h"
+
// Use as follows:
// LL_INFOS() << llformat("Test:%d (%.2f %.2f)", idx, x, y) << LL_ENDL;
//
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 3232a0e219..921f743ada 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llinstancetracker.h
* @brief LLInstanceTracker is a mixin class that automatically tracks object
* instances with or without an associated key
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -99,11 +99,11 @@ public:
return mSelf;
}
- static size_t instanceCount()
- {
- return LockStatic()->mMap.size();
+ static size_t instanceCount()
+ {
+ return LockStatic()->mMap.size();
}
-
+
// snapshot of std::pair<const KEY, std::shared_ptr<SUBCLASS>> pairs, for
// some SUBCLASS derived from T
template <typename SUBCLASS>
@@ -243,7 +243,7 @@ public:
}
protected:
- LLInstanceTracker(const KEY& key)
+ LLInstanceTracker(const KEY& key)
{
// We do not intend to manage the lifespan of this object with
// shared_ptr, so give it a no-op deleter. We store shared_ptrs in our
@@ -275,6 +275,35 @@ protected:
public:
virtual const KEY& getKey() const { return mInstanceKey; }
+ /// for use ONLY for an object we're sure resides on the heap!
+ static bool destruct(const KEY& key)
+ {
+ return destruct(getInstance(key));
+ }
+
+ /// for use ONLY for an object we're sure resides on the heap!
+ static bool destruct(const weak_t& ptr)
+ {
+ return destruct(ptr.lock());
+ }
+
+ /// for use ONLY for an object we're sure resides on the heap!
+ static bool destruct(const ptr_t& ptr)
+ {
+ if (! ptr)
+ {
+ return false;
+ }
+
+ // Because we store and return ptr_t instances with no-op deleters,
+ // merely resetting the last pointer doesn't destroy the referenced
+ // object. Don't even bother resetting 'ptr'. Just extract its raw
+ // pointer and delete that.
+ auto raw{ ptr.get() };
+ delete raw;
+ return true;
+ }
+
private:
LLInstanceTracker( const LLInstanceTracker& ) = delete;
LLInstanceTracker& operator=( const LLInstanceTracker& ) = delete;
@@ -286,9 +315,9 @@ private:
static std::string report(const char* key) { return report(std::string(key)); }
// caller must instantiate LockStatic
- void add_(LockStatic& lock, const KEY& key, const ptr_t& ptr)
- {
- mInstanceKey = key;
+ void add_(LockStatic& lock, const KEY& key, const ptr_t& ptr)
+ {
+ mInstanceKey = key;
InstanceMap& map = lock->mMap;
switch(KEY_COLLISION_BEHAVIOR)
{
@@ -373,7 +402,7 @@ public:
{
return mSelf;
}
-
+
static size_t instanceCount()
{
return LockStatic()->mSet.size();
@@ -479,6 +508,29 @@ public:
template <typename SUBCLASS>
using key_snapshot_of = instance_snapshot_of<SUBCLASS>;
+ /// for use ONLY for an object we're sure resides on the heap!
+ static bool destruct(const weak_t& ptr)
+ {
+ return destruct(ptr.lock());
+ }
+
+ /// for use ONLY for an object we're sure resides on the heap!
+ static bool destruct(const ptr_t& ptr)
+ {
+ if (! ptr)
+ {
+ return false;
+ }
+
+ // Because we store and return ptr_t instances with no-op deleters,
+ // merely resetting the last pointer doesn't destroy the referenced
+ // object. Don't even bother resetting 'ptr'. Just extract its raw
+ // pointer and delete that.
+ auto raw{ ptr.get() };
+ delete raw;
+ return true;
+ }
+
protected:
LLInstanceTracker()
{
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index d0fb586459..f7f2981638 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-02-20
* @brief Implementation for llleap.
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
@@ -14,13 +14,11 @@
// associated header
#include "llleap.h"
// STL headers
-#include <sstream>
#include <algorithm>
+#include <memory>
+#include <sstream>
// std headers
// external library headers
-#include <boost/bind.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/tokenizer.hpp>
// other Linden headers
#include "llerror.h"
#include "llstring.h"
@@ -53,18 +51,19 @@ public:
// We expect multiple LLLeapImpl instances. Definitely tweak
// mDonePump's name for uniqueness.
mDonePump("LLLeap", true),
- // Troubling thought: what if one plugin intentionally messes with
- // another plugin? LLEventPump names are in a single global namespace.
- // Try to make that more difficult by generating a UUID for the reply-
- // pump name -- so it should NOT need tweaking for uniqueness.
- mReplyPump(LLUUID::generateNewID().asString()),
mExpect(0),
// Instantiate a distinct LLLeapListener for this plugin. (Every
// plugin will want its own collection of managed listeners, etc.)
- // Pass it a callback to our connect() method, so it can send events
+ // Pass it our wstdin() method as its callback, so it can send events
// from a particular LLEventPump to the plugin without having to know
// this class or method name.
- mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2)))
+ mListener(
+ new LLLeapListener(
+ "LLLeap",
+ // Serialize any reply event to our child's stdin, suitably
+ // enriched with the pump name on which it was received.
+ [this](const std::string& pump, const LLSD& data)
+ { return wstdin(pump, data); }))
{
// Rule out unpopulated Params block
if (! cparams.executable.isProvided())
@@ -93,7 +92,7 @@ public:
}
// Listen for child "termination" right away to catch launch errors.
- mDonePump.listen("LLLeap", boost::bind(&LLLeapImpl::bad_launch, this, _1));
+ mDonePump.listen("LLLeap", [this](const LLSD& data){ return bad_launch(data); });
// Okay, launch child.
// Get a modifiable copy of params block to set files and postend.
@@ -113,7 +112,7 @@ public:
// Okay, launch apparently worked. Change our mDonePump listener.
mDonePump.stopListening("LLLeap");
- mDonePump.listen("LLLeap", boost::bind(&LLLeapImpl::done, this, _1));
+ mDonePump.listen("LLLeap", [this](const LLSD& data){ return done(data); });
// Child might pump large volumes of data through either stdout or
// stderr. Don't bother copying all that data into notification event.
@@ -123,17 +122,14 @@ public:
childout.setLimit(20);
childerr.setLimit(20);
- // Serialize any event received on mReplyPump to our child's stdin.
- mStdinConnection = connect(mReplyPump, "LLLeap");
-
// Listening on stdout is stateful. In general, we're either waiting
// for the length prefix or waiting for the specified length of data.
// We address that with two different listener methods -- one of which
// is blocked at any given time.
mStdoutConnection = childout.getPump()
- .listen("prefix", boost::bind(&LLLeapImpl::rstdout, this, _1));
+ .listen("prefix", [this](const LLSD& data){ return rstdout(data); });
mStdoutDataConnection = childout.getPump()
- .listen("data", boost::bind(&LLLeapImpl::rstdoutData, this, _1));
+ .listen("data", [this](const LLSD& data){ return rstdoutData(data); });
mBlocker.reset(new LLEventPump::Blocker(mStdoutDataConnection));
// Log anything sent up through stderr. When a typical program
@@ -142,7 +138,7 @@ public:
// interpreter behaves that way. More generally, though, a plugin
// author can log whatever s/he wants to the viewer log using stderr.
mStderrConnection = childerr.getPump()
- .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1));
+ .listen("LLLeap", [this](const LLSD& data){ return rstderr(data); });
// For our lifespan, intercept any LL_ERRS so we can notify plugin
mRecorder = LLError::addGenericRecorder(
@@ -151,7 +147,7 @@ public:
// Send child a preliminary event reporting our own reply-pump name --
// which would otherwise be pretty tricky to guess!
- wstdin(mReplyPump.getName(),
+ wstdin(mListener->getReplyPump().getName(),
LLSDMap
("command", mListener->getName())
// Include LLLeap features -- this may be important for child to
@@ -198,7 +194,7 @@ public:
return false;
}
- // Listener for events on mReplyPump: send to child stdin
+ // Listener for reply events: send to child stdin
bool wstdin(const std::string& pump, const LLSD& data)
{
LLSD packet(LLSDMap("pump", pump)("data", data));
@@ -355,7 +351,7 @@ public:
// request, send a reply. We happen to know who originated
// this request, and the reply LLEventPump of interest.
// Not our problem if the plugin ignores the reply event.
- data["reply"] = mReplyPump.getName();
+ data["reply"] = mListener->getReplyPump().getName();
sendReply(llsd::map("error",
stringize(LLError::Log::classname(err), ": ", err.what())),
data);
@@ -428,7 +424,7 @@ public:
LLSD event;
event["type"] = "error";
event["error"] = error;
- mReplyPump.post(event);
+ mListener->getReplyPump().post(event);
// All the above really accomplished was to buffer the serialized
// event in our WritePipe. Have to pump mainloop a couple times to
@@ -445,23 +441,10 @@ public:
}
private:
- /// We always want to listen on mReplyPump with wstdin(); under some
- /// circumstances we'll also echo other LLEventPumps to the plugin.
- LLBoundListener connect(LLEventPump& pump, const std::string& listener)
- {
- // Serialize any event received on the specified LLEventPump to our
- // child's stdin, suitably enriched with the pump name on which it was
- // received.
- return pump.listen(listener,
- boost::bind(&LLLeapImpl::wstdin, this, pump.getName(), _1));
- }
-
std::string mDesc;
LLEventStream mDonePump;
- LLEventStream mReplyPump;
LLProcessPtr mChild;
- LLTempBoundListener
- mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection;
+ LLTempBoundListener mStdoutConnection, mStdoutDataConnection, mStderrConnection;
std::unique_ptr<LLEventPump::Blocker> mBlocker;
LLProcess::ReadPipe::size_type mExpect;
LLError::RecorderPtr mRecorder;
diff --git a/indra/llcommon/llleaplistener.cpp b/indra/llcommon/llleaplistener.cpp
index 050d71c327..9b9b0f5121 100644
--- a/indra/llcommon/llleaplistener.cpp
+++ b/indra/llcommon/llleaplistener.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-03-16
* @brief Implementation for llleaplistener.
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
@@ -54,53 +54,62 @@
return features;
}
-LLLeapListener::LLLeapListener(const ConnectFunc& connect):
+LLLeapListener::LLLeapListener(const std::string_view& caller, const Callback& callback):
// Each LEAP plugin has an instance of this listener. Make the command
// pump name difficult for other such plugins to guess.
LLEventAPI(LLUUID::generateNewID().asString(),
"Operations relating to the LLSD Event API Plugin (LEAP) protocol"),
- mConnect(connect)
+ mCaller(caller),
+ mCallback(callback),
+ // Troubling thought: what if one plugin intentionally messes with
+ // another plugin? LLEventPump names are in a single global namespace.
+ // Try to make that more difficult by generating a UUID for the reply-
+ // pump name -- so it should NOT need tweaking for uniqueness.
+ mReplyPump(LLUUID::generateNewID().asString()),
+ mReplyConn(connect(mReplyPump, mCaller))
{
LLSD need_name(LLSDMap("name", LLSD()));
add("newpump",
- "Instantiate a new LLEventPump named like [\"name\"] and listen to it.\n"
- "[\"type\"] == \"LLEventStream\", \"LLEventMailDrop\" et al.\n"
- "Events sent through new LLEventPump will be decorated with [\"pump\"]=name.\n"
- "Returns actual name in [\"name\"] (may be different if collision).",
+R"-(Instantiate a new LLEventPump named like ["name"] and listen to it.
+["type"] == "LLEventStream", "LLEventMailDrop" et al.
+Events sent through new LLEventPump will be decorated with ["pump"]=name.
+Returns actual name in ["name"] (may be different if collision).)-",
&LLLeapListener::newpump,
need_name);
LLSD need_source_listener(LLSDMap("source", LLSD())("listener", LLSD()));
add("listen",
- "Listen to an existing LLEventPump named [\"source\"], with listener name\n"
- "[\"listener\"].\n"
- "By default, send events on [\"source\"] to the plugin, decorated\n"
- "with [\"pump\"]=[\"source\"].\n"
- "If [\"dest\"] specified, send undecorated events on [\"source\"] to the\n"
- "LLEventPump named [\"dest\"].\n"
- "Returns [\"status\"] boolean indicating whether the connection was made.",
+R"-(Listen to an existing LLEventPump named ["source"], with listener name
+["listener"].
+If ["tweak"] is specified as true, tweak listener name for uniqueness.
+By default, send events on ["source"] to the plugin, decorated
+with ["pump"]=["source"].
+If ["dest"] specified, send undecorated events on ["source"] to the
+LLEventPump named ["dest"].
+Returns ["status"] boolean indicating whether the connection was made,
+plus ["listener"] reporting (possibly tweaked) listener name.)-",
&LLLeapListener::listen,
need_source_listener);
add("stoplistening",
- "Disconnect a connection previously established by \"listen\".\n"
- "Pass same [\"source\"] and [\"listener\"] arguments.\n"
- "Returns [\"status\"] boolean indicating whether such a listener existed.",
+R"-(Disconnect a connection previously established by "listen".
+Pass same ["source"] and ["listener"] arguments.
+Returns ["status"] boolean indicating whether such a listener existed.)-",
&LLLeapListener::stoplistening,
need_source_listener);
add("ping",
- "No arguments, just a round-trip sanity check.",
+"No arguments, just a round-trip sanity check.",
&LLLeapListener::ping);
add("getAPIs",
- "Enumerate all LLEventAPI instances by name and description.",
+"Enumerate all LLEventAPI instances by name and description.",
&LLLeapListener::getAPIs);
add("getAPI",
- "Get name, description, dispatch key and operations for LLEventAPI [\"api\"].",
+R"-(Get name, description, dispatch key and operations for LLEventAPI ["api"].)-",
&LLLeapListener::getAPI,
LLSD().with("api", LLSD()));
add("getFeatures",
- "Return an LLSD map of feature strings (deltas from baseline LEAP protocol)",
+"Return an LLSD map of feature strings (deltas from baseline LEAP protocol)",
static_cast<void (LLLeapListener::*)(const LLSD&) const>(&LLLeapListener::getFeatures));
add("getFeature",
- "Return the feature value with key [\"feature\"]",
+R"-(Return the feature value with key ["feature"])-",
&LLLeapListener::getFeature,
LLSD().with("feature", LLSD()));
}
@@ -112,6 +121,7 @@ LLLeapListener::~LLLeapListener()
// value_type, and Bad Things would happen if you copied an
// LLTempBoundListener. (Destruction of the original would disconnect the
// listener, invalidating every stored connection.)
+ LL_DEBUGS("LLLeapListener") << "~LLLeapListener(\"" << mCaller << "\")" << LL_ENDL;
for (ListenersMap::value_type& pair : mListeners)
{
pair.second.disconnect();
@@ -133,8 +143,7 @@ void LLLeapListener::newpump(const LLSD& request)
reply["name"] = name;
// Now listen on this new pump with our plugin listener
- std::string myname("llleap");
- saveListener(name, myname, mConnect(new_pump, myname));
+ saveListener(name, mCaller, connect(new_pump, mCaller));
}
catch (const LLEventPumps::BadType& error)
{
@@ -149,6 +158,11 @@ void LLLeapListener::listen(const LLSD& request)
std::string source_name = request["source"];
std::string dest_name = request["dest"];
std::string listener_name = request["listener"];
+ if (request["tweak"].asBoolean())
+ {
+ listener_name = LLEventPump::inventName(listener_name);
+ }
+ reply["listener"] = listener_name;
LLEventPump & source = LLEventPumps::instance().obtain(source_name);
@@ -170,7 +184,7 @@ void LLLeapListener::listen(const LLSD& request)
{
// "dest" unspecified means to direct events on "source"
// to our plugin listener.
- saveListener(source_name, listener_name, mConnect(source, listener_name));
+ saveListener(source_name, listener_name, connect(source, listener_name));
}
reply["status"] = true;
}
@@ -292,10 +306,27 @@ void LLLeapListener::getFeature(const LLSD& request) const
}
}
+LLBoundListener LLLeapListener::connect(LLEventPump& pump, const std::string& listener)
+{
+ // Connect to source pump with an adapter that calls our callback with the
+ // pump name as well as the event data.
+ return pump.listen(
+ listener,
+ [callback=mCallback, pump=pump.getName()]
+ (const LLSD& data)
+ { return callback(pump, data); });
+}
+
void LLLeapListener::saveListener(const std::string& pump_name,
const std::string& listener_name,
const LLBoundListener& listener)
{
- mListeners.insert(ListenersMap::value_type(ListenersMap::key_type(pump_name, listener_name),
- listener));
+ // Don't use insert() or emplace() because, if this (pump_name,
+ // listener_name) pair is already in mListeners, we *want* to overwrite it.
+ auto& listener_entry{ mListeners[ListenersMap::key_type(pump_name, listener_name)] };
+ // If we already stored a connection for this pump and listener name,
+ // disconnect it before overwriting it. But if this entry was newly
+ // created, disconnect() will be a no-op.
+ listener_entry.disconnect();
+ listener_entry = listener;
}
diff --git a/indra/llcommon/llleaplistener.h b/indra/llcommon/llleaplistener.h
index cad4543d02..040fb737b7 100644
--- a/indra/llcommon/llleaplistener.h
+++ b/indra/llcommon/llleaplistener.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-03-16
* @brief LLEventAPI supporting LEAP plugins
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
@@ -13,10 +13,9 @@
#define LL_LLLEAPLISTENER_H
#include "lleventapi.h"
+#include <functional>
#include <map>
#include <string>
-#include <boost/function.hpp>
-#include <boost/ptr_container/ptr_map.hpp>
/// Listener class implementing LLLeap query/control operations.
/// See https://jira.lindenlab.com/jira/browse/DEV-31978.
@@ -24,18 +23,16 @@ class LLLeapListener: public LLEventAPI
{
public:
/**
- * Decouple LLLeap by dependency injection. Certain LLLeapListener
- * operations must be able to cause LLLeap to listen on a specified
- * LLEventPump with the LLLeap listener that wraps incoming events in an
- * outer (pump=, data=) map and forwards them to the plugin. Very well,
- * define the signature for a function that will perform that, and make
- * our constructor accept such a function.
+ * Certain LLLeapListener operations listen on a specified LLEventPump.
+ * Accept a bool(pump, data) callback from our caller for when any such
+ * event is received.
*/
- typedef boost::function<LLBoundListener(LLEventPump&, const std::string& listener)>
- ConnectFunc;
- LLLeapListener(const ConnectFunc& connect);
+ using Callback = std::function<bool(const std::string& pump, const LLSD& data)>;
+ LLLeapListener(const std::string_view& caller, const Callback& callback);
~LLLeapListener();
+ LLEventPump& getReplyPump() { return mReplyPump; }
+
static LLSD getFeatures();
private:
@@ -48,10 +45,16 @@ private:
void getFeatures(const LLSD&) const;
void getFeature(const LLSD&) const;
+ LLBoundListener connect(LLEventPump& pump, const std::string& listener);
void saveListener(const std::string& pump_name, const std::string& listener_name,
const LLBoundListener& listener);
- ConnectFunc mConnect;
+ // The relative order of these next declarations is important because the
+ // constructor will initialize in this order.
+ std::string mCaller;
+ Callback mCallback;
+ LLEventStream mReplyPump;
+ LLTempBoundListener mReplyConn;
// In theory, listen() could simply call the relevant LLEventPump's
// listen() method, stoplistening() likewise. Lifespan issues make us
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index 33c9e956b1..5789b5de2c 100644
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrefcount.h
* @brief Base class for reference counted objects for use with LLPointer
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -29,6 +29,7 @@
#include <boost/noncopyable.hpp>
#include <boost/intrusive_ptr.hpp>
#include "llatomic.h"
+#include "llerror.h"
class LLMutex;
@@ -44,42 +45,42 @@ extern const S32 gMaxRefCount;
class LL_COMMON_API LLRefCount
{
protected:
- LLRefCount(const LLRefCount& other);
- LLRefCount& operator=(const LLRefCount&);
- virtual ~LLRefCount(); // use unref()
-
+ LLRefCount(const LLRefCount& other);
+ LLRefCount& operator=(const LLRefCount&);
+ virtual ~LLRefCount(); // use unref()
+
public:
- LLRefCount();
-
- inline void ref() const
- {
- llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
- mRef++;
- llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak
- }
-
- inline S32 unref() const
- {
- llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
- llassert(mRef > 0); // ref count below 1, likely corrupted
- if (0 == --mRef)
- {
- mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging
- delete this;
- return 0;
- }
- return mRef;
- }
-
- //NOTE: when passing around a const LLRefCount object, this can return different results
- // at different types, since mRef is mutable
- S32 getNumRefs() const
- {
- return mRef;
- }
+ LLRefCount();
+
+ inline void ref() const
+ {
+ llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
+ mRef++;
+ llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak
+ }
+
+ inline S32 unref() const
+ {
+ llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
+ llassert(mRef > 0); // ref count below 1, likely corrupted
+ if (0 == --mRef)
+ {
+ mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging
+ delete this;
+ return 0;
+ }
+ return mRef;
+ }
+
+ //NOTE: when passing around a const LLRefCount object, this can return different results
+ // at different types, since mRef is mutable
+ S32 getNumRefs() const
+ {
+ return mRef;
+ }
private:
- mutable S32 mRef;
+ mutable S32 mRef;
};
@@ -90,50 +91,50 @@ private:
class LL_COMMON_API LLThreadSafeRefCount
{
public:
- static void initThreadSafeRefCount(); // creates sMutex
- static void cleanupThreadSafeRefCount(); // destroys sMutex
+ static void initThreadSafeRefCount(); // creates sMutex
+ static void cleanupThreadSafeRefCount(); // destroys sMutex
private:
- static LLMutex* sMutex;
+ static LLMutex* sMutex;
protected:
- virtual ~LLThreadSafeRefCount(); // use unref()
+ virtual ~LLThreadSafeRefCount(); // use unref()
public:
- LLThreadSafeRefCount();
- LLThreadSafeRefCount(const LLThreadSafeRefCount&);
- LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
- {
- mRef = 0;
- return *this;
- }
-
- void ref()
- {
- mRef++;
- }
-
- void unref()
- {
- llassert(mRef >= 1);
- if ((--mRef) == 0)
- {
- // If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
- // It is technically possible for a vanilla pointer to mess this up, or another thread to
- // jump in, find this object, create another smart pointer and end up dangling, but if
- // the code is that bad and not thread-safe, it's trouble already.
- delete this;
- }
- }
-
- S32 getNumRefs() const
- {
- const S32 currentVal = mRef.CurrentValue();
- return currentVal;
- }
+ LLThreadSafeRefCount();
+ LLThreadSafeRefCount(const LLThreadSafeRefCount&);
+ LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
+ {
+ mRef = 0;
+ return *this;
+ }
+
+ void ref()
+ {
+ mRef++;
+ }
+
+ void unref()
+ {
+ llassert(mRef >= 1);
+ if ((--mRef) == 0)
+ {
+ // If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
+ // It is technically possible for a vanilla pointer to mess this up, or another thread to
+ // jump in, find this object, create another smart pointer and end up dangling, but if
+ // the code is that bad and not thread-safe, it's trouble already.
+ delete this;
+ }
+ }
+
+ S32 getNumRefs() const
+ {
+ const S32 currentVal = mRef.CurrentValue();
+ return currentVal;
+ }
private:
- LLAtomicS32 mRef;
+ LLAtomicS32 mRef;
};
/**
@@ -142,12 +143,12 @@ private:
*/
inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p)
{
- p->ref();
+ p->ref();
}
inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
{
- p->unref();
+ p->unref();
}
/**
@@ -156,12 +157,12 @@ inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
*/
inline void intrusive_ptr_add_ref(LLRefCount* p)
{
- p->ref();
+ p->ref();
}
inline void intrusive_ptr_release(LLRefCount* p)
{
- p->unref();
+ p->unref();
}
#endif
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 3829978ddf..9478dff871 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstring.h
* @brief String utility functions and std::string class.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -37,7 +37,9 @@
#include <algorithm>
#include <vector>
#include <map>
+#include <type_traits>
#include "llformat.h"
+#include "stdtypes.h"
#if LL_LINUX
#include <wctype.h>
@@ -59,85 +61,85 @@ namespace std
template<>
struct char_traits<U16>
{
- typedef U16 char_type;
- typedef int int_type;
- typedef streampos pos_type;
- typedef streamoff off_type;
- typedef mbstate_t state_type;
-
- static void
- assign(char_type& __c1, const char_type& __c2)
- { __c1 = __c2; }
-
- static bool
- eq(const char_type& __c1, const char_type& __c2)
- { return __c1 == __c2; }
-
- static bool
- lt(const char_type& __c1, const char_type& __c2)
- { return __c1 < __c2; }
-
- static int
- compare(const char_type* __s1, const char_type* __s2, size_t __n)
- { return memcmp(__s1, __s2, __n * sizeof(char_type)); }
-
- static size_t
- length(const char_type* __s)
- {
- const char_type *cur_char = __s;
- while (*cur_char != 0)
- {
- ++cur_char;
- }
- return cur_char - __s;
- }
-
- static const char_type*
- find(const char_type* __s, size_t __n, const char_type& __a)
- { return static_cast<const char_type*>(memchr(__s, __a, __n * sizeof(char_type))); }
-
- static char_type*
- move(char_type* __s1, const char_type* __s2, size_t __n)
- { return static_cast<char_type*>(memmove(__s1, __s2, __n * sizeof(char_type))); }
-
- static char_type*
- copy(char_type* __s1, const char_type* __s2, size_t __n)
- { return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); } /* Flawfinder: ignore */
-
- static char_type*
- assign(char_type* __s, size_t __n, char_type __a)
- {
- // This isn't right.
- //return static_cast<char_type*>(memset(__s, __a, __n * sizeof(char_type)));
-
- // I don't think there's a standard 'memset' for 16-bit values.
- // Do this the old-fashioned way.
-
- size_t __i;
- for(__i = 0; __i < __n; __i++)
- {
- __s[__i] = __a;
- }
- return __s;
- }
-
- static char_type
- to_char_type(const int_type& __c)
- { return static_cast<char_type>(__c); }
-
- static int_type
- to_int_type(const char_type& __c)
- { return static_cast<int_type>(__c); }
-
- static bool
- eq_int_type(const int_type& __c1, const int_type& __c2)
- { return __c1 == __c2; }
-
- static int_type
- eof() { return static_cast<int_type>(EOF); }
-
- static int_type
- not_eof(const int_type& __c)
+ typedef U16 char_type;
+ typedef int int_type;
+ typedef streampos pos_type;
+ typedef streamoff off_type;
+ typedef mbstate_t state_type;
+
+ static void
+ assign(char_type& __c1, const char_type& __c2)
+ { __c1 = __c2; }
+
+ static bool
+ eq(const char_type& __c1, const char_type& __c2)
+ { return __c1 == __c2; }
+
+ static bool
+ lt(const char_type& __c1, const char_type& __c2)
+ { return __c1 < __c2; }
+
+ static int
+ compare(const char_type* __s1, const char_type* __s2, size_t __n)
+ { return memcmp(__s1, __s2, __n * sizeof(char_type)); }
+
+ static size_t
+ length(const char_type* __s)
+ {
+ const char_type *cur_char = __s;
+ while (*cur_char != 0)
+ {
+ ++cur_char;
+ }
+ return cur_char - __s;
+ }
+
+ static const char_type*
+ find(const char_type* __s, size_t __n, const char_type& __a)
+ { return static_cast<const char_type*>(memchr(__s, __a, __n * sizeof(char_type))); }
+
+ static char_type*
+ move(char_type* __s1, const char_type* __s2, size_t __n)
+ { return static_cast<char_type*>(memmove(__s1, __s2, __n * sizeof(char_type))); }
+
+ static char_type*
+ copy(char_type* __s1, const char_type* __s2, size_t __n)
+ { return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); } /* Flawfinder: ignore */
+
+ static char_type*
+ assign(char_type* __s, size_t __n, char_type __a)
+ {
+ // This isn't right.
+ //return static_cast<char_type*>(memset(__s, __a, __n * sizeof(char_type)));
+
+ // I don't think there's a standard 'memset' for 16-bit values.
+ // Do this the old-fashioned way.
+
+ size_t __i;
+ for(__i = 0; __i < __n; __i++)
+ {
+ __s[__i] = __a;
+ }
+ return __s;
+ }
+
+ static char_type
+ to_char_type(const int_type& __c)
+ { return static_cast<char_type>(__c); }
+
+ static int_type
+ to_int_type(const char_type& __c)
+ { return static_cast<int_type>(__c); }
+
+ static bool
+ eq_int_type(const int_type& __c1, const int_type& __c2)
+ { return __c1 == __c2; }
+
+ static int_type
+ eof() { return static_cast<int_type>(EOF); }
+
+ static int_type
+ not_eof(const int_type& __c)
{ return (__c == eof()) ? 0 : __c; }
};
};
@@ -146,72 +148,72 @@ struct char_traits<U16>
class LL_COMMON_API LLStringOps
{
private:
- static long sPacificTimeOffset;
- static long sLocalTimeOffset;
- static bool sPacificDaylightTime;
+ static long sPacificTimeOffset;
+ static long sLocalTimeOffset;
+ static bool sPacificDaylightTime;
- static std::map<std::string, std::string> datetimeToCodes;
+ static std::map<std::string, std::string> datetimeToCodes;
public:
- static std::vector<std::string> sWeekDayList;
- static std::vector<std::string> sWeekDayShortList;
- static std::vector<std::string> sMonthList;
- static std::vector<std::string> sMonthShortList;
- static std::string sDayFormat;
-
- static std::string sAM;
- static std::string sPM;
+ static std::vector<std::string> sWeekDayList;
+ static std::vector<std::string> sWeekDayShortList;
+ static std::vector<std::string> sMonthList;
+ static std::vector<std::string> sMonthShortList;
+ static std::string sDayFormat;
- static char toUpper(char elem) { return toupper((unsigned char)elem); }
- static llwchar toUpper(llwchar elem) { return towupper(elem); }
+ static std::string sAM;
+ static std::string sPM;
- static char toLower(char elem) { return tolower((unsigned char)elem); }
- static llwchar toLower(llwchar elem) { return towlower(elem); }
+ static char toUpper(char elem) { return toupper((unsigned char)elem); }
+ static llwchar toUpper(llwchar elem) { return towupper(elem); }
+
+ static char toLower(char elem) { return tolower((unsigned char)elem); }
+ static llwchar toLower(llwchar elem) { return towlower(elem); }
- static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; }
- static bool isSpace(llwchar elem) { return iswspace(elem) != 0; }
+ static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; }
+ static bool isSpace(llwchar elem) { return iswspace(elem) != 0; }
- static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; }
- static bool isUpper(llwchar elem) { return iswupper(elem) != 0; }
+ static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; }
+ static bool isUpper(llwchar elem) { return iswupper(elem) != 0; }
- static bool isLower(char elem) { return islower((unsigned char)elem) != 0; }
- static bool isLower(llwchar elem) { return iswlower(elem) != 0; }
+ static bool isLower(char elem) { return islower((unsigned char)elem) != 0; }
+ static bool isLower(llwchar elem) { return iswlower(elem) != 0; }
- static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; }
- static bool isDigit(llwchar a) { return iswdigit(a) != 0; }
+ static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; }
+ static bool isDigit(llwchar a) { return iswdigit(a) != 0; }
- static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; }
- static bool isPunct(llwchar a) { return iswpunct(a) != 0; }
+ static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; }
+ static bool isPunct(llwchar a) { return iswpunct(a) != 0; }
- static bool isAlpha(char a) { return isalpha((unsigned char)a) != 0; }
- static bool isAlpha(llwchar a) { return iswalpha(a) != 0; }
+ static bool isAlpha(char a) { return isalpha((unsigned char)a) != 0; }
+ static bool isAlpha(llwchar a) { return iswalpha(a) != 0; }
- static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
- static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
+ static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
+ static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
- static bool isEmoji(llwchar wch);
+ static bool isEmoji(llwchar wch);
- static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
- static S32 collate(const llwchar* a, const llwchar* b);
+ static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
+ static S32 collate(const llwchar* a, const llwchar* b);
- static void setupDatetimeInfo(bool pacific_daylight_time);
+ static void setupDatetimeInfo(bool pacific_daylight_time);
- static void setupWeekDaysNames(const std::string& data);
- static void setupWeekDaysShortNames(const std::string& data);
- static void setupMonthNames(const std::string& data);
- static void setupMonthShortNames(const std::string& data);
- static void setupDayFormat(const std::string& data);
+ static void setupWeekDaysNames(const std::string& data);
+ static void setupWeekDaysShortNames(const std::string& data);
+ static void setupMonthNames(const std::string& data);
+ static void setupMonthShortNames(const std::string& data);
+ static void setupDayFormat(const std::string& data);
- static long getPacificTimeOffset(void) { return sPacificTimeOffset;}
- static long getLocalTimeOffset(void) { return sLocalTimeOffset;}
- // Is the Pacific time zone (aka server time zone)
- // currently in daylight savings time?
- static bool getPacificDaylightTime(void) { return sPacificDaylightTime;}
+ static long getPacificTimeOffset(void) { return sPacificTimeOffset;}
+ static long getLocalTimeOffset(void) { return sLocalTimeOffset;}
+ // Is the Pacific time zone (aka server time zone)
+ // currently in daylight savings time?
+ static bool getPacificDaylightTime(void) { return sPacificDaylightTime;}
- static std::string getDatetimeCode (std::string key);
+ static std::string getDatetimeCode (std::string key);
- // Express a value like 1234567 as "1.23M"
+ // Express a value like 1234567 as "1.23M"
static std::string getReadableNumber(F64 num);
};
@@ -228,216 +230,216 @@ LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen);
class LLFormatMapString
{
public:
- LLFormatMapString() {};
- LLFormatMapString(const char* s) : mString(ll_safe_string(s)) {};
- LLFormatMapString(const std::string& s) : mString(s) {};
- operator std::string() const { return mString; }
- bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; }
- std::size_t length() const { return mString.length(); }
-
+ LLFormatMapString() {};
+ LLFormatMapString(const char* s) : mString(ll_safe_string(s)) {};
+ LLFormatMapString(const std::string& s) : mString(s) {};
+ operator std::string() const { return mString; }
+ bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; }
+ std::size_t length() const { return mString.length(); }
+
private:
- std::string mString;
+ std::string mString;
};
template <class T>
class LLStringUtilBase
{
private:
- static std::string sLocale;
+ static std::string sLocale;
public:
- typedef std::basic_string<T> string_type;
- typedef typename string_type::size_type size_type;
-
+ typedef std::basic_string<T> string_type;
+ typedef typename string_type::size_type size_type;
+
public:
- /////////////////////////////////////////////////////////////////////////////////////////
- // Static Utility functions that operate on std::strings
-
- static const string_type null;
-
- typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
- /// considers any sequence of delims as a single field separator
- LL_COMMON_API static void getTokens(const string_type& instr,
- std::vector<string_type >& tokens,
- const string_type& delims);
- /// like simple scan overload, but returns scanned vector
- static std::vector<string_type> getTokens(const string_type& instr,
- const string_type& delims);
- /// add support for keep_delims and quotes (either could be empty string)
- static void getTokens(const string_type& instr,
- std::vector<string_type>& tokens,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes=string_type());
- /// like keep_delims-and-quotes overload, but returns scanned vector
- static std::vector<string_type> getTokens(const string_type& instr,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes=string_type());
- /// add support for escapes (could be empty string)
- static void getTokens(const string_type& instr,
- std::vector<string_type>& tokens,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes,
- const string_type& escapes);
- /// like escapes overload, but returns scanned vector
- static std::vector<string_type> getTokens(const string_type& instr,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes,
- const string_type& escapes);
-
- LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals);
- LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch);
- LL_COMMON_API static S32 format(string_type& s, const format_map_t& substitutions);
- LL_COMMON_API static S32 format(string_type& s, const LLSD& substitutions);
- LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const format_map_t& substitutions);
- LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const LLSD& substitutions);
- LL_COMMON_API static void setLocale (std::string inLocale);
- LL_COMMON_API static std::string getLocale (void);
-
- static bool isValidIndex(const string_type& string, size_type i)
- {
- return !string.empty() && (0 <= i) && (i <= string.size());
- }
-
- static bool contains(const string_type& string, T c, size_type i=0)
- {
- return string.find(c, i) != string_type::npos;
- }
-
- static void trimHead(string_type& string);
- static void trimTail(string_type& string);
- static void trim(string_type& string) { trimHead(string); trimTail(string); }
- static void truncate(string_type& string, size_type count);
-
- static void toUpper(string_type& string);
- static void toLower(string_type& string);
-
- // True if this is the head of s.
- static BOOL isHead( const string_type& string, const T* s );
-
- /**
- * @brief Returns true if string starts with substr
- *
- * If etither string or substr are empty, this method returns false.
- */
- static bool startsWith(
- const string_type& string,
- const string_type& substr);
-
- /**
- * @brief Returns true if string ends in substr
- *
- * If etither string or substr are empty, this method returns false.
- */
- static bool endsWith(
- const string_type& string,
- const string_type& substr);
-
- /**
- * get environment string value with proper Unicode handling
- * (key is always UTF-8)
- * detect absence by return value == dflt
- */
- static string_type getenv(const std::string& key, const string_type& dflt="");
- /**
- * get optional environment string value with proper Unicode handling
- * (key is always UTF-8)
- * detect absence by (! return value)
- */
- static boost::optional<string_type> getoptenv(const std::string& key);
-
- static void addCRLF(string_type& string);
- static void removeCRLF(string_type& string);
- static void removeWindowsCR(string_type& string);
-
- static void replaceTabsWithSpaces( string_type& string, size_type spaces_per_tab );
- static void replaceNonstandardASCII( string_type& string, T replacement );
- static void replaceChar( string_type& string, T target, T replacement );
- static void replaceString( string_type& string, string_type target, string_type replacement );
- static string_type capitalize(const string_type& str);
- static void capitalize(string_type& str);
-
- static BOOL containsNonprintable(const string_type& string);
- static void stripNonprintable(string_type& string);
-
- /**
- * Double-quote an argument string if needed, unless it's already
- * double-quoted. Decide whether it's needed based on the presence of any
- * character in @a triggers (default space or double-quote). If we quote
- * it, escape any embedded double-quote with the @a escape string (default
- * backslash).
- *
- * Passing triggers="" means always quote, unless it's already double-quoted.
- */
- static string_type quote(const string_type& str,
- const string_type& triggers=" \"",
- const string_type& escape="\\");
-
- /**
- * @brief Unsafe way to make ascii characters. You should probably
- * only call this when interacting with the host operating system.
- * The 1 byte std::string does not work correctly.
- * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII
- * should work.
- */
- static void _makeASCII(string_type& string);
-
- // Conversion to other data types
- static BOOL convertToBOOL(const string_type& string, BOOL& value);
- static BOOL convertToU8(const string_type& string, U8& value);
- static BOOL convertToS8(const string_type& string, S8& value);
- static BOOL convertToS16(const string_type& string, S16& value);
- static BOOL convertToU16(const string_type& string, U16& value);
- static BOOL convertToU32(const string_type& string, U32& value);
- static BOOL convertToS32(const string_type& string, S32& value);
- static BOOL convertToF32(const string_type& string, F32& value);
- static BOOL convertToF64(const string_type& string, F64& value);
-
- /////////////////////////////////////////////////////////////////////////////////////////
- // Utility functions for working with char*'s and strings
-
- // Like strcmp but also handles empty strings. Uses
- // current locale.
- static S32 compareStrings(const T* lhs, const T* rhs);
- static S32 compareStrings(const string_type& lhs, const string_type& rhs);
-
- // case insensitive version of above. Uses current locale on
- // Win32, and falls back to a non-locale aware comparison on
- // Linux.
- static S32 compareInsensitive(const T* lhs, const T* rhs);
- static S32 compareInsensitive(const string_type& lhs, const string_type& rhs);
-
- // Case sensitive comparison with good handling of numbers. Does not use current locale.
- // a.k.a. strdictcmp()
- static S32 compareDict(const string_type& a, const string_type& b);
-
- // Case *in*sensitive comparison with good handling of numbers. Does not use current locale.
- // a.k.a. strdictcmp()
- static S32 compareDictInsensitive(const string_type& a, const string_type& b);
-
- // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
- static BOOL precedesDict( const string_type& a, const string_type& b );
-
- // A replacement for strncpy.
- // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds
- // up to dst_size-1 characters of src.
- static void copy(T* dst, const T* src, size_type dst_size);
-
- // Copies src into dst at a given offset.
- static void copyInto(string_type& dst, const string_type& src, size_type offset);
-
- static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); }
-
-
-#ifdef _DEBUG
- LL_COMMON_API static void testHarness();
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Static Utility functions that operate on std::strings
+
+ static const string_type null;
+
+ typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
+ /// considers any sequence of delims as a single field separator
+ LL_COMMON_API static void getTokens(const string_type& instr,
+ std::vector<string_type >& tokens,
+ const string_type& delims);
+ /// like simple scan overload, but returns scanned vector
+ static std::vector<string_type> getTokens(const string_type& instr,
+ const string_type& delims);
+ /// add support for keep_delims and quotes (either could be empty string)
+ static void getTokens(const string_type& instr,
+ std::vector<string_type>& tokens,
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes=string_type());
+ /// like keep_delims-and-quotes overload, but returns scanned vector
+ static std::vector<string_type> getTokens(const string_type& instr,
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes=string_type());
+ /// add support for escapes (could be empty string)
+ static void getTokens(const string_type& instr,
+ std::vector<string_type>& tokens,
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes,
+ const string_type& escapes);
+ /// like escapes overload, but returns scanned vector
+ static std::vector<string_type> getTokens(const string_type& instr,
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes,
+ const string_type& escapes);
+
+ LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals);
+ LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch);
+ LL_COMMON_API static S32 format(string_type& s, const format_map_t& substitutions);
+ LL_COMMON_API static S32 format(string_type& s, const LLSD& substitutions);
+ LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const format_map_t& substitutions);
+ LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const LLSD& substitutions);
+ LL_COMMON_API static void setLocale (std::string inLocale);
+ LL_COMMON_API static std::string getLocale (void);
+
+ static bool isValidIndex(const string_type& string, size_type i)
+ {
+ return !string.empty() && (0 <= i) && (i <= string.size());
+ }
+
+ static bool contains(const string_type& string, T c, size_type i=0)
+ {
+ return string.find(c, i) != string_type::npos;
+ }
+
+ static void trimHead(string_type& string);
+ static void trimTail(string_type& string);
+ static void trim(string_type& string) { trimHead(string); trimTail(string); }
+ static void truncate(string_type& string, size_type count);
+
+ static void toUpper(string_type& string);
+ static void toLower(string_type& string);
+
+ // True if this is the head of s.
+ static BOOL isHead( const string_type& string, const T* s );
+
+ /**
+ * @brief Returns true if string starts with substr
+ *
+ * If etither string or substr are empty, this method returns false.
+ */
+ static bool startsWith(
+ const string_type& string,
+ const string_type& substr);
+
+ /**
+ * @brief Returns true if string ends in substr
+ *
+ * If etither string or substr are empty, this method returns false.
+ */
+ static bool endsWith(
+ const string_type& string,
+ const string_type& substr);
+
+ /**
+ * get environment string value with proper Unicode handling
+ * (key is always UTF-8)
+ * detect absence by return value == dflt
+ */
+ static string_type getenv(const std::string& key, const string_type& dflt="");
+ /**
+ * get optional environment string value with proper Unicode handling
+ * (key is always UTF-8)
+ * detect absence by (! return value)
+ */
+ static boost::optional<string_type> getoptenv(const std::string& key);
+
+ static void addCRLF(string_type& string);
+ static void removeCRLF(string_type& string);
+ static void removeWindowsCR(string_type& string);
+
+ static void replaceTabsWithSpaces( string_type& string, size_type spaces_per_tab );
+ static void replaceNonstandardASCII( string_type& string, T replacement );
+ static void replaceChar( string_type& string, T target, T replacement );
+ static void replaceString( string_type& string, string_type target, string_type replacement );
+ static string_type capitalize(const string_type& str);
+ static void capitalize(string_type& str);
+
+ static BOOL containsNonprintable(const string_type& string);
+ static void stripNonprintable(string_type& string);
+
+ /**
+ * Double-quote an argument string if needed, unless it's already
+ * double-quoted. Decide whether it's needed based on the presence of any
+ * character in @a triggers (default space or double-quote). If we quote
+ * it, escape any embedded double-quote with the @a escape string (default
+ * backslash).
+ *
+ * Passing triggers="" means always quote, unless it's already double-quoted.
+ */
+ static string_type quote(const string_type& str,
+ const string_type& triggers=" \"",
+ const string_type& escape="\\");
+
+ /**
+ * @brief Unsafe way to make ascii characters. You should probably
+ * only call this when interacting with the host operating system.
+ * The 1 byte std::string does not work correctly.
+ * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII
+ * should work.
+ */
+ static void _makeASCII(string_type& string);
+
+ // Conversion to other data types
+ static BOOL convertToBOOL(const string_type& string, BOOL& value);
+ static BOOL convertToU8(const string_type& string, U8& value);
+ static BOOL convertToS8(const string_type& string, S8& value);
+ static BOOL convertToS16(const string_type& string, S16& value);
+ static BOOL convertToU16(const string_type& string, U16& value);
+ static BOOL convertToU32(const string_type& string, U32& value);
+ static BOOL convertToS32(const string_type& string, S32& value);
+ static BOOL convertToF32(const string_type& string, F32& value);
+ static BOOL convertToF64(const string_type& string, F64& value);
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Utility functions for working with char*'s and strings
+
+ // Like strcmp but also handles empty strings. Uses
+ // current locale.
+ static S32 compareStrings(const T* lhs, const T* rhs);
+ static S32 compareStrings(const string_type& lhs, const string_type& rhs);
+
+ // case insensitive version of above. Uses current locale on
+ // Win32, and falls back to a non-locale aware comparison on
+ // Linux.
+ static S32 compareInsensitive(const T* lhs, const T* rhs);
+ static S32 compareInsensitive(const string_type& lhs, const string_type& rhs);
+
+ // Case sensitive comparison with good handling of numbers. Does not use current locale.
+ // a.k.a. strdictcmp()
+ static S32 compareDict(const string_type& a, const string_type& b);
+
+ // Case *in*sensitive comparison with good handling of numbers. Does not use current locale.
+ // a.k.a. strdictcmp()
+ static S32 compareDictInsensitive(const string_type& a, const string_type& b);
+
+ // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
+ static BOOL precedesDict( const string_type& a, const string_type& b );
+
+ // A replacement for strncpy.
+ // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds
+ // up to dst_size-1 characters of src.
+ static void copy(T* dst, const T* src, size_type dst_size);
+
+ // Copies src into dst at a given offset.
+ static void copyInto(string_type& dst, const string_type& src, size_type offset);
+
+ static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); }
+
+
+#ifdef _DEBUG
+ LL_COMMON_API static void testHarness();
#endif
private:
- LL_COMMON_API static size_type getSubstitution(const string_type& instr, size_type& start, std::vector<string_type >& tokens);
+ LL_COMMON_API static size_type getSubstitution(const string_type& instr, size_type& start, std::vector<string_type >& tokens);
};
template<class T> const std::basic_string<T> LLStringUtilBase<T>::null;
@@ -453,18 +455,18 @@ typedef std::basic_string<llwchar> LLWString;
class LLStringExplicit : public std::string
{
public:
- explicit LLStringExplicit(const char* s) : std::string(s) {}
- LLStringExplicit(const std::string& s) : std::string(s) {}
- LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : std::string(s, pos, n) {}
+ explicit LLStringExplicit(const char* s) : std::string(s) {}
+ LLStringExplicit(const std::string& s) : std::string(s) {}
+ LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : std::string(s, pos, n) {}
};
struct LLDictionaryLess
{
public:
- bool operator()(const std::string& a, const std::string& b) const
- {
- return (LLStringUtil::precedesDict(a, b) ? true : false);
- }
+ bool operator()(const std::string& a, const std::string& b) const
+ {
+ return (LLStringUtil::precedesDict(a, b) ? true : false);
+ }
};
@@ -481,10 +483,10 @@ public:
* @return a copy of in string minus the trailing count bytes.
*/
inline std::string chop_tail_copy(
- const std::string& in,
- std::string::size_type count)
+ const std::string& in,
+ std::string::size_type count)
{
- return std::string(in, 0, in.length() - count);
+ return std::string(in, 0, in.length() - count);
}
/**
@@ -519,11 +521,38 @@ struct ll_convert_impl
TO operator()(const FROM& in) const;
};
-// Use a function template to get the nice ll_convert<TO>(from_value) API.
+/**
+ * somefunction(ll_convert(data))
+ * target = ll_convert(data)
+ * totype otherfunc(const fromtype& data)
+ * {
+ * // ...
+ * return ll_convert(data);
+ * }
+ * all infer both the FROM type and the TO type.
+ */
+template <typename FROM>
+class ll_convert
+{
+private:
+ const FROM& mRef;
+
+public:
+ ll_convert(const FROM& ref): mRef(ref) {}
+
+ template <typename TO>
+ inline operator TO() const
+ {
+ return ll_convert_impl<TO, std::decay_t<const FROM>>()(mRef);
+ }
+};
+
+// When the TO type must be explicit, use a function template to get
+// ll_convert_to<TO>(from_value) API.
template<typename TO, typename FROM>
-TO ll_convert(const FROM& in)
+TO ll_convert_to(const FROM& in)
{
- return ll_convert_impl<TO, FROM>()(in);
+ return ll_convert_impl<TO, std::decay_t<const FROM>>()(in);
}
// degenerate case
@@ -577,8 +606,8 @@ inline size_t ll_convert_length<char> (const char* zstr) { return std::strl
// and longname(const string&, len) so calls written pre-ll_convert() will
// work. Most of these overloads will be unified once we turn on C++17 and can
// use std::string_view.
-// It also uses aliasmacro to ensure that both ll_convert<OUTSTR>(const char*)
-// and ll_convert<OUTSTR>(const string&) will work.
+// It also uses aliasmacro to ensure that both ll_convert(const char*)
+// and ll_convert(const string&) will work.
#define ll_convert_forms(aliasmacro, OUTSTR, INSTR, longname) \
LL_COMMON_API OUTSTR longname(const INSTR::value_type* in, size_t len); \
inline auto longname(const INSTR& in, size_t len) \
@@ -677,10 +706,10 @@ ll_convert_forms(ll_convert_u16_alias, std::string, llutf16string, utf16str_to_u
inline std::string wstring_to_utf8str(const llutf16string &utf16str) { return utf16str_to_utf8str(utf16str);}
// Length of this UTF32 string in bytes when transformed to UTF8
-LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr);
+LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr);
// Length in bytes of this wide char in a UTF8 string
-LL_COMMON_API S32 wchar_utf8_length(const llwchar wc);
+LL_COMMON_API S32 wchar_utf8_length(const llwchar wc);
LL_COMMON_API std::string wchar_utf8_preview(const llwchar wc);
@@ -697,7 +726,7 @@ LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wst
/**
* @brief Properly truncate a utf8 string to a maximum byte count.
- *
+ *
* The returned string may be less than max_len if the truncation
* happens in the middle of a glyph. If max_len is longer than the
* string passed in, the return value == utf8str.
@@ -710,8 +739,8 @@ LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32
LL_COMMON_API std::string utf8str_trim(const std::string& utf8str);
LL_COMMON_API S32 utf8str_compare_insensitive(
- const std::string& lhs,
- const std::string& rhs);
+ const std::string& lhs,
+ const std::string& rhs);
/**
* @brief Properly truncate a utf8 string to a maximum character count.
@@ -732,14 +761,14 @@ LL_COMMON_API std::string utf8str_symbol_truncate(const std::string& utf8str, co
* @param replace_char The wchar which is written on replace
*/
LL_COMMON_API std::string utf8str_substChar(
- const std::string& utf8str,
- const llwchar target_char,
- const llwchar replace_char);
+ const std::string& utf8str,
+ const llwchar target_char,
+ const llwchar replace_char);
LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str);
// Hack - used for evil notecards.
-LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str);
+LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str);
LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
@@ -815,7 +844,7 @@ LL_COMMON_API std::string ll_convert_string_to_utf8_string(const std::string& in
template<typename STRING>
STRING windows_message(unsigned long error)
{
- return ll_convert<STRING>(windows_message<std::wstring>(error));
+ return ll_convert(windows_message<std::wstring>(error));
}
/// There's only one real implementation
@@ -845,52 +874,52 @@ LL_COMMON_API boost::optional<std::string> llstring_getoptenv(const std::string
*/
namespace LLStringFn
{
- /**
- * @brief Replace all non-printable characters with replacement in
- * string.
- * NOTE - this will zap non-ascii
- *
- * @param [in,out] string the to modify. out value is the string
- * with zero non-printable characters.
- * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
- */
- LL_COMMON_API void replace_nonprintable_in_ascii(
- std::basic_string<char>& string,
- char replacement);
-
-
- /**
- * @brief Replace all non-printable characters and pipe characters
- * with replacement in a string.
- * NOTE - this will zap non-ascii
- *
- * @param [in,out] the string to modify. out value is the string
- * with zero non-printable characters and zero pipe characters.
- * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
- */
- LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
- char replacement);
-
-
- /**
- * @brief Remove all characters that are not allowed in XML 1.0.
- * Returns a copy of the string with those characters removed.
- * Works with US ASCII and UTF-8 encoded strings. JC
- */
- LL_COMMON_API std::string strip_invalid_xml(const std::string& input);
-
-
- /**
- * @brief Replace all control characters (0 <= c < 0x20) with replacement in
- * string. This is safe for utf-8
- *
- * @param [in,out] string the to modify. out value is the string
- * with zero non-printable characters.
- * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
- */
- LL_COMMON_API void replace_ascii_controlchars(
- std::basic_string<char>& string,
- char replacement);
+ /**
+ * @brief Replace all non-printable characters with replacement in
+ * string.
+ * NOTE - this will zap non-ascii
+ *
+ * @param [in,out] string the to modify. out value is the string
+ * with zero non-printable characters.
+ * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
+ */
+ LL_COMMON_API void replace_nonprintable_in_ascii(
+ std::basic_string<char>& string,
+ char replacement);
+
+
+ /**
+ * @brief Replace all non-printable characters and pipe characters
+ * with replacement in a string.
+ * NOTE - this will zap non-ascii
+ *
+ * @param [in,out] the string to modify. out value is the string
+ * with zero non-printable characters and zero pipe characters.
+ * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
+ */
+ LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
+ char replacement);
+
+
+ /**
+ * @brief Remove all characters that are not allowed in XML 1.0.
+ * Returns a copy of the string with those characters removed.
+ * Works with US ASCII and UTF-8 encoded strings. JC
+ */
+ LL_COMMON_API std::string strip_invalid_xml(const std::string& input);
+
+
+ /**
+ * @brief Replace all control characters (0 <= c < 0x20) with replacement in
+ * string. This is safe for utf-8
+ *
+ * @param [in,out] string the to modify. out value is the string
+ * with zero non-printable characters.
+ * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
+ */
+ LL_COMMON_API void replace_ascii_controlchars(
+ std::basic_string<char>& string,
+ char replacement);
}
////////////////////////////////////////////////////////////
@@ -905,36 +934,36 @@ template <class T>
std::vector<typename LLStringUtilBase<T>::string_type>
LLStringUtilBase<T>::getTokens(const string_type& instr, const string_type& delims)
{
- std::vector<string_type> tokens;
- getTokens(instr, tokens, delims);
- return tokens;
+ std::vector<string_type> tokens;
+ getTokens(instr, tokens, delims);
+ return tokens;
}
// static
template <class T>
std::vector<typename LLStringUtilBase<T>::string_type>
LLStringUtilBase<T>::getTokens(const string_type& instr,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes)
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes)
{
- std::vector<string_type> tokens;
- getTokens(instr, tokens, drop_delims, keep_delims, quotes);
- return tokens;
+ std::vector<string_type> tokens;
+ getTokens(instr, tokens, drop_delims, keep_delims, quotes);
+ return tokens;
}
// static
template <class T>
std::vector<typename LLStringUtilBase<T>::string_type>
LLStringUtilBase<T>::getTokens(const string_type& instr,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes,
- const string_type& escapes)
-{
- std::vector<string_type> tokens;
- getTokens(instr, tokens, drop_delims, keep_delims, quotes, escapes);
- return tokens;
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes,
+ const string_type& escapes)
+{
+ std::vector<string_type> tokens;
+ getTokens(instr, tokens, drop_delims, keep_delims, quotes, escapes);
+ return tokens;
}
namespace LLStringUtilBaseImpl
@@ -950,62 +979,62 @@ namespace LLStringUtilBaseImpl
template <class T>
struct InString
{
- typedef std::basic_string<T> string_type;
- typedef typename string_type::const_iterator const_iterator;
-
- InString(const_iterator b, const_iterator e):
- mIter(b),
- mEnd(e)
- {}
- virtual ~InString() {}
-
- bool done() const { return mIter == mEnd; }
- /// Is the current character (*mIter) escaped? This implementation can
- /// answer trivially because it doesn't support escapes.
- virtual bool escaped() const { return false; }
- /// Obtain the current character and advance @c mIter.
- virtual T next() { return *mIter++; }
- /// Does the current character match specified character?
- virtual bool is(T ch) const { return (! done()) && *mIter == ch; }
- /// Is the current character any one of the specified characters?
- virtual bool oneof(const string_type& delims) const
- {
- return (! done()) && LLStringUtilBase<T>::contains(delims, *mIter);
- }
-
- /**
- * Scan forward from @from until either @a delim or end. This is primarily
- * useful for processing quoted substrings.
- *
- * If we do see @a delim, append everything from @from until (excluding)
- * @a delim to @a into, advance @c mIter to skip @a delim, and return @c
- * true.
- *
- * If we do not see @a delim, do not alter @a into or @c mIter and return
- * @c false. Do not pass GO, do not collect $200.
- *
- * @note The @c false case described above implements normal getTokens()
- * treatment of an unmatched open quote: treat the quote character as if
- * escaped, that is, simply collect it as part of the current token. Other
- * plausible behaviors directly affect the way getTokens() deals with an
- * unmatched quote: e.g. throwing an exception to treat it as an error, or
- * assuming a close quote beyond end of string (in which case return @c
- * true).
- */
- virtual bool collect_until(string_type& into, const_iterator from, T delim)
- {
- const_iterator found = std::find(from, mEnd, delim);
- // If we didn't find delim, change nothing, just tell caller.
- if (found == mEnd)
- return false;
- // Found delim! Append everything between from and found.
- into.append(from, found);
- // advance past delim in input
- mIter = found + 1;
- return true;
- }
-
- const_iterator mIter, mEnd;
+ typedef std::basic_string<T> string_type;
+ typedef typename string_type::const_iterator const_iterator;
+
+ InString(const_iterator b, const_iterator e):
+ mIter(b),
+ mEnd(e)
+ {}
+ virtual ~InString() {}
+
+ bool done() const { return mIter == mEnd; }
+ /// Is the current character (*mIter) escaped? This implementation can
+ /// answer trivially because it doesn't support escapes.
+ virtual bool escaped() const { return false; }
+ /// Obtain the current character and advance @c mIter.
+ virtual T next() { return *mIter++; }
+ /// Does the current character match specified character?
+ virtual bool is(T ch) const { return (! done()) && *mIter == ch; }
+ /// Is the current character any one of the specified characters?
+ virtual bool oneof(const string_type& delims) const
+ {
+ return (! done()) && LLStringUtilBase<T>::contains(delims, *mIter);
+ }
+
+ /**
+ * Scan forward from @from until either @a delim or end. This is primarily
+ * useful for processing quoted substrings.
+ *
+ * If we do see @a delim, append everything from @from until (excluding)
+ * @a delim to @a into, advance @c mIter to skip @a delim, and return @c
+ * true.
+ *
+ * If we do not see @a delim, do not alter @a into or @c mIter and return
+ * @c false. Do not pass GO, do not collect $200.
+ *
+ * @note The @c false case described above implements normal getTokens()
+ * treatment of an unmatched open quote: treat the quote character as if
+ * escaped, that is, simply collect it as part of the current token. Other
+ * plausible behaviors directly affect the way getTokens() deals with an
+ * unmatched quote: e.g. throwing an exception to treat it as an error, or
+ * assuming a close quote beyond end of string (in which case return @c
+ * true).
+ */
+ virtual bool collect_until(string_type& into, const_iterator from, T delim)
+ {
+ const_iterator found = std::find(from, mEnd, delim);
+ // If we didn't find delim, change nothing, just tell caller.
+ if (found == mEnd)
+ return false;
+ // Found delim! Append everything between from and found.
+ into.append(from, found);
+ // advance past delim in input
+ mIter = found + 1;
+ return true;
+ }
+
+ const_iterator mIter, mEnd;
};
/// InString subclass that handles escape characters
@@ -1013,177 +1042,177 @@ template <class T>
class InEscString: public InString<T>
{
public:
- typedef InString<T> super;
- typedef typename super::string_type string_type;
- typedef typename super::const_iterator const_iterator;
- using super::done;
- using super::mIter;
- using super::mEnd;
-
- InEscString(const_iterator b, const_iterator e, const string_type& escapes):
- super(b, e),
- mEscapes(escapes)
- {
- // Even though we've already initialized 'mIter' via our base-class
- // constructor, set it again to check for initial escape char.
- setiter(b);
- }
-
- /// This implementation uses the answer cached by setiter().
- virtual bool escaped() const { return mIsEsc; }
- virtual T next()
- {
- // If we're looking at the escape character of an escape sequence,
- // skip that character. This is the one time we can modify 'mIter'
- // without using setiter: for this one case we DO NOT CARE if the
- // escaped character is itself an escape.
- if (mIsEsc)
- ++mIter;
- // If we were looking at an escape character, this is the escaped
- // character; otherwise it's just the next character.
- T result(*mIter);
- // Advance mIter, checking for escape sequence.
- setiter(mIter + 1);
- return result;
- }
-
- virtual bool is(T ch) const
- {
- // Like base-class is(), except that an escaped character matches
- // nothing.
- return (! done()) && (! mIsEsc) && *mIter == ch;
- }
-
- virtual bool oneof(const string_type& delims) const
- {
- // Like base-class oneof(), except that an escaped character matches
- // nothing.
- return (! done()) && (! mIsEsc) && LLStringUtilBase<T>::contains(delims, *mIter);
- }
-
- virtual bool collect_until(string_type& into, const_iterator from, T delim)
- {
- // Deal with escapes in the characters we collect; that is, an escaped
- // character must become just that character without the preceding
- // escape. Collect characters in a separate string rather than
- // directly appending to 'into' in case we do not find delim, in which
- // case we're supposed to leave 'into' unmodified.
- string_type collected;
- // For scanning purposes, we're going to work directly with 'mIter'.
- // Save its current value in case we fail to see delim.
- const_iterator save_iter(mIter);
- // Okay, set 'mIter', checking for escape.
- setiter(from);
- while (! done())
- {
- // If we see an unescaped delim, stop and report success.
- if ((! mIsEsc) && *mIter == delim)
- {
- // Append collected chars to 'into'.
- into.append(collected);
- // Don't forget to advance 'mIter' past delim.
- setiter(mIter + 1);
- return true;
- }
- // We're not at end, and either we're not looking at delim or it's
- // escaped. Collect this character and keep going.
- collected.push_back(next());
- }
- // Here we hit 'mEnd' without ever seeing delim. Restore mIter and tell
- // caller.
- setiter(save_iter);
- return false;
- }
+ typedef InString<T> super;
+ typedef typename super::string_type string_type;
+ typedef typename super::const_iterator const_iterator;
+ using super::done;
+ using super::mIter;
+ using super::mEnd;
+
+ InEscString(const_iterator b, const_iterator e, const string_type& escapes):
+ super(b, e),
+ mEscapes(escapes)
+ {
+ // Even though we've already initialized 'mIter' via our base-class
+ // constructor, set it again to check for initial escape char.
+ setiter(b);
+ }
+
+ /// This implementation uses the answer cached by setiter().
+ virtual bool escaped() const { return mIsEsc; }
+ virtual T next()
+ {
+ // If we're looking at the escape character of an escape sequence,
+ // skip that character. This is the one time we can modify 'mIter'
+ // without using setiter: for this one case we DO NOT CARE if the
+ // escaped character is itself an escape.
+ if (mIsEsc)
+ ++mIter;
+ // If we were looking at an escape character, this is the escaped
+ // character; otherwise it's just the next character.
+ T result(*mIter);
+ // Advance mIter, checking for escape sequence.
+ setiter(mIter + 1);
+ return result;
+ }
+
+ virtual bool is(T ch) const
+ {
+ // Like base-class is(), except that an escaped character matches
+ // nothing.
+ return (! done()) && (! mIsEsc) && *mIter == ch;
+ }
+
+ virtual bool oneof(const string_type& delims) const
+ {
+ // Like base-class oneof(), except that an escaped character matches
+ // nothing.
+ return (! done()) && (! mIsEsc) && LLStringUtilBase<T>::contains(delims, *mIter);
+ }
+
+ virtual bool collect_until(string_type& into, const_iterator from, T delim)
+ {
+ // Deal with escapes in the characters we collect; that is, an escaped
+ // character must become just that character without the preceding
+ // escape. Collect characters in a separate string rather than
+ // directly appending to 'into' in case we do not find delim, in which
+ // case we're supposed to leave 'into' unmodified.
+ string_type collected;
+ // For scanning purposes, we're going to work directly with 'mIter'.
+ // Save its current value in case we fail to see delim.
+ const_iterator save_iter(mIter);
+ // Okay, set 'mIter', checking for escape.
+ setiter(from);
+ while (! done())
+ {
+ // If we see an unescaped delim, stop and report success.
+ if ((! mIsEsc) && *mIter == delim)
+ {
+ // Append collected chars to 'into'.
+ into.append(collected);
+ // Don't forget to advance 'mIter' past delim.
+ setiter(mIter + 1);
+ return true;
+ }
+ // We're not at end, and either we're not looking at delim or it's
+ // escaped. Collect this character and keep going.
+ collected.push_back(next());
+ }
+ // Here we hit 'mEnd' without ever seeing delim. Restore mIter and tell
+ // caller.
+ setiter(save_iter);
+ return false;
+ }
private:
- void setiter(const_iterator i)
- {
- mIter = i;
-
- // Every time we change 'mIter', set 'mIsEsc' to be able to repetitively
- // answer escaped() without having to rescan 'mEscapes'. mIsEsc caches
- // contains(mEscapes, *mIter).
-
- // We're looking at an escaped char if we're not already at end (that
- // is, *mIter is even meaningful); if *mIter is in fact one of the
- // specified escape characters; and if there's one more character
- // following it. That is, if an escape character is the very last
- // character of the input string, it loses its special meaning.
- mIsEsc = (! done()) &&
- LLStringUtilBase<T>::contains(mEscapes, *mIter) &&
- (mIter+1) != mEnd;
- }
-
- const string_type mEscapes;
- bool mIsEsc;
+ void setiter(const_iterator i)
+ {
+ mIter = i;
+
+ // Every time we change 'mIter', set 'mIsEsc' to be able to repetitively
+ // answer escaped() without having to rescan 'mEscapes'. mIsEsc caches
+ // contains(mEscapes, *mIter).
+
+ // We're looking at an escaped char if we're not already at end (that
+ // is, *mIter is even meaningful); if *mIter is in fact one of the
+ // specified escape characters; and if there's one more character
+ // following it. That is, if an escape character is the very last
+ // character of the input string, it loses its special meaning.
+ mIsEsc = (! done()) &&
+ LLStringUtilBase<T>::contains(mEscapes, *mIter) &&
+ (mIter+1) != mEnd;
+ }
+
+ const string_type mEscapes;
+ bool mIsEsc;
};
/// getTokens() implementation based on InString concept
template <typename INSTRING, typename string_type>
void getTokens(INSTRING& instr, std::vector<string_type>& tokens,
- const string_type& drop_delims, const string_type& keep_delims,
- const string_type& quotes)
-{
- // There are times when we want to match either drop_delims or
- // keep_delims. Concatenate them up front to speed things up.
- string_type all_delims(drop_delims + keep_delims);
- // no tokens yet
- tokens.clear();
-
- // try for another token
- while (! instr.done())
- {
- // scan past any drop_delims
- while (instr.oneof(drop_delims))
- {
- // skip this drop_delim
- instr.next();
- // but if that was the end of the string, done
- if (instr.done())
- return;
- }
- // found the start of another token: make a slot for it
- tokens.push_back(string_type());
- if (instr.oneof(keep_delims))
- {
- // *iter is a keep_delim, a token of exactly 1 character. Append
- // that character to the new token and proceed.
- tokens.back().push_back(instr.next());
- continue;
- }
- // Here we have a non-delimiter token, which might consist of a mix of
- // quoted and unquoted parts. Use bash rules for quoting: you can
- // embed a quoted substring in the midst of an unquoted token (e.g.
- // ~/"sub dir"/myfile.txt); you can ram two quoted substrings together
- // to make a single token (e.g. 'He said, "'"Don't."'"'). We diverge
- // from bash in that bash considers an unmatched quote an error. Our
- // param signature doesn't allow for errors, so just pretend it's not
- // a quote and embed it.
- // At this level, keep scanning until we hit the next delimiter of
- // either type (drop_delims or keep_delims).
- while (! instr.oneof(all_delims))
- {
- // If we're looking at an open quote, search forward for
- // a close quote, collecting characters along the way.
- if (instr.oneof(quotes) &&
- instr.collect_until(tokens.back(), instr.mIter+1, *instr.mIter))
- {
- // collect_until is cleverly designed to do exactly what we
- // need here. No further action needed if it returns true.
- }
- else
- {
- // Either *iter isn't a quote, or there's no matching close
- // quote: in other words, just an ordinary char. Append it to
- // current token.
- tokens.back().push_back(instr.next());
- }
- // having scanned that segment of this token, if we've reached the
- // end of the string, we're done
- if (instr.done())
- return;
- }
- }
+ const string_type& drop_delims, const string_type& keep_delims,
+ const string_type& quotes)
+{
+ // There are times when we want to match either drop_delims or
+ // keep_delims. Concatenate them up front to speed things up.
+ string_type all_delims(drop_delims + keep_delims);
+ // no tokens yet
+ tokens.clear();
+
+ // try for another token
+ while (! instr.done())
+ {
+ // scan past any drop_delims
+ while (instr.oneof(drop_delims))
+ {
+ // skip this drop_delim
+ instr.next();
+ // but if that was the end of the string, done
+ if (instr.done())
+ return;
+ }
+ // found the start of another token: make a slot for it
+ tokens.push_back(string_type());
+ if (instr.oneof(keep_delims))
+ {
+ // *iter is a keep_delim, a token of exactly 1 character. Append
+ // that character to the new token and proceed.
+ tokens.back().push_back(instr.next());
+ continue;
+ }
+ // Here we have a non-delimiter token, which might consist of a mix of
+ // quoted and unquoted parts. Use bash rules for quoting: you can
+ // embed a quoted substring in the midst of an unquoted token (e.g.
+ // ~/"sub dir"/myfile.txt); you can ram two quoted substrings together
+ // to make a single token (e.g. 'He said, "'"Don't."'"'). We diverge
+ // from bash in that bash considers an unmatched quote an error. Our
+ // param signature doesn't allow for errors, so just pretend it's not
+ // a quote and embed it.
+ // At this level, keep scanning until we hit the next delimiter of
+ // either type (drop_delims or keep_delims).
+ while (! instr.oneof(all_delims))
+ {
+ // If we're looking at an open quote, search forward for
+ // a close quote, collecting characters along the way.
+ if (instr.oneof(quotes) &&
+ instr.collect_until(tokens.back(), instr.mIter+1, *instr.mIter))
+ {
+ // collect_until is cleverly designed to do exactly what we
+ // need here. No further action needed if it returns true.
+ }
+ else
+ {
+ // Either *iter isn't a quote, or there's no matching close
+ // quote: in other words, just an ordinary char. Append it to
+ // current token.
+ tokens.back().push_back(instr.next());
+ }
+ // having scanned that segment of this token, if we've reached the
+ // end of the string, we're done
+ if (instr.done())
+ return;
+ }
+ }
}
} // namespace LLStringUtilBaseImpl
@@ -1191,256 +1220,256 @@ void getTokens(INSTRING& instr, std::vector<string_type>& tokens,
// static
template <class T>
void LLStringUtilBase<T>::getTokens(const string_type& string, std::vector<string_type>& tokens,
- const string_type& drop_delims, const string_type& keep_delims,
- const string_type& quotes)
+ const string_type& drop_delims, const string_type& keep_delims,
+ const string_type& quotes)
{
- // Because this overload doesn't support escapes, use simple InString to
- // manage input range.
- LLStringUtilBaseImpl::InString<T> instring(string.begin(), string.end());
- LLStringUtilBaseImpl::getTokens(instring, tokens, drop_delims, keep_delims, quotes);
+ // Because this overload doesn't support escapes, use simple InString to
+ // manage input range.
+ LLStringUtilBaseImpl::InString<T> instring(string.begin(), string.end());
+ LLStringUtilBaseImpl::getTokens(instring, tokens, drop_delims, keep_delims, quotes);
}
// static
template <class T>
void LLStringUtilBase<T>::getTokens(const string_type& string, std::vector<string_type>& tokens,
- const string_type& drop_delims, const string_type& keep_delims,
- const string_type& quotes, const string_type& escapes)
-{
- // This overload must deal with escapes. Delegate that to InEscString
- // (unless there ARE no escapes).
- std::unique_ptr< LLStringUtilBaseImpl::InString<T> > instrp;
- if (escapes.empty())
- instrp.reset(new LLStringUtilBaseImpl::InString<T>(string.begin(), string.end()));
- else
- instrp.reset(new LLStringUtilBaseImpl::InEscString<T>(string.begin(), string.end(), escapes));
- LLStringUtilBaseImpl::getTokens(*instrp, tokens, drop_delims, keep_delims, quotes);
+ const string_type& drop_delims, const string_type& keep_delims,
+ const string_type& quotes, const string_type& escapes)
+{
+ // This overload must deal with escapes. Delegate that to InEscString
+ // (unless there ARE no escapes).
+ std::unique_ptr< LLStringUtilBaseImpl::InString<T> > instrp;
+ if (escapes.empty())
+ instrp.reset(new LLStringUtilBaseImpl::InString<T>(string.begin(), string.end()));
+ else
+ instrp.reset(new LLStringUtilBaseImpl::InEscString<T>(string.begin(), string.end(), escapes));
+ LLStringUtilBaseImpl::getTokens(*instrp, tokens, drop_delims, keep_delims, quotes);
}
// static
-template<class T>
+template<class T>
S32 LLStringUtilBase<T>::compareStrings(const T* lhs, const T* rhs)
-{
- S32 result;
- if( lhs == rhs )
- {
- result = 0;
- }
- else
- if ( !lhs || !lhs[0] )
- {
- result = ((!rhs || !rhs[0]) ? 0 : 1);
- }
- else
- if ( !rhs || !rhs[0])
- {
- result = -1;
- }
- else
- {
- result = LLStringOps::collate(lhs, rhs);
- }
- return result;
+{
+ S32 result;
+ if( lhs == rhs )
+ {
+ result = 0;
+ }
+ else
+ if ( !lhs || !lhs[0] )
+ {
+ result = ((!rhs || !rhs[0]) ? 0 : 1);
+ }
+ else
+ if ( !rhs || !rhs[0])
+ {
+ result = -1;
+ }
+ else
+ {
+ result = LLStringOps::collate(lhs, rhs);
+ }
+ return result;
}
-//static
-template<class T>
+//static
+template<class T>
S32 LLStringUtilBase<T>::compareStrings(const string_type& lhs, const string_type& rhs)
{
- return LLStringOps::collate(lhs.c_str(), rhs.c_str());
+ return LLStringOps::collate(lhs.c_str(), rhs.c_str());
}
// static
-template<class T>
+template<class T>
S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs )
{
- S32 result;
- if( lhs == rhs )
- {
- result = 0;
- }
- else
- if ( !lhs || !lhs[0] )
- {
- result = ((!rhs || !rhs[0]) ? 0 : 1);
- }
- else
- if ( !rhs || !rhs[0] )
- {
- result = -1;
- }
- else
- {
- string_type lhs_string(lhs);
- string_type rhs_string(rhs);
- LLStringUtilBase<T>::toUpper(lhs_string);
- LLStringUtilBase<T>::toUpper(rhs_string);
- result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
- }
- return result;
+ S32 result;
+ if( lhs == rhs )
+ {
+ result = 0;
+ }
+ else
+ if ( !lhs || !lhs[0] )
+ {
+ result = ((!rhs || !rhs[0]) ? 0 : 1);
+ }
+ else
+ if ( !rhs || !rhs[0] )
+ {
+ result = -1;
+ }
+ else
+ {
+ string_type lhs_string(lhs);
+ string_type rhs_string(rhs);
+ LLStringUtilBase<T>::toUpper(lhs_string);
+ LLStringUtilBase<T>::toUpper(rhs_string);
+ result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
+ }
+ return result;
}
-//static
-template<class T>
+//static
+template<class T>
S32 LLStringUtilBase<T>::compareInsensitive(const string_type& lhs, const string_type& rhs)
{
- string_type lhs_string(lhs);
- string_type rhs_string(rhs);
- LLStringUtilBase<T>::toUpper(lhs_string);
- LLStringUtilBase<T>::toUpper(rhs_string);
- return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
+ string_type lhs_string(lhs);
+ string_type rhs_string(rhs);
+ LLStringUtilBase<T>::toUpper(lhs_string);
+ LLStringUtilBase<T>::toUpper(rhs_string);
+ return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
}
// Case sensitive comparison with good handling of numbers. Does not use current locale.
// a.k.a. strdictcmp()
-//static
+//static
template<class T>
S32 LLStringUtilBase<T>::compareDict(const string_type& astr, const string_type& bstr)
{
- const T* a = astr.c_str();
- const T* b = bstr.c_str();
- T ca, cb;
- S32 ai, bi, cnt = 0;
- S32 bias = 0;
-
- ca = *(a++);
- cb = *(b++);
- while( ca && cb ){
- if( bias==0 ){
- if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; }
- if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; }
- }else{
- if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
- if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
- }
- if( LLStringOps::isDigit(ca) ){
- if( cnt-->0 ){
- if( cb!=ca ) break;
- }else{
- if( !LLStringOps::isDigit(cb) ) break;
- for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
- for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
- if( ai<bi ){ ca=0; break; }
- if( bi<ai ){ cb=0; break; }
- if( ca!=cb ) break;
- cnt = ai;
- }
- }else if( ca!=cb ){ break;
- }
- ca = *(a++);
- cb = *(b++);
- }
- if( ca==cb ) ca += bias;
- return ca-cb;
+ const T* a = astr.c_str();
+ const T* b = bstr.c_str();
+ T ca, cb;
+ S32 ai, bi, cnt = 0;
+ S32 bias = 0;
+
+ ca = *(a++);
+ cb = *(b++);
+ while( ca && cb ){
+ if( bias==0 ){
+ if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; }
+ if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; }
+ }else{
+ if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
+ if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
+ }
+ if( LLStringOps::isDigit(ca) ){
+ if( cnt-->0 ){
+ if( cb!=ca ) break;
+ }else{
+ if( !LLStringOps::isDigit(cb) ) break;
+ for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
+ for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
+ if( ai<bi ){ ca=0; break; }
+ if( bi<ai ){ cb=0; break; }
+ if( ca!=cb ) break;
+ cnt = ai;
+ }
+ }else if( ca!=cb ){ break;
+ }
+ ca = *(a++);
+ cb = *(b++);
+ }
+ if( ca==cb ) ca += bias;
+ return ca-cb;
}
// static
template<class T>
S32 LLStringUtilBase<T>::compareDictInsensitive(const string_type& astr, const string_type& bstr)
{
- const T* a = astr.c_str();
- const T* b = bstr.c_str();
- T ca, cb;
- S32 ai, bi, cnt = 0;
-
- ca = *(a++);
- cb = *(b++);
- while( ca && cb ){
- if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
- if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
- if( LLStringOps::isDigit(ca) ){
- if( cnt-->0 ){
- if( cb!=ca ) break;
- }else{
- if( !LLStringOps::isDigit(cb) ) break;
- for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
- for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
- if( ai<bi ){ ca=0; break; }
- if( bi<ai ){ cb=0; break; }
- if( ca!=cb ) break;
- cnt = ai;
- }
- }else if( ca!=cb ){ break;
- }
- ca = *(a++);
- cb = *(b++);
- }
- return ca-cb;
+ const T* a = astr.c_str();
+ const T* b = bstr.c_str();
+ T ca, cb;
+ S32 ai, bi, cnt = 0;
+
+ ca = *(a++);
+ cb = *(b++);
+ while( ca && cb ){
+ if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
+ if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
+ if( LLStringOps::isDigit(ca) ){
+ if( cnt-->0 ){
+ if( cb!=ca ) break;
+ }else{
+ if( !LLStringOps::isDigit(cb) ) break;
+ for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
+ for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
+ if( ai<bi ){ ca=0; break; }
+ if( bi<ai ){ cb=0; break; }
+ if( ca!=cb ) break;
+ cnt = ai;
+ }
+ }else if( ca!=cb ){ break;
+ }
+ ca = *(a++);
+ cb = *(b++);
+ }
+ return ca-cb;
}
// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
-// static
-template<class T>
+// static
+template<class T>
BOOL LLStringUtilBase<T>::precedesDict( const string_type& a, const string_type& b )
{
- if( a.size() && b.size() )
- {
- return (LLStringUtilBase<T>::compareDict(a.c_str(), b.c_str()) < 0);
- }
- else
- {
- return (!b.empty());
- }
+ if( a.size() && b.size() )
+ {
+ return (LLStringUtilBase<T>::compareDict(a.c_str(), b.c_str()) < 0);
+ }
+ else
+ {
+ return (!b.empty());
+ }
}
//static
-template<class T>
-void LLStringUtilBase<T>::toUpper(string_type& string)
-{
- if( !string.empty() )
- {
- std::transform(
- string.begin(),
- string.end(),
- string.begin(),
- (T(*)(T)) &LLStringOps::toUpper);
- }
+template<class T>
+void LLStringUtilBase<T>::toUpper(string_type& string)
+{
+ if( !string.empty() )
+ {
+ std::transform(
+ string.begin(),
+ string.end(),
+ string.begin(),
+ (T(*)(T)) &LLStringOps::toUpper);
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::toLower(string_type& string)
-{
- if( !string.empty() )
- {
- std::transform(
- string.begin(),
- string.end(),
- string.begin(),
- (T(*)(T)) &LLStringOps::toLower);
- }
+{
+ if( !string.empty() )
+ {
+ std::transform(
+ string.begin(),
+ string.end(),
+ string.begin(),
+ (T(*)(T)) &LLStringOps::toLower);
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::trimHead(string_type& string)
-{
- if( !string.empty() )
- {
- size_type i = 0;
- while( i < string.length() && LLStringOps::isSpace( string[i] ) )
- {
- i++;
- }
- string.erase(0, i);
- }
+{
+ if( !string.empty() )
+ {
+ size_type i = 0;
+ while( i < string.length() && LLStringOps::isSpace( string[i] ) )
+ {
+ i++;
+ }
+ string.erase(0, i);
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::trimTail(string_type& string)
-{
- if( string.size() )
- {
- size_type len = string.length();
- size_type i = len;
- while( i > 0 && LLStringOps::isSpace( string[i-1] ) )
- {
- i--;
- }
-
- string.erase( i, len - i );
- }
+{
+ if( string.size() )
+ {
+ size_type len = string.length();
+ size_type i = len;
+ while( i > 0 && LLStringOps::isSpace( string[i-1] ) )
+ {
+ i--;
+ }
+
+ string.erase( i, len - i );
+ }
}
@@ -1449,67 +1478,67 @@ void LLStringUtilBase<T>::trimTail(string_type& string)
template<class T>
void LLStringUtilBase<T>::addCRLF(string_type& string)
{
- const T LF = 10;
- const T CR = 13;
-
- // Count the number of line feeds
- size_type count = 0;
- size_type len = string.size();
- size_type i;
- for( i = 0; i < len; i++ )
- {
- if( string[i] == LF )
- {
- count++;
- }
- }
-
- // Insert a carriage return before each line feed
- if( count )
- {
- size_type size = len + count;
- T *t = new T[size];
- size_type j = 0;
- for( i = 0; i < len; ++i )
- {
- if( string[i] == LF )
- {
- t[j] = CR;
- ++j;
- }
- t[j] = string[i];
- ++j;
- }
-
- string.assign(t, size);
- delete[] t;
- }
+ const T LF = 10;
+ const T CR = 13;
+
+ // Count the number of line feeds
+ size_type count = 0;
+ size_type len = string.size();
+ size_type i;
+ for( i = 0; i < len; i++ )
+ {
+ if( string[i] == LF )
+ {
+ count++;
+ }
+ }
+
+ // Insert a carriage return before each line feed
+ if( count )
+ {
+ size_type size = len + count;
+ T *t = new T[size];
+ size_type j = 0;
+ for( i = 0; i < len; ++i )
+ {
+ if( string[i] == LF )
+ {
+ t[j] = CR;
+ ++j;
+ }
+ t[j] = string[i];
+ ++j;
+ }
+
+ string.assign(t, size);
+ delete[] t;
+ }
}
// Remove all carriage returns
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::removeCRLF(string_type& string)
{
- const T CR = 13;
-
- size_type cr_count = 0;
- size_type len = string.size();
- size_type i;
- for( i = 0; i < len - cr_count; i++ )
- {
- if( string[i+cr_count] == CR )
- {
- cr_count++;
- }
-
- string[i] = string[i+cr_count];
- }
- string.erase(i, cr_count);
+ const T CR = 13;
+
+ size_type cr_count = 0;
+ size_type len = string.size();
+ size_type i;
+ for( i = 0; i < len - cr_count; i++ )
+ {
+ if( string[i+cr_count] == CR )
+ {
+ cr_count++;
+ }
+
+ string[i] = string[i+cr_count];
+ }
+ string.erase(i, cr_count);
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::removeWindowsCR(string_type& string)
{
if (string.empty())
@@ -1538,269 +1567,269 @@ void LLStringUtilBase<T>::removeWindowsCR(string_type& string)
template<class T>
void LLStringUtilBase<T>::replaceChar( string_type& string, T target, T replacement )
{
- size_type found_pos = 0;
- while( (found_pos = string.find(target, found_pos)) != string_type::npos )
- {
- string[found_pos] = replacement;
- found_pos++; // avoid infinite defeat if target == replacement
- }
+ size_type found_pos = 0;
+ while( (found_pos = string.find(target, found_pos)) != string_type::npos )
+ {
+ string[found_pos] = replacement;
+ found_pos++; // avoid infinite defeat if target == replacement
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::replaceString( string_type& string, string_type target, string_type replacement )
{
- size_type found_pos = 0;
- while( (found_pos = string.find(target, found_pos)) != string_type::npos )
- {
- string.replace( found_pos, target.length(), replacement );
- found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
- }
+ size_type found_pos = 0;
+ while( (found_pos = string.find(target, found_pos)) != string_type::npos )
+ {
+ string.replace( found_pos, target.length(), replacement );
+ found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::replaceNonstandardASCII( string_type& string, T replacement )
{
- const char LF = 10;
- const S8 MIN = 32;
-// const S8 MAX = 127;
-
- size_type len = string.size();
- for( size_type i = 0; i < len; i++ )
- {
- // No need to test MAX < mText[i] because we treat mText[i] as a signed char,
- // which has a max value of 127.
- if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
- {
- string[i] = replacement;
- }
- }
+ const char LF = 10;
+ const S8 MIN = 32;
+// const S8 MAX = 127;
+
+ size_type len = string.size();
+ for( size_type i = 0; i < len; i++ )
+ {
+ // No need to test MAX < mText[i] because we treat mText[i] as a signed char,
+ // which has a max value of 127.
+ if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
+ {
+ string[i] = replacement;
+ }
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::replaceTabsWithSpaces( string_type& str, size_type spaces_per_tab )
{
- const T TAB = '\t';
- const T SPACE = ' ';
-
- string_type out_str;
- // Replace tabs with spaces
- for (size_type i = 0; i < str.length(); i++)
- {
- if (str[i] == TAB)
- {
- for (size_type j = 0; j < spaces_per_tab; j++)
- out_str += SPACE;
- }
- else
- {
- out_str += str[i];
- }
- }
- str = out_str;
+ const T TAB = '\t';
+ const T SPACE = ' ';
+
+ string_type out_str;
+ // Replace tabs with spaces
+ for (size_type i = 0; i < str.length(); i++)
+ {
+ if (str[i] == TAB)
+ {
+ for (size_type j = 0; j < spaces_per_tab; j++)
+ out_str += SPACE;
+ }
+ else
+ {
+ out_str += str[i];
+ }
+ }
+ str = out_str;
}
//static
template<class T>
std::basic_string<T> LLStringUtilBase<T>::capitalize(const string_type& str)
{
- string_type result(str);
- capitalize(result);
- return result;
+ string_type result(str);
+ capitalize(result);
+ return result;
}
//static
template<class T>
void LLStringUtilBase<T>::capitalize(string_type& str)
{
- if (str.size())
- {
- auto last = str[0] = toupper(str[0]);
- for (U32 i = 1; i < str.size(); ++i)
- {
- last = (last == ' ' || last == '-' || last == '_') ? str[i] = toupper(str[i]) : str[i];
- }
- }
+ if (str.size())
+ {
+ auto last = str[0] = toupper(str[0]);
+ for (U32 i = 1; i < str.size(); ++i)
+ {
+ last = (last == ' ' || last == '-' || last == '_') ? str[i] = toupper(str[i]) : str[i];
+ }
+ }
}
//static
-template<class T>
+template<class T>
BOOL LLStringUtilBase<T>::containsNonprintable(const string_type& string)
{
- const char MIN = 32;
- BOOL rv = FALSE;
- for (size_type i = 0; i < string.size(); i++)
- {
- if(string[i] < MIN)
- {
- rv = TRUE;
- break;
- }
- }
- return rv;
+ const char MIN = 32;
+ BOOL rv = FALSE;
+ for (size_type i = 0; i < string.size(); i++)
+ {
+ if(string[i] < MIN)
+ {
+ rv = TRUE;
+ break;
+ }
+ }
+ return rv;
}
-// *TODO: reimplement in terms of algorithm
+// *TODO: reimplement in terms of algorithm
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::stripNonprintable(string_type& string)
{
- const char MIN = 32;
- size_type j = 0;
- if (string.empty())
- {
- return;
- }
- size_t src_size = string.size();
- char* c_string = new char[src_size + 1];
- if(c_string == NULL)
- {
- return;
- }
- copy(c_string, string.c_str(), src_size+1);
- char* write_head = &c_string[0];
- for (size_type i = 0; i < src_size; i++)
- {
- char* read_head = &string[i];
- write_head = &c_string[j];
- if(!(*read_head < MIN))
- {
- *write_head = *read_head;
- ++j;
- }
- }
- c_string[j]= '\0';
- string = c_string;
- delete []c_string;
+ const char MIN = 32;
+ size_type j = 0;
+ if (string.empty())
+ {
+ return;
+ }
+ size_t src_size = string.size();
+ char* c_string = new char[src_size + 1];
+ if(c_string == NULL)
+ {
+ return;
+ }
+ copy(c_string, string.c_str(), src_size+1);
+ char* write_head = &c_string[0];
+ for (size_type i = 0; i < src_size; i++)
+ {
+ char* read_head = &string[i];
+ write_head = &c_string[j];
+ if(!(*read_head < MIN))
+ {
+ *write_head = *read_head;
+ ++j;
+ }
+ }
+ c_string[j]= '\0';
+ string = c_string;
+ delete []c_string;
}
-// *TODO: reimplement in terms of algorithm
+// *TODO: reimplement in terms of algorithm
template<class T>
std::basic_string<T> LLStringUtilBase<T>::quote(const string_type& str,
- const string_type& triggers,
- const string_type& escape)
-{
- size_type len(str.length());
- // If the string is already quoted, assume user knows what s/he's doing.
- if (len >= 2 && str[0] == '"' && str[len-1] == '"')
- {
- return str;
- }
-
- // Not already quoted: do we need to? triggers.empty() is a special case
- // meaning "always quote."
- if ((! triggers.empty()) && str.find_first_of(triggers) == string_type::npos)
- {
- // no trigger characters, don't bother quoting
- return str;
- }
-
- // For whatever reason, we must quote this string.
- string_type result;
- result.push_back('"');
- for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
- {
- if (*ci == '"')
- {
- result.append(escape);
- }
- result.push_back(*ci);
- }
- result.push_back('"');
- return result;
+ const string_type& triggers,
+ const string_type& escape)
+{
+ size_type len(str.length());
+ // If the string is already quoted, assume user knows what s/he's doing.
+ if (len >= 2 && str[0] == '"' && str[len-1] == '"')
+ {
+ return str;
+ }
+
+ // Not already quoted: do we need to? triggers.empty() is a special case
+ // meaning "always quote."
+ if ((! triggers.empty()) && str.find_first_of(triggers) == string_type::npos)
+ {
+ // no trigger characters, don't bother quoting
+ return str;
+ }
+
+ // For whatever reason, we must quote this string.
+ string_type result;
+ result.push_back('"');
+ for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
+ {
+ if (*ci == '"')
+ {
+ result.append(escape);
+ }
+ result.push_back(*ci);
+ }
+ result.push_back('"');
+ return result;
}
-template<class T>
+template<class T>
void LLStringUtilBase<T>::_makeASCII(string_type& string)
{
- // Replace non-ASCII chars with LL_UNKNOWN_CHAR
- for (size_type i = 0; i < string.length(); i++)
- {
- if (string[i] > 0x7f)
- {
- string[i] = LL_UNKNOWN_CHAR;
- }
- }
+ // Replace non-ASCII chars with LL_UNKNOWN_CHAR
+ for (size_type i = 0; i < string.length(); i++)
+ {
+ if (string[i] > 0x7f)
+ {
+ string[i] = LL_UNKNOWN_CHAR;
+ }
+ }
}
// static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::copy( T* dst, const T* src, size_type dst_size )
{
- if( dst_size > 0 )
- {
- size_type min_len = 0;
- if( src )
- {
- min_len = llmin( dst_size - 1, strlen( src ) ); /* Flawfinder: ignore */
- memcpy(dst, src, min_len * sizeof(T)); /* Flawfinder: ignore */
- }
- dst[min_len] = '\0';
- }
+ if( dst_size > 0 )
+ {
+ size_type min_len = 0;
+ if( src )
+ {
+ min_len = llmin( dst_size - 1, strlen( src ) ); /* Flawfinder: ignore */
+ memcpy(dst, src, min_len * sizeof(T)); /* Flawfinder: ignore */
+ }
+ dst[min_len] = '\0';
+ }
}
// static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::copyInto(string_type& dst, const string_type& src, size_type offset)
{
- if ( offset == dst.length() )
- {
- // special case - append to end of string and avoid expensive
- // (when strings are large) string manipulations
- dst += src;
- }
- else
- {
- string_type tail = dst.substr(offset);
-
- dst = dst.substr(0, offset);
- dst += src;
- dst += tail;
- };
+ if ( offset == dst.length() )
+ {
+ // special case - append to end of string and avoid expensive
+ // (when strings are large) string manipulations
+ dst += src;
+ }
+ else
+ {
+ string_type tail = dst.substr(offset);
+
+ dst = dst.substr(0, offset);
+ dst += src;
+ dst += tail;
+ };
}
// True if this is the head of s.
//static
-template<class T>
-BOOL LLStringUtilBase<T>::isHead( const string_type& string, const T* s )
-{
- if( string.empty() )
- {
- // Early exit
- return FALSE;
- }
- else
- {
- return (strncmp( s, string.c_str(), string.size() ) == 0);
- }
+template<class T>
+BOOL LLStringUtilBase<T>::isHead( const string_type& string, const T* s )
+{
+ if( string.empty() )
+ {
+ // Early exit
+ return FALSE;
+ }
+ else
+ {
+ return (strncmp( s, string.c_str(), string.size() ) == 0);
+ }
}
// static
-template<class T>
+template<class T>
bool LLStringUtilBase<T>::startsWith(
- const string_type& string,
- const string_type& substr)
+ const string_type& string,
+ const string_type& substr)
{
- if(string.empty() || (substr.empty())) return false;
- if (substr.length() > string.length()) return false;
- if (0 == string.compare(0, substr.length(), substr)) return true;
- return false;
+ if(string.empty() || (substr.empty())) return false;
+ if (substr.length() > string.length()) return false;
+ if (0 == string.compare(0, substr.length(), substr)) return true;
+ return false;
}
// static
-template<class T>
+template<class T>
bool LLStringUtilBase<T>::endsWith(
- const string_type& string,
- const string_type& substr)
-{
- if(string.empty() || (substr.empty())) return false;
- size_t sub_len = substr.length();
- size_t str_len = string.length();
- if (sub_len > str_len) return false;
- if (0 == string.compare(str_len - sub_len, sub_len, substr)) return true;
- return false;
+ const string_type& string,
+ const string_type& substr)
+{
+ if(string.empty() || (substr.empty())) return false;
+ size_t sub_len = substr.length();
+ size_t str_len = string.length();
+ if (sub_len > str_len) return false;
+ if (0 == string.compare(str_len - sub_len, sub_len, substr)) return true;
+ return false;
}
// static
@@ -1811,7 +1840,7 @@ auto LLStringUtilBase<T>::getoptenv(const std::string& key) -> boost::optional<s
if (found)
{
// return populated boost::optional
- return { ll_convert<string_type>(*found) };
+ return { ll_convert_to<string_type>(*found) };
}
else
{
@@ -1835,187 +1864,187 @@ auto LLStringUtilBase<T>::getenv(const std::string& key, const string_type& dflt
}
}
-template<class T>
+template<class T>
BOOL LLStringUtilBase<T>::convertToBOOL(const string_type& string, BOOL& value)
{
- if( string.empty() )
- {
- return FALSE;
- }
-
- string_type temp( string );
- trim(temp);
- if(
- (temp == "1") ||
- (temp == "T") ||
- (temp == "t") ||
- (temp == "TRUE") ||
- (temp == "true") ||
- (temp == "True") )
- {
- value = TRUE;
- return TRUE;
- }
- else
- if(
- (temp == "0") ||
- (temp == "F") ||
- (temp == "f") ||
- (temp == "FALSE") ||
- (temp == "false") ||
- (temp == "False") )
- {
- value = FALSE;
- return TRUE;
- }
-
- return FALSE;
+ if( string.empty() )
+ {
+ return FALSE;
+ }
+
+ string_type temp( string );
+ trim(temp);
+ if(
+ (temp == "1") ||
+ (temp == "T") ||
+ (temp == "t") ||
+ (temp == "TRUE") ||
+ (temp == "true") ||
+ (temp == "True") )
+ {
+ value = TRUE;
+ return TRUE;
+ }
+ else
+ if(
+ (temp == "0") ||
+ (temp == "F") ||
+ (temp == "f") ||
+ (temp == "FALSE") ||
+ (temp == "false") ||
+ (temp == "False") )
+ {
+ value = FALSE;
+ return TRUE;
+ }
+
+ return FALSE;
}
-template<class T>
-BOOL LLStringUtilBase<T>::convertToU8(const string_type& string, U8& value)
-{
- S32 value32 = 0;
- BOOL success = convertToS32(string, value32);
- if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) )
- {
- value = (U8) value32;
- return TRUE;
- }
- return FALSE;
+template<class T>
+BOOL LLStringUtilBase<T>::convertToU8(const string_type& string, U8& value)
+{
+ S32 value32 = 0;
+ BOOL success = convertToS32(string, value32);
+ if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) )
+ {
+ value = (U8) value32;
+ return TRUE;
+ }
+ return FALSE;
}
-template<class T>
-BOOL LLStringUtilBase<T>::convertToS8(const string_type& string, S8& value)
-{
- S32 value32 = 0;
- BOOL success = convertToS32(string, value32);
- if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) )
- {
- value = (S8) value32;
- return TRUE;
- }
- return FALSE;
+template<class T>
+BOOL LLStringUtilBase<T>::convertToS8(const string_type& string, S8& value)
+{
+ S32 value32 = 0;
+ BOOL success = convertToS32(string, value32);
+ if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) )
+ {
+ value = (S8) value32;
+ return TRUE;
+ }
+ return FALSE;
}
-template<class T>
-BOOL LLStringUtilBase<T>::convertToS16(const string_type& string, S16& value)
-{
- S32 value32 = 0;
- BOOL success = convertToS32(string, value32);
- if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) )
- {
- value = (S16) value32;
- return TRUE;
- }
- return FALSE;
+template<class T>
+BOOL LLStringUtilBase<T>::convertToS16(const string_type& string, S16& value)
+{
+ S32 value32 = 0;
+ BOOL success = convertToS32(string, value32);
+ if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) )
+ {
+ value = (S16) value32;
+ return TRUE;
+ }
+ return FALSE;
}
-template<class T>
-BOOL LLStringUtilBase<T>::convertToU16(const string_type& string, U16& value)
-{
- S32 value32 = 0;
- BOOL success = convertToS32(string, value32);
- if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) )
- {
- value = (U16) value32;
- return TRUE;
- }
- return FALSE;
+template<class T>
+BOOL LLStringUtilBase<T>::convertToU16(const string_type& string, U16& value)
+{
+ S32 value32 = 0;
+ BOOL success = convertToS32(string, value32);
+ if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) )
+ {
+ value = (U16) value32;
+ return TRUE;
+ }
+ return FALSE;
}
-template<class T>
-BOOL LLStringUtilBase<T>::convertToU32(const string_type& string, U32& value)
-{
- if( string.empty() )
- {
- return FALSE;
- }
-
- string_type temp( string );
- trim(temp);
- U32 v;
- std::basic_istringstream<T> i_stream((string_type)temp);
- if(i_stream >> v)
- {
- value = v;
- return TRUE;
- }
- return FALSE;
+template<class T>
+BOOL LLStringUtilBase<T>::convertToU32(const string_type& string, U32& value)
+{
+ if( string.empty() )
+ {
+ return FALSE;
+ }
+
+ string_type temp( string );
+ trim(temp);
+ U32 v;
+ std::basic_istringstream<T> i_stream((string_type)temp);
+ if(i_stream >> v)
+ {
+ value = v;
+ return TRUE;
+ }
+ return FALSE;
}
-template<class T>
-BOOL LLStringUtilBase<T>::convertToS32(const string_type& string, S32& value)
-{
- if( string.empty() )
- {
- return FALSE;
- }
-
- string_type temp( string );
- trim(temp);
- S32 v;
- std::basic_istringstream<T> i_stream((string_type)temp);
- if(i_stream >> v)
- {
- //TODO: figure out overflow and underflow reporting here
- //if((LONG_MAX == v) || (LONG_MIN == v))
- //{
- // // Underflow or overflow
- // return FALSE;
- //}
-
- value = v;
- return TRUE;
- }
- return FALSE;
+template<class T>
+BOOL LLStringUtilBase<T>::convertToS32(const string_type& string, S32& value)
+{
+ if( string.empty() )
+ {
+ return FALSE;
+ }
+
+ string_type temp( string );
+ trim(temp);
+ S32 v;
+ std::basic_istringstream<T> i_stream((string_type)temp);
+ if(i_stream >> v)
+ {
+ //TODO: figure out overflow and underflow reporting here
+ //if((LONG_MAX == v) || (LONG_MIN == v))
+ //{
+ // // Underflow or overflow
+ // return FALSE;
+ //}
+
+ value = v;
+ return TRUE;
+ }
+ return FALSE;
}
-template<class T>
-BOOL LLStringUtilBase<T>::convertToF32(const string_type& string, F32& value)
-{
- F64 value64 = 0.0;
- BOOL success = convertToF64(string, value64);
- if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) )
- {
- value = (F32) value64;
- return TRUE;
- }
- return FALSE;
+template<class T>
+BOOL LLStringUtilBase<T>::convertToF32(const string_type& string, F32& value)
+{
+ F64 value64 = 0.0;
+ BOOL success = convertToF64(string, value64);
+ if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) )
+ {
+ value = (F32) value64;
+ return TRUE;
+ }
+ return FALSE;
}
-template<class T>
+template<class T>
BOOL LLStringUtilBase<T>::convertToF64(const string_type& string, F64& value)
{
- if( string.empty() )
- {
- return FALSE;
- }
-
- string_type temp( string );
- trim(temp);
- F64 v;
- std::basic_istringstream<T> i_stream((string_type)temp);
- if(i_stream >> v)
- {
- //TODO: figure out overflow and underflow reporting here
- //if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) )
- //{
- // // Underflow or overflow
- // return FALSE;
- //}
-
- value = v;
- return TRUE;
- }
- return FALSE;
+ if( string.empty() )
+ {
+ return FALSE;
+ }
+
+ string_type temp( string );
+ trim(temp);
+ F64 v;
+ std::basic_istringstream<T> i_stream((string_type)temp);
+ if(i_stream >> v)
+ {
+ //TODO: figure out overflow and underflow reporting here
+ //if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) )
+ //{
+ // // Underflow or overflow
+ // return FALSE;
+ //}
+
+ value = v;
+ return TRUE;
+ }
+ return FALSE;
}
-template<class T>
+template<class T>
void LLStringUtilBase<T>::truncate(string_type& string, size_type count)
{
- size_type cur_size = string.size();
- string.resize(count < cur_size ? count : cur_size);
+ size_type cur_size = string.size();
+ string.resize(count < cur_size ? count : cur_size);
}
// The good thing about *declaration* macros, vs. usage macros, is that now
diff --git a/indra/llcommon/lua_function.cpp b/indra/llcommon/lua_function.cpp
new file mode 100644
index 0000000000..08bc65e0c5
--- /dev/null
+++ b/indra/llcommon/lua_function.cpp
@@ -0,0 +1,984 @@
+/**
+ * @file lua_function.cpp
+ * @author Nat Goodspeed
+ * @date 2024-02-05
+ * @brief Implementation for lua_function.
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Copyright (c) 2024, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lua_function.h"
+// STL headers
+// std headers
+#include <algorithm>
+#include <exception>
+#include <iomanip> // std::quoted
+#include <map>
+#include <memory> // std::unique_ptr
+#include <typeinfo>
+// external library headers
+// other Linden headers
+#include "fsyspath.h"
+#include "hexdump.h"
+#include "lleventcoro.h"
+#include "llsd.h"
+#include "llsdutil.h"
+#include "lualistener.h"
+#include "stringize.h"
+
+const S32 INTERRUPTS_MAX_LIMIT = 20000;
+const S32 INTERRUPTS_SUSPEND_LIMIT = 100;
+
+#define lua_register(L, n, f) (lua_pushcfunction(L, (f), n), lua_setglobal(L, (n)))
+#define lua_rawlen lua_objlen
+
+/*****************************************************************************
+* luau namespace
+*****************************************************************************/
+namespace
+{
+ // can't specify free function free() as a unique_ptr deleter
+ struct freer
+ {
+ void operator()(void* ptr){ free(ptr); }
+ };
+} // anonymous namespace
+
+int lluau::dostring(lua_State* L, const std::string& desc, const std::string& text)
+{
+ auto r = loadstring(L, desc, text);
+ if (r != LUA_OK)
+ return r;
+
+ // It's important to pass LUA_MULTRET as the expected number of return
+ // values: if we pass any fixed number, we discard any returned values
+ // beyond that number.
+ return lua_pcall(L, 0, LUA_MULTRET, 0);
+}
+
+int lluau::loadstring(lua_State *L, const std::string &desc, const std::string &text)
+{
+ size_t bytecodeSize = 0;
+ // The char* returned by luau_compile() must be freed by calling free().
+ // Use unique_ptr so the memory will be freed even if luau_load() throws.
+ std::unique_ptr<char[], freer> bytecode{
+ luau_compile(text.data(), text.length(), nullptr, &bytecodeSize)};
+ return luau_load(L, desc.data(), bytecode.get(), bytecodeSize, 0);
+}
+
+fsyspath lluau::source_path(lua_State* L)
+{
+ //Luau lua_Debug and lua_getinfo() are different compared to default Lua:
+ //see https://github.com/luau-lang/luau/blob/80928acb92d1e4b6db16bada6d21b1fb6fa66265/VM/include/lua.h
+ lua_Debug ar;
+ lua_getinfo(L, 1, "s", &ar);
+ return ar.source;
+}
+
+void lluau::set_interrupts_counter(lua_State *L, S32 counter)
+{
+ luaL_checkstack(L, 2, nullptr);
+ lua_pushstring(L, "_INTERRUPTS");
+ lua_pushinteger(L, counter);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+}
+
+void lluau::check_interrupts_counter(lua_State* L)
+{
+ luaL_checkstack(L, 1, nullptr);
+ lua_pushstring(L, "_INTERRUPTS");
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ S32 counter = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+
+ lluau::set_interrupts_counter(L, ++counter);
+ if (counter > INTERRUPTS_MAX_LIMIT)
+ {
+ lluau::error(L, "Possible infinite loop, terminated.");
+ }
+ else if (counter % INTERRUPTS_SUSPEND_LIMIT == 0)
+ {
+ LL_DEBUGS("Lua") << LLCoros::getName() << " suspending at " << counter << " interrupts"
+ << LL_ENDL;
+ llcoro::suspend();
+ }
+}
+
+/*****************************************************************************
+* Lua <=> C++ conversions
+*****************************************************************************/
+std::string lua_tostdstring(lua_State* L, int index)
+{
+ size_t len;
+ const char* strval{ lua_tolstring(L, index, &len) };
+ return { strval, len };
+}
+
+void lua_pushstdstring(lua_State* L, const std::string& str)
+{
+ luaL_checkstack(L, 1, nullptr);
+ lua_pushlstring(L, str.c_str(), str.length());
+}
+
+// By analogy with existing lua_tomumble() functions, return an LLSD object
+// corresponding to the Lua object at stack index 'index' in state L.
+// This function assumes that a Lua caller is fully aware that they're trying
+// to call a viewer function. In other words, the caller must specifically
+// construct Lua data convertible to LLSD.
+//
+// For proper error handling, we REQUIRE that the Lua runtime be compiled as
+// C++ so errors are raised as C++ exceptions rather than as longjmp() calls:
+// http://www.lua.org/manual/5.4/manual.html#4.4
+// "Internally, Lua uses the C longjmp facility to handle errors. (Lua will
+// use exceptions if you compile it as C++; search for LUAI_THROW in the
+// source code for details.)"
+// Some blocks within this function construct temporary C++ objects in the
+// expectation that these objects will be properly destroyed even if code
+// reached by that block raises a Lua error.
+LLSD lua_tollsd(lua_State* L, int index)
+{
+ switch (lua_type(L, index))
+ {
+ case LUA_TNONE:
+ // Should LUA_TNONE be an error instead of returning isUndefined()?
+ case LUA_TNIL:
+ return {};
+
+ case LUA_TBOOLEAN:
+ return bool(lua_toboolean(L, index));
+
+ case LUA_TNUMBER:
+ {
+ // Vanilla Lua supports lua_tointegerx(), which tells the caller
+ // whether the number at the specified stack index is or is not an
+ // integer. Apparently the function exists but does not work right in
+ // Luau: it reports even non-integer numbers as integers.
+ // Instead, check if integer truncation leaves the number intact.
+ lua_Number numval{ lua_tonumber(L, index) };
+ lua_Integer intval{ narrow(numval) };
+ if (lua_Number(intval) == numval)
+ {
+ return LLSD::Integer(intval);
+ }
+ else
+ {
+ return numval;
+ }
+ }
+
+ case LUA_TSTRING:
+ return lua_tostdstring(L, index);
+
+ case LUA_TUSERDATA:
+ {
+ LLSD::Binary binary(lua_rawlen(L, index));
+ std::memcpy(binary.data(), lua_touserdata(L, index), binary.size());
+ return binary;
+ }
+
+ case LUA_TTABLE:
+ {
+ // A Lua table correctly constructed to convert to LLSD will have
+ // either consecutive integer keys starting at 1, which we represent
+ // as an LLSD array (with Lua key 1 at C++ index 0), or will have
+ // all string keys.
+ //
+ // In the belief that Lua table traversal skips "holes," that is, it
+ // doesn't report any key/value pair whose value is nil, we allow a
+ // table with integer keys >= 1 but with "holes." This produces an
+ // LLSD array with isUndefined() entries at unspecified keys. There
+ // would be no other way for a Lua caller to construct an
+ // isUndefined() LLSD array entry. However, to guard against crazy int
+ // keys, we forbid gaps larger than a certain size: crazy int keys
+ // could result in a crazy large contiguous LLSD array.
+ //
+ // Possible looseness could include:
+ // - A mix of integer and string keys could produce an LLSD map in
+ // which the integer keys are converted to string. (Key conversion
+ // must be performed in C++, not Lua, to avoid confusing
+ // lua_next().)
+ // - However, since in Lua t[0] and t["0"] are distinct table entries,
+ // do not consider converting numeric string keys to int to return
+ // an LLSD array.
+ // But until we get more experience with actual Lua scripts in
+ // practice, let's say that any deviation is a Lua coding error.
+ // An important property of the strict definition above is that most
+ // conforming data blobs can make a round trip across the language
+ // boundary and still compare equal. A non-conforming data blob would
+ // lose that property.
+ // Known exceptions to round trip identity:
+ // - Empty LLSD map and empty LLSD array convert to empty Lua table.
+ // But empty Lua table converts to isUndefined() LLSD object.
+ // - LLSD::Real with integer value returns as LLSD::Integer.
+ // - LLSD::UUID, LLSD::Date and LLSD::URI all convert to Lua string,
+ // and so return as LLSD::String.
+ // - Lua does not store any table key whose value is nil. An LLSD
+ // array with isUndefined() entries produces a Lua table with
+ // "holes" in the int key sequence; this converts back to an LLSD
+ // array containing corresponding isUndefined() entries -- except
+ // when one or more of the final entries isUndefined(). These are
+ // simply dropped, producing a shorter LLSD array than the original.
+ // - For the same reason, any keys in an LLSD map whose value
+ // isUndefined() are simply discarded in the converted Lua table.
+ // This converts back to an LLSD map lacking those keys.
+ // - If it's important to preserve the original length of an LLSD
+ // array whose final entries are undefined, or the full set of keys
+ // for an LLSD map some of whose values are undefined, store an
+ // LLSD::emptyArray() or emptyMap() instead. These will be
+ // represented in Lua as empty table, which should convert back to
+ // undefined LLSD. Naturally, though, those won't survive a second
+ // round trip.
+
+ // This is the most important of the luaL_checkstack() calls because a
+ // deeply nested Lua structure will enter this case at each level, and
+ // we'll need another 2 stack slots to traverse each nested table.
+ luaL_checkstack(L, 2, nullptr);
+ // BEFORE we push nil to initialize the lua_next() traversal, convert
+ // 'index' to absolute! Our caller might have passed a relative index;
+ // we do, below: lua_tollsd(L, -1). If 'index' is -1, then when we
+ // push nil, what we find at index -1 is nil, not the table!
+ index = lua_absindex(L, index);
+ lua_pushnil(L); // first key
+ if (! lua_next(L, index))
+ {
+ // it's a table, but the table is empty -- no idea if it should be
+ // modeled as empty array or empty map -- return isUndefined(),
+ // which can be consumed as either
+ return {};
+ }
+ // key is at stack index -2, value at index -1
+ // from here until lua_next() returns 0, have to lua_pop(2) if we
+ // return early
+ LuaPopper popper(L, 2);
+ // Remember the type of the first key
+ auto firstkeytype{ lua_type(L, -2) };
+ switch (firstkeytype)
+ {
+ case LUA_TNUMBER:
+ {
+ // First Lua key is a number: try to convert table to LLSD array.
+ // This is tricky because we don't know in advance the size of the
+ // array. The Lua reference manual says that lua_rawlen() is the
+ // same as the length operator '#'; but the length operator states
+ // that it might stop at any "hole" in the subject table.
+ // Moreover, the Lua next() function (and presumably lua_next())
+ // traverses a table in unspecified order, even for numeric keys
+ // (emphasized in the doc).
+ // Make a preliminary pass over the whole table to validate and to
+ // collect keys.
+ std::vector<LLSD::Integer> keys;
+ // Try to determine the length of the table. If the length
+ // operator is truthful, avoid allocations while we grow the keys
+ // vector. Even if it's not, we can still grow the vector, albeit
+ // a little less efficiently.
+ keys.reserve(lua_objlen(L, index));
+ do
+ {
+ auto arraykeytype{ lua_type(L, -2) };
+ switch (arraykeytype)
+ {
+ case LUA_TNUMBER:
+ {
+ int isint;
+ lua_Integer intkey{ lua_tointegerx(L, -2, &isint) };
+ if (! isint)
+ {
+ // key isn't an integer - this doesn't fit our LLSD
+ // array constraints
+ return lluau::error(L, "Expected integer array key, got %f instead",
+ lua_tonumber(L, -2));
+ }
+ if (intkey < 1)
+ {
+ return lluau::error(L, "array key %d out of bounds", int(intkey));
+ }
+
+ keys.push_back(LLSD::Integer(intkey));
+ break;
+ }
+
+ case LUA_TSTRING:
+ // break out strings specially to report the value
+ return lluau::error(L, "Cannot convert string array key '%s' to LLSD",
+ lua_tostring(L, -2));
+
+ default:
+ return lluau::error(L, "Cannot convert %s array key to LLSD",
+ lua_typename(L, arraykeytype));
+ }
+
+ // remove value, keep key for next iteration
+ lua_pop(L, 1);
+ } while (lua_next(L, index) != 0);
+ popper.disarm();
+ // Table keys are all integers: are they reasonable integers?
+ // Arbitrary max: may bite us, but more likely to protect us
+ const size_t array_max{ 10000 };
+ if (keys.size() > array_max)
+ {
+ return lluau::error(L, "Conversion from Lua to LLSD array limited to %d entries",
+ int(array_max));
+ }
+ // We know the smallest key is >= 1. Check the largest. We also
+ // know the vector is NOT empty, else we wouldn't have gotten here.
+ std::sort(keys.begin(), keys.end());
+ LLSD::Integer highkey = *keys.rbegin();
+ if ((highkey - LLSD::Integer(keys.size())) > 100)
+ {
+ // Looks like we've gone beyond intentional array gaps into
+ // crazy key territory.
+ return lluau::error(L, "Gaps in Lua table too large for conversion to LLSD array");
+ }
+ // right away expand the result array to the size we'll need
+ LLSD result{ LLSD::emptyArray() };
+ result[highkey - 1] = LLSD();
+ // Traverse the table again, and this time populate result array.
+ lua_pushnil(L); // first key
+ while (lua_next(L, index))
+ {
+ // key at stack index -2, value at index -1
+ // We've already validated lua_tointegerx() for each key.
+ auto key{ lua_tointeger(L, -2) };
+ // Don't forget to subtract 1 from Lua key for LLSD subscript!
+ result[LLSD::Integer(key) - 1] = lua_tollsd(L, -1);
+ // remove value, keep key for next iteration
+ lua_pop(L, 1);
+ }
+ return result;
+ }
+
+ case LUA_TSTRING:
+ {
+ // First Lua key is a string: try to convert table to LLSD map
+ LLSD result{ LLSD::emptyMap() };
+ do
+ {
+ auto mapkeytype{ lua_type(L, -2) };
+ if (mapkeytype != LUA_TSTRING)
+ {
+ return lluau::error(L, "Cannot convert %s map key to LLSD",
+ lua_typename(L, mapkeytype));
+ }
+
+ auto key{ lua_tostdstring(L, -2) };
+ result[key] = lua_tollsd(L, -1);
+ // remove value, keep key for next iteration
+ lua_pop(L, 1);
+ } while (lua_next(L, index) != 0);
+ popper.disarm();
+ return result;
+ }
+
+ default:
+ // First Lua key isn't number or string: sorry
+ return lluau::error(L, "Cannot convert %s table key to LLSD",
+ lua_typename(L, firstkeytype));
+ }
+ }
+
+ default:
+ // Other Lua entities (e.g. function, C function, light userdata,
+ // thread, userdata) are not convertible to LLSD, indicating a coding
+ // error in the caller.
+ return lluau::error(L, "Cannot convert type %s to LLSD", luaL_typename(L, index));
+ }
+}
+
+// By analogy with existing lua_pushmumble() functions, push onto state L's
+// stack a Lua object corresponding to the passed LLSD object.
+void lua_pushllsd(lua_State* L, const LLSD& data)
+{
+ // might need 2 slots for array or map
+ luaL_checkstack(L, 2, nullptr);
+ switch (data.type())
+ {
+ case LLSD::TypeUndefined:
+ lua_pushnil(L);
+ break;
+
+ case LLSD::TypeBoolean:
+ lua_pushboolean(L, data.asBoolean());
+ break;
+
+ case LLSD::TypeInteger:
+ lua_pushinteger(L, data.asInteger());
+ break;
+
+ case LLSD::TypeReal:
+ lua_pushnumber(L, data.asReal());
+ break;
+
+ case LLSD::TypeBinary:
+ {
+ auto binary{ data.asBinary() };
+ std::memcpy(lua_newuserdata(L, binary.size()),
+ binary.data(), binary.size());
+ break;
+ }
+
+ case LLSD::TypeMap:
+ {
+ // push a new table with space for our non-array keys
+ lua_createtable(L, 0, data.size());
+ for (const auto& pair: llsd::inMap(data))
+ {
+ // push value -- so now table is at -2, value at -1
+ lua_pushllsd(L, pair.second);
+ // pop value, assign to table[key]
+ lua_setfield(L, -2, pair.first.c_str());
+ }
+ break;
+ }
+
+ case LLSD::TypeArray:
+ {
+ // push a new table with space for array entries
+ lua_createtable(L, data.size(), 0);
+ lua_Integer key{ 0 };
+ for (const auto& item: llsd::inArray(data))
+ {
+ // push new array value: table at -2, value at -1
+ lua_pushllsd(L, item);
+ // pop value, assign table[key] = value
+ lua_rawseti(L, -2, ++key);
+ }
+ break;
+ }
+
+ case LLSD::TypeString:
+ case LLSD::TypeUUID:
+ case LLSD::TypeDate:
+ case LLSD::TypeURI:
+ default:
+ {
+ lua_pushstdstring(L, data.asString());
+ break;
+ }
+ }
+}
+
+/*****************************************************************************
+* LuaState class
+*****************************************************************************/
+LuaState::LuaState(script_finished_fn cb):
+ mCallback(cb),
+ mState(nullptr)
+{
+ initLuaState();
+}
+
+void LuaState::initLuaState()
+{
+ if (mState)
+ {
+ lua_close(mState);
+ }
+ mState = luaL_newstate();
+ luaL_openlibs(mState);
+ LuaFunction::init(mState);
+ // Try to make print() write to our log.
+ lua_register(mState, "print", LuaFunction::get("print_info"));
+ // We don't want to have to prefix require().
+ lua_register(mState, "require", LuaFunction::get("require"));
+}
+
+LuaState::~LuaState()
+{
+ // Did somebody call obtainListener() on this LuaState?
+ // That is, is there a LuaListener key in its registry?
+ LuaListener::destruct(getListener());
+
+ lua_close(mState);
+
+ if (mCallback)
+ {
+ // mError potentially set by previous checkLua() call(s)
+ mCallback(mError);
+ }
+}
+
+bool LuaState::checkLua(const std::string& desc, int r)
+{
+ if (r != LUA_OK)
+ {
+ mError = lua_tostring(mState, -1);
+ lua_pop(mState, 1);
+
+ LL_WARNS() << desc << ": " << mError << LL_ENDL;
+ return false;
+ }
+ return true;
+}
+
+std::pair<int, LLSD> LuaState::expr(const std::string& desc, const std::string& text)
+{
+ lluau::set_interrupts_counter(mState, 0);
+
+ lua_callbacks(mState)->interrupt = [](lua_State *L, int gc)
+ {
+ // skip if we're interrupting only for garbage collection
+ if (gc >= 0)
+ return;
+
+ LLCoros::checkStop();
+ lluau::check_interrupts_counter(L);
+ };
+
+ if (! checkLua(desc, lluau::dostring(mState, desc, text)))
+ {
+ LL_WARNS("Lua") << desc << " error: " << mError << LL_ENDL;
+ return { -1, mError };
+ }
+
+ // here we believe there was no error -- did the Lua fragment leave
+ // anything on the stack?
+ std::pair<int, LLSD> result{ lua_gettop(mState), {} };
+ LL_INFOS("Lua") << desc << " done, " << result.first << " results." << LL_ENDL;
+ if (result.first)
+ {
+ // aha, at least one entry on the stack!
+ if (result.first == 1)
+ {
+ // Don't forget that lua_tollsd() can throw Lua errors.
+ try
+ {
+ result.second = lua_tollsd(mState, 1);
+ }
+ catch (const std::exception& error)
+ {
+ LL_WARNS("Lua") << desc << " error converting result: " << error.what() << LL_ENDL;
+ // lua_tollsd() is designed to be called from a lua_function(),
+ // that is, from a C++ function called by Lua. In case of error,
+ // it throws a Lua error to be caught by the Lua runtime. expr()
+ // is a peculiar use case in which our C++ code is calling
+ // lua_tollsd() after return from the Lua runtime. We must catch
+ // the exception thrown for a Lua error, else it will propagate
+ // out to the main coroutine and terminate the viewer -- but since
+ // we instead of the Lua runtime catch it, our lua_State retains
+ // its internal error status. Any subsequent lua_pcall() calls
+ // with this lua_State will report error regardless of whether the
+ // chunk runs successfully. Get a new lua_State().
+ initLuaState();
+ return { -1, stringize(LLError::Log::classname(error), ": ", error.what()) };
+ }
+ }
+ else
+ {
+ // multiple entries on the stack
+ int index;
+ try
+ {
+ for (index = 1; index <= result.first; ++index)
+ {
+ result.second.append(lua_tollsd(mState, index));
+ }
+ }
+ catch (const std::exception& error)
+ {
+ LL_WARNS("Lua") << desc << " error converting result " << index << ": "
+ << error.what() << LL_ENDL;
+ // see above comments regarding lua_State's error status
+ initLuaState();
+ return { -1, stringize(LLError::Log::classname(error), ": ", error.what()) };
+ }
+ }
+ }
+ // pop everything
+ lua_settop(mState, 0);
+
+ // If we ran a script that loaded the fiber module, finish up with a call
+ // to fiber.run(). That allows a script to kick off some number of fibers,
+ // do some work on the main thread and then fall off the end of the script
+ // without explicitly appending a call to fiber.run(). run() ensures the
+ // rest of the fibers run to completion (or error).
+ luaL_checkstack(mState, 4, nullptr);
+ // Push _MODULES table on stack
+ luaL_findtable(mState, LUA_REGISTRYINDEX, "_MODULES", 1);
+ int index = lua_gettop(mState);
+ bool found = false;
+ // Did this chunk already require('fiber')? To find out, we must search
+ // the _MODULES table, because our require() implementation uses the
+ // pathname of the module file as the key. Push nil key to start.
+ lua_pushnil(mState);
+ while (lua_next(mState, index) != 0)
+ {
+ // key is at index -2, value at index -1
+ // "While traversing a table, do not call lua_tolstring directly on a
+ // key, unless you know that the key is actually a string. Recall that
+ // lua_tolstring changes the value at the given index; this confuses
+ // the next call to lua_next."
+ // https://www.lua.org/manual/5.1/manual.html#lua_next
+ if (lua_type(mState, -2) == LUA_TSTRING &&
+ fsyspath(lua_tostdstring(mState, -2)).stem() == "fiber")
+ {
+ found = true;
+ break;
+ }
+ // pop value so key is at top for lua_next()
+ lua_pop(mState, 1);
+ }
+ if (found)
+ {
+ // okay, index -1 is a table loaded from a file 'fiber.xxx' --
+ // does it have a function named 'run'?
+ auto run_type{ lua_getfield(mState, -1, "run") };
+ if (run_type == LUA_TFUNCTION)
+ {
+ // there's a fiber.run() function sitting on the top of the stack
+ // -- call it with no arguments, discarding anything it returns
+ LL_INFOS("Lua") << desc << " p.s. fiber.run()" << LL_ENDL;
+ if (! checkLua(desc, lua_pcall(mState, 0, 0, 0)))
+ {
+ LL_WARNS("Lua") << desc << " p.s. fiber.run() error: " << mError << LL_ENDL;
+ return { -1, mError };
+ }
+ LL_INFOS("Lua") << desc << " p.s. done." << LL_ENDL;
+ }
+ }
+ // pop everything again
+ lua_settop(mState, 0);
+ return result;
+}
+
+LuaListener::ptr_t LuaState::getListener(lua_State* L)
+{
+ // have to use one more stack slot
+ luaL_checkstack(L, 1, nullptr);
+ LuaListener::ptr_t listener;
+ // Does this lua_State already have a LuaListener stored in the registry?
+ auto keytype{ lua_getfield(L, LUA_REGISTRYINDEX, "event.listener") };
+ llassert(keytype == LUA_TNIL || keytype == LUA_TNUMBER);
+ if (keytype == LUA_TNUMBER)
+ {
+ // We do already have a LuaListener. Retrieve it.
+ int isint;
+ listener = LuaListener::getInstance(lua_tointegerx(L, -1, &isint));
+ // Nobody should have destroyed this LuaListener instance!
+ llassert(isint && listener);
+ }
+ // pop the int "event.listener" key
+ lua_pop(L, 1);
+ return listener;
+}
+
+LuaListener::ptr_t LuaState::obtainListener(lua_State* L)
+{
+ auto listener{ getListener(L) };
+ if (! listener)
+ {
+ // have to use one more stack slot
+ luaL_checkstack(L, 1, nullptr);
+ // instantiate a new LuaListener, binding the L state -- but use a
+ // no-op deleter: we do NOT want this ptr_t to manage the lifespan of
+ // this new LuaListener!
+ listener.reset(new LuaListener(L), [](LuaListener*){});
+ // set its key in the field where we'll look for it later
+ lua_pushinteger(L, listener->getKey());
+ lua_setfield(L, LUA_REGISTRYINDEX, "event.listener");
+ }
+ return listener;
+}
+
+/*****************************************************************************
+* LuaPopper class
+*****************************************************************************/
+LuaPopper::~LuaPopper()
+{
+ if (mCount)
+ {
+ lua_pop(mState, mCount);
+ }
+}
+
+/*****************************************************************************
+* LuaFunction class
+*****************************************************************************/
+LuaFunction::LuaFunction(const std::string_view& name, lua_CFunction function,
+ const std::string_view& helptext)
+{
+ const auto& [registry, lookup] = getState();
+ registry.emplace(name, Registry::mapped_type{ function, helptext });
+ lookup.emplace(function, name);
+}
+
+void LuaFunction::init(lua_State* L)
+{
+ const auto& [registry, lookup] = getRState();
+ luaL_checkstack(L, 2, nullptr);
+ // create LL table --
+ // it happens that we know exactly how many non-array members we want
+ lua_createtable(L, 0, int(narrow(lookup.size())));
+ int idx = lua_gettop(L);
+ for (const auto& [name, pair]: registry)
+ {
+ const auto& [funcptr, helptext] = pair;
+ // store funcptr in LL table with saved name
+ lua_pushcfunction(L, funcptr, name.c_str());
+ lua_setfield(L, idx, name.c_str());
+ }
+ // store LL in new lua_State's globals
+ lua_setglobal(L, "LL");
+}
+
+lua_CFunction LuaFunction::get(const std::string& key)
+{
+ // use find() instead of subscripting to avoid creating an entry for
+ // unknown key
+ const auto& [registry, lookup] = getState();
+ auto found{ registry.find(key) };
+ return (found == registry.end())? nullptr : found->second.first;
+}
+
+std::pair<LuaFunction::Registry&, LuaFunction::Lookup&> LuaFunction::getState()
+{
+ // use function-local statics to ensure they're initialized
+ static Registry registry;
+ static Lookup lookup;
+ return { registry, lookup };
+}
+
+/*****************************************************************************
+* source_path()
+*****************************************************************************/
+lua_function(source_path, "return the source path of the running Lua script")
+{
+ luaL_checkstack(L, 1, nullptr);
+ lua_pushstdstring(L, lluau::source_path(L).u8string());
+ return 1;
+}
+
+/*****************************************************************************
+* source_dir()
+*****************************************************************************/
+lua_function(source_dir, "return the source directory of the running Lua script")
+{
+ luaL_checkstack(L, 1, nullptr);
+ lua_pushstdstring(L, lluau::source_path(L).parent_path().u8string());
+ return 1;
+}
+
+/*****************************************************************************
+* abspath()
+*****************************************************************************/
+lua_function(abspath,
+ "for given filesystem path relative to running script, return absolute path")
+{
+ auto path{ lua_tostdstring(L, 1) };
+ lua_pop(L, 1);
+ lua_pushstdstring(L, (lluau::source_path(L).parent_path() / path).u8string());
+ return 1;
+}
+
+/*****************************************************************************
+* check_stop()
+*****************************************************************************/
+lua_function(check_stop, "ensure that a Lua script responds to viewer shutdown")
+{
+ LLCoros::checkStop();
+ return 0;
+}
+
+/*****************************************************************************
+* help()
+*****************************************************************************/
+lua_function(help,
+ "help(): list viewer's Lua functions\n"
+ "help(function): show help string for specific function")
+{
+ auto& luapump{ LLEventPumps::instance().obtain("lua output") };
+ const auto& [registry, lookup]{ LuaFunction::getRState() };
+ if (! lua_gettop(L))
+ {
+ // no arguments passed: list all lua_functions
+ for (const auto& [name, pair] : registry)
+ {
+ const auto& [fptr, helptext] = pair;
+ luapump.post(helptext);
+ }
+ }
+ else
+ {
+ // arguments passed: list each of the specified lua_functions
+ for (int idx = 1, top = lua_gettop(L); idx <= top; ++idx)
+ {
+ std::string arg{ stringize("<unknown ", lua_typename(L, lua_type(L, idx)), ">") };
+ if (lua_type(L, idx) == LUA_TSTRING)
+ {
+ arg = lua_tostdstring(L, idx);
+ }
+ else if (lua_type(L, idx) == LUA_TFUNCTION)
+ {
+ // Caller passed the actual function instead of its string
+ // name. A Lua function is an anonymous callable object; it
+ // has a name only by assigment. You can't ask Lua for a
+ // function's name, which is why our constructor maintains a
+ // reverse Lookup map.
+ auto function{ lua_tocfunction(L, idx) };
+ if (auto found = lookup.find(function); found != lookup.end())
+ {
+ // okay, pass found name to lookup below
+ arg = found->second;
+ }
+ }
+
+ if (auto found = registry.find(arg); found != registry.end())
+ {
+ luapump.post(found->second.second);
+ }
+ else
+ {
+ luapump.post(arg + ": NOT FOUND");
+ }
+ }
+ // pop all arguments
+ lua_settop(L, 0);
+ }
+ return 0; // void return
+}
+
+/*****************************************************************************
+* leaphelp()
+*****************************************************************************/
+lua_function(
+ leaphelp,
+ "leaphelp(): list viewer's LEAP APIs\n"
+ "leaphelp(api): show help for specific api string name")
+{
+ LLSD request;
+ int top{ lua_gettop(L) };
+ if (top)
+ {
+ request = llsd::map("op", "getAPI", "api", lua_tostdstring(L, 1));
+ }
+ else
+ {
+ request = llsd::map("op", "getAPIs");
+ }
+ // pop all args
+ lua_settop(L, 0);
+
+ auto& outpump{ LLEventPumps::instance().obtain("lua output") };
+ auto listener{ LuaState::obtainListener(L) };
+ LLEventStream replyPump("leaphelp", true);
+ // ask the LuaListener's LeapListener and suspend calling coroutine until reply
+ auto reply{ llcoro::postAndSuspend(request, listener->getCommandName(), replyPump, "reply") };
+ reply.erase("reqid");
+
+ if (auto error = reply["error"]; error.isString())
+ {
+ outpump.post(error.asString());
+ return 0;
+ }
+
+ if (top)
+ {
+ // caller wants a specific API
+ outpump.post(stringize(reply["name"].asString(), ":\n", reply["desc"].asString()));
+ for (const auto& opmap : llsd::inArray(reply["ops"]))
+ {
+ std::ostringstream reqstr;
+ auto req{ opmap["required"] };
+ if (req.isArray())
+ {
+ const char* sep = " (requires ";
+ for (const auto& [reqkey, reqval] : llsd::inMap(req))
+ {
+ reqstr << sep << reqkey;
+ sep = ", ";
+ }
+ reqstr << ")";
+ }
+ outpump.post(stringize("---- ", reply["key"].asString(), " == '",
+ opmap["name"].asString(), "'", reqstr.str(), ":\n",
+ opmap["desc"].asString()));
+ }
+ }
+ else
+ {
+ // caller wants a list of APIs
+ for (const auto& [name, data] : llsd::inMap(reply))
+ {
+ outpump.post(stringize("==== ", name, ":\n", data["desc"].asString()));
+ }
+ }
+ return 0; // void return
+}
+
+/*****************************************************************************
+* lua_what
+*****************************************************************************/
+std::ostream& operator<<(std::ostream& out, const lua_what& self)
+{
+ switch (lua_type(self.L, self.index))
+ {
+ case LUA_TNONE:
+ // distinguish acceptable but non-valid index
+ out << "none";
+ break;
+
+ case LUA_TNIL:
+ out << "nil";
+ break;
+
+ case LUA_TBOOLEAN:
+ {
+ auto oldflags { out.flags() };
+ out << std::boolalpha << lua_toboolean(self.L, self.index);
+ out.flags(oldflags);
+ break;
+ }
+
+ case LUA_TNUMBER:
+ out << lua_tonumber(self.L, self.index);
+ break;
+
+ case LUA_TSTRING:
+ out << std::quoted(lua_tostdstring(self.L, self.index));
+ break;
+
+ case LUA_TUSERDATA:
+ {
+ const S32 maxlen = 20;
+ S32 binlen{ lua_rawlen(self.L, self.index) };
+ LLSD::Binary binary(std::min(maxlen, binlen));
+ std::memcpy(binary.data(), lua_touserdata(self.L, self.index), binary.size());
+ out << LL::hexdump(binary);
+ if (binlen > maxlen)
+ {
+ out << "...(" << (binlen - maxlen) << " more)";
+ }
+ break;
+ }
+
+ case LUA_TLIGHTUSERDATA:
+ out << lua_touserdata(self.L, self.index);
+ break;
+
+ default:
+ // anything else, don't bother trying to report value, just type
+ out << lua_typename(self.L, lua_type(self.L, self.index));
+ break;
+ }
+ return out;
+}
+
+/*****************************************************************************
+* lua_stack
+*****************************************************************************/
+std::ostream& operator<<(std::ostream& out, const lua_stack& self)
+{
+ out << "stack: [";
+ const char* sep = "";
+ for (int index = 1; index <= lua_gettop(self.L); ++index)
+ {
+ out << sep << lua_what(self.L, index);
+ sep = ", ";
+ }
+ out << ']';
+ return out;
+}
diff --git a/indra/llcommon/lua_function.h b/indra/llcommon/lua_function.h
new file mode 100644
index 0000000000..e7013f92c6
--- /dev/null
+++ b/indra/llcommon/lua_function.h
@@ -0,0 +1,259 @@
+/**
+ * @file lua_function.h
+ * @author Nat Goodspeed
+ * @date 2024-02-05
+ * @brief Definitions useful for coding a new Luau entry point into C++
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Copyright (c) 2024, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LUA_FUNCTION_H)
+#define LL_LUA_FUNCTION_H
+
+#include "luau/luacode.h"
+#include "luau/lua.h"
+#include "luau/luaconf.h"
+#include "luau/lualib.h"
+#include "fsyspath.h"
+#include "stringize.h"
+#include <exception> // std::uncaught_exceptions()
+#include <memory> // std::shared_ptr
+#include <utility> // std::pair
+
+class LuaListener;
+
+namespace lluau
+{
+ // luau defines luaL_error() as void, but we want to use the Lua idiom of
+ // 'return error(...)'. Wrap luaL_error() in an int function.
+#if __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-security"
+#endif // __clang__
+ template<typename... Args>
+ int error(lua_State* L, const char* format, Args&&... args)
+ {
+ luaL_error(L, format, std::forward<Args>(args)...);
+#ifndef LL_MSVC
+ return 0;
+#endif
+ }
+#if __clang__
+#pragma clang diagnostic pop
+#endif // __clang__
+
+ // luau removed lua_dostring(), but since we perform the equivalent luau
+ // sequence in multiple places, encapsulate it. desc and text are strings
+ // rather than string_views because dostring() needs pointers to nul-
+ // terminated char arrays.
+ int dostring(lua_State* L, const std::string& desc, const std::string& text);
+ int loadstring(lua_State* L, const std::string& desc, const std::string& text);
+
+ fsyspath source_path(lua_State* L);
+
+ void set_interrupts_counter(lua_State *L, S32 counter);
+ void check_interrupts_counter(lua_State* L);
+} // namespace lluau
+
+std::string lua_tostdstring(lua_State* L, int index);
+void lua_pushstdstring(lua_State* L, const std::string& str);
+LLSD lua_tollsd(lua_State* L, int index);
+void lua_pushllsd(lua_State* L, const LLSD& data);
+
+/**
+ * RAII class to manage the lifespan of a lua_State
+ */
+class LuaState
+{
+public:
+ typedef std::function<void(std::string msg)> script_finished_fn;
+
+ LuaState(script_finished_fn cb={});
+
+ LuaState(const LuaState&) = delete;
+ LuaState& operator=(const LuaState&) = delete;
+
+ ~LuaState();
+
+ void initLuaState();
+
+ bool checkLua(const std::string& desc, int r);
+
+ // expr() is for when we want to capture any results left on the stack
+ // by a Lua expression, possibly including multiple return values.
+ // int < 0 means error, and LLSD::asString() is the error message.
+ // int == 0 with LLSD::isUndefined() means the Lua expression returned no
+ // results.
+ // int == 1 means the Lua expression returned one result.
+ // int > 1 with LLSD::isArray() means the Lua expression returned
+ // multiple results, represented as the entries of the array.
+ std::pair<int, LLSD> expr(const std::string& desc, const std::string& text);
+
+ operator lua_State*() const { return mState; }
+
+ // Return LuaListener for this LuaState if we already have one, else empty
+ // shared_ptr.
+ std::shared_ptr<LuaListener> getListener() { return getListener(mState); }
+ // Find or create LuaListener for this LuaState, returning its ptr_t.
+ std::shared_ptr<LuaListener> obtainListener() { return obtainListener(mState); }
+ // Return LuaListener for passed lua_State if we already have one, else
+ // empty shared_ptr.
+ static std::shared_ptr<LuaListener> getListener(lua_State* L);
+ // Find or create LuaListener for passed lua_State, returning its ptr_t.
+ static std::shared_ptr<LuaListener> obtainListener(lua_State* L);
+
+private:
+ script_finished_fn mCallback;
+ lua_State* mState;
+ std::string mError;
+};
+
+/**
+ * LuaPopper is an RAII struct whose role is to pop some number of entries
+ * from the Lua stack if the calling function exits early.
+ */
+struct LuaPopper
+{
+ LuaPopper(lua_State* L, int count):
+ mState(L),
+ mCount(count)
+ {}
+
+ LuaPopper(const LuaPopper&) = delete;
+ LuaPopper& operator=(const LuaPopper&) = delete;
+
+ ~LuaPopper();
+
+ void disarm() { set(0); }
+ void set(int count) { mCount = count; }
+
+ lua_State* mState;
+ int mCount;
+};
+
+/**
+ * LuaFunction is a base class containing a static registry of its static
+ * subclass call() methods. call() is NOT virtual: instead, each subclass
+ * constructor passes a pointer to its distinct call() method to the base-
+ * class constructor, along with a name by which to register that method.
+ *
+ * The init() method walks the registry and registers each such name with the
+ * passed lua_State.
+ */
+class LuaFunction
+{
+public:
+ LuaFunction(const std::string_view& name, lua_CFunction function,
+ const std::string_view& helptext);
+
+ static void init(lua_State* L);
+
+ static lua_CFunction get(const std::string& key);
+
+protected:
+ using Registry = std::map<std::string, std::pair<lua_CFunction, std::string>>;
+ using Lookup = std::map<lua_CFunction, std::string>;
+ static std::pair<const Registry&, const Lookup&> getRState() { return getState(); }
+
+private:
+ static std::pair<Registry&, Lookup&> getState();
+};
+
+/**
+ * lua_function(name, helptext) is a macro to facilitate defining C++ functions
+ * available to Lua. It defines a subclass of LuaFunction and declares a
+ * static instance of that subclass, thereby forcing the compiler to call its
+ * constructor at module initialization time. The constructor passes the
+ * stringized instance name to its LuaFunction base-class constructor, along
+ * with a pointer to the static subclass call() method. It then emits the
+ * call() method definition header, to be followed by a method body enclosed
+ * in curly braces as usual.
+ */
+#define lua_function(name, helptext) \
+static struct name##_luasub : public LuaFunction \
+{ \
+ name##_luasub(): LuaFunction(#name, &call, helptext) {} \
+ static int call(lua_State* L); \
+} name##_lua; \
+int name##_luasub::call(lua_State* L)
+// {
+// ... supply method body here, referencing 'L' ...
+// }
+
+// Usage: std::cout << lua_what(L, stackindex) << ...;
+// Reports on the Lua value found at the passed stackindex.
+// If cast to std::string, returns the corresponding string value.
+class lua_what
+{
+public:
+ lua_what(lua_State* state, int idx):
+ L(state),
+ index(idx)
+ {}
+
+ friend std::ostream& operator<<(std::ostream& out, const lua_what& self);
+
+ operator std::string() const { return stringize(*this); }
+
+private:
+ lua_State* L;
+ int index;
+};
+
+// Usage: std::cout << lua_stack(L) << ...;
+// Reports on the contents of the Lua stack.
+// If cast to std::string, returns the corresponding string value.
+class lua_stack
+{
+public:
+ lua_stack(lua_State* state):
+ L(state)
+ {}
+
+ friend std::ostream& operator<<(std::ostream& out, const lua_stack& self);
+
+ operator std::string() const { return stringize(*this); }
+
+private:
+ lua_State* L;
+};
+
+// adapted from indra/test/debug.h
+// can't generalize Debug::operator() target because it's a variadic template
+class LuaLog
+{
+public:
+ template <typename... ARGS>
+ LuaLog(lua_State* L, ARGS&&... args):
+ L(L),
+ mBlock(stringize(std::forward<ARGS>(args)...))
+ {
+ (*this)("entry ", lua_stack(L));
+ }
+
+ // non-copyable
+ LuaLog(const LuaLog&) = delete;
+ LuaLog& operator=(const LuaLog&) = delete;
+
+ ~LuaLog()
+ {
+ auto exceptional{ std::uncaught_exceptions()? "exceptional " : "" };
+ (*this)(exceptional, "exit ", lua_stack(L));
+ }
+
+ template <typename... ARGS>
+ void operator()(ARGS&&... args)
+ {
+ LL_INFOS("Lua") << mBlock << ' ';
+ stream_to(LL_CONT, std::forward<ARGS>(args)...);
+ LL_ENDL;
+ }
+
+private:
+ lua_State* L;
+ const std::string mBlock;
+};
+
+#endif /* ! defined(LL_LUA_FUNCTION_H) */
diff --git a/indra/llcommon/lualistener.cpp b/indra/llcommon/lualistener.cpp
new file mode 100644
index 0000000000..5c4989e891
--- /dev/null
+++ b/indra/llcommon/lualistener.cpp
@@ -0,0 +1,114 @@
+/**
+ * @file lualistener.cpp
+ * @author Nat Goodspeed
+ * @date 2024-02-06
+ * @brief Implementation for lualistener.
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Copyright (c) 2024, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lualistener.h"
+// STL headers
+// std headers
+#include <cstdlib> // std::rand()
+#include <cstring> // std::memcpy()
+// external library headers
+#include "luau/lua.h"
+// other Linden headers
+#include "llerror.h"
+#include "llleaplistener.h"
+#include "lua_function.h"
+
+const int MAX_QSIZE = 1000;
+
+std::ostream& operator<<(std::ostream& out, const LuaListener& self)
+{
+ return out << "LuaListener(" << self.getReplyName() << ", " << self.getCommandName() << ")";
+}
+
+LuaListener::LuaListener(lua_State* L):
+ super(getUniqueKey()),
+ mCoroName(LLCoros::getName()),
+ mListener(new LLLeapListener(
+ "LuaListener",
+ [this](const std::string& pump, const LLSD& data)
+ { return queueEvent(pump, data); })),
+ // Listen for shutdown events.
+ mShutdownConnection(
+ LLCoros::getStopListener(
+ "LuaState",
+ mCoroName,
+ [this](const LLSD&)
+ {
+ // If a Lua script is still blocked in getNext() during
+ // viewer shutdown, close the queue to wake up getNext().
+ mQueue.close();
+ }))
+{}
+
+LuaListener::~LuaListener()
+{}
+
+int LuaListener::getUniqueKey()
+{
+ // Find a random key that does NOT already correspond to a LuaListener
+ // instance. Passing a duplicate key to LLInstanceTracker would do Bad
+ // Things.
+ int key;
+ do
+ {
+ key = std::rand();
+ } while (LuaListener::getInstance(key));
+ // This is theoretically racy, if we were instantiating new
+ // LuaListeners on multiple threads. Don't.
+ return key;
+}
+
+std::string LuaListener::getReplyName() const
+{
+ return mListener->getReplyPump().getName();
+}
+
+std::string LuaListener::getCommandName() const
+{
+ return mListener->getPumpName();
+}
+
+bool LuaListener::queueEvent(const std::string& pump, const LLSD& data)
+{
+ // Our Lua script might be stalled, or just fail to retrieve events. Don't
+ // grow this queue indefinitely. But don't set MAX_QSIZE as the queue
+ // capacity or we'd block the post() call trying to propagate this event!
+ if (auto size = mQueue.size(); size > MAX_QSIZE)
+ {
+ LL_WARNS("Lua") << "LuaListener queue for " << getReplyName()
+ << " exceeds " << MAX_QSIZE << ": " << size
+ << " -- discarding event" << LL_ENDL;
+ }
+ else
+ {
+ mQueue.push(decltype(mQueue)::value_type(pump, data));
+ }
+ return false;
+}
+
+LuaListener::PumpData LuaListener::getNext()
+{
+ try
+ {
+ LLCoros::TempStatus status("get_event_next()");
+ return mQueue.pop();
+ }
+ catch (const LLThreadSafeQueueInterrupt&)
+ {
+ // mQueue has been closed. The only way that happens is when we detect
+ // viewer shutdown. Terminate the calling coroutine.
+ LLCoros::checkStop();
+ return {};
+ }
+}
diff --git a/indra/llcommon/lualistener.h b/indra/llcommon/lualistener.h
new file mode 100644
index 0000000000..85fb093cd6
--- /dev/null
+++ b/indra/llcommon/lualistener.h
@@ -0,0 +1,81 @@
+/**
+ * @file lualistener.h
+ * @author Nat Goodspeed
+ * @date 2024-02-06
+ * @brief Define LuaListener class
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Copyright (c) 2024, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LUALISTENER_H)
+#define LL_LUALISTENER_H
+
+#include "llevents.h"
+#include "llinstancetracker.h"
+#include "llsd.h"
+#include "llthreadsafequeue.h"
+#include <iosfwd> // std::ostream
+#include <memory> // std::unique_ptr
+#include <string>
+#include <utility> // std::pair
+
+struct lua_State;
+class LLLeapListener;
+
+/**
+ * LuaListener is based on LLLeap. It serves an analogous function.
+ *
+ * Each LuaListener instance has an int key, generated randomly to
+ * inconvenience malicious Lua scripts wanting to mess with others. The idea
+ * is that a given lua_State stores in its Registry:
+ * - "event.listener": the int key of the corresponding LuaListener, if any
+ * The original thought was that LuaListener would itself store the Lua
+ * function -- but surprisingly, there is no C/C++ type in the API that stores
+ * a Lua function.
+ *
+ * (We considered storing in "event.listener" the LuaListener pointer itself
+ * as a light userdata, but the problem would be if Lua code overwrote that.
+ * We want to prevent any Lua script from crashing the viewer, intentionally
+ * or otherwise. Safer to use a key lookup.)
+ *
+ * Like LLLeap, each LuaListener instance also has an associated
+ * LLLeapListener to respond to LLEventPump management commands.
+ */
+class LuaListener: public LLInstanceTracker<LuaListener, int>
+{
+ using super = LLInstanceTracker<LuaListener, int>;
+public:
+ LuaListener(lua_State* L);
+
+ LuaListener(const LuaListener&) = delete;
+ LuaListener& operator=(const LuaListener&) = delete;
+
+ ~LuaListener();
+
+ std::string getReplyName() const;
+ std::string getCommandName() const;
+
+ /**
+ * LuaListener enqueues reply events from its LLLeapListener on mQueue.
+ * Call getNext() to retrieve the next such event. Blocks the calling
+ * coroutine if the queue is empty.
+ */
+ using PumpData = std::pair<std::string, LLSD>;
+ PumpData getNext();
+
+ friend std::ostream& operator<<(std::ostream& out, const LuaListener& self);
+
+private:
+ static int getUniqueKey();
+ bool queueEvent(const std::string& pump, const LLSD& data);
+
+ LLThreadSafeQueue<PumpData> mQueue;
+
+ std::string mCoroName;
+ std::unique_ptr<LLLeapListener> mListener;
+ LLTempBoundListener mShutdownConnection;
+};
+
+#endif /* ! defined(LL_LUALISTENER_H) */
diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h
index 536a18abc1..63d44a7272 100644
--- a/indra/llcommon/stringize.h
+++ b/indra/llcommon/stringize.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-12-17
* @brief stringize(item) template function and STRINGIZE(expression) macro
- *
+ *
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -88,13 +88,13 @@ struct gstringize_impl
};
// partially specialize for a single STRING argument -
-// note that ll_convert<T>(T) already handles the trivial case
+// note that ll_convert_to<T>(T) already handles the trivial case
template <typename OUTCHAR, typename INCHAR>
struct gstringize_impl<OUTCHAR, std::basic_string<INCHAR>>
{
auto operator()(const std::basic_string<INCHAR>& arg)
{
- return ll_convert<std::basic_string<OUTCHAR>>(arg);
+ return ll_convert_to<std::basic_string<OUTCHAR>>(arg);
}
};
@@ -105,7 +105,7 @@ struct gstringize_impl<OUTCHAR, INCHAR*>
{
auto operator()(const INCHAR* arg)
{
- return ll_convert<std::basic_string<OUTCHAR>>(arg);
+ return ll_convert_to<std::basic_string<OUTCHAR>>(arg);
}
};
diff --git a/indra/llcommon/tests/StringVec.h b/indra/llcommon/tests/StringVec.h
index 4311cba992..761956a012 100644
--- a/indra/llcommon/tests/StringVec.h
+++ b/indra/llcommon/tests/StringVec.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-02-24
* @brief Extend TUT ensure_equals() to handle std::vector<std::string>
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
@@ -18,6 +18,16 @@
typedef std::vector<std::string> StringVec;
+#if defined(LL_LLTUT_H)
+// Modern compilers require us to define operator<<(std::ostream&, StringVec)
+// before the definition of the ensure() template that engages it. The error
+// stating that the compiler can't find a viable operator<<() is so perplexing
+// that even though I've obviously hit it a couple times before, a new
+// instance still caused much head-scratching. This warning is intended to
+// demystify any inadvertent future recurrence.
+#warning "StringVec.h must be #included BEFORE lltut.h for ensure() to work"
+#endif
+
std::ostream& operator<<(std::ostream& out, const StringVec& strings)
{
out << '(';
diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp
index a3c54ffaa2..e7674fde37 100644
--- a/indra/llcommon/tests/lleventcoro_test.cpp
+++ b/indra/llcommon/tests/lleventcoro_test.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-04-22
* @brief Test for coroutine.
- *
+ *
* $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$
*/
@@ -113,14 +113,13 @@ namespace tut
void test_data::explicit_wait(std::shared_ptr<LLCoros::Promise<std::string>>& cbp)
{
- BEGIN
- {
- mSync.bump();
- // The point of this test is to verify / illustrate suspending a
- // coroutine for something other than an LLEventPump. In other
- // words, this shows how to adapt to any async operation that
- // provides a callback-style notification (and prove that it
- // works).
+ DEBUG;
+ mSync.bump();
+ // The point of this test is to verify / illustrate suspending a
+ // coroutine for something other than an LLEventPump. In other
+ // words, this shows how to adapt to any async operation that
+ // provides a callback-style notification (and prove that it
+ // works).
// Perhaps we would send a request to a remote server and arrange
// for cbp->set_value() to be called on response.
@@ -130,13 +129,11 @@ namespace tut
cbp = std::make_shared<LLCoros::Promise<std::string>>();
LLCoros::Future<std::string> future = LLCoros::getFuture(*cbp);
- // calling get() on the future causes us to suspend
- debug("about to suspend");
- stringdata = future.get();
- mSync.bump();
- ensure_equals("Got it", stringdata, "received");
- }
- END
+ // calling get() on the future causes us to suspend
+ debug("about to suspend");
+ stringdata = future.get();
+ mSync.bump();
+ ensure_equals("Got it", stringdata, "received");
}
template<> template<>
@@ -163,13 +160,9 @@ namespace tut
void test_data::waitForEventOn1()
{
- BEGIN
- {
- mSync.bump();
- result = suspendUntilEventOn("source");
- mSync.bump();
- }
- END
+ mSync.bump();
+ result = suspendUntilEventOn("source");
+ mSync.bump();
}
template<> template<>
@@ -189,15 +182,11 @@ namespace tut
void test_data::coroPump()
{
- BEGIN
- {
- mSync.bump();
- LLCoroEventPump waiter;
- replyName = waiter.getName();
- result = waiter.suspend();
- mSync.bump();
- }
- END
+ mSync.bump();
+ LLCoroEventPump waiter;
+ replyName = waiter.getName();
+ result = waiter.suspend();
+ mSync.bump();
}
template<> template<>
@@ -217,16 +206,12 @@ namespace tut
void test_data::postAndWait1()
{
- BEGIN
- {
- mSync.bump();
- result = postAndSuspend(LLSDMap("value", 17), // request event
- immediateAPI.getPump(), // requestPump
- "reply1", // replyPump
- "reply"); // request["reply"] = name
- mSync.bump();
- }
- END
+ mSync.bump();
+ result = postAndSuspend(LLSDMap("value", 17), // request event
+ immediateAPI.getPump(), // requestPump
+ "reply1", // replyPump
+ "reply"); // request["reply"] = name
+ mSync.bump();
}
template<> template<>
@@ -240,15 +225,11 @@ namespace tut
void test_data::coroPumpPost()
{
- BEGIN
- {
- mSync.bump();
- LLCoroEventPump waiter;
- result = waiter.postAndSuspend(LLSDMap("value", 17),
- immediateAPI.getPump(), "reply");
- mSync.bump();
- }
- END
+ mSync.bump();
+ LLCoroEventPump waiter;
+ result = waiter.postAndSuspend(LLSDMap("value", 17),
+ immediateAPI.getPump(), "reply");
+ mSync.bump();
}
template<> template<>
diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp
index a99acba848..244cd07ac9 100644
--- a/indra/llcommon/tests/lleventdispatcher_test.cpp
+++ b/indra/llcommon/tests/lleventdispatcher_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2011-01-20
* @brief Test for lleventdispatcher.
- *
+ *
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Copyright (c) 2011, Linden Research, Inc.
* $/LicenseInfo$
@@ -17,13 +17,13 @@
// std headers
// external library headers
// other Linden headers
+#include "StringVec.h"
#include "../test/lltut.h"
#include "lleventfilter.h"
#include "llsd.h"
#include "llsdutil.h"
#include "llevents.h"
#include "stringize.h"
-#include "StringVec.h"
#include "tests/wrapllerrs.h"
#include "../test/catch_and_store_what_in.h"
#include "../test/debug.h"
@@ -470,7 +470,7 @@ namespace tut
params["a"], "\n"
"params[\"b\"]:\n",
params["b"]);
- // default LLSD::Binary value
+ // default LLSD::Binary value
std::vector<U8> binary;
for (size_t ix = 0, h = 0xaa; ix < 6; ++ix, h += 0x11)
{
diff --git a/indra/llcommon/tests/lleventfilter_test.cpp b/indra/llcommon/tests/lleventfilter_test.cpp
index a01d7fe415..ed7cb56506 100644
--- a/indra/llcommon/tests/lleventfilter_test.cpp
+++ b/indra/llcommon/tests/lleventfilter_test.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-03-06
* @brief Test for lleventfilter.
- *
+ *
* $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$
*/
@@ -34,10 +34,10 @@
// std headers
// external library headers
// other Linden headers
+#include "listener.h"
#include "../test/lltut.h"
#include "stringize.h"
#include "llsdutil.h"
-#include "listener.h"
#include "tests/wrapllerrs.h"
#include <typeinfo>
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index fa48bcdefd..6fe9e3446f 100644
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-02-21
* @brief Test for llleap.
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
@@ -18,6 +18,7 @@
#include <functional>
// external library headers
// other Linden headers
+#include "StringVec.h"
#include "../test/lltut.h"
#include "../test/namedtempfile.h"
#include "../test/catch_and_store_what_in.h"
@@ -26,7 +27,6 @@
#include "llprocess.h"
#include "llstring.h"
#include "stringize.h"
-#include "StringVec.h"
#if defined(LL_WINDOWS)
#define sleep(secs) _sleep((secs) * 1000)
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 56fdc51e82..730731a927 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsdserialize_test.cpp
* @date 2006-04
* @brief LLSDSerialize unit tests
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -52,11 +52,11 @@ typedef U32 uint32_t;
#include "llformat.h"
#include "llmemorystream.h"
-#include "../test/hexdump.h"
+#include "hexdump.h"
+#include "StringVec.h"
#include "../test/lltut.h"
#include "../test/namedtempfile.h"
#include "stringize.h"
-#include "StringVec.h"
#include <functional>
typedef std::function<void(const LLSD& data, std::ostream& str)> FormatterFunction;
@@ -64,313 +64,313 @@ typedef std::function<bool(std::istream& istr, LLSD& data, llssize max_bytes)> P
std::vector<U8> string_to_vector(const std::string& str)
{
- return std::vector<U8>(str.begin(), str.end());
+ return std::vector<U8>(str.begin(), str.end());
}
namespace tut
{
- struct sd_xml_data
- {
- sd_xml_data()
- {
- mFormatter = new LLSDXMLFormatter;
- }
- LLSD mSD;
- LLPointer<LLSDXMLFormatter> mFormatter;
- void xml_test(const char* name, const std::string& expected)
- {
- std::ostringstream ostr;
- mFormatter->format(mSD, ostr);
- ensure_equals(name, ostr.str(), expected);
- }
- };
-
- typedef test_group<sd_xml_data> sd_xml_test;
- typedef sd_xml_test::object sd_xml_object;
- tut::sd_xml_test sd_xml_stream("LLSDXMLFormatter");
-
- template<> template<>
- void sd_xml_object::test<1>()
- {
- // random atomic tests
- std::string expected;
-
- expected = "<llsd><undef /></llsd>\n";
- xml_test("undef", expected);
-
- mSD = 3463;
- expected = "<llsd><integer>3463</integer></llsd>\n";
- xml_test("integer", expected);
-
- mSD = "";
- expected = "<llsd><string /></llsd>\n";
- xml_test("empty string", expected);
-
- mSD = "foobar";
- expected = "<llsd><string>foobar</string></llsd>\n";
- xml_test("string", expected);
-
- mSD = LLUUID::null;
- expected = "<llsd><uuid /></llsd>\n";
- xml_test("null uuid", expected);
-
- mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed");
- expected = "<llsd><uuid>c96f9b1e-f589-4100-9774-d98643ce0bed</uuid></llsd>\n";
- xml_test("uuid", expected);
-
- mSD = LLURI("https://secondlife.com/login");
- expected = "<llsd><uri>https://secondlife.com/login</uri></llsd>\n";
- xml_test("uri", expected);
-
- mSD = LLDate("2006-04-24T16:11:33Z");
- expected = "<llsd><date>2006-04-24T16:11:33Z</date></llsd>\n";
- xml_test("date", expected);
-
- // Generated by: echo -n 'hello' | openssl enc -e -base64
- std::vector<U8> hello;
- hello.push_back('h');
- hello.push_back('e');
- hello.push_back('l');
- hello.push_back('l');
- hello.push_back('o');
- mSD = hello;
- expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
- xml_test("binary", expected);
- }
-
- template<> template<>
- void sd_xml_object::test<2>()
- {
- // tests with boolean values.
- std::string expected;
-
- mFormatter->boolalpha(true);
- mSD = true;
- expected = "<llsd><boolean>true</boolean></llsd>\n";
- xml_test("bool alpha true", expected);
- mSD = false;
- expected = "<llsd><boolean>false</boolean></llsd>\n";
- xml_test("bool alpha false", expected);
-
- mFormatter->boolalpha(false);
- mSD = true;
- expected = "<llsd><boolean>1</boolean></llsd>\n";
- xml_test("bool true", expected);
- mSD = false;
- expected = "<llsd><boolean>0</boolean></llsd>\n";
- xml_test("bool false", expected);
- }
-
-
- template<> template<>
- void sd_xml_object::test<3>()
- {
- // tests with real values.
- std::string expected;
-
- mFormatter->realFormat("%.2f");
- mSD = 1.0;
- expected = "<llsd><real>1.00</real></llsd>\n";
- xml_test("real 1", expected);
-
- mSD = -34379.0438;
- expected = "<llsd><real>-34379.04</real></llsd>\n";
- xml_test("real reduced precision", expected);
- mFormatter->realFormat("%.4f");
- expected = "<llsd><real>-34379.0438</real></llsd>\n";
- xml_test("higher precision", expected);
-
- mFormatter->realFormat("%.0f");
- mSD = 0.0;
- expected = "<llsd><real>0</real></llsd>\n";
- xml_test("no decimal 0", expected);
- mSD = 3287.4387;
- expected = "<llsd><real>3287</real></llsd>\n";
- xml_test("no decimal real number", expected);
- }
-
- template<> template<>
- void sd_xml_object::test<4>()
- {
- // tests with arrays
- std::string expected;
-
- mSD = LLSD::emptyArray();
- expected = "<llsd><array /></llsd>\n";
- xml_test("empty array", expected);
-
- mSD.append(LLSD());
- expected = "<llsd><array><undef /></array></llsd>\n";
- xml_test("1 element array", expected);
-
- mSD.append(1);
- expected = "<llsd><array><undef /><integer>1</integer></array></llsd>\n";
- xml_test("2 element array", expected);
- }
-
- template<> template<>
- void sd_xml_object::test<5>()
- {
- // tests with arrays
- std::string expected;
-
- mSD = LLSD::emptyMap();
- expected = "<llsd><map /></llsd>\n";
- xml_test("empty map", expected);
-
- mSD["foo"] = "bar";
- expected = "<llsd><map><key>foo</key><string>bar</string></map></llsd>\n";
- xml_test("1 element map", expected);
-
- mSD["baz"] = LLSD();
- expected = "<llsd><map><key>baz</key><undef /><key>foo</key><string>bar</string></map></llsd>\n";
- xml_test("2 element map", expected);
- }
-
- template<> template<>
- void sd_xml_object::test<6>()
- {
- // tests with binary
- std::string expected;
-
- // Generated by: echo -n 'hello' | openssl enc -e -base64
- mSD = string_to_vector("hello");
- expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
- xml_test("binary", expected);
-
- mSD = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
- expected = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
- xml_test("binary", expected);
- }
-
- class TestLLSDSerializeData
- {
- public:
- TestLLSDSerializeData();
- ~TestLLSDSerializeData();
-
- void doRoundTripTests(const std::string&);
- void checkRoundTrip(const std::string&, const LLSD& v);
-
- void setFormatterParser(LLPointer<LLSDFormatter> formatter, LLPointer<LLSDParser> parser)
- {
- mFormatter = [formatter](const LLSD& data, std::ostream& str)
- {
- formatter->format(data, str);
- };
- // this lambda must be mutable since otherwise the bound 'parser'
- // is assumed to point to a const LLSDParser
- mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes) mutable
- {
- // reset() call is needed since test code re-uses parser object
- parser->reset();
- return (parser->parse(istr, data, max_bytes) > 0);
- };
- }
-
- void setParser(bool (*parser)(LLSD&, std::istream&, llssize))
- {
- // why does LLSDSerialize::deserialize() reverse the parse() params??
- mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes)
- {
- return parser(data, istr, max_bytes);
- };
- }
-
- FormatterFunction mFormatter;
- ParserFunction mParser;
- };
-
- TestLLSDSerializeData::TestLLSDSerializeData()
- {
- }
-
- TestLLSDSerializeData::~TestLLSDSerializeData()
- {
- }
-
- void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v)
- {
- std::stringstream stream;
- mFormatter(v, stream);
- //LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL;
- LLSD w;
- mParser(stream, w, stream.str().size());
-
- try
- {
- ensure_equals(msg, w, v);
- }
- catch (...)
- {
- std::cerr << "the serialized string was:" << std::endl;
- std::cerr << stream.str() << std::endl;
- throw;
- }
- }
-
- static void fillmap(LLSD& root, U32 width, U32 depth)
- {
- if(depth == 0)
- {
- root["foo"] = "bar";
- return;
- }
-
- for(U32 i = 0; i < width; ++i)
- {
- std::string key = llformat("child %d", i);
- root[key] = LLSD::emptyMap();
- fillmap(root[key], width, depth - 1);
- }
- }
-
- void TestLLSDSerializeData::doRoundTripTests(const std::string& msg)
- {
- LLSD v;
- checkRoundTrip(msg + " undefined", v);
-
- v = true;
- checkRoundTrip(msg + " true bool", v);
-
- v = false;
- checkRoundTrip(msg + " false bool", v);
-
- v = 1;
- checkRoundTrip(msg + " positive int", v);
-
- v = 0;
- checkRoundTrip(msg + " zero int", v);
-
- v = -1;
- checkRoundTrip(msg + " negative int", v);
-
- v = 1234.5f;
- checkRoundTrip(msg + " positive float", v);
-
- v = 0.0f;
- checkRoundTrip(msg + " zero float", v);
-
- v = -1234.5f;
- checkRoundTrip(msg + " negative float", v);
-
- // FIXME: need a NaN test
-
- v = LLUUID::null;
- checkRoundTrip(msg + " null uuid", v);
-
- LLUUID newUUID;
- newUUID.generate();
- v = newUUID;
- checkRoundTrip(msg + " new uuid", v);
-
- v = "";
- checkRoundTrip(msg + " empty string", v);
-
- v = "some string";
- checkRoundTrip(msg + " non-empty string", v);
-
- v =
+ struct sd_xml_data
+ {
+ sd_xml_data()
+ {
+ mFormatter = new LLSDXMLFormatter;
+ }
+ LLSD mSD;
+ LLPointer<LLSDXMLFormatter> mFormatter;
+ void xml_test(const char* name, const std::string& expected)
+ {
+ std::ostringstream ostr;
+ mFormatter->format(mSD, ostr);
+ ensure_equals(name, ostr.str(), expected);
+ }
+ };
+
+ typedef test_group<sd_xml_data> sd_xml_test;
+ typedef sd_xml_test::object sd_xml_object;
+ tut::sd_xml_test sd_xml_stream("LLSDXMLFormatter");
+
+ template<> template<>
+ void sd_xml_object::test<1>()
+ {
+ // random atomic tests
+ std::string expected;
+
+ expected = "<llsd><undef /></llsd>\n";
+ xml_test("undef", expected);
+
+ mSD = 3463;
+ expected = "<llsd><integer>3463</integer></llsd>\n";
+ xml_test("integer", expected);
+
+ mSD = "";
+ expected = "<llsd><string /></llsd>\n";
+ xml_test("empty string", expected);
+
+ mSD = "foobar";
+ expected = "<llsd><string>foobar</string></llsd>\n";
+ xml_test("string", expected);
+
+ mSD = LLUUID::null;
+ expected = "<llsd><uuid /></llsd>\n";
+ xml_test("null uuid", expected);
+
+ mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed");
+ expected = "<llsd><uuid>c96f9b1e-f589-4100-9774-d98643ce0bed</uuid></llsd>\n";
+ xml_test("uuid", expected);
+
+ mSD = LLURI("https://secondlife.com/login");
+ expected = "<llsd><uri>https://secondlife.com/login</uri></llsd>\n";
+ xml_test("uri", expected);
+
+ mSD = LLDate("2006-04-24T16:11:33Z");
+ expected = "<llsd><date>2006-04-24T16:11:33Z</date></llsd>\n";
+ xml_test("date", expected);
+
+ // Generated by: echo -n 'hello' | openssl enc -e -base64
+ std::vector<U8> hello;
+ hello.push_back('h');
+ hello.push_back('e');
+ hello.push_back('l');
+ hello.push_back('l');
+ hello.push_back('o');
+ mSD = hello;
+ expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+ xml_test("binary", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<2>()
+ {
+ // tests with boolean values.
+ std::string expected;
+
+ mFormatter->boolalpha(true);
+ mSD = true;
+ expected = "<llsd><boolean>true</boolean></llsd>\n";
+ xml_test("bool alpha true", expected);
+ mSD = false;
+ expected = "<llsd><boolean>false</boolean></llsd>\n";
+ xml_test("bool alpha false", expected);
+
+ mFormatter->boolalpha(false);
+ mSD = true;
+ expected = "<llsd><boolean>1</boolean></llsd>\n";
+ xml_test("bool true", expected);
+ mSD = false;
+ expected = "<llsd><boolean>0</boolean></llsd>\n";
+ xml_test("bool false", expected);
+ }
+
+
+ template<> template<>
+ void sd_xml_object::test<3>()
+ {
+ // tests with real values.
+ std::string expected;
+
+ mFormatter->realFormat("%.2f");
+ mSD = 1.0;
+ expected = "<llsd><real>1.00</real></llsd>\n";
+ xml_test("real 1", expected);
+
+ mSD = -34379.0438;
+ expected = "<llsd><real>-34379.04</real></llsd>\n";
+ xml_test("real reduced precision", expected);
+ mFormatter->realFormat("%.4f");
+ expected = "<llsd><real>-34379.0438</real></llsd>\n";
+ xml_test("higher precision", expected);
+
+ mFormatter->realFormat("%.0f");
+ mSD = 0.0;
+ expected = "<llsd><real>0</real></llsd>\n";
+ xml_test("no decimal 0", expected);
+ mSD = 3287.4387;
+ expected = "<llsd><real>3287</real></llsd>\n";
+ xml_test("no decimal real number", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<4>()
+ {
+ // tests with arrays
+ std::string expected;
+
+ mSD = LLSD::emptyArray();
+ expected = "<llsd><array /></llsd>\n";
+ xml_test("empty array", expected);
+
+ mSD.append(LLSD());
+ expected = "<llsd><array><undef /></array></llsd>\n";
+ xml_test("1 element array", expected);
+
+ mSD.append(1);
+ expected = "<llsd><array><undef /><integer>1</integer></array></llsd>\n";
+ xml_test("2 element array", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<5>()
+ {
+ // tests with arrays
+ std::string expected;
+
+ mSD = LLSD::emptyMap();
+ expected = "<llsd><map /></llsd>\n";
+ xml_test("empty map", expected);
+
+ mSD["foo"] = "bar";
+ expected = "<llsd><map><key>foo</key><string>bar</string></map></llsd>\n";
+ xml_test("1 element map", expected);
+
+ mSD["baz"] = LLSD();
+ expected = "<llsd><map><key>baz</key><undef /><key>foo</key><string>bar</string></map></llsd>\n";
+ xml_test("2 element map", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<6>()
+ {
+ // tests with binary
+ std::string expected;
+
+ // Generated by: echo -n 'hello' | openssl enc -e -base64
+ mSD = string_to_vector("hello");
+ expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+ xml_test("binary", expected);
+
+ mSD = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+ expected = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+ xml_test("binary", expected);
+ }
+
+ class TestLLSDSerializeData
+ {
+ public:
+ TestLLSDSerializeData();
+ ~TestLLSDSerializeData();
+
+ void doRoundTripTests(const std::string&);
+ void checkRoundTrip(const std::string&, const LLSD& v);
+
+ void setFormatterParser(LLPointer<LLSDFormatter> formatter, LLPointer<LLSDParser> parser)
+ {
+ mFormatter = [formatter](const LLSD& data, std::ostream& str)
+ {
+ formatter->format(data, str);
+ };
+ // this lambda must be mutable since otherwise the bound 'parser'
+ // is assumed to point to a const LLSDParser
+ mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes) mutable
+ {
+ // reset() call is needed since test code re-uses parser object
+ parser->reset();
+ return (parser->parse(istr, data, max_bytes) > 0);
+ };
+ }
+
+ void setParser(bool (*parser)(LLSD&, std::istream&, llssize))
+ {
+ // why does LLSDSerialize::deserialize() reverse the parse() params??
+ mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes)
+ {
+ return parser(data, istr, max_bytes);
+ };
+ }
+
+ FormatterFunction mFormatter;
+ ParserFunction mParser;
+ };
+
+ TestLLSDSerializeData::TestLLSDSerializeData()
+ {
+ }
+
+ TestLLSDSerializeData::~TestLLSDSerializeData()
+ {
+ }
+
+ void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v)
+ {
+ std::stringstream stream;
+ mFormatter(v, stream);
+ //LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL;
+ LLSD w;
+ mParser(stream, w, stream.str().size());
+
+ try
+ {
+ ensure_equals(msg, w, v);
+ }
+ catch (...)
+ {
+ std::cerr << "the serialized string was:" << std::endl;
+ std::cerr << stream.str() << std::endl;
+ throw;
+ }
+ }
+
+ static void fillmap(LLSD& root, U32 width, U32 depth)
+ {
+ if(depth == 0)
+ {
+ root["foo"] = "bar";
+ return;
+ }
+
+ for(U32 i = 0; i < width; ++i)
+ {
+ std::string key = llformat("child %d", i);
+ root[key] = LLSD::emptyMap();
+ fillmap(root[key], width, depth - 1);
+ }
+ }
+
+ void TestLLSDSerializeData::doRoundTripTests(const std::string& msg)
+ {
+ LLSD v;
+ checkRoundTrip(msg + " undefined", v);
+
+ v = true;
+ checkRoundTrip(msg + " true bool", v);
+
+ v = false;
+ checkRoundTrip(msg + " false bool", v);
+
+ v = 1;
+ checkRoundTrip(msg + " positive int", v);
+
+ v = 0;
+ checkRoundTrip(msg + " zero int", v);
+
+ v = -1;
+ checkRoundTrip(msg + " negative int", v);
+
+ v = 1234.5f;
+ checkRoundTrip(msg + " positive float", v);
+
+ v = 0.0f;
+ checkRoundTrip(msg + " zero float", v);
+
+ v = -1234.5f;
+ checkRoundTrip(msg + " negative float", v);
+
+ // FIXME: need a NaN test
+
+ v = LLUUID::null;
+ checkRoundTrip(msg + " null uuid", v);
+
+ LLUUID newUUID;
+ newUUID.generate();
+ v = newUUID;
+ checkRoundTrip(msg + " new uuid", v);
+
+ v = "";
+ checkRoundTrip(msg + " empty string", v);
+
+ v = "some string";
+ checkRoundTrip(msg + " non-empty string", v);
+
+ v =
"Second Life is a 3-D virtual world entirely built and owned by its residents. "
"Since opening to the public in 2003, it has grown explosively and today is "
"inhabited by nearly 100,000 people from around the globe.\n"
@@ -390,437 +390,437 @@ namespace tut
"currency exchanges.\n"
"\n"
"Welcome to Second Life. We look forward to seeing you in-world!\n"
- ;
- checkRoundTrip(msg + " long string", v);
-
- static const U32 block_size = 0x000020;
- for (U32 block = 0x000000; block <= 0x10ffff; block += block_size)
- {
- std::ostringstream out;
-
- for (U32 c = block; c < block + block_size; ++c)
- {
- if (c <= 0x000001f
- && c != 0x000009
- && c != 0x00000a)
- {
- // see XML standard, sections 2.2 and 4.1
- continue;
- }
- if (0x00d800 <= c && c <= 0x00dfff) { continue; }
- if (0x00fdd0 <= c && c <= 0x00fdef) { continue; }
- if ((c & 0x00fffe) == 0x00fffe) { continue; }
- // see Unicode standard, section 15.8
-
- if (c <= 0x00007f)
- {
- out << (char)(c & 0x7f);
- }
- else if (c <= 0x0007ff)
- {
- out << (char)(0xc0 | ((c >> 6) & 0x1f));
- out << (char)(0x80 | ((c >> 0) & 0x3f));
- }
- else if (c <= 0x00ffff)
- {
- out << (char)(0xe0 | ((c >> 12) & 0x0f));
- out << (char)(0x80 | ((c >> 6) & 0x3f));
- out << (char)(0x80 | ((c >> 0) & 0x3f));
- }
- else
- {
- out << (char)(0xf0 | ((c >> 18) & 0x07));
- out << (char)(0x80 | ((c >> 12) & 0x3f));
- out << (char)(0x80 | ((c >> 6) & 0x3f));
- out << (char)(0x80 | ((c >> 0) & 0x3f));
- }
- }
-
- v = out.str();
-
- std::ostringstream blockmsg;
- blockmsg << msg << " unicode string block 0x" << std::hex << block;
- checkRoundTrip(blockmsg.str(), v);
- }
-
- LLDate epoch;
- v = epoch;
- checkRoundTrip(msg + " epoch date", v);
-
- LLDate aDay("2002-12-07T05:07:15.00Z");
- v = aDay;
- checkRoundTrip(msg + " date", v);
-
- LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
- v = path;
- checkRoundTrip(msg + " url", v);
-
- const char source[] = "it must be a blue moon again";
- std::vector<U8> data;
- // note, includes terminating '\0'
- copy(&source[0], &source[sizeof(source)], back_inserter(data));
-
- v = data;
- checkRoundTrip(msg + " binary", v);
-
- v = LLSD::emptyMap();
- checkRoundTrip(msg + " empty map", v);
-
- v = LLSD::emptyMap();
- v["name"] = "luke"; //v.insert("name", "luke");
- v["age"] = 3; //v.insert("age", 3);
- checkRoundTrip(msg + " map", v);
-
- v.clear();
- v["a"]["1"] = true;
- v["b"]["0"] = false;
- checkRoundTrip(msg + " nested maps", v);
-
- v = LLSD::emptyArray();
- checkRoundTrip(msg + " empty array", v);
-
- v = LLSD::emptyArray();
- v.append("ali");
- v.append(28);
- checkRoundTrip(msg + " array", v);
-
- v.clear();
- v[0][0] = true;
- v[1][0] = false;
- checkRoundTrip(msg + " nested arrays", v);
-
- v = LLSD::emptyMap();
- fillmap(v, 10, 3); // 10^6 maps
- checkRoundTrip(msg + " many nested maps", v);
- }
-
- typedef tut::test_group<TestLLSDSerializeData> TestLLSDSerializeGroup;
- typedef TestLLSDSerializeGroup::object TestLLSDSerializeObject;
- TestLLSDSerializeGroup gTestLLSDSerializeGroup("llsd serialization");
-
- template<> template<>
- void TestLLSDSerializeObject::test<1>()
- {
- setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY),
- new LLSDNotationParser());
- doRoundTripTests("pretty binary notation serialization");
- }
-
- template<> template<>
- void TestLLSDSerializeObject::test<2>()
- {
- setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
- new LLSDNotationParser());
- doRoundTripTests("raw binary notation serialization");
- }
-
- template<> template<>
- void TestLLSDSerializeObject::test<3>()
- {
- setFormatterParser(new LLSDXMLFormatter(), new LLSDXMLParser());
- doRoundTripTests("xml serialization");
- }
-
- template<> template<>
- void TestLLSDSerializeObject::test<4>()
- {
- setFormatterParser(new LLSDBinaryFormatter(), new LLSDBinaryParser());
- doRoundTripTests("binary serialization");
- }
-
- template<> template<>
- void TestLLSDSerializeObject::test<5>()
- {
- mFormatter = [](const LLSD& sd, std::ostream& str)
- {
- LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_BINARY);
- };
- setParser(LLSDSerialize::deserialize);
- doRoundTripTests("serialize(LLSD_BINARY)");
- };
-
- template<> template<>
- void TestLLSDSerializeObject::test<6>()
- {
- mFormatter = [](const LLSD& sd, std::ostream& str)
- {
- LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_XML);
- };
- setParser(LLSDSerialize::deserialize);
- doRoundTripTests("serialize(LLSD_XML)");
- };
-
- template<> template<>
- void TestLLSDSerializeObject::test<7>()
- {
- mFormatter = [](const LLSD& sd, std::ostream& str)
- {
- LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_NOTATION);
- };
- setParser(LLSDSerialize::deserialize);
- // In this test, serialize(LLSD_NOTATION) emits a header recognized by
- // deserialize().
- doRoundTripTests("serialize(LLSD_NOTATION)");
- };
-
- template<> template<>
- void TestLLSDSerializeObject::test<8>()
- {
- setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
- new LLSDNotationParser());
- setParser(LLSDSerialize::deserialize);
- // This is an interesting test because LLSDNotationFormatter does not
- // emit an llsd/notation header.
- doRoundTripTests("LLSDNotationFormatter -> deserialize");
- };
-
- template<> template<>
- void TestLLSDSerializeObject::test<9>()
- {
- setFormatterParser(new LLSDXMLFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
- new LLSDXMLParser());
- setParser(LLSDSerialize::deserialize);
- // This is an interesting test because LLSDXMLFormatter does not
- // emit an LLSD/XML header.
- doRoundTripTests("LLSDXMLFormatter -> deserialize");
- };
+ ;
+ checkRoundTrip(msg + " long string", v);
+
+ static const U32 block_size = 0x000020;
+ for (U32 block = 0x000000; block <= 0x10ffff; block += block_size)
+ {
+ std::ostringstream out;
+
+ for (U32 c = block; c < block + block_size; ++c)
+ {
+ if (c <= 0x000001f
+ && c != 0x000009
+ && c != 0x00000a)
+ {
+ // see XML standard, sections 2.2 and 4.1
+ continue;
+ }
+ if (0x00d800 <= c && c <= 0x00dfff) { continue; }
+ if (0x00fdd0 <= c && c <= 0x00fdef) { continue; }
+ if ((c & 0x00fffe) == 0x00fffe) { continue; }
+ // see Unicode standard, section 15.8
+
+ if (c <= 0x00007f)
+ {
+ out << (char)(c & 0x7f);
+ }
+ else if (c <= 0x0007ff)
+ {
+ out << (char)(0xc0 | ((c >> 6) & 0x1f));
+ out << (char)(0x80 | ((c >> 0) & 0x3f));
+ }
+ else if (c <= 0x00ffff)
+ {
+ out << (char)(0xe0 | ((c >> 12) & 0x0f));
+ out << (char)(0x80 | ((c >> 6) & 0x3f));
+ out << (char)(0x80 | ((c >> 0) & 0x3f));
+ }
+ else
+ {
+ out << (char)(0xf0 | ((c >> 18) & 0x07));
+ out << (char)(0x80 | ((c >> 12) & 0x3f));
+ out << (char)(0x80 | ((c >> 6) & 0x3f));
+ out << (char)(0x80 | ((c >> 0) & 0x3f));
+ }
+ }
+
+ v = out.str();
+
+ std::ostringstream blockmsg;
+ blockmsg << msg << " unicode string block 0x" << std::hex << block;
+ checkRoundTrip(blockmsg.str(), v);
+ }
+
+ LLDate epoch;
+ v = epoch;
+ checkRoundTrip(msg + " epoch date", v);
+
+ LLDate aDay("2002-12-07T05:07:15.00Z");
+ v = aDay;
+ checkRoundTrip(msg + " date", v);
+
+ LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
+ v = path;
+ checkRoundTrip(msg + " url", v);
+
+ const char source[] = "it must be a blue moon again";
+ std::vector<U8> data;
+ // note, includes terminating '\0'
+ copy(&source[0], &source[sizeof(source)], back_inserter(data));
+
+ v = data;
+ checkRoundTrip(msg + " binary", v);
+
+ v = LLSD::emptyMap();
+ checkRoundTrip(msg + " empty map", v);
+
+ v = LLSD::emptyMap();
+ v["name"] = "luke"; //v.insert("name", "luke");
+ v["age"] = 3; //v.insert("age", 3);
+ checkRoundTrip(msg + " map", v);
+
+ v.clear();
+ v["a"]["1"] = true;
+ v["b"]["0"] = false;
+ checkRoundTrip(msg + " nested maps", v);
+
+ v = LLSD::emptyArray();
+ checkRoundTrip(msg + " empty array", v);
+
+ v = LLSD::emptyArray();
+ v.append("ali");
+ v.append(28);
+ checkRoundTrip(msg + " array", v);
+
+ v.clear();
+ v[0][0] = true;
+ v[1][0] = false;
+ checkRoundTrip(msg + " nested arrays", v);
+
+ v = LLSD::emptyMap();
+ fillmap(v, 10, 3); // 10^6 maps
+ checkRoundTrip(msg + " many nested maps", v);
+ }
+
+ typedef tut::test_group<TestLLSDSerializeData> TestLLSDSerializeGroup;
+ typedef TestLLSDSerializeGroup::object TestLLSDSerializeObject;
+ TestLLSDSerializeGroup gTestLLSDSerializeGroup("llsd serialization");
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<1>()
+ {
+ setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY),
+ new LLSDNotationParser());
+ doRoundTripTests("pretty binary notation serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<2>()
+ {
+ setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
+ new LLSDNotationParser());
+ doRoundTripTests("raw binary notation serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<3>()
+ {
+ setFormatterParser(new LLSDXMLFormatter(), new LLSDXMLParser());
+ doRoundTripTests("xml serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<4>()
+ {
+ setFormatterParser(new LLSDBinaryFormatter(), new LLSDBinaryParser());
+ doRoundTripTests("binary serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<5>()
+ {
+ mFormatter = [](const LLSD& sd, std::ostream& str)
+ {
+ LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_BINARY);
+ };
+ setParser(LLSDSerialize::deserialize);
+ doRoundTripTests("serialize(LLSD_BINARY)");
+ };
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<6>()
+ {
+ mFormatter = [](const LLSD& sd, std::ostream& str)
+ {
+ LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_XML);
+ };
+ setParser(LLSDSerialize::deserialize);
+ doRoundTripTests("serialize(LLSD_XML)");
+ };
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<7>()
+ {
+ mFormatter = [](const LLSD& sd, std::ostream& str)
+ {
+ LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_NOTATION);
+ };
+ setParser(LLSDSerialize::deserialize);
+ // In this test, serialize(LLSD_NOTATION) emits a header recognized by
+ // deserialize().
+ doRoundTripTests("serialize(LLSD_NOTATION)");
+ };
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<8>()
+ {
+ setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
+ new LLSDNotationParser());
+ setParser(LLSDSerialize::deserialize);
+ // This is an interesting test because LLSDNotationFormatter does not
+ // emit an llsd/notation header.
+ doRoundTripTests("LLSDNotationFormatter -> deserialize");
+ };
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<9>()
+ {
+ setFormatterParser(new LLSDXMLFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
+ new LLSDXMLParser());
+ setParser(LLSDSerialize::deserialize);
+ // This is an interesting test because LLSDXMLFormatter does not
+ // emit an LLSD/XML header.
+ doRoundTripTests("LLSDXMLFormatter -> deserialize");
+ };
/*==========================================================================*|
- // We do not expect this test to succeed. Without a header, neither
- // notation LLSD nor binary LLSD reliably start with a distinct character,
- // the way XML LLSD starts with '<'. By convention, we default to notation
- // rather than binary.
- template<> template<>
- void TestLLSDSerializeObject::test<10>()
- {
- setFormatterParser(new LLSDBinaryFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
- new LLSDBinaryParser());
- setParser(LLSDSerialize::deserialize);
- // This is an interesting test because LLSDBinaryFormatter does not
- // emit an LLSD/Binary header.
- doRoundTripTests("LLSDBinaryFormatter -> deserialize");
- };
+ // We do not expect this test to succeed. Without a header, neither
+ // notation LLSD nor binary LLSD reliably start with a distinct character,
+ // the way XML LLSD starts with '<'. By convention, we default to notation
+ // rather than binary.
+ template<> template<>
+ void TestLLSDSerializeObject::test<10>()
+ {
+ setFormatterParser(new LLSDBinaryFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
+ new LLSDBinaryParser());
+ setParser(LLSDSerialize::deserialize);
+ // This is an interesting test because LLSDBinaryFormatter does not
+ // emit an LLSD/Binary header.
+ doRoundTripTests("LLSDBinaryFormatter -> deserialize");
+ };
|*==========================================================================*/
- /**
- * @class TestLLSDParsing
- * @brief Base class for of a parse tester.
- */
- template <class parser_t>
- class TestLLSDParsing
- {
- public:
- TestLLSDParsing()
- {
- mParser = new parser_t;
- }
-
- void ensureParse(
- const std::string& msg,
- const std::string& in,
- const LLSD& expected_value,
- S32 expected_count,
- S32 depth_limit = -1)
- {
- std::stringstream input;
- input.str(in);
-
- LLSD parsed_result;
- mParser->reset(); // reset() call is needed since test code re-uses mParser
- S32 parsed_count = mParser->parse(input, parsed_result, in.size(), depth_limit);
- ensure_equals(msg.c_str(), parsed_result, expected_value);
-
- // This count check is really only useful for expected
- // parse failures, since the ensures equal will already
- // require equality.
- std::string count_msg(msg);
- count_msg += " (count)";
- ensure_equals(count_msg, parsed_count, expected_count);
- }
-
- LLPointer<parser_t> mParser;
- };
-
-
- /**
- * @class TestLLSDXMLParsing
- * @brief Concrete instance of a parse tester.
- */
- class TestLLSDXMLParsing : public TestLLSDParsing<LLSDXMLParser>
- {
- public:
- TestLLSDXMLParsing() {}
- };
-
- typedef tut::test_group<TestLLSDXMLParsing> TestLLSDXMLParsingGroup;
- typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject;
- TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing");
-
- template<> template<>
- void TestLLSDXMLParsingObject::test<1>()
- {
- // test handling of xml not recognized as llsd results in an
- // LLSD Undefined
- ensureParse(
- "malformed xml",
- "<llsd><string>ha ha</string>",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "not llsd",
- "<html><body><p>ha ha</p></body></html>",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "value without llsd",
- "<string>ha ha</string>",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "key without llsd",
- "<key>ha ha</key>",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
-
- template<> template<>
- void TestLLSDXMLParsingObject::test<2>()
- {
- // test handling of unrecognized or unparseable llsd values
- LLSD v;
- v["amy"] = 23;
- v["bob"] = LLSD();
- v["cam"] = 1.23;
-
- ensureParse(
- "unknown data type",
- "<llsd><map>"
- "<key>amy</key><integer>23</integer>"
- "<key>bob</key><bigint>99999999999999999</bigint>"
- "<key>cam</key><real>1.23</real>"
- "</map></llsd>",
- v,
- v.size() + 1);
- }
-
- template<> template<>
- void TestLLSDXMLParsingObject::test<3>()
- {
- // test handling of nested bad data
-
- LLSD v;
- v["amy"] = 23;
- v["cam"] = 1.23;
-
- ensureParse(
- "map with html",
- "<llsd><map>"
- "<key>amy</key><integer>23</integer>"
- "<html><body>ha ha</body></html>"
- "<key>cam</key><real>1.23</real>"
- "</map></llsd>",
- v,
- v.size() + 1);
-
- v.clear();
- v["amy"] = 23;
- v["cam"] = 1.23;
- ensureParse(
- "map with value for key",
- "<llsd><map>"
- "<key>amy</key><integer>23</integer>"
- "<string>ha ha</string>"
- "<key>cam</key><real>1.23</real>"
- "</map></llsd>",
- v,
- v.size() + 1);
-
- v.clear();
- v["amy"] = 23;
- v["bob"] = LLSD::emptyMap();
- v["cam"] = 1.23;
- ensureParse(
- "map with map of html",
- "<llsd><map>"
- "<key>amy</key><integer>23</integer>"
- "<key>bob</key>"
- "<map>"
- "<html><body>ha ha</body></html>"
- "</map>"
- "<key>cam</key><real>1.23</real>"
- "</map></llsd>",
- v,
- v.size() + 1);
-
- v.clear();
- v[0] = 23;
- v[1] = LLSD();
- v[2] = 1.23;
-
- ensureParse(
- "array value of html",
- "<llsd><array>"
- "<integer>23</integer>"
- "<html><body>ha ha</body></html>"
- "<real>1.23</real>"
- "</array></llsd>",
- v,
- v.size() + 1);
-
- v.clear();
- v[0] = 23;
- v[1] = LLSD::emptyMap();
- v[2] = 1.23;
- ensureParse(
- "array with map of html",
- "<llsd><array>"
- "<integer>23</integer>"
- "<map>"
- "<html><body>ha ha</body></html>"
- "</map>"
- "<real>1.23</real>"
- "</array></llsd>",
- v,
- v.size() + 1);
- }
-
- template<> template<>
- void TestLLSDXMLParsingObject::test<4>()
- {
- // test handling of binary object in XML
- std::string xml;
- LLSD expected;
-
- // Generated by: echo -n 'hello' | openssl enc -e -base64
- expected = string_to_vector("hello");
- xml = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
- ensureParse(
- "the word 'hello' packed in binary encoded base64",
- xml,
- expected,
- 1);
-
- expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
- xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
- ensureParse(
- "a common binary blob for object -> agent offline inv transfer",
- xml,
- expected,
- 1);
-
- expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
- xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBl\n";
- xml += "NDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5\n";
- xml += "LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZm\n";
- xml += "ZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMy\n";
- xml += "OXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
- ensureParse(
- "a common binary blob for object -> agent offline inv transfer",
- xml,
- expected,
- 1);
- }
+ /**
+ * @class TestLLSDParsing
+ * @brief Base class for of a parse tester.
+ */
+ template <class parser_t>
+ class TestLLSDParsing
+ {
+ public:
+ TestLLSDParsing()
+ {
+ mParser = new parser_t;
+ }
+
+ void ensureParse(
+ const std::string& msg,
+ const std::string& in,
+ const LLSD& expected_value,
+ S32 expected_count,
+ S32 depth_limit = -1)
+ {
+ std::stringstream input;
+ input.str(in);
+
+ LLSD parsed_result;
+ mParser->reset(); // reset() call is needed since test code re-uses mParser
+ S32 parsed_count = mParser->parse(input, parsed_result, in.size(), depth_limit);
+ ensure_equals(msg.c_str(), parsed_result, expected_value);
+
+ // This count check is really only useful for expected
+ // parse failures, since the ensures equal will already
+ // require equality.
+ std::string count_msg(msg);
+ count_msg += " (count)";
+ ensure_equals(count_msg, parsed_count, expected_count);
+ }
+
+ LLPointer<parser_t> mParser;
+ };
+
+
+ /**
+ * @class TestLLSDXMLParsing
+ * @brief Concrete instance of a parse tester.
+ */
+ class TestLLSDXMLParsing : public TestLLSDParsing<LLSDXMLParser>
+ {
+ public:
+ TestLLSDXMLParsing() {}
+ };
+
+ typedef tut::test_group<TestLLSDXMLParsing> TestLLSDXMLParsingGroup;
+ typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject;
+ TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing");
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<1>()
+ {
+ // test handling of xml not recognized as llsd results in an
+ // LLSD Undefined
+ ensureParse(
+ "malformed xml",
+ "<llsd><string>ha ha</string>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "not llsd",
+ "<html><body><p>ha ha</p></body></html>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "value without llsd",
+ "<string>ha ha</string>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "key without llsd",
+ "<key>ha ha</key>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<2>()
+ {
+ // test handling of unrecognized or unparseable llsd values
+ LLSD v;
+ v["amy"] = 23;
+ v["bob"] = LLSD();
+ v["cam"] = 1.23;
+
+ ensureParse(
+ "unknown data type",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<key>bob</key><bigint>99999999999999999</bigint>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+ }
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<3>()
+ {
+ // test handling of nested bad data
+
+ LLSD v;
+ v["amy"] = 23;
+ v["cam"] = 1.23;
+
+ ensureParse(
+ "map with html",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<html><body>ha ha</body></html>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v["amy"] = 23;
+ v["cam"] = 1.23;
+ ensureParse(
+ "map with value for key",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<string>ha ha</string>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v["amy"] = 23;
+ v["bob"] = LLSD::emptyMap();
+ v["cam"] = 1.23;
+ ensureParse(
+ "map with map of html",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<key>bob</key>"
+ "<map>"
+ "<html><body>ha ha</body></html>"
+ "</map>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v[0] = 23;
+ v[1] = LLSD();
+ v[2] = 1.23;
+
+ ensureParse(
+ "array value of html",
+ "<llsd><array>"
+ "<integer>23</integer>"
+ "<html><body>ha ha</body></html>"
+ "<real>1.23</real>"
+ "</array></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v[0] = 23;
+ v[1] = LLSD::emptyMap();
+ v[2] = 1.23;
+ ensureParse(
+ "array with map of html",
+ "<llsd><array>"
+ "<integer>23</integer>"
+ "<map>"
+ "<html><body>ha ha</body></html>"
+ "</map>"
+ "<real>1.23</real>"
+ "</array></llsd>",
+ v,
+ v.size() + 1);
+ }
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<4>()
+ {
+ // test handling of binary object in XML
+ std::string xml;
+ LLSD expected;
+
+ // Generated by: echo -n 'hello' | openssl enc -e -base64
+ expected = string_to_vector("hello");
+ xml = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+ ensureParse(
+ "the word 'hello' packed in binary encoded base64",
+ xml,
+ expected,
+ 1);
+
+ expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+ xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+ ensureParse(
+ "a common binary blob for object -> agent offline inv transfer",
+ xml,
+ expected,
+ 1);
+
+ expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+ xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBl\n";
+ xml += "NDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5\n";
+ xml += "LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZm\n";
+ xml += "ZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMy\n";
+ xml += "OXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+ ensureParse(
+ "a common binary blob for object -> agent offline inv transfer",
+ xml,
+ expected,
+ 1);
+ }
template<> template<>
void TestLLSDXMLParsingObject::test<5>()
@@ -858,272 +858,272 @@ namespace tut
}
- /*
- TODO:
- test XML parsing
- binary with unrecognized encoding
- nested LLSD tags
- multiple values inside an LLSD
- */
-
-
- /**
- * @class TestLLSDNotationParsing
- * @brief Concrete instance of a parse tester.
- */
- class TestLLSDNotationParsing : public TestLLSDParsing<LLSDNotationParser>
- {
- public:
- TestLLSDNotationParsing() {}
- };
-
- typedef tut::test_group<TestLLSDNotationParsing> TestLLSDNotationParsingGroup;
- typedef TestLLSDNotationParsingGroup::object TestLLSDNotationParsingObject;
- TestLLSDNotationParsingGroup gTestLLSDNotationParsingGroup(
- "llsd notation parsing");
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<1>()
- {
- // test handling of xml not recognized as llsd results in an
- // LLSD Undefined
- ensureParse(
- "malformed notation map",
- "{'ha ha'",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "malformed notation array",
- "['ha ha'",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "malformed notation string",
- "'ha ha",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "bad notation noise",
- "g48ejlnfr",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<2>()
- {
- ensureParse("valid undef", "!", LLSD(), 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<3>()
- {
- LLSD val = false;
- ensureParse("valid boolean false 0", "false", val, 1);
- ensureParse("valid boolean false 1", "f", val, 1);
- ensureParse("valid boolean false 2", "0", val, 1);
- ensureParse("valid boolean false 3", "F", val, 1);
- ensureParse("valid boolean false 4", "FALSE", val, 1);
- val = true;
- ensureParse("valid boolean true 0", "true", val, 1);
- ensureParse("valid boolean true 1", "t", val, 1);
- ensureParse("valid boolean true 2", "1", val, 1);
- ensureParse("valid boolean true 3", "T", val, 1);
- ensureParse("valid boolean true 4", "TRUE", val, 1);
-
- val.clear();
- ensureParse("invalid true", "TR", val, LLSDParser::PARSE_FAILURE);
- ensureParse("invalid false", "FAL", val, LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<4>()
- {
- LLSD val = 123;
- ensureParse("valid integer", "i123", val, 1);
- val.clear();
- ensureParse("invalid integer", "421", val, LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<5>()
- {
- LLSD val = 456.7;
- ensureParse("valid real", "r456.7", val, 1);
- val.clear();
- ensureParse("invalid real", "456.7", val, LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<6>()
- {
- LLUUID id;
- LLSD val = id;
- ensureParse(
- "unparseable uuid",
- "u123",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- id.generate();
- val = id;
- std::string uuid_str("u");
- uuid_str += id.asString();
- ensureParse("valid uuid", uuid_str.c_str(), val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<7>()
- {
- LLSD val = std::string("foolish");
- ensureParse("valid string 1", "\"foolish\"", val, 1);
- val = std::string("g'day");
- ensureParse("valid string 2", "\"g'day\"", val, 1);
- val = std::string("have a \"nice\" day");
- ensureParse("valid string 3", "'have a \"nice\" day'", val, 1);
- val = std::string("whatever");
- ensureParse("valid string 4", "s(8)\"whatever\"", val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<8>()
- {
- ensureParse(
- "invalid string 1",
- "s(7)\"whatever\"",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "invalid string 2",
- "s(9)\"whatever\"",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<9>()
- {
- LLSD val = LLURI("http://www.google.com");
- ensureParse("valid uri", "l\"http://www.google.com\"", val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<10>()
- {
- LLSD val = LLDate("2007-12-28T09:22:53.10Z");
- ensureParse("valid date", "d\"2007-12-28T09:22:53.10Z\"", val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<11>()
- {
- std::vector<U8> vec;
- vec.push_back((U8)'a'); vec.push_back((U8)'b'); vec.push_back((U8)'c');
- vec.push_back((U8)'3'); vec.push_back((U8)'2'); vec.push_back((U8)'1');
- LLSD val = vec;
- ensureParse("valid binary b64", "b64\"YWJjMzIx\"", val, 1);
- ensureParse("valid bainry b16", "b16\"616263333231\"", val, 1);
- ensureParse("valid bainry raw", "b(6)\"abc321\"", val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<12>()
- {
- ensureParse(
- "invalid -- binary length specified too long",
- "b(7)\"abc321\"",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "invalid -- binary length specified way too long",
- "b(1000000)\"abc321\"",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<13>()
- {
- LLSD val;
- val["amy"] = 23;
- val["bob"] = LLSD();
- val["cam"] = 1.23;
- ensureParse("simple map", "{'amy':i23,'bob':!,'cam':r1.23}", val, 4);
-
- val["bob"] = LLSD::emptyMap();
- val["bob"]["vehicle"] = std::string("bicycle");
- ensureParse(
- "nested map",
- "{'amy':i23,'bob':{'vehicle':'bicycle'},'cam':r1.23}",
- val,
- 5);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<14>()
- {
- LLSD val;
- val.append(23);
- val.append(LLSD());
- val.append(1.23);
- ensureParse("simple array", "[i23,!,r1.23]", val, 4);
- val[1] = LLSD::emptyArray();
- val[1].append("bicycle");
- ensureParse("nested array", "[i23,['bicycle'],r1.23]", val, 5);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<15>()
- {
- LLSD val;
- val["amy"] = 23;
- val["bob"]["dogs"] = LLSD::emptyArray();
- val["bob"]["dogs"].append(LLSD::emptyMap());
- val["bob"]["dogs"][0]["name"] = std::string("groove");
- val["bob"]["dogs"][0]["breed"] = std::string("samoyed");
- val["bob"]["dogs"].append(LLSD::emptyMap());
- val["bob"]["dogs"][1]["name"] = std::string("greyley");
- val["bob"]["dogs"][1]["breed"] = std::string("chow/husky");
- val["cam"] = 1.23;
- ensureParse(
- "nested notation",
- "{'amy':i23,"
- " 'bob':{'dogs':["
- "{'name':'groove', 'breed':'samoyed'},"
- "{'name':'greyley', 'breed':'chow/husky'}]},"
- " 'cam':r1.23}",
- val,
- 11);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<16>()
- {
- // text to make sure that incorrect sizes bail because
- std::string bad_str("s(5)\"hi\"");
- ensureParse(
- "size longer than bytes left",
- bad_str,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<17>()
- {
- // text to make sure that incorrect sizes bail because
- std::string bad_bin("b(5)\"hi\"");
- ensureParse(
- "size longer than bytes left",
- bad_bin,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
+ /*
+ TODO:
+ test XML parsing
+ binary with unrecognized encoding
+ nested LLSD tags
+ multiple values inside an LLSD
+ */
+
+
+ /**
+ * @class TestLLSDNotationParsing
+ * @brief Concrete instance of a parse tester.
+ */
+ class TestLLSDNotationParsing : public TestLLSDParsing<LLSDNotationParser>
+ {
+ public:
+ TestLLSDNotationParsing() {}
+ };
+
+ typedef tut::test_group<TestLLSDNotationParsing> TestLLSDNotationParsingGroup;
+ typedef TestLLSDNotationParsingGroup::object TestLLSDNotationParsingObject;
+ TestLLSDNotationParsingGroup gTestLLSDNotationParsingGroup(
+ "llsd notation parsing");
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<1>()
+ {
+ // test handling of xml not recognized as llsd results in an
+ // LLSD Undefined
+ ensureParse(
+ "malformed notation map",
+ "{'ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed notation array",
+ "['ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed notation string",
+ "'ha ha",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "bad notation noise",
+ "g48ejlnfr",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<2>()
+ {
+ ensureParse("valid undef", "!", LLSD(), 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<3>()
+ {
+ LLSD val = false;
+ ensureParse("valid boolean false 0", "false", val, 1);
+ ensureParse("valid boolean false 1", "f", val, 1);
+ ensureParse("valid boolean false 2", "0", val, 1);
+ ensureParse("valid boolean false 3", "F", val, 1);
+ ensureParse("valid boolean false 4", "FALSE", val, 1);
+ val = true;
+ ensureParse("valid boolean true 0", "true", val, 1);
+ ensureParse("valid boolean true 1", "t", val, 1);
+ ensureParse("valid boolean true 2", "1", val, 1);
+ ensureParse("valid boolean true 3", "T", val, 1);
+ ensureParse("valid boolean true 4", "TRUE", val, 1);
+
+ val.clear();
+ ensureParse("invalid true", "TR", val, LLSDParser::PARSE_FAILURE);
+ ensureParse("invalid false", "FAL", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<4>()
+ {
+ LLSD val = 123;
+ ensureParse("valid integer", "i123", val, 1);
+ val.clear();
+ ensureParse("invalid integer", "421", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<5>()
+ {
+ LLSD val = 456.7;
+ ensureParse("valid real", "r456.7", val, 1);
+ val.clear();
+ ensureParse("invalid real", "456.7", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<6>()
+ {
+ LLUUID id;
+ LLSD val = id;
+ ensureParse(
+ "unparseable uuid",
+ "u123",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ id.generate();
+ val = id;
+ std::string uuid_str("u");
+ uuid_str += id.asString();
+ ensureParse("valid uuid", uuid_str.c_str(), val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<7>()
+ {
+ LLSD val = std::string("foolish");
+ ensureParse("valid string 1", "\"foolish\"", val, 1);
+ val = std::string("g'day");
+ ensureParse("valid string 2", "\"g'day\"", val, 1);
+ val = std::string("have a \"nice\" day");
+ ensureParse("valid string 3", "'have a \"nice\" day'", val, 1);
+ val = std::string("whatever");
+ ensureParse("valid string 4", "s(8)\"whatever\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<8>()
+ {
+ ensureParse(
+ "invalid string 1",
+ "s(7)\"whatever\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "invalid string 2",
+ "s(9)\"whatever\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<9>()
+ {
+ LLSD val = LLURI("http://www.google.com");
+ ensureParse("valid uri", "l\"http://www.google.com\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<10>()
+ {
+ LLSD val = LLDate("2007-12-28T09:22:53.10Z");
+ ensureParse("valid date", "d\"2007-12-28T09:22:53.10Z\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<11>()
+ {
+ std::vector<U8> vec;
+ vec.push_back((U8)'a'); vec.push_back((U8)'b'); vec.push_back((U8)'c');
+ vec.push_back((U8)'3'); vec.push_back((U8)'2'); vec.push_back((U8)'1');
+ LLSD val = vec;
+ ensureParse("valid binary b64", "b64\"YWJjMzIx\"", val, 1);
+ ensureParse("valid bainry b16", "b16\"616263333231\"", val, 1);
+ ensureParse("valid bainry raw", "b(6)\"abc321\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<12>()
+ {
+ ensureParse(
+ "invalid -- binary length specified too long",
+ "b(7)\"abc321\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "invalid -- binary length specified way too long",
+ "b(1000000)\"abc321\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<13>()
+ {
+ LLSD val;
+ val["amy"] = 23;
+ val["bob"] = LLSD();
+ val["cam"] = 1.23;
+ ensureParse("simple map", "{'amy':i23,'bob':!,'cam':r1.23}", val, 4);
+
+ val["bob"] = LLSD::emptyMap();
+ val["bob"]["vehicle"] = std::string("bicycle");
+ ensureParse(
+ "nested map",
+ "{'amy':i23,'bob':{'vehicle':'bicycle'},'cam':r1.23}",
+ val,
+ 5);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<14>()
+ {
+ LLSD val;
+ val.append(23);
+ val.append(LLSD());
+ val.append(1.23);
+ ensureParse("simple array", "[i23,!,r1.23]", val, 4);
+ val[1] = LLSD::emptyArray();
+ val[1].append("bicycle");
+ ensureParse("nested array", "[i23,['bicycle'],r1.23]", val, 5);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<15>()
+ {
+ LLSD val;
+ val["amy"] = 23;
+ val["bob"]["dogs"] = LLSD::emptyArray();
+ val["bob"]["dogs"].append(LLSD::emptyMap());
+ val["bob"]["dogs"][0]["name"] = std::string("groove");
+ val["bob"]["dogs"][0]["breed"] = std::string("samoyed");
+ val["bob"]["dogs"].append(LLSD::emptyMap());
+ val["bob"]["dogs"][1]["name"] = std::string("greyley");
+ val["bob"]["dogs"][1]["breed"] = std::string("chow/husky");
+ val["cam"] = 1.23;
+ ensureParse(
+ "nested notation",
+ "{'amy':i23,"
+ " 'bob':{'dogs':["
+ "{'name':'groove', 'breed':'samoyed'},"
+ "{'name':'greyley', 'breed':'chow/husky'}]},"
+ " 'cam':r1.23}",
+ val,
+ 11);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<16>()
+ {
+ // text to make sure that incorrect sizes bail because
+ std::string bad_str("s(5)\"hi\"");
+ ensureParse(
+ "size longer than bytes left",
+ bad_str,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<17>()
+ {
+ // text to make sure that incorrect sizes bail because
+ std::string bad_bin("b(5)\"hi\"");
+ ensureParse(
+ "size longer than bytes left",
+ bad_bin,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
template<> template<>
void TestLLSDNotationParsingObject::test<18>()
{
- LLSD level_1 = LLSD::emptyMap(); level_1["level_2"] = 99;
- LLSD level_0 = LLSD::emptyMap(); level_0["level_1"] = level_1;
+ LLSD level_1 = LLSD::emptyMap(); level_1["level_2"] = 99;
+ LLSD level_0 = LLSD::emptyMap(); level_0["level_1"] = level_1;
LLSD deep = LLSD::emptyMap();
deep["level_0"] = level_0;
@@ -1168,7 +1168,7 @@ namespace tut
template<> template<>
void TestLLSDNotationParsingObject::test<20>()
{
- LLSD end = LLSD::emptyMap(); end["end"] = (S32)99;
+ LLSD end = LLSD::emptyMap(); end["end"] = (S32)99;
LLSD level_49 = LLSD::emptyMap(); level_49["level_49"] = end;
LLSD level_48 = LLSD::emptyMap(); level_48["level_48"] = level_49;
@@ -1259,536 +1259,536 @@ namespace tut
9);
}
- /**
- * @class TestLLSDBinaryParsing
- * @brief Concrete instance of a parse tester.
- */
- class TestLLSDBinaryParsing : public TestLLSDParsing<LLSDBinaryParser>
- {
- public:
- TestLLSDBinaryParsing() {}
- };
-
- typedef tut::test_group<TestLLSDBinaryParsing> TestLLSDBinaryParsingGroup;
- typedef TestLLSDBinaryParsingGroup::object TestLLSDBinaryParsingObject;
- TestLLSDBinaryParsingGroup gTestLLSDBinaryParsingGroup(
- "llsd binary parsing");
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<1>()
- {
- std::vector<U8> vec;
- vec.resize(6);
- vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
- vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
- std::string string_expected((char*)&vec[0], vec.size());
- LLSD value = string_expected;
-
- vec.resize(11);
- vec[0] = 's'; // for string
- vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
- vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
-
- uint32_t size = htonl(6);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse("correct string parse", str_good, value, 1);
-
- size = htonl(7);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_1((char*)&vec[0], vec.size());
- ensureParse(
- "incorrect size string parse",
- str_bad_1,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- size = htonl(100000);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_2((char*)&vec[0], vec.size());
- ensureParse(
- "incorrect size string parse",
- str_bad_2,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<2>()
- {
- std::vector<U8> vec;
- vec.resize(6);
- vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
- vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
- LLSD value = vec;
-
- vec.resize(11);
- vec[0] = 'b'; // for binary
- vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
- vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
-
- uint32_t size = htonl(6);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse("correct binary parse", str_good, value, 1);
-
- size = htonl(7);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_1((char*)&vec[0], vec.size());
- ensureParse(
- "incorrect size binary parse 1",
- str_bad_1,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- size = htonl(100000);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_2((char*)&vec[0], vec.size());
- ensureParse(
- "incorrect size binary parse 2",
- str_bad_2,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<3>()
- {
- // test handling of xml not recognized as llsd results in an
- // LLSD Undefined
- ensureParse(
- "malformed binary map",
- "{'ha ha'",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "malformed binary array",
- "['ha ha'",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "malformed binary string",
- "'ha ha",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "bad noise",
- "g48ejlnfr",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
- template<> template<>
- void TestLLSDBinaryParsingObject::test<4>()
- {
- ensureParse("valid undef", "!", LLSD(), 1);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<5>()
- {
- LLSD val = false;
- ensureParse("valid boolean false 2", "0", val, 1);
- val = true;
- ensureParse("valid boolean true 2", "1", val, 1);
-
- val.clear();
- ensureParse("invalid true", "t", val, LLSDParser::PARSE_FAILURE);
- ensureParse("invalid false", "f", val, LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<6>()
- {
- std::vector<U8> vec;
- vec.push_back('{');
- vec.resize(vec.size() + 4);
- uint32_t size = htonl(1);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- vec.push_back('k');
- int key_size_loc = vec.size();
- size = htonl(1); // 1 too short
- vec.resize(vec.size() + 4);
- memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
- vec.push_back('a'); vec.push_back('m'); vec.push_back('y');
- vec.push_back('i');
- int integer_loc = vec.size();
- vec.resize(vec.size() + 4);
- uint32_t val_int = htonl(23);
- memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
- std::string str_bad_1((char*)&vec[0], vec.size());
- ensureParse(
- "invalid key size",
- str_bad_1,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- // check with correct size, but unterminated map (missing '}')
- size = htonl(3); // correct size
- memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
- std::string str_bad_2((char*)&vec[0], vec.size());
- ensureParse(
- "valid key size, unterminated map",
- str_bad_2,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- // check w/ correct size and correct map termination
- LLSD val;
- val["amy"] = 23;
- vec.push_back('}');
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse(
- "valid map",
- str_good,
- val,
- 2);
-
- // check w/ incorrect sizes and correct map termination
- size = htonl(0); // 1 too few (for the map entry)
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_3((char*)&vec[0], vec.size());
- ensureParse(
- "invalid map too long",
- str_bad_3,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- size = htonl(2); // 1 too many
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_4((char*)&vec[0], vec.size());
- ensureParse(
- "invalid map too short",
- str_bad_4,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<7>()
- {
- std::vector<U8> vec;
- vec.push_back('[');
- vec.resize(vec.size() + 4);
- uint32_t size = htonl(1); // 1 too short
- memcpy(&vec[1], &size, sizeof(uint32_t));
- vec.push_back('"'); vec.push_back('a'); vec.push_back('m');
- vec.push_back('y'); vec.push_back('"'); vec.push_back('i');
- int integer_loc = vec.size();
- vec.resize(vec.size() + 4);
- uint32_t val_int = htonl(23);
- memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
-
- std::string str_bad_1((char*)&vec[0], vec.size());
- ensureParse(
- "invalid array size",
- str_bad_1,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- // check with correct size, but unterminated map (missing ']')
- size = htonl(2); // correct size
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_2((char*)&vec[0], vec.size());
- ensureParse(
- "unterminated array",
- str_bad_2,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- // check w/ correct size and correct map termination
- LLSD val;
- val.append("amy");
- val.append(23);
- vec.push_back(']');
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse(
- "valid array",
- str_good,
- val,
- 3);
-
- // check with too many elements
- size = htonl(3); // 1 too long
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_3((char*)&vec[0], vec.size());
- ensureParse(
- "array too short",
- str_bad_3,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<8>()
- {
- std::vector<U8> vec;
- vec.push_back('{');
- vec.resize(vec.size() + 4);
- memset(&vec[1], 0, 4);
- vec.push_back('}');
- std::string str_good((char*)&vec[0], vec.size());
- LLSD val = LLSD::emptyMap();
- ensureParse(
- "empty map",
- str_good,
- val,
- 1);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<9>()
- {
- std::vector<U8> vec;
- vec.push_back('[');
- vec.resize(vec.size() + 4);
- memset(&vec[1], 0, 4);
- vec.push_back(']');
- std::string str_good((char*)&vec[0], vec.size());
- LLSD val = LLSD::emptyArray();
- ensureParse(
- "empty array",
- str_good,
- val,
- 1);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<10>()
- {
- std::vector<U8> vec;
- vec.push_back('l');
- vec.resize(vec.size() + 4);
- uint32_t size = htonl(14); // 1 too long
- memcpy(&vec[1], &size, sizeof(uint32_t));
- vec.push_back('h'); vec.push_back('t'); vec.push_back('t');
- vec.push_back('p'); vec.push_back(':'); vec.push_back('/');
- vec.push_back('/'); vec.push_back('s'); vec.push_back('l');
- vec.push_back('.'); vec.push_back('c'); vec.push_back('o');
- vec.push_back('m');
- std::string str_bad((char*)&vec[0], vec.size());
- ensureParse(
- "invalid uri length size",
- str_bad,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- LLSD val;
- val = LLURI("http://sl.com");
- size = htonl(13); // correct length
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse(
- "valid key size",
- str_good,
- val,
- 1);
- }
+ /**
+ * @class TestLLSDBinaryParsing
+ * @brief Concrete instance of a parse tester.
+ */
+ class TestLLSDBinaryParsing : public TestLLSDParsing<LLSDBinaryParser>
+ {
+ public:
+ TestLLSDBinaryParsing() {}
+ };
+
+ typedef tut::test_group<TestLLSDBinaryParsing> TestLLSDBinaryParsingGroup;
+ typedef TestLLSDBinaryParsingGroup::object TestLLSDBinaryParsingObject;
+ TestLLSDBinaryParsingGroup gTestLLSDBinaryParsingGroup(
+ "llsd binary parsing");
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<1>()
+ {
+ std::vector<U8> vec;
+ vec.resize(6);
+ vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
+ vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
+ std::string string_expected((char*)&vec[0], vec.size());
+ LLSD value = string_expected;
+
+ vec.resize(11);
+ vec[0] = 's'; // for string
+ vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
+ vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
+
+ uint32_t size = htonl(6);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse("correct string parse", str_good, value, 1);
+
+ size = htonl(7);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size string parse",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ size = htonl(100000);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size string parse",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<2>()
+ {
+ std::vector<U8> vec;
+ vec.resize(6);
+ vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
+ vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
+ LLSD value = vec;
+
+ vec.resize(11);
+ vec[0] = 'b'; // for binary
+ vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
+ vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
+
+ uint32_t size = htonl(6);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse("correct binary parse", str_good, value, 1);
+
+ size = htonl(7);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size binary parse 1",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ size = htonl(100000);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size binary parse 2",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<3>()
+ {
+ // test handling of xml not recognized as llsd results in an
+ // LLSD Undefined
+ ensureParse(
+ "malformed binary map",
+ "{'ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed binary array",
+ "['ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed binary string",
+ "'ha ha",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "bad noise",
+ "g48ejlnfr",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<4>()
+ {
+ ensureParse("valid undef", "!", LLSD(), 1);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<5>()
+ {
+ LLSD val = false;
+ ensureParse("valid boolean false 2", "0", val, 1);
+ val = true;
+ ensureParse("valid boolean true 2", "1", val, 1);
+
+ val.clear();
+ ensureParse("invalid true", "t", val, LLSDParser::PARSE_FAILURE);
+ ensureParse("invalid false", "f", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<6>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('{');
+ vec.resize(vec.size() + 4);
+ uint32_t size = htonl(1);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ vec.push_back('k');
+ int key_size_loc = vec.size();
+ size = htonl(1); // 1 too short
+ vec.resize(vec.size() + 4);
+ memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
+ vec.push_back('a'); vec.push_back('m'); vec.push_back('y');
+ vec.push_back('i');
+ int integer_loc = vec.size();
+ vec.resize(vec.size() + 4);
+ uint32_t val_int = htonl(23);
+ memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid key size",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check with correct size, but unterminated map (missing '}')
+ size = htonl(3); // correct size
+ memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid key size, unterminated map",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check w/ correct size and correct map termination
+ LLSD val;
+ val["amy"] = 23;
+ vec.push_back('}');
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid map",
+ str_good,
+ val,
+ 2);
+
+ // check w/ incorrect sizes and correct map termination
+ size = htonl(0); // 1 too few (for the map entry)
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_3((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid map too long",
+ str_bad_3,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ size = htonl(2); // 1 too many
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_4((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid map too short",
+ str_bad_4,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<7>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('[');
+ vec.resize(vec.size() + 4);
+ uint32_t size = htonl(1); // 1 too short
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ vec.push_back('"'); vec.push_back('a'); vec.push_back('m');
+ vec.push_back('y'); vec.push_back('"'); vec.push_back('i');
+ int integer_loc = vec.size();
+ vec.resize(vec.size() + 4);
+ uint32_t val_int = htonl(23);
+ memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
+
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid array size",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check with correct size, but unterminated map (missing ']')
+ size = htonl(2); // correct size
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "unterminated array",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check w/ correct size and correct map termination
+ LLSD val;
+ val.append("amy");
+ val.append(23);
+ vec.push_back(']');
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid array",
+ str_good,
+ val,
+ 3);
+
+ // check with too many elements
+ size = htonl(3); // 1 too long
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_3((char*)&vec[0], vec.size());
+ ensureParse(
+ "array too short",
+ str_bad_3,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<8>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('{');
+ vec.resize(vec.size() + 4);
+ memset(&vec[1], 0, 4);
+ vec.push_back('}');
+ std::string str_good((char*)&vec[0], vec.size());
+ LLSD val = LLSD::emptyMap();
+ ensureParse(
+ "empty map",
+ str_good,
+ val,
+ 1);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<9>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('[');
+ vec.resize(vec.size() + 4);
+ memset(&vec[1], 0, 4);
+ vec.push_back(']');
+ std::string str_good((char*)&vec[0], vec.size());
+ LLSD val = LLSD::emptyArray();
+ ensureParse(
+ "empty array",
+ str_good,
+ val,
+ 1);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<10>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('l');
+ vec.resize(vec.size() + 4);
+ uint32_t size = htonl(14); // 1 too long
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ vec.push_back('h'); vec.push_back('t'); vec.push_back('t');
+ vec.push_back('p'); vec.push_back(':'); vec.push_back('/');
+ vec.push_back('/'); vec.push_back('s'); vec.push_back('l');
+ vec.push_back('.'); vec.push_back('c'); vec.push_back('o');
+ vec.push_back('m');
+ std::string str_bad((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid uri length size",
+ str_bad,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ LLSD val;
+ val = LLURI("http://sl.com");
+ size = htonl(13); // correct length
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid key size",
+ str_good,
+ val,
+ 1);
+ }
/*
- template<> template<>
- void TestLLSDBinaryParsingObject::test<11>()
- {
- }
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<11>()
+ {
+ }
*/
/**
- * @class TestLLSDCrossCompatible
- * @brief Miscellaneous serialization and parsing tests
- */
- class TestLLSDCrossCompatible
- {
- public:
- TestLLSDCrossCompatible() {}
-
- void ensureBinaryAndNotation(
- const std::string& msg,
- const LLSD& input)
- {
- // to binary, and back again
- std::stringstream str1;
- S32 count1 = LLSDSerialize::toBinary(input, str1);
- LLSD actual_value_bin;
- S32 count2 = LLSDSerialize::fromBinary(
- actual_value_bin,
- str1,
- LLSDSerialize::SIZE_UNLIMITED);
- ensure_equals(
- "ensureBinaryAndNotation binary count",
- count2,
- count1);
-
- // to notation and back again
- std::stringstream str2;
- S32 count3 = LLSDSerialize::toNotation(actual_value_bin, str2);
- ensure_equals(
- "ensureBinaryAndNotation notation count1",
- count3,
- count2);
- LLSD actual_value_notation;
- S32 count4 = LLSDSerialize::fromNotation(
- actual_value_notation,
- str2,
- LLSDSerialize::SIZE_UNLIMITED);
- ensure_equals(
- "ensureBinaryAndNotation notation count2",
- count4,
- count3);
- ensure_equals(
- (msg + " (binaryandnotation)").c_str(),
- actual_value_notation,
- input);
- }
-
- void ensureBinaryAndXML(
- const std::string& msg,
- const LLSD& input)
- {
- // to binary, and back again
- std::stringstream str1;
- S32 count1 = LLSDSerialize::toBinary(input, str1);
- LLSD actual_value_bin;
- S32 count2 = LLSDSerialize::fromBinary(
- actual_value_bin,
- str1,
- LLSDSerialize::SIZE_UNLIMITED);
- ensure_equals(
- "ensureBinaryAndXML binary count",
- count2,
- count1);
-
- // to xml and back again
- std::stringstream str2;
- S32 count3 = LLSDSerialize::toXML(actual_value_bin, str2);
- ensure_equals(
- "ensureBinaryAndXML xml count1",
- count3,
- count2);
- LLSD actual_value_xml;
- S32 count4 = LLSDSerialize::fromXML(actual_value_xml, str2);
- ensure_equals(
- "ensureBinaryAndXML xml count2",
- count4,
- count3);
- ensure_equals((msg + " (binaryandxml)").c_str(), actual_value_xml, input);
- }
- };
-
- typedef tut::test_group<TestLLSDCrossCompatible> TestLLSDCompatibleGroup;
- typedef TestLLSDCompatibleGroup::object TestLLSDCompatibleObject;
- TestLLSDCompatibleGroup gTestLLSDCompatibleGroup(
- "llsd serialize compatible");
-
- template<> template<>
- void TestLLSDCompatibleObject::test<1>()
- {
- LLSD test;
- ensureBinaryAndNotation("undef", test);
- ensureBinaryAndXML("undef", test);
- test = true;
- ensureBinaryAndNotation("boolean true", test);
- ensureBinaryAndXML("boolean true", test);
- test = false;
- ensureBinaryAndNotation("boolean false", test);
- ensureBinaryAndXML("boolean false", test);
- test = 0;
- ensureBinaryAndNotation("integer zero", test);
- ensureBinaryAndXML("integer zero", test);
- test = 1;
- ensureBinaryAndNotation("integer positive", test);
- ensureBinaryAndXML("integer positive", test);
- test = -234567;
- ensureBinaryAndNotation("integer negative", test);
- ensureBinaryAndXML("integer negative", test);
- test = 0.0;
- ensureBinaryAndNotation("real zero", test);
- ensureBinaryAndXML("real zero", test);
- test = 1.0;
- ensureBinaryAndNotation("real positive", test);
- ensureBinaryAndXML("real positive", test);
- test = -1.0;
- ensureBinaryAndNotation("real negative", test);
- ensureBinaryAndXML("real negative", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<2>()
- {
- LLSD test;
- test = "foobar";
- ensureBinaryAndNotation("string", test);
- ensureBinaryAndXML("string", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<3>()
- {
- LLSD test;
- LLUUID id;
- id.generate();
- test = id;
- ensureBinaryAndNotation("uuid", test);
- ensureBinaryAndXML("uuid", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<4>()
- {
- LLSD test;
- test = LLDate(12345.0);
- ensureBinaryAndNotation("date", test);
- ensureBinaryAndXML("date", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<5>()
- {
- LLSD test;
- test = LLURI("http://www.secondlife.com/");
- ensureBinaryAndNotation("uri", test);
- ensureBinaryAndXML("uri", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<6>()
- {
- LLSD test;
- typedef std::vector<U8> buf_t;
- buf_t val;
- for(int ii = 0; ii < 100; ++ii)
- {
- srand(ii); /* Flawfinder: ignore */
- S32 size = rand() % 100 + 10;
- std::generate_n(
- std::back_insert_iterator<buf_t>(val),
- size,
- rand);
- }
- test = val;
- ensureBinaryAndNotation("binary", test);
- ensureBinaryAndXML("binary", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<7>()
- {
- LLSD test;
- test = LLSD::emptyArray();
- test.append(1);
- test.append("hello");
- ensureBinaryAndNotation("array", test);
- ensureBinaryAndXML("array", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<8>()
- {
- LLSD test;
- test = LLSD::emptyArray();
- test["foo"] = "bar";
- test["baz"] = 100;
- ensureBinaryAndNotation("map", test);
- ensureBinaryAndXML("map", test);
- }
+ * @class TestLLSDCrossCompatible
+ * @brief Miscellaneous serialization and parsing tests
+ */
+ class TestLLSDCrossCompatible
+ {
+ public:
+ TestLLSDCrossCompatible() {}
+
+ void ensureBinaryAndNotation(
+ const std::string& msg,
+ const LLSD& input)
+ {
+ // to binary, and back again
+ std::stringstream str1;
+ S32 count1 = LLSDSerialize::toBinary(input, str1);
+ LLSD actual_value_bin;
+ S32 count2 = LLSDSerialize::fromBinary(
+ actual_value_bin,
+ str1,
+ LLSDSerialize::SIZE_UNLIMITED);
+ ensure_equals(
+ "ensureBinaryAndNotation binary count",
+ count2,
+ count1);
+
+ // to notation and back again
+ std::stringstream str2;
+ S32 count3 = LLSDSerialize::toNotation(actual_value_bin, str2);
+ ensure_equals(
+ "ensureBinaryAndNotation notation count1",
+ count3,
+ count2);
+ LLSD actual_value_notation;
+ S32 count4 = LLSDSerialize::fromNotation(
+ actual_value_notation,
+ str2,
+ LLSDSerialize::SIZE_UNLIMITED);
+ ensure_equals(
+ "ensureBinaryAndNotation notation count2",
+ count4,
+ count3);
+ ensure_equals(
+ (msg + " (binaryandnotation)").c_str(),
+ actual_value_notation,
+ input);
+ }
+
+ void ensureBinaryAndXML(
+ const std::string& msg,
+ const LLSD& input)
+ {
+ // to binary, and back again
+ std::stringstream str1;
+ S32 count1 = LLSDSerialize::toBinary(input, str1);
+ LLSD actual_value_bin;
+ S32 count2 = LLSDSerialize::fromBinary(
+ actual_value_bin,
+ str1,
+ LLSDSerialize::SIZE_UNLIMITED);
+ ensure_equals(
+ "ensureBinaryAndXML binary count",
+ count2,
+ count1);
+
+ // to xml and back again
+ std::stringstream str2;
+ S32 count3 = LLSDSerialize::toXML(actual_value_bin, str2);
+ ensure_equals(
+ "ensureBinaryAndXML xml count1",
+ count3,
+ count2);
+ LLSD actual_value_xml;
+ S32 count4 = LLSDSerialize::fromXML(actual_value_xml, str2);
+ ensure_equals(
+ "ensureBinaryAndXML xml count2",
+ count4,
+ count3);
+ ensure_equals((msg + " (binaryandxml)").c_str(), actual_value_xml, input);
+ }
+ };
+
+ typedef tut::test_group<TestLLSDCrossCompatible> TestLLSDCompatibleGroup;
+ typedef TestLLSDCompatibleGroup::object TestLLSDCompatibleObject;
+ TestLLSDCompatibleGroup gTestLLSDCompatibleGroup(
+ "llsd serialize compatible");
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<1>()
+ {
+ LLSD test;
+ ensureBinaryAndNotation("undef", test);
+ ensureBinaryAndXML("undef", test);
+ test = true;
+ ensureBinaryAndNotation("boolean true", test);
+ ensureBinaryAndXML("boolean true", test);
+ test = false;
+ ensureBinaryAndNotation("boolean false", test);
+ ensureBinaryAndXML("boolean false", test);
+ test = 0;
+ ensureBinaryAndNotation("integer zero", test);
+ ensureBinaryAndXML("integer zero", test);
+ test = 1;
+ ensureBinaryAndNotation("integer positive", test);
+ ensureBinaryAndXML("integer positive", test);
+ test = -234567;
+ ensureBinaryAndNotation("integer negative", test);
+ ensureBinaryAndXML("integer negative", test);
+ test = 0.0;
+ ensureBinaryAndNotation("real zero", test);
+ ensureBinaryAndXML("real zero", test);
+ test = 1.0;
+ ensureBinaryAndNotation("real positive", test);
+ ensureBinaryAndXML("real positive", test);
+ test = -1.0;
+ ensureBinaryAndNotation("real negative", test);
+ ensureBinaryAndXML("real negative", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<2>()
+ {
+ LLSD test;
+ test = "foobar";
+ ensureBinaryAndNotation("string", test);
+ ensureBinaryAndXML("string", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<3>()
+ {
+ LLSD test;
+ LLUUID id;
+ id.generate();
+ test = id;
+ ensureBinaryAndNotation("uuid", test);
+ ensureBinaryAndXML("uuid", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<4>()
+ {
+ LLSD test;
+ test = LLDate(12345.0);
+ ensureBinaryAndNotation("date", test);
+ ensureBinaryAndXML("date", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<5>()
+ {
+ LLSD test;
+ test = LLURI("http://www.secondlife.com/");
+ ensureBinaryAndNotation("uri", test);
+ ensureBinaryAndXML("uri", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<6>()
+ {
+ LLSD test;
+ typedef std::vector<U8> buf_t;
+ buf_t val;
+ for(int ii = 0; ii < 100; ++ii)
+ {
+ srand(ii); /* Flawfinder: ignore */
+ S32 size = rand() % 100 + 10;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(val),
+ size,
+ rand);
+ }
+ test = val;
+ ensureBinaryAndNotation("binary", test);
+ ensureBinaryAndXML("binary", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<7>()
+ {
+ LLSD test;
+ test = LLSD::emptyArray();
+ test.append(1);
+ test.append("hello");
+ ensureBinaryAndNotation("array", test);
+ ensureBinaryAndXML("array", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<8>()
+ {
+ LLSD test;
+ test = LLSD::emptyArray();
+ test["foo"] = "bar";
+ test["baz"] = 100;
+ ensureBinaryAndNotation("map", test);
+ ensureBinaryAndXML("map", test);
+ }
// helper for TestPythonCompatible
static std::string import_llsd("import os.path\n"
@@ -1921,12 +1921,12 @@ namespace tut
int bufflen{ static_cast<int>(buffstr.length()) };
out.write(reinterpret_cast<const char*>(&bufflen), sizeof(bufflen));
LL_DEBUGS() << "Wrote length: "
- << hexdump(reinterpret_cast<const char*>(&bufflen),
- sizeof(bufflen))
+ << LL::hexdump(reinterpret_cast<const char*>(&bufflen),
+ sizeof(bufflen))
<< LL_ENDL;
out.write(buffstr.c_str(), buffstr.length());
LL_DEBUGS() << "Wrote data: "
- << hexmix(buffstr.c_str(), buffstr.length())
+ << LL::hexmix(buffstr.c_str(), buffstr.length())
<< LL_ENDL;
}
}
@@ -2130,7 +2130,7 @@ namespace tut
item.asReal(), 3.14, 7); // 7 bits ~= 0.01
ensure("Failed to read LLSD::String from Python",
itemFromStream(inf, item, parse));
- ensure_equals(item.asString(),
+ ensure_equals(item.asString(),
"This string\n"
"has several\n"
"lines.");
diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp
index 302bbe6f8d..edccdb097b 100644
--- a/indra/llcommon/threadpool.cpp
+++ b/indra/llcommon/threadpool.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-10-21
* @brief Implementation for threadpool.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
@@ -18,6 +18,7 @@
// external library headers
// other Linden headers
#include "commoncontrol.h"
+#include "llcoros.h"
#include "llerror.h"
#include "llevents.h"
#include "llsd.h"
@@ -90,20 +91,14 @@ void LL::ThreadPoolBase::start()
return;
}
- // Listen on "LLApp", and when the app is shutting down, close the queue
- // and join the workers.
- LLEventPumps::instance().obtain("LLApp").listen(
+ // When the app is shutting down, close the queue and join the workers.
+ mStopListener = LLCoros::getStopListener(
mName,
- [this](const LLSD& stat)
+ [this](const LLSD& status)
{
- std::string status(stat["status"]);
- if (status != "running")
- {
- // viewer is starting shutdown -- proclaim the end is nigh!
- LL_DEBUGS("ThreadPool") << mName << " saw " << status << LL_ENDL;
- close();
- }
- return false;
+ // viewer is starting shutdown -- proclaim the end is nigh!
+ LL_DEBUGS("ThreadPool") << mName << " saw " << status << LL_ENDL;
+ close();
});
}
diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h
index 0eb1891754..7ced7fbf9f 100644
--- a/indra/llcommon/threadpool.h
+++ b/indra/llcommon/threadpool.h
@@ -4,7 +4,7 @@
* @date 2021-10-21
* @brief ThreadPool configures a WorkQueue along with a pool of threads to
* service it.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
@@ -13,6 +13,7 @@
#if ! defined(LL_THREADPOOL_H)
#define LL_THREADPOOL_H
+#include "llcoros.h"
#include "threadpool_fwd.h"
#include "workqueue.h"
#include <memory> // std::unique_ptr
@@ -52,8 +53,8 @@ namespace LL
void start();
/**
- * ThreadPool listens for application shutdown messages on the "LLApp"
- * LLEventPump. Call close() to shut down this ThreadPool early.
+ * ThreadPool listens for application shutdown events. Call close() to
+ * shut down this ThreadPool early.
*/
virtual void close();
@@ -95,6 +96,7 @@ namespace LL
std::string mName;
size_t mThreadCount;
+ LLTempBoundListener mStopListener;
};
/**
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index 6066e74fb5..800547084a 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-10-06
* @brief Implementation for WorkQueue.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
@@ -32,8 +32,11 @@ using Lock = LLCoros::LockType;
LL::WorkQueueBase::WorkQueueBase(const std::string& name):
super(makeName(name))
{
- // TODO: register for "LLApp" events so we can implicitly close() on
- // viewer shutdown.
+ // Register for status change events so we'll implicitly close() on viewer
+ // shutdown.
+ mStopListener = LLCoros::getStopListener(
+ "WorkQueue:" + getKey(),
+ [this](const LLSD&){ close(); });
}
void LL::WorkQueueBase::runUntilClose()
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index 9d7bbfbf7a..4c46290f2a 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-09-30
* @brief Queue used for inter-thread work passing.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
@@ -13,6 +13,7 @@
#define LL_WORKQUEUE_H
#include "llcoros.h"
+#include "llevents.h"
#include "llexception.h"
#include "llinstancetracker.h"
#include "llinstancetrackersubclass.h"
@@ -194,6 +195,8 @@ namespace LL
static std::string makeName(const std::string& name);
void callWork(const Work& work);
+ LLTempBoundListener mStopListener;
+
private:
virtual Work pop_() = 0;
virtual bool tryPop_(Work&) = 0;
diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp
index cbf4c1ffb8..750d4e21b9 100644
--- a/indra/llfilesystem/lldir.cpp
+++ b/indra/llfilesystem/lldir.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldir.cpp
* @brief implementation of directory utilities base class
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -37,7 +37,7 @@
#include "lldir.h"
#include "llerror.h"
-#include "lltimer.h" // ms_sleep()
+#include "lltimer.h" // ms_sleep()
#include "lluuid.h"
#include "lldiriterator.h"
@@ -69,28 +69,28 @@ LLDir *gDirUtilp = (LLDir *)&gDirUtil;
/// Values for findSkinnedFilenames(subdir) parameter
const char
- *LLDir::XUI = "xui",
- *LLDir::TEXTURES = "textures",
- *LLDir::SKINBASE = "";
+ *LLDir::XUI = "xui",
+ *LLDir::TEXTURES = "textures",
+ *LLDir::SKINBASE = "";
static const char* const empty = "";
std::string LLDir::sDumpDir = "";
LLDir::LLDir()
-: mAppName(""),
- mExecutablePathAndName(""),
- mExecutableFilename(""),
- mExecutableDir(""),
- mAppRODataDir(""),
- mOSUserDir(""),
- mOSUserAppDir(""),
- mLindenUserDir(""),
- mOSCacheDir(""),
- mCAFile(""),
- mTempDir(""),
- mDirDelimiter("/"), // fallback to forward slash if not overridden
- mLanguage("en"),
- mUserName("undefined")
+: mAppName(""),
+ mExecutablePathAndName(""),
+ mExecutableFilename(""),
+ mExecutableDir(""),
+ mAppRODataDir(""),
+ mOSUserDir(""),
+ mOSUserAppDir(""),
+ mLindenUserDir(""),
+ mOSCacheDir(""),
+ mCAFile(""),
+ mTempDir(""),
+ mDirDelimiter("/"), // fallback to forward slash if not overridden
+ mLanguage("en"),
+ mUserName("undefined")
{
}
@@ -109,7 +109,7 @@ std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)
#endif
std::vector<std::string> v;
-
+
if (exists(p))
{
if (is_directory(p))
@@ -127,188 +127,188 @@ std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)
}
}
return v;
-}
-
+}
+
S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
{
- S32 count = 0;
- std::string filename;
- std::string fullpath;
- S32 result;
-
- // File masks starting with "/" will match nothing, so we consider them invalid.
- if (LLStringUtil::startsWith(mask, getDirDelimiter()))
- {
- LL_WARNS() << "Invalid file mask: " << mask << LL_ENDL;
- llassert(!"Invalid file mask");
- }
-
- LLDirIterator iter(dirname, mask);
- while (iter.next(filename))
- {
- fullpath = add(dirname, filename);
-
- if(LLFile::isdir(fullpath))
- {
- // skipping directory traversal filenames
- count++;
- continue;
- }
-
- S32 retry_count = 0;
- while (retry_count < 5)
- {
- if (0 != LLFile::remove(fullpath))
- {
- retry_count++;
- result = errno;
- LL_WARNS() << "Problem removing " << fullpath << " - errorcode: "
- << result << " attempt " << retry_count << LL_ENDL;
-
- if(retry_count >= 5)
- {
- LL_WARNS() << "Failed to remove " << fullpath << LL_ENDL ;
- return count ;
- }
-
- ms_sleep(100);
- }
- else
- {
- if (retry_count)
- {
- LL_WARNS() << "Successfully removed " << fullpath << LL_ENDL;
- }
- break;
- }
- }
- count++;
- }
- return count;
+ S32 count = 0;
+ std::string filename;
+ std::string fullpath;
+ S32 result;
+
+ // File masks starting with "/" will match nothing, so we consider them invalid.
+ if (LLStringUtil::startsWith(mask, getDirDelimiter()))
+ {
+ LL_WARNS() << "Invalid file mask: " << mask << LL_ENDL;
+ llassert(!"Invalid file mask");
+ }
+
+ LLDirIterator iter(dirname, mask);
+ while (iter.next(filename))
+ {
+ fullpath = add(dirname, filename);
+
+ if(LLFile::isdir(fullpath))
+ {
+ // skipping directory traversal filenames
+ count++;
+ continue;
+ }
+
+ S32 retry_count = 0;
+ while (retry_count < 5)
+ {
+ if (0 != LLFile::remove(fullpath))
+ {
+ retry_count++;
+ result = errno;
+ LL_WARNS() << "Problem removing " << fullpath << " - errorcode: "
+ << result << " attempt " << retry_count << LL_ENDL;
+
+ if(retry_count >= 5)
+ {
+ LL_WARNS() << "Failed to remove " << fullpath << LL_ENDL ;
+ return count ;
+ }
+
+ ms_sleep(100);
+ }
+ else
+ {
+ if (retry_count)
+ {
+ LL_WARNS() << "Successfully removed " << fullpath << LL_ENDL;
+ }
+ break;
+ }
+ }
+ count++;
+ }
+ return count;
}
U32 LLDir::deleteDirAndContents(const std::string& dir_name)
{
//Removes the directory and its contents. Returns number of files deleted.
+
+ U32 num_deleted = 0;
- U32 num_deleted = 0;
-
- try
- {
+ try
+ {
#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name));
+ boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name));
#else
- boost::filesystem::path dir_path(dir_name);
+ boost::filesystem::path dir_path(dir_name);
#endif
- if (boost::filesystem::exists (dir_path))
- {
- if (!boost::filesystem::is_empty (dir_path))
- { // Directory has content
- num_deleted = boost::filesystem::remove_all (dir_path);
- }
- else
- { // Directory is empty
- boost::filesystem::remove (dir_path);
- }
- }
- }
- catch (boost::filesystem::filesystem_error &er)
- {
- LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL;
- }
- return num_deleted;
-}
-
-const std::string LLDir::findFile(const std::string &filename,
- const std::string& searchPath1,
- const std::string& searchPath2,
- const std::string& searchPath3) const
-{
- std::vector<std::string> search_paths;
- search_paths.push_back(searchPath1);
- search_paths.push_back(searchPath2);
- search_paths.push_back(searchPath3);
- return findFile(filename, search_paths);
+ if (boost::filesystem::exists (dir_path))
+ {
+ if (!boost::filesystem::is_empty (dir_path))
+ { // Directory has content
+ num_deleted = boost::filesystem::remove_all (dir_path);
+ }
+ else
+ { // Directory is empty
+ boost::filesystem::remove (dir_path);
+ }
+ }
+ }
+ catch (boost::filesystem::filesystem_error &er)
+ {
+ LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL;
+ }
+ return num_deleted;
+}
+
+const std::string LLDir::findFile(const std::string &filename,
+ const std::string& searchPath1,
+ const std::string& searchPath2,
+ const std::string& searchPath3) const
+{
+ std::vector<std::string> search_paths;
+ search_paths.push_back(searchPath1);
+ search_paths.push_back(searchPath2);
+ search_paths.push_back(searchPath3);
+ return findFile(filename, search_paths);
}
const std::string LLDir::findFile(const std::string& filename, const std::vector<std::string> search_paths) const
{
- std::vector<std::string>::const_iterator search_path_iter;
- for (search_path_iter = search_paths.begin();
- search_path_iter != search_paths.end();
- ++search_path_iter)
- {
- if (!search_path_iter->empty())
- {
- std::string filename_and_path = (*search_path_iter);
- if (!filename.empty())
- {
- filename_and_path += getDirDelimiter() + filename;
- }
- if (fileExists(filename_and_path))
- {
- return filename_and_path;
- }
- }
- }
- return "";
+ std::vector<std::string>::const_iterator search_path_iter;
+ for (search_path_iter = search_paths.begin();
+ search_path_iter != search_paths.end();
+ ++search_path_iter)
+ {
+ if (!search_path_iter->empty())
+ {
+ std::string filename_and_path = (*search_path_iter);
+ if (!filename.empty())
+ {
+ filename_and_path += getDirDelimiter() + filename;
+ }
+ if (fileExists(filename_and_path))
+ {
+ return filename_and_path;
+ }
+ }
+ }
+ return "";
}
const std::string &LLDir::getExecutablePathAndName() const
{
- return mExecutablePathAndName;
+ return mExecutablePathAndName;
}
const std::string &LLDir::getExecutableFilename() const
{
- return mExecutableFilename;
+ return mExecutableFilename;
}
const std::string &LLDir::getExecutableDir() const
{
- return mExecutableDir;
+ return mExecutableDir;
}
const std::string &LLDir::getWorkingDir() const
{
- return mWorkingDir;
+ return mWorkingDir;
}
const std::string &LLDir::getAppName() const
{
- return mAppName;
+ return mAppName;
}
const std::string &LLDir::getAppRODataDir() const
{
- return mAppRODataDir;
+ return mAppRODataDir;
}
const std::string &LLDir::getOSUserDir() const
{
- return mOSUserDir;
+ return mOSUserDir;
}
const std::string &LLDir::getOSUserAppDir() const
{
- return mOSUserAppDir;
+ return mOSUserAppDir;
}
const std::string &LLDir::getLindenUserDir() const
{
- if (mLindenUserDir.empty())
- {
- LL_DEBUGS() << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << LL_ENDL;
- }
+ if (mLindenUserDir.empty())
+ {
+ LL_DEBUGS() << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << LL_ENDL;
+ }
- return mLindenUserDir;
+ return mLindenUserDir;
}
const std::string& LLDir::getChatLogsDir() const
{
- return mChatLogsDir;
+ return mChatLogsDir;
}
void LLDir::setDumpDir( const std::string& path )
@@ -326,14 +326,14 @@ const std::string &LLDir::getDumpDir() const
{
LLUUID uid;
uid.generate();
-
+
sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "")
+ "dump-" + uid.asString();
- dir_exists_or_crash(sDumpDir);
+ dir_exists_or_crash(sDumpDir);
}
- return LLDir::sDumpDir;
+ return LLDir::sDumpDir;
}
bool LLDir::dumpDirExists() const
@@ -343,80 +343,80 @@ bool LLDir::dumpDirExists() const
const std::string &LLDir::getPerAccountChatLogsDir() const
{
- return mPerAccountChatLogsDir;
+ return mPerAccountChatLogsDir;
}
const std::string &LLDir::getTempDir() const
{
- return mTempDir;
+ return mTempDir;
}
const std::string LLDir::getCacheDir(bool get_default) const
{
- if (mCacheDir.empty() || get_default)
- {
- if (!mDefaultCacheDir.empty())
- { // Set at startup - can't set here due to const API
- return mDefaultCacheDir;
- }
-
- std::string res = buildSLOSCacheDir();
- return res;
- }
- else
- {
- return mCacheDir;
- }
+ if (mCacheDir.empty() || get_default)
+ {
+ if (!mDefaultCacheDir.empty())
+ { // Set at startup - can't set here due to const API
+ return mDefaultCacheDir;
+ }
+
+ std::string res = buildSLOSCacheDir();
+ return res;
+ }
+ else
+ {
+ return mCacheDir;
+ }
}
// Return the default cache directory
std::string LLDir::buildSLOSCacheDir() const
{
- std::string res;
- if (getOSCacheDir().empty())
- {
- if (getOSUserAppDir().empty())
- {
- res = "data";
- }
- else
- {
- res = add(getOSUserAppDir(), "cache");
- }
- }
- else
- {
- res = add(getOSCacheDir(), "SecondLife");
- }
- return res;
+ std::string res;
+ if (getOSCacheDir().empty())
+ {
+ if (getOSUserAppDir().empty())
+ {
+ res = "data";
+ }
+ else
+ {
+ res = add(getOSUserAppDir(), "cache");
+ }
+ }
+ else
+ {
+ res = add(getOSCacheDir(), "SecondLife");
+ }
+ return res;
}
const std::string &LLDir::getOSCacheDir() const
{
- return mOSCacheDir;
+ return mOSCacheDir;
}
const std::string &LLDir::getCAFile() const
{
- return mCAFile;
+ return mCAFile;
}
const std::string &LLDir::getDirDelimiter() const
{
- return mDirDelimiter;
+ return mDirDelimiter;
}
const std::string& LLDir::getDefaultSkinDir() const
{
- return mDefaultSkinDir;
+ return mDefaultSkinDir;
}
const std::string &LLDir::getSkinDir() const
{
- return mSkinDir;
+ return mSkinDir;
}
const std::string &LLDir::getUserDefaultSkinDir() const
@@ -426,258 +426,263 @@ const std::string &LLDir::getUserDefaultSkinDir() const
const std::string &LLDir::getUserSkinDir() const
{
- return mUserSkinDir;
+ return mUserSkinDir;
}
const std::string LLDir::getSkinBaseDir() const
{
- return mSkinBaseDir;
+ return mSkinBaseDir;
}
const std::string &LLDir::getLLPluginDir() const
{
- return mLLPluginDir;
+ return mLLPluginDir;
}
const std::string &LLDir::getUserName() const
{
- return mUserName;
+ return mUserName;
}
static std::string ELLPathToString(ELLPath location)
{
- typedef std::map<ELLPath, const char*> ELLPathMap;
+ typedef std::map<ELLPath, const char*> ELLPathMap;
#define ENT(symbol) (symbol, #symbol)
- static const ELLPathMap sMap = map_list_of
- ENT(LL_PATH_NONE)
- ENT(LL_PATH_USER_SETTINGS)
- ENT(LL_PATH_APP_SETTINGS)
- ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet
- ENT(LL_PATH_CACHE)
- ENT(LL_PATH_CHARACTER)
- ENT(LL_PATH_HELP)
- ENT(LL_PATH_LOGS)
- ENT(LL_PATH_TEMP)
- ENT(LL_PATH_SKINS)
- ENT(LL_PATH_TOP_SKIN)
- ENT(LL_PATH_CHAT_LOGS)
- ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS)
- ENT(LL_PATH_USER_SKIN)
- ENT(LL_PATH_LOCAL_ASSETS)
- ENT(LL_PATH_EXECUTABLE)
- ENT(LL_PATH_DEFAULT_SKIN)
- ENT(LL_PATH_FONTS)
- ENT(LL_PATH_LAST)
- ;
+ static const ELLPathMap sMap = map_list_of
+ ENT(LL_PATH_NONE)
+ ENT(LL_PATH_USER_SETTINGS)
+ ENT(LL_PATH_APP_SETTINGS)
+ ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet
+ ENT(LL_PATH_CACHE)
+ ENT(LL_PATH_CHARACTER)
+ ENT(LL_PATH_HELP)
+ ENT(LL_PATH_LOGS)
+ ENT(LL_PATH_TEMP)
+ ENT(LL_PATH_SKINS)
+ ENT(LL_PATH_TOP_SKIN)
+ ENT(LL_PATH_CHAT_LOGS)
+ ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS)
+ ENT(LL_PATH_USER_SKIN)
+ ENT(LL_PATH_LOCAL_ASSETS)
+ ENT(LL_PATH_EXECUTABLE)
+ ENT(LL_PATH_DEFAULT_SKIN)
+ ENT(LL_PATH_FONTS)
+ ENT(LL_PATH_LAST)
+ ENT(LL_PATH_SCRIPTS)
+ ;
#undef ENT
- ELLPathMap::const_iterator found = sMap.find(location);
- if (found != sMap.end())
- return found->second;
- return STRINGIZE("Invalid ELLPath value " << location);
+ ELLPathMap::const_iterator found = sMap.find(location);
+ if (found != sMap.end())
+ return found->second;
+ return STRINGIZE("Invalid ELLPath value " << location);
}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
{
- return getExpandedFilename(location, "", filename);
+ return getExpandedFilename(location, "", filename);
}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir, const std::string& filename) const
{
- return getExpandedFilename(location, "", subdir, filename);
+ return getExpandedFilename(location, "", subdir, filename);
}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subdir1, const std::string& subdir2, const std::string& in_filename) const
{
- std::string prefix;
- switch (location)
- {
- case LL_PATH_NONE:
- // Do nothing
- break;
-
- case LL_PATH_APP_SETTINGS:
- prefix = add(getAppRODataDir(), "app_settings");
- break;
-
- case LL_PATH_CHARACTER:
- prefix = add(getAppRODataDir(), "character");
- break;
-
- case LL_PATH_HELP:
- prefix = "help";
- break;
-
- case LL_PATH_CACHE:
- prefix = getCacheDir();
- break;
-
+ std::string prefix;
+ switch (location)
+ {
+ case LL_PATH_NONE:
+ // Do nothing
+ break;
+
+ case LL_PATH_APP_SETTINGS:
+ prefix = add(getAppRODataDir(), "app_settings");
+ break;
+
+ case LL_PATH_CHARACTER:
+ prefix = add(getAppRODataDir(), "character");
+ break;
+
+ case LL_PATH_HELP:
+ prefix = "help";
+ break;
+
+ case LL_PATH_CACHE:
+ prefix = getCacheDir();
+ break;
+
case LL_PATH_DUMP:
prefix=getDumpDir();
break;
-
- case LL_PATH_USER_SETTINGS:
- prefix = add(getOSUserAppDir(), "user_settings");
- break;
-
- case LL_PATH_PER_SL_ACCOUNT:
- prefix = getLindenUserDir();
- if (prefix.empty())
- {
- // if we're asking for the per-SL-account directory but we haven't
- // logged in yet (or otherwise don't know the account name from
- // which to build this string), then intentionally return a blank
- // string to the caller and skip the below warning about a blank
- // prefix.
- LL_DEBUGS("LLDir") << "getLindenUserDir() not yet set: "
- << ELLPathToString(location)
- << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
- << "' => ''" << LL_ENDL;
- return std::string();
- }
- break;
-
- case LL_PATH_CHAT_LOGS:
- prefix = getChatLogsDir();
- break;
-
- case LL_PATH_PER_ACCOUNT_CHAT_LOGS:
- prefix = getPerAccountChatLogsDir();
- if (prefix.empty())
- {
- // potentially directory was not set yet
- // intentionally return a blank string to the caller
- LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL;
- return std::string();
- }
- break;
-
- case LL_PATH_LOGS:
- prefix = add(getOSUserAppDir(), "logs");
- break;
-
- case LL_PATH_TEMP:
- prefix = getTempDir();
- break;
-
- case LL_PATH_TOP_SKIN:
- prefix = getSkinDir();
- break;
-
- case LL_PATH_DEFAULT_SKIN:
- prefix = getDefaultSkinDir();
- break;
-
- case LL_PATH_USER_SKIN:
- prefix = getUserSkinDir();
- break;
-
- case LL_PATH_SKINS:
- prefix = getSkinBaseDir();
- break;
-
- case LL_PATH_LOCAL_ASSETS:
- prefix = add(getAppRODataDir(), "local_assets");
- break;
-
- case LL_PATH_EXECUTABLE:
- prefix = getExecutableDir();
- break;
-
- case LL_PATH_FONTS:
- prefix = add(getAppRODataDir(), "fonts");
+
+ case LL_PATH_USER_SETTINGS:
+ prefix = add(getOSUserAppDir(), "user_settings");
+ break;
+
+ case LL_PATH_PER_SL_ACCOUNT:
+ prefix = getLindenUserDir();
+ if (prefix.empty())
+ {
+ // if we're asking for the per-SL-account directory but we haven't
+ // logged in yet (or otherwise don't know the account name from
+ // which to build this string), then intentionally return a blank
+ // string to the caller and skip the below warning about a blank
+ // prefix.
+ LL_DEBUGS("LLDir") << "getLindenUserDir() not yet set: "
+ << ELLPathToString(location)
+ << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
+ << "' => ''" << LL_ENDL;
+ return std::string();
+ }
+ break;
+
+ case LL_PATH_CHAT_LOGS:
+ prefix = getChatLogsDir();
+ break;
+
+ case LL_PATH_PER_ACCOUNT_CHAT_LOGS:
+ prefix = getPerAccountChatLogsDir();
+ if (prefix.empty())
+ {
+ // potentially directory was not set yet
+ // intentionally return a blank string to the caller
+ LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL;
+ return std::string();
+ }
+ break;
+
+ case LL_PATH_LOGS:
+ prefix = add(getOSUserAppDir(), "logs");
+ break;
+
+ case LL_PATH_TEMP:
+ prefix = getTempDir();
+ break;
+
+ case LL_PATH_TOP_SKIN:
+ prefix = getSkinDir();
+ break;
+
+ case LL_PATH_DEFAULT_SKIN:
+ prefix = getDefaultSkinDir();
+ break;
+
+ case LL_PATH_USER_SKIN:
+ prefix = getUserSkinDir();
+ break;
+
+ case LL_PATH_SKINS:
+ prefix = getSkinBaseDir();
+ break;
+
+ case LL_PATH_LOCAL_ASSETS:
+ prefix = add(getAppRODataDir(), "local_assets");
+ break;
+
+ case LL_PATH_EXECUTABLE:
+ prefix = getExecutableDir();
+ break;
+
+ case LL_PATH_FONTS:
+ prefix = add(getAppRODataDir(), "fonts");
+ break;
+
+ case LL_PATH_SCRIPTS:
+ prefix = add(getAppRODataDir(), "scripts");
break;
-
- default:
- llassert(0);
- }
-
- if (prefix.empty())
- {
- LL_WARNS() << ELLPathToString(location)
- << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
- << "': prefix is empty, possible bad filename" << LL_ENDL;
- }
-
- std::string expanded_filename = add(prefix, subdir1, subdir2);
- if (expanded_filename.empty() && in_filename.empty())
- {
- return "";
- }
- // Use explicit concatenation here instead of another add() call. Callers
- // passing in_filename as "" expect to obtain a pathname ending with
- // mDirSeparator so they can later directly concatenate with a specific
- // filename. A caller using add() doesn't care, but there's still code
- // loose in the system that uses std::string::operator+().
- expanded_filename += mDirDelimiter;
- expanded_filename += in_filename;
-
- LL_DEBUGS("LLDir") << ELLPathToString(location)
- << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
- << "' => '" << expanded_filename << "'" << LL_ENDL;
- return expanded_filename;
+
+ default:
+ llassert(0);
+ }
+
+ if (prefix.empty())
+ {
+ LL_WARNS() << ELLPathToString(location)
+ << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
+ << "': prefix is empty, possible bad filename" << LL_ENDL;
+ }
+
+ std::string expanded_filename = add(prefix, subdir1, subdir2);
+ if (expanded_filename.empty() && in_filename.empty())
+ {
+ return "";
+ }
+ // Use explicit concatenation here instead of another add() call. Callers
+ // passing in_filename as "" expect to obtain a pathname ending with
+ // mDirSeparator so they can later directly concatenate with a specific
+ // filename. A caller using add() doesn't care, but there's still code
+ // loose in the system that uses std::string::operator+().
+ expanded_filename += mDirDelimiter;
+ expanded_filename += in_filename;
+
+ LL_DEBUGS("LLDir") << ELLPathToString(location)
+ << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
+ << "' => '" << expanded_filename << "'" << LL_ENDL;
+ return expanded_filename;
}
std::string LLDir::getBaseFileName(const std::string& filepath, bool strip_exten) const
{
- std::size_t offset = filepath.find_last_of(getDirDelimiter());
- offset = (offset == std::string::npos) ? 0 : offset+1;
- std::string res = filepath.substr(offset, std::string::npos);
- if (strip_exten)
- {
- offset = res.find_last_of('.');
- if (offset != std::string::npos &&
- offset != 0) // if basename STARTS with '.', don't strip
- {
- res = res.substr(0, offset);
- }
- }
- return res;
+ std::size_t offset = filepath.find_last_of(getDirDelimiter());
+ offset = (offset == std::string::npos) ? 0 : offset+1;
+ std::string res = filepath.substr(offset, std::string::npos);
+ if (strip_exten)
+ {
+ offset = res.find_last_of('.');
+ if (offset != std::string::npos &&
+ offset != 0) // if basename STARTS with '.', don't strip
+ {
+ res = res.substr(0, offset);
+ }
+ }
+ return res;
}
std::string LLDir::getDirName(const std::string& filepath) const
{
- std::size_t offset = filepath.find_last_of(getDirDelimiter());
- S32 len = (offset == std::string::npos) ? 0 : offset;
- std::string dirname = filepath.substr(0, len);
- return dirname;
+ std::size_t offset = filepath.find_last_of(getDirDelimiter());
+ S32 len = (offset == std::string::npos) ? 0 : offset;
+ std::string dirname = filepath.substr(0, len);
+ return dirname;
}
std::string LLDir::getExtension(const std::string& filepath) const
{
- if (filepath.empty())
- return std::string();
- std::string basename = getBaseFileName(filepath, false);
- std::size_t offset = basename.find_last_of('.');
- std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1);
- LLStringUtil::toLower(exten);
- return exten;
+ if (filepath.empty())
+ return std::string();
+ std::string basename = getBaseFileName(filepath, false);
+ std::size_t offset = basename.find_last_of('.');
+ std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1);
+ LLStringUtil::toLower(exten);
+ return exten;
}
std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir,
- const std::string &filename,
- ESkinConstraint constraint) const
+ const std::string &filename,
+ ESkinConstraint constraint) const
{
- // This implementation is basically just as described in the declaration comments.
- std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
- if (found.empty())
- {
- return "";
- }
- return found.front();
+ // This implementation is basically just as described in the declaration comments.
+ std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
+ if (found.empty())
+ {
+ return "";
+ }
+ return found.front();
}
std::string LLDir::findSkinnedFilename(const std::string &subdir,
- const std::string &filename,
- ESkinConstraint constraint) const
+ const std::string &filename,
+ ESkinConstraint constraint) const
{
- // This implementation is basically just as described in the declaration comments.
- std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
- if (found.empty())
- {
- return "";
- }
- return found.back();
+ // This implementation is basically just as described in the declaration comments.
+ std::vector<std::string> found(findSkinnedFilenames(subdir, filename, constraint));
+ if (found.empty())
+ {
+ return "";
+ }
+ return found.back();
}
// This method exists because the two code paths for
@@ -686,210 +691,210 @@ std::string LLDir::findSkinnedFilename(const std::string &subdir,
// difference is in the body of the inner loop.
template <typename FUNCTION>
void LLDir::walkSearchSkinDirs(const std::string& subdir,
- const std::vector<std::string>& subsubdirs,
- const std::string& filename,
- const FUNCTION& function) const
-{
- for (const std::string& skindir : mSearchSkinDirs)
- {
- std::string subdir_path(add(skindir, subdir));
- for (const std::string& subsubdir : subsubdirs)
- {
- std::string full_path(add(subdir_path, subsubdir, filename));
- if (fileExists(full_path))
- {
- function(subsubdir, full_path);
- }
- }
- }
+ const std::vector<std::string>& subsubdirs,
+ const std::string& filename,
+ const FUNCTION& function) const
+{
+ for (const std::string& skindir : mSearchSkinDirs)
+ {
+ std::string subdir_path(add(skindir, subdir));
+ for (const std::string& subsubdir : subsubdirs)
+ {
+ std::string full_path(add(subdir_path, subsubdir, filename));
+ if (fileExists(full_path))
+ {
+ function(subsubdir, full_path);
+ }
+ }
+ }
}
// ridiculous little helper function that should go away when we can use lambda
inline void push_back(std::vector<std::string>& vector, const std::string& value)
{
- vector.push_back(value);
+ vector.push_back(value);
}
typedef std::map<std::string, std::string> StringMap;
// ridiculous little helper function that should go away when we can use lambda
inline void store_in_map(StringMap& map, const std::string& key, const std::string& value)
{
- map[key] = value;
+ map[key] = value;
}
std::vector<std::string> LLDir::findSkinnedFilenames(const std::string& subdir,
- const std::string& filename,
- ESkinConstraint constraint) const
-{
- // Recognize subdirs that have no localization.
- static const std::set<std::string> sUnlocalized = list_of
- ("") // top-level directory not localized
- ("textures") // textures not localized
- ;
-
- LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename
- << "', constraint "
- << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS")
- << LL_ENDL;
-
- // Build results vector.
- std::vector<std::string> results;
- // Disallow filenames that may escape subdir
- if (filename.find("..") != std::string::npos)
- {
- LL_WARNS("LLDir") << "Ignoring potentially relative filename '" << filename << "'" << LL_ENDL;
- return results;
- }
-
- // Cache the default language directory for each subdir we've encountered.
- // A cache entry whose value is the empty string means "not localized,
- // don't bother checking again."
- static StringMap sLocalized;
-
- // Check whether we've already discovered if this subdir is localized.
- StringMap::const_iterator found = sLocalized.find(subdir);
- if (found == sLocalized.end())
- {
- // We have not yet determined that. Is it one of the subdirs "known"
- // to be unlocalized?
- if (sUnlocalized.find(subdir) != sUnlocalized.end())
- {
- // This subdir is known to be unlocalized. Remember that.
- found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
- }
- else
- {
- // We do not recognize this subdir. Investigate.
- std::string subdir_path(add(getDefaultSkinDir(), subdir));
- if (fileExists(add(subdir_path, "en")))
- {
- // defaultSkinDir/subdir contains subdir "en". That's our
- // default language; this subdir is localized.
- found = sLocalized.insert(StringMap::value_type(subdir, "en")).first;
- }
- else if (fileExists(add(subdir_path, "en-us")))
- {
- // defaultSkinDir/subdir contains subdir "en-us" but not "en".
- // Set as default language; this subdir is localized.
- found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first;
- }
- else
- {
- // defaultSkinDir/subdir contains neither "en" nor "en-us".
- // Assume it's not localized. Remember that assumption.
- found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
- }
- }
- }
- // Every code path above should have resulted in 'found' becoming a valid
- // iterator to an entry in sLocalized.
- llassert(found != sLocalized.end());
-
- // Now -- is this subdir localized, or not? The answer determines what
- // subdirectories we check (under subdir) for the requested filename.
- std::vector<std::string> subsubdirs;
- if (found->second.empty())
- {
- // subdir is not localized. filename should be located directly within it.
- subsubdirs.push_back("");
- }
- else
- {
- // subdir is localized, and found->second is the default language
- // directory within it. Check both the default language and the
- // current language -- if it differs from the default, of course.
- subsubdirs.push_back(found->second);
- if (mLanguage != found->second)
- {
- subsubdirs.push_back(mLanguage);
- }
- }
-
- // The process we use depends on 'constraint'.
- if (constraint != CURRENT_SKIN) // meaning ALL_SKINS
- {
- // ALL_SKINS is simpler: just return every pathname generated by
- // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its
- // FUNCTION the subsubdir as well as the full pathname. We just want
- // the full pathname.
- walkSearchSkinDirs(subdir, subsubdirs, filename,
- boost::bind(push_back, boost::ref(results), _2));
- }
- else // CURRENT_SKIN
- {
- // CURRENT_SKIN turns out to be a bit of a misnomer because we might
- // still return files from two different skins. In any case, this
- // value of 'constraint' means we will return at most two paths: one
- // for the default language, one for the current language (supposing
- // those differ).
- // It is important to allow a user to override only the localization
- // for a particular file, for all viewer installs, without also
- // overriding the default-language file.
- // It is important to allow a user to override only the default-
- // language file, for all viewer installs, without also overriding the
- // applicable localization of that file.
- // Therefore, treat the default language and the current language as
- // two separate cases. For each, capture the most-specialized file
- // that exists.
- // Use a map keyed by subsubdir (i.e. language code). This allows us
- // to handle the case of a single subsubdirs entry with the same logic
- // that handles two. For every real file path generated by
- // walkSearchSkinDirs(), update the map entry for its subsubdir.
- StringMap path_for;
- walkSearchSkinDirs(subdir, subsubdirs, filename,
- boost::bind(store_in_map, boost::ref(path_for), _1, _2));
- // Now that we have a path for each of the default language and the
- // current language, copy them -- in proper order -- into results.
- // Don't drive this by walking the map itself: it matters that we
- // generate results in the same order as subsubdirs.
- for (const std::string& subsubdir : subsubdirs)
- {
- StringMap::const_iterator found(path_for.find(subsubdir));
- if (found != path_for.end())
- {
- results.push_back(found->second);
- }
- }
- }
-
- LL_DEBUGS("LLDir") << empty;
- const char* comma = "";
- for (const std::string& path : results)
- {
- LL_CONT << comma << "'" << path << "'";
- comma = ", ";
- }
- LL_CONT << LL_ENDL;
-
- return results;
+ const std::string& filename,
+ ESkinConstraint constraint) const
+{
+ // Recognize subdirs that have no localization.
+ static const std::set<std::string> sUnlocalized = list_of
+ ("") // top-level directory not localized
+ ("textures") // textures not localized
+ ;
+
+ LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename
+ << "', constraint "
+ << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS")
+ << LL_ENDL;
+
+ // Build results vector.
+ std::vector<std::string> results;
+ // Disallow filenames that may escape subdir
+ if (filename.find("..") != std::string::npos)
+ {
+ LL_WARNS("LLDir") << "Ignoring potentially relative filename '" << filename << "'" << LL_ENDL;
+ return results;
+ }
+
+ // Cache the default language directory for each subdir we've encountered.
+ // A cache entry whose value is the empty string means "not localized,
+ // don't bother checking again."
+ static StringMap sLocalized;
+
+ // Check whether we've already discovered if this subdir is localized.
+ StringMap::const_iterator found = sLocalized.find(subdir);
+ if (found == sLocalized.end())
+ {
+ // We have not yet determined that. Is it one of the subdirs "known"
+ // to be unlocalized?
+ if (sUnlocalized.find(subdir) != sUnlocalized.end())
+ {
+ // This subdir is known to be unlocalized. Remember that.
+ found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
+ }
+ else
+ {
+ // We do not recognize this subdir. Investigate.
+ std::string subdir_path(add(getDefaultSkinDir(), subdir));
+ if (fileExists(add(subdir_path, "en")))
+ {
+ // defaultSkinDir/subdir contains subdir "en". That's our
+ // default language; this subdir is localized.
+ found = sLocalized.insert(StringMap::value_type(subdir, "en")).first;
+ }
+ else if (fileExists(add(subdir_path, "en-us")))
+ {
+ // defaultSkinDir/subdir contains subdir "en-us" but not "en".
+ // Set as default language; this subdir is localized.
+ found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first;
+ }
+ else
+ {
+ // defaultSkinDir/subdir contains neither "en" nor "en-us".
+ // Assume it's not localized. Remember that assumption.
+ found = sLocalized.insert(StringMap::value_type(subdir, "")).first;
+ }
+ }
+ }
+ // Every code path above should have resulted in 'found' becoming a valid
+ // iterator to an entry in sLocalized.
+ llassert(found != sLocalized.end());
+
+ // Now -- is this subdir localized, or not? The answer determines what
+ // subdirectories we check (under subdir) for the requested filename.
+ std::vector<std::string> subsubdirs;
+ if (found->second.empty())
+ {
+ // subdir is not localized. filename should be located directly within it.
+ subsubdirs.push_back("");
+ }
+ else
+ {
+ // subdir is localized, and found->second is the default language
+ // directory within it. Check both the default language and the
+ // current language -- if it differs from the default, of course.
+ subsubdirs.push_back(found->second);
+ if (mLanguage != found->second)
+ {
+ subsubdirs.push_back(mLanguage);
+ }
+ }
+
+ // The process we use depends on 'constraint'.
+ if (constraint != CURRENT_SKIN) // meaning ALL_SKINS
+ {
+ // ALL_SKINS is simpler: just return every pathname generated by
+ // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its
+ // FUNCTION the subsubdir as well as the full pathname. We just want
+ // the full pathname.
+ walkSearchSkinDirs(subdir, subsubdirs, filename,
+ boost::bind(push_back, boost::ref(results), _2));
+ }
+ else // CURRENT_SKIN
+ {
+ // CURRENT_SKIN turns out to be a bit of a misnomer because we might
+ // still return files from two different skins. In any case, this
+ // value of 'constraint' means we will return at most two paths: one
+ // for the default language, one for the current language (supposing
+ // those differ).
+ // It is important to allow a user to override only the localization
+ // for a particular file, for all viewer installs, without also
+ // overriding the default-language file.
+ // It is important to allow a user to override only the default-
+ // language file, for all viewer installs, without also overriding the
+ // applicable localization of that file.
+ // Therefore, treat the default language and the current language as
+ // two separate cases. For each, capture the most-specialized file
+ // that exists.
+ // Use a map keyed by subsubdir (i.e. language code). This allows us
+ // to handle the case of a single subsubdirs entry with the same logic
+ // that handles two. For every real file path generated by
+ // walkSearchSkinDirs(), update the map entry for its subsubdir.
+ StringMap path_for;
+ walkSearchSkinDirs(subdir, subsubdirs, filename,
+ boost::bind(store_in_map, boost::ref(path_for), _1, _2));
+ // Now that we have a path for each of the default language and the
+ // current language, copy them -- in proper order -- into results.
+ // Don't drive this by walking the map itself: it matters that we
+ // generate results in the same order as subsubdirs.
+ for (const std::string& subsubdir : subsubdirs)
+ {
+ StringMap::const_iterator found(path_for.find(subsubdir));
+ if (found != path_for.end())
+ {
+ results.push_back(found->second);
+ }
+ }
+ }
+
+ LL_DEBUGS("LLDir") << empty;
+ const char* comma = "";
+ for (const std::string& path : results)
+ {
+ LL_CONT << comma << "'" << path << "'";
+ comma = ", ";
+ }
+ LL_CONT << LL_ENDL;
+
+ return results;
}
std::string LLDir::getTempFilename() const
{
- LLUUID random_uuid;
- std::string uuid_str;
+ LLUUID random_uuid;
+ std::string uuid_str;
- random_uuid.generate();
- random_uuid.toString(uuid_str);
+ random_uuid.generate();
+ random_uuid.toString(uuid_str);
- return add(getTempDir(), uuid_str + ".tmp");
+ return add(getTempDir(), uuid_str + ".tmp");
}
// static
std::string LLDir::getScrubbedFileName(const std::string uncleanFileName)
{
- std::string name(uncleanFileName);
- const std::string illegalChars(getForbiddenFileChars());
- // replace any illegal file chars with and underscore '_'
- for( unsigned int i = 0; i < illegalChars.length(); i++ )
- {
- int j = -1;
- while((j = name.find(illegalChars[i])) > -1)
- {
- name[j] = '_';
- }
- }
- return name;
+ std::string name(uncleanFileName);
+ const std::string illegalChars(getForbiddenFileChars());
+ // replace any illegal file chars with and underscore '_'
+ for( unsigned int i = 0; i < illegalChars.length(); i++ )
+ {
+ int j = -1;
+ while((j = name.find(illegalChars[i])) > -1)
+ {
+ name[j] = '_';
+ }
+ }
+ return name;
}
std::string LLDir::getDumpLogsDirPath(const std::string &file_name)
@@ -900,241 +905,241 @@ std::string LLDir::getDumpLogsDirPath(const std::string &file_name)
// static
std::string LLDir::getForbiddenFileChars()
{
- return "\\/:*?\"<>|";
+ return "\\/:*?\"<>|";
}
void LLDir::setLindenUserDir(const std::string &username)
{
- // if the username isn't set, that's bad
- if (!username.empty())
- {
- // some platforms have case-sensitive filesystems, so be
- // utterly consistent with our firstname/lastname case.
- std::string userlower(username);
- LLStringUtil::toLower(userlower);
- LLStringUtil::replaceChar(userlower, ' ', '_');
- mLindenUserDir = add(getOSUserAppDir(), userlower);
- }
- else
- {
- LL_ERRS() << "NULL name for LLDir::setLindenUserDir" << LL_ENDL;
- }
+ // if the username isn't set, that's bad
+ if (!username.empty())
+ {
+ // some platforms have case-sensitive filesystems, so be
+ // utterly consistent with our firstname/lastname case.
+ std::string userlower(username);
+ LLStringUtil::toLower(userlower);
+ LLStringUtil::replaceChar(userlower, ' ', '_');
+ mLindenUserDir = add(getOSUserAppDir(), userlower);
+ }
+ else
+ {
+ LL_ERRS() << "NULL name for LLDir::setLindenUserDir" << LL_ENDL;
+ }
- dumpCurrentDirectories();
+ dumpCurrentDirectories();
}
void LLDir::setChatLogsDir(const std::string &path)
{
- if (!path.empty() )
- {
- mChatLogsDir = path;
- }
- else
- {
- LL_WARNS() << "Invalid name for LLDir::setChatLogsDir" << LL_ENDL;
- }
+ if (!path.empty() )
+ {
+ mChatLogsDir = path;
+ }
+ else
+ {
+ LL_WARNS() << "Invalid name for LLDir::setChatLogsDir" << LL_ENDL;
+ }
}
void LLDir::updatePerAccountChatLogsDir()
{
- mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName);
+ mPerAccountChatLogsDir = add(getChatLogsDir(), mUserName);
}
void LLDir::setPerAccountChatLogsDir(const std::string &username)
{
- // if both first and last aren't set, assume we're grabbing the cached dir
- if (!username.empty())
- {
- // some platforms have case-sensitive filesystems, so be
- // utterly consistent with our firstname/lastname case.
- std::string userlower(username);
- LLStringUtil::toLower(userlower);
- LLStringUtil::replaceChar(userlower, ' ', '_');
-
- mUserName = userlower;
- updatePerAccountChatLogsDir();
- }
- else
- {
- LL_ERRS() << "NULL name for LLDir::setPerAccountChatLogsDir" << LL_ENDL;
- }
+ // if both first and last aren't set, assume we're grabbing the cached dir
+ if (!username.empty())
+ {
+ // some platforms have case-sensitive filesystems, so be
+ // utterly consistent with our firstname/lastname case.
+ std::string userlower(username);
+ LLStringUtil::toLower(userlower);
+ LLStringUtil::replaceChar(userlower, ' ', '_');
+
+ mUserName = userlower;
+ updatePerAccountChatLogsDir();
+ }
+ else
+ {
+ LL_ERRS() << "NULL name for LLDir::setPerAccountChatLogsDir" << LL_ENDL;
+ }
}
void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language)
{
- LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'"
- << LL_ENDL;
- mSkinName = skin_folder;
- mLanguage = language;
-
- // This method is called multiple times during viewer initialization. Each
- // time it's called, reset mSearchSkinDirs.
- mSearchSkinDirs.clear();
-
- // base skin which is used as fallback for all skinned files
- // e.g. c:\program files\secondlife\skins\default
- mDefaultSkinDir = getSkinBaseDir();
- append(mDefaultSkinDir, "default");
- // This is always the most general of the search skin directories.
- addSearchSkinDir(mDefaultSkinDir);
-
- mSkinDir = getSkinBaseDir();
- append(mSkinDir, skin_folder);
- // Next level of generality is a skin installed with the viewer.
- addSearchSkinDir(mSkinDir);
-
- // user modifications to skins, current and default
- // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle
- mUserSkinDir = getOSUserAppDir();
- append(mUserSkinDir, "skins");
- mUserDefaultSkinDir = mUserSkinDir;
- append(mUserDefaultSkinDir, "default");
- append(mUserSkinDir, skin_folder);
- // Next level of generality is user modifications to default skin...
- addSearchSkinDir(mUserDefaultSkinDir);
- // then user-defined skins.
- addSearchSkinDir(mUserSkinDir);
+ LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'"
+ << LL_ENDL;
+ mSkinName = skin_folder;
+ mLanguage = language;
+
+ // This method is called multiple times during viewer initialization. Each
+ // time it's called, reset mSearchSkinDirs.
+ mSearchSkinDirs.clear();
+
+ // base skin which is used as fallback for all skinned files
+ // e.g. c:\program files\secondlife\skins\default
+ mDefaultSkinDir = getSkinBaseDir();
+ append(mDefaultSkinDir, "default");
+ // This is always the most general of the search skin directories.
+ addSearchSkinDir(mDefaultSkinDir);
+
+ mSkinDir = getSkinBaseDir();
+ append(mSkinDir, skin_folder);
+ // Next level of generality is a skin installed with the viewer.
+ addSearchSkinDir(mSkinDir);
+
+ // user modifications to skins, current and default
+ // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle
+ mUserSkinDir = getOSUserAppDir();
+ append(mUserSkinDir, "skins");
+ mUserDefaultSkinDir = mUserSkinDir;
+ append(mUserDefaultSkinDir, "default");
+ append(mUserSkinDir, skin_folder);
+ // Next level of generality is user modifications to default skin...
+ addSearchSkinDir(mUserDefaultSkinDir);
+ // then user-defined skins.
+ addSearchSkinDir(mUserSkinDir);
}
void LLDir::addSearchSkinDir(const std::string& skindir)
{
- if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end())
- {
- LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL;
- mSearchSkinDirs.push_back(skindir);
- }
+ if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end())
+ {
+ LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL;
+ mSearchSkinDirs.push_back(skindir);
+ }
}
std::string LLDir::getSkinFolder() const
{
- return mSkinName;
+ return mSkinName;
}
std::string LLDir::getLanguage() const
{
- return mLanguage;
+ return mLanguage;
}
bool LLDir::setCacheDir(const std::string &path)
{
- if (path.empty() )
- {
- // reset to default
- mCacheDir = "";
- return true;
- }
- else
- {
- LLFile::mkdir(path);
- std::string tempname = add(path, "temp");
- LLFILE* file = LLFile::fopen(tempname,"wt");
- if (file)
- {
- fclose(file);
- LLFile::remove(tempname);
- mCacheDir = path;
- return true;
- }
- return false;
- }
+ if (path.empty() )
+ {
+ // reset to default
+ mCacheDir = "";
+ return true;
+ }
+ else
+ {
+ LLFile::mkdir(path);
+ std::string tempname = add(path, "temp");
+ LLFILE* file = LLFile::fopen(tempname,"wt");
+ if (file)
+ {
+ fclose(file);
+ LLFile::remove(tempname);
+ mCacheDir = path;
+ return true;
+ }
+ return false;
+ }
}
void LLDir::dumpCurrentDirectories(LLError::ELevel level)
{
- LL_VLOGS(level, "AppInit","Directories") << "Current Directories:" << LL_ENDL;
-
- LL_VLOGS(level, "AppInit", "Directories") << " CurPath: " << getCurPath() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " AppName: " << getAppName() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " ExecutableFilename: " << getExecutableFilename() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " ExecutableDir: " << getExecutableDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " WorkingDir: " << getWorkingDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " AppRODataDir: " << getAppRODataDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " OSUserDir: " << getOSUserDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " OSUserAppDir: " << getOSUserAppDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " TempDir: " << getTempDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " CAFile: " << getCAFile() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL;
- LL_VLOGS(level, "AppInit", "Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit","Directories") << "Current Directories:" << LL_ENDL;
+
+ LL_VLOGS(level, "AppInit", "Directories") << " CurPath: " << getCurPath() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " AppName: " << getAppName() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " ExecutableFilename: " << getExecutableFilename() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " ExecutableDir: " << getExecutableDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " ExecutablePathAndName: " << getExecutablePathAndName() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " WorkingDir: " << getWorkingDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " AppRODataDir: " << getAppRODataDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " OSUserDir: " << getOSUserDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " OSUserAppDir: " << getOSUserAppDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " TempDir: " << getTempDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " CAFile: " << getCAFile() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL;
+ LL_VLOGS(level, "AppInit", "Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
}
void LLDir::append(std::string& destpath, const std::string& name) const
{
- // Delegate question of whether we need a separator to helper method.
- SepOff sepoff(needSep(destpath, name));
- if (sepoff.first) // do we need a separator?
- {
- destpath += mDirDelimiter;
- }
- // If destpath ends with a separator, AND name starts with one, skip
- // name's leading separator.
- destpath += name.substr(sepoff.second);
+ // Delegate question of whether we need a separator to helper method.
+ SepOff sepoff(needSep(destpath, name));
+ if (sepoff.first) // do we need a separator?
+ {
+ destpath += mDirDelimiter;
+ }
+ // If destpath ends with a separator, AND name starts with one, skip
+ // name's leading separator.
+ destpath += name.substr(sepoff.second);
}
LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const
{
- if (path.empty() || name.empty())
- {
- // If either path or name are empty, we do not need a separator
- // between them.
- return SepOff(false, 0);
- }
- // Here we know path and name are both non-empty. But if path already ends
- // with a separator, or if name already starts with a separator, we need
- // not add one.
- std::string::size_type seplen(mDirDelimiter.length());
- bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter);
- bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter);
- if ((! path_ends_sep) && (! name_starts_sep))
- {
- // If neither path nor name brings a separator to the junction, then
- // we need one.
- return SepOff(true, 0);
- }
- if (path_ends_sep && name_starts_sep)
- {
- // But if BOTH path and name bring a separator, we need not add one.
- // Moreover, we should actually skip the leading separator of 'name'.
- return SepOff(false, (unsigned short)seplen);
- }
- // Here we know that either path_ends_sep or name_starts_sep is true --
- // but not both. So don't add a separator, and don't skip any characters:
- // simple concatenation will do the trick.
- return SepOff(false, 0);
+ if (path.empty() || name.empty())
+ {
+ // If either path or name are empty, we do not need a separator
+ // between them.
+ return SepOff(false, 0);
+ }
+ // Here we know path and name are both non-empty. But if path already ends
+ // with a separator, or if name already starts with a separator, we need
+ // not add one.
+ std::string::size_type seplen(mDirDelimiter.length());
+ bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter);
+ bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter);
+ if ((! path_ends_sep) && (! name_starts_sep))
+ {
+ // If neither path nor name brings a separator to the junction, then
+ // we need one.
+ return SepOff(true, 0);
+ }
+ if (path_ends_sep && name_starts_sep)
+ {
+ // But if BOTH path and name bring a separator, we need not add one.
+ // Moreover, we should actually skip the leading separator of 'name'.
+ return SepOff(false, (unsigned short)seplen);
+ }
+ // Here we know that either path_ends_sep or name_starts_sep is true --
+ // but not both. So don't add a separator, and don't skip any characters:
+ // simple concatenation will do the trick.
+ return SepOff(false, 0);
}
void dir_exists_or_crash(const std::string &dir_name)
{
#if LL_WINDOWS
- // *FIX: lame - it doesn't do the same thing on windows. not so
- // important since we don't deploy simulator to windows boxes.
- LLFile::mkdir(dir_name, 0700);
+ // *FIX: lame - it doesn't do the same thing on windows. not so
+ // important since we don't deploy simulator to windows boxes.
+ LLFile::mkdir(dir_name, 0700);
#else
- struct stat dir_stat;
- if(0 != LLFile::stat(dir_name, &dir_stat))
- {
- S32 stat_rv = errno;
- if(ENOENT == stat_rv)
- {
- if(0 != LLFile::mkdir(dir_name, 0700)) // octal
- {
- LL_ERRS() << "Unable to create directory: " << dir_name << LL_ENDL;
- }
- }
- else
- {
- LL_ERRS() << "Unable to stat: " << dir_name << " errno = " << stat_rv
- << LL_ENDL;
- }
- }
- else
- {
- // data_dir exists, make sure it's a directory.
- if(!S_ISDIR(dir_stat.st_mode))
- {
- LL_ERRS() << "Data directory collision: " << dir_name << LL_ENDL;
- }
- }
+ struct stat dir_stat;
+ if(0 != LLFile::stat(dir_name, &dir_stat))
+ {
+ S32 stat_rv = errno;
+ if(ENOENT == stat_rv)
+ {
+ if(0 != LLFile::mkdir(dir_name, 0700)) // octal
+ {
+ LL_ERRS() << "Unable to create directory: " << dir_name << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_ERRS() << "Unable to stat: " << dir_name << " errno = " << stat_rv
+ << LL_ENDL;
+ }
+ }
+ else
+ {
+ // data_dir exists, make sure it's a directory.
+ if(!S_ISDIR(dir_stat.st_mode))
+ {
+ LL_ERRS() << "Data directory collision: " << dir_name << LL_ENDL;
+ }
+ }
#endif
}
diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h
index be82f55e46..7d418159d1 100644
--- a/indra/llfilesystem/lldir.h
+++ b/indra/llfilesystem/lldir.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldir.h
* @brief Definition of directory utilities class
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,245 +30,246 @@
// these numbers are read from settings_files.xml, so we need to be explicit
typedef enum ELLPath
{
- LL_PATH_NONE = 0,
- LL_PATH_USER_SETTINGS = 1,
- LL_PATH_APP_SETTINGS = 2,
- LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet
- LL_PATH_CACHE = 4,
- LL_PATH_CHARACTER = 5,
- LL_PATH_HELP = 6,
- LL_PATH_LOGS = 7,
- LL_PATH_TEMP = 8,
- LL_PATH_SKINS = 9,
- LL_PATH_TOP_SKIN = 10,
- LL_PATH_CHAT_LOGS = 11,
- LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12,
- LL_PATH_USER_SKIN = 14,
- LL_PATH_LOCAL_ASSETS = 15,
- LL_PATH_EXECUTABLE = 16,
- LL_PATH_DEFAULT_SKIN = 17,
- LL_PATH_FONTS = 18,
+ LL_PATH_NONE = 0,
+ LL_PATH_USER_SETTINGS = 1,
+ LL_PATH_APP_SETTINGS = 2,
+ LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet
+ LL_PATH_CACHE = 4,
+ LL_PATH_CHARACTER = 5,
+ LL_PATH_HELP = 6,
+ LL_PATH_LOGS = 7,
+ LL_PATH_TEMP = 8,
+ LL_PATH_SKINS = 9,
+ LL_PATH_TOP_SKIN = 10,
+ LL_PATH_CHAT_LOGS = 11,
+ LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12,
+ LL_PATH_USER_SKIN = 14,
+ LL_PATH_LOCAL_ASSETS = 15,
+ LL_PATH_EXECUTABLE = 16,
+ LL_PATH_DEFAULT_SKIN = 17,
+ LL_PATH_FONTS = 18,
LL_PATH_DUMP = 19,
- LL_PATH_LAST
+ LL_PATH_SCRIPTS = 20,
+ LL_PATH_LAST
} ELLPath;
/// Directory operations
class LLDir
{
public:
- LLDir();
- virtual ~LLDir();
+ LLDir();
+ virtual ~LLDir();
- // app_name - Usually SecondLife, used for creating settings directories
- // in OS-specific location, such as C:\Documents and Settings
- // app_read_only_data_dir - Usually the source code directory, used
- // for test applications to read newview data files.
- virtual void initAppDirs(const std::string &app_name,
- const std::string& app_read_only_data_dir = "") = 0;
+ // app_name - Usually SecondLife, used for creating settings directories
+ // in OS-specific location, such as C:\Documents and Settings
+ // app_read_only_data_dir - Usually the source code directory, used
+ // for test applications to read newview data files.
+ virtual void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir = "") = 0;
- virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
+ virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
U32 deleteDirAndContents(const std::string& dir_name);
std::vector<std::string> getFilesInDir(const std::string &dirname);
// pure virtual functions
- virtual std::string getCurPath() = 0;
- virtual bool fileExists(const std::string &filename) const = 0;
+ virtual std::string getCurPath() = 0;
+ virtual bool fileExists(const std::string &filename) const = 0;
- const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;
- const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const;
+ const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;
+ const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const;
- virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell
- virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so')
+ virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell
+ virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so')
- const std::string &getExecutablePathAndName() const; // Full pathname of the executable
- const std::string &getAppName() const; // install directory under progams/ ie "SecondLife"
- const std::string &getExecutableDir() const; // Directory where the executable is located
- const std::string &getExecutableFilename() const;// Filename of .exe
- const std::string &getWorkingDir() const; // Current working directory
- const std::string &getAppRODataDir() const; // Location of read-only data files
- const std::string &getOSUserDir() const; // Location of the os-specific user dir
- const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir
- const std::string &getLindenUserDir() const; // Location of the Linden user dir.
- const std::string &getChatLogsDir() const; // Location of the chat logs dir.
- const std::string &getDumpDir() const; // Location of the per-run dump dir.
- bool dumpDirExists() const;
- const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir.
- const std::string &getTempDir() const; // Common temporary directory
- const std::string getCacheDir(bool get_default = false) const; // Location of the cache.
- const std::string &getOSCacheDir() const; // location of OS-specific cache folder (may be empty string)
- const std::string &getCAFile() const; // File containing TLS certificate authorities
- const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':')
- const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default
- const std::string &getSkinDir() const; // User-specified skin folder.
- const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin
- const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin
- const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins
- const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell
- const std::string &getUserName() const;
+ const std::string &getExecutablePathAndName() const; // Full pathname of the executable
+ const std::string &getAppName() const; // install directory under progams/ ie "SecondLife"
+ const std::string &getExecutableDir() const; // Directory where the executable is located
+ const std::string &getExecutableFilename() const;// Filename of .exe
+ const std::string &getWorkingDir() const; // Current working directory
+ const std::string &getAppRODataDir() const; // Location of read-only data files
+ const std::string &getOSUserDir() const; // Location of the os-specific user dir
+ const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir
+ const std::string &getLindenUserDir() const; // Location of the Linden user dir.
+ const std::string &getChatLogsDir() const; // Location of the chat logs dir.
+ const std::string &getDumpDir() const; // Location of the per-run dump dir.
+ bool dumpDirExists() const;
+ const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir.
+ const std::string &getTempDir() const; // Common temporary directory
+ const std::string getCacheDir(bool get_default = false) const; // Location of the cache.
+ const std::string &getOSCacheDir() const; // location of OS-specific cache folder (may be empty string)
+ const std::string &getCAFile() const; // File containing TLS certificate authorities
+ const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':')
+ const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default
+ const std::string &getSkinDir() const; // User-specified skin folder.
+ const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin
+ const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin
+ const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins
+ const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell
+ const std::string &getUserName() const;
- // Expanded filename
- std::string getExpandedFilename(ELLPath location, const std::string &filename) const;
- std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const;
- std::string getExpandedFilename(ELLPath location, const std::string &subdir1, const std::string &subdir2, const std::string &filename) const;
+ // Expanded filename
+ std::string getExpandedFilename(ELLPath location, const std::string &filename) const;
+ std::string getExpandedFilename(ELLPath location, const std::string &subdir, const std::string &filename) const;
+ std::string getExpandedFilename(ELLPath location, const std::string &subdir1, const std::string &subdir2, const std::string &filename) const;
- // Base and Directory name extraction
- std::string getBaseFileName(const std::string& filepath, bool strip_exten = false) const;
- std::string getDirName(const std::string& filepath) const;
- std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav"
+ // Base and Directory name extraction
+ std::string getBaseFileName(const std::string& filepath, bool strip_exten = false) const;
+ std::string getDirName(const std::string& filepath) const;
+ std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav"
- // these methods search the various skin paths for the specified file in the following order:
- // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir()
- /// param value for findSkinnedFilenames(), explained below
- enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS };
- /**
- * Given a filename within skin, return an ordered sequence of paths to
- * search. Nonexistent files will be filtered out -- which means that the
- * vector might be empty.
- *
- * @param subdir Identify top-level skin subdirectory by passing one of
- * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file
- * lives under "textures" subtree), LLDir::SKINBASE (file lives at top
- * level of skin subdirectory).
- * @param filename Desired filename within subdir within skin, e.g.
- * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language.
- * @param constraint Callers perform two different kinds of processing.
- * When fetching a XUI file, for instance, the existence of @a filename in
- * the specified skin completely supercedes any @a filename in the default
- * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The
- * returned vector will contain only
- * ".../<i>current_skin</i>/xui/en/<i>filename</i>",
- * ".../<i>current_skin</i>/xui/<i>current_language</i>/<i>filename</i>".
- * But for (e.g.) "strings.xml", we want a given skin to be able to
- * override only specific entries from the default skin. Any string not
- * defined in the specified skin will be sought in the default skin. For
- * that case, pass @a constraint=ALL_SKINS. The returned vector will
- * contain at least ".../default/xui/en/strings.xml",
- * ".../default/xui/<i>current_language</i>/strings.xml",
- * ".../<i>current_skin</i>/xui/en/strings.xml",
- * ".../<i>current_skin</i>/xui/<i>current_language</i>/strings.xml".
- */
- std::vector<std::string> findSkinnedFilenames(const std::string& subdir,
- const std::string& filename,
- ESkinConstraint constraint=CURRENT_SKIN) const;
- /// Values for findSkinnedFilenames(subdir) parameter
- static const char *XUI, *TEXTURES, *SKINBASE;
- /**
- * Return the base-language pathname from findSkinnedFilenames(), or
- * the empty string if no such file exists. Parameters are identical to
- * findSkinnedFilenames(). This is shorthand for capturing the vector
- * returned by findSkinnedFilenames(), checking for empty() and then
- * returning front().
- */
- std::string findSkinnedFilenameBaseLang(const std::string &subdir,
- const std::string &filename,
- ESkinConstraint constraint=CURRENT_SKIN) const;
- /**
- * Return the "most localized" pathname from findSkinnedFilenames(), or
- * the empty string if no such file exists. Parameters are identical to
- * findSkinnedFilenames(). This is shorthand for capturing the vector
- * returned by findSkinnedFilenames(), checking for empty() and then
- * returning back().
- */
- std::string findSkinnedFilename(const std::string &subdir,
- const std::string &filename,
- ESkinConstraint constraint=CURRENT_SKIN) const;
+ // these methods search the various skin paths for the specified file in the following order:
+ // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir()
+ /// param value for findSkinnedFilenames(), explained below
+ enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS };
+ /**
+ * Given a filename within skin, return an ordered sequence of paths to
+ * search. Nonexistent files will be filtered out -- which means that the
+ * vector might be empty.
+ *
+ * @param subdir Identify top-level skin subdirectory by passing one of
+ * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file
+ * lives under "textures" subtree), LLDir::SKINBASE (file lives at top
+ * level of skin subdirectory).
+ * @param filename Desired filename within subdir within skin, e.g.
+ * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language.
+ * @param constraint Callers perform two different kinds of processing.
+ * When fetching a XUI file, for instance, the existence of @a filename in
+ * the specified skin completely supercedes any @a filename in the default
+ * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The
+ * returned vector will contain only
+ * ".../<i>current_skin</i>/xui/en/<i>filename</i>",
+ * ".../<i>current_skin</i>/xui/<i>current_language</i>/<i>filename</i>".
+ * But for (e.g.) "strings.xml", we want a given skin to be able to
+ * override only specific entries from the default skin. Any string not
+ * defined in the specified skin will be sought in the default skin. For
+ * that case, pass @a constraint=ALL_SKINS. The returned vector will
+ * contain at least ".../default/xui/en/strings.xml",
+ * ".../default/xui/<i>current_language</i>/strings.xml",
+ * ".../<i>current_skin</i>/xui/en/strings.xml",
+ * ".../<i>current_skin</i>/xui/<i>current_language</i>/strings.xml".
+ */
+ std::vector<std::string> findSkinnedFilenames(const std::string& subdir,
+ const std::string& filename,
+ ESkinConstraint constraint=CURRENT_SKIN) const;
+ /// Values for findSkinnedFilenames(subdir) parameter
+ static const char *XUI, *TEXTURES, *SKINBASE;
+ /**
+ * Return the base-language pathname from findSkinnedFilenames(), or
+ * the empty string if no such file exists. Parameters are identical to
+ * findSkinnedFilenames(). This is shorthand for capturing the vector
+ * returned by findSkinnedFilenames(), checking for empty() and then
+ * returning front().
+ */
+ std::string findSkinnedFilenameBaseLang(const std::string &subdir,
+ const std::string &filename,
+ ESkinConstraint constraint=CURRENT_SKIN) const;
+ /**
+ * Return the "most localized" pathname from findSkinnedFilenames(), or
+ * the empty string if no such file exists. Parameters are identical to
+ * findSkinnedFilenames(). This is shorthand for capturing the vector
+ * returned by findSkinnedFilenames(), checking for empty() and then
+ * returning back().
+ */
+ std::string findSkinnedFilename(const std::string &subdir,
+ const std::string &filename,
+ ESkinConstraint constraint=CURRENT_SKIN) const;
- // random filename in common temporary directory
- std::string getTempFilename() const;
+ // random filename in common temporary directory
+ std::string getTempFilename() const;
static std::string getDumpLogsDirPath(const std::string &file_name = "");
- // For producing safe download file names from potentially unsafe ones
- static std::string getScrubbedFileName(const std::string uncleanFileName);
- static std::string getForbiddenFileChars();
+ // For producing safe download file names from potentially unsafe ones
+ static std::string getScrubbedFileName(const std::string uncleanFileName);
+ static std::string getForbiddenFileChars();
void setDumpDir( const std::string& path );
- virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir
- virtual void setPerAccountChatLogsDir(const std::string &username); // Set the per user chat log directory.
- virtual void setLindenUserDir(const std::string &username); // Set the linden user dir to this user's dir
- virtual void setSkinFolder(const std::string &skin_folder, const std::string& language);
- virtual std::string getSkinFolder() const;
- virtual std::string getLanguage() const;
- virtual bool setCacheDir(const std::string &path);
- virtual void updatePerAccountChatLogsDir();
+ virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir
+ virtual void setPerAccountChatLogsDir(const std::string &username); // Set the per user chat log directory.
+ virtual void setLindenUserDir(const std::string &username); // Set the linden user dir to this user's dir
+ virtual void setSkinFolder(const std::string &skin_folder, const std::string& language);
+ virtual std::string getSkinFolder() const;
+ virtual std::string getLanguage() const;
+ virtual bool setCacheDir(const std::string &path);
+ virtual void updatePerAccountChatLogsDir();
- virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG);
+ virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG);
- // Utility routine
- std::string buildSLOSCacheDir() const;
+ // Utility routine
+ std::string buildSLOSCacheDir() const;
- /// Append specified @a name to @a destpath, separated by getDirDelimiter()
- /// if both are non-empty.
- void append(std::string& destpath, const std::string& name) const;
- /// Variadic form: append @a name0 and @a name1 and arbitrary other @a
- /// names to @a destpath, separated by getDirDelimiter() as needed.
- template <typename... NAMES>
- void append(std::string& destpath, const std::string& name0, const std::string& name1,
- const NAMES& ... names) const
- {
- // In a typical recursion case, we'd accept (destpath, name0, names).
- // We accept (destpath, name0, name1, names) because it's important to
- // delegate the two-argument case to the non-template implementation.
- append(destpath, name0);
- append(destpath, name1, names...);
- }
+ /// Append specified @a name to @a destpath, separated by getDirDelimiter()
+ /// if both are non-empty.
+ void append(std::string& destpath, const std::string& name) const;
+ /// Variadic form: append @a name0 and @a name1 and arbitrary other @a
+ /// names to @a destpath, separated by getDirDelimiter() as needed.
+ template <typename... NAMES>
+ void append(std::string& destpath, const std::string& name0, const std::string& name1,
+ const NAMES& ... names) const
+ {
+ // In a typical recursion case, we'd accept (destpath, name0, names).
+ // We accept (destpath, name0, name1, names) because it's important to
+ // delegate the two-argument case to the non-template implementation.
+ append(destpath, name0);
+ append(destpath, name1, names...);
+ }
- /// Append specified @a names to @a path, separated by getDirDelimiter()
- /// as needed. Return result, leaving @a path unmodified.
- template <typename... NAMES>
- std::string add(const std::string& path, const NAMES& ... names) const
- {
- std::string destpath(path);
- append(destpath, names...);
- return destpath;
- }
+ /// Append specified @a names to @a path, separated by getDirDelimiter()
+ /// as needed. Return result, leaving @a path unmodified.
+ template <typename... NAMES>
+ std::string add(const std::string& path, const NAMES& ... names) const
+ {
+ std::string destpath(path);
+ append(destpath, names...);
+ return destpath;
+ }
protected:
- // Does an add() or append() call need a directory delimiter?
- typedef std::pair<bool, unsigned short> SepOff;
- SepOff needSep(const std::string& path, const std::string& name) const;
- // build mSearchSkinDirs without adding duplicates
- void addSearchSkinDir(const std::string& skindir);
+ // Does an add() or append() call need a directory delimiter?
+ typedef std::pair<bool, unsigned short> SepOff;
+ SepOff needSep(const std::string& path, const std::string& name) const;
+ // build mSearchSkinDirs without adding duplicates
+ void addSearchSkinDir(const std::string& skindir);
- // Internal to findSkinnedFilenames()
- template <typename FUNCTION>
- void walkSearchSkinDirs(const std::string& subdir,
- const std::vector<std::string>& subsubdirs,
- const std::string& filename,
- const FUNCTION& function) const;
+ // Internal to findSkinnedFilenames()
+ template <typename FUNCTION>
+ void walkSearchSkinDirs(const std::string& subdir,
+ const std::vector<std::string>& subsubdirs,
+ const std::string& filename,
+ const FUNCTION& function) const;
- std::string mAppName; // install directory under progams/ ie "SecondLife"
- std::string mExecutablePathAndName; // full path + Filename of .exe
- std::string mExecutableFilename; // Filename of .exe
- std::string mExecutableDir; // Location of executable
- std::string mWorkingDir; // Current working directory
- std::string mAppRODataDir; // Location for static app data
- std::string mOSUserDir; // OS Specific user directory
- std::string mOSUserAppDir; // OS Specific user app directory
- std::string mLindenUserDir; // Location for Linden user-specific data
- std::string mPerAccountChatLogsDir; // Location for chat logs.
- std::string mChatLogsDir; // Location for chat logs.
- std::string mCAFile; // Location of the TLS certificate authority PEM file.
- std::string mTempDir;
- std::string mCacheDir; // cache directory as set by user preference
- std::string mDefaultCacheDir; // default cache diretory
- std::string mOSCacheDir; // operating system cache dir
- std::string mDirDelimiter;
- std::string mSkinName; // caller-specified skin name
- std::string mSkinBaseDir; // Base for skins paths.
- std::string mDefaultSkinDir; // Location for default skin info.
- std::string mSkinDir; // Location for current skin info.
- std::string mUserDefaultSkinDir; // Location for default skin info.
- std::string mUserSkinDir; // Location for user-modified skin info.
- // Skin directories to search, most general to most specific. This order
- // works well for composing fine-grained files, in which an individual item
- // in a specific file overrides the corresponding item in more general
- // files. Of course, for a file-level search, iterate backwards.
- std::vector<std::string> mSearchSkinDirs;
- std::string mLanguage; // Current viewer language
- std::string mLLPluginDir; // Location for plugins and plugin shell
+ std::string mAppName; // install directory under progams/ ie "SecondLife"
+ std::string mExecutablePathAndName; // full path + Filename of .exe
+ std::string mExecutableFilename; // Filename of .exe
+ std::string mExecutableDir; // Location of executable
+ std::string mWorkingDir; // Current working directory
+ std::string mAppRODataDir; // Location for static app data
+ std::string mOSUserDir; // OS Specific user directory
+ std::string mOSUserAppDir; // OS Specific user app directory
+ std::string mLindenUserDir; // Location for Linden user-specific data
+ std::string mPerAccountChatLogsDir; // Location for chat logs.
+ std::string mChatLogsDir; // Location for chat logs.
+ std::string mCAFile; // Location of the TLS certificate authority PEM file.
+ std::string mTempDir;
+ std::string mCacheDir; // cache directory as set by user preference
+ std::string mDefaultCacheDir; // default cache diretory
+ std::string mOSCacheDir; // operating system cache dir
+ std::string mDirDelimiter;
+ std::string mSkinName; // caller-specified skin name
+ std::string mSkinBaseDir; // Base for skins paths.
+ std::string mDefaultSkinDir; // Location for default skin info.
+ std::string mSkinDir; // Location for current skin info.
+ std::string mUserDefaultSkinDir; // Location for default skin info.
+ std::string mUserSkinDir; // Location for user-modified skin info.
+ // Skin directories to search, most general to most specific. This order
+ // works well for composing fine-grained files, in which an individual item
+ // in a specific file overrides the corresponding item in more general
+ // files. Of course, for a file-level search, iterate backwards.
+ std::vector<std::string> mSearchSkinDirs;
+ std::string mLanguage; // Current viewer language
+ std::string mLLPluginDir; // Location for plugins and plugin shell
static std::string sDumpDir; // Per-run crash report subdir of log directory.
- std::string mUserName; // Current user name
+ std::string mUserName; // Current user name
};
void dir_exists_or_crash(const std::string &dir_name);
diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp
index 49fc1afd82..ffcd7d257f 100644
--- a/indra/llimage/tests/llimageworker_test.cpp
+++ b/indra/llimage/tests/llimageworker_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llimageworker_test.cpp
* @author Merov Linden
* @date 2009-04-28
@@ -6,28 +6,28 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
// Precompiled header: almost always required for newview cpp files
#include "linden_common.h"
-// Class to test
+// Class to test
#include "../llimageworker.h"
// For timer class
#include "../llcommon/lltimer.h"
@@ -38,13 +38,13 @@
// -------------------------------------------------------------------------------------------
// Stubbing: Declarations required to link and run the class being tested
-// Notes:
+// Notes:
// * Add here stubbed implementation of the few classes and methods used in the class to be tested
// * Add as little as possible (let the link errors guide you)
// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
// * A simulator for a class can be implemented here. Please comment and document thoroughly.
-LLImageBase::LLImageBase()
+LLImageBase::LLImageBase()
: mData(NULL),
mDataSize(0),
mWidth(0),
@@ -78,91 +78,91 @@ U8* LLImageBase::getData() { return NULL; }
namespace tut
{
- // Test wrapper declarations
+ // Test wrapper declarations
- // Note: We derive the responder class for 2 reasons:
- // 1. It's a pure virtual class and we can't compile without completed() being implemented
- // 2. We actually need a responder to test that the thread work test completed
- // We implement this making no assumption on what's done in the thread or worker
- // though, just that the responder's completed() method is called in the end.
- // Note on responders: responders are ref counted and *will* be deleted by the request they are
- // attached to when the queued request is deleted. The recommended way of using them is to
- // create them when creating a request, put a callback method in completed() and not rely on
- // anything to survive in the responder object once completed() has been called. Let the request
- // do the deletion and clean up itself.
- class responder_test : public LLImageDecodeThread::Responder
- {
- public:
- responder_test(bool* res)
- {
- done = res;
- *done = false;
- }
- virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32)
- {
- *done = true;
- }
- private:
- // This is what can be thought of as the minimal implementation of a responder
- // Done will be switched to true when completed() is called and can be tested
- // outside the responder. A better way of doing this is to store a callback here.
- bool* done;
- };
+ // Note: We derive the responder class for 2 reasons:
+ // 1. It's a pure virtual class and we can't compile without completed() being implemented
+ // 2. We actually need a responder to test that the thread work test completed
+ // We implement this making no assumption on what's done in the thread or worker
+ // though, just that the responder's completed() method is called in the end.
+ // Note on responders: responders are ref counted and *will* be deleted by the request they are
+ // attached to when the queued request is deleted. The recommended way of using them is to
+ // create them when creating a request, put a callback method in completed() and not rely on
+ // anything to survive in the responder object once completed() has been called. Let the request
+ // do the deletion and clean up itself.
+ class responder_test : public LLImageDecodeThread::Responder
+ {
+ public:
+ responder_test(bool* res)
+ {
+ done = res;
+ *done = false;
+ }
+ virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32)
+ {
+ *done = true;
+ }
+ private:
+ // This is what can be thought of as the minimal implementation of a responder
+ // Done will be switched to true when completed() is called and can be tested
+ // outside the responder. A better way of doing this is to store a callback here.
+ bool* done;
+ };
- // Test wrapper declaration : decode thread
- struct imagedecodethread_test
- {
- // Instance to be tested
- LLImageDecodeThread* mThread;
- // Constructor and destructor of the test wrapper
- imagedecodethread_test()
- {
- mThread = NULL;
- }
- ~imagedecodethread_test()
- {
- delete mThread;
- }
- };
+ // Test wrapper declaration : decode thread
+ struct imagedecodethread_test
+ {
+ // Instance to be tested
+ LLImageDecodeThread* mThread;
+ // Constructor and destructor of the test wrapper
+ imagedecodethread_test()
+ {
+ mThread = NULL;
+ }
+ ~imagedecodethread_test()
+ {
+ delete mThread;
+ }
+ };
- // Tut templating thingamagic: test group, object and test instance
- typedef test_group<imagedecodethread_test> imagedecodethread_t;
- typedef imagedecodethread_t::object imagedecodethread_object_t;
- tut::imagedecodethread_t tut_imagedecodethread("LLImageDecodeThread");
+ // Tut templating thingamagic: test group, object and test instance
+ typedef test_group<imagedecodethread_test> imagedecodethread_t;
+ typedef imagedecodethread_t::object imagedecodethread_object_t;
+ tut::imagedecodethread_t tut_imagedecodethread("LLImageDecodeThread");
- // ---------------------------------------------------------------------------------------
- // Test functions
- // Notes:
- // * Test as many as you possibly can without requiring a full blown simulation of everything
- // * The tests are executed in sequence so the test instance state may change between calls
- // * Remember that you cannot test private methods with tut
- // ---------------------------------------------------------------------------------------
+ // ---------------------------------------------------------------------------------------
+ // Test functions
+ // Notes:
+ // * Test as many as you possibly can without requiring a full blown simulation of everything
+ // * The tests are executed in sequence so the test instance state may change between calls
+ // * Remember that you cannot test private methods with tut
+ // ---------------------------------------------------------------------------------------
- // ---------------------------------------------------------------------------------------
- // Test the LLImageDecodeThread interface
- // ---------------------------------------------------------------------------------------
+ // ---------------------------------------------------------------------------------------
+ // Test the LLImageDecodeThread interface
+ // ---------------------------------------------------------------------------------------
- template<> template<>
- void imagedecodethread_object_t::test<1>()
- {
- // Test a *threaded* instance of the class
- mThread = new LLImageDecodeThread(true);
- ensure("LLImageDecodeThread: threaded constructor failed", mThread != NULL);
- // Insert something in the queue
- bool done = false;
- LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, 0, FALSE, new responder_test(&done));
- // Verifies we get back a valid handle
- ensure("LLImageDecodeThread: threaded decodeImage(), returned handle is null", decodeHandle != 0);
- // Wait till the thread has time to handle the work order (though it doesn't do much per work order...)
- const U32 INCREMENT_TIME = 500; // 500 milliseconds
- const U32 MAX_TIME = 20 * INCREMENT_TIME; // Do the loop 20 times max, i.e. wait 10 seconds but no more
- U32 total_time = 0;
- while ((done == false) && (total_time < MAX_TIME))
- {
- ms_sleep(INCREMENT_TIME);
- total_time += INCREMENT_TIME;
- }
- // Verifies that the responder has now been called
- ensure("LLImageDecodeThread: threaded work unit not processed", done == true);
- }
+ template<> template<>
+ void imagedecodethread_object_t::test<1>()
+ {
+ // Test a *threaded* instance of the class
+ mThread = new LLImageDecodeThread(true);
+ ensure("LLImageDecodeThread: threaded constructor failed", mThread != NULL);
+ // Insert something in the queue
+ bool done = false;
+ LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, 0, FALSE, new responder_test(&done));
+ // Verifies we get back a valid handle
+ ensure("LLImageDecodeThread: threaded decodeImage(), returned handle is null", decodeHandle != 0);
+ // Wait till the thread has time to handle the work order (though it doesn't do much per work order...)
+ const U32 INCREMENT_TIME = 500; // 500 milliseconds
+ const U32 MAX_TIME = 20 * INCREMENT_TIME; // Do the loop 20 times max, i.e. wait 10 seconds but no more
+ U32 total_time = 0;
+ while ((done == false) && (total_time < MAX_TIME))
+ {
+ ms_sleep(INCREMENT_TIME);
+ total_time += INCREMENT_TIME;
+ }
+ // Verifies that the responder has now been called
+ ensure("LLImageDecodeThread: threaded work unit not processed", done == true);
+ }
}
diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index 959cfb2762..c1c1db7437 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -41,7 +41,7 @@
//=========================================================================
// Map of pool sizes for known pools
static const std::map<std::string, U32> DefaultPoolSizes{
- {std::string("Upload"), 1},
+ {std::string("Upload"), 1},
{std::string("AIS"), 1},
// *TODO: Rider for the moment keep AIS calls serialized otherwise the COF will tend to get out of sync.
};
@@ -61,11 +61,11 @@ public:
LLCoprocedurePool(const std::string &name, size_t size);
~LLCoprocedurePool();
- /// Places the coprocedure on the queue for processing.
- ///
+ /// Places the coprocedure on the queue for processing.
+ ///
/// @param name Is used for debugging and should identify this coroutine.
- /// @param proc Is a bound function to be executed
- ///
+ /// @param proc Is a bound function to be executed
+ ///
/// @return This method returns a UUID that can be used later to cancel execution.
LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc);
@@ -91,7 +91,7 @@ public:
}
void close();
-
+
private:
struct QueuedCoproc
{
@@ -108,7 +108,7 @@ private:
CoProcedure_t mProc;
};
- // we use a buffered_channel here rather than unbuffered_channel since we want to be able to
+ // we use a buffered_channel here rather than unbuffered_channel since we want to be able to
// push values without blocking,even if there's currently no one calling a pop operation (due to
// fiber running right now)
typedef boost::fibers::buffered_channel<QueuedCoproc::ptr_t> CoprocQueue_t;
@@ -167,7 +167,7 @@ void LLCoprocedureManager::initializePool(const std::string &poolName)
if (size == 0)
{
- // if not found grab the know default... if there is no known
+ // if not found grab the know default... if there is no known
// default use a reasonable number like 5.
auto it = DefaultPoolSizes.find(poolName);
size = (it != DefaultPoolSizes.end()) ? it->second : DEFAULT_POOL_SIZE;
@@ -190,7 +190,7 @@ void LLCoprocedureManager::initializePool(const std::string &poolName)
//-------------------------------------------------------------------------
LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc)
{
- // Attempt to find the pool and enqueue the procedure. If the pool does
+ // Attempt to find the pool and enqueue the procedure. If the pool does
// not exist, create it.
poolMap_t::iterator it = mPoolMap.find(pool);
@@ -307,25 +307,20 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
{
try
{
- // store in our LLTempBoundListener so that when the LLCoprocedurePool is
- // destroyed, we implicitly disconnect from this LLEventPump
- // Monitores application status
- mStatusListener = LLEventPumps::instance().obtain("LLApp").listen(
+ // Store in our LLTempBoundListener so that when the LLCoprocedurePool is
+ // destroyed, we implicitly disconnect from this LLEventPump.
+ // Monitors application status.
+ mStatusListener = LLCoros::getStopListener(
poolName + "_pool", // Make sure it won't repeat names from lleventcoro
- [pendingCoprocs = mPendingCoprocs, poolName](const LLSD& status)
- {
- auto& statsd = status["status"];
- if (statsd.asString() != "running")
+ [pendingCoprocs = mPendingCoprocs, poolName](const LLSD& event)
{
LL_INFOS("CoProcMgr") << "Pool " << poolName
- << " closing queue because status " << statsd
+ << " closing queue because status " << event
<< LL_ENDL;
// This should ensure that all waiting coprocedures in this
// pool will wake up and terminate.
pendingCoprocs->close();
- }
- return false;
- });
+ });
}
catch (const LLEventPump::DupListenerName &)
{
@@ -334,7 +329,7 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
//
// If this somehow happens again it is better to crash later on shutdown due to pump
// not stopping coroutine and see warning in logs than on startup or during login.
- LL_WARNS("CoProcMgr") << "Attempted to register dupplicate listener name: " << poolName
+ LL_WARNS("CoProcMgr") << "Attempted to register duplicate listener name: " << poolName
<< "_pool. Failed to start listener." << LL_ENDL;
llassert(0); // Fix Me! Ignoring missing listener!
@@ -355,7 +350,7 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
LL_INFOS("CoProcMgr") << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items, queue max " << LLCoprocedureManager::DEFAULT_QUEUE_SIZE << LL_ENDL;
}
-LLCoprocedurePool::~LLCoprocedurePool()
+LLCoprocedurePool::~LLCoprocedurePool()
{
}
diff --git a/indra/llprimitive/tests/llgltfmaterial_test.cpp b/indra/llprimitive/tests/llgltfmaterial_test.cpp
index 143cf8e9c0..823a36ec3a 100644
--- a/indra/llprimitive/tests/llgltfmaterial_test.cpp
+++ b/indra/llprimitive/tests/llgltfmaterial_test.cpp
@@ -1,26 +1,26 @@
-/**
+/**
* @file llgltfmaterial_test.cpp
*
- * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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$
+ * $/LicenseInfo$
*/
#include "linden_common.h"
@@ -143,7 +143,7 @@ namespace tut
#if LL_WINDOWS
// If any fields are added/changed, these tests should be updated (consider also updating ASSET_VERSION in LLGLTFMaterial)
// This test result will vary between compilers, so only test a single platform
- ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 216);
+ ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 232);
#endif
#endif
ensure_equals("LLGLTFMaterial texture info count", (U32)LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT, 4);
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index a0314cb5f2..69e1b57245 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -49,6 +49,7 @@ set(llui_SOURCE_FILES
lllineeditor.cpp
llloadingindicator.cpp
lllocalcliprect.cpp
+ llluafloater.cpp
llmenubutton.cpp
llmenugl.cpp
llmodaldialog.cpp
@@ -164,6 +165,7 @@ set(llui_HEADER_FILES
lllineeditor.h
llloadingindicator.h
lllocalcliprect.h
+ llluafloater.h
llmenubutton.h
llmenugl.h
llmodaldialog.h
diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp
index aa3d1a1171..8316101264 100644
--- a/indra/llui/llfloaterreglistener.cpp
+++ b/indra/llui/llfloaterreglistener.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-08-12
* @brief Implementation for llfloaterreglistener.
- *
+ *
* $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$
*/
@@ -37,6 +37,7 @@
#include "llfloaterreg.h"
#include "llfloater.h"
#include "llbutton.h"
+#include "llluafloater.h"
LLFloaterRegListener::LLFloaterRegListener():
LLEventAPI("LLFloaterReg",
@@ -72,6 +73,13 @@ LLFloaterRegListener::LLFloaterRegListener():
"Simulate clicking the named [\"button\"] in the visible floater named in [\"name\"]",
&LLFloaterRegListener::clickButton,
requiredNameButton);
+
+ add("showLuaFloater",
+ "Open the new floater using XML file specified in [\"xml_path\"] with ID in [\"reqid\"]",
+ &LLLuaFloater::showLuaFloater, {llsd::map("xml_path", LLSD(), "reqid", LLSD())});
+ add("getFloaterEvents",
+ "Return the table of Lua Floater events which are send to the script",
+ &LLFloaterRegListener::getLuaFloaterEvents);
}
void LLFloaterRegListener::getBuildMap(const LLSD& event) const
@@ -154,3 +162,9 @@ void LLFloaterRegListener::clickButton(const LLSD& event) const
LLEventPumps::instance().obtain(replyPump).post(reply);
}
}
+
+void LLFloaterRegListener::getLuaFloaterEvents(const LLSD &event) const
+{
+ Response response(llsd::map("events", LLLuaFloater::getEventsData()), event);
+}
+
diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h
index a36072892c..9cb0af2de5 100644
--- a/indra/llui/llfloaterreglistener.h
+++ b/indra/llui/llfloaterreglistener.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-08-12
* @brief Wrap (subset of) LLFloaterReg API with an event API
- *
+ *
* $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$
*/
@@ -49,6 +49,8 @@ private:
void toggleInstance(const LLSD& event) const;
void instanceVisible(const LLSD& event) const;
void clickButton(const LLSD& event) const;
+
+ void getLuaFloaterEvents(const LLSD &event) const;
};
#endif /* ! defined(LL_LLFLOATERREGLISTENER_H) */
diff --git a/indra/llui/llluafloater.cpp b/indra/llui/llluafloater.cpp
new file mode 100644
index 0000000000..e584a67a00
--- /dev/null
+++ b/indra/llui/llluafloater.cpp
@@ -0,0 +1,295 @@
+/**
+ * @file llluafloater.cpp
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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 "llluafloater.h"
+
+#include "fsyspath.h"
+#include "llevents.h"
+
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llscrolllistctrl.h"
+#include "lltexteditor.h"
+
+const std::string LISTENER_NAME("LLLuaFloater");
+
+std::set<std::string> EVENT_LIST = {
+ "commit",
+ "double_click",
+ "mouse_enter",
+ "mouse_leave",
+ "mouse_down",
+ "mouse_up",
+ "right_mouse_down",
+ "right_mouse_up",
+ "post_build",
+ "floater_close",
+ "keystroke"
+};
+
+LLLuaFloater::LLLuaFloater(const LLSD &key) :
+ LLFloater(key),
+ mDispatchListener(LLUUID::generateNewID().asString(), "action"),
+ mReplyPumpName(key["reply"].asString()),
+ mReqID(key)
+{
+ auto ctrl_lookup = [this](const LLSD &event, std::function<LLSD(LLUICtrl*,const LLSD&)> cb)
+ {
+ LLUICtrl *ctrl = getChild<LLUICtrl>(event["ctrl_name"].asString());
+ if (!ctrl)
+ {
+ LL_WARNS("LuaFloater") << "Control not found: " << event["ctrl_name"] << LL_ENDL;
+ return LLSD();
+ }
+ return cb(ctrl, event);
+ };
+
+ LLSD requiredParams = llsd::map("ctrl_name", LLSD(), "value", LLSD());
+ mDispatchListener.add("set_enabled", "", [ctrl_lookup](const LLSD &event)
+ {
+ return ctrl_lookup(event, [](LLUICtrl *ctrl, const LLSD &event) { ctrl->setEnabled(event["value"].asBoolean()); return LLSD(); });
+ }, requiredParams);
+ mDispatchListener.add("set_visible", "", [ctrl_lookup](const LLSD &event)
+ {
+ return ctrl_lookup(event, [](LLUICtrl *ctrl, const LLSD &event) { ctrl->setVisible(event["value"].asBoolean()); return LLSD(); });
+ }, requiredParams);
+ mDispatchListener.add("set_value", "", [ctrl_lookup](const LLSD &event)
+ {
+ return ctrl_lookup(event, [](LLUICtrl *ctrl, const LLSD &event) { ctrl->setValue(event["value"]); return LLSD(); });
+ }, requiredParams);
+
+ mDispatchListener.add("add_list_element", "", [this](const LLSD &event)
+ {
+ LLScrollListCtrl *ctrl = getChild<LLScrollListCtrl>(event["ctrl_name"].asString());
+ if(ctrl)
+ {
+ LLSD element_data = event["value"];
+ if (element_data.isArray())
+ {
+ for (const auto &row : llsd::inArray(element_data))
+ {
+ ctrl->addElement(row);
+ }
+ }
+ else
+ {
+ ctrl->addElement(element_data);
+ }
+ }
+ }, requiredParams);
+
+ mDispatchListener.add("add_text", "", [this](const LLSD &event)
+ {
+ LLTextEditor *editor = getChild<LLTextEditor>(event["ctrl_name"].asString());
+ if (editor)
+ {
+ editor->pasteTextWithLinebreaks(stringize(event["value"]));
+ editor->addLineBreakChar(true);
+ }
+ }, requiredParams);
+
+ mDispatchListener.add("set_title", "", [this](const LLSD &event)
+ {
+ setTitle(event["value"].asString());
+ }, llsd::map("value", LLSD()));
+
+ mDispatchListener.add("get_value", "", [ctrl_lookup](const LLSD &event)
+ {
+ return ctrl_lookup(event, [](LLUICtrl *ctrl, const LLSD &event) { return llsd::map("value", ctrl->getValue()); });
+ }, llsd::map("ctrl_name", LLSD(), "reqid", LLSD()));
+}
+
+LLLuaFloater::~LLLuaFloater()
+{
+ //post empty LLSD() to indicate done, in case it wasn't handled by the script after CLOSE_EVENT
+ post(LLSD());
+}
+
+BOOL LLLuaFloater::postBuild()
+{
+ for (LLView *view : *getChildList())
+ {
+ LLUICtrl *ctrl = dynamic_cast<LLUICtrl*>(view);
+ if (ctrl)
+ {
+ LLSD data;
+ data["ctrl_name"] = view->getName();
+
+ ctrl->setCommitCallback([this, data](LLUICtrl *ctrl, const LLSD &param)
+ {
+ LLSD event(data);
+ event["value"] = ctrl->getValue();
+ postEvent(event, "commit");
+ });
+ }
+ }
+
+ //optional field to send additional specified events to the script
+ if (mKey.has("extra_events"))
+ {
+ //the first value is ctrl name, the second contains array of events to send
+ for (const auto &[name, data] : llsd::inMap(mKey["extra_events"]))
+ {
+ for (const auto &event : llsd::inArray(data))
+ {
+ registerCallback(name, event);
+ }
+ }
+ }
+
+ //send pump name to the script after the floater is built
+ postEvent(llsd::map("command_name", mDispatchListener.getPumpName()), "post_build");
+
+ return true;
+}
+
+void LLLuaFloater::onClose(bool app_quitting)
+{
+ postEvent(llsd::map("app_quitting", app_quitting), "floater_close");
+}
+
+bool event_is(const std::string &event_name, const std::string &list_event)
+{
+ llassert(EVENT_LIST.find(list_event) != EVENT_LIST.end());
+ return (event_name == list_event);
+}
+
+void LLLuaFloater::registerCallback(const std::string &ctrl_name, const std::string &event)
+{
+ LLUICtrl *ctrl = getChild<LLUICtrl>(ctrl_name);
+ if (!ctrl) return;
+
+ LLSD data;
+ data["ctrl_name"] = ctrl_name;
+ data["event"] = event;
+
+ auto mouse_event_cb = [this, data](LLUICtrl *ctrl, const LLSD &param) { post(data); };
+
+ auto mouse_event_coords_cb = [this, data](LLUICtrl *ctrl, S32 x, S32 y, MASK mask)
+ {
+ LLSD event(data);
+ post(event.with("x", x).with("y", y));
+ };
+
+ auto post_with_value = [this, data](LLSD value)
+ {
+ LLSD event(data);
+ post(event.with("value", value));
+ };
+
+ if (event_is(event, "mouse_enter"))
+ {
+ ctrl->setMouseEnterCallback(mouse_event_cb);
+ }
+ else if (event_is(event, "mouse_leave"))
+ {
+ ctrl->setMouseLeaveCallback(mouse_event_cb);
+ }
+ else if (event_is(event, "mouse_down"))
+ {
+ ctrl->setMouseDownCallback(mouse_event_coords_cb);
+ }
+ else if (event_is(event, "mouse_up"))
+ {
+ ctrl->setMouseUpCallback(mouse_event_coords_cb);
+ }
+ else if (event_is(event, "right_mouse_down"))
+ {
+ ctrl->setRightMouseDownCallback(mouse_event_coords_cb);
+ }
+ else if (event_is(event, "right_mouse_up"))
+ {
+ ctrl->setRightMouseUpCallback(mouse_event_coords_cb);
+ }
+ else if (event_is(event, "double_click"))
+ {
+ LLScrollListCtrl *list = dynamic_cast<LLScrollListCtrl *>(ctrl);
+ if (list)
+ {
+ list->setDoubleClickCallback( [post_with_value, list](){ post_with_value(LLSD(list->getCurrentID())); });
+ }
+ else
+ {
+ ctrl->setDoubleClickCallback(mouse_event_coords_cb);
+ }
+ }
+ else if (event_is(event, "keystroke"))
+ {
+ LLTextEditor* text_editor = dynamic_cast<LLTextEditor*>(ctrl);
+ if (text_editor)
+ {
+ text_editor->setKeystrokeCallback([post_with_value](LLTextEditor *editor) { post_with_value(editor->getValue()); });
+ }
+ LLLineEditor* line_editor = dynamic_cast<LLLineEditor*>(ctrl);
+ if (line_editor)
+ {
+ line_editor->setKeystrokeCallback([post_with_value](LLLineEditor *editor, void* userdata) { post_with_value(editor->getValue()); }, NULL);
+ }
+ }
+ else
+ {
+ LL_WARNS("LuaFloater") << "Can't register callback for unknown event: " << event << " , control: " << ctrl_name << LL_ENDL;
+ }
+}
+
+void LLLuaFloater::post(const LLSD &data)
+{
+ // send event data to the script signed with ["reqid"] key
+ LLSD stamped_data(data);
+ mReqID.stamp(stamped_data);
+ LLEventPumps::instance().obtain(mReplyPumpName).post(stamped_data);
+}
+
+void LLLuaFloater::postEvent(LLSD data, const std::string &event_name)
+{
+ llassert(EVENT_LIST.find(event_name) != EVENT_LIST.end());
+ post(data.with("event", event_name));
+}
+
+void LLLuaFloater::showLuaFloater(const LLSD &data)
+{
+ fsyspath fs_path(data["xml_path"].asString());
+ std::string path = fs_path.lexically_normal().u8string();
+ if (!fs_path.is_absolute())
+ {
+ std::string lib_path = gDirUtilp->getExpandedFilename(LL_PATH_SCRIPTS, "lua");
+ path = (fsyspath(lib_path) / path).u8string();
+ }
+
+ LLLuaFloater *floater = new LLLuaFloater(data);
+ floater->buildFromFile(path);
+ floater->openFloater(floater->getKey());
+}
+
+LLSD LLLuaFloater::getEventsData()
+{
+ LLSD event_data;
+ for (auto &it : EVENT_LIST)
+ {
+ event_data.append(it);
+ }
+ return event_data;
+}
diff --git a/indra/llui/llluafloater.h b/indra/llui/llluafloater.h
new file mode 100644
index 0000000000..ccc3ccb39b
--- /dev/null
+++ b/indra/llui/llluafloater.h
@@ -0,0 +1,54 @@
+/**
+ * @file llluafloater.h
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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_LLLUAFLOATER_H
+#define LL_LLLUAFLOATER_H
+
+#include "llfloater.h"
+#include "lleventdispatcher.h"
+#include "llevents.h"
+
+class LLLuaFloater : public LLFloater
+{
+public:
+ LLLuaFloater(const LLSD &key);
+ BOOL postBuild();
+ virtual ~LLLuaFloater();
+
+ void registerCallback(const std::string &ctrl_name, const std::string &event);
+ void onClose(bool app_quitting);
+
+ void post(const LLSD &data);
+ void postEvent(LLSD data, const std::string &event);
+ static void showLuaFloater(const LLSD &data);
+ static LLSD getEventsData();
+
+private:
+ LLReqID mReqID;
+ LLDispatchListener mDispatchListener;
+
+ std::string mReplyPumpName;
+};
+#endif
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 72e041672a..fdbfb38474 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmenugl.h
* @brief Declaration of the opengl based menu system.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -45,183 +45,183 @@ extern S32 MENU_BAR_WIDTH;
class LLMenuKeyboardBinding
{
public:
- KEY mKey;
- MASK mMask;
+ KEY mKey;
+ MASK mMask;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuItemGL
//
-// The LLMenuItemGL represents a single menu item in a menu.
+// The LLMenuItemGL represents a single menu item in a menu.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLMenuItemGL: public LLUICtrl, public ll::ui::SearchableControl
{
public:
- struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
- {
- Optional<std::string> shortcut;
- Optional<KEY> jump_key;
- Optional<bool> use_mac_ctrl,
- allow_key_repeat;
-
- Ignored rect,
- left,
- top,
- right,
- bottom,
- width,
- height,
- bottom_delta,
- left_delta;
-
- Optional<LLUIColor> enabled_color,
- disabled_color,
- highlight_bg_color,
- highlight_fg_color;
-
-
- Params();
- };
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<std::string> shortcut;
+ Optional<KEY> jump_key;
+ Optional<bool> use_mac_ctrl,
+ allow_key_repeat;
+
+ Ignored rect,
+ left,
+ top,
+ right,
+ bottom,
+ width,
+ height,
+ bottom_delta,
+ left_delta;
+
+ Optional<LLUIColor> enabled_color,
+ disabled_color,
+ highlight_bg_color,
+ highlight_fg_color;
+
+
+ Params();
+ };
protected:
- LLMenuItemGL(const Params&);
- friend class LLUICtrlFactory;
+ LLMenuItemGL(const Params&);
+ friend class LLUICtrlFactory;
public:
- // LLView overrides
- /*virtual*/ void onVisibilityChange(BOOL new_visibility);
- /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
-
- // LLUICtrl overrides
- /*virtual*/ void setValue(const LLSD& value);
- /*virtual*/ LLSD getValue() const;
-
- virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
- virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
-
- LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); }
-
- void setJumpKey(KEY key);
- KEY getJumpKey() const { return mJumpKey; }
-
- // set the font used by this item.
- void setFont(const LLFontGL* font) { mFont = font; }
- const LLFontGL* getFont() const { return mFont; }
-
- // returns the height in pixels for the current font.
- virtual U32 getNominalHeight( void ) const;
-
- // Marks item as not needing space for check marks or accelerator keys
- virtual void setBriefItem(BOOL brief);
- virtual BOOL isBriefItem() const;
-
- virtual BOOL addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp);
- void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; }
- BOOL getAllowKeyRepeat() const { return mAllowKeyRepeat; }
-
- // change the label
- void setLabel( const LLStringExplicit& label ) { mLabel = label; }
- std::string getLabel( void ) const { return mLabel.getString(); }
- virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
-
- // Get the parent menu for this item
- virtual class LLMenuGL* getMenu() const;
-
- // returns the normal width of this control in pixels - this is
- // used for calculating the widest item, as well as for horizontal
- // arrangement.
- virtual U32 getNominalWidth( void ) const;
-
- // buildDrawLabel() - constructs the string used during the draw()
- // function. This reduces the overall string manipulation, but can
- // lead to visual errors if the state of the object changes
- // without the knowledge of the menu item. For example, if a
- // boolean being watched is changed outside of the menu item's
- // onCommit() function, the draw buffer will not be updated and will
- // reflect the wrong value. If this ever becomes an issue, there
- // are ways to fix this.
- // Returns the enabled state of the item.
- virtual void buildDrawLabel( void );
-
- // for branching menu items, bring sub menus up to root level of menu hierarchy
- virtual void updateBranchParent( LLView* parentp ){};
-
- virtual void onCommit( void );
-
- virtual void setHighlight( BOOL highlight );
- virtual BOOL getHighlight() const { return mHighlight; }
-
- // determine if this represents an active sub-menu
- virtual BOOL isActive( void ) const { return FALSE; }
-
- // determine if this represents an open sub-menu
- virtual BOOL isOpen( void ) const { return FALSE; }
-
- virtual void setEnabledSubMenus(BOOL enable){};
-
- // LLView Functionality
- 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 handleScrollWheel( S32 x, S32 y, S32 clicks );
-
- virtual void onMouseEnter(S32 x, S32 y, MASK mask);
- virtual void onMouseLeave(S32 x, S32 y, MASK mask);
-
- virtual void draw( void );
-
- BOOL getHover() const { return mGotHover; }
-
- void setDrawTextDisabled(BOOL disabled) { mDrawTextDisabled = disabled; }
- BOOL getDrawTextDisabled() const { return mDrawTextDisabled; }
+ // LLView overrides
+ /*virtual*/ void onVisibilityChange(BOOL new_visibility);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
+
+ // LLUICtrl overrides
+ /*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ LLSD getValue() const;
+
+ virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
+ virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
+
+ LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); }
+
+ void setJumpKey(KEY key);
+ KEY getJumpKey() const { return mJumpKey; }
+
+ // set the font used by this item.
+ void setFont(const LLFontGL* font) { mFont = font; }
+ const LLFontGL* getFont() const { return mFont; }
+
+ // returns the height in pixels for the current font.
+ virtual U32 getNominalHeight( void ) const;
+
+ // Marks item as not needing space for check marks or accelerator keys
+ virtual void setBriefItem(BOOL brief);
+ virtual BOOL isBriefItem() const;
+
+ virtual BOOL addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp);
+ void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; }
+ BOOL getAllowKeyRepeat() const { return mAllowKeyRepeat; }
+
+ // change the label
+ void setLabel( const LLStringExplicit& label ) { mLabel = label; }
+ std::string getLabel( void ) const { return mLabel.getString(); }
+ virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
+
+ // Get the parent menu for this item
+ virtual class LLMenuGL* getMenu() const;
+
+ // returns the normal width of this control in pixels - this is
+ // used for calculating the widest item, as well as for horizontal
+ // arrangement.
+ virtual U32 getNominalWidth( void ) const;
+
+ // buildDrawLabel() - constructs the string used during the draw()
+ // function. This reduces the overall string manipulation, but can
+ // lead to visual errors if the state of the object changes
+ // without the knowledge of the menu item. For example, if a
+ // boolean being watched is changed outside of the menu item's
+ // onCommit() function, the draw buffer will not be updated and will
+ // reflect the wrong value. If this ever becomes an issue, there
+ // are ways to fix this.
+ // Returns the enabled state of the item.
+ virtual void buildDrawLabel( void );
+
+ // for branching menu items, bring sub menus up to root level of menu hierarchy
+ virtual void updateBranchParent( LLView* parentp ){};
+
+ virtual void onCommit( void );
+
+ virtual void setHighlight( BOOL highlight );
+ virtual BOOL getHighlight() const { return mHighlight; }
+
+ // determine if this represents an active sub-menu
+ virtual BOOL isActive( void ) const { return FALSE; }
+
+ // determine if this represents an open sub-menu
+ virtual BOOL isOpen( void ) const { return FALSE; }
+
+ virtual void setEnabledSubMenus(BOOL enable){};
+
+ // LLView Functionality
+ 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 handleScrollWheel( S32 x, S32 y, S32 clicks );
+
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+
+ virtual void draw( void );
+
+ BOOL getHover() const { return mGotHover; }
+
+ void setDrawTextDisabled(BOOL disabled) { mDrawTextDisabled = disabled; }
+ BOOL getDrawTextDisabled() const { return mDrawTextDisabled; }
protected:
- void setHover(BOOL hover) { mGotHover = hover; }
+ void setHover(BOOL hover) { mGotHover = hover; }
- // This function appends the character string representation of
- // the current accelerator key and mask to the provided string.
- void appendAcceleratorString( std::string& st ) const;
+ // This function appends the character string representation of
+ // the current accelerator key and mask to the provided string.
+ void appendAcceleratorString( std::string& st ) const;
- virtual std::string _getSearchText() const
- {
- return mLabel.getString();
- }
+ virtual std::string _getSearchText() const
+ {
+ return mLabel.getString();
+ }
protected:
- KEY mAcceleratorKey;
- MASK mAcceleratorMask;
- // mLabel contains the actual label specified by the user.
- LLUIString mLabel;
-
- // The draw labels contain some of the labels that we draw during
- // the draw() routine. This optimizes away some of the string
- // manipulation.
- LLUIString mDrawBoolLabel;
- LLUIString mDrawAccelLabel;
- LLUIString mDrawBranchLabel;
-
- LLUIColor mEnabledColor;
- LLUIColor mDisabledColor;
- LLUIColor mHighlightBackground;
- LLUIColor mHighlightForeground;
-
- BOOL mHighlight;
+ KEY mAcceleratorKey;
+ MASK mAcceleratorMask;
+ // mLabel contains the actual label specified by the user.
+ LLUIString mLabel;
+
+ // The draw labels contain some of the labels that we draw during
+ // the draw() routine. This optimizes away some of the string
+ // manipulation.
+ LLUIString mDrawBoolLabel;
+ LLUIString mDrawAccelLabel;
+ LLUIString mDrawBranchLabel;
+
+ LLUIColor mEnabledColor;
+ LLUIColor mDisabledColor;
+ LLUIColor mHighlightBackground;
+ LLUIColor mHighlightForeground;
+
+ BOOL mHighlight;
private:
- // Keyboard and mouse variables
- BOOL mAllowKeyRepeat;
- BOOL mGotHover;
+ // Keyboard and mouse variables
+ BOOL mAllowKeyRepeat;
+ BOOL mGotHover;
- // If true, suppress normal space for check marks on the left and accelerator
- // keys on the right.
- BOOL mBriefItem;
+ // If true, suppress normal space for check marks on the left and accelerator
+ // keys on the right.
+ BOOL mBriefItem;
- // Font for this item
- const LLFontGL* mFont;
- BOOL mDrawTextDisabled;
+ // Font for this item
+ const LLFontGL* mFont;
+ BOOL mDrawTextDisabled;
- KEY mJumpKey;
+ KEY mJumpKey;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -232,22 +232,22 @@ private:
class LLMenuItemSeparatorGL : public LLMenuItemGL
{
public:
- struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
- {
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
Optional<EnableCallbackParam > on_visible;
Params();
- };
+ };
LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p = LLMenuItemSeparatorGL::Params());
- /*virtual*/ void draw( void );
- /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ void draw( void );
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
virtual void buildDrawLabel();
- /*virtual*/ U32 getNominalHeight( void ) const;
+ /*virtual*/ U32 getNominalHeight( void ) const;
private:
enable_signal_t mVisibleSignal;
@@ -263,49 +263,49 @@ private:
class LLMenuItemCallGL : public LLMenuItemGL
{
public:
- struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
- {
- Optional<EnableCallbackParam > on_enable;
- Optional<CommitCallbackParam > on_click;
- Optional<EnableCallbackParam > on_visible;
- Params()
- : on_enable("on_enable"),
- on_click("on_click"),
- on_visible("on_visible")
- {}
- };
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
+ Optional<EnableCallbackParam > on_enable;
+ Optional<CommitCallbackParam > on_click;
+ Optional<EnableCallbackParam > on_visible;
+ Params()
+ : on_enable("on_enable"),
+ on_click("on_click"),
+ on_visible("on_visible")
+ {}
+ };
protected:
- LLMenuItemCallGL(const Params&);
- friend class LLUICtrlFactory;
- void updateEnabled( void );
- void updateVisible( void );
+ LLMenuItemCallGL(const Params&);
+ friend class LLUICtrlFactory;
+ void updateEnabled( void );
+ void updateVisible( void );
public:
- void initFromParams(const Params& p);
-
- // called to rebuild the draw label
- virtual void buildDrawLabel( void );
-
- virtual void onCommit( void );
-
- virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
- virtual BOOL handleKeyHere(KEY key, MASK mask);
-
- //virtual void draw();
-
- boost::signals2::connection setClickCallback( const commit_signal_t::slot_type& cb )
- {
- return setCommitCallback(cb);
- }
-
- boost::signals2::connection setEnableCallback( const enable_signal_t::slot_type& cb )
- {
- return mEnableSignal.connect(cb);
- }
-
+ void initFromParams(const Params& p);
+
+ // called to rebuild the draw label
+ virtual void buildDrawLabel( void );
+
+ virtual void onCommit( void );
+
+ virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ //virtual void draw();
+
+ boost::signals2::connection setClickCallback( const commit_signal_t::slot_type& cb )
+ {
+ return setCommitCallback(cb);
+ }
+
+ boost::signals2::connection setEnableCallback( const enable_signal_t::slot_type& cb )
+ {
+ return mEnableSignal.connect(cb);
+ }
+
private:
- enable_signal_t mEnableSignal;
- enable_signal_t mVisibleSignal;
+ enable_signal_t mEnableSignal;
+ enable_signal_t mVisibleSignal;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -318,40 +318,40 @@ private:
// EFFICIENT because it may need to be checked a lot.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLMenuItemCheckGL
-: public LLMenuItemCallGL
+class LLMenuItemCheckGL
+: public LLMenuItemCallGL
{
public:
- struct Params : public LLInitParam::Block<Params, LLMenuItemCallGL::Params>
- {
- Optional<EnableCallbackParam > on_check;
- Params()
- : on_check("on_check")
- {}
- };
+ struct Params : public LLInitParam::Block<Params, LLMenuItemCallGL::Params>
+ {
+ Optional<EnableCallbackParam > on_check;
+ Params()
+ : on_check("on_check")
+ {}
+ };
protected:
- LLMenuItemCheckGL(const Params&);
- friend class LLUICtrlFactory;
+ LLMenuItemCheckGL(const Params&);
+ friend class LLUICtrlFactory;
public:
-
- void initFromParams(const Params& p);
-
- virtual void onCommit( void );
-
- virtual void setValue(const LLSD& value);
- virtual LLSD getValue() const;
-
- // called to rebuild the draw label
- virtual void buildDrawLabel( void );
-
- boost::signals2::connection setCheckCallback( const enable_signal_t::slot_type& cb )
- {
- return mCheckSignal.connect(cb);
- }
-
+
+ void initFromParams(const Params& p);
+
+ virtual void onCommit( void );
+
+ virtual void setValue(const LLSD& value);
+ virtual LLSD getValue() const;
+
+ // called to rebuild the draw label
+ virtual void buildDrawLabel( void );
+
+ boost::signals2::connection setCheckCallback( const enable_signal_t::slot_type& cb )
+ {
+ return mCheckSignal.connect(cb);
+ }
+
private:
- enable_signal_t mCheckSignal;
+ enable_signal_t mCheckSignal;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -368,233 +368,234 @@ private:
// child widget registry
struct MenuRegistry : public LLChildRegistry<MenuRegistry>
{
- LLSINGLETON_EMPTY_CTOR(MenuRegistry);
+ LLSINGLETON_EMPTY_CTOR(MenuRegistry);
};
-class LLMenuGL
-: public LLUICtrl
+class LLMenuGL
+: public LLUICtrl
{
public:
- struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
- {
- Optional<KEY> jump_key;
- Optional<bool> horizontal_layout,
- can_tear_off,
- drop_shadow,
- bg_visible,
- create_jump_keys,
- keep_fixed_size,
- scrollable;
- Optional<U32> max_scrollable_items;
- Optional<U32> preferred_width;
- Optional<LLUIColor> bg_color;
- Optional<S32> shortcut_pad;
-
- Params()
- : jump_key("jump_key", KEY_NONE),
- horizontal_layout("horizontal_layout"),
- can_tear_off("tear_off", false),
- drop_shadow("drop_shadow", true),
- bg_visible("bg_visible", true),
- create_jump_keys("create_jump_keys", false),
- keep_fixed_size("keep_fixed_size", false),
- bg_color("bg_color", LLUIColorTable::instance().getColor( "MenuDefaultBgColor" )),
- scrollable("scrollable", false),
- max_scrollable_items("max_scrollable_items", U32_MAX),
- preferred_width("preferred_width", U32_MAX),
- shortcut_pad("shortcut_pad")
- {
- addSynonym(bg_visible, "opaque");
- addSynonym(bg_color, "color");
- addSynonym(can_tear_off, "can_tear_off");
- }
- };
-
- // my valid children are contained in MenuRegistry
- typedef MenuRegistry child_registry_t;
-
- void initFromParams(const Params&);
-
- // textual artwork which menugl-imitators may want to match
- static const std::string BOOLEAN_TRUE_PREFIX;
- static const std::string BRANCH_SUFFIX;
- static const std::string ARROW_UP;
- static const std::string ARROW_DOWN;
-
- // for scrollable menus
- typedef enum e_scrolling_direction
- {
- SD_UP = 0,
- SD_DOWN = 1,
- SD_BEGIN = 2,
- SD_END = 3
- } EScrollingDirection;
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<KEY> jump_key;
+ Optional<bool> horizontal_layout,
+ can_tear_off,
+ drop_shadow,
+ bg_visible,
+ create_jump_keys,
+ keep_fixed_size,
+ scrollable;
+ Optional<U32> max_scrollable_items;
+ Optional<U32> preferred_width;
+ Optional<LLUIColor> bg_color;
+ Optional<S32> shortcut_pad;
+
+ Params()
+ : jump_key("jump_key", KEY_NONE),
+ horizontal_layout("horizontal_layout"),
+ can_tear_off("tear_off", false),
+ drop_shadow("drop_shadow", true),
+ bg_visible("bg_visible", true),
+ create_jump_keys("create_jump_keys", false),
+ keep_fixed_size("keep_fixed_size", false),
+ bg_color("bg_color", LLUIColorTable::instance().getColor( "MenuDefaultBgColor" )),
+ scrollable("scrollable", false),
+ max_scrollable_items("max_scrollable_items", U32_MAX),
+ preferred_width("preferred_width", U32_MAX),
+ shortcut_pad("shortcut_pad")
+ {
+ addSynonym(bg_visible, "opaque");
+ addSynonym(bg_color, "color");
+ addSynonym(can_tear_off, "can_tear_off");
+ }
+ };
+
+ // my valid children are contained in MenuRegistry
+ typedef MenuRegistry child_registry_t;
+
+ void initFromParams(const Params&);
+
+ // textual artwork which menugl-imitators may want to match
+ static const std::string BOOLEAN_TRUE_PREFIX;
+ static const std::string BRANCH_SUFFIX;
+ static const std::string ARROW_UP;
+ static const std::string ARROW_DOWN;
+
+ // for scrollable menus
+ typedef enum e_scrolling_direction
+ {
+ SD_UP = 0,
+ SD_DOWN = 1,
+ SD_BEGIN = 2,
+ SD_END = 3
+ } EScrollingDirection;
protected:
- LLMenuGL(const LLMenuGL::Params& p);
- friend class LLUICtrlFactory;
- // let branching menu items use my protected traversal methods
- friend class LLMenuItemBranchGL;
+ LLMenuGL(const LLMenuGL::Params& p);
+ friend class LLUICtrlFactory;
+ // let branching menu items use my protected traversal methods
+ friend class LLMenuItemBranchGL;
public:
- virtual ~LLMenuGL( void );
-
- void parseChildXML(LLXMLNodePtr child, LLView* parent);
-
- // LLView Functionality
- /*virtual*/ BOOL handleUnicodeCharHere( llwchar uni_char );
- /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask );
- /*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
- /*virtual*/ void draw( void );
- /*virtual*/ void drawBackground(LLMenuItemGL* itemp, F32 alpha);
- /*virtual*/ void setVisible(BOOL visible);
- /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
+ virtual ~LLMenuGL( void );
+
+ void parseChildXML(LLXMLNodePtr child, LLView* parent);
+
+ // LLView Functionality
+ /*virtual*/ BOOL handleUnicodeCharHere( llwchar uni_char );
+ /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask );
+ /*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+ /*virtual*/ void draw( void );
+ /*virtual*/ void drawBackground(LLMenuItemGL* itemp, F32 alpha);
+ /*virtual*/ void setVisible(BOOL visible);
+ /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
/*virtual*/ void deleteAllChildren();
- /*virtual*/ void removeChild( LLView* ctrl);
- /*virtual*/ BOOL postBuild();
-
- virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
- virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
-
- LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const;
-
- BOOL clearHoverItem();
-
- // return the name label
- const std::string& getLabel( void ) const { return mLabel.getString(); }
- void setLabel(const LLStringExplicit& label) { mLabel = label; }
-
- // background colors
- void setBackgroundColor( const LLUIColor& color ) { mBackgroundColor = color; }
- const LLUIColor& getBackgroundColor() const { return mBackgroundColor; }
- void setBackgroundVisible( BOOL b ) { mBgVisible = b; }
- void setCanTearOff(BOOL tear_off);
-
- // add a separator to this menu
- virtual BOOL addSeparator();
-
- // for branching menu items, bring sub menus up to root level of menu hierarchy
- virtual void updateParent( LLView* parentp );
-
- // setItemEnabled() - pass the name and the enable flag for a
- // menu item. TRUE will make sure it's enabled, FALSE will disable
- // it.
- void setItemEnabled( const std::string& name, BOOL enable );
-
- // propagate message to submenus
- void setEnabledSubMenus(BOOL enable);
-
- void setItemVisible( const std::string& name, BOOL visible);
+ /*virtual*/ void removeChild( LLView* ctrl);
+ /*virtual*/ BOOL postBuild();
+
+ virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
+ virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
+
+ LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const;
+
+ BOOL clearHoverItem();
+
+ // return the name label
+ const std::string& getLabel( void ) const { return mLabel.getString(); }
+ void setLabel(const LLStringExplicit& label) { mLabel = label; }
+
+ // background colors
+ void setBackgroundColor( const LLUIColor& color ) { mBackgroundColor = color; }
+ const LLUIColor& getBackgroundColor() const { return mBackgroundColor; }
+ void setBackgroundVisible( BOOL b ) { mBgVisible = b; }
+ void setCanTearOff(BOOL tear_off);
+
+ // add a separator to this menu
+ virtual BOOL addSeparator();
+
+ // for branching menu items, bring sub menus up to root level of menu hierarchy
+ virtual void updateParent( LLView* parentp );
+
+ // setItemEnabled() - pass the name and the enable flag for a
+ // menu item. TRUE will make sure it's enabled, FALSE will disable
+ // it.
+ void setItemEnabled( const std::string& name, BOOL enable );
+
+ // propagate message to submenus
+ void setEnabledSubMenus(BOOL enable);
+
+ void setItemVisible( const std::string& name, BOOL visible);
void setItemLabel(const std::string &name, const std::string &label);
+
+ // sets the left,bottom corner of menu, useful for popups
+ void setLeftAndBottom(S32 left, S32 bottom);
- // sets the left,bottom corner of menu, useful for popups
- void setLeftAndBottom(S32 left, S32 bottom);
-
- virtual BOOL handleJumpKey(KEY key);
+ virtual BOOL handleJumpKey(KEY key);
- virtual BOOL jumpKeysActive();
+ virtual BOOL jumpKeysActive();
- virtual BOOL isOpen();
+ virtual BOOL isOpen();
- void needsArrange() { mNeedsArrange = TRUE; }
- // Shape this menu to fit the current state of the children, and
- // adjust the child rects to fit. This is called automatically
- // when you add items. *FIX: We may need to deal with visibility
- // arrangement.
- virtual void arrange( void );
- void arrangeAndClear( void );
+ void needsArrange() { mNeedsArrange = TRUE; }
+ // Shape this menu to fit the current state of the children, and
+ // adjust the child rects to fit. This is called automatically
+ // when you add items. *FIX: We may need to deal with visibility
+ // arrangement.
+ virtual void arrange( void );
+ void arrangeAndClear( void );
- // remove all items on the menu
- void empty( void );
+ // remove all items on the menu
+ void empty( void );
- // erase group of items from menu
- void erase( S32 begin, S32 end, bool arrange = true );
+ // erase group of items from menu
+ void erase( S32 begin, S32 end, bool arrange = true );
- // add new item at position
- void insert( S32 begin, LLView * ctrl, bool arrange = true );
+ // add new item at position
+ void insert( S32 begin, LLView * ctrl, bool arrange = true );
- void setItemLastSelected(LLMenuItemGL* item); // must be in menu
- U32 getItemCount(); // number of menu items
- LLMenuItemGL* getItem(S32 number); // 0 = first item
+ void setItemLastSelected(LLMenuItemGL* item); // must be in menu
+ U32 getItemCount(); // number of menu items
+ LLMenuItemGL* getItem(S32 number); // 0 = first item
LLMenuItemGL* getItem(std::string name);
- LLMenuItemGL* getHighlightedItem();
+ LLMenuItemGL* getHighlightedItem();
- LLMenuItemGL* highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disabled = TRUE);
- LLMenuItemGL* highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disabled = TRUE);
+ LLMenuItemGL* highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disabled = TRUE);
+ LLMenuItemGL* highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disabled = TRUE);
- void buildDrawLabels();
- void createJumpKeys();
+ void buildDrawLabels();
+ void createJumpKeys();
- // Show popup at a specific location, in the spawn_view's coordinate frame
- static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y, S32 mouse_x = 0, S32 mouse_y = 0);
+ // Show popup at a specific location, in the spawn_view's coordinate frame
+ static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y, S32 mouse_x = 0, S32 mouse_y = 0);
- // Whether to drop shadow menu bar
- void setDropShadowed( const BOOL shadowed );
+ // Whether to drop shadow menu bar
+ void setDropShadowed( const BOOL shadowed );
- void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item->getHandle(); }
- LLMenuItemGL* getParentMenuItem() const { return dynamic_cast<LLMenuItemGL*>(mParentMenuItem.get()); }
+ void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item->getHandle(); }
+ LLMenuItemGL* getParentMenuItem() const { return dynamic_cast<LLMenuItemGL*>(mParentMenuItem.get()); }
- void setTornOff(BOOL torn_off);
- BOOL getTornOff() { return mTornOff; }
+ void setTornOff(BOOL torn_off);
+ BOOL getTornOff() { return mTornOff; }
- BOOL getCanTearOff() { return mTearOffItem != NULL; }
+ BOOL getCanTearOff() { return mTearOffItem != NULL; }
- KEY getJumpKey() const { return mJumpKey; }
- void setJumpKey(KEY key) { mJumpKey = key; }
+ KEY getJumpKey() const { return mJumpKey; }
+ void setJumpKey(KEY key) { mJumpKey = key; }
- static void setKeyboardMode(BOOL mode) { sKeyboardMode = mode; }
- static BOOL getKeyboardMode() { return sKeyboardMode; }
+ static void setKeyboardMode(BOOL mode) { sKeyboardMode = mode; }
+ static BOOL getKeyboardMode() { return sKeyboardMode; }
- S32 getShortcutPad() { return mShortcutPad; }
+ S32 getShortcutPad() { return mShortcutPad; }
- bool scrollItems(EScrollingDirection direction);
- BOOL isScrollable() const { return mScrollable; }
+ bool scrollItems(EScrollingDirection direction);
+ BOOL isScrollable() const { return mScrollable; }
- static class LLMenuHolderGL* sMenuContainer;
+ static class LLMenuHolderGL* sMenuContainer;
+
+ void resetScrollPositionOnShow(bool reset_scroll_pos) { mResetScrollPositionOnShow = reset_scroll_pos; }
+ bool isScrollPositionOnShowReset() { return mResetScrollPositionOnShow; }
- void resetScrollPositionOnShow(bool reset_scroll_pos) { mResetScrollPositionOnShow = reset_scroll_pos; }
- bool isScrollPositionOnShowReset() { return mResetScrollPositionOnShow; }
+ void setAlwaysShowMenu(BOOL show) { mAlwaysShowMenu = show; }
+ BOOL getAlwaysShowMenu() { return mAlwaysShowMenu; }
- void setAlwaysShowMenu(BOOL show) { mAlwaysShowMenu = show; }
- BOOL getAlwaysShowMenu() { return mAlwaysShowMenu; }
+ // add a context menu branch
+ BOOL appendContextSubMenu(LLMenuGL *menu);
- // add a context menu branch
- BOOL appendContextSubMenu(LLMenuGL *menu);
-
- const LLFontGL *getFont() const { return mFont; }
-
- protected:
- void createSpilloverBranch();
- void cleanupSpilloverBranch();
// Add the menu item to this menu.
virtual BOOL append( LLMenuItemGL* item );
// add a menu - this will create a cascading menu
- virtual BOOL appendMenu( LLMenuGL* menu );
-
- // Used in LLContextMenu and in LLTogleableMenu
- // to add an item of context menu branch
- bool addContextChild(LLView* view, S32 tab_group);
-
- // TODO: create accessor methods for these?
- typedef std::list< LLMenuItemGL* > item_list_t;
- item_list_t mItems;
- LLMenuItemGL*mFirstVisibleItem;
- LLMenuItemGL *mArrowUpItem, *mArrowDownItem;
-
- typedef std::map<KEY, LLMenuItemGL*> navigation_key_map_t;
- navigation_key_map_t mJumpKeys;
- S32 mLastMouseX;
- S32 mLastMouseY;
- S32 mMouseVelX;
- S32 mMouseVelY;
- U32 mMaxScrollableItems;
- U32 mPreferredWidth;
- BOOL mHorizontalLayout;
- BOOL mScrollable;
- BOOL mKeepFixedSize;
- BOOL mNeedsArrange;
+ virtual BOOL appendMenu(LLMenuGL *menu);
+
+ const LLFontGL *getFont() const { return mFont; }
+
+protected:
+ void createSpilloverBranch();
+ void cleanupSpilloverBranch();
+
+ // Used in LLContextMenu and in LLTogleableMenu
+ // to add an item of context menu branch
+ bool addContextChild(LLView* view, S32 tab_group);
+
+ // TODO: create accessor methods for these?
+ typedef std::list< LLMenuItemGL* > item_list_t;
+ item_list_t mItems;
+ LLMenuItemGL*mFirstVisibleItem;
+ LLMenuItemGL *mArrowUpItem, *mArrowDownItem;
+
+ typedef std::map<KEY, LLMenuItemGL*> navigation_key_map_t;
+ navigation_key_map_t mJumpKeys;
+ S32 mLastMouseX;
+ S32 mLastMouseY;
+ S32 mMouseVelX;
+ S32 mMouseVelY;
+ U32 mMaxScrollableItems;
+ U32 mPreferredWidth;
+ BOOL mHorizontalLayout;
+ BOOL mScrollable;
+ BOOL mKeepFixedSize;
+ BOOL mNeedsArrange;
// Font for top menu items only
const LLFontGL* mFont;
@@ -602,27 +603,27 @@ public:
private:
- static LLColor4 sDefaultBackgroundColor;
- static BOOL sKeyboardMode;
-
- BOOL mAlwaysShowMenu;
-
- LLUIColor mBackgroundColor;
- BOOL mBgVisible;
- LLHandle<LLView> mParentMenuItem;
- LLUIString mLabel;
- BOOL mDropShadowed; // Whether to drop shadow
- bool mHasSelection;
- LLFrameTimer mFadeTimer;
- LLTimer mScrollItemsTimer;
- BOOL mTornOff;
- class LLMenuItemTearOffGL* mTearOffItem;
- class LLMenuItemBranchGL* mSpilloverBranch;
- LLMenuGL* mSpilloverMenu;
- KEY mJumpKey;
- BOOL mCreateJumpKeys;
- S32 mShortcutPad;
- bool mResetScrollPositionOnShow;
+ static LLColor4 sDefaultBackgroundColor;
+ static BOOL sKeyboardMode;
+
+ BOOL mAlwaysShowMenu;
+
+ LLUIColor mBackgroundColor;
+ BOOL mBgVisible;
+ LLHandle<LLView> mParentMenuItem;
+ LLUIString mLabel;
+ BOOL mDropShadowed; // Whether to drop shadow
+ bool mHasSelection;
+ LLFrameTimer mFadeTimer;
+ LLTimer mScrollItemsTimer;
+ BOOL mTornOff;
+ class LLMenuItemTearOffGL* mTearOffItem;
+ class LLMenuItemBranchGL* mSpilloverBranch;
+ LLMenuGL* mSpilloverMenu;
+ KEY mJumpKey;
+ BOOL mCreateJumpKeys;
+ S32 mShortcutPad;
+ bool mResetScrollPositionOnShow;
}; // end class LLMenuGL
@@ -637,61 +638,61 @@ private:
class LLMenuItemBranchGL : public LLMenuItemGL
{
public:
- struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
- {
- Optional<LLMenuGL*> branch;
- };
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
+ Optional<LLMenuGL*> branch;
+ };
protected:
- LLMenuItemBranchGL(const Params&);
- friend class LLUICtrlFactory;
+ LLMenuItemBranchGL(const Params&);
+ friend class LLUICtrlFactory;
public:
- virtual ~LLMenuItemBranchGL();
-
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual ~LLMenuItemBranchGL();
+
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
- virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
+ virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
+ virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
- // check if we've used these accelerators already
- virtual BOOL addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp);
+ // check if we've used these accelerators already
+ virtual BOOL addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp);
- // called to rebuild the draw label
- virtual void buildDrawLabel( void );
+ // called to rebuild the draw label
+ virtual void buildDrawLabel( void );
- virtual void onCommit( void );
+ virtual void onCommit( void );
- virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
- virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
+ virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+ virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
- // set the hover status (called by it's menu) and if the object is
- // active. This is used for behavior transfer.
- virtual void setHighlight( BOOL highlight );
+ // set the hover status (called by it's menu) and if the object is
+ // active. This is used for behavior transfer.
+ virtual void setHighlight( BOOL highlight );
- virtual BOOL handleKeyHere(KEY key, MASK mask);
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
- virtual BOOL isActive() const;
+ virtual BOOL isActive() const;
- virtual BOOL isOpen() const;
+ virtual BOOL isOpen() const;
- LLMenuGL* getBranch() const { return (LLMenuGL*)mBranchHandle.get(); }
+ LLMenuGL* getBranch() const { return (LLMenuGL*)mBranchHandle.get(); }
- virtual void updateBranchParent( LLView* parentp );
+ virtual void updateBranchParent( LLView* parentp );
- // LLView Functionality
- virtual void onVisibilityChange( BOOL curVisibilityIn );
+ // LLView Functionality
+ virtual void onVisibilityChange( BOOL curVisibilityIn );
- virtual void draw();
+ virtual void draw();
- virtual void setEnabledSubMenus(BOOL enabled) { if (getBranch()) getBranch()->setEnabledSubMenus(enabled); }
+ virtual void setEnabledSubMenus(BOOL enabled) { if (getBranch()) getBranch()->setEnabledSubMenus(enabled); }
- virtual void openMenu();
+ virtual void openMenu();
- virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const;
- virtual LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const;
+ virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const;
+ virtual LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const;
private:
- LLHandle<LLView> mBranchHandle;
+ LLHandle<LLView> mBranchHandle;
}; // end class LLMenuItemBranchGL
@@ -704,44 +705,44 @@ class LLContextMenu
: public LLMenuGL
{
public:
- struct Params : public LLInitParam::Block<Params, LLMenuGL::Params>
- {
- Params()
- {
- changeDefault(visible, false);
- }
- };
+ struct Params : public LLInitParam::Block<Params, LLMenuGL::Params>
+ {
+ Params()
+ {
+ changeDefault(visible, false);
+ }
+ };
protected:
- LLContextMenu(const Params& p);
- friend class LLUICtrlFactory;
+ LLContextMenu(const Params& p);
+ friend class LLUICtrlFactory;
public:
- virtual ~LLContextMenu() {}
-
- // LLView Functionality
- // can't set visibility directly, must call show or hide
- virtual void setVisible (BOOL visible);
+ virtual ~LLContextMenu() {}
- virtual void show (S32 x, S32 y, LLView* spawning_view = NULL);
- virtual void hide ();
+ // LLView Functionality
+ // can't set visibility directly, must call show or hide
+ virtual void setVisible (BOOL visible);
+
+ virtual void show (S32 x, S32 y, LLView* spawning_view = NULL);
+ virtual void hide ();
- virtual BOOL handleHover ( S32 x, S32 y, MASK mask );
- virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
- virtual BOOL handleRightMouseUp ( S32 x, S32 y, MASK mask );
+ virtual BOOL handleHover ( S32 x, S32 y, MASK mask );
+ virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+ virtual BOOL handleRightMouseUp ( S32 x, S32 y, MASK mask );
- virtual bool addChild (LLView* view, S32 tab_group = 0);
+ virtual bool addChild (LLView* view, S32 tab_group = 0);
- LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); }
+ LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); }
- LLView* getSpawningView() const { return mSpawningViewHandle.get(); }
- void setSpawningView(LLHandle<LLView> spawning_view) { mSpawningViewHandle = spawning_view; }
+ LLView* getSpawningView() const { return mSpawningViewHandle.get(); }
+ void setSpawningView(LLHandle<LLView> spawning_view) { mSpawningViewHandle = spawning_view; }
protected:
- BOOL mHoveredAnyItem;
- LLMenuItemGL* mHoverItem;
- LLRootHandle<LLContextMenu> mHandle;
- LLHandle<LLView> mSpawningViewHandle;
+ BOOL mHoveredAnyItem;
+ LLMenuItemGL* mHoverItem;
+ LLRootHandle<LLContextMenu> mHandle;
+ LLHandle<LLView> mSpawningViewHandle;
};
//-----------------------------------------------------------------------------
@@ -751,28 +752,28 @@ protected:
class LLContextMenuBranch : public LLMenuItemGL
{
public:
- struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
- {
- Mandatory<LLContextMenu*> branch;
- };
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
+ Mandatory<LLContextMenu*> branch;
+ };
- LLContextMenuBranch(const Params&);
+ LLContextMenuBranch(const Params&);
- virtual ~LLContextMenuBranch();
+ virtual ~LLContextMenuBranch();
- // called to rebuild the draw label
- virtual void buildDrawLabel( void );
+ // called to rebuild the draw label
+ virtual void buildDrawLabel( void );
- // onCommit() - do the primary funcationality of the menu item.
- virtual void onCommit( void );
+ // onCommit() - do the primary funcationality of the menu item.
+ virtual void onCommit( void );
- LLContextMenu* getBranch() { return mBranch.get(); }
- void setHighlight( BOOL highlight );
+ LLContextMenu* getBranch() { return mBranch.get(); }
+ void setHighlight( BOOL highlight );
protected:
- void showSubMenu();
+ void showSubMenu();
- LLHandle<LLContextMenu> mBranch;
+ LLHandle<LLContextMenu> mBranch;
};
@@ -785,42 +786,43 @@ protected:
class LLMenuBarGL : public LLMenuGL
{
public:
- struct Params : public LLInitParam::Block<Params, LLMenuGL::Params>
- {};
- LLMenuBarGL( const Params& p );
- virtual ~LLMenuBarGL();
+ struct Params : public LLInitParam::Block<Params, LLMenuGL::Params>
+ {};
+ LLMenuBarGL( const Params& p );
+ virtual ~LLMenuBarGL();
- /*virtual*/ BOOL handleAcceleratorKey(KEY key, MASK mask);
- /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
- /*virtual*/ BOOL handleJumpKey(KEY key);
- /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleAcceleratorKey(KEY key, MASK mask);
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+ /*virtual*/ BOOL handleJumpKey(KEY key);
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
- /*virtual*/ void draw();
- /*virtual*/ BOOL jumpKeysActive();
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL jumpKeysActive();
- // add a vertical separator to this menu
- virtual BOOL addSeparator();
+ // add a vertical separator to this menu
+ virtual BOOL addSeparator();
- // LLView Functionality
- virtual BOOL handleHover( S32 x, S32 y, MASK mask );
+ // LLView Functionality
+ virtual BOOL handleHover( S32 x, S32 y, MASK mask );
- // Returns x position of rightmost child, usually Help menu
- S32 getRightmostMenuEdge();
+ // Returns x position of rightmost child, usually Help menu
+ S32 getRightmostMenuEdge();
- void resetMenuTrigger() { mAltKeyTrigger = FALSE; }
+ void resetMenuTrigger() { mAltKeyTrigger = FALSE; }
-private:
// add a menu - this will create a drop down menu.
- virtual BOOL appendMenu( LLMenuGL* menu );
- // rearrange the child rects so they fit the shape of the menu
- // bar.
- virtual void arrange( void );
+ virtual BOOL appendMenu(LLMenuGL *menu);
- void checkMenuTrigger();
+private:
+ // rearrange the child rects so they fit the shape of the menu
+ // bar.
+ virtual void arrange( void );
- std::list <LLMenuKeyboardBinding*> mAccelerators;
- BOOL mAltKeyTrigger;
+ void checkMenuTrigger();
+
+ std::list <LLMenuKeyboardBinding*> mAccelerators;
+ BOOL mAltKeyTrigger;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -831,39 +833,39 @@ private:
class LLMenuHolderGL : public LLPanel
{
public:
- struct Params : public LLInitParam::Block<Params, LLPanel::Params>
- {};
- LLMenuHolderGL(const Params& p);
- virtual ~LLMenuHolderGL() {}
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {};
+ LLMenuHolderGL(const Params& p);
+ virtual ~LLMenuHolderGL() {}
- virtual BOOL hideMenus();
- void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- void setCanHide(BOOL can_hide) { mCanHide = can_hide; }
+ virtual BOOL hideMenus();
+ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ void setCanHide(BOOL can_hide) { mCanHide = can_hide; }
- // LLView functionality
- virtual void draw();
- virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
- virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+ // LLView functionality
+ virtual void draw();
+ virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
+ virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
- // Close context menus on right mouse up not handled by menus.
- /*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask );
+ // Close context menus on right mouse up not handled by menus.
+ /*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask );
- virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
- virtual const LLRect getMenuRect() const { return getLocalRect(); }
- LLView*const getVisibleMenu() const;
- virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;}
+ virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+ virtual const LLRect getMenuRect() const { return getLocalRect(); }
+ LLView*const getVisibleMenu() const;
+ virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;}
- static void setActivatedItem(LLMenuItemGL* item);
+ static void setActivatedItem(LLMenuItemGL* item);
- // Need to detect if mouse-up after context menu spawn has moved.
- // If not, need to keep the menu up.
- static LLCoordGL sContextMenuSpawnPos;
+ // Need to detect if mouse-up after context menu spawn has moved.
+ // If not, need to keep the menu up.
+ static LLCoordGL sContextMenuSpawnPos;
private:
- static LLHandle<LLView> sItemLastSelectedHandle;
- static LLFrameTimer sItemActivationTimer;
+ static LLHandle<LLView> sItemLastSelectedHandle;
+ static LLFrameTimer sItemActivationTimer;
- BOOL mCanHide;
+ BOOL mCanHide;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -875,26 +877,26 @@ private:
class LLTearOffMenu : public LLFloater
{
public:
- static LLTearOffMenu* create(LLMenuGL* menup);
- virtual ~LLTearOffMenu();
+ static LLTearOffMenu* create(LLMenuGL* menup);
+ virtual ~LLTearOffMenu();
- virtual void draw(void);
- virtual void onFocusReceived();
- virtual void onFocusLost();
- virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
- virtual BOOL handleKeyHere(KEY key, MASK mask);
- virtual void translate(S32 x, S32 y);
+ virtual void draw(void);
+ virtual void onFocusReceived();
+ virtual void onFocusLost();
+ virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+ virtual void translate(S32 x, S32 y);
- void updateSize();
+ void updateSize();
private:
- LLTearOffMenu(LLMenuGL* menup);
-
- void closeTearOff();
-
- LLView* mOldParent;
- LLMenuGL* mMenu;
- S32 mTargetHeight;
+ LLTearOffMenu(LLMenuGL* menup);
+
+ void closeTearOff();
+
+ LLView* mOldParent;
+ LLMenuGL* mMenu;
+ S32 mTargetHeight;
bool mQuitRequested;
};
@@ -907,16 +909,16 @@ private:
class LLMenuItemTearOffGL : public LLMenuItemGL
{
public:
- struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
- {};
-
- LLMenuItemTearOffGL( const Params& );
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {};
- virtual void onCommit(void);
- virtual void draw(void);
- virtual U32 getNominalHeight() const;
+ LLMenuItemTearOffGL( const Params& );
+
+ virtual void onCommit(void);
+ virtual void draw(void);
+ virtual U32 getNominalHeight() const;
- LLFloater* getParentFloater();
+ LLFloater* getParentFloater();
};
@@ -924,13 +926,13 @@ public:
class LLEditMenuHandlerMgr
{
public:
- LLEditMenuHandlerMgr& getInstance() {
- static LLEditMenuHandlerMgr instance;
- return instance;
- }
- virtual ~LLEditMenuHandlerMgr() {}
+ LLEditMenuHandlerMgr& getInstance() {
+ static LLEditMenuHandlerMgr instance;
+ return instance;
+ }
+ virtual ~LLEditMenuHandlerMgr() {}
private:
- LLEditMenuHandlerMgr() {};
+ LLEditMenuHandlerMgr() {};
};
@@ -939,40 +941,40 @@ private:
class view_listener_t : public boost::signals2::trackable
{
public:
- virtual bool handleEvent(const LLSD& userdata) = 0;
- view_listener_t() { sListeners.insert(this); }
- virtual ~view_listener_t() { sListeners.erase(this); }
-
- static void addEnable(view_listener_t* listener, const std::string& name)
- {
- LLUICtrl::EnableCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2));
- }
-
- static void addCommit(view_listener_t* listener, const std::string& name)
- {
- LLUICtrl::CommitCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2));
- }
-
- static void addMenu(view_listener_t* listener, const std::string& name)
- {
- // For now, add to both click and enable registries
- addEnable(listener, name);
- addCommit(listener, name);
- }
-
- static void cleanup()
- {
- listener_vector_t listeners(sListeners.begin(), sListeners.end());
- sListeners.clear();
-
- std::for_each(listeners.begin(), listeners.end(), DeletePointer());
- listeners.clear();
- }
+ virtual bool handleEvent(const LLSD& userdata) = 0;
+ view_listener_t() { sListeners.insert(this); }
+ virtual ~view_listener_t() { sListeners.erase(this); }
+
+ static void addEnable(view_listener_t* listener, const std::string& name)
+ {
+ LLUICtrl::EnableCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2));
+ }
+
+ static void addCommit(view_listener_t* listener, const std::string& name)
+ {
+ LLUICtrl::CommitCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2));
+ }
+
+ static void addMenu(view_listener_t* listener, const std::string& name)
+ {
+ // For now, add to both click and enable registries
+ addEnable(listener, name);
+ addCommit(listener, name);
+ }
+
+ static void cleanup()
+ {
+ listener_vector_t listeners(sListeners.begin(), sListeners.end());
+ sListeners.clear();
+
+ std::for_each(listeners.begin(), listeners.end(), DeletePointer());
+ listeners.clear();
+ }
private:
- typedef std::set<view_listener_t*> listener_map_t;
- typedef std::vector<view_listener_t*> listener_vector_t;
- static listener_map_t sListeners;
+ typedef std::set<view_listener_t*> listener_map_t;
+ typedef std::vector<view_listener_t*> listener_vector_t;
+ static listener_map_t sListeners;
};
#endif // LL_LLMENUGL_H
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 4fd650f2da..d6fc7d5377 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file lltexteditor.cpp
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -32,7 +32,7 @@
#include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR
#include "llfontgl.h"
-#include "llgl.h" // LLGLSUIDefault()
+#include "llgl.h" // LLGLSUIDefault()
#include "lllocalcliprect.h"
#include "llrender.h"
#include "llui.h"
@@ -64,105 +64,105 @@
#include <queue>
#include "llcombobox.h"
-//
+//
// Globals
//
static LLDefaultChildRegistry::Register<LLTextEditor> r("simple_text_editor");
// Compiler optimization, generate extern template
template class LLTextEditor* LLView::getChild<class LLTextEditor>(
- const std::string& name, BOOL recurse) const;
+ const std::string& name, BOOL recurse) const;
//
// Constants
//
-const S32 SPACES_PER_TAB = 4;
-const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on
+const S32 SPACES_PER_TAB = 4;
+const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on
///////////////////////////////////////////////////////////////////
class LLTextEditor::TextCmdInsert : public LLTextBase::TextCmd
{
public:
- TextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment)
- : TextCmd(pos, group_with_next, segment), mWString(ws)
- {
- }
- virtual ~TextCmdInsert() {}
- virtual BOOL execute( LLTextBase* editor, S32* delta )
- {
- *delta = insert(editor, getPosition(), mWString );
- LLWStringUtil::truncate(mWString, *delta);
- //mWString = wstring_truncate(mWString, *delta);
- return (*delta != 0);
- }
- virtual S32 undo( LLTextBase* editor )
- {
- remove(editor, getPosition(), mWString.length() );
- return getPosition();
- }
- virtual S32 redo( LLTextBase* editor )
- {
- insert(editor, getPosition(), mWString );
- return getPosition() + mWString.length();
- }
+ TextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment)
+ : TextCmd(pos, group_with_next, segment), mWString(ws)
+ {
+ }
+ virtual ~TextCmdInsert() {}
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
+ {
+ *delta = insert(editor, getPosition(), mWString );
+ LLWStringUtil::truncate(mWString, *delta);
+ //mWString = wstring_truncate(mWString, *delta);
+ return (*delta != 0);
+ }
+ virtual S32 undo( LLTextBase* editor )
+ {
+ remove(editor, getPosition(), mWString.length() );
+ return getPosition();
+ }
+ virtual S32 redo( LLTextBase* editor )
+ {
+ insert(editor, getPosition(), mWString );
+ return getPosition() + mWString.length();
+ }
private:
- LLWString mWString;
+ LLWString mWString;
};
///////////////////////////////////////////////////////////////////
class LLTextEditor::TextCmdAddChar : public LLTextBase::TextCmd
{
public:
- TextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment)
- : TextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE)
- {
- }
- virtual void blockExtensions()
- {
- mBlockExtensions = TRUE;
- }
- virtual BOOL canExtend(S32 pos) const
- {
- // cannot extend text with custom segments
- if (!mSegments.empty()) return FALSE;
-
- return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length());
- }
- virtual BOOL execute( LLTextBase* editor, S32* delta )
- {
- *delta = insert(editor, getPosition(), mWString);
- LLWStringUtil::truncate(mWString, *delta);
- //mWString = wstring_truncate(mWString, *delta);
- return (*delta != 0);
- }
- virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar wc, S32* delta )
- {
- LLWString ws;
- ws += wc;
-
- *delta = insert(editor, pos, ws);
- if( *delta > 0 )
- {
- mWString += wc;
- }
- return (*delta != 0);
- }
- virtual S32 undo( LLTextBase* editor )
- {
- remove(editor, getPosition(), mWString.length() );
- return getPosition();
- }
- virtual S32 redo( LLTextBase* editor )
- {
- insert(editor, getPosition(), mWString );
- return getPosition() + mWString.length();
- }
+ TextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment)
+ : TextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE)
+ {
+ }
+ virtual void blockExtensions()
+ {
+ mBlockExtensions = TRUE;
+ }
+ virtual BOOL canExtend(S32 pos) const
+ {
+ // cannot extend text with custom segments
+ if (!mSegments.empty()) return FALSE;
+
+ return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length());
+ }
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
+ {
+ *delta = insert(editor, getPosition(), mWString);
+ LLWStringUtil::truncate(mWString, *delta);
+ //mWString = wstring_truncate(mWString, *delta);
+ return (*delta != 0);
+ }
+ virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar wc, S32* delta )
+ {
+ LLWString ws;
+ ws += wc;
+
+ *delta = insert(editor, pos, ws);
+ if( *delta > 0 )
+ {
+ mWString += wc;
+ }
+ return (*delta != 0);
+ }
+ virtual S32 undo( LLTextBase* editor )
+ {
+ remove(editor, getPosition(), mWString.length() );
+ return getPosition();
+ }
+ virtual S32 redo( LLTextBase* editor )
+ {
+ insert(editor, getPosition(), mWString );
+ return getPosition() + mWString.length();
+ }
private:
- LLWString mWString;
- BOOL mBlockExtensions;
+ LLWString mWString;
+ BOOL mBlockExtensions;
};
@@ -171,30 +171,30 @@ private:
class LLTextEditor::TextCmdOverwriteChar : public LLTextBase::TextCmd
{
public:
- TextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc)
- : TextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {}
-
- virtual BOOL execute( LLTextBase* editor, S32* delta )
- {
- mOldChar = editor->getWText()[getPosition()];
- overwrite(editor, getPosition(), mChar);
- *delta = 0;
- return TRUE;
- }
- virtual S32 undo( LLTextBase* editor )
- {
- overwrite(editor, getPosition(), mOldChar);
- return getPosition();
- }
- virtual S32 redo( LLTextBase* editor )
- {
- overwrite(editor, getPosition(), mChar);
- return getPosition()+1;
- }
+ TextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc)
+ : TextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {}
+
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
+ {
+ mOldChar = editor->getWText()[getPosition()];
+ overwrite(editor, getPosition(), mChar);
+ *delta = 0;
+ return TRUE;
+ }
+ virtual S32 undo( LLTextBase* editor )
+ {
+ overwrite(editor, getPosition(), mOldChar);
+ return getPosition();
+ }
+ virtual S32 redo( LLTextBase* editor )
+ {
+ overwrite(editor, getPosition(), mChar);
+ return getPosition()+1;
+ }
private:
- llwchar mChar;
- llwchar mOldChar;
+ llwchar mChar;
+ llwchar mOldChar;
};
///////////////////////////////////////////////////////////////////
@@ -202,114 +202,114 @@ private:
class LLTextEditor::TextCmdRemove : public LLTextBase::TextCmd
{
public:
- TextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) :
- TextCmd(pos, group_with_next), mLen(len)
- {
- std::swap(mSegments, segments);
- }
- virtual BOOL execute( LLTextBase* editor, S32* delta )
- {
- mWString = editor->getWText().substr(getPosition(), mLen);
- *delta = remove(editor, getPosition(), mLen );
- return (*delta != 0);
- }
- virtual S32 undo( LLTextBase* editor )
- {
- insert(editor, getPosition(), mWString);
- return getPosition() + mWString.length();
- }
- virtual S32 redo( LLTextBase* editor )
- {
- remove(editor, getPosition(), mLen );
- return getPosition();
- }
+ TextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) :
+ TextCmd(pos, group_with_next), mLen(len)
+ {
+ std::swap(mSegments, segments);
+ }
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
+ {
+ mWString = editor->getWText().substr(getPosition(), mLen);
+ *delta = remove(editor, getPosition(), mLen );
+ return (*delta != 0);
+ }
+ virtual S32 undo( LLTextBase* editor )
+ {
+ insert(editor, getPosition(), mWString);
+ return getPosition() + mWString.length();
+ }
+ virtual S32 redo( LLTextBase* editor )
+ {
+ remove(editor, getPosition(), mLen );
+ return getPosition();
+ }
private:
- LLWString mWString;
- S32 mLen;
+ LLWString mWString;
+ S32 mLen;
};
///////////////////////////////////////////////////////////////////
LLTextEditor::Params::Params()
-: default_text("default_text"),
- prevalidate_callback("prevalidate_callback"),
- embedded_items("embedded_items", false),
- ignore_tab("ignore_tab", true),
- auto_indent("auto_indent", true),
- default_color("default_color"),
+: default_text("default_text"),
+ prevalidate_callback("prevalidate_callback"),
+ embedded_items("embedded_items", false),
+ ignore_tab("ignore_tab", true),
+ auto_indent("auto_indent", true),
+ default_color("default_color"),
commit_on_focus_lost("commit_on_focus_lost", false),
- show_context_menu("show_context_menu"),
- show_emoji_helper("show_emoji_helper"),
- enable_tooltip_paste("enable_tooltip_paste")
+ show_context_menu("show_context_menu"),
+ show_emoji_helper("show_emoji_helper"),
+ enable_tooltip_paste("enable_tooltip_paste")
{
- addSynonym(prevalidate_callback, "text_type");
+ addSynonym(prevalidate_callback, "text_type");
}
LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
- LLTextBase(p),
- mAutoreplaceCallback(),
- mBaseDocIsPristine(TRUE),
- mPristineCmd( NULL ),
- mLastCmd( NULL ),
- mDefaultColor( p.default_color() ),
- mAutoIndent(p.auto_indent),
- mCommitOnFocusLost( p.commit_on_focus_lost),
- mAllowEmbeddedItems( p.embedded_items ),
- mMouseDownX(0),
- mMouseDownY(0),
- mTabsToNextField(p.ignore_tab),
- mPrevalidateFunc(p.prevalidate_callback()),
- mShowContextMenu(p.show_context_menu),
- mShowEmojiHelper(p.show_emoji_helper),
- mEnableTooltipPaste(p.enable_tooltip_paste),
- mPassDelete(FALSE),
- mKeepSelectionOnReturn(false)
-{
- mSourceID.generate();
-
- //FIXME: use image?
- LLViewBorder::Params params;
- params.name = "text ed border";
- params.rect = getLocalRect();
- params.bevel_style = LLViewBorder::BEVEL_IN;
- params.border_thickness = 1;
- params.visible = p.border_visible;
- mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
- addChild( mBorder );
- setText(p.default_text());
-
- mParseOnTheFly = TRUE;
+ LLTextBase(p),
+ mAutoreplaceCallback(),
+ mBaseDocIsPristine(TRUE),
+ mPristineCmd( NULL ),
+ mLastCmd( NULL ),
+ mDefaultColor( p.default_color() ),
+ mAutoIndent(p.auto_indent),
+ mCommitOnFocusLost( p.commit_on_focus_lost),
+ mAllowEmbeddedItems( p.embedded_items ),
+ mMouseDownX(0),
+ mMouseDownY(0),
+ mTabsToNextField(p.ignore_tab),
+ mPrevalidateFunc(p.prevalidate_callback()),
+ mShowContextMenu(p.show_context_menu),
+ mShowEmojiHelper(p.show_emoji_helper),
+ mEnableTooltipPaste(p.enable_tooltip_paste),
+ mPassDelete(FALSE),
+ mKeepSelectionOnReturn(false)
+{
+ mSourceID.generate();
+
+ //FIXME: use image?
+ LLViewBorder::Params params;
+ params.name = "text ed border";
+ params.rect = getLocalRect();
+ params.bevel_style = LLViewBorder::BEVEL_IN;
+ params.border_thickness = 1;
+ params.visible = p.border_visible;
+ mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
+ addChild( mBorder );
+ setText(p.default_text());
+
+ mParseOnTheFly = TRUE;
}
void LLTextEditor::initFromParams( const LLTextEditor::Params& p)
{
- LLTextBase::initFromParams(p);
+ LLTextBase::initFromParams(p);
- // HACK: text editors always need to be enabled so that we can scroll
- LLView::setEnabled(true);
+ // HACK: text editors always need to be enabled so that we can scroll
+ LLView::setEnabled(true);
- if (p.commit_on_focus_lost.isProvided())
- {
- mCommitOnFocusLost = p.commit_on_focus_lost;
- }
-
- updateAllowingLanguageInput();
+ if (p.commit_on_focus_lost.isProvided())
+ {
+ mCommitOnFocusLost = p.commit_on_focus_lost;
+ }
+
+ updateAllowingLanguageInput();
}
LLTextEditor::~LLTextEditor()
{
- gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() while LLTextEditor still valid
+ gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() while LLTextEditor still valid
- // Scrollbar is deleted by LLView
- std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
- mUndoStack.clear();
- // Mark the menu as dead or its retained in memory till shutdown.
- LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
- if(menu)
- {
- menu->die();
- mContextMenuHandle.markDead();
- }
+ // Scrollbar is deleted by LLView
+ std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
+ mUndoStack.clear();
+ // Mark the menu as dead or its retained in memory till shutdown.
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+ if(menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
}
////////////////////////////////////////////////////////////
@@ -318,649 +318,649 @@ LLTextEditor::~LLTextEditor()
void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
{
- // validate incoming text if necessary
- if (mPrevalidateFunc)
- {
- LLWString test_text = utf8str_to_wstring(utf8str);
- if (!mPrevalidateFunc(test_text))
- {
- // not valid text, nothing to do
- return;
- }
- }
-
- blockUndo();
- deselect();
+ // validate incoming text if necessary
+ if (mPrevalidateFunc)
+ {
+ LLWString test_text = utf8str_to_wstring(utf8str);
+ if (!mPrevalidateFunc(test_text))
+ {
+ // not valid text, nothing to do
+ return;
+ }
+ }
- mParseOnTheFly = FALSE;
- LLTextBase::setText(utf8str, input_params);
- mParseOnTheFly = TRUE;
+ blockUndo();
+ deselect();
+
+ mParseOnTheFly = FALSE;
+ LLTextBase::setText(utf8str, input_params);
+ mParseOnTheFly = TRUE;
- resetDirty();
+ resetDirty();
}
void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap)
{
- if (search_text_in.empty())
- {
- return;
- }
-
- LLWString text = getWText();
- LLWString search_text = utf8str_to_wstring(search_text_in);
- if (case_insensitive)
- {
- LLWStringUtil::toLower(text);
- LLWStringUtil::toLower(search_text);
- }
-
- if (mIsSelecting)
- {
- LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd);
-
- if (selected_text == search_text)
- {
- // We already have this word selected, we are searching for the next.
- setCursorPos(mCursorPos + search_text.size());
- }
- }
-
- S32 loc = text.find(search_text,mCursorPos);
-
- // If Maybe we wrapped, search again
- if (wrap && (-1 == loc))
- {
- loc = text.find(search_text);
- }
-
- // If still -1, then search_text just isn't found.
+ if (search_text_in.empty())
+ {
+ return;
+ }
+
+ LLWString text = getWText();
+ LLWString search_text = utf8str_to_wstring(search_text_in);
+ if (case_insensitive)
+ {
+ LLWStringUtil::toLower(text);
+ LLWStringUtil::toLower(search_text);
+ }
+
+ if (mIsSelecting)
+ {
+ LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd);
+
+ if (selected_text == search_text)
+ {
+ // We already have this word selected, we are searching for the next.
+ setCursorPos(mCursorPos + search_text.size());
+ }
+ }
+
+ S32 loc = text.find(search_text,mCursorPos);
+
+ // If Maybe we wrapped, search again
+ if (wrap && (-1 == loc))
+ {
+ loc = text.find(search_text);
+ }
+
+ // If still -1, then search_text just isn't found.
if (-1 == loc)
- {
- mIsSelecting = FALSE;
- mSelectionEnd = 0;
- mSelectionStart = 0;
- return;
- }
-
- setCursorPos(loc);
+ {
+ mIsSelecting = FALSE;
+ mSelectionEnd = 0;
+ mSelectionStart = 0;
+ return;
+ }
- mIsSelecting = TRUE;
- mSelectionEnd = mCursorPos;
- mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));
+ setCursorPos(loc);
+
+ mIsSelecting = TRUE;
+ mSelectionEnd = mCursorPos;
+ mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));
}
BOOL LLTextEditor::replaceText(const std::string& search_text_in, const std::string& replace_text,
- BOOL case_insensitive, BOOL wrap)
+ BOOL case_insensitive, BOOL wrap)
{
- BOOL replaced = FALSE;
+ BOOL replaced = FALSE;
- if (search_text_in.empty())
- {
- return replaced;
- }
+ if (search_text_in.empty())
+ {
+ return replaced;
+ }
- LLWString search_text = utf8str_to_wstring(search_text_in);
- if (mIsSelecting)
- {
- LLWString text = getWText();
- LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd);
+ LLWString search_text = utf8str_to_wstring(search_text_in);
+ if (mIsSelecting)
+ {
+ LLWString text = getWText();
+ LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd);
- if (case_insensitive)
- {
- LLWStringUtil::toLower(selected_text);
- LLWStringUtil::toLower(search_text);
- }
+ if (case_insensitive)
+ {
+ LLWStringUtil::toLower(selected_text);
+ LLWStringUtil::toLower(search_text);
+ }
- if (selected_text == search_text)
- {
- insertText(replace_text);
- replaced = TRUE;
- }
- }
+ if (selected_text == search_text)
+ {
+ insertText(replace_text);
+ replaced = TRUE;
+ }
+ }
- selectNext(search_text_in, case_insensitive, wrap);
- return replaced;
+ selectNext(search_text_in, case_insensitive, wrap);
+ return replaced;
}
void LLTextEditor::replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive)
{
- startOfDoc();
- selectNext(search_text, case_insensitive, FALSE);
+ startOfDoc();
+ selectNext(search_text, case_insensitive, FALSE);
- BOOL replaced = TRUE;
- while ( replaced )
- {
- replaced = replaceText(search_text,replace_text, case_insensitive, FALSE);
- }
+ BOOL replaced = TRUE;
+ while ( replaced )
+ {
+ replaced = replaceText(search_text,replace_text, case_insensitive, FALSE);
+ }
}
S32 LLTextEditor::prevWordPos(S32 cursorPos) const
{
- LLWString wtext(getWText());
- while( (cursorPos > 0) && (wtext[cursorPos-1] == ' ') )
- {
- cursorPos--;
- }
- while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) )
- {
- cursorPos--;
- }
- return cursorPos;
+ LLWString wtext(getWText());
+ while( (cursorPos > 0) && (wtext[cursorPos-1] == ' ') )
+ {
+ cursorPos--;
+ }
+ while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) )
+ {
+ cursorPos--;
+ }
+ return cursorPos;
}
S32 LLTextEditor::nextWordPos(S32 cursorPos) const
{
- LLWString wtext(getWText());
- while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) )
- {
- cursorPos++;
- }
- while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') )
- {
- cursorPos++;
- }
- return cursorPos;
+ LLWString wtext(getWText());
+ while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) )
+ {
+ cursorPos++;
+ }
+ while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') )
+ {
+ cursorPos++;
+ }
+ return cursorPos;
}
-const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const
+const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const
{
- static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment;
+ static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment;
- index_segment->setStart(mCursorPos);
- index_segment->setEnd(mCursorPos);
+ index_segment->setStart(mCursorPos);
+ index_segment->setEnd(mCursorPos);
- // find segment index at character to left of cursor (or rightmost edge of selection)
- segment_set_t::const_iterator it = mSegments.lower_bound(index_segment);
+ // find segment index at character to left of cursor (or rightmost edge of selection)
+ segment_set_t::const_iterator it = mSegments.lower_bound(index_segment);
- if (it != mSegments.end())
- {
- return *it;
- }
- else
- {
- return LLTextSegmentPtr();
- }
+ if (it != mSegments.end())
+ {
+ return *it;
+ }
+ else
+ {
+ return LLTextSegmentPtr();
+ }
}
void LLTextEditor::getSelectedSegments(LLTextEditor::segment_vec_t& segments) const
{
- S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
- S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
+ S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
+ S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
- return getSegmentsInRange(segments, left, right, true);
+ return getSegmentsInRange(segments, left, right, true);
}
void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out, S32 start, S32 end, bool include_partial) const
{
- segment_set_t::const_iterator first_it = getSegIterContaining(start);
- segment_set_t::const_iterator end_it = getSegIterContaining(end - 1);
- if (end_it != mSegments.end()) ++end_it;
+ segment_set_t::const_iterator first_it = getSegIterContaining(start);
+ segment_set_t::const_iterator end_it = getSegIterContaining(end - 1);
+ if (end_it != mSegments.end()) ++end_it;
- for (segment_set_t::const_iterator it = first_it; it != end_it; ++it)
- {
- LLTextSegmentPtr segment = *it;
- if (include_partial
- || (segment->getStart() >= start
- && segment->getEnd() <= end))
- {
- segments_out.push_back(segment);
- }
- }
+ for (segment_set_t::const_iterator it = first_it; it != end_it; ++it)
+ {
+ LLTextSegmentPtr segment = *it;
+ if (include_partial
+ || (segment->getStart() >= start
+ && segment->getEnd() <= end))
+ {
+ segments_out.push_back(segment);
+ }
+ }
}
void LLTextEditor::setShowEmojiHelper(bool show)
{
- if (!mShowEmojiHelper)
- {
- LLEmojiHelper::instance().hideHelper(this);
- }
+ if (!mShowEmojiHelper)
+ {
+ LLEmojiHelper::instance().hideHelper(this);
+ }
- mShowEmojiHelper = show;
+ mShowEmojiHelper = show;
}
BOOL LLTextEditor::selectionContainsLineBreaks()
{
- if (hasSelection())
- {
- S32 left = llmin(mSelectionStart, mSelectionEnd);
- S32 right = left + llabs(mSelectionStart - mSelectionEnd);
+ if (hasSelection())
+ {
+ S32 left = llmin(mSelectionStart, mSelectionEnd);
+ S32 right = left + llabs(mSelectionStart - mSelectionEnd);
- LLWString wtext = getWText();
- for( S32 i = left; i < right; i++ )
- {
- if (wtext[i] == '\n')
- {
- return TRUE;
- }
- }
- }
- return FALSE;
+ LLWString wtext = getWText();
+ for( S32 i = left; i < right; i++ )
+ {
+ if (wtext[i] == '\n')
+ {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
}
S32 LLTextEditor::indentLine( S32 pos, S32 spaces )
{
- // Assumes that pos is at the start of the line
- // spaces may be positive (indent) or negative (unindent).
- // Returns the actual number of characters added or removed.
-
- llassert(pos >= 0);
- llassert(pos <= getLength() );
-
- S32 delta_spaces = 0;
-
- if (spaces >= 0)
- {
- // Indent
- for(S32 i=0; i < spaces; i++)
- {
- delta_spaces += addChar(pos, ' ');
- }
- }
- else
- {
- // Unindent
- for(S32 i=0; i < -spaces; i++)
- {
- LLWString wtext = getWText();
- if (wtext[pos] == ' ')
- {
- delta_spaces += remove( pos, 1, FALSE );
- }
- }
- }
-
- return delta_spaces;
+ // Assumes that pos is at the start of the line
+ // spaces may be positive (indent) or negative (unindent).
+ // Returns the actual number of characters added or removed.
+
+ llassert(pos >= 0);
+ llassert(pos <= getLength() );
+
+ S32 delta_spaces = 0;
+
+ if (spaces >= 0)
+ {
+ // Indent
+ for(S32 i=0; i < spaces; i++)
+ {
+ delta_spaces += addChar(pos, ' ');
+ }
+ }
+ else
+ {
+ // Unindent
+ for(S32 i=0; i < -spaces; i++)
+ {
+ LLWString wtext = getWText();
+ if (wtext[pos] == ' ')
+ {
+ delta_spaces += remove( pos, 1, FALSE );
+ }
+ }
+ }
+
+ return delta_spaces;
}
void LLTextEditor::indentSelectedLines( S32 spaces )
{
- if( hasSelection() )
- {
- LLWString text = getWText();
- S32 left = llmin( mSelectionStart, mSelectionEnd );
- S32 right = left + llabs( mSelectionStart - mSelectionEnd );
- BOOL cursor_on_right = (mSelectionEnd > mSelectionStart);
- S32 cur = left;
-
- // Expand left to start of line
- while( (cur > 0) && (text[cur] != '\n') )
- {
- cur--;
- }
- left = cur;
- if( cur > 0 )
- {
- left++;
- }
-
- // Expand right to end of line
- if( text[right - 1] == '\n' )
- {
- right--;
- }
- else
- {
- while( (text[right] != '\n') && (right <= getLength() ) )
- {
- right++;
- }
- }
-
- // Disabling parsing on the fly to avoid updating text segments
- // until all indentation commands are executed.
- mParseOnTheFly = FALSE;
-
- // Find each start-of-line and indent it
- do
- {
- if( text[cur] == '\n' )
- {
- cur++;
- }
-
- S32 delta_spaces = indentLine( cur, spaces );
- if( delta_spaces > 0 )
- {
- cur += delta_spaces;
- }
- right += delta_spaces;
-
- text = getWText();
-
- // Find the next new line
- while( (cur < right) && (text[cur] != '\n') )
- {
- cur++;
- }
- }
- while( cur < right );
-
- mParseOnTheFly = TRUE;
-
- if( (right < getLength()) && (text[right] == '\n') )
- {
- right++;
- }
-
- // Set the selection and cursor
- if( cursor_on_right )
- {
- mSelectionStart = left;
- mSelectionEnd = right;
- }
- else
- {
- mSelectionStart = right;
- mSelectionEnd = left;
- }
- setCursorPos(mSelectionEnd);
- }
+ if( hasSelection() )
+ {
+ LLWString text = getWText();
+ S32 left = llmin( mSelectionStart, mSelectionEnd );
+ S32 right = left + llabs( mSelectionStart - mSelectionEnd );
+ BOOL cursor_on_right = (mSelectionEnd > mSelectionStart);
+ S32 cur = left;
+
+ // Expand left to start of line
+ while( (cur > 0) && (text[cur] != '\n') )
+ {
+ cur--;
+ }
+ left = cur;
+ if( cur > 0 )
+ {
+ left++;
+ }
+
+ // Expand right to end of line
+ if( text[right - 1] == '\n' )
+ {
+ right--;
+ }
+ else
+ {
+ while( (text[right] != '\n') && (right <= getLength() ) )
+ {
+ right++;
+ }
+ }
+
+ // Disabling parsing on the fly to avoid updating text segments
+ // until all indentation commands are executed.
+ mParseOnTheFly = FALSE;
+
+ // Find each start-of-line and indent it
+ do
+ {
+ if( text[cur] == '\n' )
+ {
+ cur++;
+ }
+
+ S32 delta_spaces = indentLine( cur, spaces );
+ if( delta_spaces > 0 )
+ {
+ cur += delta_spaces;
+ }
+ right += delta_spaces;
+
+ text = getWText();
+
+ // Find the next new line
+ while( (cur < right) && (text[cur] != '\n') )
+ {
+ cur++;
+ }
+ }
+ while( cur < right );
+
+ mParseOnTheFly = TRUE;
+
+ if( (right < getLength()) && (text[right] == '\n') )
+ {
+ right++;
+ }
+
+ // Set the selection and cursor
+ if( cursor_on_right )
+ {
+ mSelectionStart = left;
+ mSelectionEnd = right;
+ }
+ else
+ {
+ mSelectionStart = right;
+ mSelectionEnd = left;
+ }
+ setCursorPos(mSelectionEnd);
+ }
}
//virtual
BOOL LLTextEditor::canSelectAll() const
{
- return TRUE;
+ return TRUE;
}
// virtual
void LLTextEditor::selectAll()
{
- mSelectionStart = getLength();
- mSelectionEnd = 0;
- setCursorPos(mSelectionEnd);
- updatePrimary();
+ mSelectionStart = getLength();
+ mSelectionEnd = 0;
+ setCursorPos(mSelectionEnd);
+ updatePrimary();
}
void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos)
{
- setCursorPos(prev_cursor_pos);
- startSelection();
- setCursorPos(next_cursor_pos);
- endSelection();
+ setCursorPos(prev_cursor_pos);
+ startSelection();
+ setCursorPos(next_cursor_pos);
+ endSelection();
}
void LLTextEditor::insertEmoji(llwchar emoji)
{
- LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL;
- auto styleParams = LLStyle::Params();
- styleParams.font = LLFontGL::getFontEmoji();
- auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this);
- insert(mCursorPos, LLWString(1, emoji), false, segment);
- setCursorPos(mCursorPos + 1);
+ LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL;
+ auto styleParams = LLStyle::Params();
+ styleParams.font = LLFontGL::getFontEmoji();
+ auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this);
+ insert(mCursorPos, LLWString(1, emoji), false, segment);
+ setCursorPos(mCursorPos + 1);
}
void LLTextEditor::handleEmojiCommit(llwchar emoji)
{
- S32 shortCodePos;
- if (LLEmojiHelper::isCursorInEmojiCode(getWText(), mCursorPos, &shortCodePos))
- {
- remove(shortCodePos, mCursorPos - shortCodePos, true);
- setCursorPos(shortCodePos);
+ S32 shortCodePos;
+ if (LLEmojiHelper::isCursorInEmojiCode(getWText(), mCursorPos, &shortCodePos))
+ {
+ remove(shortCodePos, mCursorPos - shortCodePos, true);
+ setCursorPos(shortCodePos);
- insertEmoji(emoji);
- }
+ insertEmoji(emoji);
+ }
}
BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
-
- // set focus first, in case click callbacks want to change it
- // RN: do we really need to have a tab stop?
- if (hasTabStop())
- {
- setFocus( TRUE );
- }
-
- // Let scrollbar have first dibs
- handled = LLTextBase::handleMouseDown(x, y, mask);
-
- if( !handled )
- {
- if (!(mask & MASK_SHIFT))
- {
- deselect();
- }
-
- BOOL start_select = TRUE;
- if( start_select )
- {
- // If we're not scrolling (handled by child), then we're selecting
- if (mask & MASK_SHIFT)
- {
- S32 old_cursor_pos = mCursorPos;
- setCursorAtLocalPos( x, y, true );
-
- if (hasSelection())
- {
- mSelectionEnd = mCursorPos;
- }
- else
- {
- mSelectionStart = old_cursor_pos;
- mSelectionEnd = mCursorPos;
- }
- // assume we're starting a drag select
- mIsSelecting = TRUE;
- }
- else
- {
- setCursorAtLocalPos( x, y, true );
- startSelection();
- }
- }
-
- handled = TRUE;
- }
-
- // Delay cursor flashing
- resetCursorBlink();
-
- if (handled && !gFocusMgr.getMouseCapture())
- {
- gFocusMgr.setMouseCapture( this );
- }
- return handled;
+ BOOL handled = FALSE;
+
+ // set focus first, in case click callbacks want to change it
+ // RN: do we really need to have a tab stop?
+ if (hasTabStop())
+ {
+ setFocus( TRUE );
+ }
+
+ // Let scrollbar have first dibs
+ handled = LLTextBase::handleMouseDown(x, y, mask);
+
+ if( !handled )
+ {
+ if (!(mask & MASK_SHIFT))
+ {
+ deselect();
+ }
+
+ BOOL start_select = TRUE;
+ if( start_select )
+ {
+ // If we're not scrolling (handled by child), then we're selecting
+ if (mask & MASK_SHIFT)
+ {
+ S32 old_cursor_pos = mCursorPos;
+ setCursorAtLocalPos( x, y, true );
+
+ if (hasSelection())
+ {
+ mSelectionEnd = mCursorPos;
+ }
+ else
+ {
+ mSelectionStart = old_cursor_pos;
+ mSelectionEnd = mCursorPos;
+ }
+ // assume we're starting a drag select
+ mIsSelecting = TRUE;
+ }
+ else
+ {
+ setCursorAtLocalPos( x, y, true );
+ startSelection();
+ }
+ }
+
+ handled = TRUE;
+ }
+
+ // Delay cursor flashing
+ resetCursorBlink();
+
+ if (handled && !gFocusMgr.getMouseCapture())
+ {
+ gFocusMgr.setMouseCapture( this );
+ }
+ return handled;
}
BOOL LLTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- if (hasTabStop())
- {
- setFocus(TRUE);
- }
+ if (hasTabStop())
+ {
+ setFocus(TRUE);
+ }
- bool show_menu = false;
+ bool show_menu = false;
- // Prefer editor menu if it has selection. See EXT-6806.
- if (hasSelection())
- {
- S32 click_pos = getDocIndexFromLocalCoord(x, y, FALSE);
- if (click_pos > mSelectionStart && click_pos < mSelectionEnd)
- {
- show_menu = true;
- }
- }
+ // Prefer editor menu if it has selection. See EXT-6806.
+ if (hasSelection())
+ {
+ S32 click_pos = getDocIndexFromLocalCoord(x, y, FALSE);
+ if (click_pos > mSelectionStart && click_pos < mSelectionEnd)
+ {
+ show_menu = true;
+ }
+ }
- // Let segments handle the click, if nothing does, show editor menu
- if (!show_menu && !LLTextBase::handleRightMouseDown(x, y, mask))
- {
- show_menu = true;
- }
+ // Let segments handle the click, if nothing does, show editor menu
+ if (!show_menu && !LLTextBase::handleRightMouseDown(x, y, mask))
+ {
+ show_menu = true;
+ }
- if (show_menu && getShowContextMenu())
- {
- showContextMenu(x, y);
- }
+ if (show_menu && getShowContextMenu())
+ {
+ showContextMenu(x, y);
+ }
- return TRUE;
+ return TRUE;
}
BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
- if (hasTabStop())
- {
- setFocus(TRUE);
- }
+ if (hasTabStop())
+ {
+ setFocus(TRUE);
+ }
- if (!LLTextBase::handleMouseDown(x, y, mask))
- {
- if( canPastePrimary() )
- {
- setCursorAtLocalPos( x, y, true );
- // does not rely on focus being set
- pastePrimary();
- }
- }
- return TRUE;
+ if (!LLTextBase::handleMouseDown(x, y, mask))
+ {
+ if( canPastePrimary() )
+ {
+ setCursorAtLocalPos( x, y, true );
+ // does not rely on focus being set
+ pastePrimary();
+ }
+ }
+ return TRUE;
}
BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
-
- if(hasMouseCapture() )
- {
- if( mIsSelecting )
- {
- if(mScroller)
- {
- mScroller->autoScroll(x, y);
- }
- S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
- S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
- setCursorAtLocalPos( clamped_x, clamped_y, true );
- mSelectionEnd = mCursorPos;
- }
- LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL;
- getWindow()->setCursor(UI_CURSOR_IBEAM);
- handled = TRUE;
- }
-
- if( !handled )
- {
- // Pass to children
- handled = LLTextBase::handleHover(x, y, mask);
- }
-
- if( handled )
- {
- // Delay cursor flashing
- resetCursorBlink();
- }
-
- if( !handled )
- {
- getWindow()->setCursor(UI_CURSOR_IBEAM);
- handled = TRUE;
- }
-
- return handled;
+ BOOL handled = FALSE;
+
+ if(hasMouseCapture() )
+ {
+ if( mIsSelecting )
+ {
+ if(mScroller)
+ {
+ mScroller->autoScroll(x, y);
+ }
+ S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
+ S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
+ setCursorAtLocalPos( clamped_x, clamped_y, true );
+ mSelectionEnd = mCursorPos;
+ }
+ LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL;
+ getWindow()->setCursor(UI_CURSOR_IBEAM);
+ handled = TRUE;
+ }
+
+ if( !handled )
+ {
+ // Pass to children
+ handled = LLTextBase::handleHover(x, y, mask);
+ }
+
+ if( handled )
+ {
+ // Delay cursor flashing
+ resetCursorBlink();
+ }
+
+ if( !handled )
+ {
+ getWindow()->setCursor(UI_CURSOR_IBEAM);
+ handled = TRUE;
+ }
+
+ return handled;
}
BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
-
- // if I'm not currently selecting text
- if (!(mIsSelecting && hasMouseCapture()))
- {
- // let text segments handle mouse event
- handled = LLTextBase::handleMouseUp(x, y, mask);
- }
-
- if( !handled )
- {
- if( mIsSelecting )
- {
- if(mScroller)
- {
- mScroller->autoScroll(x, y);
- }
- S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
- S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
- setCursorAtLocalPos( clamped_x, clamped_y, true );
- endSelection();
- }
-
- // take selection to 'primary' clipboard
- updatePrimary();
-
- handled = TRUE;
- }
-
- // Delay cursor flashing
- resetCursorBlink();
-
- if( hasMouseCapture() )
- {
- gFocusMgr.setMouseCapture( NULL );
-
- handled = TRUE;
- }
-
- return handled;
+ BOOL handled = FALSE;
+
+ // if I'm not currently selecting text
+ if (!(mIsSelecting && hasMouseCapture()))
+ {
+ // let text segments handle mouse event
+ handled = LLTextBase::handleMouseUp(x, y, mask);
+ }
+
+ if( !handled )
+ {
+ if( mIsSelecting )
+ {
+ if(mScroller)
+ {
+ mScroller->autoScroll(x, y);
+ }
+ S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
+ S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
+ setCursorAtLocalPos( clamped_x, clamped_y, true );
+ endSelection();
+ }
+
+ // take selection to 'primary' clipboard
+ updatePrimary();
+
+ handled = TRUE;
+ }
+
+ // Delay cursor flashing
+ resetCursorBlink();
+
+ if( hasMouseCapture() )
+ {
+ gFocusMgr.setMouseCapture( NULL );
+
+ handled = TRUE;
+ }
+
+ return handled;
}
BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
+ BOOL handled = FALSE;
- // let scrollbar and text segments have first dibs
- handled = LLTextBase::handleDoubleClick(x, y, mask);
+ // let scrollbar and text segments have first dibs
+ handled = LLTextBase::handleDoubleClick(x, y, mask);
- if( !handled )
- {
- setCursorAtLocalPos( x, y, false );
- deselect();
+ if( !handled )
+ {
+ setCursorAtLocalPos( x, y, false );
+ deselect();
- LLWString text = getWText();
+ LLWString text = getWText();
+
+ if( LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
+ {
+ // Select word the cursor is over
+ while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord(text[mCursorPos-1]))
+ {
+ if (!setCursorPos(mCursorPos - 1)) break;
+ }
+ startSelection();
- if( LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
- {
- // Select word the cursor is over
- while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord(text[mCursorPos-1]))
- {
- if (!setCursorPos(mCursorPos - 1)) break;
- }
- startSelection();
-
- while ((mCursorPos < (S32)text.length()) && LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
- {
- if (!setCursorPos(mCursorPos + 1)) break;
- }
-
- mSelectionEnd = mCursorPos;
- }
- else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) )
- {
- // Select the character the cursor is over
- startSelection();
- setCursorPos(mCursorPos + 1);
- mSelectionEnd = mCursorPos;
- }
+ while ((mCursorPos < (S32)text.length()) && LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
+ {
+ if (!setCursorPos(mCursorPos + 1)) break;
+ }
+
+ mSelectionEnd = mCursorPos;
+ }
+ else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) )
+ {
+ // Select the character the cursor is over
+ startSelection();
+ setCursorPos(mCursorPos + 1);
+ mSelectionEnd = mCursorPos;
+ }
- // We don't want handleMouseUp() to "finish" the selection (and thereby
- // set mSelectionEnd to where the mouse is), so we finish the selection here.
- mIsSelecting = FALSE;
+ // We don't want handleMouseUp() to "finish" the selection (and thereby
+ // set mSelectionEnd to where the mouse is), so we finish the selection here.
+ mIsSelecting = FALSE;
- // delay cursor flashing
- resetCursorBlink();
+ // delay cursor flashing
+ resetCursorBlink();
- // take selection to 'primary' clipboard
- updatePrimary();
+ // take selection to 'primary' clipboard
+ updatePrimary();
- handled = TRUE;
- }
+ handled = TRUE;
+ }
- return handled;
+ return handled;
}
@@ -969,228 +969,228 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
S32 LLTextEditor::execute( TextCmd* cmd )
{
- if (!mReadOnly && mShowEmojiHelper)
- {
- // Any change to our contents should always hide the helper
- LLEmojiHelper::instance().hideHelper(this);
- }
-
- S32 delta = 0;
- if( cmd->execute(this, &delta) )
- {
- // Delete top of undo stack
- undo_stack_t::iterator enditer = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
- std::for_each(mUndoStack.begin(), enditer, DeletePointer());
- mUndoStack.erase(mUndoStack.begin(), enditer);
- // Push the new command is now on the top (front) of the undo stack.
- mUndoStack.push_front(cmd);
- mLastCmd = cmd;
-
- bool need_to_rollback = mPrevalidateFunc
- && !mPrevalidateFunc(getViewModel()->getDisplay());
- if (need_to_rollback)
- {
- // get rid of this last command and clean up undo stack
- undo();
-
- // remove any evidence of this command from redo history
- mUndoStack.pop_front();
- delete cmd;
-
- // failure, nothing changed
- delta = 0;
- }
- }
- else
- {
- // Operation failed, so don't put it on the undo stack.
- delete cmd;
- }
-
- return delta;
+ if (!mReadOnly && mShowEmojiHelper)
+ {
+ // Any change to our contents should always hide the helper
+ LLEmojiHelper::instance().hideHelper(this);
+ }
+
+ S32 delta = 0;
+ if( cmd->execute(this, &delta) )
+ {
+ // Delete top of undo stack
+ undo_stack_t::iterator enditer = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
+ std::for_each(mUndoStack.begin(), enditer, DeletePointer());
+ mUndoStack.erase(mUndoStack.begin(), enditer);
+ // Push the new command is now on the top (front) of the undo stack.
+ mUndoStack.push_front(cmd);
+ mLastCmd = cmd;
+
+ bool need_to_rollback = mPrevalidateFunc
+ && !mPrevalidateFunc(getViewModel()->getDisplay());
+ if (need_to_rollback)
+ {
+ // get rid of this last command and clean up undo stack
+ undo();
+
+ // remove any evidence of this command from redo history
+ mUndoStack.pop_front();
+ delete cmd;
+
+ // failure, nothing changed
+ delta = 0;
+ }
+ }
+ else
+ {
+ // Operation failed, so don't put it on the undo stack.
+ delete cmd;
+ }
+
+ return delta;
}
S32 LLTextEditor::insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment)
{
- return execute( new TextCmdInsert( pos, group_with_next_op, wstr, segment ) );
+ return execute( new TextCmdInsert( pos, group_with_next_op, wstr, segment ) );
}
S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op)
{
- S32 end_pos = getEditableIndex(pos + length, true);
- BOOL removedChar = FALSE;
+ S32 end_pos = getEditableIndex(pos + length, true);
+ BOOL removedChar = FALSE;
- segment_vec_t segments_to_remove;
- // store text segments
- getSegmentsInRange(segments_to_remove, pos, pos + length, false);
+ segment_vec_t segments_to_remove;
+ // store text segments
+ getSegmentsInRange(segments_to_remove, pos, pos + length, false);
+
+ if (pos <= end_pos)
+ {
+ removedChar = execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) );
+ }
- if (pos <= end_pos)
- {
- removedChar = execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) );
- }
-
- return removedChar;
+ return removedChar;
}
S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc)
{
- if ((S32)getLength() == pos)
- {
- return addChar(pos, wc);
- }
- else
- {
- return execute(new TextCmdOverwriteChar(pos, FALSE, wc));
- }
+ if ((S32)getLength() == pos)
+ {
+ return addChar(pos, wc);
+ }
+ else
+ {
+ return execute(new TextCmdOverwriteChar(pos, FALSE, wc));
+ }
}
// Remove a single character from the text. Tries to remove
// a pseudo-tab (up to for spaces in a row)
void LLTextEditor::removeCharOrTab()
{
- if (!getEnabled())
- {
- return;
- }
-
- if (mCursorPos > 0)
- {
- S32 chars_to_remove = 1;
-
- LLWString text = getWText();
- if (text[mCursorPos - 1] == ' ')
- {
- // Try to remove a "tab"
- S32 offset = getLineOffsetFromDocIndex(mCursorPos);
- if (offset > 0)
- {
- chars_to_remove = offset % SPACES_PER_TAB;
- if (chars_to_remove == 0)
- {
- chars_to_remove = SPACES_PER_TAB;
- }
-
- for (S32 i = 0; i < chars_to_remove; i++)
- {
- if (text[mCursorPos - i - 1] != ' ')
- {
- // Fewer than a full tab's worth of spaces, so
- // just delete a single character.
- chars_to_remove = 1;
- break;
- }
- }
- }
- }
-
- for (S32 i = 0; i < chars_to_remove; i++)
- {
- setCursorPos(mCursorPos - 1);
- remove(mCursorPos, 1, false);
- }
-
- tryToShowEmojiHelper();
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
+ if (!getEnabled())
+ {
+ return;
+ }
+
+ if (mCursorPos > 0)
+ {
+ S32 chars_to_remove = 1;
+
+ LLWString text = getWText();
+ if (text[mCursorPos - 1] == ' ')
+ {
+ // Try to remove a "tab"
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+ if (offset > 0)
+ {
+ chars_to_remove = offset % SPACES_PER_TAB;
+ if (chars_to_remove == 0)
+ {
+ chars_to_remove = SPACES_PER_TAB;
+ }
+
+ for (S32 i = 0; i < chars_to_remove; i++)
+ {
+ if (text[mCursorPos - i - 1] != ' ')
+ {
+ // Fewer than a full tab's worth of spaces, so
+ // just delete a single character.
+ chars_to_remove = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ for (S32 i = 0; i < chars_to_remove; i++)
+ {
+ setCursorPos(mCursorPos - 1);
+ remove(mCursorPos, 1, false);
+ }
+
+ tryToShowEmojiHelper();
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
}
// Remove a single character from the text
S32 LLTextEditor::removeChar(S32 pos)
{
- return remove(pos, 1, false);
+ return remove(pos, 1, false);
}
void LLTextEditor::removeChar()
{
- if (!getEnabled())
- {
- return;
- }
+ if (!getEnabled())
+ {
+ return;
+ }
- if (mCursorPos > 0)
- {
- setCursorPos(mCursorPos - 1);
- removeChar(mCursorPos);
- tryToShowEmojiHelper();
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
+ if (mCursorPos > 0)
+ {
+ setCursorPos(mCursorPos - 1);
+ removeChar(mCursorPos);
+ tryToShowEmojiHelper();
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
}
// Add a single character to the text
S32 LLTextEditor::addChar(S32 pos, llwchar wc)
{
- if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength)
- {
- make_ui_sound("UISndBadKeystroke");
- return 0;
- }
-
- if (mLastCmd && mLastCmd->canExtend(pos))
- {
- S32 delta = 0;
- if (mPrevalidateFunc)
- {
- // get a copy of current text contents
- LLWString test_string(getViewModel()->getDisplay());
-
- // modify text contents as if this addChar succeeded
- llassert(pos <= (S32)test_string.size());
- test_string.insert(pos, 1, wc);
- if (!mPrevalidateFunc( test_string))
- {
- return 0;
- }
- }
- mLastCmd->extendAndExecute(this, pos, wc, &delta);
-
- return delta;
- }
- else
- {
- return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
- }
+ if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength)
+ {
+ make_ui_sound("UISndBadKeystroke");
+ return 0;
+ }
+
+ if (mLastCmd && mLastCmd->canExtend(pos))
+ {
+ S32 delta = 0;
+ if (mPrevalidateFunc)
+ {
+ // get a copy of current text contents
+ LLWString test_string(getViewModel()->getDisplay());
+
+ // modify text contents as if this addChar succeeded
+ llassert(pos <= (S32)test_string.size());
+ test_string.insert(pos, 1, wc);
+ if (!mPrevalidateFunc( test_string))
+ {
+ return 0;
+ }
+ }
+ mLastCmd->extendAndExecute(this, pos, wc, &delta);
+
+ return delta;
+ }
+ else
+ {
+ return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
+ }
}
void LLTextEditor::addChar(llwchar wc)
{
- if( !getEnabled() )
- {
- return;
- }
- if( hasSelection() )
- {
- deleteSelection(TRUE);
- }
- else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
- {
- removeChar(mCursorPos);
- }
-
- setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
- tryToShowEmojiHelper();
-
- if (!mReadOnly && mAutoreplaceCallback != NULL)
- {
- // autoreplace the text, if necessary
- S32 replacement_start;
- S32 replacement_length;
- LLWString replacement_string;
- S32 new_cursor_pos = mCursorPos;
- mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, getWText());
-
- if (replacement_length > 0 || !replacement_string.empty())
- {
- remove(replacement_start, replacement_length, true);
- insert(replacement_start, replacement_string, false, LLTextSegmentPtr());
- setCursorPos(new_cursor_pos);
- }
- }
+ if( !getEnabled() )
+ {
+ return;
+ }
+ if( hasSelection() )
+ {
+ deleteSelection(TRUE);
+ }
+ else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
+ {
+ removeChar(mCursorPos);
+ }
+
+ setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
+ tryToShowEmojiHelper();
+
+ if (!mReadOnly && mAutoreplaceCallback != NULL)
+ {
+ // autoreplace the text, if necessary
+ S32 replacement_start;
+ S32 replacement_length;
+ LLWString replacement_string;
+ S32 new_cursor_pos = mCursorPos;
+ mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, getWText());
+
+ if (replacement_length > 0 || !replacement_string.empty())
+ {
+ remove(replacement_start, replacement_length, true);
+ insert(replacement_start, replacement_string, false, LLTextSegmentPtr());
+ setCursorPos(new_cursor_pos);
+ }
+ }
}
void LLTextEditor::showEmojiHelper()
@@ -1226,791 +1226,792 @@ void LLTextEditor::tryToShowEmojiHelper()
void LLTextEditor::addLineBreakChar(BOOL group_together)
{
- if( !getEnabled() )
- {
- return;
- }
- if( hasSelection() )
- {
- deleteSelection(TRUE);
- }
- else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
- {
- removeChar(mCursorPos);
- }
-
- LLStyleConstSP sp(new LLStyle(LLStyle::Params()));
- LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos);
+ if( !getEnabled() )
+ {
+ return;
+ }
+ if( hasSelection() )
+ {
+ deleteSelection(TRUE);
+ }
+ else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
+ {
+ removeChar(mCursorPos);
+ }
- S32 pos = execute(new TextCmdAddChar(mCursorPos, group_together, '\n', segment));
+ LLStyleConstSP sp(new LLStyle(LLStyle::Params()));
+ LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos);
- setCursorPos(mCursorPos + pos);
+ S32 pos = execute(new TextCmdAddChar(mCursorPos, group_together, '\n', segment));
+
+ setCursorPos(mCursorPos + pos);
}
BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask)
{
- BOOL handled = FALSE;
-
- if( mask & MASK_SHIFT )
- {
- handled = TRUE;
-
- switch( key )
- {
- case KEY_LEFT:
- if( 0 < mCursorPos )
- {
- startSelection();
- setCursorPos(mCursorPos - 1);
- if( mask & MASK_CONTROL )
- {
- setCursorPos(prevWordPos(mCursorPos));
- }
- mSelectionEnd = mCursorPos;
- }
- break;
-
- case KEY_RIGHT:
- if( mCursorPos < getLength() )
- {
- startSelection();
- setCursorPos(mCursorPos + 1);
- if( mask & MASK_CONTROL )
- {
- setCursorPos(nextWordPos(mCursorPos));
- }
- mSelectionEnd = mCursorPos;
- }
- break;
-
- case KEY_UP:
- startSelection();
- changeLine( -1 );
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_PAGE_UP:
- startSelection();
- changePage( -1 );
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_HOME:
- startSelection();
- if( mask & MASK_CONTROL )
- {
- setCursorPos(0);
- }
- else
- {
- startOfLine();
- }
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_DOWN:
- startSelection();
- changeLine( 1 );
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_PAGE_DOWN:
- startSelection();
- changePage( 1 );
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_END:
- startSelection();
- if( mask & MASK_CONTROL )
- {
- setCursorPos(getLength());
- }
- else
- {
- endOfLine();
- }
- mSelectionEnd = mCursorPos;
- break;
-
- default:
- handled = FALSE;
- break;
- }
- }
-
- if( handled )
- {
- // take selection to 'primary' clipboard
- updatePrimary();
- }
-
- return handled;
+ BOOL handled = FALSE;
+
+ if( mask & MASK_SHIFT )
+ {
+ handled = TRUE;
+
+ switch( key )
+ {
+ case KEY_LEFT:
+ if( 0 < mCursorPos )
+ {
+ startSelection();
+ setCursorPos(mCursorPos - 1);
+ if( mask & MASK_CONTROL )
+ {
+ setCursorPos(prevWordPos(mCursorPos));
+ }
+ mSelectionEnd = mCursorPos;
+ }
+ break;
+
+ case KEY_RIGHT:
+ if( mCursorPos < getLength() )
+ {
+ startSelection();
+ setCursorPos(mCursorPos + 1);
+ if( mask & MASK_CONTROL )
+ {
+ setCursorPos(nextWordPos(mCursorPos));
+ }
+ mSelectionEnd = mCursorPos;
+ }
+ break;
+
+ case KEY_UP:
+ startSelection();
+ changeLine( -1 );
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_PAGE_UP:
+ startSelection();
+ changePage( -1 );
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_HOME:
+ startSelection();
+ if( mask & MASK_CONTROL )
+ {
+ setCursorPos(0);
+ }
+ else
+ {
+ startOfLine();
+ }
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_DOWN:
+ startSelection();
+ changeLine( 1 );
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_PAGE_DOWN:
+ startSelection();
+ changePage( 1 );
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_END:
+ startSelection();
+ if( mask & MASK_CONTROL )
+ {
+ setCursorPos(getLength());
+ }
+ else
+ {
+ endOfLine();
+ }
+ mSelectionEnd = mCursorPos;
+ break;
+
+ default:
+ handled = FALSE;
+ break;
+ }
+ }
+
+ if( handled )
+ {
+ // take selection to 'primary' clipboard
+ updatePrimary();
+ }
+
+ return handled;
}
BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask)
{
- BOOL handled = FALSE;
-
- // Ignore capslock key
- if( MASK_NONE == mask )
- {
- handled = TRUE;
- switch( key )
- {
- case KEY_UP:
- changeLine( -1 );
- break;
-
- case KEY_PAGE_UP:
- changePage( -1 );
- break;
-
- case KEY_HOME:
- startOfLine();
- break;
-
- case KEY_DOWN:
- changeLine( 1 );
- deselect();
- break;
-
- case KEY_PAGE_DOWN:
- changePage( 1 );
- break;
-
- case KEY_END:
- endOfLine();
- break;
-
- case KEY_LEFT:
- if( hasSelection() )
- {
- setCursorPos(llmin( mSelectionStart, mSelectionEnd ));
- }
- else
- {
- if( 0 < mCursorPos )
- {
- setCursorPos(mCursorPos - 1);
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
- }
- break;
-
- case KEY_RIGHT:
- if( hasSelection() )
- {
- setCursorPos(llmax( mSelectionStart, mSelectionEnd ));
- }
- else
- {
- if( mCursorPos < getLength() )
- {
- setCursorPos(mCursorPos + 1);
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
- }
- break;
-
- default:
- handled = FALSE;
- break;
- }
- }
-
- if (handled)
- {
- deselect();
- }
-
- return handled;
+ BOOL handled = FALSE;
+
+ // Ignore capslock key
+ if( MASK_NONE == mask )
+ {
+ handled = TRUE;
+ switch( key )
+ {
+ case KEY_UP:
+ changeLine( -1 );
+ break;
+
+ case KEY_PAGE_UP:
+ changePage( -1 );
+ break;
+
+ case KEY_HOME:
+ startOfLine();
+ break;
+
+ case KEY_DOWN:
+ changeLine( 1 );
+ deselect();
+ break;
+
+ case KEY_PAGE_DOWN:
+ changePage( 1 );
+ break;
+
+ case KEY_END:
+ endOfLine();
+ break;
+
+ case KEY_LEFT:
+ if( hasSelection() )
+ {
+ setCursorPos(llmin( mSelectionStart, mSelectionEnd ));
+ }
+ else
+ {
+ if( 0 < mCursorPos )
+ {
+ setCursorPos(mCursorPos - 1);
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
+ }
+ break;
+
+ case KEY_RIGHT:
+ if( hasSelection() )
+ {
+ setCursorPos(llmax( mSelectionStart, mSelectionEnd ));
+ }
+ else
+ {
+ if( mCursorPos < getLength() )
+ {
+ setCursorPos(mCursorPos + 1);
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
+ }
+ break;
+
+ default:
+ handled = FALSE;
+ break;
+ }
+ }
+
+ if (handled)
+ {
+ deselect();
+ }
+
+ return handled;
}
void LLTextEditor::deleteSelection(BOOL group_with_next_op )
{
- if( getEnabled() && hasSelection() )
- {
- S32 pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
+ if( getEnabled() && hasSelection() )
+ {
+ S32 pos = llmin( mSelectionStart, mSelectionEnd );
+ S32 length = llabs( mSelectionStart - mSelectionEnd );
+
+ remove( pos, length, group_with_next_op );
- remove( pos, length, group_with_next_op );
-
- deselect();
- setCursorPos(pos);
- }
+ deselect();
+ setCursorPos(pos);
+ }
}
// virtual
BOOL LLTextEditor::canCut() const
{
- return !mReadOnly && hasSelection();
+ return !mReadOnly && hasSelection();
}
// cut selection to clipboard
void LLTextEditor::cut()
{
- if( !canCut() )
- {
- return;
- }
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
- LLClipboard::instance().copyToClipboard( getWText(), left_pos, length);
- deleteSelection( FALSE );
+ if( !canCut() )
+ {
+ return;
+ }
+ S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
+ S32 length = llabs( mSelectionStart - mSelectionEnd );
+ LLClipboard::instance().copyToClipboard( getWText(), left_pos, length);
+ deleteSelection( FALSE );
- onKeyStroke();
+ onKeyStroke();
}
BOOL LLTextEditor::canCopy() const
{
- return hasSelection();
+ return hasSelection();
}
// copy selection to clipboard
void LLTextEditor::copy()
{
- if( !canCopy() )
- {
- return;
- }
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
- LLClipboard::instance().copyToClipboard(getWText(), left_pos, length);
+ if( !canCopy() )
+ {
+ return;
+ }
+ S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
+ S32 length = llabs( mSelectionStart - mSelectionEnd );
+ LLClipboard::instance().copyToClipboard(getWText(), left_pos, length);
}
BOOL LLTextEditor::canPaste() const
{
- return !mReadOnly && LLClipboard::instance().isTextAvailable();
+ return !mReadOnly && LLClipboard::instance().isTextAvailable();
}
// paste from clipboard
void LLTextEditor::paste()
{
- bool is_primary = false;
- pasteHelper(is_primary);
+ bool is_primary = false;
+ pasteHelper(is_primary);
}
// paste from primary
void LLTextEditor::pastePrimary()
{
- bool is_primary = true;
- pasteHelper(is_primary);
+ bool is_primary = true;
+ pasteHelper(is_primary);
}
// paste from primary (itsprimary==true) or clipboard (itsprimary==false)
void LLTextEditor::pasteHelper(bool is_primary)
{
- mParseOnTheFly = FALSE;
- bool can_paste_it;
- if (is_primary)
- {
- can_paste_it = canPastePrimary();
- }
- else
- {
- can_paste_it = canPaste();
- }
+ mParseOnTheFly = FALSE;
+ bool can_paste_it;
+ if (is_primary)
+ {
+ can_paste_it = canPastePrimary();
+ }
+ else
+ {
+ can_paste_it = canPaste();
+ }
- if (!can_paste_it)
- {
- return;
- }
+ if (!can_paste_it)
+ {
+ return;
+ }
- LLWString paste;
- LLClipboard::instance().pasteFromClipboard(paste, is_primary);
+ LLWString paste;
+ LLClipboard::instance().pasteFromClipboard(paste, is_primary);
- if (paste.empty())
- {
- return;
- }
+ if (paste.empty())
+ {
+ return;
+ }
- // Delete any selected characters (the paste replaces them)
- if( (!is_primary) && hasSelection() )
- {
- deleteSelection(TRUE);
- }
+ // Delete any selected characters (the paste replaces them)
+ if( (!is_primary) && hasSelection() )
+ {
+ deleteSelection(TRUE);
+ }
- // Clean up string (replace tabs and remove characters that our fonts don't support).
- LLWString clean_string(paste);
- cleanStringForPaste(clean_string);
+ // Clean up string (replace tabs and remove characters that our fonts don't support).
+ LLWString clean_string(paste);
+ cleanStringForPaste(clean_string);
- // Insert the new text into the existing text.
+ // Insert the new text into the existing text.
- //paste text with linebreaks.
- pasteTextWithLinebreaks(clean_string);
+ //paste text with linebreaks.
+ pasteTextWithLinebreaks(clean_string);
- deselect();
+ deselect();
- onKeyStroke();
- mParseOnTheFly = TRUE;
+ onKeyStroke();
+ mParseOnTheFly = TRUE;
}
// Clean up string (replace tabs and remove characters that our fonts don't support).
void LLTextEditor::cleanStringForPaste(LLWString & clean_string)
{
- std::string clean_string_utf = wstring_to_utf8str(clean_string);
- std::replace( clean_string_utf.begin(), clean_string_utf.end(), '\r', '\n');
- clean_string = utf8str_to_wstring(clean_string_utf);
-
- LLWStringUtil::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB);
- if( mAllowEmbeddedItems )
- {
- const llwchar LF = 10;
- S32 len = clean_string.length();
- for( S32 i = 0; i < len; i++ )
- {
- llwchar wc = clean_string[i];
- if( (wc < LLFontFreetype::FIRST_CHAR) && (wc != LF) )
- {
- clean_string[i] = LL_UNKNOWN_CHAR;
- }
- else if (wc >= FIRST_EMBEDDED_CHAR && wc <= LAST_EMBEDDED_CHAR)
- {
- clean_string[i] = pasteEmbeddedItem(wc);
- }
- }
- }
-}
-
-
-void LLTextEditor::pasteTextWithLinebreaks(LLWString & clean_string)
-{
- std::basic_string<llwchar>::size_type start = 0;
- std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start);
-
- while((pos != -1) && (pos != clean_string.length() -1))
- {
- if(pos!=start)
- {
- std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,pos-start);
- setCursorPos(mCursorPos + insert(mCursorPos, str, TRUE, LLTextSegmentPtr()));
- }
- addLineBreakChar(TRUE); // Add a line break and group with the next addition.
-
- start = pos+1;
- pos = clean_string.find('\n',start);
- }
-
- if (pos != start)
- {
- std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start);
- setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
- }
- else
- {
- addLineBreakChar(FALSE); // Add a line break and end the grouping.
- }
+ std::string clean_string_utf = wstring_to_utf8str(clean_string);
+ std::replace( clean_string_utf.begin(), clean_string_utf.end(), '\r', '\n');
+ clean_string = utf8str_to_wstring(clean_string_utf);
+
+ LLWStringUtil::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB);
+ if( mAllowEmbeddedItems )
+ {
+ const llwchar LF = 10;
+ S32 len = clean_string.length();
+ for( S32 i = 0; i < len; i++ )
+ {
+ llwchar wc = clean_string[i];
+ if( (wc < LLFontFreetype::FIRST_CHAR) && (wc != LF) )
+ {
+ clean_string[i] = LL_UNKNOWN_CHAR;
+ }
+ else if (wc >= FIRST_EMBEDDED_CHAR && wc <= LAST_EMBEDDED_CHAR)
+ {
+ clean_string[i] = pasteEmbeddedItem(wc);
+ }
+ }
+ }
+}
+
+
+template <>
+void LLTextEditor::pasteTextWithLinebreaks<LLWString>(const LLWString & clean_string)
+{
+ std::basic_string<llwchar>::size_type start = 0;
+ std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start);
+
+ while((pos != -1) && (pos != clean_string.length() -1))
+ {
+ if(pos!=start)
+ {
+ std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,pos-start);
+ setCursorPos(mCursorPos + insert(mCursorPos, str, TRUE, LLTextSegmentPtr()));
+ }
+ addLineBreakChar(TRUE); // Add a line break and group with the next addition.
+
+ start = pos+1;
+ pos = clean_string.find('\n',start);
+ }
+
+ if (pos != start)
+ {
+ std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start);
+ setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
+ }
+ else
+ {
+ addLineBreakChar(FALSE); // Add a line break and end the grouping.
+ }
}
// copy selection to primary
void LLTextEditor::copyPrimary()
{
- if( !canCopy() )
- {
- return;
- }
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
- LLClipboard::instance().copyToClipboard(getWText(), left_pos, length, true);
+ if( !canCopy() )
+ {
+ return;
+ }
+ S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
+ S32 length = llabs( mSelectionStart - mSelectionEnd );
+ LLClipboard::instance().copyToClipboard(getWText(), left_pos, length, true);
}
BOOL LLTextEditor::canPastePrimary() const
{
- return !mReadOnly && LLClipboard::instance().isTextAvailable(true);
+ return !mReadOnly && LLClipboard::instance().isTextAvailable(true);
}
void LLTextEditor::updatePrimary()
{
- if (canCopy())
- {
- copyPrimary();
- }
-}
-
-BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask)
-{
- BOOL handled = FALSE;
-
- if( mask & MASK_CONTROL )
- {
- handled = TRUE;
-
- switch( key )
- {
- case KEY_HOME:
- if( mask & MASK_SHIFT )
- {
- startSelection();
- setCursorPos(0);
- mSelectionEnd = mCursorPos;
- }
- else
- {
- // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
- // all move the cursor as if clicking, so should deselect.
- deselect();
- startOfDoc();
- }
- break;
-
- case KEY_END:
- {
- if( mask & MASK_SHIFT )
- {
- startSelection();
- }
- else
- {
- // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
- // all move the cursor as if clicking, so should deselect.
- deselect();
- }
- endOfDoc();
- if( mask & MASK_SHIFT )
- {
- mSelectionEnd = mCursorPos;
- }
- break;
- }
-
- case KEY_RIGHT:
- if( mCursorPos < getLength() )
- {
- // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
- // all move the cursor as if clicking, so should deselect.
- deselect();
-
- setCursorPos(nextWordPos(mCursorPos + 1));
- }
- break;
-
-
- case KEY_LEFT:
- if( mCursorPos > 0 )
- {
- // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
- // all move the cursor as if clicking, so should deselect.
- deselect();
-
- setCursorPos(prevWordPos(mCursorPos - 1));
- }
- break;
-
- default:
- handled = FALSE;
- break;
- }
- }
-
- if (handled && !gFocusMgr.getMouseCapture())
- {
- updatePrimary();
- }
-
- return handled;
-}
-
-
-BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask)
- {
- BOOL handled = TRUE;
-
- if (mReadOnly) return FALSE;
-
- switch( key )
- {
- case KEY_INSERT:
- if (mask == MASK_NONE)
- {
- gKeyboard->toggleInsertMode();
- }
- break;
-
- case KEY_BACKSPACE:
- if( hasSelection() )
- {
- deleteSelection(FALSE);
- }
- else
- if( 0 < mCursorPos )
- {
- removeCharOrTab();
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
- break;
-
-
- case KEY_RETURN:
- if (mask == MASK_NONE)
- {
- if( hasSelection() && !mKeepSelectionOnReturn )
- {
- deleteSelection(FALSE);
- }
- if (mAutoIndent)
- {
- autoIndent();
- }
- }
- else
- {
- handled = FALSE;
- break;
- }
- break;
-
- case KEY_TAB:
- if (mask & MASK_CONTROL)
- {
- handled = FALSE;
- break;
- }
- if( hasSelection() && selectionContainsLineBreaks() )
- {
- indentSelectedLines( (mask & MASK_SHIFT) ? -SPACES_PER_TAB : SPACES_PER_TAB );
- }
- else
- {
- if( hasSelection() )
- {
- deleteSelection(FALSE);
- }
-
- S32 offset = getLineOffsetFromDocIndex(mCursorPos);
-
- S32 spaces_needed = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
- for( S32 i=0; i < spaces_needed; i++ )
- {
- addChar( ' ' );
- }
- }
- break;
-
- default:
- handled = FALSE;
- break;
- }
-
- if (handled)
- {
- onKeyStroke();
- }
- return handled;
+ if (canCopy())
+ {
+ copyPrimary();
+ }
+}
+
+BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask)
+{
+ BOOL handled = FALSE;
+
+ if( mask & MASK_CONTROL )
+ {
+ handled = TRUE;
+
+ switch( key )
+ {
+ case KEY_HOME:
+ if( mask & MASK_SHIFT )
+ {
+ startSelection();
+ setCursorPos(0);
+ mSelectionEnd = mCursorPos;
+ }
+ else
+ {
+ // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
+ // all move the cursor as if clicking, so should deselect.
+ deselect();
+ startOfDoc();
+ }
+ break;
+
+ case KEY_END:
+ {
+ if( mask & MASK_SHIFT )
+ {
+ startSelection();
+ }
+ else
+ {
+ // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
+ // all move the cursor as if clicking, so should deselect.
+ deselect();
+ }
+ endOfDoc();
+ if( mask & MASK_SHIFT )
+ {
+ mSelectionEnd = mCursorPos;
+ }
+ break;
+ }
+
+ case KEY_RIGHT:
+ if( mCursorPos < getLength() )
+ {
+ // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
+ // all move the cursor as if clicking, so should deselect.
+ deselect();
+
+ setCursorPos(nextWordPos(mCursorPos + 1));
+ }
+ break;
+
+
+ case KEY_LEFT:
+ if( mCursorPos > 0 )
+ {
+ // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
+ // all move the cursor as if clicking, so should deselect.
+ deselect();
+
+ setCursorPos(prevWordPos(mCursorPos - 1));
+ }
+ break;
+
+ default:
+ handled = FALSE;
+ break;
+ }
+ }
+
+ if (handled && !gFocusMgr.getMouseCapture())
+ {
+ updatePrimary();
+ }
+
+ return handled;
+}
+
+
+BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask)
+ {
+ BOOL handled = TRUE;
+
+ if (mReadOnly) return FALSE;
+
+ switch( key )
+ {
+ case KEY_INSERT:
+ if (mask == MASK_NONE)
+ {
+ gKeyboard->toggleInsertMode();
+ }
+ break;
+
+ case KEY_BACKSPACE:
+ if( hasSelection() )
+ {
+ deleteSelection(FALSE);
+ }
+ else
+ if( 0 < mCursorPos )
+ {
+ removeCharOrTab();
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
+ break;
+
+
+ case KEY_RETURN:
+ if (mask == MASK_NONE)
+ {
+ if( hasSelection() && !mKeepSelectionOnReturn )
+ {
+ deleteSelection(FALSE);
+ }
+ if (mAutoIndent)
+ {
+ autoIndent();
+ }
+ }
+ else
+ {
+ handled = FALSE;
+ break;
+ }
+ break;
+
+ case KEY_TAB:
+ if (mask & MASK_CONTROL)
+ {
+ handled = FALSE;
+ break;
+ }
+ if( hasSelection() && selectionContainsLineBreaks() )
+ {
+ indentSelectedLines( (mask & MASK_SHIFT) ? -SPACES_PER_TAB : SPACES_PER_TAB );
+ }
+ else
+ {
+ if( hasSelection() )
+ {
+ deleteSelection(FALSE);
+ }
+
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+
+ S32 spaces_needed = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
+ for( S32 i=0; i < spaces_needed; i++ )
+ {
+ addChar( ' ' );
+ }
+ }
+ break;
+
+ default:
+ handled = FALSE;
+ break;
+ }
+
+ if (handled)
+ {
+ onKeyStroke();
+ }
+ return handled;
}
void LLTextEditor::unindentLineBeforeCloseBrace()
{
- if( mCursorPos >= 1 )
- {
- LLWString text = getWText();
- if( ' ' == text[ mCursorPos - 1 ] )
- {
- S32 line = getLineNumFromDocIndex(mCursorPos, false);
- S32 line_start = getLineStart(line);
-
- // Jump over spaces in the current line
- while ((' ' == text[line_start]) && (line_start < mCursorPos))
- {
- line_start++;
- }
-
- // Make sure there is nothing but ' ' before the Brace we are unindenting
- if (line_start == mCursorPos)
- {
- removeCharOrTab();
- }
- }
- }
+ if( mCursorPos >= 1 )
+ {
+ LLWString text = getWText();
+ if( ' ' == text[ mCursorPos - 1 ] )
+ {
+ S32 line = getLineNumFromDocIndex(mCursorPos, false);
+ S32 line_start = getLineStart(line);
+
+ // Jump over spaces in the current line
+ while ((' ' == text[line_start]) && (line_start < mCursorPos))
+ {
+ line_start++;
+ }
+
+ // Make sure there is nothing but ' ' before the Brace we are unindenting
+ if (line_start == mCursorPos)
+ {
+ removeCharOrTab();
+ }
+ }
+ }
}
BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
{
- BOOL handled = FALSE;
-
- // Special case for TAB. If want to move to next field, report
- // not handled and let the parent take care of field movement.
- if (KEY_TAB == key && mTabsToNextField)
- {
- return FALSE;
- }
-
- if (mReadOnly && mScroller)
- {
- handled = (mScroller && mScroller->handleKeyHere( key, mask ))
- || handleSelectionKey(key, mask)
- || handleControlKey(key, mask);
- }
- else
- {
- if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask))
- {
- return TRUE;
- }
-
- if (mEnableTooltipPaste &&
- LLToolTipMgr::instance().toolTipVisible() &&
+ BOOL handled = FALSE;
+
+ // Special case for TAB. If want to move to next field, report
+ // not handled and let the parent take care of field movement.
+ if (KEY_TAB == key && mTabsToNextField)
+ {
+ return FALSE;
+ }
+
+ if (mReadOnly && mScroller)
+ {
+ handled = (mScroller && mScroller->handleKeyHere( key, mask ))
+ || handleSelectionKey(key, mask)
+ || handleControlKey(key, mask);
+ }
+ else
+ {
+ if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask))
+ {
+ return TRUE;
+ }
+
+ if (mEnableTooltipPaste &&
+ LLToolTipMgr::instance().toolTipVisible() &&
LLToolTipMgr::instance().isTooltipPastable() &&
- KEY_TAB == key)
- { // Paste the first line of a tooltip into the editor
- std::string message;
- LLToolTipMgr::instance().getToolTipMessage(message);
- LLWString tool_tip_text(utf8str_to_wstring(message));
-
- if (tool_tip_text.size() > 0)
- {
- // Delete any selected characters (the tooltip text replaces them)
- if(hasSelection())
- {
- deleteSelection(TRUE);
- }
-
- std::basic_string<llwchar>::size_type pos = tool_tip_text.find('\n',0);
- if (pos != -1)
- { // Extract the first line of the tooltip
- tool_tip_text = std::basic_string<llwchar>(tool_tip_text, 0, pos);
- }
-
- // Add the text
- cleanStringForPaste(tool_tip_text);
- pasteTextWithLinebreaks(tool_tip_text);
- handled = TRUE;
- }
- }
- else
- { // Normal key handling
- handled = handleNavigationKey( key, mask )
- || handleSelectionKey(key, mask)
- || handleControlKey(key, mask)
- || handleSpecialKey(key, mask);
- }
- }
-
- if( handled )
- {
- resetCursorBlink();
- needsScroll();
-
- if (mShowEmojiHelper)
- {
- // Dismiss the helper whenever we handled a key that it didn't
- LLEmojiHelper::instance().hideHelper(this);
- }
- }
-
- return handled;
+ KEY_TAB == key)
+ { // Paste the first line of a tooltip into the editor
+ std::string message;
+ LLToolTipMgr::instance().getToolTipMessage(message);
+ LLWString tool_tip_text(utf8str_to_wstring(message));
+
+ if (tool_tip_text.size() > 0)
+ {
+ // Delete any selected characters (the tooltip text replaces them)
+ if(hasSelection())
+ {
+ deleteSelection(TRUE);
+ }
+
+ std::basic_string<llwchar>::size_type pos = tool_tip_text.find('\n',0);
+ if (pos != -1)
+ { // Extract the first line of the tooltip
+ tool_tip_text = std::basic_string<llwchar>(tool_tip_text, 0, pos);
+ }
+
+ // Add the text
+ cleanStringForPaste(tool_tip_text);
+ pasteTextWithLinebreaks(tool_tip_text);
+ handled = TRUE;
+ }
+ }
+ else
+ { // Normal key handling
+ handled = handleNavigationKey( key, mask )
+ || handleSelectionKey(key, mask)
+ || handleControlKey(key, mask)
+ || handleSpecialKey(key, mask);
+ }
+ }
+
+ if( handled )
+ {
+ resetCursorBlink();
+ needsScroll();
+
+ if (mShowEmojiHelper)
+ {
+ // Dismiss the helper whenever we handled a key that it didn't
+ LLEmojiHelper::instance().hideHelper(this);
+ }
+ }
+
+ return handled;
}
BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
{
- if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL
- {
- return FALSE;
- }
+ if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL
+ {
+ return FALSE;
+ }
- BOOL handled = FALSE;
+ BOOL handled = FALSE;
- // Handle most keys only if the text editor is writeable.
- if( !mReadOnly )
- {
+ // Handle most keys only if the text editor is writeable.
+ if( !mReadOnly )
+ {
if (mShowEmojiHelper && uni_char < 0x80 && LLEmojiHelper::instance().handleKey(this, (KEY)uni_char, MASK_NONE))
{
return TRUE;
}
if( mAutoIndent && '}' == uni_char )
- {
- unindentLineBeforeCloseBrace();
- }
+ {
+ unindentLineBeforeCloseBrace();
+ }
- // TODO: KLW Add auto show of tool tip on (
- addChar( uni_char );
+ // TODO: KLW Add auto show of tool tip on (
+ addChar( uni_char );
- // Keys that add characters temporarily hide the cursor
- getWindow()->hideCursorUntilMouseMove();
+ // Keys that add characters temporarily hide the cursor
+ getWindow()->hideCursorUntilMouseMove();
- handled = TRUE;
- }
+ handled = TRUE;
+ }
- if( handled )
- {
- resetCursorBlink();
+ if( handled )
+ {
+ resetCursorBlink();
- // Most keystrokes will make the selection box go away, but not all will.
- deselect();
+ // Most keystrokes will make the selection box go away, but not all will.
+ deselect();
- onKeyStroke();
- }
+ onKeyStroke();
+ }
- return handled;
+ return handled;
}
// virtual
BOOL LLTextEditor::canDoDelete() const
{
- return !mReadOnly && ( !mPassDelete || ( hasSelection() || (mCursorPos < getLength())) );
+ return !mReadOnly && ( !mPassDelete || ( hasSelection() || (mCursorPos < getLength())) );
}
void LLTextEditor::doDelete()
{
- if( !canDoDelete() )
- {
- return;
- }
- if( hasSelection() )
- {
- deleteSelection(FALSE);
- }
- else
- if( mCursorPos < getLength() )
- {
- S32 i;
- S32 chars_to_remove = 1;
- LLWString text = getWText();
- if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) )
- {
- // Try to remove a full tab's worth of spaces
- S32 offset = getLineOffsetFromDocIndex(mCursorPos);
- chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
- if( chars_to_remove == 0 )
- {
- chars_to_remove = SPACES_PER_TAB;
- }
-
- for( i = 0; i < chars_to_remove; i++ )
- {
- if( text[mCursorPos + i] != ' ' )
- {
- chars_to_remove = 1;
- break;
- }
- }
- }
-
- for( i = 0; i < chars_to_remove; i++ )
- {
- setCursorPos(mCursorPos + 1);
- removeChar();
- }
-
- }
-
- onKeyStroke();
+ if( !canDoDelete() )
+ {
+ return;
+ }
+ if( hasSelection() )
+ {
+ deleteSelection(FALSE);
+ }
+ else
+ if( mCursorPos < getLength() )
+ {
+ S32 i;
+ S32 chars_to_remove = 1;
+ LLWString text = getWText();
+ if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) )
+ {
+ // Try to remove a full tab's worth of spaces
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+ chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
+ if( chars_to_remove == 0 )
+ {
+ chars_to_remove = SPACES_PER_TAB;
+ }
+
+ for( i = 0; i < chars_to_remove; i++ )
+ {
+ if( text[mCursorPos + i] != ' ' )
+ {
+ chars_to_remove = 1;
+ break;
+ }
+ }
+ }
+
+ for( i = 0; i < chars_to_remove; i++ )
+ {
+ setCursorPos(mCursorPos + 1);
+ removeChar();
+ }
+
+ }
+
+ onKeyStroke();
}
//----------------------------------------------------------------------------
@@ -2018,624 +2019,624 @@ void LLTextEditor::doDelete()
void LLTextEditor::blockUndo()
{
- mBaseDocIsPristine = FALSE;
- mLastCmd = NULL;
- std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
- mUndoStack.clear();
+ mBaseDocIsPristine = FALSE;
+ mLastCmd = NULL;
+ std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
+ mUndoStack.clear();
}
// virtual
BOOL LLTextEditor::canUndo() const
{
- return !mReadOnly && mLastCmd != NULL;
+ return !mReadOnly && mLastCmd != NULL;
}
void LLTextEditor::undo()
{
- if( !canUndo() )
- {
- return;
- }
- deselect();
- S32 pos = 0;
- do
- {
- pos = mLastCmd->undo(this);
- undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
- if (iter != mUndoStack.end())
- ++iter;
- if (iter != mUndoStack.end())
- mLastCmd = *iter;
- else
- mLastCmd = NULL;
+ if( !canUndo() )
+ {
+ return;
+ }
+ deselect();
+ S32 pos = 0;
+ do
+ {
+ pos = mLastCmd->undo(this);
+ undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
+ if (iter != mUndoStack.end())
+ ++iter;
+ if (iter != mUndoStack.end())
+ mLastCmd = *iter;
+ else
+ mLastCmd = NULL;
- } while( mLastCmd && mLastCmd->groupWithNext() );
+ } while( mLastCmd && mLastCmd->groupWithNext() );
- setCursorPos(pos);
+ setCursorPos(pos);
- onKeyStroke();
+ onKeyStroke();
}
BOOL LLTextEditor::canRedo() const
{
- return !mReadOnly && (mUndoStack.size() > 0) && (mLastCmd != mUndoStack.front());
+ return !mReadOnly && (mUndoStack.size() > 0) && (mLastCmd != mUndoStack.front());
}
void LLTextEditor::redo()
{
- if( !canRedo() )
- {
- return;
- }
- deselect();
- S32 pos = 0;
- do
- {
- if( !mLastCmd )
- {
- mLastCmd = mUndoStack.back();
- }
- else
- {
- undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
- if (iter != mUndoStack.begin())
- mLastCmd = *(--iter);
- else
- mLastCmd = NULL;
- }
-
- if( mLastCmd )
- {
- pos = mLastCmd->redo(this);
- }
- } while(
- mLastCmd &&
- mLastCmd->groupWithNext() &&
- (mLastCmd != mUndoStack.front()) );
-
- setCursorPos(pos);
-
- onKeyStroke();
+ if( !canRedo() )
+ {
+ return;
+ }
+ deselect();
+ S32 pos = 0;
+ do
+ {
+ if( !mLastCmd )
+ {
+ mLastCmd = mUndoStack.back();
+ }
+ else
+ {
+ undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
+ if (iter != mUndoStack.begin())
+ mLastCmd = *(--iter);
+ else
+ mLastCmd = NULL;
+ }
+
+ if( mLastCmd )
+ {
+ pos = mLastCmd->redo(this);
+ }
+ } while(
+ mLastCmd &&
+ mLastCmd->groupWithNext() &&
+ (mLastCmd != mUndoStack.front()) );
+
+ setCursorPos(pos);
+
+ onKeyStroke();
}
void LLTextEditor::onFocusReceived()
{
- LLTextBase::onFocusReceived();
- updateAllowingLanguageInput();
+ LLTextBase::onFocusReceived();
+ updateAllowingLanguageInput();
}
void LLTextEditor::focusLostHelper()
{
- updateAllowingLanguageInput();
+ updateAllowingLanguageInput();
- // Route menu back to the default
- if( gEditMenuHandler == this )
- {
- gEditMenuHandler = NULL;
- }
+ // Route menu back to the default
+ if( gEditMenuHandler == this )
+ {
+ gEditMenuHandler = NULL;
+ }
- if (mCommitOnFocusLost)
- {
- onCommit();
- }
+ if (mCommitOnFocusLost)
+ {
+ onCommit();
+ }
- // Make sure cursor is shown again
- getWindow()->showCursorFromMouseMove();
+ // Make sure cursor is shown again
+ getWindow()->showCursorFromMouseMove();
}
void LLTextEditor::onFocusLost()
{
- focusLostHelper();
- LLTextBase::onFocusLost();
+ focusLostHelper();
+ LLTextBase::onFocusLost();
}
void LLTextEditor::onCommit()
{
- setControlValue(getValue());
- LLTextBase::onCommit();
+ setControlValue(getValue());
+ LLTextBase::onCommit();
}
void LLTextEditor::setEnabled(BOOL enabled)
{
- // just treat enabled as read-only flag
- bool read_only = !enabled;
- if (read_only != mReadOnly)
- {
- //mReadOnly = read_only;
- LLTextBase::setReadOnly(read_only);
- updateSegments();
- updateAllowingLanguageInput();
- }
+ // just treat enabled as read-only flag
+ bool read_only = !enabled;
+ if (read_only != mReadOnly)
+ {
+ //mReadOnly = read_only;
+ LLTextBase::setReadOnly(read_only);
+ updateSegments();
+ updateAllowingLanguageInput();
+ }
}
void LLTextEditor::showContextMenu(S32 x, S32 y)
{
- LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
- if (!menu)
- {
- llassert(LLMenuGL::sMenuContainer != NULL);
- menu = LLUICtrlFactory::createFromFile<LLContextMenu>("menu_text_editor.xml",
- LLMenuGL::sMenuContainer,
- LLMenuHolderGL::child_registry_t::instance());
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+ if (!menu)
+ {
+ llassert(LLMenuGL::sMenuContainer != NULL);
+ menu = LLUICtrlFactory::createFromFile<LLContextMenu>("menu_text_editor.xml",
+ LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
if(!menu)
{
LL_WARNS() << "Failed to create menu for LLTextEditor: " << getName() << LL_ENDL;
return;
}
- mContextMenuHandle = menu->getHandle();
- }
-
- // Route menu to this class
- // previously this was done in ::handleRightMoseDown:
- //if(hasTabStop())
- // setFocus(TRUE) - why? weird...
- // and then inside setFocus
- // ....
- // gEditMenuHandler = this;
- // ....
- // but this didn't work in all cases and just weird...
- //why not here?
- // (all this was done for EXT-4443)
-
- gEditMenuHandler = this;
-
- S32 screen_x, screen_y;
- localPointToScreen(x, y, &screen_x, &screen_y);
-
- setCursorAtLocalPos(x, y, false);
- if (hasSelection())
- {
- if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) )
- {
- deselect();
- }
- else
- {
- setCursorPos(llmax(mSelectionStart, mSelectionEnd));
- }
- }
-
- bool use_spellcheck = getSpellCheck(), is_misspelled = false;
- if (use_spellcheck)
- {
- mSuggestionList.clear();
-
- // If the cursor is on a misspelled word, retrieve suggestions for it
- std::string misspelled_word = getMisspelledWord(mCursorPos);
- if ((is_misspelled = !misspelled_word.empty()) == true)
- {
- LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList);
- }
- }
-
- menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty()));
- menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled));
- menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled));
- menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled));
- menu->show(screen_x, screen_y, this);
+ mContextMenuHandle = menu->getHandle();
+ }
+
+ // Route menu to this class
+ // previously this was done in ::handleRightMoseDown:
+ //if(hasTabStop())
+ // setFocus(TRUE) - why? weird...
+ // and then inside setFocus
+ // ....
+ // gEditMenuHandler = this;
+ // ....
+ // but this didn't work in all cases and just weird...
+ //why not here?
+ // (all this was done for EXT-4443)
+
+ gEditMenuHandler = this;
+
+ S32 screen_x, screen_y;
+ localPointToScreen(x, y, &screen_x, &screen_y);
+
+ setCursorAtLocalPos(x, y, false);
+ if (hasSelection())
+ {
+ if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) )
+ {
+ deselect();
+ }
+ else
+ {
+ setCursorPos(llmax(mSelectionStart, mSelectionEnd));
+ }
+ }
+
+ bool use_spellcheck = getSpellCheck(), is_misspelled = false;
+ if (use_spellcheck)
+ {
+ mSuggestionList.clear();
+
+ // If the cursor is on a misspelled word, retrieve suggestions for it
+ std::string misspelled_word = getMisspelledWord(mCursorPos);
+ if ((is_misspelled = !misspelled_word.empty()) == true)
+ {
+ LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList);
+ }
+ }
+
+ menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty()));
+ menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled));
+ menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled));
+ menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled));
+ menu->show(screen_x, screen_y, this);
}
void LLTextEditor::drawPreeditMarker()
{
- static LLUICachedControl<F32> preedit_marker_brightness ("UIPreeditMarkerBrightness", 0);
- static LLUICachedControl<S32> preedit_marker_gap ("UIPreeditMarkerGap", 0);
- static LLUICachedControl<S32> preedit_marker_position ("UIPreeditMarkerPosition", 0);
- static LLUICachedControl<S32> preedit_marker_thickness ("UIPreeditMarkerThickness", 0);
- static LLUICachedControl<F32> preedit_standout_brightness ("UIPreeditStandoutBrightness", 0);
- static LLUICachedControl<S32> preedit_standout_gap ("UIPreeditStandoutGap", 0);
- static LLUICachedControl<S32> preedit_standout_position ("UIPreeditStandoutPosition", 0);
- static LLUICachedControl<S32> preedit_standout_thickness ("UIPreeditStandoutThickness", 0);
+ static LLUICachedControl<F32> preedit_marker_brightness ("UIPreeditMarkerBrightness", 0);
+ static LLUICachedControl<S32> preedit_marker_gap ("UIPreeditMarkerGap", 0);
+ static LLUICachedControl<S32> preedit_marker_position ("UIPreeditMarkerPosition", 0);
+ static LLUICachedControl<S32> preedit_marker_thickness ("UIPreeditMarkerThickness", 0);
+ static LLUICachedControl<F32> preedit_standout_brightness ("UIPreeditStandoutBrightness", 0);
+ static LLUICachedControl<S32> preedit_standout_gap ("UIPreeditStandoutGap", 0);
+ static LLUICachedControl<S32> preedit_standout_position ("UIPreeditStandoutPosition", 0);
+ static LLUICachedControl<S32> preedit_standout_thickness ("UIPreeditStandoutThickness", 0);
- if (!hasPreeditString())
- {
- return;
- }
+ if (!hasPreeditString())
+ {
+ return;
+ }
const LLWString textString(getWText());
- const llwchar *text = textString.c_str();
- const S32 text_len = getLength();
- const S32 num_lines = getLineCount();
-
- S32 cur_line = getFirstVisibleLine();
- if (cur_line >= num_lines)
- {
- return;
- }
-
- const S32 line_height = mFont->getLineHeight();
-
- S32 line_start = getLineStart(cur_line);
- S32 line_y = mVisibleTextRect.mTop - line_height;
- while((mVisibleTextRect.mBottom <= line_y) && (num_lines > cur_line))
- {
- S32 next_start = -1;
- S32 line_end = text_len;
-
- if ((cur_line + 1) < num_lines)
- {
- next_start = getLineStart(cur_line + 1);
- line_end = next_start;
- }
- if ( text[line_end-1] == '\n' )
- {
- --line_end;
- }
-
- // Does this line contain preedits?
- if (line_start >= mPreeditPositions.back())
- {
- // We have passed the preedits.
- break;
- }
- if (line_end > mPreeditPositions.front())
- {
- for (U32 i = 0; i < mPreeditStandouts.size(); i++)
- {
- S32 left = mPreeditPositions[i];
- S32 right = mPreeditPositions[i + 1];
- if (right <= line_start || left >= line_end)
- {
- continue;
- }
-
- line_info& line = mLineInfoList[cur_line];
- LLRect text_rect(line.mRect);
- text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents
- text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position
-
- S32 preedit_left = text_rect.mLeft;
- if (left > line_start)
- {
- preedit_left += mFont->getWidth(text, line_start, left - line_start);
- }
- S32 preedit_right = text_rect.mLeft;
- if (right < line_end)
- {
- preedit_right += mFont->getWidth(text, line_start, right - line_start);
- }
- else
- {
- preedit_right += mFont->getWidth(text, line_start, line_end - line_start);
- }
-
- if (mPreeditStandouts[i])
- {
- gl_rect_2d(preedit_left + preedit_standout_gap,
- text_rect.mBottom + mFont->getDescenderHeight() - 1,
- preedit_right - preedit_standout_gap - 1,
- text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_standout_thickness,
- (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f));
- }
- else
- {
- gl_rect_2d(preedit_left + preedit_marker_gap,
- text_rect.mBottom + mFont->getDescenderHeight() - 1,
- preedit_right - preedit_marker_gap - 1,
- text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_marker_thickness,
- (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f));
- }
- }
- }
-
- // move down one line
- line_y -= line_height;
- line_start = next_start;
- cur_line++;
- }
+ const llwchar *text = textString.c_str();
+ const S32 text_len = getLength();
+ const S32 num_lines = getLineCount();
+
+ S32 cur_line = getFirstVisibleLine();
+ if (cur_line >= num_lines)
+ {
+ return;
+ }
+
+ const S32 line_height = mFont->getLineHeight();
+
+ S32 line_start = getLineStart(cur_line);
+ S32 line_y = mVisibleTextRect.mTop - line_height;
+ while((mVisibleTextRect.mBottom <= line_y) && (num_lines > cur_line))
+ {
+ S32 next_start = -1;
+ S32 line_end = text_len;
+
+ if ((cur_line + 1) < num_lines)
+ {
+ next_start = getLineStart(cur_line + 1);
+ line_end = next_start;
+ }
+ if ( text[line_end-1] == '\n' )
+ {
+ --line_end;
+ }
+
+ // Does this line contain preedits?
+ if (line_start >= mPreeditPositions.back())
+ {
+ // We have passed the preedits.
+ break;
+ }
+ if (line_end > mPreeditPositions.front())
+ {
+ for (U32 i = 0; i < mPreeditStandouts.size(); i++)
+ {
+ S32 left = mPreeditPositions[i];
+ S32 right = mPreeditPositions[i + 1];
+ if (right <= line_start || left >= line_end)
+ {
+ continue;
+ }
+
+ line_info& line = mLineInfoList[cur_line];
+ LLRect text_rect(line.mRect);
+ text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents
+ text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position
+
+ S32 preedit_left = text_rect.mLeft;
+ if (left > line_start)
+ {
+ preedit_left += mFont->getWidth(text, line_start, left - line_start);
+ }
+ S32 preedit_right = text_rect.mLeft;
+ if (right < line_end)
+ {
+ preedit_right += mFont->getWidth(text, line_start, right - line_start);
+ }
+ else
+ {
+ preedit_right += mFont->getWidth(text, line_start, line_end - line_start);
+ }
+
+ if (mPreeditStandouts[i])
+ {
+ gl_rect_2d(preedit_left + preedit_standout_gap,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1,
+ preedit_right - preedit_standout_gap - 1,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_standout_thickness,
+ (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f));
+ }
+ else
+ {
+ gl_rect_2d(preedit_left + preedit_marker_gap,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1,
+ preedit_right - preedit_marker_gap - 1,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_marker_thickness,
+ (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f));
+ }
+ }
+ }
+
+ // move down one line
+ line_y -= line_height;
+ line_start = next_start;
+ cur_line++;
+ }
}
void LLTextEditor::draw()
{
- {
- // pad clipping rectangle so that cursor can draw at full width
- // when at left edge of mVisibleTextRect
- LLRect clip_rect(mVisibleTextRect);
- clip_rect.stretch(1);
- LLLocalClipRect clip(clip_rect);
- }
+ {
+ // pad clipping rectangle so that cursor can draw at full width
+ // when at left edge of mVisibleTextRect
+ LLRect clip_rect(mVisibleTextRect);
+ clip_rect.stretch(1);
+ LLLocalClipRect clip(clip_rect);
+ }
- LLTextBase::draw();
+ LLTextBase::draw();
drawPreeditMarker();
- //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
- // when in readonly mode
- mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly);
+ //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
+ // when in readonly mode
+ mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly);
}
// Start or stop the editor from accepting text-editing keystrokes
// see also LLLineEditor
void LLTextEditor::setFocus( BOOL new_state )
{
- BOOL old_state = hasFocus();
+ BOOL old_state = hasFocus();
- // Don't change anything if the focus state didn't change
- if (new_state == old_state) return;
+ // Don't change anything if the focus state didn't change
+ if (new_state == old_state) return;
- // Notify early if we are losing focus.
- if (!new_state)
- {
- getWindow()->allowLanguageTextInput(this, FALSE);
- }
+ // Notify early if we are losing focus.
+ if (!new_state)
+ {
+ getWindow()->allowLanguageTextInput(this, FALSE);
+ }
- LLTextBase::setFocus( new_state );
+ LLTextBase::setFocus( new_state );
- if( new_state )
- {
- // Route menu to this class
- gEditMenuHandler = this;
+ if( new_state )
+ {
+ // Route menu to this class
+ gEditMenuHandler = this;
- // Don't start the cursor flashing right away
- resetCursorBlink();
- }
- else
- {
- // Route menu back to the default
- if( gEditMenuHandler == this )
- {
- gEditMenuHandler = NULL;
- }
+ // Don't start the cursor flashing right away
+ resetCursorBlink();
+ }
+ else
+ {
+ // Route menu back to the default
+ if( gEditMenuHandler == this )
+ {
+ gEditMenuHandler = NULL;
+ }
- endSelection();
- }
+ endSelection();
+ }
}
// public
void LLTextEditor::setCursorAndScrollToEnd()
{
- deselect();
- endOfDoc();
+ deselect();
+ endOfDoc();
}
-void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap )
-{
- *line = getLineNumFromDocIndex(mCursorPos, include_wordwrap);
- *col = getLineOffsetFromDocIndex(mCursorPos, include_wordwrap);
+void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap )
+{
+ *line = getLineNumFromDocIndex(mCursorPos, include_wordwrap);
+ *col = getLineOffsetFromDocIndex(mCursorPos, include_wordwrap);
}
void LLTextEditor::autoIndent()
{
- // Count the number of spaces in the current line
- S32 line = getLineNumFromDocIndex(mCursorPos, false);
- S32 line_start = getLineStart(line);
- S32 space_count = 0;
- S32 i;
+ // Count the number of spaces in the current line
+ S32 line = getLineNumFromDocIndex(mCursorPos, false);
+ S32 line_start = getLineStart(line);
+ S32 space_count = 0;
+ S32 i;
- LLWString text = getWText();
- S32 offset = getLineOffsetFromDocIndex(mCursorPos);
- while(( ' ' == text[line_start] ) && (space_count < offset))
- {
- space_count++;
- line_start++;
- }
+ LLWString text = getWText();
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+ while(( ' ' == text[line_start] ) && (space_count < offset))
+ {
+ space_count++;
+ line_start++;
+ }
- // If we're starting a braced section, indent one level.
- if( (mCursorPos > 0) && (text[mCursorPos -1] == '{') )
- {
- space_count += SPACES_PER_TAB;
- }
+ // If we're starting a braced section, indent one level.
+ if( (mCursorPos > 0) && (text[mCursorPos -1] == '{') )
+ {
+ space_count += SPACES_PER_TAB;
+ }
- // Insert that number of spaces on the new line
+ // Insert that number of spaces on the new line
- //appendLineBreakSegment(LLStyle::Params());//addChar( '\n' );
- addLineBreakChar();
+ //appendLineBreakSegment(LLStyle::Params());//addChar( '\n' );
+ addLineBreakChar();
- for( i = 0; i < space_count; i++ )
- {
- addChar( ' ' );
- }
+ for( i = 0; i < space_count; i++ )
+ {
+ addChar( ' ' );
+ }
}
// Inserts new text at the cursor position
void LLTextEditor::insertText(const std::string &new_text)
{
- BOOL enabled = getEnabled();
- setEnabled( TRUE );
+ BOOL enabled = getEnabled();
+ setEnabled( TRUE );
- // Delete any selected characters (the insertion replaces them)
- if( hasSelection() )
- {
- deleteSelection(TRUE);
- }
-
- setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE, LLTextSegmentPtr() ));
+ // Delete any selected characters (the insertion replaces them)
+ if( hasSelection() )
+ {
+ deleteSelection(TRUE);
+ }
- setEnabled( enabled );
+ setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE, LLTextSegmentPtr() ));
+
+ setEnabled( enabled );
}
void LLTextEditor::insertText(LLWString &new_text)
{
- BOOL enabled = getEnabled();
- setEnabled( TRUE );
+ BOOL enabled = getEnabled();
+ setEnabled( TRUE );
- // Delete any selected characters (the insertion replaces them)
- if( hasSelection() )
- {
- deleteSelection(TRUE);
- }
+ // Delete any selected characters (the insertion replaces them)
+ if( hasSelection() )
+ {
+ deleteSelection(TRUE);
+ }
- setCursorPos(mCursorPos + insert( mCursorPos, new_text, FALSE, LLTextSegmentPtr() ));
+ setCursorPos(mCursorPos + insert( mCursorPos, new_text, FALSE, LLTextSegmentPtr() ));
- setEnabled( enabled );
+ setEnabled( enabled );
}
void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo)
{
- // Save old state
- S32 selection_start = mSelectionStart;
- S32 selection_end = mSelectionEnd;
- BOOL was_selecting = mIsSelecting;
- S32 cursor_pos = mCursorPos;
- S32 old_length = getLength();
- BOOL cursor_was_at_end = (mCursorPos == old_length);
+ // Save old state
+ S32 selection_start = mSelectionStart;
+ S32 selection_end = mSelectionEnd;
+ BOOL was_selecting = mIsSelecting;
+ S32 cursor_pos = mCursorPos;
+ S32 old_length = getLength();
+ BOOL cursor_was_at_end = (mCursorPos == old_length);
- deselect();
+ deselect();
- setCursorPos(old_length);
+ setCursorPos(old_length);
- LLWString widget_wide_text = utf8str_to_wstring(text);
+ LLWString widget_wide_text = utf8str_to_wstring(text);
- LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
- insert(getLength(), widget_wide_text, FALSE, segment);
+ LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
+ insert(getLength(), widget_wide_text, FALSE, segment);
- // Set the cursor and scroll position
- if( selection_start != selection_end )
- {
- mSelectionStart = selection_start;
- mSelectionEnd = selection_end;
+ // Set the cursor and scroll position
+ if( selection_start != selection_end )
+ {
+ mSelectionStart = selection_start;
+ mSelectionEnd = selection_end;
- mIsSelecting = was_selecting;
- setCursorPos(cursor_pos);
- }
- else if( cursor_was_at_end )
- {
- setCursorPos(getLength());
- }
- else
- {
- setCursorPos(cursor_pos);
- }
+ mIsSelecting = was_selecting;
+ setCursorPos(cursor_pos);
+ }
+ else if( cursor_was_at_end )
+ {
+ setCursorPos(getLength());
+ }
+ else
+ {
+ setCursorPos(cursor_pos);
+ }
- if (!allow_undo)
- {
- blockUndo();
- }
+ if (!allow_undo)
+ {
+ blockUndo();
+ }
}
void LLTextEditor::removeTextFromEnd(S32 num_chars)
{
- if (num_chars <= 0) return;
+ if (num_chars <= 0) return;
- remove(getLength() - num_chars, num_chars, FALSE);
+ remove(getLength() - num_chars, num_chars, FALSE);
- S32 len = getLength();
- setCursorPos (llclamp(mCursorPos, 0, len));
- mSelectionStart = llclamp(mSelectionStart, 0, len);
- mSelectionEnd = llclamp(mSelectionEnd, 0, len);
+ S32 len = getLength();
+ setCursorPos (llclamp(mCursorPos, 0, len));
+ mSelectionStart = llclamp(mSelectionStart, 0, len);
+ mSelectionEnd = llclamp(mSelectionEnd, 0, len);
- needsScroll();
+ needsScroll();
}
//----------------------------------------------------------------------------
void LLTextEditor::onSpellCheckPerformed()
{
- if (isPristine())
- {
- mBaseDocIsPristine = FALSE;
- }
+ if (isPristine())
+ {
+ mBaseDocIsPristine = FALSE;
+ }
}
void LLTextEditor::makePristine()
{
- mPristineCmd = mLastCmd;
- mBaseDocIsPristine = !mLastCmd;
+ mPristineCmd = mLastCmd;
+ mBaseDocIsPristine = !mLastCmd;
- // Create a clean partition in the undo stack. We don't want a single command to extend from
- // the "pre-pristine" state to the "post-pristine" state.
- if( mLastCmd )
- {
- mLastCmd->blockExtensions();
- }
+ // Create a clean partition in the undo stack. We don't want a single command to extend from
+ // the "pre-pristine" state to the "post-pristine" state.
+ if( mLastCmd )
+ {
+ mLastCmd->blockExtensions();
+ }
}
BOOL LLTextEditor::isPristine() const
{
- if( mPristineCmd )
- {
- return (mPristineCmd == mLastCmd);
- }
- else
- {
- // No undo stack, so check if the version before and commands were done was the original version
- return !mLastCmd && mBaseDocIsPristine;
- }
+ if( mPristineCmd )
+ {
+ return (mPristineCmd == mLastCmd);
+ }
+ else
+ {
+ // No undo stack, so check if the version before and commands were done was the original version
+ return !mLastCmd && mBaseDocIsPristine;
+ }
}
BOOL LLTextEditor::tryToRevertToPristineState()
{
- if( !isPristine() )
- {
- deselect();
- S32 i = 0;
- while( !isPristine() && canUndo() )
- {
- undo();
- i--;
- }
-
- while( !isPristine() && canRedo() )
- {
- redo();
- i++;
- }
-
- if( !isPristine() )
- {
- // failed, so go back to where we started
- while( i > 0 )
- {
- undo();
- i--;
- }
- }
- }
-
- return isPristine(); // TRUE => success
+ if( !isPristine() )
+ {
+ deselect();
+ S32 i = 0;
+ while( !isPristine() && canUndo() )
+ {
+ undo();
+ i--;
+ }
+
+ while( !isPristine() && canRedo() )
+ {
+ redo();
+ i++;
+ }
+
+ if( !isPristine() )
+ {
+ // failed, so go back to where we started
+ while( i > 0 )
+ {
+ undo();
+ i--;
+ }
+ }
+ }
+
+ return isPristine(); // TRUE => success
}
void LLTextEditor::updateLinkSegments()
{
- LLWString wtext = getWText();
-
- // update any segments that contain a link
- for (segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); ++it)
- {
- LLTextSegment *segment = *it;
- if (segment && segment->getStyle() && segment->getStyle()->isLink())
- {
- LLStyleConstSP style = segment->getStyle();
- LLStyleSP new_style(new LLStyle(*style));
- LLWString url_label = wtext.substr(segment->getStart(), segment->getEnd()-segment->getStart());
-
- segment_set_t::const_iterator next_it = mSegments.upper_bound(segment);
- LLTextSegment *next_segment = *next_it;
- if (next_segment)
- {
- LLWString next_url_label = wtext.substr(next_segment->getStart(), next_segment->getEnd()-next_segment->getStart());
- std::string link_check = wstring_to_utf8str(url_label) + wstring_to_utf8str(next_url_label);
- LLUrlMatch match;
-
- if ( LLUrlRegistry::instance().findUrl(link_check, match))
- {
- if(match.getQuery() == wstring_to_utf8str(next_url_label))
- {
- continue;
- }
- }
- }
-
- // if the link's label (what the user can edit) is a valid Url,
- // then update the link's HREF to be the same as the label text.
- // This lets users edit Urls in-place.
- if (acceptsTextInput() && LLUrlRegistry::instance().hasUrl(url_label))
- {
- std::string new_url = wstring_to_utf8str(url_label);
- LLStringUtil::trim(new_url);
- new_style->setLinkHREF(new_url);
- LLStyleConstSP sp(new_style);
- segment->setStyle(sp);
- }
- }
- }
+ LLWString wtext = getWText();
+
+ // update any segments that contain a link
+ for (segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); ++it)
+ {
+ LLTextSegment *segment = *it;
+ if (segment && segment->getStyle() && segment->getStyle()->isLink())
+ {
+ LLStyleConstSP style = segment->getStyle();
+ LLStyleSP new_style(new LLStyle(*style));
+ LLWString url_label = wtext.substr(segment->getStart(), segment->getEnd()-segment->getStart());
+
+ segment_set_t::const_iterator next_it = mSegments.upper_bound(segment);
+ LLTextSegment *next_segment = *next_it;
+ if (next_segment)
+ {
+ LLWString next_url_label = wtext.substr(next_segment->getStart(), next_segment->getEnd()-next_segment->getStart());
+ std::string link_check = wstring_to_utf8str(url_label) + wstring_to_utf8str(next_url_label);
+ LLUrlMatch match;
+
+ if ( LLUrlRegistry::instance().findUrl(link_check, match))
+ {
+ if(match.getQuery() == wstring_to_utf8str(next_url_label))
+ {
+ continue;
+ }
+ }
+ }
+
+ // if the link's label (what the user can edit) is a valid Url,
+ // then update the link's HREF to be the same as the label text.
+ // This lets users edit Urls in-place.
+ if (acceptsTextInput() && LLUrlRegistry::instance().hasUrl(url_label))
+ {
+ std::string new_url = wstring_to_utf8str(url_label);
+ LLStringUtil::trim(new_url);
+ new_style->setLinkHREF(new_url);
+ LLStyleConstSP sp(new_style);
+ segment->setStyle(sp);
+ }
+ }
+ }
}
void LLTextEditor::onMouseCaptureLost()
{
- endSelection();
+ endSelection();
}
///////////////////////////////////////////////////////////////////
@@ -2643,135 +2644,135 @@ void LLTextEditor::onMouseCaptureLost()
BOOL LLTextEditor::importBuffer(const char* buffer, S32 length )
{
- std::istringstream instream(buffer);
-
- // Version 1 format:
- // Linden text version 1\n
- // {\n
- // <EmbeddedItemList chunk>
- // Text length <bytes without \0>\n
- // <text without \0> (text may contain ext_char_values)
- // }\n
-
- char tbuf[MAX_STRING]; /* Flawfinder: ignore */
-
- S32 version = 0;
- instream.getline(tbuf, MAX_STRING);
- if( 1 != sscanf(tbuf, "Linden text version %d", &version) )
- {
- LL_WARNS() << "Invalid Linden text file header " << LL_ENDL;
- return FALSE;
- }
-
- if( 1 != version )
- {
- LL_WARNS() << "Invalid Linden text file version: " << version << LL_ENDL;
- return FALSE;
- }
-
- instream.getline(tbuf, MAX_STRING);
- if( 0 != sscanf(tbuf, "{") )
- {
- LL_WARNS() << "Invalid Linden text file format" << LL_ENDL;
- return FALSE;
- }
-
- S32 text_len = 0;
- instream.getline(tbuf, MAX_STRING);
- if( 1 != sscanf(tbuf, "Text length %d", &text_len) )
- {
- LL_WARNS() << "Invalid Linden text length field" << LL_ENDL;
- return FALSE;
- }
-
- if( text_len > mMaxTextByteLength )
- {
- LL_WARNS() << "Invalid Linden text length: " << text_len << LL_ENDL;
- return FALSE;
- }
-
- BOOL success = TRUE;
-
- char* text = new char[ text_len + 1];
- if (text == NULL)
- {
+ std::istringstream instream(buffer);
+
+ // Version 1 format:
+ // Linden text version 1\n
+ // {\n
+ // <EmbeddedItemList chunk>
+ // Text length <bytes without \0>\n
+ // <text without \0> (text may contain ext_char_values)
+ // }\n
+
+ char tbuf[MAX_STRING]; /* Flawfinder: ignore */
+
+ S32 version = 0;
+ instream.getline(tbuf, MAX_STRING);
+ if( 1 != sscanf(tbuf, "Linden text version %d", &version) )
+ {
+ LL_WARNS() << "Invalid Linden text file header " << LL_ENDL;
+ return FALSE;
+ }
+
+ if( 1 != version )
+ {
+ LL_WARNS() << "Invalid Linden text file version: " << version << LL_ENDL;
+ return FALSE;
+ }
+
+ instream.getline(tbuf, MAX_STRING);
+ if( 0 != sscanf(tbuf, "{") )
+ {
+ LL_WARNS() << "Invalid Linden text file format" << LL_ENDL;
+ return FALSE;
+ }
+
+ S32 text_len = 0;
+ instream.getline(tbuf, MAX_STRING);
+ if( 1 != sscanf(tbuf, "Text length %d", &text_len) )
+ {
+ LL_WARNS() << "Invalid Linden text length field" << LL_ENDL;
+ return FALSE;
+ }
+
+ if( text_len > mMaxTextByteLength )
+ {
+ LL_WARNS() << "Invalid Linden text length: " << text_len << LL_ENDL;
+ return FALSE;
+ }
+
+ BOOL success = TRUE;
+
+ char* text = new char[ text_len + 1];
+ if (text == NULL)
+ {
LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS() << "Memory allocation failure." << LL_ENDL;
- return FALSE;
- }
- instream.get(text, text_len + 1, '\0');
- text[text_len] = '\0';
- if( text_len != (S32)strlen(text) )/* Flawfinder: ignore */
- {
- LL_WARNS() << llformat("Invalid text length: %d != %d ",strlen(text),text_len) << LL_ENDL;/* Flawfinder: ignore */
- success = FALSE;
- }
-
- instream.getline(tbuf, MAX_STRING);
- if( success && (0 != sscanf(tbuf, "}")) )
- {
- LL_WARNS() << "Invalid Linden text file format: missing terminal }" << LL_ENDL;
- success = FALSE;
- }
-
- if( success )
- {
- // Actually set the text
- setText( LLStringExplicit(text) );
- }
-
- delete[] text;
-
- startOfDoc();
- deselect();
-
- return success;
+ LL_ERRS() << "Memory allocation failure." << LL_ENDL;
+ return FALSE;
+ }
+ instream.get(text, text_len + 1, '\0');
+ text[text_len] = '\0';
+ if( text_len != (S32)strlen(text) )/* Flawfinder: ignore */
+ {
+ LL_WARNS() << llformat("Invalid text length: %d != %d ",strlen(text),text_len) << LL_ENDL;/* Flawfinder: ignore */
+ success = FALSE;
+ }
+
+ instream.getline(tbuf, MAX_STRING);
+ if( success && (0 != sscanf(tbuf, "}")) )
+ {
+ LL_WARNS() << "Invalid Linden text file format: missing terminal }" << LL_ENDL;
+ success = FALSE;
+ }
+
+ if( success )
+ {
+ // Actually set the text
+ setText( LLStringExplicit(text) );
+ }
+
+ delete[] text;
+
+ startOfDoc();
+ deselect();
+
+ return success;
}
BOOL LLTextEditor::exportBuffer(std::string &buffer )
{
- std::ostringstream outstream(buffer);
-
- outstream << "Linden text version 1\n";
- outstream << "{\n";
+ std::ostringstream outstream(buffer);
+
+ outstream << "Linden text version 1\n";
+ outstream << "{\n";
- outstream << llformat("Text length %d\n", getLength() );
- outstream << getText();
- outstream << "}\n";
+ outstream << llformat("Text length %d\n", getLength() );
+ outstream << getText();
+ outstream << "}\n";
- return TRUE;
+ return TRUE;
}
void LLTextEditor::updateAllowingLanguageInput()
{
- LLWindow* window = getWindow();
- if (!window)
- {
- // test app, no window available
- return;
- }
- if (hasFocus() && !mReadOnly)
- {
- window->allowLanguageTextInput(this, TRUE);
- }
- else
- {
- window->allowLanguageTextInput(this, FALSE);
- }
+ LLWindow* window = getWindow();
+ if (!window)
+ {
+ // test app, no window available
+ return;
+ }
+ if (hasFocus() && !mReadOnly)
+ {
+ window->allowLanguageTextInput(this, TRUE);
+ }
+ else
+ {
+ window->allowLanguageTextInput(this, FALSE);
+ }
}
// Preedit is managed off the undo/redo command stack.
BOOL LLTextEditor::hasPreeditString() const
{
- return (mPreeditPositions.size() > 1);
+ return (mPreeditPositions.size() > 1);
}
void LLTextEditor::resetPreedit()
{
if (hasSelection())
{
- if (hasPreeditString())
+ if (hasPreeditString())
{
LL_WARNS() << "Preedit and selection!" << LL_ENDL;
deselect();
@@ -2781,277 +2782,277 @@ void LLTextEditor::resetPreedit()
deleteSelection(TRUE);
}
}
- if (hasPreeditString())
- {
- if (hasSelection())
- {
- LL_WARNS() << "Preedit and selection!" << LL_ENDL;
- deselect();
- }
+ if (hasPreeditString())
+ {
+ if (hasSelection())
+ {
+ LL_WARNS() << "Preedit and selection!" << LL_ENDL;
+ deselect();
+ }
- setCursorPos(mPreeditPositions.front());
- removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);
- insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString);
+ setCursorPos(mPreeditPositions.front());
+ removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);
+ insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString);
- mPreeditWString.clear();
- mPreeditOverwrittenWString.clear();
- mPreeditPositions.clear();
+ mPreeditWString.clear();
+ mPreeditOverwrittenWString.clear();
+ mPreeditPositions.clear();
- // A call to updatePreedit should soon follow under a
- // normal course of operation, so we don't need to
- // maintain internal variables such as line start
- // positions now.
- }
+ // A call to updatePreedit should soon follow under a
+ // normal course of operation, so we don't need to
+ // maintain internal variables such as line start
+ // positions now.
+ }
}
void LLTextEditor::updatePreedit(const LLWString &preedit_string,
- const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position)
+ const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position)
{
- // Just in case.
- if (mReadOnly)
- {
- return;
- }
+ // Just in case.
+ if (mReadOnly)
+ {
+ return;
+ }
- getWindow()->hideCursorUntilMouseMove();
+ getWindow()->hideCursorUntilMouseMove();
- S32 insert_preedit_at = mCursorPos;
-
- mPreeditWString = preedit_string;
- mPreeditPositions.resize(preedit_segment_lengths.size() + 1);
- S32 position = insert_preedit_at;
- for (segment_lengths_t::size_type i = 0; i < preedit_segment_lengths.size(); i++)
- {
- mPreeditPositions[i] = position;
- position += preedit_segment_lengths[i];
- }
- mPreeditPositions.back() = position;
+ S32 insert_preedit_at = mCursorPos;
- if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
- {
- mPreeditOverwrittenWString = getWText().substr(insert_preedit_at, mPreeditWString.length());
- removeStringNoUndo(insert_preedit_at, mPreeditWString.length());
- }
- else
- {
- mPreeditOverwrittenWString.clear();
- }
+ mPreeditWString = preedit_string;
+ mPreeditPositions.resize(preedit_segment_lengths.size() + 1);
+ S32 position = insert_preedit_at;
+ for (segment_lengths_t::size_type i = 0; i < preedit_segment_lengths.size(); i++)
+ {
+ mPreeditPositions[i] = position;
+ position += preedit_segment_lengths[i];
+ }
+ mPreeditPositions.back() = position;
- segment_vec_t segments;
- //pass empty segments to let "insertStringNoUndo" make new LLNormalTextSegment and insert it, if needed.
- insertStringNoUndo(insert_preedit_at, mPreeditWString, &segments);
+ if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
+ {
+ mPreeditOverwrittenWString = getWText().substr(insert_preedit_at, mPreeditWString.length());
+ removeStringNoUndo(insert_preedit_at, mPreeditWString.length());
+ }
+ else
+ {
+ mPreeditOverwrittenWString.clear();
+ }
+
+ segment_vec_t segments;
+ //pass empty segments to let "insertStringNoUndo" make new LLNormalTextSegment and insert it, if needed.
+ insertStringNoUndo(insert_preedit_at, mPreeditWString, &segments);
- mPreeditStandouts = preedit_standouts;
+ mPreeditStandouts = preedit_standouts;
- setCursorPos(insert_preedit_at + caret_position);
+ setCursorPos(insert_preedit_at + caret_position);
- // Update of the preedit should be caused by some key strokes.
- resetCursorBlink();
+ // Update of the preedit should be caused by some key strokes.
+ resetCursorBlink();
- onKeyStroke();
+ onKeyStroke();
}
BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const
{
- if (control)
- {
- LLRect control_rect_screen;
- localRectToScreen(mVisibleTextRect, &control_rect_screen);
- LLUI::getInstance()->screenRectToGL(control_rect_screen, control);
- }
-
- S32 preedit_left_position, preedit_right_position;
- if (hasPreeditString())
- {
- preedit_left_position = mPreeditPositions.front();
- preedit_right_position = mPreeditPositions.back();
- }
- else
- {
- preedit_left_position = preedit_right_position = mCursorPos;
- }
-
- const S32 query = (query_offset >= 0 ? preedit_left_position + query_offset : mCursorPos);
- if (query < preedit_left_position || query > preedit_right_position)
- {
- return FALSE;
- }
-
- const S32 first_visible_line = getFirstVisibleLine();
- if (query < getLineStart(first_visible_line))
- {
- return FALSE;
- }
-
- S32 current_line = first_visible_line;
- S32 current_line_start, current_line_end;
- for (;;)
- {
- current_line_start = getLineStart(current_line);
- current_line_end = getLineStart(current_line + 1);
- if (query >= current_line_start && query < current_line_end)
- {
- break;
- }
- if (current_line_start == current_line_end)
- {
- // We have reached on the last line. The query position must be here.
- break;
- }
- current_line++;
- }
+ if (control)
+ {
+ LLRect control_rect_screen;
+ localRectToScreen(mVisibleTextRect, &control_rect_screen);
+ LLUI::getInstance()->screenRectToGL(control_rect_screen, control);
+ }
+
+ S32 preedit_left_position, preedit_right_position;
+ if (hasPreeditString())
+ {
+ preedit_left_position = mPreeditPositions.front();
+ preedit_right_position = mPreeditPositions.back();
+ }
+ else
+ {
+ preedit_left_position = preedit_right_position = mCursorPos;
+ }
+
+ const S32 query = (query_offset >= 0 ? preedit_left_position + query_offset : mCursorPos);
+ if (query < preedit_left_position || query > preedit_right_position)
+ {
+ return FALSE;
+ }
+
+ const S32 first_visible_line = getFirstVisibleLine();
+ if (query < getLineStart(first_visible_line))
+ {
+ return FALSE;
+ }
+
+ S32 current_line = first_visible_line;
+ S32 current_line_start, current_line_end;
+ for (;;)
+ {
+ current_line_start = getLineStart(current_line);
+ current_line_end = getLineStart(current_line + 1);
+ if (query >= current_line_start && query < current_line_end)
+ {
+ break;
+ }
+ if (current_line_start == current_line_end)
+ {
+ // We have reached on the last line. The query position must be here.
+ break;
+ }
+ current_line++;
+ }
const LLWString textString(getWText());
- const llwchar * const text = textString.c_str();
- const S32 line_height = mFont->getLineHeight();
-
- if (coord)
- {
- const S32 query_x = mVisibleTextRect.mLeft + mFont->getWidth(text, current_line_start, query - current_line_start);
- const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
- S32 query_screen_x, query_screen_y;
- localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y);
- LLUI::getInstance()->screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY);
- }
-
- if (bounds)
- {
- S32 preedit_left = mVisibleTextRect.mLeft;
- if (preedit_left_position > current_line_start)
- {
- preedit_left += mFont->getWidth(text, current_line_start, preedit_left_position - current_line_start);
- }
-
- S32 preedit_right = mVisibleTextRect.mLeft;
- if (preedit_right_position < current_line_end)
- {
- preedit_right += mFont->getWidth(text, current_line_start, preedit_right_position - current_line_start);
- }
- else
- {
- preedit_right += mFont->getWidth(text, current_line_start, current_line_end - current_line_start);
- }
-
- const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height;
- const S32 preedit_bottom = preedit_top - line_height;
-
- const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom);
- LLRect preedit_rect_screen;
- localRectToScreen(preedit_rect_local, &preedit_rect_screen);
- LLUI::getInstance()->screenRectToGL(preedit_rect_screen, bounds);
- }
-
- return TRUE;
+ const llwchar * const text = textString.c_str();
+ const S32 line_height = mFont->getLineHeight();
+
+ if (coord)
+ {
+ const S32 query_x = mVisibleTextRect.mLeft + mFont->getWidth(text, current_line_start, query - current_line_start);
+ const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
+ S32 query_screen_x, query_screen_y;
+ localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y);
+ LLUI::getInstance()->screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY);
+ }
+
+ if (bounds)
+ {
+ S32 preedit_left = mVisibleTextRect.mLeft;
+ if (preedit_left_position > current_line_start)
+ {
+ preedit_left += mFont->getWidth(text, current_line_start, preedit_left_position - current_line_start);
+ }
+
+ S32 preedit_right = mVisibleTextRect.mLeft;
+ if (preedit_right_position < current_line_end)
+ {
+ preedit_right += mFont->getWidth(text, current_line_start, preedit_right_position - current_line_start);
+ }
+ else
+ {
+ preedit_right += mFont->getWidth(text, current_line_start, current_line_end - current_line_start);
+ }
+
+ const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height;
+ const S32 preedit_bottom = preedit_top - line_height;
+
+ const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom);
+ LLRect preedit_rect_screen;
+ localRectToScreen(preedit_rect_local, &preedit_rect_screen);
+ LLUI::getInstance()->screenRectToGL(preedit_rect_screen, bounds);
+ }
+
+ return TRUE;
}
void LLTextEditor::getSelectionRange(S32 *position, S32 *length) const
{
- if (hasSelection())
- {
- *position = llmin(mSelectionStart, mSelectionEnd);
- *length = llabs(mSelectionStart - mSelectionEnd);
- }
- else
- {
- *position = mCursorPos;
- *length = 0;
- }
+ if (hasSelection())
+ {
+ *position = llmin(mSelectionStart, mSelectionEnd);
+ *length = llabs(mSelectionStart - mSelectionEnd);
+ }
+ else
+ {
+ *position = mCursorPos;
+ *length = 0;
+ }
}
void LLTextEditor::getPreeditRange(S32 *position, S32 *length) const
{
- if (hasPreeditString())
- {
- *position = mPreeditPositions.front();
- *length = mPreeditPositions.back() - mPreeditPositions.front();
- }
- else
- {
- *position = mCursorPos;
- *length = 0;
- }
+ if (hasPreeditString())
+ {
+ *position = mPreeditPositions.front();
+ *length = mPreeditPositions.back() - mPreeditPositions.front();
+ }
+ else
+ {
+ *position = mCursorPos;
+ *length = 0;
+ }
}
void LLTextEditor::markAsPreedit(S32 position, S32 length)
{
- deselect();
- setCursorPos(position);
- if (hasPreeditString())
- {
- LL_WARNS() << "markAsPreedit invoked when hasPreeditString is true." << LL_ENDL;
- }
- mPreeditWString = LLWString( getWText(), position, length );
- if (length > 0)
- {
- mPreeditPositions.resize(2);
- mPreeditPositions[0] = position;
- mPreeditPositions[1] = position + length;
- mPreeditStandouts.resize(1);
- mPreeditStandouts[0] = FALSE;
- }
- else
- {
- mPreeditPositions.clear();
- mPreeditStandouts.clear();
- }
- if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
- {
- mPreeditOverwrittenWString = mPreeditWString;
- }
- else
- {
- mPreeditOverwrittenWString.clear();
- }
+ deselect();
+ setCursorPos(position);
+ if (hasPreeditString())
+ {
+ LL_WARNS() << "markAsPreedit invoked when hasPreeditString is true." << LL_ENDL;
+ }
+ mPreeditWString = LLWString( getWText(), position, length );
+ if (length > 0)
+ {
+ mPreeditPositions.resize(2);
+ mPreeditPositions[0] = position;
+ mPreeditPositions[1] = position + length;
+ mPreeditStandouts.resize(1);
+ mPreeditStandouts[0] = FALSE;
+ }
+ else
+ {
+ mPreeditPositions.clear();
+ mPreeditStandouts.clear();
+ }
+ if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
+ {
+ mPreeditOverwrittenWString = mPreeditWString;
+ }
+ else
+ {
+ mPreeditOverwrittenWString.clear();
+ }
}
S32 LLTextEditor::getPreeditFontSize() const
{
- return ll_round((F32)mFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]);
+ return ll_round((F32)mFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]);
}
BOOL LLTextEditor::isDirty() const
{
- if(mReadOnly)
- {
- return FALSE;
- }
+ if(mReadOnly)
+ {
+ return FALSE;
+ }
- if( mPristineCmd )
- {
- return ( mPristineCmd == mLastCmd );
- }
- else
- {
- return ( NULL != mLastCmd );
- }
+ if( mPristineCmd )
+ {
+ return ( mPristineCmd == mLastCmd );
+ }
+ else
+ {
+ return ( NULL != mLastCmd );
+ }
}
void LLTextEditor::setKeystrokeCallback(const keystroke_signal_t::slot_type& callback)
{
- mKeystrokeSignal.connect(callback);
+ mKeystrokeSignal.connect(callback);
}
void LLTextEditor::onKeyStroke()
{
- mKeystrokeSignal(this);
+ mKeystrokeSignal(this);
- mSpellCheckStart = mSpellCheckEnd = -1;
- mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY);
+ mSpellCheckStart = mSpellCheckEnd = -1;
+ mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY);
}
//virtual
void LLTextEditor::clear()
{
- getViewModel()->setDisplay(LLWStringUtil::null);
- clearSegments();
+ getViewModel()->setDisplay(LLWStringUtil::null);
+ clearSegments();
}
bool LLTextEditor::canLoadOrSaveToFile()
{
- return !mReadOnly;
+ return !mReadOnly;
}
S32 LLTextEditor::spacesPerTab()
{
- return SPACES_PER_TAB;
+ return SPACES_PER_TAB;
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index e965848ce1..658bfb9295 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -34,6 +34,7 @@
#include "llstyle.h"
#include "lleditmenuhandler.h"
#include "llviewborder.h" // for params
+#include "llstring.h"
#include "lltextbase.h"
#include "lltextvalidate.h"
@@ -47,305 +48,316 @@ class LLUICtrlFactory;
class LLScrollContainer;
class LLTextEditor :
- public LLTextBase,
- protected LLPreeditor
+ public LLTextBase,
+ protected LLPreeditor
{
public:
- struct Params : public LLInitParam::Block<Params, LLTextBase::Params>
- {
- Optional<std::string> default_text;
- Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
-
- Optional<bool> embedded_items,
- ignore_tab,
- commit_on_focus_lost,
- show_context_menu,
- show_emoji_helper,
- enable_tooltip_paste,
- auto_indent;
-
- //colors
- Optional<LLUIColor> default_color;
-
- Params();
- };
-
- void initFromParams(const Params&);
+ struct Params : public LLInitParam::Block<Params, LLTextBase::Params>
+ {
+ Optional<std::string> default_text;
+ Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
+
+ Optional<bool> embedded_items,
+ ignore_tab,
+ commit_on_focus_lost,
+ show_context_menu,
+ show_emoji_helper,
+ enable_tooltip_paste,
+ auto_indent;
+
+ //colors
+ Optional<LLUIColor> default_color;
+
+ Params();
+ };
+
+ void initFromParams(const Params&);
protected:
- LLTextEditor(const Params&);
- friend class LLUICtrlFactory;
+ LLTextEditor(const Params&);
+ friend class LLUICtrlFactory;
public:
- //
- // Constants
- //
- static const llwchar FIRST_EMBEDDED_CHAR = 0x100000;
- static const llwchar LAST_EMBEDDED_CHAR = 0x10ffff;
- static const S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR - FIRST_EMBEDDED_CHAR + 1;
+ //
+ // Constants
+ //
+ static const llwchar FIRST_EMBEDDED_CHAR = 0x100000;
+ static const llwchar LAST_EMBEDDED_CHAR = 0x10ffff;
+ static const S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR - FIRST_EMBEDDED_CHAR + 1;
- virtual ~LLTextEditor();
+ virtual ~LLTextEditor();
- typedef boost::signals2::signal<void (LLTextEditor* caller)> keystroke_signal_t;
+ typedef boost::signals2::signal<void (LLTextEditor* caller)> keystroke_signal_t;
- void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback);
+ void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback);
- void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;}
+ void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;}
- static S32 spacesPerTab();
+ static S32 spacesPerTab();
- void insertEmoji(llwchar emoji);
- void handleEmojiCommit(llwchar emoji);
+ void insertEmoji(llwchar emoji);
+ void handleEmojiCommit(llwchar emoji);
- // mousehandler overrides
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask );
- virtual BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask);
+ // mousehandler overrides
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask );
+ virtual BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask);
- virtual BOOL handleKeyHere(KEY key, MASK mask );
- virtual BOOL handleUnicodeCharHere(llwchar uni_char);
+ virtual BOOL handleKeyHere(KEY key, MASK mask );
+ virtual BOOL handleUnicodeCharHere(llwchar uni_char);
- virtual void onMouseCaptureLost();
+ virtual void onMouseCaptureLost();
- // view overrides
- virtual void draw();
- virtual void onFocusReceived();
- virtual void onFocusLost();
- virtual void onCommit();
- virtual void setEnabled(BOOL enabled);
+ // view overrides
+ virtual void draw();
+ virtual void onFocusReceived();
+ virtual void onFocusLost();
+ virtual void onCommit();
+ virtual void setEnabled(BOOL enabled);
- // uictrl overrides
- virtual void clear();
- virtual void setFocus( BOOL b );
- virtual BOOL isDirty() const;
+ // uictrl overrides
+ virtual void clear();
+ virtual void setFocus( BOOL b );
+ virtual BOOL isDirty() const;
- // LLEditMenuHandler interface
- virtual void undo();
- virtual BOOL canUndo() const;
- virtual void redo();
- virtual BOOL canRedo() const;
+ // LLEditMenuHandler interface
+ virtual void undo();
+ virtual BOOL canUndo() const;
+ virtual void redo();
+ virtual BOOL canRedo() const;
- virtual void cut();
- virtual BOOL canCut() const;
- virtual void copy();
- virtual BOOL canCopy() const;
- virtual void paste();
- virtual BOOL canPaste() const;
+ virtual void cut();
+ virtual BOOL canCut() const;
+ virtual void copy();
+ virtual BOOL canCopy() const;
+ virtual void paste();
+ virtual BOOL canPaste() const;
- virtual void updatePrimary();
- virtual void copyPrimary();
- virtual void pastePrimary();
- virtual BOOL canPastePrimary() const;
+ virtual void updatePrimary();
+ virtual void copyPrimary();
+ virtual void pastePrimary();
+ virtual BOOL canPastePrimary() const;
- virtual void doDelete();
- virtual BOOL canDoDelete() const;
- virtual void selectAll();
- virtual BOOL canSelectAll() const;
+ virtual void doDelete();
+ virtual BOOL canDoDelete() const;
+ virtual void selectAll();
+ virtual BOOL canSelectAll() const;
- void selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos);
+ void selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos);
- virtual bool canLoadOrSaveToFile();
+ virtual bool canLoadOrSaveToFile();
- void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE);
- BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
- void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive);
+ void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE);
+ BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
+ void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive);
- // Undo/redo stack
- void blockUndo();
+ // Undo/redo stack
+ void blockUndo();
- // Text editing
- virtual void makePristine();
- BOOL isPristine() const;
- BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; }
+ // Text editing
+ virtual void makePristine();
+ BOOL isPristine() const;
+ BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; }
- // Autoreplace (formerly part of LLLineEditor)
- typedef boost::function<void(S32&, S32&, LLWString&, S32&, const LLWString&)> autoreplace_callback_t;
- autoreplace_callback_t mAutoreplaceCallback;
- void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; }
+ // Autoreplace (formerly part of LLLineEditor)
+ typedef boost::function<void(S32&, S32&, LLWString&, S32&, const LLWString&)> autoreplace_callback_t;
+ autoreplace_callback_t mAutoreplaceCallback;
+ void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; }
- /*virtual*/ void onSpellCheckPerformed();
+ /*virtual*/ void onSpellCheckPerformed();
- //
- // Text manipulation
- //
+ //
+ // Text manipulation
+ //
- // inserts text at cursor
- void insertText(const std::string &text);
- void insertText(LLWString &text);
+ // inserts text at cursor
+ void insertText(const std::string &text);
+ void insertText(LLWString &text);
- void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
- // Non-undoable
- void setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params = LLStyle::Params());
+ void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
+ // Non-undoable
+ void setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params = LLStyle::Params());
- // Removes text from the end of document
- // Does not change highlight or cursor position.
- void removeTextFromEnd(S32 num_chars);
+ // Removes text from the end of document
+ // Does not change highlight or cursor position.
+ void removeTextFromEnd(S32 num_chars);
- BOOL tryToRevertToPristineState();
+ BOOL tryToRevertToPristineState();
- void setCursorAndScrollToEnd();
+ void setCursorAndScrollToEnd();
- void getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap );
+ void getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap );
- // Hacky methods to make it into a word-wrapping, potentially scrolling,
- // read-only text box.
- void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; }
+ // Hacky methods to make it into a word-wrapping, potentially scrolling,
+ // read-only text box.
+ void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; }
- // Hack to handle Notecards
- virtual BOOL importBuffer(const char* buffer, S32 length );
- virtual BOOL exportBuffer(std::string& buffer );
+ // Hack to handle Notecards
+ virtual BOOL importBuffer(const char* buffer, S32 length );
+ virtual BOOL exportBuffer(std::string& buffer );
- const LLUUID& getSourceID() const { return mSourceID; }
+ const LLUUID& getSourceID() const { return mSourceID; }
- const LLTextSegmentPtr getPreviousSegment() const;
- const LLTextSegmentPtr getLastSegment() const;
- void getSelectedSegments(segment_vec_t& segments) const;
+ const LLTextSegmentPtr getPreviousSegment() const;
+ const LLTextSegmentPtr getLastSegment() const;
+ void getSelectedSegments(segment_vec_t& segments) const;
- void setShowContextMenu(bool show) { mShowContextMenu = show; }
- bool getShowContextMenu() const { return mShowContextMenu; }
+ void setShowContextMenu(bool show) { mShowContextMenu = show; }
+ bool getShowContextMenu() const { return mShowContextMenu; }
- void showEmojiHelper();
- void setShowEmojiHelper(bool show);
- bool getShowEmojiHelper() const { return mShowEmojiHelper; }
+ void showEmojiHelper();
+ void setShowEmojiHelper(bool show);
+ bool getShowEmojiHelper() const { return mShowEmojiHelper; }
- void setPassDelete(BOOL b) { mPassDelete = b; }
+ void setPassDelete(BOOL b) { mPassDelete = b; }
protected:
- void showContextMenu(S32 x, S32 y);
- void drawPreeditMarker();
-
- void assignEmbedded(const std::string &s);
-
- void removeCharOrTab();
-
- void indentSelectedLines( S32 spaces );
- S32 indentLine( S32 pos, S32 spaces );
- void unindentLineBeforeCloseBrace();
-
- virtual BOOL handleSpecialKey(const KEY key, const MASK mask);
- BOOL handleNavigationKey(const KEY key, const MASK mask);
- BOOL handleSelectionKey(const KEY key, const MASK mask);
- BOOL handleControlKey(const KEY key, const MASK mask);
-
- BOOL selectionContainsLineBreaks();
- void deleteSelection(BOOL transient_operation);
-
- S32 prevWordPos(S32 cursorPos) const;
- S32 nextWordPos(S32 cursorPos) const;
-
- void autoIndent();
-
- void findEmbeddedItemSegments(S32 start, S32 end);
- void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const;
-
- virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; }
-
-
- // Here's the method that takes and applies text commands.
- S32 execute(TextCmd* cmd);
-
- // Undoable operations
- void addChar(llwchar c); // at mCursorPos
- S32 addChar(S32 pos, llwchar wc);
- void addLineBreakChar(BOOL group_together = FALSE);
- S32 overwriteChar(S32 pos, llwchar wc);
- void removeChar();
- S32 removeChar(S32 pos);
- S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);
- S32 remove(S32 pos, S32 length, bool group_with_next_op);
-
- void tryToShowEmojiHelper();
- void focusLostHelper();
- void updateAllowingLanguageInput();
- BOOL hasPreeditString() const;
-
- // Overrides LLPreeditor
- virtual void resetPreedit();
- virtual void updatePreedit(const LLWString &preedit_string,
- const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position);
- virtual void markAsPreedit(S32 position, S32 length);
- virtual void getPreeditRange(S32 *position, S32 *length) const;
- virtual void getSelectionRange(S32 *position, S32 *length) const;
- virtual BOOL getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
- virtual S32 getPreeditFontSize() const;
- virtual LLWString getPreeditString() const { return getWText(); }
- //
- // Protected data
- //
- // Probably deserves serious thought to hiding as many of these
- // as possible behind protected accessor methods.
- //
-
- // Use these to determine if a click on an embedded item is a drag or not.
- S32 mMouseDownX;
- S32 mMouseDownY;
-
- LLWString mPreeditWString;
- LLWString mPreeditOverwrittenWString;
- std::vector<S32> mPreeditPositions;
- std::vector<BOOL> mPreeditStandouts;
+ void showContextMenu(S32 x, S32 y);
+ void drawPreeditMarker();
+
+ void assignEmbedded(const std::string &s);
+
+ void removeCharOrTab();
+
+ void indentSelectedLines( S32 spaces );
+ S32 indentLine( S32 pos, S32 spaces );
+ void unindentLineBeforeCloseBrace();
+
+ virtual BOOL handleSpecialKey(const KEY key, const MASK mask);
+ BOOL handleNavigationKey(const KEY key, const MASK mask);
+ BOOL handleSelectionKey(const KEY key, const MASK mask);
+ BOOL handleControlKey(const KEY key, const MASK mask);
+
+ BOOL selectionContainsLineBreaks();
+ void deleteSelection(BOOL transient_operation);
+
+ S32 prevWordPos(S32 cursorPos) const;
+ S32 nextWordPos(S32 cursorPos) const;
+
+ void autoIndent();
+
+ void findEmbeddedItemSegments(S32 start, S32 end);
+ void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const;
+
+ virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; }
+
+
+ // Here's the method that takes and applies text commands.
+ S32 execute(TextCmd* cmd);
+
+ // Undoable operations
+ void addChar(llwchar c); // at mCursorPos
+ S32 addChar(S32 pos, llwchar wc);
+public:
+ void addLineBreakChar(BOOL group_together = FALSE);
+protected:
+ S32 overwriteChar(S32 pos, llwchar wc);
+ void removeChar();
+ S32 removeChar(S32 pos);
+ S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);
+ S32 remove(S32 pos, S32 length, bool group_with_next_op);
+
+ void tryToShowEmojiHelper();
+ void focusLostHelper();
+ void updateAllowingLanguageInput();
+ BOOL hasPreeditString() const;
+
+ // Overrides LLPreeditor
+ virtual void resetPreedit();
+ virtual void updatePreedit(const LLWString &preedit_string,
+ const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position);
+ virtual void markAsPreedit(S32 position, S32 length);
+ virtual void getPreeditRange(S32 *position, S32 *length) const;
+ virtual void getSelectionRange(S32 *position, S32 *length) const;
+ virtual BOOL getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
+ virtual S32 getPreeditFontSize() const;
+ virtual LLWString getPreeditString() const { return getWText(); }
+ //
+ // Protected data
+ //
+ // Probably deserves serious thought to hiding as many of these
+ // as possible behind protected accessor methods.
+ //
+
+ // Use these to determine if a click on an embedded item is a drag or not.
+ S32 mMouseDownX;
+ S32 mMouseDownY;
+
+ LLWString mPreeditWString;
+ LLWString mPreeditOverwrittenWString;
+ std::vector<S32> mPreeditPositions;
+ std::vector<BOOL> mPreeditStandouts;
protected:
- LLUIColor mDefaultColor;
+ LLUIColor mDefaultColor;
- bool mAutoIndent;
- bool mParseOnTheFly;
+ bool mAutoIndent;
+ bool mParseOnTheFly;
- void updateLinkSegments();
- void keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; }
- class LLViewBorder* mBorder;
+ void updateLinkSegments();
+ void keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; }
+ class LLViewBorder* mBorder;
private:
- //
- // Methods
- //
- void pasteHelper(bool is_primary);
- void cleanStringForPaste(LLWString & clean_string);
- void pasteTextWithLinebreaks(LLWString & clean_string);
+ //
+ // Methods
+ //
+ void pasteHelper(bool is_primary);
+ void cleanStringForPaste(LLWString & clean_string);
+
+public:
+ template <typename STRINGTYPE>
+ void pasteTextWithLinebreaks(const STRINGTYPE& clean_string)
+ {
+ pasteTextWithLinebreaks<LLWString>(ll_convert(clean_string));
+ }
+ template <>
+ void pasteTextWithLinebreaks<LLWString>(const LLWString & clean_string);
- void onKeyStroke();
+private:
+ void onKeyStroke();
- // Concrete TextCmd sub-classes used by the LLTextEditor base class
- class TextCmdInsert;
- class TextCmdAddChar;
- class TextCmdOverwriteChar;
- class TextCmdRemove;
+ // Concrete TextCmd sub-classes used by the LLTextEditor base class
+ class TextCmdInsert;
+ class TextCmdAddChar;
+ class TextCmdOverwriteChar;
+ class TextCmdRemove;
- BOOL mBaseDocIsPristine;
- TextCmd* mPristineCmd;
+ BOOL mBaseDocIsPristine;
+ TextCmd* mPristineCmd;
- TextCmd* mLastCmd;
+ TextCmd* mLastCmd;
- typedef std::deque<TextCmd*> undo_stack_t;
- undo_stack_t mUndoStack;
+ typedef std::deque<TextCmd*> undo_stack_t;
+ undo_stack_t mUndoStack;
- BOOL mTabsToNextField; // if true, tab moves focus to next field, else inserts spaces
- BOOL mCommitOnFocusLost;
- BOOL mTakesFocus;
+ BOOL mTabsToNextField; // if true, tab moves focus to next field, else inserts spaces
+ BOOL mCommitOnFocusLost;
+ BOOL mTakesFocus;
- BOOL mAllowEmbeddedItems;
- bool mShowContextMenu;
- bool mShowEmojiHelper;
- bool mEnableTooltipPaste;
- bool mPassDelete;
- bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter
+ BOOL mAllowEmbeddedItems;
+ bool mShowContextMenu;
+ bool mShowEmojiHelper;
+ bool mEnableTooltipPaste;
+ bool mPassDelete;
+ bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter
- LLUUID mSourceID;
+ LLUUID mSourceID;
- LLCoordGL mLastIMEPosition; // Last position of the IME editor
+ LLCoordGL mLastIMEPosition; // Last position of the IME editor
- keystroke_signal_t mKeystrokeSignal;
- LLTextValidate::validate_func_t mPrevalidateFunc;
+ keystroke_signal_t mKeystrokeSignal;
+ LLTextValidate::validate_func_t mPrevalidateFunc;
- LLHandle<LLContextMenu> mContextMenuHandle;
+ LLHandle<LLContextMenu> mContextMenuHandle;
}; // end class LLTextEditor
// Build time optimization, generate once in .cpp file
#ifndef LLTEXTEDITOR_CPP
extern template class LLTextEditor* LLView::getChild<class LLTextEditor>(
- const std::string& name, BOOL recurse) const;
+ const std::string& name, BOOL recurse) const;
#endif
#endif // LL_TEXTEDITOR_H
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 8ccda101c1..9e9e424455 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llwindow.h
* @brief Basic graphical window class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -44,40 +44,40 @@ class LLWindow : public LLInstanceTracker<LLWindow>
{
public:
- struct LLWindowResolution
- {
- S32 mWidth;
- S32 mHeight;
- };
- enum ESwapMethod
- {
- SWAP_METHOD_UNDEFINED,
- SWAP_METHOD_EXCHANGE,
- SWAP_METHOD_COPY
- };
- enum EFlags
- {
- // currently unused
- };
+ struct LLWindowResolution
+ {
+ S32 mWidth;
+ S32 mHeight;
+ };
+ enum ESwapMethod
+ {
+ SWAP_METHOD_UNDEFINED,
+ SWAP_METHOD_EXCHANGE,
+ SWAP_METHOD_COPY
+ };
+ enum EFlags
+ {
+ // currently unused
+ };
public:
- virtual void show() = 0;
- virtual void hide() = 0;
- virtual void close() = 0;
- virtual BOOL getVisible() = 0;
- virtual BOOL getMinimized() = 0;
- virtual BOOL getMaximized() = 0;
- virtual BOOL maximize() = 0;
- virtual void minimize() = 0;
- virtual void restore() = 0;
- BOOL getFullscreen() { return mFullscreen; };
- virtual BOOL getPosition(LLCoordScreen *position) = 0;
- virtual BOOL getSize(LLCoordScreen *size) = 0;
- virtual BOOL getSize(LLCoordWindow *size) = 0;
- virtual BOOL setPosition(LLCoordScreen position) = 0;
- BOOL setSize(LLCoordScreen size);
- BOOL setSize(LLCoordWindow size);
- virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
- virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) = 0;
+ virtual void show() = 0;
+ virtual void hide() = 0;
+ virtual void close() = 0;
+ virtual BOOL getVisible() = 0;
+ virtual BOOL getMinimized() = 0;
+ virtual BOOL getMaximized() = 0;
+ virtual BOOL maximize() = 0;
+ virtual void minimize() = 0;
+ virtual void restore() = 0;
+ BOOL getFullscreen() { return mFullscreen; };
+ virtual BOOL getPosition(LLCoordScreen *position) = 0;
+ virtual BOOL getSize(LLCoordScreen *size) = 0;
+ virtual BOOL getSize(LLCoordWindow *size) = 0;
+ virtual BOOL setPosition(LLCoordScreen position) = 0;
+ BOOL setSize(LLCoordScreen size);
+ BOOL setSize(LLCoordWindow size);
+ virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
+ virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) = 0;
//create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread
// returns a pointer to be handed back to destroySharedConext/makeContextCurrent
@@ -91,111 +91,113 @@ public:
virtual void toggleVSync(bool enable_vsync) = 0;
virtual BOOL setCursorPosition(LLCoordWindow position) = 0;
- virtual BOOL getCursorPosition(LLCoordWindow *position) = 0;
+ virtual BOOL getCursorPosition(LLCoordWindow *position) = 0;
#if LL_WINDOWS
virtual BOOL getCursorDelta(LLCoordCommon* delta) = 0;
#endif
- virtual void showCursor() = 0;
- virtual void hideCursor() = 0;
- virtual BOOL isCursorHidden() = 0;
- virtual void showCursorFromMouseMove() = 0;
- virtual void hideCursorUntilMouseMove() = 0;
+ virtual void showCursor() = 0;
+ virtual void hideCursor() = 0;
+ virtual BOOL isCursorHidden() = 0;
+ virtual void showCursorFromMouseMove() = 0;
+ virtual void hideCursorUntilMouseMove() = 0;
// Provide a way to set the Viewer window title after the
// windows has been created. The initial use case for this
- // is described in SL-16102 (update window title with agent
+ // is described in SL-16102 (update window title with agent
// name, location etc. for non-interactive viewer) but it
// may also be useful in other cases.
virtual void setTitle(const std::string title);
- // These two functions create a way to make a busy cursor instead
- // of an arrow when someone's busy doing something. Draw an
- // arrow/hour if busycount > 0.
- virtual void incBusyCount();
- virtual void decBusyCount();
- virtual void resetBusyCount();
- virtual S32 getBusyCount() const;
+ // These two functions create a way to make a busy cursor instead
+ // of an arrow when someone's busy doing something. Draw an
+ // arrow/hour if busycount > 0.
+ virtual void incBusyCount();
+ virtual void decBusyCount();
+ virtual void resetBusyCount();
+ virtual S32 getBusyCount() const;
- // Sets cursor, may set to arrow+hourglass
- virtual void setCursor(ECursorType cursor) { mNextCursor = cursor; };
+ // Sets cursor, may set to arrow+hourglass
+ virtual void setCursor(ECursorType cursor) { mNextCursor = cursor; };
virtual ECursorType getCursor() const;
virtual ECursorType getNextCursor() const { return mNextCursor; };
- virtual void updateCursor() = 0;
-
- virtual void captureMouse() = 0;
- virtual void releaseMouse() = 0;
- virtual void setMouseClipping( BOOL b ) = 0;
-
- virtual BOOL isClipboardTextAvailable() = 0;
- virtual BOOL pasteTextFromClipboard(LLWString &dst) = 0;
- virtual BOOL copyTextToClipboard(const LLWString &src) = 0;
-
- virtual BOOL isPrimaryTextAvailable();
- virtual BOOL pasteTextFromPrimary(LLWString &dst);
- virtual BOOL copyTextToPrimary(const LLWString &src);
-
- virtual void flashIcon(F32 seconds) = 0;
- virtual F32 getGamma() = 0;
- virtual BOOL setGamma(const F32 gamma) = 0; // Set the gamma
- virtual void setFSAASamples(const U32 fsaa_samples) = 0; //set number of FSAA samples
- virtual U32 getFSAASamples() = 0;
- virtual BOOL restoreGamma() = 0; // Restore original gamma table (before updating gamma)
- virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
- virtual void processMiscNativeEvents();
- virtual void gatherInput() = 0;
- virtual void delayInputProcessing() = 0;
- virtual void swapBuffers() = 0;
- virtual void bringToFront() = 0;
- virtual void focusClient() { }; // this may not have meaning or be required on other platforms, therefore, it's not abstract
- virtual void setOldResize(bool oldresize) { };
- // handy coordinate space conversion routines
- // NB: screen to window and vice verse won't work on width/height coordinate pairs,
- // as the conversion must take into account left AND right border widths, etc.
- virtual BOOL convertCoords( LLCoordScreen from, LLCoordWindow *to) = 0;
- virtual BOOL convertCoords( LLCoordWindow from, LLCoordScreen *to) = 0;
- virtual BOOL convertCoords( LLCoordWindow from, LLCoordGL *to) = 0;
- virtual BOOL convertCoords( LLCoordGL from, LLCoordWindow *to) = 0;
- virtual BOOL convertCoords( LLCoordScreen from, LLCoordGL *to) = 0;
- virtual BOOL convertCoords( LLCoordGL from, LLCoordScreen *to) = 0;
-
- // query supported resolutions
- virtual LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) = 0;
- virtual F32 getNativeAspectRatio() = 0;
- virtual F32 getPixelAspectRatio() = 0;
- virtual void setNativeAspectRatio(F32 aspect) = 0;
-
- // query VRAM usage
- virtual U32 getAvailableVRAMMegabytes() = 0;
-
- virtual void beforeDialog() {}; // prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode)
- virtual void afterDialog() {}; // undo whatever was done in beforeDialog()
-
- // opens system default color picker, modally
- // Returns TRUE if valid color selected
- virtual BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
+ virtual void updateCursor() = 0;
+
+ virtual void captureMouse() = 0;
+ virtual void releaseMouse() = 0;
+ virtual void setMouseClipping( BOOL b ) = 0;
+
+ virtual BOOL isClipboardTextAvailable() = 0;
+ virtual BOOL pasteTextFromClipboard(LLWString &dst) = 0;
+ virtual BOOL copyTextToClipboard(const LLWString &src) = 0;
+
+ virtual BOOL isPrimaryTextAvailable();
+ virtual BOOL pasteTextFromPrimary(LLWString &dst);
+ virtual BOOL copyTextToPrimary(const LLWString &src);
+
+ virtual void flashIcon(F32 seconds) = 0;
+ virtual F32 getGamma() = 0;
+ virtual BOOL setGamma(const F32 gamma) = 0; // Set the gamma
+ virtual void setFSAASamples(const U32 fsaa_samples) = 0; //set number of FSAA samples
+ virtual U32 getFSAASamples() = 0;
+ virtual BOOL restoreGamma() = 0; // Restore original gamma table (before updating gamma)
+ virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
+ virtual void processMiscNativeEvents();
+ virtual void gatherInput() = 0;
+ virtual void delayInputProcessing() = 0;
+ virtual void swapBuffers() = 0;
+ virtual void bringToFront() = 0;
+ virtual void focusClient() { }; // this may not have meaning or be required on other platforms, therefore, it's not abstract
+ virtual void setOldResize(bool oldresize) { };
+ // handy coordinate space conversion routines
+ // NB: screen to window and vice verse won't work on width/height coordinate pairs,
+ // as the conversion must take into account left AND right border widths, etc.
+ virtual BOOL convertCoords( LLCoordScreen from, LLCoordWindow *to) = 0;
+ virtual BOOL convertCoords( LLCoordWindow from, LLCoordScreen *to) = 0;
+ virtual BOOL convertCoords( LLCoordWindow from, LLCoordGL *to) = 0;
+ virtual BOOL convertCoords( LLCoordGL from, LLCoordWindow *to) = 0;
+ virtual BOOL convertCoords( LLCoordScreen from, LLCoordGL *to) = 0;
+ virtual BOOL convertCoords( LLCoordGL from, LLCoordScreen *to) = 0;
+
+ // query supported resolutions
+ virtual LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) = 0;
+ virtual F32 getNativeAspectRatio() = 0;
+ virtual F32 getPixelAspectRatio() = 0;
+ virtual void setNativeAspectRatio(F32 aspect) = 0;
+
+ // query VRAM usage
+ virtual U32 getAvailableVRAMMegabytes() = 0;
+
+ virtual void beforeDialog() {}; // prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode)
+ virtual void afterDialog() {}; // undo whatever was done in beforeDialog()
+
+ // opens system default color picker, modally
+ // Returns TRUE if valid color selected
+ virtual BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
// return a platform-specific window reference (HWND on Windows, WindowRef on the Mac, Gtk window on Linux)
- virtual void *getPlatformWindow() = 0;
+ virtual void *getPlatformWindow() = 0;
// return the platform-specific window reference we use to initialize llmozlib (HWND on Windows, WindowRef on the Mac, Gtk window on Linux)
- virtual void *getMediaWindow();
-
- // control platform's Language Text Input mechanisms.
- virtual void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) {}
- virtual void setLanguageTextInput( const LLCoordGL & pos ) {};
- virtual void updateLanguageTextInputArea() {}
- virtual void interruptLanguageTextInput() {}
- virtual void spawnWebBrowser(const std::string& escaped_url, bool async) {};
+ virtual void *getMediaWindow();
+
+ // control platform's Language Text Input mechanisms.
+ virtual void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) {}
+ virtual void setLanguageTextInput( const LLCoordGL & pos ) {};
+ virtual void updateLanguageTextInputArea() {}
+ virtual void interruptLanguageTextInput() {}
+ virtual void spawnWebBrowser(const std::string& escaped_url, bool async) {};
- static std::vector<std::string> getDynamicFallbackFontList();
+ virtual void openFolder(const std::string &path) {};
- // Provide native key event data
- virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); }
+ static std::vector<std::string> getDynamicFallbackFontList();
+
+ // Provide native key event data
+ virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); }
- // Get system UI size based on DPI (for 96 DPI UI size should be 1.0)
- virtual F32 getSystemUISize() { return 1.0; }
+ // Get system UI size based on DPI (for 96 DPI UI size should be 1.0)
+ virtual F32 getSystemUISize() { return 1.0; }
- static std::vector<std::string> getDisplaysResolutionList();
+ static std::vector<std::string> getDisplaysResolutionList();
// windows only DirectInput8 for joysticks
virtual void* getDirectInput8() { return NULL; };
@@ -203,49 +205,49 @@ public:
virtual S32 getRefreshRate() { return mRefreshRate; }
protected:
- LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags);
- virtual ~LLWindow();
- // Defaults to true
- virtual BOOL isValid();
- // Defaults to true
- virtual BOOL canDelete();
+ LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags);
+ virtual ~LLWindow();
+ // Defaults to true
+ virtual BOOL isValid();
+ // Defaults to true
+ virtual BOOL canDelete();
- virtual BOOL setSizeImpl(LLCoordScreen size) = 0;
- virtual BOOL setSizeImpl(LLCoordWindow size) = 0;
+ virtual BOOL setSizeImpl(LLCoordScreen size) = 0;
+ virtual BOOL setSizeImpl(LLCoordWindow size) = 0;
protected:
- LLWindowCallbacks* mCallbacks;
-
- BOOL mPostQuit; // should this window post a quit message when destroyed?
- BOOL mFullscreen;
- S32 mFullscreenWidth;
- S32 mFullscreenHeight;
- S32 mFullscreenBits;
- S32 mFullscreenRefresh;
- LLWindowResolution* mSupportedResolutions;
- S32 mNumSupportedResolutions;
- ECursorType mCurrentCursor;
- ECursorType mNextCursor;
- BOOL mCursorHidden;
- S32 mBusyCount; // how deep is the "cursor busy" stack?
- BOOL mIsMouseClipping; // Is this window currently clipping the mouse
- ESwapMethod mSwapMethod;
- BOOL mHideCursorPermanent;
- U32 mFlags;
- U16 mHighSurrogate;
- S32 mMinWindowWidth;
- S32 mMinWindowHeight;
+ LLWindowCallbacks* mCallbacks;
+
+ BOOL mPostQuit; // should this window post a quit message when destroyed?
+ BOOL mFullscreen;
+ S32 mFullscreenWidth;
+ S32 mFullscreenHeight;
+ S32 mFullscreenBits;
+ S32 mFullscreenRefresh;
+ LLWindowResolution* mSupportedResolutions;
+ S32 mNumSupportedResolutions;
+ ECursorType mCurrentCursor;
+ ECursorType mNextCursor;
+ BOOL mCursorHidden;
+ S32 mBusyCount; // how deep is the "cursor busy" stack?
+ BOOL mIsMouseClipping; // Is this window currently clipping the mouse
+ ESwapMethod mSwapMethod;
+ BOOL mHideCursorPermanent;
+ U32 mFlags;
+ U16 mHighSurrogate;
+ S32 mMinWindowWidth;
+ S32 mMinWindowHeight;
S32 mRefreshRate;
- // Handle a UTF-16 encoding unit received from keyboard.
- // Converting the series of UTF-16 encoding units to UTF-32 data,
- // this method passes the resulting UTF-32 data to mCallback's
- // handleUnicodeChar. The mask should be that to be passed to the
- // callback. This method uses mHighSurrogate as a dedicated work
- // variable.
- void handleUnicodeUTF16(U16 utf16, MASK mask);
+ // Handle a UTF-16 encoding unit received from keyboard.
+ // Converting the series of UTF-16 encoding units to UTF-32 data,
+ // this method passes the resulting UTF-32 data to mCallback's
+ // handleUnicodeChar. The mask should be that to be passed to the
+ // callback. This method uses mHighSurrogate as a dedicated work
+ // variable.
+ void handleUnicodeUTF16(U16 utf16, MASK mask);
- friend class LLWindowManager;
+ friend class LLWindowManager;
};
@@ -258,24 +260,24 @@ protected:
class LLSplashScreen
{
public:
- LLSplashScreen() { };
- virtual ~LLSplashScreen() { };
+ LLSplashScreen() { };
+ virtual ~LLSplashScreen() { };
- // Call to display the window.
- static LLSplashScreen * create();
- static void show();
- static void hide();
- static void update(const std::string& string);
+ // Call to display the window.
+ static LLSplashScreen * create();
+ static void show();
+ static void hide();
+ static void update(const std::string& string);
- static bool isVisible();
+ static bool isVisible();
protected:
- // These are overridden by the platform implementation
- virtual void showImpl() = 0;
- virtual void updateImpl(const std::string& string) = 0;
- virtual void hideImpl() = 0;
+ // These are overridden by the platform implementation
+ virtual void showImpl() = 0;
+ virtual void updateImpl(const std::string& string) = 0;
+ virtual void hideImpl() = 0;
- static BOOL sVisible;
+ static BOOL sVisible;
};
@@ -297,21 +299,21 @@ const S32 OSBTN_CANCEL = 3;
class LLWindowManager
{
public:
- static LLWindow *createWindow(
- LLWindowCallbacks* callbacks,
- const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
- U32 flags = 0,
- BOOL fullscreen = FALSE,
- BOOL clearBg = FALSE,
- BOOL enable_vsync = FALSE,
- BOOL use_gl = TRUE,
- BOOL ignore_pixel_depth = FALSE,
- U32 fsaa_samples = 0,
+ static LLWindow *createWindow(
+ LLWindowCallbacks* callbacks,
+ const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
+ U32 flags = 0,
+ BOOL fullscreen = FALSE,
+ BOOL clearBg = FALSE,
+ BOOL enable_vsync = FALSE,
+ BOOL use_gl = TRUE,
+ BOOL ignore_pixel_depth = FALSE,
+ U32 fsaa_samples = 0,
U32 max_cores = 0,
U32 max_vram = 0,
F32 max_gl_version = 4.6f);
- static BOOL destroyWindow(LLWindow* window);
- static BOOL isWindowValid(LLWindow *window);
+ static BOOL destroyWindow(LLWindow* window);
+ static BOOL isWindowValid(LLWindow *window);
};
//
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index 31dc83493e..ade303c6d4 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llwindowmacosx-objc.h
* @brief Prototypes for functions shared between llwindowmacosx.cpp
* and llwindowmacosx-objc.mm.
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -40,8 +40,8 @@ typedef std::vector<int> segment_lengths;
typedef std::vector<int> segment_standouts;
struct attributedStringInfo {
- segment_lengths seg_lengths;
- segment_standouts seg_standouts;
+ segment_lengths seg_lengths;
+ segment_standouts seg_standouts;
};
// This will actually hold an NSCursor*, but that type is only available in objective C.
@@ -57,7 +57,7 @@ struct NativeKeyEventData {
KEYDOWN,
KEYCHAR
};
-
+
EventType mKeyEvent = KEYUNKNOWN;
uint32_t mEventType = 0;
uint32_t mEventModifiers = 0;
@@ -177,6 +177,8 @@ void setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned i
void getPreeditLocation(float *location, unsigned int length);
void allowDirectMarkedTextInput(bool allow, GLViewRef glView);
+void openFolderWithFinder(const char *folder_path);
+
NSWindowRef getMainAppWindow();
GLViewRef getGLView();
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index 690fe058db..56d1798dcf 100644
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -462,6 +462,13 @@ long showAlert(std::string text, std::string title, int type)
return ret;
}
+void openFolderWithFinder(const char *folder_path)
+{
+ @autoreleasepool {
+ NSString *folderPathString = [NSString stringWithUTF8String:folder_path];
+ [[NSWorkspace sharedWorkspace] openFile:folderPathString withApplication:@"Finder"];
+ }
+}
/*
GLViewRef getGLView()
{
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 34ec85bcf6..b774597eb6 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -46,8 +46,8 @@
extern BOOL gDebugWindowProc;
BOOL gHiDPISupport = TRUE;
-const S32 BITS_PER_PIXEL = 32;
-const S32 MAX_NUM_RESOLUTIONS = 32;
+const S32 BITS_PER_PIXEL = 32;
+const S32 MAX_NUM_RESOLUTIONS = 32;
const S32 DEFAULT_REFRESH_RATE = 60;
@@ -65,34 +65,34 @@ BOOL LLWindowMacOSX::sUseMultGL = FALSE;
BOOL check_for_card(const char* RENDERER, const char* bad_card)
{
- if (!strnicmp(RENDERER, bad_card, strlen(bad_card)))
- {
- std::string buffer = llformat(
- "Your video card appears to be a %s, which Second Life does not support.\n"
- "\n"
- "Second Life requires a video card with 32 Mb of memory or more, as well as\n"
- "multitexture support. We explicitly support nVidia GeForce 2 or better, \n"
- "and ATI Radeon 8500 or better.\n"
- "\n"
- "If you own a supported card and continue to receive this message, try \n"
- "updating to the latest video card drivers. Otherwise look in the\n"
- "secondlife.com support section or e-mail technical support\n"
- "\n"
- "You can try to run Second Life, but it will probably crash or run\n"
- "very slowly. Try anyway?",
- bad_card);
- S32 button = OSMessageBox(buffer.c_str(), "Unsupported video card", OSMB_YESNO);
- if (OSBTN_YES == button)
- {
- return FALSE;
- }
- else
- {
- return TRUE;
- }
- }
-
- return FALSE;
+ if (!strnicmp(RENDERER, bad_card, strlen(bad_card)))
+ {
+ std::string buffer = llformat(
+ "Your video card appears to be a %s, which Second Life does not support.\n"
+ "\n"
+ "Second Life requires a video card with 32 Mb of memory or more, as well as\n"
+ "multitexture support. We explicitly support nVidia GeForce 2 or better, \n"
+ "and ATI Radeon 8500 or better.\n"
+ "\n"
+ "If you own a supported card and continue to receive this message, try \n"
+ "updating to the latest video card drivers. Otherwise look in the\n"
+ "secondlife.com support section or e-mail technical support\n"
+ "\n"
+ "You can try to run Second Life, but it will probably crash or run\n"
+ "very slowly. Try anyway?",
+ bad_card);
+ S32 button = OSMessageBox(buffer.c_str(), "Unsupported video card", OSMB_YESNO);
+ if (OSBTN_YES == button)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
}
// Switch to determine whether we capture all displays, or just the main one.
@@ -110,93 +110,93 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key);
static LLWindowMacOSX *gWindowImplementation = NULL;
LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
- const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
- S32 height, U32 flags,
- BOOL fullscreen, BOOL clearBg,
- BOOL enable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth,
- U32 fsaa_samples)
- : LLWindow(NULL, fullscreen, flags)
-{
- // *HACK: During window construction we get lots of OS events for window
- // reshape, activate, etc. that the viewer isn't ready to handle.
- // Route them to a dummy callback structure until the end of constructor.
- LLWindowCallbacks null_callbacks;
- mCallbacks = &null_callbacks;
-
- // Voodoo for calling cocoa from carbon (see llwindowmacosx-objc.mm).
- setupCocoa();
-
- // Initialize the keyboard
- gKeyboard = new LLKeyboardMacOSX();
- gKeyboard->setCallbacks(callbacks);
-
- // Ignore use_gl for now, only used for drones on PC
- mWindow = NULL;
- mContext = NULL;
- mPixelFormat = NULL;
- mDisplay = CGMainDisplayID();
- mSimulatedRightClick = FALSE;
- mLastModifiers = 0;
- mHandsOffEvents = FALSE;
- mCursorDecoupled = FALSE;
- mCursorLastEventDeltaX = 0;
- mCursorLastEventDeltaY = 0;
- mCursorIgnoreNextDelta = FALSE;
- mNeedsResize = FALSE;
- mOverrideAspectRatio = 0.f;
- mMaximized = FALSE;
- mMinimized = FALSE;
- mLanguageTextInputAllowed = FALSE;
- mPreeditor = NULL;
- mFSAASamples = fsaa_samples;
- mForceRebuild = FALSE;
-
- // Get the original aspect ratio of the main device.
- mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay);
-
- // Stash the window title
- mWindowTitle = title;
- //mWindowTitle[0] = title.length();
-
- mDragOverrideCursor = -1;
-
- // Set up global event handlers (the fullscreen case needs this)
- //InstallStandardEventHandler(GetApplicationEventTarget());
-
- // Stash an object pointer for OSMessageBox()
- gWindowImplementation = this;
- // Create the GL context and set it up for windowed or fullscreen, as appropriate.
- if(createContext(x, y, width, height, 32, fullscreen, enable_vsync))
- {
- if(mWindow != NULL)
- {
- makeWindowOrderFront(mWindow);
- }
-
- if (!gGLManager.initGL())
- {
- setupFailure(
- "Second Life is unable to run because your video card drivers\n"
- "are out of date or unsupported. Please make sure you have\n"
- "the latest video card drivers installed.\n"
- "If you continue to receive this message, contact customer service.",
- "Error",
- OSMB_OK);
- return;
- }
+ const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
+ S32 height, U32 flags,
+ BOOL fullscreen, BOOL clearBg,
+ BOOL enable_vsync, BOOL use_gl,
+ BOOL ignore_pixel_depth,
+ U32 fsaa_samples)
+ : LLWindow(NULL, fullscreen, flags)
+{
+ // *HACK: During window construction we get lots of OS events for window
+ // reshape, activate, etc. that the viewer isn't ready to handle.
+ // Route them to a dummy callback structure until the end of constructor.
+ LLWindowCallbacks null_callbacks;
+ mCallbacks = &null_callbacks;
+
+ // Voodoo for calling cocoa from carbon (see llwindowmacosx-objc.mm).
+ setupCocoa();
+
+ // Initialize the keyboard
+ gKeyboard = new LLKeyboardMacOSX();
+ gKeyboard->setCallbacks(callbacks);
+
+ // Ignore use_gl for now, only used for drones on PC
+ mWindow = NULL;
+ mContext = NULL;
+ mPixelFormat = NULL;
+ mDisplay = CGMainDisplayID();
+ mSimulatedRightClick = FALSE;
+ mLastModifiers = 0;
+ mHandsOffEvents = FALSE;
+ mCursorDecoupled = FALSE;
+ mCursorLastEventDeltaX = 0;
+ mCursorLastEventDeltaY = 0;
+ mCursorIgnoreNextDelta = FALSE;
+ mNeedsResize = FALSE;
+ mOverrideAspectRatio = 0.f;
+ mMaximized = FALSE;
+ mMinimized = FALSE;
+ mLanguageTextInputAllowed = FALSE;
+ mPreeditor = NULL;
+ mFSAASamples = fsaa_samples;
+ mForceRebuild = FALSE;
+
+ // Get the original aspect ratio of the main device.
+ mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay);
+
+ // Stash the window title
+ mWindowTitle = title;
+ //mWindowTitle[0] = title.length();
+
+ mDragOverrideCursor = -1;
+
+ // Set up global event handlers (the fullscreen case needs this)
+ //InstallStandardEventHandler(GetApplicationEventTarget());
+
+ // Stash an object pointer for OSMessageBox()
+ gWindowImplementation = this;
+ // Create the GL context and set it up for windowed or fullscreen, as appropriate.
+ if(createContext(x, y, width, height, 32, fullscreen, enable_vsync))
+ {
+ if(mWindow != NULL)
+ {
+ makeWindowOrderFront(mWindow);
+ }
+
+ if (!gGLManager.initGL())
+ {
+ setupFailure(
+ "Second Life is unable to run because your video card drivers\n"
+ "are out of date or unsupported. Please make sure you have\n"
+ "the latest video card drivers installed.\n"
+ "If you continue to receive this message, contact customer service.",
+ "Error",
+ OSMB_OK);
+ return;
+ }
//start with arrow cursor
- initCursors();
- setCursor( UI_CURSOR_ARROW );
-
- allowLanguageTextInput(NULL, FALSE);
- }
-
- mCallbacks = callbacks;
- stop_glerror();
-
+ initCursors();
+ setCursor( UI_CURSOR_ARROW );
+
+ allowLanguageTextInput(NULL, FALSE);
+ }
+ mCallbacks = callbacks;
+ stop_glerror();
+
+
}
// These functions are used as wrappers for our internal event handling callbacks.
@@ -205,7 +205,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
{
mRawKeyEvent = event;
- bool retVal = gKeyboard->handleKeyUp(key, mask);
+ bool retVal = gKeyboard->handleKeyUp(key, mask);
mRawKeyEvent = NULL;
return retVal;
}
@@ -222,22 +222,22 @@ bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wch
}
mRawKeyEvent = event;
- bool retVal = gKeyboard->handleKeyDown(key, mask);
+ bool retVal = gKeyboard->handleKeyDown(key, mask);
mRawKeyEvent = NULL;
return retVal;
}
void callResetKeys()
{
- gKeyboard->resetKeys();
+ gKeyboard->resetKeys();
}
bool callUnicodeCallback(wchar_t character, unsigned int mask)
{
NativeKeyEventData eventData;
-
+
memset(&eventData, 0, sizeof(NativeKeyEventData));
-
+
eventData.mKeyEvent = NativeKeyEventData::KEYCHAR;
eventData.mEventType = 0;
eventData.mEventModifiers = mask;
@@ -245,9 +245,9 @@ bool callUnicodeCallback(wchar_t character, unsigned int mask)
eventData.mEventChars = character;
eventData.mEventUnmodChars = character;
eventData.mEventRepeat = false;
-
+
mRawKeyEvent = &eventData;
-
+
bool result = gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask);
mRawKeyEvent = NULL;
return result;
@@ -255,18 +255,18 @@ bool callUnicodeCallback(wchar_t character, unsigned int mask)
void callFocus()
{
- if (gWindowImplementation)
- {
- gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation);
- }
+ if (gWindowImplementation)
+ {
+ gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation);
+ }
}
void callFocusLost()
{
- if (gWindowImplementation)
- {
- gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
- }
+ if (gWindowImplementation)
+ {
+ gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
+ }
}
void callRightMouseDown(float *pos, MASK mask)
@@ -275,11 +275,11 @@ void callRightMouseDown(float *pos, MASK mask)
{
gWindowImplementation->interruptLanguageTextInput();
}
-
- LLCoordGL outCoords;
- outCoords.mX = ll_round(pos[0]);
- outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleRightMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+
+ LLCoordGL outCoords;
+ outCoords.mX = ll_round(pos[0]);
+ outCoords.mY = ll_round(pos[1]);
+ gWindowImplementation->getCallbacks()->handleRightMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
}
void callRightMouseUp(float *pos, MASK mask)
@@ -288,11 +288,11 @@ void callRightMouseUp(float *pos, MASK mask)
{
gWindowImplementation->interruptLanguageTextInput();
}
-
- LLCoordGL outCoords;
- outCoords.mX = ll_round(pos[0]);
- outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleRightMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+
+ LLCoordGL outCoords;
+ outCoords.mX = ll_round(pos[0]);
+ outCoords.mY = ll_round(pos[1]);
+ gWindowImplementation->getCallbacks()->handleRightMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
}
void callLeftMouseDown(float *pos, MASK mask)
@@ -301,11 +301,11 @@ void callLeftMouseDown(float *pos, MASK mask)
{
gWindowImplementation->interruptLanguageTextInput();
}
-
- LLCoordGL outCoords;
- outCoords.mX = ll_round(pos[0]);
- outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+
+ LLCoordGL outCoords;
+ outCoords.mX = ll_round(pos[0]);
+ outCoords.mY = ll_round(pos[1]);
+ gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
}
void callLeftMouseUp(float *pos, MASK mask)
@@ -314,12 +314,12 @@ void callLeftMouseUp(float *pos, MASK mask)
{
gWindowImplementation->interruptLanguageTextInput();
}
-
- LLCoordGL outCoords;
- outCoords.mX = ll_round(pos[0]);
- outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
-
+
+ LLCoordGL outCoords;
+ outCoords.mX = ll_round(pos[0]);
+ outCoords.mY = ll_round(pos[1]);
+ gWindowImplementation->getCallbacks()->handleMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+
}
void callDoubleClick(float *pos, MASK mask)
@@ -328,37 +328,37 @@ void callDoubleClick(float *pos, MASK mask)
{
gWindowImplementation->interruptLanguageTextInput();
}
-
- LLCoordGL outCoords;
- outCoords.mX = ll_round(pos[0]);
- outCoords.mY = ll_round(pos[1]);
- gWindowImplementation->getCallbacks()->handleDoubleClick(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+
+ LLCoordGL outCoords;
+ outCoords.mX = ll_round(pos[0]);
+ outCoords.mY = ll_round(pos[1]);
+ gWindowImplementation->getCallbacks()->handleDoubleClick(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
}
void callResize(unsigned int width, unsigned int height)
{
- if (gWindowImplementation != NULL)
- {
- gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height);
- }
+ if (gWindowImplementation != NULL)
+ {
+ gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height);
+ }
}
void callMouseMoved(float *pos, MASK mask)
{
- LLCoordGL outCoords;
- outCoords.mX = ll_round(pos[0]);
- outCoords.mY = ll_round(pos[1]);
- float deltas[2];
- gWindowImplementation->getMouseDeltas(deltas);
- outCoords.mX += deltas[0];
- outCoords.mY += deltas[1];
- gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
- //gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0);
+ LLCoordGL outCoords;
+ outCoords.mX = ll_round(pos[0]);
+ outCoords.mY = ll_round(pos[1]);
+ float deltas[2];
+ gWindowImplementation->getMouseDeltas(deltas);
+ outCoords.mX += deltas[0];
+ outCoords.mY += deltas[1];
+ gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE));
+ //gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0);
}
void callMouseDragged(float *pos, MASK mask)
{
- LLCoordGL outCoords;
+ LLCoordGL outCoords;
outCoords.mX = ll_round(pos[0]);
outCoords.mY = ll_round(pos[1]);
float deltas[2];
@@ -370,78 +370,78 @@ void callMouseDragged(float *pos, MASK mask)
void callScrollMoved(float deltaX, float deltaY)
{
- if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
- {
- gWindowImplementation->getCallbacks()->handleScrollHWheel(gWindowImplementation, deltaX);
- gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, deltaY);
- }
+ if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
+ {
+ gWindowImplementation->getCallbacks()->handleScrollHWheel(gWindowImplementation, deltaX);
+ gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, deltaY);
+ }
}
void callMouseExit()
{
- gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation);
+ gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation);
}
void callWindowFocus()
{
if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
- {
- gWindowImplementation->getCallbacks()->handleFocus (gWindowImplementation);
- }
- else
- {
- LL_WARNS("COCOA") << "Window Implementation or callbacks not yet initialized." << LL_ENDL;
- }
+ {
+ gWindowImplementation->getCallbacks()->handleFocus (gWindowImplementation);
+ }
+ else
+ {
+ LL_WARNS("COCOA") << "Window Implementation or callbacks not yet initialized." << LL_ENDL;
+ }
}
void callWindowUnfocus()
{
- if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
- {
- gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
- }
+ if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
+ {
+ gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
+ }
}
void callWindowHide()
-{
- if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
- {
- gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, false);
- }
+{
+ if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
+ {
+ gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, false);
+ }
}
void callWindowUnhide()
-{
- if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
- {
- gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, true);
- }
+{
+ if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
+ {
+ gWindowImplementation->getCallbacks()->handleActivate(gWindowImplementation, true);
+ }
}
void callWindowDidChangeScreen()
{
- if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
- {
- gWindowImplementation->getCallbacks()->handleWindowDidChangeScreen(gWindowImplementation);
- }
+ if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
+ {
+ gWindowImplementation->getCallbacks()->handleWindowDidChangeScreen(gWindowImplementation);
+ }
}
void callDeltaUpdate(float *delta, MASK mask)
{
- gWindowImplementation->updateMouseDeltas(delta);
+ gWindowImplementation->updateMouseDeltas(delta);
}
void callOtherMouseDown(float *pos, MASK mask, int button)
{
- LLCoordGL outCoords;
- outCoords.mX = ll_round(pos[0]);
- outCoords.mY = ll_round(pos[1]);
- float deltas[2];
- gWindowImplementation->getMouseDeltas(deltas);
- outCoords.mX += deltas[0];
- outCoords.mY += deltas[1];
+ LLCoordGL outCoords;
+ outCoords.mX = ll_round(pos[0]);
+ outCoords.mY = ll_round(pos[1]);
+ float deltas[2];
+ gWindowImplementation->getMouseDeltas(deltas);
+ outCoords.mX += deltas[0];
+ outCoords.mY += deltas[1];
if (button == 2)
{
@@ -455,12 +455,12 @@ void callOtherMouseDown(float *pos, MASK mask, int button)
void callOtherMouseUp(float *pos, MASK mask, int button)
{
- LLCoordGL outCoords;
- outCoords.mX = ll_round(pos[0]);
- outCoords.mY = ll_round(pos[1]);
- float deltas[2];
- gWindowImplementation->getMouseDeltas(deltas);
- outCoords.mX += deltas[0];
+ LLCoordGL outCoords;
+ outCoords.mX = ll_round(pos[0]);
+ outCoords.mY = ll_round(pos[1]);
+ float deltas[2];
+ gWindowImplementation->getMouseDeltas(deltas);
+ outCoords.mX += deltas[0];
outCoords.mY += deltas[1];
if (button == 2)
{
@@ -474,169 +474,169 @@ void callOtherMouseUp(float *pos, MASK mask, int button)
void callModifier(MASK mask)
{
- gKeyboard->handleModifier(mask);
+ gKeyboard->handleModifier(mask);
}
void callHandleDragEntered(std::string url)
{
- gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING);
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING);
}
void callHandleDragExited(std::string url)
{
- gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING);
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING);
}
void callHandleDragUpdated(std::string url)
{
- gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK);
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK);
}
void callHandleDragDropped(std::string url)
{
- gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED);
+ gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED);
}
void callQuitHandler()
{
- if (gWindowImplementation)
- {
- if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation))
- {
- gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation);
- }
- }
+ if (gWindowImplementation)
+ {
+ if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation))
+ {
+ gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation);
+ }
+ }
}
void getPreeditSelectionRange(int *position, int *length)
{
- if (gWindowImplementation->getPreeditor())
- {
- gWindowImplementation->getPreeditor()->getSelectionRange(position, length);
- }
+ if (gWindowImplementation->getPreeditor())
+ {
+ gWindowImplementation->getPreeditor()->getSelectionRange(position, length);
+ }
}
void getPreeditMarkedRange(int *position, int *length)
{
- if (gWindowImplementation->getPreeditor())
- {
- gWindowImplementation->getPreeditor()->getPreeditRange(position, length);
- }
+ if (gWindowImplementation->getPreeditor())
+ {
+ gWindowImplementation->getPreeditor()->getPreeditRange(position, length);
+ }
}
void setPreeditMarkedRange(int position, int length)
{
- if (gWindowImplementation->getPreeditor())
- {
- gWindowImplementation->getPreeditor()->markAsPreedit(position, length);
- }
+ if (gWindowImplementation->getPreeditor())
+ {
+ gWindowImplementation->getPreeditor()->markAsPreedit(position, length);
+ }
}
bool handleUnicodeCharacter(wchar_t c)
{
bool success = false;
- if (gWindowImplementation->getPreeditor())
- {
+ if (gWindowImplementation->getPreeditor())
+ {
success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c);
- }
-
+ }
+
return success;
}
void resetPreedit()
{
- if (gWindowImplementation->getPreeditor())
- {
- gWindowImplementation->getPreeditor()->resetPreedit();
- }
+ if (gWindowImplementation->getPreeditor())
+ {
+ gWindowImplementation->getPreeditor()->resetPreedit();
+ }
}
// For reasons of convenience, handle IME updates here.
// This largely mirrors the old implementation, only sans the carbon parameters.
void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments)
{
- if (gWindowImplementation->getPreeditor())
- {
- LLPreeditor *preeditor = gWindowImplementation->getPreeditor();
- preeditor->resetPreedit();
- // This should be a viable replacement for the kEventParamTextInputSendReplaceRange parameter.
- if (replacementRange[0] < replacementRange[1])
- {
- const LLWString& text = preeditor->getPreeditString();
- const S32 location = wstring_wstring_length_from_utf16_length(text, 0, replacementRange[0]);
- const S32 length = wstring_wstring_length_from_utf16_length(text, location, replacementRange[1]);
- preeditor->markAsPreedit(location, length);
- }
-
- LLWString fix_str = utf16str_to_wstring(llutf16string(unitext, text_len));
-
- S32 caret_position = fix_str.length();
-
- preeditor->updatePreedit(fix_str, segments.seg_lengths, segments.seg_standouts, caret_position);
- }
+ if (gWindowImplementation->getPreeditor())
+ {
+ LLPreeditor *preeditor = gWindowImplementation->getPreeditor();
+ preeditor->resetPreedit();
+ // This should be a viable replacement for the kEventParamTextInputSendReplaceRange parameter.
+ if (replacementRange[0] < replacementRange[1])
+ {
+ const LLWString& text = preeditor->getPreeditString();
+ const S32 location = wstring_wstring_length_from_utf16_length(text, 0, replacementRange[0]);
+ const S32 length = wstring_wstring_length_from_utf16_length(text, location, replacementRange[1]);
+ preeditor->markAsPreedit(location, length);
+ }
+
+ LLWString fix_str = utf16str_to_wstring(llutf16string(unitext, text_len));
+
+ S32 caret_position = fix_str.length();
+
+ preeditor->updatePreedit(fix_str, segments.seg_lengths, segments.seg_standouts, caret_position);
+ }
}
void getPreeditLocation(float *location, unsigned int length)
{
- if (gWindowImplementation->getPreeditor())
- {
- LLPreeditor *preeditor = gWindowImplementation->getPreeditor();
- LLCoordGL coord;
- LLCoordScreen screen;
- LLRect rect;
-
- preeditor->getPreeditLocation(length, &coord, &rect, NULL);
-
- float c[4] = {float(coord.mX), float(coord.mY), 0, 0};
-
- convertRectToScreen(gWindowImplementation->getWindow(), c);
-
- location[0] = c[0];
- location[1] = c[1];
- }
+ if (gWindowImplementation->getPreeditor())
+ {
+ LLPreeditor *preeditor = gWindowImplementation->getPreeditor();
+ LLCoordGL coord;
+ LLCoordScreen screen;
+ LLRect rect;
+
+ preeditor->getPreeditLocation(length, &coord, &rect, NULL);
+
+ float c[4] = {float(coord.mX), float(coord.mY), 0, 0};
+
+ convertRectToScreen(gWindowImplementation->getWindow(), c);
+
+ location[0] = c[0];
+ location[1] = c[1];
+ }
}
void LLWindowMacOSX::updateMouseDeltas(float* deltas)
{
- if (mCursorDecoupled)
- {
- mCursorLastEventDeltaX = ll_round(deltas[0]);
- mCursorLastEventDeltaY = ll_round(-deltas[1]);
-
- if (mCursorIgnoreNextDelta)
- {
- mCursorLastEventDeltaX = 0;
- mCursorLastEventDeltaY = 0;
- mCursorIgnoreNextDelta = FALSE;
- }
- } else {
- mCursorLastEventDeltaX = 0;
- mCursorLastEventDeltaY = 0;
- }
+ if (mCursorDecoupled)
+ {
+ mCursorLastEventDeltaX = ll_round(deltas[0]);
+ mCursorLastEventDeltaY = ll_round(-deltas[1]);
+
+ if (mCursorIgnoreNextDelta)
+ {
+ mCursorLastEventDeltaX = 0;
+ mCursorLastEventDeltaY = 0;
+ mCursorIgnoreNextDelta = FALSE;
+ }
+ } else {
+ mCursorLastEventDeltaX = 0;
+ mCursorLastEventDeltaY = 0;
+ }
}
void LLWindowMacOSX::getMouseDeltas(float* delta)
{
- delta[0] = mCursorLastEventDeltaX;
- delta[1] = mCursorLastEventDeltaY;
+ delta[0] = mCursorLastEventDeltaX;
+ delta[1] = mCursorLastEventDeltaY;
}
BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL enable_vsync)
{
- mFullscreen = fullscreen;
-
- if (mWindow == NULL)
- {
- mWindow = getMainAppWindow();
- }
-
- if(mContext == NULL)
- {
- // Our OpenGL view is already defined within SecondLife.xib.
- // Get the view instead.
- mGLView = createOpenGLView(mWindow, mFSAASamples, enable_vsync);
- mContext = getCGLContextObj(mGLView);
- gGLManager.mVRAM = getVramSize(mGLView);
+ mFullscreen = fullscreen;
+
+ if (mWindow == NULL)
+ {
+ mWindow = getMainAppWindow();
+ }
+
+ if(mContext == NULL)
+ {
+ // Our OpenGL view is already defined within SecondLife.xib.
+ // Get the view instead.
+ mGLView = createOpenGLView(mWindow, mFSAASamples, enable_vsync);
+ mContext = getCGLContextObj(mGLView);
+ gGLManager.mVRAM = getVramSize(mGLView);
if(!mPixelFormat)
{
@@ -659,30 +659,30 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
GLint numPixelFormats;
CGLChoosePixelFormat (attribs, &mPixelFormat, &numPixelFormats);
-
+
if(mPixelFormat == NULL) {
CGLChoosePixelFormat (attribs, &mPixelFormat, &numPixelFormats);
}
}
- }
-
- // This sets up our view to recieve text from our non-inline text input window.
- setupInputWindow(mWindow, mGLView);
-
- // Hook up the context to a drawable
-
- if(mContext != NULL)
- {
-
-
- U32 err = CGLSetCurrentContext(mContext);
- if (err != kCGLNoError)
- {
- setupFailure("Can't activate GL rendering context", "Error", OSMB_OK);
- return FALSE;
- }
- }
+ }
+
+ // This sets up our view to recieve text from our non-inline text input window.
+ setupInputWindow(mWindow, mGLView);
+
+ // Hook up the context to a drawable
+
+ if(mContext != NULL)
+ {
+
+
+ U32 err = CGLSetCurrentContext(mContext);
+ if (err != kCGLNoError)
+ {
+ setupFailure("Can't activate GL rendering context", "Error", OSMB_OK);
+ return FALSE;
+ }
+ }
mRefreshRate = CGDisplayModeGetRefreshRate(CGDisplayCopyDisplayMode(mDisplay));
if(mRefreshRate == 0)
@@ -691,29 +691,29 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
mRefreshRate = DEFAULT_REFRESH_RATE;
}
- // Disable vertical sync for swap
+ // Disable vertical sync for swap
toggleVSync(enable_vsync);
- //enable multi-threaded OpenGL
- if (sUseMultGL)
- {
- CGLError cgl_err;
- CGLContextObj ctx = CGLGetCurrentContext();
+ //enable multi-threaded OpenGL
+ if (sUseMultGL)
+ {
+ CGLError cgl_err;
+ CGLContextObj ctx = CGLGetCurrentContext();
- cgl_err = CGLEnable( ctx, kCGLCEMPEngine);
+ cgl_err = CGLEnable( ctx, kCGLCEMPEngine);
- if (cgl_err != kCGLNoError )
- {
- LL_INFOS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
- }
- else
- {
+ if (cgl_err != kCGLNoError )
+ {
+ LL_INFOS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
+ }
+ else
+ {
LL_INFOS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
- }
- }
- makeFirstResponder(mWindow, mGLView);
-
- return TRUE;
+ }
+ }
+ makeFirstResponder(mWindow, mGLView);
+
+ return TRUE;
}
@@ -721,66 +721,66 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
// This makes this method obsolete.
BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp)
{
- return FALSE;
+ return FALSE;
}
void LLWindowMacOSX::destroyContext()
{
- if (!mContext)
- {
- // We don't have a context
- return;
- }
- // Unhook the GL context from any drawable it may have
- if(mContext != NULL)
- {
- LL_DEBUGS("Window") << "destroyContext: unhooking drawable " << LL_ENDL;
- CGLSetCurrentContext(NULL);
- }
-
- // Clean up remaining GL state before blowing away window
- gGLManager.shutdownGL();
-
- // Clean up the pixel format
- if(mPixelFormat != NULL)
- {
- CGLDestroyPixelFormat(mPixelFormat);
- mPixelFormat = NULL;
- }
-
- // Clean up the GL context
- if(mContext != NULL)
- {
- CGLDestroyContext(mContext);
- }
-
- // Destroy our LLOpenGLView
- if(mGLView != NULL)
- {
- removeGLView(mGLView);
- mGLView = NULL;
- }
-
- // Close the window
- if(mWindow != NULL)
- {
+ if (!mContext)
+ {
+ // We don't have a context
+ return;
+ }
+ // Unhook the GL context from any drawable it may have
+ if(mContext != NULL)
+ {
+ LL_DEBUGS("Window") << "destroyContext: unhooking drawable " << LL_ENDL;
+ CGLSetCurrentContext(NULL);
+ }
+
+ // Clean up remaining GL state before blowing away window
+ gGLManager.shutdownGL();
+
+ // Clean up the pixel format
+ if(mPixelFormat != NULL)
+ {
+ CGLDestroyPixelFormat(mPixelFormat);
+ mPixelFormat = NULL;
+ }
+
+ // Clean up the GL context
+ if(mContext != NULL)
+ {
+ CGLDestroyContext(mContext);
+ }
+
+ // Destroy our LLOpenGLView
+ if(mGLView != NULL)
+ {
+ removeGLView(mGLView);
+ mGLView = NULL;
+ }
+
+ // Close the window
+ if(mWindow != NULL)
+ {
NSWindowRef dead_window = mWindow;
mWindow = NULL;
- closeWindow(dead_window);
- }
+ closeWindow(dead_window);
+ }
}
LLWindowMacOSX::~LLWindowMacOSX()
{
- destroyContext();
+ destroyContext();
- if(mSupportedResolutions != NULL)
- {
- delete []mSupportedResolutions;
- }
+ if(mSupportedResolutions != NULL)
+ {
+ delete []mSupportedResolutions;
+ }
- gWindowImplementation = NULL;
+ gWindowImplementation = NULL;
}
@@ -791,20 +791,20 @@ void LLWindowMacOSX::show()
void LLWindowMacOSX::hide()
{
- setMouseClipping(FALSE);
+ setMouseClipping(FALSE);
}
//virtual
void LLWindowMacOSX::minimize()
{
- setMouseClipping(FALSE);
- showCursor();
+ setMouseClipping(FALSE);
+ showCursor();
}
//virtual
void LLWindowMacOSX::restore()
{
- show();
+ show();
}
@@ -812,193 +812,193 @@ void LLWindowMacOSX::restore()
// Usually called from LLWindowManager::destroyWindow()
void LLWindowMacOSX::close()
{
- // Is window is already closed?
- // if (!mWindow)
- // {
- // return;
- // }
+ // Is window is already closed?
+ // if (!mWindow)
+ // {
+ // return;
+ // }
- // Make sure cursor is visible and we haven't mangled the clipping state.
- setMouseClipping(FALSE);
- showCursor();
+ // Make sure cursor is visible and we haven't mangled the clipping state.
+ setMouseClipping(FALSE);
+ showCursor();
- destroyContext();
+ destroyContext();
}
BOOL LLWindowMacOSX::isValid()
{
- if(mFullscreen)
- {
- return(TRUE);
- }
+ if(mFullscreen)
+ {
+ return(TRUE);
+ }
- return (mWindow != NULL);
+ return (mWindow != NULL);
}
BOOL LLWindowMacOSX::getVisible()
{
- BOOL result = FALSE;
+ BOOL result = FALSE;
- if(mFullscreen)
- {
- result = TRUE;
- }if (mWindow)
- {
- result = TRUE;
- }
+ if(mFullscreen)
+ {
+ result = TRUE;
+ }if (mWindow)
+ {
+ result = TRUE;
+ }
- return(result);
+ return(result);
}
BOOL LLWindowMacOSX::getMinimized()
{
- return mMinimized;
+ return mMinimized;
}
BOOL LLWindowMacOSX::getMaximized()
{
- return mMaximized;
+ return mMaximized;
}
BOOL LLWindowMacOSX::maximize()
{
- if (mWindow && !mMaximized)
- {
- }
+ if (mWindow && !mMaximized)
+ {
+ }
- return mMaximized;
+ return mMaximized;
}
BOOL LLWindowMacOSX::getFullscreen()
{
- return mFullscreen;
+ return mFullscreen;
}
void LLWindowMacOSX::gatherInput()
{
- updateCursor();
+ updateCursor();
}
BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position)
{
- S32 err = -1;
+ S32 err = -1;
- if(mFullscreen)
- {
- position->mX = 0;
- position->mY = 0;
- err = noErr;
- }
- else if(mWindow)
- {
- const CGPoint & pos = getContentViewBoundsPosition(mWindow);
+ if(mFullscreen)
+ {
+ position->mX = 0;
+ position->mY = 0;
+ err = noErr;
+ }
+ else if(mWindow)
+ {
+ const CGPoint & pos = getContentViewBoundsPosition(mWindow);
- position->mX = pos.x;
- position->mY = pos.y;
+ position->mX = pos.x;
+ position->mY = pos.y;
- err = noErr;
- }
- else
- {
- LL_ERRS() << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << LL_ENDL;
- }
+ err = noErr;
+ }
+ else
+ {
+ LL_ERRS() << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << LL_ENDL;
+ }
- return (err == noErr);
+ return (err == noErr);
}
BOOL LLWindowMacOSX::getSize(LLCoordScreen *size)
{
- S32 err = -1;
+ S32 err = -1;
- if(mFullscreen)
- {
- size->mX = mFullscreenWidth;
- size->mY = mFullscreenHeight;
- err = noErr;
- }
- else if(mWindow)
- {
- const CGSize & sz = gHiDPISupport ? getDeviceContentViewSize(mWindow, mGLView) : getContentViewBoundsSize(mWindow);
+ if(mFullscreen)
+ {
+ size->mX = mFullscreenWidth;
+ size->mY = mFullscreenHeight;
+ err = noErr;
+ }
+ else if(mWindow)
+ {
+ const CGSize & sz = gHiDPISupport ? getDeviceContentViewSize(mWindow, mGLView) : getContentViewBoundsSize(mWindow);
- size->mX = sz.width;
- size->mY = sz.height;
+ size->mX = sz.width;
+ size->mY = sz.height;
err = noErr;
- }
- else
- {
- LL_ERRS() << "LLWindowMacOSX::getSize(): no window and not fullscreen!" << LL_ENDL;
- }
+ }
+ else
+ {
+ LL_ERRS() << "LLWindowMacOSX::getSize(): no window and not fullscreen!" << LL_ENDL;
+ }
- return (err == noErr);
+ return (err == noErr);
}
BOOL LLWindowMacOSX::getSize(LLCoordWindow *size)
{
- S32 err = -1;
-
- if(mFullscreen)
- {
- size->mX = mFullscreenWidth;
- size->mY = mFullscreenHeight;
- err = noErr;
- }
- else if(mWindow)
- {
- const CGSize & sz = gHiDPISupport ? getDeviceContentViewSize(mWindow, mGLView) : getContentViewBoundsSize(mWindow);
-
- size->mX = sz.width;
- size->mY = sz.height;
+ S32 err = -1;
+
+ if(mFullscreen)
+ {
+ size->mX = mFullscreenWidth;
+ size->mY = mFullscreenHeight;
+ err = noErr;
+ }
+ else if(mWindow)
+ {
+ const CGSize & sz = gHiDPISupport ? getDeviceContentViewSize(mWindow, mGLView) : getContentViewBoundsSize(mWindow);
+
+ size->mX = sz.width;
+ size->mY = sz.height;
err = noErr;
-
-
- }
- else
- {
- LL_ERRS() << "LLWindowMacOSX::getSize(): no window and not fullscreen!" << LL_ENDL;
- }
-
- return (err == noErr);
+
+
+ }
+ else
+ {
+ LL_ERRS() << "LLWindowMacOSX::getSize(): no window and not fullscreen!" << LL_ENDL;
+ }
+
+ return (err == noErr);
}
BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position)
{
- if(mWindow)
- {
- float pos[2] = {float(position.mX), float(position.mY)};
- setWindowPos(mWindow, pos);
- }
+ if(mWindow)
+ {
+ float pos[2] = {float(position.mX), float(position.mY)};
+ setWindowPos(mWindow, pos);
+ }
- return TRUE;
+ return TRUE;
}
BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size)
{
- if(mWindow)
- {
+ if(mWindow)
+ {
LLCoordWindow to;
convertCoords(size, &to);
- setWindowSize(mWindow, to.mX, to.mY);
+ setWindowSize(mWindow, to.mX, to.mY);
return TRUE;
- }
+ }
- return FALSE;
+ return FALSE;
}
BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size)
{
- if (mWindow)
- {
+ if (mWindow)
+ {
const int titlePadding = 22;
setWindowSize(mWindow, size.mX, size.mY + titlePadding);
return TRUE;
- }
-
- return FALSE;
+ }
+
+ return FALSE;
}
void LLWindowMacOSX::swapBuffers()
{
- CGLFlushDrawable(mContext);
+ CGLFlushDrawable(mContext);
}
void LLWindowMacOSX::restoreGLContext()
@@ -1008,106 +1008,106 @@ void LLWindowMacOSX::restoreGLContext()
F32 LLWindowMacOSX::getGamma()
{
- F32 result = 2.2; // Default to something sane
-
- CGGammaValue redMin;
- CGGammaValue redMax;
- CGGammaValue redGamma;
- CGGammaValue greenMin;
- CGGammaValue greenMax;
- CGGammaValue greenGamma;
- CGGammaValue blueMin;
- CGGammaValue blueMax;
- CGGammaValue blueGamma;
-
- if(CGGetDisplayTransferByFormula(
- mDisplay,
- &redMin,
- &redMax,
- &redGamma,
- &greenMin,
- &greenMax,
- &greenGamma,
- &blueMin,
- &blueMax,
- &blueGamma) == noErr)
- {
- // So many choices...
- // Let's just return the green channel gamma for now.
- result = greenGamma;
- }
-
- return result;
+ F32 result = 2.2; // Default to something sane
+
+ CGGammaValue redMin;
+ CGGammaValue redMax;
+ CGGammaValue redGamma;
+ CGGammaValue greenMin;
+ CGGammaValue greenMax;
+ CGGammaValue greenGamma;
+ CGGammaValue blueMin;
+ CGGammaValue blueMax;
+ CGGammaValue blueGamma;
+
+ if(CGGetDisplayTransferByFormula(
+ mDisplay,
+ &redMin,
+ &redMax,
+ &redGamma,
+ &greenMin,
+ &greenMax,
+ &greenGamma,
+ &blueMin,
+ &blueMax,
+ &blueGamma) == noErr)
+ {
+ // So many choices...
+ // Let's just return the green channel gamma for now.
+ result = greenGamma;
+ }
+
+ return result;
}
U32 LLWindowMacOSX::getFSAASamples()
{
- return mFSAASamples;
+ return mFSAASamples;
}
void LLWindowMacOSX::setFSAASamples(const U32 samples)
{
- mFSAASamples = samples;
- mForceRebuild = TRUE;
+ mFSAASamples = samples;
+ mForceRebuild = TRUE;
}
BOOL LLWindowMacOSX::restoreGamma()
{
- CGDisplayRestoreColorSyncSettings();
- return true;
+ CGDisplayRestoreColorSyncSettings();
+ return true;
}
BOOL LLWindowMacOSX::setGamma(const F32 gamma)
{
- CGGammaValue redMin;
- CGGammaValue redMax;
- CGGammaValue redGamma;
- CGGammaValue greenMin;
- CGGammaValue greenMax;
- CGGammaValue greenGamma;
- CGGammaValue blueMin;
- CGGammaValue blueMax;
- CGGammaValue blueGamma;
-
- // MBW -- XXX -- Should we allow this in windowed mode?
-
- if(CGGetDisplayTransferByFormula(
- mDisplay,
- &redMin,
- &redMax,
- &redGamma,
- &greenMin,
- &greenMax,
- &greenGamma,
- &blueMin,
- &blueMax,
- &blueGamma) != noErr)
- {
- return false;
- }
-
- if(CGSetDisplayTransferByFormula(
- mDisplay,
- redMin,
- redMax,
- gamma,
- greenMin,
- greenMax,
- gamma,
- blueMin,
- blueMax,
- gamma) != noErr)
- {
- return false;
- }
-
-
- return true;
+ CGGammaValue redMin;
+ CGGammaValue redMax;
+ CGGammaValue redGamma;
+ CGGammaValue greenMin;
+ CGGammaValue greenMax;
+ CGGammaValue greenGamma;
+ CGGammaValue blueMin;
+ CGGammaValue blueMax;
+ CGGammaValue blueGamma;
+
+ // MBW -- XXX -- Should we allow this in windowed mode?
+
+ if(CGGetDisplayTransferByFormula(
+ mDisplay,
+ &redMin,
+ &redMax,
+ &redGamma,
+ &greenMin,
+ &greenMax,
+ &greenGamma,
+ &blueMin,
+ &blueMax,
+ &blueGamma) != noErr)
+ {
+ return false;
+ }
+
+ if(CGSetDisplayTransferByFormula(
+ mDisplay,
+ redMin,
+ redMax,
+ gamma,
+ greenMin,
+ greenMax,
+ gamma,
+ blueMin,
+ blueMax,
+ gamma) != noErr)
+ {
+ return false;
+ }
+
+
+ return true;
}
BOOL LLWindowMacOSX::isCursorHidden()
{
- return mCursorHidden;
+ return mCursorHidden;
}
@@ -1115,142 +1115,142 @@ BOOL LLWindowMacOSX::isCursorHidden()
// Constrains the mouse to the window.
void LLWindowMacOSX::setMouseClipping( BOOL b )
{
- // Just stash the requested state. We'll simulate this when the cursor is hidden by decoupling.
- mIsMouseClipping = b;
+ // Just stash the requested state. We'll simulate this when the cursor is hidden by decoupling.
+ mIsMouseClipping = b;
- if(b)
- {
- // LL_INFOS() << "setMouseClipping(TRUE)" << LL_ENDL;
- }
- else
- {
- // LL_INFOS() << "setMouseClipping(FALSE)" << LL_ENDL;
- }
+ if(b)
+ {
+ // LL_INFOS() << "setMouseClipping(TRUE)" << LL_ENDL;
+ }
+ else
+ {
+ // LL_INFOS() << "setMouseClipping(FALSE)" << LL_ENDL;
+ }
- adjustCursorDecouple();
+ adjustCursorDecouple();
}
BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
{
- BOOL result = FALSE;
- LLCoordScreen screen_pos;
+ BOOL result = FALSE;
+ LLCoordScreen screen_pos;
- if (!convertCoords(position, &screen_pos))
- {
- return FALSE;
- }
+ if (!convertCoords(position, &screen_pos))
+ {
+ return FALSE;
+ }
- CGPoint newPosition;
+ CGPoint newPosition;
- // LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL;
+ // LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL;
- newPosition.x = screen_pos.mX;
- newPosition.y = screen_pos.mY;
+ newPosition.x = screen_pos.mX;
+ newPosition.y = screen_pos.mY;
- CGSetLocalEventsSuppressionInterval(0.0);
- if(CGWarpMouseCursorPosition(newPosition) == noErr)
- {
- result = TRUE;
- }
+ CGSetLocalEventsSuppressionInterval(0.0);
+ if(CGWarpMouseCursorPosition(newPosition) == noErr)
+ {
+ result = TRUE;
+ }
- // Under certain circumstances, this will trigger us to decouple the cursor.
- adjustCursorDecouple(true);
+ // Under certain circumstances, this will trigger us to decouple the cursor.
+ adjustCursorDecouple(true);
- // trigger mouse move callback
- LLCoordGL gl_pos;
- convertCoords(position, &gl_pos);
- float scale = getSystemUISize();
- gl_pos.mX *= scale;
- gl_pos.mY *= scale;
- mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
+ // trigger mouse move callback
+ LLCoordGL gl_pos;
+ convertCoords(position, &gl_pos);
+ float scale = getSystemUISize();
+ gl_pos.mX *= scale;
+ gl_pos.mY *= scale;
+ mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
- return result;
+ return result;
}
BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position)
{
- float cursor_point[2];
- LLCoordScreen screen_pos;
-
- if(mWindow == NULL)
- return FALSE;
+ float cursor_point[2];
+ LLCoordScreen screen_pos;
- getCursorPos(mWindow, cursor_point);
+ if(mWindow == NULL)
+ return FALSE;
+
+ getCursorPos(mWindow, cursor_point);
- if(mCursorDecoupled)
- {
- // CGMouseDelta x, y;
+ if(mCursorDecoupled)
+ {
+ // CGMouseDelta x, y;
- // If the cursor's decoupled, we need to read the latest movement delta as well.
- // CGGetLastMouseDelta( &x, &y );
- // cursor_point.h += x;
- // cursor_point.v += y;
+ // If the cursor's decoupled, we need to read the latest movement delta as well.
+ // CGGetLastMouseDelta( &x, &y );
+ // cursor_point.h += x;
+ // cursor_point.v += y;
- // CGGetLastMouseDelta may behave strangely when the cursor's first captured.
- // Stash in the event handler instead.
- cursor_point[0] += mCursorLastEventDeltaX;
- cursor_point[1] += mCursorLastEventDeltaY;
- }
+ // CGGetLastMouseDelta may behave strangely when the cursor's first captured.
+ // Stash in the event handler instead.
+ cursor_point[0] += mCursorLastEventDeltaX;
+ cursor_point[1] += mCursorLastEventDeltaY;
+ }
- float scale = getSystemUISize();
- position->mX = cursor_point[0] * scale;
- position->mY = cursor_point[1] * scale;
+ float scale = getSystemUISize();
+ position->mX = cursor_point[0] * scale;
+ position->mY = cursor_point[1] * scale;
- return TRUE;
+ return TRUE;
}
void LLWindowMacOSX::adjustCursorDecouple(bool warpingMouse)
{
- if(mIsMouseClipping && mCursorHidden)
- {
- if(warpingMouse)
- {
- // The cursor should be decoupled. Make sure it is.
- if(!mCursorDecoupled)
- {
- // LL_INFOS() << "adjustCursorDecouple: decoupling cursor" << LL_ENDL;
- CGAssociateMouseAndMouseCursorPosition(false);
- mCursorDecoupled = true;
- mCursorIgnoreNextDelta = TRUE;
- }
- }
- }
- else
- {
- // The cursor should not be decoupled. Make sure it isn't.
- if(mCursorDecoupled)
- {
- // LL_INFOS() << "adjustCursorDecouple: recoupling cursor" << LL_ENDL;
- CGAssociateMouseAndMouseCursorPosition(true);
- mCursorDecoupled = false;
- }
- }
+ if(mIsMouseClipping && mCursorHidden)
+ {
+ if(warpingMouse)
+ {
+ // The cursor should be decoupled. Make sure it is.
+ if(!mCursorDecoupled)
+ {
+ // LL_INFOS() << "adjustCursorDecouple: decoupling cursor" << LL_ENDL;
+ CGAssociateMouseAndMouseCursorPosition(false);
+ mCursorDecoupled = true;
+ mCursorIgnoreNextDelta = TRUE;
+ }
+ }
+ }
+ else
+ {
+ // The cursor should not be decoupled. Make sure it isn't.
+ if(mCursorDecoupled)
+ {
+ // LL_INFOS() << "adjustCursorDecouple: recoupling cursor" << LL_ENDL;
+ CGAssociateMouseAndMouseCursorPosition(true);
+ mCursorDecoupled = false;
+ }
+ }
}
F32 LLWindowMacOSX::getNativeAspectRatio()
{
- if (mFullscreen)
- {
- return (F32)mFullscreenWidth / (F32)mFullscreenHeight;
- }
- else
- {
- // The constructor for this class grabs the aspect ratio of the monitor before doing any resolution
- // switching, and stashes it in mOriginalAspectRatio. Here, we just return it.
+ if (mFullscreen)
+ {
+ return (F32)mFullscreenWidth / (F32)mFullscreenHeight;
+ }
+ else
+ {
+ // The constructor for this class grabs the aspect ratio of the monitor before doing any resolution
+ // switching, and stashes it in mOriginalAspectRatio. Here, we just return it.
- if (mOverrideAspectRatio > 0.f)
- {
- return mOverrideAspectRatio;
- }
+ if (mOverrideAspectRatio > 0.f)
+ {
+ return mOverrideAspectRatio;
+ }
- return mOriginalAspectRatio;
- }
+ return mOriginalAspectRatio;
+ }
}
F32 LLWindowMacOSX::getPixelAspectRatio()
{
- //OS X always enforces a 1:1 pixel aspect ratio, regardless of video mode
- return 1.f;
+ //OS X always enforces a 1:1 pixel aspect ratio, regardless of video mode
+ return 1.f;
}
U32 LLWindowMacOSX::getAvailableVRAMMegabytes() {
@@ -1281,165 +1281,165 @@ void LLWindowMacOSX::afterDialog()
void LLWindowMacOSX::flashIcon(F32 seconds)
{
- // For consistency with OS X conventions, the number of seconds given is ignored and
- // left up to the OS (which will actually bounce it for one second).
- requestUserAttention();
+ // For consistency with OS X conventions, the number of seconds given is ignored and
+ // left up to the OS (which will actually bounce it for one second).
+ requestUserAttention();
}
BOOL LLWindowMacOSX::isClipboardTextAvailable()
{
- return pasteBoardAvailable();
+ return pasteBoardAvailable();
}
BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst)
{
unsigned short* pboard_data = copyFromPBoard(); // must free returned data
- llutf16string str(pboard_data);
+ llutf16string str(pboard_data);
free(pboard_data);
- dst = utf16str_to_wstring(str);
- if (dst != L"")
- {
- return true;
- } else {
- return false;
- }
+ dst = utf16str_to_wstring(str);
+ if (dst != L"")
+ {
+ return true;
+ } else {
+ return false;
+ }
}
BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s)
{
- BOOL result = false;
- llutf16string utf16str = wstring_to_utf16str(s);
-
- result = copyToPBoard(utf16str.data(), utf16str.length());
+ BOOL result = false;
+ llutf16string utf16str = wstring_to_utf16str(s);
+
+ result = copyToPBoard(utf16str.data(), utf16str.length());
- return result;
+ return result;
}
// protected
BOOL LLWindowMacOSX::resetDisplayResolution()
{
- // This is only called from elsewhere in this class, and it's not used by the Mac implementation.
- return true;
+ // This is only called from elsewhere in this class, and it's not used by the Mac implementation.
+ return true;
}
LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_resolutions)
{
- if (!mSupportedResolutions)
- {
- CFArrayRef modes = CGDisplayCopyAllDisplayModes(mDisplay, nullptr);
-
- if(modes != NULL)
- {
- CFIndex index, cnt;
-
- mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
- mNumSupportedResolutions = 0;
-
- // Examine each mode
- cnt = CFArrayGetCount( modes );
-
- for ( index = 0; (index < cnt) && (mNumSupportedResolutions < MAX_NUM_RESOLUTIONS); index++ )
- {
- // Pull the mode dictionary out of the CFArray
- CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex( modes, index );
- long width = getDictLong(mode, kCGDisplayWidth);
- long height = getDictLong(mode, kCGDisplayHeight);
- long bits = getDictLong(mode, kCGDisplayBitsPerPixel);
-
- if(bits == BITS_PER_PIXEL && width >= 800 && height >= 600)
- {
- BOOL resolution_exists = FALSE;
- for(S32 i = 0; i < mNumSupportedResolutions; i++)
- {
- if (mSupportedResolutions[i].mWidth == width &&
- mSupportedResolutions[i].mHeight == height)
- {
- resolution_exists = TRUE;
- }
- }
- if (!resolution_exists)
- {
- mSupportedResolutions[mNumSupportedResolutions].mWidth = width;
- mSupportedResolutions[mNumSupportedResolutions].mHeight = height;
- mNumSupportedResolutions++;
- }
- }
- }
+ if (!mSupportedResolutions)
+ {
+ CFArrayRef modes = CGDisplayCopyAllDisplayModes(mDisplay, nullptr);
+
+ if(modes != NULL)
+ {
+ CFIndex index, cnt;
+
+ mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
+ mNumSupportedResolutions = 0;
+
+ // Examine each mode
+ cnt = CFArrayGetCount( modes );
+
+ for ( index = 0; (index < cnt) && (mNumSupportedResolutions < MAX_NUM_RESOLUTIONS); index++ )
+ {
+ // Pull the mode dictionary out of the CFArray
+ CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex( modes, index );
+ long width = getDictLong(mode, kCGDisplayWidth);
+ long height = getDictLong(mode, kCGDisplayHeight);
+ long bits = getDictLong(mode, kCGDisplayBitsPerPixel);
+
+ if(bits == BITS_PER_PIXEL && width >= 800 && height >= 600)
+ {
+ BOOL resolution_exists = FALSE;
+ for(S32 i = 0; i < mNumSupportedResolutions; i++)
+ {
+ if (mSupportedResolutions[i].mWidth == width &&
+ mSupportedResolutions[i].mHeight == height)
+ {
+ resolution_exists = TRUE;
+ }
+ }
+ if (!resolution_exists)
+ {
+ mSupportedResolutions[mNumSupportedResolutions].mWidth = width;
+ mSupportedResolutions[mNumSupportedResolutions].mHeight = height;
+ mNumSupportedResolutions++;
+ }
+ }
+ }
CFRelease(modes);
- }
- }
+ }
+ }
- num_resolutions = mNumSupportedResolutions;
- return mSupportedResolutions;
+ num_resolutions = mNumSupportedResolutions;
+ return mSupportedResolutions;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to)
{
- to->mX = from.mX;
- to->mY = from.mY;
- return TRUE;
+ to->mX = from.mX;
+ to->mY = from.mY;
+ return TRUE;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to)
{
- to->mX = from.mX;
- to->mY = from.mY;
- return TRUE;
+ to->mX = from.mX;
+ to->mY = from.mY;
+ return TRUE;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to)
{
- if(mWindow)
- {
- float mouse_point[2];
-
- mouse_point[0] = from.mX;
- mouse_point[1] = from.mY;
+ if(mWindow)
+ {
+ float mouse_point[2];
- convertScreenToWindow(mWindow, mouse_point);
+ mouse_point[0] = from.mX;
+ mouse_point[1] = from.mY;
+
+ convertScreenToWindow(mWindow, mouse_point);
- to->mX = mouse_point[0];
- to->mY = mouse_point[1];
+ to->mX = mouse_point[0];
+ to->mY = mouse_point[1];
- return TRUE;
- }
- return FALSE;
+ return TRUE;
+ }
+ return FALSE;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to)
{
- if(mWindow)
- {
- float mouse_point[2];
+ if(mWindow)
+ {
+ float mouse_point[2];
- mouse_point[0] = from.mX;
- mouse_point[1] = from.mY;
+ mouse_point[0] = from.mX;
+ mouse_point[1] = from.mY;
+
+ convertWindowToScreen(mWindow, mouse_point);
- convertWindowToScreen(mWindow, mouse_point);
+ to->mX = mouse_point[0];
+ to->mY = mouse_point[1];
- to->mX = mouse_point[0];
- to->mY = mouse_point[1];
-
- return TRUE;
- }
- return FALSE;
+ return TRUE;
+ }
+ return FALSE;
}
BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to)
{
- LLCoordWindow window_coord;
+ LLCoordWindow window_coord;
- return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
+ return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
}
BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to)
{
- LLCoordWindow window_coord;
+ LLCoordWindow window_coord;
- return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
+ return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
}
@@ -1447,66 +1447,66 @@ BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to)
void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& caption, U32 type)
{
- destroyContext();
+ destroyContext();
- OSMessageBox(text, caption, type);
+ OSMessageBox(text, caption, type);
}
- // Note on event recording - QUIT is a known special case and we are choosing NOT to record it for the record and playback feature
- // it is handled at a very low-level
+ // Note on event recording - QUIT is a known special case and we are choosing NOT to record it for the record and playback feature
+ // it is handled at a very low-level
const char* cursorIDToName(int id)
{
- switch (id)
- {
- case UI_CURSOR_ARROW: return "UI_CURSOR_ARROW";
- case UI_CURSOR_WAIT: return "UI_CURSOR_WAIT";
- case UI_CURSOR_HAND: return "UI_CURSOR_HAND";
- case UI_CURSOR_IBEAM: return "UI_CURSOR_IBEAM";
- case UI_CURSOR_CROSS: return "UI_CURSOR_CROSS";
- case UI_CURSOR_SIZENWSE: return "UI_CURSOR_SIZENWSE";
- case UI_CURSOR_SIZENESW: return "UI_CURSOR_SIZENESW";
- case UI_CURSOR_SIZEWE: return "UI_CURSOR_SIZEWE";
- case UI_CURSOR_SIZENS: return "UI_CURSOR_SIZENS";
- case UI_CURSOR_SIZEALL: return "UI_CURSOR_SIZEALL";
- case UI_CURSOR_NO: return "UI_CURSOR_NO";
- case UI_CURSOR_WORKING: return "UI_CURSOR_WORKING";
- case UI_CURSOR_TOOLGRAB: return "UI_CURSOR_TOOLGRAB";
- case UI_CURSOR_TOOLLAND: return "UI_CURSOR_TOOLLAND";
- case UI_CURSOR_TOOLFOCUS: return "UI_CURSOR_TOOLFOCUS";
- case UI_CURSOR_TOOLCREATE: return "UI_CURSOR_TOOLCREATE";
- case UI_CURSOR_ARROWDRAG: return "UI_CURSOR_ARROWDRAG";
- case UI_CURSOR_ARROWCOPY: return "UI_CURSOR_ARROWCOPY";
- case UI_CURSOR_ARROWDRAGMULTI: return "UI_CURSOR_ARROWDRAGMULTI";
- case UI_CURSOR_ARROWCOPYMULTI: return "UI_CURSOR_ARROWCOPYMULTI";
- case UI_CURSOR_NOLOCKED: return "UI_CURSOR_NOLOCKED";
- case UI_CURSOR_ARROWLOCKED: return "UI_CURSOR_ARROWLOCKED";
- case UI_CURSOR_GRABLOCKED: return "UI_CURSOR_GRABLOCKED";
- case UI_CURSOR_TOOLTRANSLATE: return "UI_CURSOR_TOOLTRANSLATE";
- case UI_CURSOR_TOOLROTATE: return "UI_CURSOR_TOOLROTATE";
- case UI_CURSOR_TOOLSCALE: return "UI_CURSOR_TOOLSCALE";
- case UI_CURSOR_TOOLCAMERA: return "UI_CURSOR_TOOLCAMERA";
- case UI_CURSOR_TOOLPAN: return "UI_CURSOR_TOOLPAN";
- case UI_CURSOR_TOOLZOOMIN: return "UI_CURSOR_TOOLZOOMIN";
- case UI_CURSOR_TOOLZOOMOUT: return "UI_CURSOR_TOOLZOOMOUT";
- case UI_CURSOR_TOOLPICKOBJECT3: return "UI_CURSOR_TOOLPICKOBJECT3";
- case UI_CURSOR_TOOLPLAY: return "UI_CURSOR_TOOLPLAY";
- case UI_CURSOR_TOOLPAUSE: return "UI_CURSOR_TOOLPAUSE";
- case UI_CURSOR_TOOLMEDIAOPEN: return "UI_CURSOR_TOOLMEDIAOPEN";
- case UI_CURSOR_PIPETTE: return "UI_CURSOR_PIPETTE";
- case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT";
- case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY";
- case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN";
- case UI_CURSOR_TOOLPATHFINDING: return "UI_CURSOR_PATHFINDING";
- case UI_CURSOR_TOOLPATHFINDING_PATH_START: return "UI_CURSOR_PATHFINDING_START";
- case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD: return "UI_CURSOR_PATHFINDING_START_ADD";
- case UI_CURSOR_TOOLPATHFINDING_PATH_END: return "UI_CURSOR_PATHFINDING_END";
- case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD: return "UI_CURSOR_PATHFINDING_END_ADD";
- case UI_CURSOR_TOOLNO: return "UI_CURSOR_NO";
- }
-
- LL_ERRS() << "cursorIDToName: unknown cursor id" << id << LL_ENDL;
-
- return "UI_CURSOR_ARROW";
+ switch (id)
+ {
+ case UI_CURSOR_ARROW: return "UI_CURSOR_ARROW";
+ case UI_CURSOR_WAIT: return "UI_CURSOR_WAIT";
+ case UI_CURSOR_HAND: return "UI_CURSOR_HAND";
+ case UI_CURSOR_IBEAM: return "UI_CURSOR_IBEAM";
+ case UI_CURSOR_CROSS: return "UI_CURSOR_CROSS";
+ case UI_CURSOR_SIZENWSE: return "UI_CURSOR_SIZENWSE";
+ case UI_CURSOR_SIZENESW: return "UI_CURSOR_SIZENESW";
+ case UI_CURSOR_SIZEWE: return "UI_CURSOR_SIZEWE";
+ case UI_CURSOR_SIZENS: return "UI_CURSOR_SIZENS";
+ case UI_CURSOR_SIZEALL: return "UI_CURSOR_SIZEALL";
+ case UI_CURSOR_NO: return "UI_CURSOR_NO";
+ case UI_CURSOR_WORKING: return "UI_CURSOR_WORKING";
+ case UI_CURSOR_TOOLGRAB: return "UI_CURSOR_TOOLGRAB";
+ case UI_CURSOR_TOOLLAND: return "UI_CURSOR_TOOLLAND";
+ case UI_CURSOR_TOOLFOCUS: return "UI_CURSOR_TOOLFOCUS";
+ case UI_CURSOR_TOOLCREATE: return "UI_CURSOR_TOOLCREATE";
+ case UI_CURSOR_ARROWDRAG: return "UI_CURSOR_ARROWDRAG";
+ case UI_CURSOR_ARROWCOPY: return "UI_CURSOR_ARROWCOPY";
+ case UI_CURSOR_ARROWDRAGMULTI: return "UI_CURSOR_ARROWDRAGMULTI";
+ case UI_CURSOR_ARROWCOPYMULTI: return "UI_CURSOR_ARROWCOPYMULTI";
+ case UI_CURSOR_NOLOCKED: return "UI_CURSOR_NOLOCKED";
+ case UI_CURSOR_ARROWLOCKED: return "UI_CURSOR_ARROWLOCKED";
+ case UI_CURSOR_GRABLOCKED: return "UI_CURSOR_GRABLOCKED";
+ case UI_CURSOR_TOOLTRANSLATE: return "UI_CURSOR_TOOLTRANSLATE";
+ case UI_CURSOR_TOOLROTATE: return "UI_CURSOR_TOOLROTATE";
+ case UI_CURSOR_TOOLSCALE: return "UI_CURSOR_TOOLSCALE";
+ case UI_CURSOR_TOOLCAMERA: return "UI_CURSOR_TOOLCAMERA";
+ case UI_CURSOR_TOOLPAN: return "UI_CURSOR_TOOLPAN";
+ case UI_CURSOR_TOOLZOOMIN: return "UI_CURSOR_TOOLZOOMIN";
+ case UI_CURSOR_TOOLZOOMOUT: return "UI_CURSOR_TOOLZOOMOUT";
+ case UI_CURSOR_TOOLPICKOBJECT3: return "UI_CURSOR_TOOLPICKOBJECT3";
+ case UI_CURSOR_TOOLPLAY: return "UI_CURSOR_TOOLPLAY";
+ case UI_CURSOR_TOOLPAUSE: return "UI_CURSOR_TOOLPAUSE";
+ case UI_CURSOR_TOOLMEDIAOPEN: return "UI_CURSOR_TOOLMEDIAOPEN";
+ case UI_CURSOR_PIPETTE: return "UI_CURSOR_PIPETTE";
+ case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT";
+ case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY";
+ case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN";
+ case UI_CURSOR_TOOLPATHFINDING: return "UI_CURSOR_PATHFINDING";
+ case UI_CURSOR_TOOLPATHFINDING_PATH_START: return "UI_CURSOR_PATHFINDING_START";
+ case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD: return "UI_CURSOR_PATHFINDING_START_ADD";
+ case UI_CURSOR_TOOLPATHFINDING_PATH_END: return "UI_CURSOR_PATHFINDING_END";
+ case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD: return "UI_CURSOR_PATHFINDING_END_ADD";
+ case UI_CURSOR_TOOLNO: return "UI_CURSOR_NO";
+ }
+
+ LL_ERRS() << "cursorIDToName: unknown cursor id" << id << LL_ENDL;
+
+ return "UI_CURSOR_ARROW";
}
static CursorRef gCursors[UI_CURSOR_COUNT];
@@ -1514,233 +1514,233 @@ static CursorRef gCursors[UI_CURSOR_COUNT];
static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY)
{
- // cursors are in <Application Bundle>/Contents/Resources/cursors_mac/UI_CURSOR_FOO.tif
- std::string fullpath = gDirUtilp->add(
- gDirUtilp->getAppRODataDir(),
- "cursors_mac",
- cursorIDToName(cursorid) + std::string(".tif"));
+ // cursors are in <Application Bundle>/Contents/Resources/cursors_mac/UI_CURSOR_FOO.tif
+ std::string fullpath = gDirUtilp->add(
+ gDirUtilp->getAppRODataDir(),
+ "cursors_mac",
+ cursorIDToName(cursorid) + std::string(".tif"));
- gCursors[cursorid] = createImageCursor(fullpath.c_str(), hotspotX, hotspotY);
+ gCursors[cursorid] = createImageCursor(fullpath.c_str(), hotspotX, hotspotY);
}
void LLWindowMacOSX::updateCursor()
{
- S32 result = 0;
-
- if (mDragOverrideCursor != -1)
- {
- // A drag is in progress...remember the requested cursor and we'll
- // restore it when it is done
- mCurrentCursor = mNextCursor;
- return;
- }
-
- if (mNextCursor == UI_CURSOR_ARROW
- && mBusyCount > 0)
- {
- mNextCursor = UI_CURSOR_WORKING;
- }
-
+ S32 result = 0;
+
+ if (mDragOverrideCursor != -1)
+ {
+ // A drag is in progress...remember the requested cursor and we'll
+ // restore it when it is done
+ mCurrentCursor = mNextCursor;
+ return;
+ }
+
+ if (mNextCursor == UI_CURSOR_ARROW
+ && mBusyCount > 0)
+ {
+ mNextCursor = UI_CURSOR_WORKING;
+ }
+
if(mCurrentCursor == mNextCursor)
{
if(mCursorHidden && mHideCursorPermanent && isCGCursorVisible())
{
- hideNSCursor();
+ hideNSCursor();
adjustCursorDecouple();
}
return;
}
- // RN: replace multi-drag cursors with single versions
- if (mNextCursor == UI_CURSOR_ARROWDRAGMULTI)
- {
- mNextCursor = UI_CURSOR_ARROWDRAG;
- }
- else if (mNextCursor == UI_CURSOR_ARROWCOPYMULTI)
- {
- mNextCursor = UI_CURSOR_ARROWCOPY;
- }
-
- switch(mNextCursor)
- {
- default:
- case UI_CURSOR_ARROW:
- setArrowCursor();
- if(mCursorHidden)
- {
- // Since InitCursor resets the hide level, correct for it here.
- hideNSCursor();
- }
- break;
-
- // MBW -- XXX -- Some of the standard Windows cursors have no standard Mac equivalents.
- // Find out what they look like and replicate them.
-
- // These are essentially correct
- case UI_CURSOR_WAIT: /* Apple purposely doesn't allow us to set the beachball cursor manually. Let NSApp figure out when to do this. */ break;
- case UI_CURSOR_IBEAM: setIBeamCursor(); break;
- case UI_CURSOR_CROSS: setCrossCursor(); break;
- case UI_CURSOR_HAND: setPointingHandCursor(); break;
- // case UI_CURSOR_NO: SetThemeCursor(kThemeNotAllowedCursor); break;
- case UI_CURSOR_ARROWCOPY: setCopyCursor(); break;
-
- // Double-check these
- case UI_CURSOR_NO:
- case UI_CURSOR_SIZEWE:
- case UI_CURSOR_SIZENS:
- case UI_CURSOR_SIZENWSE:
- case UI_CURSOR_SIZENESW:
- case UI_CURSOR_WORKING:
- case UI_CURSOR_TOOLGRAB:
- case UI_CURSOR_TOOLLAND:
- case UI_CURSOR_TOOLFOCUS:
- case UI_CURSOR_TOOLCREATE:
- case UI_CURSOR_ARROWDRAG:
- case UI_CURSOR_NOLOCKED:
- case UI_CURSOR_ARROWLOCKED:
- case UI_CURSOR_GRABLOCKED:
- case UI_CURSOR_PIPETTE:
- case UI_CURSOR_TOOLTRANSLATE:
- case UI_CURSOR_TOOLROTATE:
- case UI_CURSOR_TOOLSCALE:
- case UI_CURSOR_TOOLCAMERA:
- case UI_CURSOR_TOOLPAN:
- case UI_CURSOR_TOOLZOOMIN:
- case UI_CURSOR_TOOLPICKOBJECT3:
- case UI_CURSOR_TOOLPLAY:
- case UI_CURSOR_TOOLPAUSE:
- case UI_CURSOR_TOOLMEDIAOPEN:
- case UI_CURSOR_TOOLSIT:
- case UI_CURSOR_TOOLBUY:
- case UI_CURSOR_TOOLOPEN:
- case UI_CURSOR_TOOLPATHFINDING:
- case UI_CURSOR_TOOLPATHFINDING_PATH_START:
- case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD:
- case UI_CURSOR_TOOLPATHFINDING_PATH_END:
- case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD:
- case UI_CURSOR_TOOLNO:
- result = setImageCursor(gCursors[mNextCursor]);
- break;
-
- }
-
- if(result != noErr)
- {
- setArrowCursor();
- }
-
- mCurrentCursor = mNextCursor;
+ // RN: replace multi-drag cursors with single versions
+ if (mNextCursor == UI_CURSOR_ARROWDRAGMULTI)
+ {
+ mNextCursor = UI_CURSOR_ARROWDRAG;
+ }
+ else if (mNextCursor == UI_CURSOR_ARROWCOPYMULTI)
+ {
+ mNextCursor = UI_CURSOR_ARROWCOPY;
+ }
+
+ switch(mNextCursor)
+ {
+ default:
+ case UI_CURSOR_ARROW:
+ setArrowCursor();
+ if(mCursorHidden)
+ {
+ // Since InitCursor resets the hide level, correct for it here.
+ hideNSCursor();
+ }
+ break;
+
+ // MBW -- XXX -- Some of the standard Windows cursors have no standard Mac equivalents.
+ // Find out what they look like and replicate them.
+
+ // These are essentially correct
+ case UI_CURSOR_WAIT: /* Apple purposely doesn't allow us to set the beachball cursor manually. Let NSApp figure out when to do this. */ break;
+ case UI_CURSOR_IBEAM: setIBeamCursor(); break;
+ case UI_CURSOR_CROSS: setCrossCursor(); break;
+ case UI_CURSOR_HAND: setPointingHandCursor(); break;
+ // case UI_CURSOR_NO: SetThemeCursor(kThemeNotAllowedCursor); break;
+ case UI_CURSOR_ARROWCOPY: setCopyCursor(); break;
+
+ // Double-check these
+ case UI_CURSOR_NO:
+ case UI_CURSOR_SIZEWE:
+ case UI_CURSOR_SIZENS:
+ case UI_CURSOR_SIZENWSE:
+ case UI_CURSOR_SIZENESW:
+ case UI_CURSOR_WORKING:
+ case UI_CURSOR_TOOLGRAB:
+ case UI_CURSOR_TOOLLAND:
+ case UI_CURSOR_TOOLFOCUS:
+ case UI_CURSOR_TOOLCREATE:
+ case UI_CURSOR_ARROWDRAG:
+ case UI_CURSOR_NOLOCKED:
+ case UI_CURSOR_ARROWLOCKED:
+ case UI_CURSOR_GRABLOCKED:
+ case UI_CURSOR_PIPETTE:
+ case UI_CURSOR_TOOLTRANSLATE:
+ case UI_CURSOR_TOOLROTATE:
+ case UI_CURSOR_TOOLSCALE:
+ case UI_CURSOR_TOOLCAMERA:
+ case UI_CURSOR_TOOLPAN:
+ case UI_CURSOR_TOOLZOOMIN:
+ case UI_CURSOR_TOOLPICKOBJECT3:
+ case UI_CURSOR_TOOLPLAY:
+ case UI_CURSOR_TOOLPAUSE:
+ case UI_CURSOR_TOOLMEDIAOPEN:
+ case UI_CURSOR_TOOLSIT:
+ case UI_CURSOR_TOOLBUY:
+ case UI_CURSOR_TOOLOPEN:
+ case UI_CURSOR_TOOLPATHFINDING:
+ case UI_CURSOR_TOOLPATHFINDING_PATH_START:
+ case UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD:
+ case UI_CURSOR_TOOLPATHFINDING_PATH_END:
+ case UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD:
+ case UI_CURSOR_TOOLNO:
+ result = setImageCursor(gCursors[mNextCursor]);
+ break;
+
+ }
+
+ if(result != noErr)
+ {
+ setArrowCursor();
+ }
+
+ mCurrentCursor = mNextCursor;
}
ECursorType LLWindowMacOSX::getCursor() const
{
- return mCurrentCursor;
+ return mCurrentCursor;
}
void LLWindowMacOSX::initCursors()
{
- initPixmapCursor(UI_CURSOR_NO, 8, 8);
- initPixmapCursor(UI_CURSOR_WORKING, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLGRAB, 2, 14);
- initPixmapCursor(UI_CURSOR_TOOLLAND, 13, 8);
- initPixmapCursor(UI_CURSOR_TOOLFOCUS, 7, 6);
- initPixmapCursor(UI_CURSOR_TOOLCREATE, 7, 7);
- initPixmapCursor(UI_CURSOR_ARROWDRAG, 1, 1);
- initPixmapCursor(UI_CURSOR_ARROWCOPY, 1, 1);
- initPixmapCursor(UI_CURSOR_NOLOCKED, 8, 8);
- initPixmapCursor(UI_CURSOR_ARROWLOCKED, 1, 1);
- initPixmapCursor(UI_CURSOR_GRABLOCKED, 2, 14);
- initPixmapCursor(UI_CURSOR_PIPETTE, 3, 29);
- initPixmapCursor(UI_CURSOR_TOOLTRANSLATE, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLROTATE, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLSCALE, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLCAMERA, 7, 6);
- initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6);
- initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6);
+ initPixmapCursor(UI_CURSOR_NO, 8, 8);
+ initPixmapCursor(UI_CURSOR_WORKING, 1, 1);
+ initPixmapCursor(UI_CURSOR_TOOLGRAB, 2, 14);
+ initPixmapCursor(UI_CURSOR_TOOLLAND, 13, 8);
+ initPixmapCursor(UI_CURSOR_TOOLFOCUS, 7, 6);
+ initPixmapCursor(UI_CURSOR_TOOLCREATE, 7, 7);
+ initPixmapCursor(UI_CURSOR_ARROWDRAG, 1, 1);
+ initPixmapCursor(UI_CURSOR_ARROWCOPY, 1, 1);
+ initPixmapCursor(UI_CURSOR_NOLOCKED, 8, 8);
+ initPixmapCursor(UI_CURSOR_ARROWLOCKED, 1, 1);
+ initPixmapCursor(UI_CURSOR_GRABLOCKED, 2, 14);
+ initPixmapCursor(UI_CURSOR_PIPETTE, 3, 29);
+ initPixmapCursor(UI_CURSOR_TOOLTRANSLATE, 1, 1);
+ initPixmapCursor(UI_CURSOR_TOOLROTATE, 1, 1);
+ initPixmapCursor(UI_CURSOR_TOOLSCALE, 1, 1);
+ initPixmapCursor(UI_CURSOR_TOOLCAMERA, 7, 6);
+ initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6);
+ initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLZOOMOUT, 7, 6);
- initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLSIT, 20, 15);
- initPixmapCursor(UI_CURSOR_TOOLBUY, 20, 15);
- initPixmapCursor(UI_CURSOR_TOOLOPEN, 20, 15);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD, 16, 16);
- initPixmapCursor(UI_CURSOR_TOOLNO, 8, 8);
-
- initPixmapCursor(UI_CURSOR_SIZENWSE, 10, 10);
- initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10);
- initPixmapCursor(UI_CURSOR_SIZEWE, 10, 10);
- initPixmapCursor(UI_CURSOR_SIZENS, 10, 10);
+ initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1);
+ initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1);
+ initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1);
+ initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1);
+ initPixmapCursor(UI_CURSOR_TOOLSIT, 20, 15);
+ initPixmapCursor(UI_CURSOR_TOOLBUY, 20, 15);
+ initPixmapCursor(UI_CURSOR_TOOLOPEN, 20, 15);
+ initPixmapCursor(UI_CURSOR_TOOLPATHFINDING, 16, 16);
+ initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START, 16, 16);
+ initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD, 16, 16);
+ initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END, 16, 16);
+ initPixmapCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD, 16, 16);
+ initPixmapCursor(UI_CURSOR_TOOLNO, 8, 8);
+
+ initPixmapCursor(UI_CURSOR_SIZENWSE, 10, 10);
+ initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10);
+ initPixmapCursor(UI_CURSOR_SIZEWE, 10, 10);
+ initPixmapCursor(UI_CURSOR_SIZENS, 10, 10);
initPixmapCursor(UI_CURSOR_SIZEALL, 10, 10);
}
void LLWindowMacOSX::captureMouse()
{
- // By registering a global CarbonEvent handler for mouse move events, we ensure that
- // mouse events are always processed. Thus, capture and release are unnecessary.
+ // By registering a global CarbonEvent handler for mouse move events, we ensure that
+ // mouse events are always processed. Thus, capture and release are unnecessary.
}
void LLWindowMacOSX::releaseMouse()
{
- // By registering a global CarbonEvent handler for mouse move events, we ensure that
- // mouse events are always processed. Thus, capture and release are unnecessary.
+ // By registering a global CarbonEvent handler for mouse move events, we ensure that
+ // mouse events are always processed. Thus, capture and release are unnecessary.
}
void LLWindowMacOSX::hideCursor()
{
- if(!mCursorHidden)
- {
- // LL_INFOS() << "hideCursor: hiding" << LL_ENDL;
- mCursorHidden = TRUE;
- mHideCursorPermanent = TRUE;
- hideNSCursor();
- }
- else
- {
- // LL_INFOS() << "hideCursor: already hidden" << LL_ENDL;
- }
+ if(!mCursorHidden)
+ {
+ // LL_INFOS() << "hideCursor: hiding" << LL_ENDL;
+ mCursorHidden = TRUE;
+ mHideCursorPermanent = TRUE;
+ hideNSCursor();
+ }
+ else
+ {
+ // LL_INFOS() << "hideCursor: already hidden" << LL_ENDL;
+ }
- adjustCursorDecouple();
+ adjustCursorDecouple();
}
void LLWindowMacOSX::showCursor()
{
- if(mCursorHidden || !isCGCursorVisible())
- {
- // LL_INFOS() << "showCursor: showing" << LL_ENDL;
- mCursorHidden = FALSE;
- mHideCursorPermanent = FALSE;
- showNSCursor();
- }
- else
- {
- // LL_INFOS() << "showCursor: already visible" << LL_ENDL;
- }
+ if(mCursorHidden || !isCGCursorVisible())
+ {
+ // LL_INFOS() << "showCursor: showing" << LL_ENDL;
+ mCursorHidden = FALSE;
+ mHideCursorPermanent = FALSE;
+ showNSCursor();
+ }
+ else
+ {
+ // LL_INFOS() << "showCursor: already visible" << LL_ENDL;
+ }
- adjustCursorDecouple();
+ adjustCursorDecouple();
}
void LLWindowMacOSX::showCursorFromMouseMove()
{
- if (!mHideCursorPermanent)
- {
- showCursor();
- }
+ if (!mHideCursorPermanent)
+ {
+ showCursor();
+ }
}
void LLWindowMacOSX::hideCursorUntilMouseMove()
{
- if (!mHideCursorPermanent)
- {
- hideCursor();
- mHideCursorPermanent = FALSE;
- }
+ if (!mHideCursorPermanent)
+ {
+ hideCursor();
+ mHideCursorPermanent = FALSE;
+ }
}
@@ -1750,7 +1750,7 @@ void LLWindowMacOSX::hideCursorUntilMouseMove()
//
LLSplashScreenMacOSX::LLSplashScreenMacOSX()
{
- mWindow = NULL;
+ mWindow = NULL;
}
LLSplashScreenMacOSX::~LLSplashScreenMacOSX()
@@ -1759,201 +1759,201 @@ LLSplashScreenMacOSX::~LLSplashScreenMacOSX()
void LLSplashScreenMacOSX::showImpl()
{
- // This code _could_ be used to display a spash screen...
+ // This code _could_ be used to display a spash screen...
}
void LLSplashScreenMacOSX::updateImpl(const std::string& mesg)
{
- if(mWindow != NULL)
- {
- CFStringCreateWithCString(NULL, mesg.c_str(), kCFStringEncodingUTF8);
- }
+ if(mWindow != NULL)
+ {
+ CFStringCreateWithCString(NULL, mesg.c_str(), kCFStringEncodingUTF8);
+ }
}
void LLSplashScreenMacOSX::hideImpl()
{
- if(mWindow != NULL)
- {
- mWindow = NULL;
- }
+ if(mWindow != NULL)
+ {
+ mWindow = NULL;
+ }
}
S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 type)
{
- return showAlert(text, caption, type);
+ return showAlert(text, caption, type);
}
// Open a URL with the user's default web browser.
// Must begin with protocol identifier.
void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
{
- // I'm fairly certain that this is all legitimate under Apple's currently supported APIs.
-
- bool found = false;
- S32 i;
- for (i = 0; i < gURLProtocolWhitelistCount; i++)
- {
- if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos)
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- LL_WARNS() << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << LL_ENDL;
- return;
- }
-
- S32 result = 0;
- CFURLRef urlRef = NULL;
-
- LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL;
-
- CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8);
- if (stringRef)
- {
- // This will succeed if the string is a full URL, including the http://
- // Note that URLs specified this way need to be properly percent-escaped.
- urlRef = CFURLCreateWithString(NULL, stringRef, NULL);
-
- // Don't use CRURLCreateWithFileSystemPath -- only want valid URLs
-
- CFRelease(stringRef);
- }
-
- if (urlRef)
- {
- result = LSOpenCFURLRef(urlRef, NULL);
-
- if (result != noErr)
- {
- LL_INFOS() << "Error " << result << " on open." << LL_ENDL;
- }
-
- CFRelease(urlRef);
- }
- else
- {
- LL_INFOS() << "Error: couldn't create URL." << LL_ENDL;
- }
+ // I'm fairly certain that this is all legitimate under Apple's currently supported APIs.
+
+ bool found = false;
+ S32 i;
+ for (i = 0; i < gURLProtocolWhitelistCount; i++)
+ {
+ if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ LL_WARNS() << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << LL_ENDL;
+ return;
+ }
+
+ S32 result = 0;
+ CFURLRef urlRef = NULL;
+
+ LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL;
+
+ CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8);
+ if (stringRef)
+ {
+ // This will succeed if the string is a full URL, including the http://
+ // Note that URLs specified this way need to be properly percent-escaped.
+ urlRef = CFURLCreateWithString(NULL, stringRef, NULL);
+
+ // Don't use CRURLCreateWithFileSystemPath -- only want valid URLs
+
+ CFRelease(stringRef);
+ }
+
+ if (urlRef)
+ {
+ result = LSOpenCFURLRef(urlRef, NULL);
+
+ if (result != noErr)
+ {
+ LL_INFOS() << "Error " << result << " on open." << LL_ENDL;
+ }
+
+ CFRelease(urlRef);
+ }
+ else
+ {
+ LL_INFOS() << "Error: couldn't create URL." << LL_ENDL;
+ }
}
LLSD LLWindowMacOSX::getNativeKeyData()
{
- LLSD result = LLSD::emptyMap();
+ LLSD result = LLSD::emptyMap();
- if(mRawKeyEvent)
- {
+ if(mRawKeyEvent)
+ {
result["event_type"] = LLSD::Integer(mRawKeyEvent->mEventType);
result["event_modifiers"] = LLSD::Integer(mRawKeyEvent->mEventModifiers);
result["event_keycode"] = LLSD::Integer(mRawKeyEvent->mEventKeyCode);
result["event_chars"] = (mRawKeyEvent->mEventChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventChars)) : LLSD();
result["event_umodchars"] = (mRawKeyEvent->mEventUnmodChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventUnmodChars)) : LLSD();
result["event_isrepeat"] = LLSD::Boolean(mRawKeyEvent->mEventRepeat);
- }
+ }
- LL_DEBUGS() << "native key data is: " << result << LL_ENDL;
+ LL_DEBUGS() << "native key data is: " << result << LL_ENDL;
- return result;
+ return result;
}
BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
- BOOL retval = FALSE;
- OSErr error = noErr;
- NColorPickerInfo info;
-
- memset(&info, 0, sizeof(info));
- info.theColor.color.rgb.red = (UInt16)(*r * 65535.f);
- info.theColor.color.rgb.green = (UInt16)(*g * 65535.f);
- info.theColor.color.rgb.blue = (UInt16)(*b * 65535.f);
- info.placeWhere = kCenterOnMainScreen;
-
- error = NPickColor(&info);
-
- if (error == noErr)
- {
- retval = info.newColorChosen;
- if (info.newColorChosen)
- {
- *r = ((float) info.theColor.color.rgb.red) / 65535.0;
- *g = ((float) info.theColor.color.rgb.green) / 65535.0;
- *b = ((float) info.theColor.color.rgb.blue) / 65535.0;
- }
- }
-
- return (retval);
+ BOOL retval = FALSE;
+ OSErr error = noErr;
+ NColorPickerInfo info;
+
+ memset(&info, 0, sizeof(info));
+ info.theColor.color.rgb.red = (UInt16)(*r * 65535.f);
+ info.theColor.color.rgb.green = (UInt16)(*g * 65535.f);
+ info.theColor.color.rgb.blue = (UInt16)(*b * 65535.f);
+ info.placeWhere = kCenterOnMainScreen;
+
+ error = NPickColor(&info);
+
+ if (error == noErr)
+ {
+ retval = info.newColorChosen;
+ if (info.newColorChosen)
+ {
+ *r = ((float) info.theColor.color.rgb.red) / 65535.0;
+ *g = ((float) info.theColor.color.rgb.green) / 65535.0;
+ *b = ((float) info.theColor.color.rgb.blue) / 65535.0;
+ }
+ }
+
+ return (retval);
}
void *LLWindowMacOSX::getPlatformWindow()
{
- // NOTE: this will be NULL in fullscreen mode. Plan accordingly.
- return (void*)mWindow;
+ // NOTE: this will be NULL in fullscreen mode. Plan accordingly.
+ return (void*)mWindow;
}
// get a double value from a dictionary
/*
static double getDictDouble (CFDictionaryRef refDict, CFStringRef key)
{
- double double_value;
- CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key);
- if (!number_value) // if can't get a number for the dictionary
- return -1; // fail
- if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &double_value)) // or if cant convert it
- return -1; // fail
- return double_value; // otherwise return the long value
+ double double_value;
+ CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key);
+ if (!number_value) // if can't get a number for the dictionary
+ return -1; // fail
+ if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &double_value)) // or if cant convert it
+ return -1; // fail
+ return double_value; // otherwise return the long value
}*/
// get a long value from a dictionary
static long getDictLong (CFDictionaryRef refDict, CFStringRef key)
{
- long int_value;
- CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key);
- if (!number_value) // if can't get a number for the dictionary
- return -1; // fail
- if (!CFNumberGetValue(number_value, kCFNumberLongType, &int_value)) // or if cant convert it
- return -1; // fail
- return int_value; // otherwise return the long value
+ long int_value;
+ CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key);
+ if (!number_value) // if can't get a number for the dictionary
+ return -1; // fail
+ if (!CFNumberGetValue(number_value, kCFNumberLongType, &int_value)) // or if cant convert it
+ return -1; // fail
+ return int_value; // otherwise return the long value
}
void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
{
- if (preeditor != mPreeditor && !b)
- {
- // This condition may occur by a call to
- // setEnabled(BOOL) against LLTextEditor or LLLineEditor
- // when the control is not focused.
- // We need to silently ignore the case so that
- // the language input status of the focused control
- // is not disturbed.
- return;
- }
-
- // Take care of old and new preeditors.
- if (preeditor != mPreeditor || !b)
- {
- // We need to interrupt before updating mPreeditor,
- // so that the fix string from input method goes to
- // the old preeditor.
- if (mLanguageTextInputAllowed)
- {
- interruptLanguageTextInput();
- }
- mPreeditor = (b ? preeditor : NULL);
- }
-
- if (b == mLanguageTextInputAllowed)
- {
- return;
- }
- mLanguageTextInputAllowed = b;
+ if (preeditor != mPreeditor && !b)
+ {
+ // This condition may occur by a call to
+ // setEnabled(BOOL) against LLTextEditor or LLLineEditor
+ // when the control is not focused.
+ // We need to silently ignore the case so that
+ // the language input status of the focused control
+ // is not disturbed.
+ return;
+ }
+
+ // Take care of old and new preeditors.
+ if (preeditor != mPreeditor || !b)
+ {
+ // We need to interrupt before updating mPreeditor,
+ // so that the fix string from input method goes to
+ // the old preeditor.
+ if (mLanguageTextInputAllowed)
+ {
+ interruptLanguageTextInput();
+ }
+ mPreeditor = (b ? preeditor : NULL);
+ }
+
+ if (b == mLanguageTextInputAllowed)
+ {
+ return;
+ }
+ mLanguageTextInputAllowed = b;
allowDirectMarkedTextInput(b, mGLView); // mLanguageTextInputAllowed and mMarkedTextAllowed should be updated at once (by Pell Smit
}
-class sharedContext
+class sharedContext
{
public:
CGLContextObj mContext;
@@ -1963,7 +1963,7 @@ void* LLWindowMacOSX::createSharedContext()
{
sharedContext* sc = new sharedContext();
CGLCreateContext(mPixelFormat, mContext, &(sc->mContext));
-
+
if (sUseMultGL)
{
CGLEnable(mContext, kCGLCEMPEngine);
@@ -1977,23 +1977,23 @@ void LLWindowMacOSX::makeContextCurrent(void* context)
CGLSetCurrentContext(((sharedContext*)context)->mContext);
//enable multi-threaded OpenGL
- if (sUseMultGL)
- {
- CGLError cgl_err;
- CGLContextObj ctx = CGLGetCurrentContext();
-
- cgl_err = CGLEnable( ctx, kCGLCEMPEngine);
-
- if (cgl_err != kCGLNoError )
- {
- LL_INFOS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
- }
- else
- {
+ if (sUseMultGL)
+ {
+ CGLError cgl_err;
+ CGLContextObj ctx = CGLGetCurrentContext();
+
+ cgl_err = CGLEnable( ctx, kCGLCEMPEngine);
+
+ if (cgl_err != kCGLNoError )
+ {
+ LL_INFOS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
+ }
+ else
+ {
LL_INFOS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
- }
- }
-
+ }
+ }
+
}
void LLWindowMacOSX::destroySharedContext(void* context)
@@ -2016,166 +2016,171 @@ void LLWindowMacOSX::toggleVSync(bool enable_vsync)
{
frames_per_swap = 1;
}
-
+
CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap);
}
void LLWindowMacOSX::interruptLanguageTextInput()
{
- commitCurrentPreedit(mGLView);
+ commitCurrentPreedit(mGLView);
}
std::vector<std::string> LLWindowMacOSX::getDisplaysResolutionList()
{
- std::vector<std::string> resolution_list;
-
- CGDirectDisplayID display_ids[10];
- uint32_t found_displays = 0;
- CGError err = CGGetActiveDisplayList(10, display_ids, &found_displays);
-
- if (kCGErrorSuccess != err)
- {
- LL_WARNS() << "Couldn't get a list of active displays" << LL_ENDL;
- return std::vector<std::string>();
- }
-
- for (uint32_t i = 0; i < found_displays; i++)
- {
- S32 monitor_width = CGDisplayPixelsWide(display_ids[i]);
- S32 monitor_height = CGDisplayPixelsHigh(display_ids[i]);
-
- std::ostringstream sstream;
- sstream << monitor_width << "x" << monitor_height;;
- std::string res = sstream.str();
-
- resolution_list.push_back(res);
- }
-
- return resolution_list;
+ std::vector<std::string> resolution_list;
+
+ CGDirectDisplayID display_ids[10];
+ uint32_t found_displays = 0;
+ CGError err = CGGetActiveDisplayList(10, display_ids, &found_displays);
+
+ if (kCGErrorSuccess != err)
+ {
+ LL_WARNS() << "Couldn't get a list of active displays" << LL_ENDL;
+ return std::vector<std::string>();
+ }
+
+ for (uint32_t i = 0; i < found_displays; i++)
+ {
+ S32 monitor_width = CGDisplayPixelsWide(display_ids[i]);
+ S32 monitor_height = CGDisplayPixelsHigh(display_ids[i]);
+
+ std::ostringstream sstream;
+ sstream << monitor_width << "x" << monitor_height;;
+ std::string res = sstream.str();
+
+ resolution_list.push_back(res);
+ }
+
+ return resolution_list;
}
//static
std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList()
{
- // Fonts previously in getFontListSans() have moved to fonts.xml.
- return std::vector<std::string>();
+ // Fonts previously in getFontListSans() have moved to fonts.xml.
+ return std::vector<std::string>();
}
// static
MASK LLWindowMacOSX::modifiersToMask(S16 modifiers)
{
- MASK mask = 0;
- if(modifiers & MAC_SHIFT_KEY) { mask |= MASK_SHIFT; }
- if(modifiers & (MAC_CMD_KEY | MAC_CTRL_KEY)) { mask |= MASK_CONTROL; }
- if(modifiers & MAC_ALT_KEY) { mask |= MASK_ALT; }
- return mask;
+ MASK mask = 0;
+ if(modifiers & MAC_SHIFT_KEY) { mask |= MASK_SHIFT; }
+ if(modifiers & (MAC_CMD_KEY | MAC_CTRL_KEY)) { mask |= MASK_CONTROL; }
+ if(modifiers & MAC_ALT_KEY) { mask |= MASK_ALT; }
+ return mask;
}
F32 LLWindowMacOSX::getSystemUISize()
{
- return gHiDPISupport ? ::getDeviceUnitSize(mGLView) : LLWindow::getSystemUISize();
+ return gHiDPISupport ? ::getDeviceUnitSize(mGLView) : LLWindow::getSystemUISize();
+}
+
+void LLWindowMacOSX::openFolder(const std::string &path)
+{
+ openFolderWithFinder(path.c_str());
}
#if LL_OS_DRAGDROP_ENABLED
/*
S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
- void * handlerRefCon, DragRef drag)
+ void * handlerRefCon, DragRef drag)
{
- S16 result = 0;
- LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
+ S16 result = 0;
+ LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
- LL_DEBUGS() << "drag tracking handler, message = " << message << LL_ENDL;
+ LL_DEBUGS() << "drag tracking handler, message = " << message << LL_ENDL;
- switch(message)
- {
- case kDragTrackingInWindow:
- result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_TRACK);
- break;
+ switch(message)
+ {
+ case kDragTrackingInWindow:
+ result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_TRACK);
+ break;
- case kDragTrackingEnterHandler:
- result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_START_TRACKING);
- break;
+ case kDragTrackingEnterHandler:
+ result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_START_TRACKING);
+ break;
- case kDragTrackingLeaveHandler:
- result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_STOP_TRACKING);
- break;
+ case kDragTrackingLeaveHandler:
+ result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_STOP_TRACKING);
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
- return result;
+ return result;
}
OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon,
- DragRef drag)
+ DragRef drag)
{
- LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
- return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED);
+ LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
+ return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED);
}
*/
void LLWindowMacOSX::handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action)
{
- MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers());
-
- float mouse_point[2];
- // This will return the mouse point in window coords
- getCursorPos(mWindow, mouse_point);
- LLCoordWindow window_coords(mouse_point[0], mouse_point[1]);
- LLCoordGL gl_pos;
- convertCoords(window_coords, &gl_pos);
-
- if(!url.empty())
- {
- LLWindowCallbacks::DragNDropResult res =
- mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url);
-
- switch (res) {
- case LLWindowCallbacks::DND_NONE: // No drop allowed
- if (action == LLWindowCallbacks::DNDA_TRACK)
- {
- mDragOverrideCursor = 0;
- }
- else {
- mDragOverrideCursor = -1;
- }
- break;
- case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation
- mDragOverrideCursor = UI_CURSOR_NO;
- break;
- case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation
- mDragOverrideCursor = UI_CURSOR_ARROWCOPY;
- break;
- default:
- mDragOverrideCursor = -1;
- break;
- }
- // This overrides the cursor being set by setCursor.
- // This is a bit of a hack workaround because lots of areas
- // within the viewer just blindly set the cursor.
- if (mDragOverrideCursor == -1)
- {
- // Restore the cursor
- ECursorType temp_cursor = mCurrentCursor;
- // get around the "setting the same cursor" code in setCursor()
- mCurrentCursor = UI_CURSOR_COUNT;
- setCursor(temp_cursor);
- }
- else {
- // Override the cursor
- switch (mDragOverrideCursor) {
- case 0:
- setArrowCursor();
- break;
- case UI_CURSOR_NO:
- setNotAllowedCursor();
- case UI_CURSOR_ARROWCOPY:
- setCopyCursor();
- default:
- break;
- };
- }
- }
+ MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers());
+
+ float mouse_point[2];
+ // This will return the mouse point in window coords
+ getCursorPos(mWindow, mouse_point);
+ LLCoordWindow window_coords(mouse_point[0], mouse_point[1]);
+ LLCoordGL gl_pos;
+ convertCoords(window_coords, &gl_pos);
+
+ if(!url.empty())
+ {
+ LLWindowCallbacks::DragNDropResult res =
+ mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url);
+
+ switch (res) {
+ case LLWindowCallbacks::DND_NONE: // No drop allowed
+ if (action == LLWindowCallbacks::DNDA_TRACK)
+ {
+ mDragOverrideCursor = 0;
+ }
+ else {
+ mDragOverrideCursor = -1;
+ }
+ break;
+ case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation
+ mDragOverrideCursor = UI_CURSOR_NO;
+ break;
+ case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation
+ mDragOverrideCursor = UI_CURSOR_ARROWCOPY;
+ break;
+ default:
+ mDragOverrideCursor = -1;
+ break;
+ }
+ // This overrides the cursor being set by setCursor.
+ // This is a bit of a hack workaround because lots of areas
+ // within the viewer just blindly set the cursor.
+ if (mDragOverrideCursor == -1)
+ {
+ // Restore the cursor
+ ECursorType temp_cursor = mCurrentCursor;
+ // get around the "setting the same cursor" code in setCursor()
+ mCurrentCursor = UI_CURSOR_COUNT;
+ setCursor(temp_cursor);
+ }
+ else {
+ // Override the cursor
+ switch (mDragOverrideCursor) {
+ case 0:
+ setArrowCursor();
+ break;
+ case UI_CURSOR_NO:
+ setNotAllowedCursor();
+ case UI_CURSOR_ARROWCOPY:
+ setCopyCursor();
+ default:
+ break;
+ };
+ }
+ }
}
#endif // LL_OS_DRAGDROP_ENABLED
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index 196a284ac3..5f728fb72e 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llwindowmacosx.h
* @brief Mac implementation of LLWindow class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -44,94 +44,96 @@
class LLWindowMacOSX : public LLWindow
{
public:
- void show() override;
- void hide() override;
- void close() override;
- BOOL getVisible() override;
- BOOL getMinimized() override;
- BOOL getMaximized() override;
- BOOL maximize() override;
- void minimize() override;
- void restore() override;
- BOOL getFullscreen();
- BOOL getPosition(LLCoordScreen *position) override;
- BOOL getSize(LLCoordScreen *size) override;
- BOOL getSize(LLCoordWindow *size) override;
- BOOL setPosition(LLCoordScreen position) override;
- BOOL setSizeImpl(LLCoordScreen size) override;
- BOOL setSizeImpl(LLCoordWindow size) override;
- BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) override;
- BOOL setCursorPosition(LLCoordWindow position) override;
- BOOL getCursorPosition(LLCoordWindow *position) override;
- void showCursor() override;
- void hideCursor() override;
- void showCursorFromMouseMove() override;
- void hideCursorUntilMouseMove() override;
- BOOL isCursorHidden() override;
- void updateCursor() override;
- ECursorType getCursor() const override;
- void captureMouse() override;
- void releaseMouse() override;
- void setMouseClipping( BOOL b ) override;
- BOOL isClipboardTextAvailable() override;
- BOOL pasteTextFromClipboard(LLWString &dst) override;
- BOOL copyTextToClipboard(const LLWString & src) override;
- void flashIcon(F32 seconds) override;
- F32 getGamma() override;
- BOOL setGamma(const F32 gamma) override; // Set the gamma
- U32 getFSAASamples() override;
- void setFSAASamples(const U32 fsaa_samples) override;
- BOOL restoreGamma() override; // Restore original gamma table (before updating gamma)
- ESwapMethod getSwapMethod() override { return mSwapMethod; }
- void gatherInput() override;
- void delayInputProcessing() override {};
- void swapBuffers() override;
-
- // handy coordinate space conversion routines
- BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override;
- BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override;
- BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override;
- BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override;
- BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override;
- BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override;
-
- LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override;
- F32 getNativeAspectRatio() override;
- F32 getPixelAspectRatio() override;
- void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
-
- // query VRAM usage
+ void show() override;
+ void hide() override;
+ void close() override;
+ BOOL getVisible() override;
+ BOOL getMinimized() override;
+ BOOL getMaximized() override;
+ BOOL maximize() override;
+ void minimize() override;
+ void restore() override;
+ BOOL getFullscreen();
+ BOOL getPosition(LLCoordScreen *position) override;
+ BOOL getSize(LLCoordScreen *size) override;
+ BOOL getSize(LLCoordWindow *size) override;
+ BOOL setPosition(LLCoordScreen position) override;
+ BOOL setSizeImpl(LLCoordScreen size) override;
+ BOOL setSizeImpl(LLCoordWindow size) override;
+ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) override;
+ BOOL setCursorPosition(LLCoordWindow position) override;
+ BOOL getCursorPosition(LLCoordWindow *position) override;
+ void showCursor() override;
+ void hideCursor() override;
+ void showCursorFromMouseMove() override;
+ void hideCursorUntilMouseMove() override;
+ BOOL isCursorHidden() override;
+ void updateCursor() override;
+ ECursorType getCursor() const override;
+ void captureMouse() override;
+ void releaseMouse() override;
+ void setMouseClipping( BOOL b ) override;
+ BOOL isClipboardTextAvailable() override;
+ BOOL pasteTextFromClipboard(LLWString &dst) override;
+ BOOL copyTextToClipboard(const LLWString & src) override;
+ void flashIcon(F32 seconds) override;
+ F32 getGamma() override;
+ BOOL setGamma(const F32 gamma) override; // Set the gamma
+ U32 getFSAASamples() override;
+ void setFSAASamples(const U32 fsaa_samples) override;
+ BOOL restoreGamma() override; // Restore original gamma table (before updating gamma)
+ ESwapMethod getSwapMethod() override { return mSwapMethod; }
+ void gatherInput() override;
+ void delayInputProcessing() override {};
+ void swapBuffers() override;
+
+ // handy coordinate space conversion routines
+ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override;
+ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override;
+ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override;
+ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override;
+ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override;
+ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override;
+
+ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override;
+ F32 getNativeAspectRatio() override;
+ F32 getPixelAspectRatio() override;
+ void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
+
+ // query VRAM usage
/*virtual*/ U32 getAvailableVRAMMegabytes() override;
- void beforeDialog() override;
- void afterDialog() override;
-
- BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
-
- void *getPlatformWindow() override;
- void bringToFront() override {};
-
- void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) override;
- void interruptLanguageTextInput() override;
- void spawnWebBrowser(const std::string& escaped_url, bool async) override;
- F32 getSystemUISize() override;
-
- static std::vector<std::string> getDisplaysResolutionList();
-
- static std::vector<std::string> getDynamicFallbackFontList();
-
- // Provide native key event data
- LLSD getNativeKeyData() override;
-
- void* getWindow() { return mWindow; }
- LLWindowCallbacks* getCallbacks() { return mCallbacks; }
- LLPreeditor* getPreeditor() { return mPreeditor; }
-
- void updateMouseDeltas(float* deltas);
- void getMouseDeltas(float* delta);
-
- void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action);
-
+ void beforeDialog() override;
+ void afterDialog() override;
+
+ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
+
+ void *getPlatformWindow() override;
+ void bringToFront() override {};
+
+ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) override;
+ void interruptLanguageTextInput() override;
+ void spawnWebBrowser(const std::string& escaped_url, bool async) override;
+ F32 getSystemUISize() override;
+
+ void openFolder(const std::string &path) override;
+
+ static std::vector<std::string> getDisplaysResolutionList();
+
+ static std::vector<std::string> getDynamicFallbackFontList();
+
+ // Provide native key event data
+ LLSD getNativeKeyData() override;
+
+ void* getWindow() { return mWindow; }
+ LLWindowCallbacks* getCallbacks() { return mCallbacks; }
+ LLPreeditor* getPreeditor() { return mPreeditor; }
+
+ void updateMouseDeltas(float* deltas);
+ void getMouseDeltas(float* delta);
+
+ void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action);
+
bool allowsLanguageInput() { return mLanguageTextInputAllowed; }
//create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread
@@ -146,29 +148,29 @@ public:
void toggleVSync(bool enable_vsync) override;
protected:
- LLWindowMacOSX(LLWindowCallbacks* callbacks,
- const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
- BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth,
- U32 fsaa_samples);
- ~LLWindowMacOSX();
-
- void initCursors();
- BOOL isValid() override;
- void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
+ LLWindowMacOSX(LLWindowCallbacks* callbacks,
+ const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
+ BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl,
+ BOOL ignore_pixel_depth,
+ U32 fsaa_samples);
+ ~LLWindowMacOSX();
+ void initCursors();
+ BOOL isValid() override;
+ void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
- // Changes display resolution. Returns true if successful
- BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
- // Go back to last fullscreen display resolution.
- BOOL setFullscreenResolution();
+ // Changes display resolution. Returns true if successful
+ BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
- // Restore the display resolution to its value before we ran the app.
- BOOL resetDisplayResolution();
+ // Go back to last fullscreen display resolution.
+ BOOL setFullscreenResolution();
- BOOL shouldPostQuit() { return mPostQuit; }
+ // Restore the display resolution to its value before we ran the app.
+ BOOL resetDisplayResolution();
+ BOOL shouldPostQuit() { return mPostQuit; }
+
//Satisfy MAINT-3135 and MAINT-3288 with a flag.
/*virtual */ void setOldResize(bool oldresize) override {setResizeMode(oldresize, mGLView); }
@@ -176,81 +178,81 @@ private:
void restoreGLContext();
protected:
- //
- // Platform specific methods
- //
-
- // create or re-create the GL context/window. Called from the constructor and switchContext().
- BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL enable_vsync);
- void destroyContext();
- void setupFailure(const std::string& text, const std::string& caption, U32 type);
- void adjustCursorDecouple(bool warpingMouse = false);
- static MASK modifiersToMask(S16 modifiers);
-
+ //
+ // Platform specific methods
+ //
+
+ // create or re-create the GL context/window. Called from the constructor and switchContext().
+ BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL enable_vsync);
+ void destroyContext();
+ void setupFailure(const std::string& text, const std::string& caption, U32 type);
+ void adjustCursorDecouple(bool warpingMouse = false);
+ static MASK modifiersToMask(S16 modifiers);
+
#if LL_OS_DRAGDROP_ENABLED
-
- //static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
- //static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
-
-
+
+ //static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
+ //static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
+
+
#endif // LL_OS_DRAGDROP_ENABLED
-
- //
- // Platform specific variables
- //
-
- // Use generic pointers here. This lets us do some funky Obj-C interop using Obj-C objects without having to worry about any compilation problems that may arise.
- NSWindowRef mWindow;
- GLViewRef mGLView;
- CGLContextObj mContext;
- CGLPixelFormatObj mPixelFormat;
- CGDirectDisplayID mDisplay;
-
- LLRect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
- std::string mWindowTitle;
- double mOriginalAspectRatio;
- BOOL mSimulatedRightClick;
- U32 mLastModifiers;
- BOOL mHandsOffEvents; // When true, temporarially disable CarbonEvent processing.
- // Used to allow event processing when putting up dialogs in fullscreen mode.
- BOOL mCursorDecoupled;
- S32 mCursorLastEventDeltaX;
- S32 mCursorLastEventDeltaY;
- BOOL mCursorIgnoreNextDelta;
- BOOL mNeedsResize; // Constructor figured out the window is too big, it needs a resize.
- LLCoordScreen mNeedsResizeSize;
- F32 mOverrideAspectRatio;
- BOOL mMaximized;
- BOOL mMinimized;
- U32 mFSAASamples;
- BOOL mForceRebuild;
-
- S32 mDragOverrideCursor;
-
- // Input method management through Text Service Manager.
- BOOL mLanguageTextInputAllowed;
- LLPreeditor* mPreeditor;
-
+
+ //
+ // Platform specific variables
+ //
+
+ // Use generic pointers here. This lets us do some funky Obj-C interop using Obj-C objects without having to worry about any compilation problems that may arise.
+ NSWindowRef mWindow;
+ GLViewRef mGLView;
+ CGLContextObj mContext;
+ CGLPixelFormatObj mPixelFormat;
+ CGDirectDisplayID mDisplay;
+
+ LLRect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
+ std::string mWindowTitle;
+ double mOriginalAspectRatio;
+ BOOL mSimulatedRightClick;
+ U32 mLastModifiers;
+ BOOL mHandsOffEvents; // When true, temporarially disable CarbonEvent processing.
+ // Used to allow event processing when putting up dialogs in fullscreen mode.
+ BOOL mCursorDecoupled;
+ S32 mCursorLastEventDeltaX;
+ S32 mCursorLastEventDeltaY;
+ BOOL mCursorIgnoreNextDelta;
+ BOOL mNeedsResize; // Constructor figured out the window is too big, it needs a resize.
+ LLCoordScreen mNeedsResizeSize;
+ F32 mOverrideAspectRatio;
+ BOOL mMaximized;
+ BOOL mMinimized;
+ U32 mFSAASamples;
+ BOOL mForceRebuild;
+
+ S32 mDragOverrideCursor;
+
+ // Input method management through Text Service Manager.
+ BOOL mLanguageTextInputAllowed;
+ LLPreeditor* mPreeditor;
+
public:
- static BOOL sUseMultGL;
-
- friend class LLWindowManager;
+ static BOOL sUseMultGL;
+ friend class LLWindowManager;
+
};
class LLSplashScreenMacOSX : public LLSplashScreen
{
public:
- LLSplashScreenMacOSX();
- virtual ~LLSplashScreenMacOSX();
+ LLSplashScreenMacOSX();
+ virtual ~LLSplashScreenMacOSX();
- void showImpl();
- void updateImpl(const std::string& mesg);
- void hideImpl();
+ void showImpl();
+ void updateImpl(const std::string& mesg);
+ void hideImpl();
private:
- WindowRef mWindow;
+ WindowRef mWindow;
};
S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 type);
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 8670298f46..dd776e5a0f 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llwindowwin32.cpp
* @brief Platform-dependent implementation of llwindow
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -53,7 +53,7 @@
#include <commdlg.h>
#include <WinUser.h>
#include <mapi.h>
-#include <process.h> // for _spawn
+#include <process.h> // for _spawn
#include <shellapi.h>
#include <fstream>
#include <Imm.h>
@@ -75,10 +75,10 @@
#pragma comment(lib, "dxguid.lib") // needed for llurlentry test to build on some systems
#pragma comment(lib, "dinput8")
-const S32 MAX_MESSAGE_PER_UPDATE = 20;
-const S32 BITS_PER_PIXEL = 32;
-const S32 MAX_NUM_RESOLUTIONS = 32;
-const F32 ICON_FLASH_TIME = 0.5f;
+const S32 MAX_MESSAGE_PER_UPDATE = 20;
+const S32 BITS_PER_PIXEL = 32;
+const S32 MAX_NUM_RESOLUTIONS = 32;
+const F32 ICON_FLASH_TIME = 0.5f;
#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0
@@ -114,16 +114,16 @@ LLW32MsgCallback gAsyncMsgCallback = NULL;
#ifndef DPI_ENUMS_DECLARED
typedef enum PROCESS_DPI_AWARENESS {
- PROCESS_DPI_UNAWARE = 0,
- PROCESS_SYSTEM_DPI_AWARE = 1,
- PROCESS_PER_MONITOR_DPI_AWARE = 2
+ PROCESS_DPI_UNAWARE = 0,
+ PROCESS_SYSTEM_DPI_AWARE = 1,
+ PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;
typedef enum MONITOR_DPI_TYPE {
- MDT_EFFECTIVE_DPI = 0,
- MDT_ANGULAR_DPI = 1,
- MDT_RAW_DPI = 2,
- MDT_DEFAULT = MDT_EFFECTIVE_DPI
+ MDT_EFFECTIVE_DPI = 0,
+ MDT_ANGULAR_DPI = 1,
+ MDT_RAW_DPI = 2,
+ MDT_DEFAULT = MDT_EFFECTIVE_DPI
} MONITOR_DPI_TYPE;
#endif
@@ -131,14 +131,14 @@ typedef enum MONITOR_DPI_TYPE {
typedef HRESULT(STDAPICALLTYPE *SetProcessDpiAwarenessType)(_In_ PROCESS_DPI_AWARENESS value);
typedef HRESULT(STDAPICALLTYPE *GetProcessDpiAwarenessType)(
- _In_ HANDLE hprocess,
- _Out_ PROCESS_DPI_AWARENESS *value);
+ _In_ HANDLE hprocess,
+ _Out_ PROCESS_DPI_AWARENESS *value);
typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)(
- _In_ HMONITOR hmonitor,
- _In_ MONITOR_DPI_TYPE dpiType,
- _Out_ UINT *dpiX,
- _Out_ UINT *dpiY);
+ _In_ HMONITOR hmonitor,
+ _In_ MONITOR_DPI_TYPE dpiType,
+ _Out_ UINT *dpiX,
+ _Out_ UINT *dpiY);
//
// LLWindowWin32
@@ -146,19 +146,19 @@ typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)(
void show_window_creation_error(const std::string& title)
{
- LL_WARNS("Window") << title << LL_ENDL;
+ LL_WARNS("Window") << title << LL_ENDL;
}
HGLRC SafeCreateContext(HDC &hdc)
{
- __try
- {
- return wglCreateContext(hdc);
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- return NULL;
- }
+ __try
+ {
+ return wglCreateContext(hdc);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ return NULL;
+ }
}
GLuint SafeChoosePixelFormat(HDC &hdc, const PIXELFORMATDESCRIPTOR *ppfd)
@@ -180,11 +180,11 @@ GLuint SafeChoosePixelFormat(HDC &hdc, const PIXELFORMATDESCRIPTOR *ppfd)
//static
BOOL LLWindowWin32::sIsClassRegistered = FALSE;
-BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE;
-BOOL LLWindowWin32::sWinIMEOpened = FALSE;
-HKL LLWindowWin32::sWinInputLocale = 0;
-DWORD LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE;
-DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC;
+BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE;
+BOOL LLWindowWin32::sWinIMEOpened = FALSE;
+HKL LLWindowWin32::sWinInputLocale = 0;
+DWORD LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE;
+DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC;
LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1);
// The following class LLWinImm delegates Windows IMM APIs.
@@ -196,110 +196,110 @@ LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1);
class LLWinImm
{
public:
- static bool isAvailable() { return true; }
+ static bool isAvailable() { return true; }
public:
- // Wrappers for IMM API.
- static BOOL isIME(HKL hkl);
- static HIMC getContext(HWND hwnd);
- static BOOL releaseContext(HWND hwnd, HIMC himc);
- static BOOL getOpenStatus(HIMC himc);
- static BOOL setOpenStatus(HIMC himc, BOOL status);
- static BOOL getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);
- static BOOL setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);
- static BOOL getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
- static BOOL setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
- static LONG getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length);
- static BOOL setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength);
- static BOOL setCompositionFont(HIMC himc, LPLOGFONTW logfont);
- static BOOL setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form);
- static BOOL notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value);
+ // Wrappers for IMM API.
+ static BOOL isIME(HKL hkl);
+ static HIMC getContext(HWND hwnd);
+ static BOOL releaseContext(HWND hwnd, HIMC himc);
+ static BOOL getOpenStatus(HIMC himc);
+ static BOOL setOpenStatus(HIMC himc, BOOL status);
+ static BOOL getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence);
+ static BOOL setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence);
+ static BOOL getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
+ static BOOL setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form);
+ static LONG getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length);
+ static BOOL setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength);
+ static BOOL setCompositionFont(HIMC himc, LPLOGFONTW logfont);
+ static BOOL setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form);
+ static BOOL notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value);
};
-// static
-BOOL LLWinImm::isIME(HKL hkl)
-{
- return ImmIsIME(hkl);
+// static
+BOOL LLWinImm::isIME(HKL hkl)
+{
+ return ImmIsIME(hkl);
}
-// static
-HIMC LLWinImm::getContext(HWND hwnd)
+// static
+HIMC LLWinImm::getContext(HWND hwnd)
{
- return ImmGetContext(hwnd);
+ return ImmGetContext(hwnd);
}
-//static
-BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc)
-{
- return ImmReleaseContext(hwnd, himc);
+//static
+BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc)
+{
+ return ImmReleaseContext(hwnd, himc);
}
-// static
-BOOL LLWinImm::getOpenStatus(HIMC himc)
-{
- return ImmGetOpenStatus(himc);
+// static
+BOOL LLWinImm::getOpenStatus(HIMC himc)
+{
+ return ImmGetOpenStatus(himc);
}
-// static
-BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status)
-{
- return ImmSetOpenStatus(himc, status);
+// static
+BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status)
+{
+ return ImmSetOpenStatus(himc, status);
}
-// static
-BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)
-{
- return ImmGetConversionStatus(himc, conversion, sentence);
+// static
+BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)
+{
+ return ImmGetConversionStatus(himc, conversion, sentence);
}
-// static
-BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)
-{
- return ImmSetConversionStatus(himc, conversion, sentence);
+// static
+BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)
+{
+ return ImmSetConversionStatus(himc, conversion, sentence);
}
-// static
-BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
-{
- return ImmGetCompositionWindow(himc, form);
+// static
+BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
+{
+ return ImmGetCompositionWindow(himc, form);
}
-// static
-BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
-{
- return ImmSetCompositionWindow(himc, form);
+// static
+BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
+{
+ return ImmSetCompositionWindow(himc, form);
}
-// static
-LONG LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length)
-{
- return ImmGetCompositionString(himc, index, data, length);
+// static
+LONG LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length)
+{
+ return ImmGetCompositionString(himc, index, data, length);
}
-// static
-BOOL LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)
-{
- return ImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);
+// static
+BOOL LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)
+{
+ return ImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);
}
-// static
-BOOL LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)
-{
- return ImmSetCompositionFont(himc, pFont);
+// static
+BOOL LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)
+{
+ return ImmSetCompositionFont(himc, pFont);
}
-// static
-BOOL LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)
-{
- return ImmSetCandidateWindow(himc, form);
+// static
+BOOL LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)
+{
+ return ImmSetCandidateWindow(himc, form);
}
-// static
-BOOL LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)
-{
- return ImmNotifyIME(himc, action, index, value);
+// static
+BOOL LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)
+{
+ return ImmNotifyIME(himc, action, index, value);
}
@@ -308,31 +308,31 @@ class LLMonitorInfo
{
public:
- std::vector<std::string> getResolutionsList() { return mResList; }
+ std::vector<std::string> getResolutionsList() { return mResList; }
- LLMonitorInfo()
- {
- EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this);
- }
+ LLMonitorInfo()
+ {
+ EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this);
+ }
private:
- static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
- {
- int monitor_width = lprcMonitor->right - lprcMonitor->left;
- int monitor_height = lprcMonitor->bottom - lprcMonitor->top;
-
- std::ostringstream sstream;
- sstream << monitor_width << "x" << monitor_height;;
- std::string res = sstream.str();
+ static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
+ {
+ int monitor_width = lprcMonitor->right - lprcMonitor->left;
+ int monitor_height = lprcMonitor->bottom - lprcMonitor->top;
+
+ std::ostringstream sstream;
+ sstream << monitor_width << "x" << monitor_height;;
+ std::string res = sstream.str();
- LLMonitorInfo* pThis = reinterpret_cast<LLMonitorInfo*>(pData);
- pThis->mResList.push_back(res);
+ LLMonitorInfo* pThis = reinterpret_cast<LLMonitorInfo*>(pData);
+ pThis->mResList.push_back(res);
- return TRUE;
- }
+ return TRUE;
+ }
- std::vector<std::string> mResList;
+ std::vector<std::string> mResList;
};
static LLMonitorInfo sMonitorInfo;
@@ -363,7 +363,7 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
// initialzie DXGI adapter (for querying available VRAM)
void initDX();
-
+
// initialize D3D (if DXGI cannot be used)
void initD3D();
@@ -437,28 +437,28 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
- const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
- S32 height, U32 flags,
- BOOL fullscreen, BOOL clearBg,
- BOOL enable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth,
- U32 fsaa_samples,
+ const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
+ S32 height, U32 flags,
+ BOOL fullscreen, BOOL clearBg,
+ BOOL enable_vsync, BOOL use_gl,
+ BOOL ignore_pixel_depth,
+ U32 fsaa_samples,
U32 max_cores,
U32 max_vram,
F32 max_gl_version)
- :
- LLWindow(callbacks, fullscreen, flags),
- mMaxGLVersion(max_gl_version),
+ :
+ LLWindow(callbacks, fullscreen, flags),
+ mMaxGLVersion(max_gl_version),
mMaxCores(max_cores)
{
sMainThreadId = LLThread::currentID();
mWindowThread = new LLWindowWin32Thread();
mWindowThread->mMaxVRAM = max_vram;
- //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways
- LoadLibrary(L"opengl32.dll");
-
-
+ //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways
+ LoadLibrary(L"opengl32.dll");
+
+
if (mMaxCores != 0)
{
HANDLE hProcess = GetCurrentProcess();
@@ -530,76 +530,76 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
#endif
- mFSAASamples = fsaa_samples;
- mIconResource = gIconResource;
- mOverrideAspectRatio = 0.f;
- mNativeAspectRatio = 0.f;
- mInputProcessingPaused = FALSE;
- mPreeditor = NULL;
- mKeyCharCode = 0;
- mKeyScanCode = 0;
- mKeyVirtualKey = 0;
- mhDC = NULL;
- mhRC = NULL;
- memset(mCurrentGammaRamp, 0, sizeof(mCurrentGammaRamp));
- memset(mPrevGammaRamp, 0, sizeof(mPrevGammaRamp));
- mCustomGammaSet = FALSE;
- mWindowHandle = NULL;
+ mFSAASamples = fsaa_samples;
+ mIconResource = gIconResource;
+ mOverrideAspectRatio = 0.f;
+ mNativeAspectRatio = 0.f;
+ mInputProcessingPaused = FALSE;
+ mPreeditor = NULL;
+ mKeyCharCode = 0;
+ mKeyScanCode = 0;
+ mKeyVirtualKey = 0;
+ mhDC = NULL;
+ mhRC = NULL;
+ memset(mCurrentGammaRamp, 0, sizeof(mCurrentGammaRamp));
+ memset(mPrevGammaRamp, 0, sizeof(mPrevGammaRamp));
+ mCustomGammaSet = FALSE;
+ mWindowHandle = NULL;
mRect = {0, 0, 0, 0};
mClientRect = {0, 0, 0, 0};
-
- if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &mMouseVanish, 0))
- {
- mMouseVanish = TRUE;
- }
-
- // Initialize the keyboard
- gKeyboard = new LLKeyboardWin32();
- gKeyboard->setCallbacks(callbacks);
-
- // Initialize the Drag and Drop functionality
- mDragDrop = new LLDragDropWin32;
-
- // Initialize (boot strap) the Language text input management,
- // based on the system's (user's) default settings.
- allowLanguageTextInput(mPreeditor, FALSE);
-
- WNDCLASS wc;
- RECT window_rect;
-
- // Set the window title
- if (title.empty())
- {
- mWindowTitle = new WCHAR[50];
- wsprintf(mWindowTitle, L"OpenGL Window");
- }
- else
- {
- mWindowTitle = new WCHAR[256]; // Assume title length < 255 chars.
- mbstowcs(mWindowTitle, title.c_str(), 255);
- mWindowTitle[255] = 0;
- }
-
- // Set the window class name
- if (name.empty())
- {
- mWindowClassName = new WCHAR[50];
- wsprintf(mWindowClassName, L"OpenGL Window");
- }
- else
- {
- mWindowClassName = new WCHAR[256]; // Assume title length < 255 chars.
- mbstowcs(mWindowClassName, name.c_str(), 255);
- mWindowClassName[255] = 0;
- }
-
-
- // We're not clipping yet
- SetRect( &mOldMouseClip, 0, 0, 0, 0 );
-
- // Make an instance of our window then define the window class
- mhInstance = GetModuleHandle(NULL);
+
+ if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &mMouseVanish, 0))
+ {
+ mMouseVanish = TRUE;
+ }
+
+ // Initialize the keyboard
+ gKeyboard = new LLKeyboardWin32();
+ gKeyboard->setCallbacks(callbacks);
+
+ // Initialize the Drag and Drop functionality
+ mDragDrop = new LLDragDropWin32;
+
+ // Initialize (boot strap) the Language text input management,
+ // based on the system's (user's) default settings.
+ allowLanguageTextInput(mPreeditor, FALSE);
+
+ WNDCLASS wc;
+ RECT window_rect;
+
+ // Set the window title
+ if (title.empty())
+ {
+ mWindowTitle = new WCHAR[50];
+ wsprintf(mWindowTitle, L"OpenGL Window");
+ }
+ else
+ {
+ mWindowTitle = new WCHAR[256]; // Assume title length < 255 chars.
+ mbstowcs(mWindowTitle, title.c_str(), 255);
+ mWindowTitle[255] = 0;
+ }
+
+ // Set the window class name
+ if (name.empty())
+ {
+ mWindowClassName = new WCHAR[50];
+ wsprintf(mWindowClassName, L"OpenGL Window");
+ }
+ else
+ {
+ mWindowClassName = new WCHAR[256]; // Assume title length < 255 chars.
+ mbstowcs(mWindowClassName, name.c_str(), 255);
+ mWindowClassName[255] = 0;
+ }
+
+
+ // We're not clipping yet
+ SetRect( &mOldMouseClip, 0, 0, 0, 0 );
+
+ // Make an instance of our window then define the window class
+ mhInstance = GetModuleHandle(NULL);
// Init Direct Input - needed for joystick / Spacemouse
@@ -616,199 +616,199 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
gDirectInput8 = di8_interface;
}
- mSwapMethod = SWAP_METHOD_UNDEFINED;
-
- // No WPARAM yet.
- mLastSizeWParam = 0;
-
- // Windows GDI rects don't include rightmost pixel
- window_rect.left = (long) 0;
- window_rect.right = (long) width;
- window_rect.top = (long) 0;
- window_rect.bottom = (long) height;
-
- // Grab screen size to sanitize the window
- S32 window_border_y = GetSystemMetrics(SM_CYBORDER);
- S32 virtual_screen_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
- S32 virtual_screen_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
- S32 virtual_screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
- S32 virtual_screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
-
- if (x < virtual_screen_x) x = virtual_screen_x;
- if (y < virtual_screen_y - window_border_y) y = virtual_screen_y - window_border_y;
-
- if (x + width > virtual_screen_x + virtual_screen_width) x = virtual_screen_x + virtual_screen_width - width;
- if (y + height > virtual_screen_y + virtual_screen_height) y = virtual_screen_y + virtual_screen_height - height;
-
- if (!sIsClassRegistered)
- {
- // Force redraw when resized and create a private device context
-
- // Makes double click messages.
- wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
-
- // Set message handler function
- wc.lpfnWndProc = (WNDPROC) mainWindowProc;
-
- // unused
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
-
- wc.hInstance = mhInstance;
- wc.hIcon = LoadIcon(mhInstance, mIconResource);
-
- // We will set the cursor ourselves
- wc.hCursor = NULL;
-
- // background color is not used
- if (clearBg)
- {
- wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
- }
- else
- {
- wc.hbrBackground = (HBRUSH) NULL;
- }
-
- // we don't use windows menus
- wc.lpszMenuName = NULL;
-
- wc.lpszClassName = mWindowClassName;
-
- if (!RegisterClass(&wc))
- {
- OSMessageBox(mCallbacks->translateString("MBRegClassFailed"),
- mCallbacks->translateString("MBError"), OSMB_OK);
- return;
- }
- sIsClassRegistered = TRUE;
- }
-
- //-----------------------------------------------------------------------
- // Get the current refresh rate
- //-----------------------------------------------------------------------
-
- DEVMODE dev_mode;
- ::ZeroMemory(&dev_mode, sizeof(DEVMODE));
- dev_mode.dmSize = sizeof(DEVMODE);
- DWORD current_refresh;
- if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
- {
- current_refresh = dev_mode.dmDisplayFrequency;
- mNativeAspectRatio = ((F32)dev_mode.dmPelsWidth) / ((F32)dev_mode.dmPelsHeight);
- }
- else
- {
- current_refresh = 60;
- }
+ mSwapMethod = SWAP_METHOD_UNDEFINED;
+
+ // No WPARAM yet.
+ mLastSizeWParam = 0;
+
+ // Windows GDI rects don't include rightmost pixel
+ window_rect.left = (long) 0;
+ window_rect.right = (long) width;
+ window_rect.top = (long) 0;
+ window_rect.bottom = (long) height;
+
+ // Grab screen size to sanitize the window
+ S32 window_border_y = GetSystemMetrics(SM_CYBORDER);
+ S32 virtual_screen_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
+ S32 virtual_screen_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
+ S32 virtual_screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ S32 virtual_screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+
+ if (x < virtual_screen_x) x = virtual_screen_x;
+ if (y < virtual_screen_y - window_border_y) y = virtual_screen_y - window_border_y;
+
+ if (x + width > virtual_screen_x + virtual_screen_width) x = virtual_screen_x + virtual_screen_width - width;
+ if (y + height > virtual_screen_y + virtual_screen_height) y = virtual_screen_y + virtual_screen_height - height;
+
+ if (!sIsClassRegistered)
+ {
+ // Force redraw when resized and create a private device context
+
+ // Makes double click messages.
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
+
+ // Set message handler function
+ wc.lpfnWndProc = (WNDPROC) mainWindowProc;
+
+ // unused
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+
+ wc.hInstance = mhInstance;
+ wc.hIcon = LoadIcon(mhInstance, mIconResource);
+
+ // We will set the cursor ourselves
+ wc.hCursor = NULL;
+
+ // background color is not used
+ if (clearBg)
+ {
+ wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ }
+ else
+ {
+ wc.hbrBackground = (HBRUSH) NULL;
+ }
+
+ // we don't use windows menus
+ wc.lpszMenuName = NULL;
+
+ wc.lpszClassName = mWindowClassName;
+
+ if (!RegisterClass(&wc))
+ {
+ OSMessageBox(mCallbacks->translateString("MBRegClassFailed"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
+ return;
+ }
+ sIsClassRegistered = TRUE;
+ }
+
+ //-----------------------------------------------------------------------
+ // Get the current refresh rate
+ //-----------------------------------------------------------------------
+
+ DEVMODE dev_mode;
+ ::ZeroMemory(&dev_mode, sizeof(DEVMODE));
+ dev_mode.dmSize = sizeof(DEVMODE);
+ DWORD current_refresh;
+ if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
+ {
+ current_refresh = dev_mode.dmDisplayFrequency;
+ mNativeAspectRatio = ((F32)dev_mode.dmPelsWidth) / ((F32)dev_mode.dmPelsHeight);
+ }
+ else
+ {
+ current_refresh = 60;
+ }
mRefreshRate = current_refresh;
- //-----------------------------------------------------------------------
- // Drop resolution and go fullscreen
- // use a display mode with our desired size and depth, with a refresh
- // rate as close at possible to the users' default
- //-----------------------------------------------------------------------
- if (mFullscreen)
- {
- BOOL success = FALSE;
- DWORD closest_refresh = 0;
-
- for (S32 mode_num = 0;; mode_num++)
- {
- if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
- {
- break;
- }
-
- if (dev_mode.dmPelsWidth == width &&
- dev_mode.dmPelsHeight == height &&
- dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
- {
- success = TRUE;
- if ((dev_mode.dmDisplayFrequency - current_refresh)
- < (closest_refresh - current_refresh))
- {
- closest_refresh = dev_mode.dmDisplayFrequency;
- }
- }
- }
-
- if (closest_refresh == 0)
- {
- LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
- //success = FALSE;
-
- if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
- {
- success = FALSE;
- }
- else
- {
- if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
- {
- LL_WARNS("Window") << "Current BBP is OK falling back to that" << LL_ENDL;
- window_rect.right=width=dev_mode.dmPelsWidth;
- window_rect.bottom=height=dev_mode.dmPelsHeight;
- success = TRUE;
- }
- else
- {
- LL_WARNS("Window") << "Current BBP is BAD" << LL_ENDL;
- success = FALSE;
- }
- }
- }
-
- // If we found a good resolution, use it.
- if (success)
- {
- success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
- }
-
- // Keep a copy of the actual current device mode in case we minimize
- // and change the screen resolution. JC
- EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
-
- // If it failed, we don't want to run fullscreen
- if (success)
- {
- mFullscreen = TRUE;
- mFullscreenWidth = dev_mode.dmPelsWidth;
- mFullscreenHeight = dev_mode.dmPelsHeight;
- mFullscreenBits = dev_mode.dmBitsPerPel;
- mFullscreenRefresh = dev_mode.dmDisplayFrequency;
-
- LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
- << "x" << dev_mode.dmPelsHeight
- << "x" << dev_mode.dmBitsPerPel
- << " @ " << dev_mode.dmDisplayFrequency
- << LL_ENDL;
- }
- else
- {
- mFullscreen = FALSE;
- mFullscreenWidth = -1;
- mFullscreenHeight = -1;
- mFullscreenBits = -1;
- mFullscreenRefresh = -1;
-
- std::map<std::string,std::string> args;
- args["[WIDTH]"] = llformat("%d", width);
- args["[HEIGHT]"] = llformat ("%d", height);
- OSMessageBox(mCallbacks->translateString("MBFullScreenErr", args),
- mCallbacks->translateString("MBError"), OSMB_OK);
- }
- }
-
- // TODO: add this after resolving _WIN32_WINNT issue
- // if (!fullscreen)
- // {
- // TRACKMOUSEEVENT track_mouse_event;
- // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT );
- // track_mouse_event.dwFlags = TME_LEAVE;
- // track_mouse_event.hwndTrack = mWindowHandle;
- // track_mouse_event.dwHoverTime = HOVER_DEFAULT;
- // TrackMouseEvent( &track_mouse_event );
- // }
+ //-----------------------------------------------------------------------
+ // Drop resolution and go fullscreen
+ // use a display mode with our desired size and depth, with a refresh
+ // rate as close at possible to the users' default
+ //-----------------------------------------------------------------------
+ if (mFullscreen)
+ {
+ BOOL success = FALSE;
+ DWORD closest_refresh = 0;
+
+ for (S32 mode_num = 0;; mode_num++)
+ {
+ if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
+ {
+ break;
+ }
+
+ if (dev_mode.dmPelsWidth == width &&
+ dev_mode.dmPelsHeight == height &&
+ dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
+ {
+ success = TRUE;
+ if ((dev_mode.dmDisplayFrequency - current_refresh)
+ < (closest_refresh - current_refresh))
+ {
+ closest_refresh = dev_mode.dmDisplayFrequency;
+ }
+ }
+ }
+
+ if (closest_refresh == 0)
+ {
+ LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL;
+ //success = FALSE;
+
+ if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
+ {
+ success = FALSE;
+ }
+ else
+ {
+ if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
+ {
+ LL_WARNS("Window") << "Current BBP is OK falling back to that" << LL_ENDL;
+ window_rect.right=width=dev_mode.dmPelsWidth;
+ window_rect.bottom=height=dev_mode.dmPelsHeight;
+ success = TRUE;
+ }
+ else
+ {
+ LL_WARNS("Window") << "Current BBP is BAD" << LL_ENDL;
+ success = FALSE;
+ }
+ }
+ }
+
+ // If we found a good resolution, use it.
+ if (success)
+ {
+ success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
+ }
+
+ // Keep a copy of the actual current device mode in case we minimize
+ // and change the screen resolution. JC
+ EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
+
+ // If it failed, we don't want to run fullscreen
+ if (success)
+ {
+ mFullscreen = TRUE;
+ mFullscreenWidth = dev_mode.dmPelsWidth;
+ mFullscreenHeight = dev_mode.dmPelsHeight;
+ mFullscreenBits = dev_mode.dmBitsPerPel;
+ mFullscreenRefresh = dev_mode.dmDisplayFrequency;
+
+ LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
+ << "x" << dev_mode.dmPelsHeight
+ << "x" << dev_mode.dmBitsPerPel
+ << " @ " << dev_mode.dmDisplayFrequency
+ << LL_ENDL;
+ }
+ else
+ {
+ mFullscreen = FALSE;
+ mFullscreenWidth = -1;
+ mFullscreenHeight = -1;
+ mFullscreenBits = -1;
+ mFullscreenRefresh = -1;
+
+ std::map<std::string,std::string> args;
+ args["[WIDTH]"] = llformat("%d", width);
+ args["[HEIGHT]"] = llformat ("%d", height);
+ OSMessageBox(mCallbacks->translateString("MBFullScreenErr", args),
+ mCallbacks->translateString("MBError"), OSMB_OK);
+ }
+ }
+
+ // TODO: add this after resolving _WIN32_WINNT issue
+ // if (!fullscreen)
+ // {
+ // TRACKMOUSEEVENT track_mouse_event;
+ // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT );
+ // track_mouse_event.dwFlags = TME_LEAVE;
+ // track_mouse_event.hwndTrack = mWindowHandle;
+ // track_mouse_event.dwHoverTime = HOVER_DEFAULT;
+ // TrackMouseEvent( &track_mouse_event );
+ // }
// SL-12971 dual GPU display
DISPLAY_DEVICEA display_device;
@@ -842,20 +842,20 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
LL_INFOS("Window") << "Total Display Devices: " << display_index << LL_ENDL;
- //-----------------------------------------------------------------------
- // Create GL drawing context
- //-----------------------------------------------------------------------
- LLCoordScreen windowPos(x,y);
- LLCoordScreen windowSize(window_rect.right - window_rect.left,
- window_rect.bottom - window_rect.top);
- if (!switchContext(mFullscreen, windowSize, enable_vsync, &windowPos))
- {
- return;
- }
-
- //start with arrow cursor
- initCursors();
- setCursor( UI_CURSOR_ARROW );
+ //-----------------------------------------------------------------------
+ // Create GL drawing context
+ //-----------------------------------------------------------------------
+ LLCoordScreen windowPos(x,y);
+ LLCoordScreen windowSize(window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top);
+ if (!switchContext(mFullscreen, windowSize, enable_vsync, &windowPos))
+ {
+ return;
+ }
+
+ //start with arrow cursor
+ initCursors();
+ setCursor( UI_CURSOR_ARROW );
mRawMouse.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
mRawMouse.usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE
@@ -864,56 +864,56 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
RegisterRawInputDevices(&mRawMouse, 1, sizeof(mRawMouse));
- // Initialize (boot strap) the Language text input management,
- // based on the system's (or user's) default settings.
- allowLanguageTextInput(NULL, FALSE);
+ // Initialize (boot strap) the Language text input management,
+ // based on the system's (or user's) default settings.
+ allowLanguageTextInput(NULL, FALSE);
}
LLWindowWin32::~LLWindowWin32()
{
- delete mDragDrop;
+ delete mDragDrop;
- delete [] mWindowTitle;
- mWindowTitle = NULL;
+ delete [] mWindowTitle;
+ mWindowTitle = NULL;
- delete [] mSupportedResolutions;
- mSupportedResolutions = NULL;
-
- delete [] mWindowClassName;
- mWindowClassName = NULL;
+ delete [] mSupportedResolutions;
+ mSupportedResolutions = NULL;
+ delete [] mWindowClassName;
+ mWindowClassName = NULL;
+
delete mWindowThread;
}
void LLWindowWin32::show()
{
LL_DEBUGS("Window") << "Setting window to show" << LL_ENDL;
- ShowWindow(mWindowHandle, SW_SHOW);
- SetForegroundWindow(mWindowHandle);
- SetFocus(mWindowHandle);
+ ShowWindow(mWindowHandle, SW_SHOW);
+ SetForegroundWindow(mWindowHandle);
+ SetFocus(mWindowHandle);
}
void LLWindowWin32::hide()
{
- setMouseClipping(FALSE);
- ShowWindow(mWindowHandle, SW_HIDE);
+ setMouseClipping(FALSE);
+ ShowWindow(mWindowHandle, SW_HIDE);
}
//virtual
void LLWindowWin32::minimize()
{
- setMouseClipping(FALSE);
- showCursor();
- ShowWindow(mWindowHandle, SW_MINIMIZE);
+ setMouseClipping(FALSE);
+ showCursor();
+ ShowWindow(mWindowHandle, SW_MINIMIZE);
}
//virtual
void LLWindowWin32::restore()
{
- ShowWindow(mWindowHandle, SW_RESTORE);
- SetForegroundWindow(mWindowHandle);
- SetFocus(mWindowHandle);
+ ShowWindow(mWindowHandle, SW_RESTORE);
+ SetForegroundWindow(mWindowHandle);
+ SetFocus(mWindowHandle);
}
// See SL-12170
@@ -942,88 +942,88 @@ bool destroy_window_handler(HWND hWnd)
// Usually called from LLWindowManager::destroyWindow()
void LLWindowWin32::close()
{
- LL_DEBUGS("Window") << "Closing LLWindowWin32" << LL_ENDL;
- // Is window is already closed?
- if (!mWindowHandle)
- {
- return;
- }
-
- mDragDrop->reset();
-
-
- // Go back to screen mode written in the registry.
- if (mFullscreen)
- {
- resetDisplayResolution();
- }
-
- // Make sure cursor is visible and we haven't mangled the clipping state.
- showCursor();
- setMouseClipping(FALSE);
- if (gKeyboard)
- {
- gKeyboard->resetKeys();
- }
-
- // Clean up remaining GL state
- if (gGLManager.mInited)
- {
- LL_INFOS("Window") << "Cleaning up GL" << LL_ENDL;
- gGLManager.shutdownGL();
- }
-
- LL_DEBUGS("Window") << "Releasing Context" << LL_ENDL;
- if (mhRC)
- {
- if (!wglMakeCurrent(NULL, NULL))
- {
- LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL;
- }
-
- if (!wglDeleteContext(mhRC))
- {
- LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL;
- }
-
- mhRC = NULL;
- }
-
- // Restore gamma to the system values.
- restoreGamma();
-
- LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
+ LL_DEBUGS("Window") << "Closing LLWindowWin32" << LL_ENDL;
+ // Is window is already closed?
+ if (!mWindowHandle)
+ {
+ return;
+ }
+
+ mDragDrop->reset();
+
+
+ // Go back to screen mode written in the registry.
+ if (mFullscreen)
+ {
+ resetDisplayResolution();
+ }
+
+ // Make sure cursor is visible and we haven't mangled the clipping state.
+ showCursor();
+ setMouseClipping(FALSE);
+ if (gKeyboard)
+ {
+ gKeyboard->resetKeys();
+ }
+
+ // Clean up remaining GL state
+ if (gGLManager.mInited)
+ {
+ LL_INFOS("Window") << "Cleaning up GL" << LL_ENDL;
+ gGLManager.shutdownGL();
+ }
+
+ LL_DEBUGS("Window") << "Releasing Context" << LL_ENDL;
+ if (mhRC)
+ {
+ if (!wglMakeCurrent(NULL, NULL))
+ {
+ LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL;
+ }
+
+ if (!wglDeleteContext(mhRC))
+ {
+ LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL;
+ }
+
+ mhRC = NULL;
+ }
+
+ // Restore gamma to the system values.
+ restoreGamma();
+
+ LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
mhDC = NULL;
mWindowHandle = NULL;
-
+
mWindowThread->wakeAndDestroy();
}
BOOL LLWindowWin32::isValid()
{
- return (mWindowHandle != NULL);
+ return (mWindowHandle != NULL);
}
BOOL LLWindowWin32::getVisible()
{
- return (mWindowHandle && IsWindowVisible(mWindowHandle));
+ return (mWindowHandle && IsWindowVisible(mWindowHandle));
}
BOOL LLWindowWin32::getMinimized()
{
- return (mWindowHandle && IsIconic(mWindowHandle));
+ return (mWindowHandle && IsIconic(mWindowHandle));
}
BOOL LLWindowWin32::getMaximized()
{
- return (mWindowHandle && IsZoomed(mWindowHandle));
+ return (mWindowHandle && IsZoomed(mWindowHandle));
}
BOOL LLWindowWin32::maximize()
{
- BOOL success = FALSE;
- if (!mWindowHandle) return success;
+ BOOL success = FALSE;
+ if (!mWindowHandle) return success;
mWindowThread->post([=]
{
@@ -1042,52 +1042,52 @@ BOOL LLWindowWin32::maximize()
BOOL LLWindowWin32::getFullscreen()
{
- return mFullscreen;
+ return mFullscreen;
}
BOOL LLWindowWin32::getPosition(LLCoordScreen *position)
{
position->mX = mRect.left;
- position->mY = mRect.top;
- return TRUE;
+ position->mY = mRect.top;
+ return TRUE;
}
BOOL LLWindowWin32::getSize(LLCoordScreen *size)
{
- size->mX = mRect.right - mRect.left;
- size->mY = mRect.bottom - mRect.top;
- return TRUE;
+ size->mX = mRect.right - mRect.left;
+ size->mY = mRect.bottom - mRect.top;
+ return TRUE;
}
BOOL LLWindowWin32::getSize(LLCoordWindow *size)
{
- size->mX = mClientRect.right - mClientRect.left;
- size->mY = mClientRect.bottom - mClientRect.top;
- return TRUE;
+ size->mX = mClientRect.right - mClientRect.left;
+ size->mY = mClientRect.bottom - mClientRect.top;
+ return TRUE;
}
BOOL LLWindowWin32::setPosition(const LLCoordScreen position)
{
- LLCoordScreen size;
+ LLCoordScreen size;
- if (!mWindowHandle)
- {
- return FALSE;
- }
- getSize(&size);
- moveWindow(position, size);
- return TRUE;
+ if (!mWindowHandle)
+ {
+ return FALSE;
+ }
+ getSize(&size);
+ moveWindow(position, size);
+ return TRUE;
}
BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size)
{
- LLCoordScreen position;
+ LLCoordScreen position;
- getPosition(&position);
- if (!mWindowHandle)
- {
- return FALSE;
- }
+ getPosition(&position);
+ if (!mWindowHandle)
+ {
+ return FALSE;
+ }
mWindowThread->post([=]()
{
@@ -1101,33 +1101,33 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size)
}
});
- moveWindow(position, size);
- return TRUE;
+ moveWindow(position, size);
+ return TRUE;
}
BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size)
{
- RECT window_rect = {0, 0, size.mX, size.mY };
- DWORD dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
- DWORD dw_style = WS_OVERLAPPEDWINDOW;
+ RECT window_rect = {0, 0, size.mX, size.mY };
+ DWORD dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
+ DWORD dw_style = WS_OVERLAPPEDWINDOW;
AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style);
- return setSizeImpl(LLCoordScreen(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top));
+ return setSizeImpl(LLCoordScreen(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top));
}
// changing fullscreen resolution
BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BOOL enable_vsync, const LLCoordScreen* const posp)
{
//called from main thread
- GLuint pixel_format;
+ GLuint pixel_format;
DEVMODE dev_mode;
::ZeroMemory(&dev_mode, sizeof(DEVMODE));
dev_mode.dmSize = sizeof(DEVMODE);
- DWORD current_refresh;
- DWORD dw_ex_style;
- DWORD dw_style;
- RECT window_rect = { 0, 0, 0, 0 };
+ DWORD current_refresh;
+ DWORD dw_ex_style;
+ DWORD dw_style;
+ RECT window_rect = { 0, 0, 0, 0 };
S32 width = size.mX;
S32 height = size.mY;
BOOL auto_show = FALSE;
@@ -1203,7 +1203,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
}
- // Keep a copy of the actual current device mode in case we minimize
+ // Keep a copy of the actual current device mode in case we minimize
// and change the screen resolution. JC
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
@@ -1222,7 +1222,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
<< LL_ENDL;
window_rect.left = (long)0;
- window_rect.right = (long)width; // Windows GDI rects don't include rightmost pixel
+ window_rect.right = (long)width; // Windows GDI rects don't include rightmost pixel
window_rect.top = (long)0;
window_rect.bottom = (long)height;
dw_ex_style = WS_EX_APPWINDOW;
@@ -1249,7 +1249,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
{
mFullscreen = FALSE;
window_rect.left = (long)(posp ? posp->mX : 0);
- window_rect.right = (long)width + window_rect.left; // Windows GDI rects don't include rightmost pixel
+ window_rect.right = (long)width + window_rect.left; // Windows GDI rects don't include rightmost pixel
window_rect.top = (long)(posp ? posp->mY : 0);
window_rect.bottom = (long)height + window_rect.top;
// Window with an edge
@@ -1270,318 +1270,318 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
<< " Fullscreen: " << mFullscreen
<< LL_ENDL;
- recreateWindow(window_rect, dw_ex_style, dw_style);
-
- if (mWindowHandle)
- {
- LL_INFOS("Window") << "window is created." << LL_ENDL ;
- }
- else
- {
- LL_WARNS("Window") << "Window creation failed, code: " << GetLastError() << LL_ENDL;
- }
-
- //-----------------------------------------------------------------------
- // Create GL drawing context
- //-----------------------------------------------------------------------
- static PIXELFORMATDESCRIPTOR pfd =
- {
- sizeof(PIXELFORMATDESCRIPTOR),
- 1,
- PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
- PFD_TYPE_RGBA,
- BITS_PER_PIXEL,
- 0, 0, 0, 0, 0, 0, // RGB bits and shift, unused
- 8, // alpha bits
- 0, // alpha shift
- 0, // accum bits
- 0, 0, 0, 0, // accum RGBA
- 24, // depth bits
- 8, // stencil bits, avi added for stencil test
- 0,
- PFD_MAIN_PLANE,
- 0,
- 0, 0, 0
- };
-
- if (!mhDC)
- {
- close();
- OSMessageBox(mCallbacks->translateString("MBDevContextErr"),
- mCallbacks->translateString("MBError"), OSMB_OK);
- return FALSE;
- }
-
- LL_INFOS("Window") << "Device context retrieved." << LL_ENDL ;
+ recreateWindow(window_rect, dw_ex_style, dw_style);
+
+ if (mWindowHandle)
+ {
+ LL_INFOS("Window") << "window is created." << LL_ENDL ;
+ }
+ else
+ {
+ LL_WARNS("Window") << "Window creation failed, code: " << GetLastError() << LL_ENDL;
+ }
+
+ //-----------------------------------------------------------------------
+ // Create GL drawing context
+ //-----------------------------------------------------------------------
+ static PIXELFORMATDESCRIPTOR pfd =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
+ PFD_TYPE_RGBA,
+ BITS_PER_PIXEL,
+ 0, 0, 0, 0, 0, 0, // RGB bits and shift, unused
+ 8, // alpha bits
+ 0, // alpha shift
+ 0, // accum bits
+ 0, 0, 0, 0, // accum RGBA
+ 24, // depth bits
+ 8, // stencil bits, avi added for stencil test
+ 0,
+ PFD_MAIN_PLANE,
+ 0,
+ 0, 0, 0
+ };
+
+ if (!mhDC)
+ {
+ close();
+ OSMessageBox(mCallbacks->translateString("MBDevContextErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
+ return FALSE;
+ }
+
+ LL_INFOS("Window") << "Device context retrieved." << LL_ENDL ;
try
{
// Looks like ChoosePixelFormat can crash in case of faulty driver
if (!(pixel_format = SafeChoosePixelFormat(mhDC, &pfd)))
- {
+ {
LL_WARNS("Window") << "ChoosePixelFormat failed, code: " << GetLastError() << LL_ENDL;
OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
- close();
+ close();
return FALSE;
}
}
catch (...)
{
LOG_UNHANDLED_EXCEPTION("ChoosePixelFormat");
- OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
- mCallbacks->translateString("MBError"), OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
- }
+ return FALSE;
+ }
- LL_INFOS("Window") << "Pixel format chosen." << LL_ENDL ;
+ LL_INFOS("Window") << "Pixel format chosen." << LL_ENDL ;
- // Verify what pixel format we actually received.
- if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
- &pfd))
- {
- OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"),
- mCallbacks->translateString("MBError"), OSMB_OK);
+ // Verify what pixel format we actually received.
+ if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
+ &pfd))
+ {
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
- }
-
- // (EXP-1765) dump pixel data to see if there is a pattern that leads to unreproducible crash
- LL_INFOS("Window") << "--- begin pixel format dump ---" << LL_ENDL ;
- LL_INFOS("Window") << "pixel_format is " << pixel_format << LL_ENDL ;
- LL_INFOS("Window") << "pfd.nSize: " << pfd.nSize << LL_ENDL ;
- LL_INFOS("Window") << "pfd.nVersion: " << pfd.nVersion << LL_ENDL ;
- LL_INFOS("Window") << "pfd.dwFlags: 0x" << std::hex << pfd.dwFlags << std::dec << LL_ENDL ;
- LL_INFOS("Window") << "pfd.iPixelType: " << (int)pfd.iPixelType << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cColorBits: " << (int)pfd.cColorBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cRedBits: " << (int)pfd.cRedBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cRedShift: " << (int)pfd.cRedShift << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cGreenBits: " << (int)pfd.cGreenBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cGreenShift: " << (int)pfd.cGreenShift << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cBlueBits: " << (int)pfd.cBlueBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cBlueShift: " << (int)pfd.cBlueShift << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cAlphaBits: " << (int)pfd.cAlphaBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cAlphaShift: " << (int)pfd.cAlphaShift << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cAccumBits: " << (int)pfd.cAccumBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cAccumRedBits: " << (int)pfd.cAccumRedBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cAccumGreenBits: " << (int)pfd.cAccumGreenBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cAccumBlueBits: " << (int)pfd.cAccumBlueBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cAccumAlphaBits: " << (int)pfd.cAccumAlphaBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cDepthBits: " << (int)pfd.cDepthBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cStencilBits: " << (int)pfd.cStencilBits << LL_ENDL ;
- LL_INFOS("Window") << "pfd.cAuxBuffers: " << (int)pfd.cAuxBuffers << LL_ENDL ;
- LL_INFOS("Window") << "pfd.iLayerType: " << (int)pfd.iLayerType << LL_ENDL ;
- LL_INFOS("Window") << "pfd.bReserved: " << (int)pfd.bReserved << LL_ENDL ;
- LL_INFOS("Window") << "pfd.dwLayerMask: " << pfd.dwLayerMask << LL_ENDL ;
- LL_INFOS("Window") << "pfd.dwVisibleMask: " << pfd.dwVisibleMask << LL_ENDL ;
- LL_INFOS("Window") << "pfd.dwDamageMask: " << pfd.dwDamageMask << LL_ENDL ;
- LL_INFOS("Window") << "--- end pixel format dump ---" << LL_ENDL ;
-
- if (!SetPixelFormat(mhDC, pixel_format, &pfd))
- {
- OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
- mCallbacks->translateString("MBError"), OSMB_OK);
+ return FALSE;
+ }
+
+ // (EXP-1765) dump pixel data to see if there is a pattern that leads to unreproducible crash
+ LL_INFOS("Window") << "--- begin pixel format dump ---" << LL_ENDL ;
+ LL_INFOS("Window") << "pixel_format is " << pixel_format << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.nSize: " << pfd.nSize << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.nVersion: " << pfd.nVersion << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.dwFlags: 0x" << std::hex << pfd.dwFlags << std::dec << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.iPixelType: " << (int)pfd.iPixelType << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cColorBits: " << (int)pfd.cColorBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cRedBits: " << (int)pfd.cRedBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cRedShift: " << (int)pfd.cRedShift << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cGreenBits: " << (int)pfd.cGreenBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cGreenShift: " << (int)pfd.cGreenShift << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cBlueBits: " << (int)pfd.cBlueBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cBlueShift: " << (int)pfd.cBlueShift << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cAlphaBits: " << (int)pfd.cAlphaBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cAlphaShift: " << (int)pfd.cAlphaShift << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cAccumBits: " << (int)pfd.cAccumBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cAccumRedBits: " << (int)pfd.cAccumRedBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cAccumGreenBits: " << (int)pfd.cAccumGreenBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cAccumBlueBits: " << (int)pfd.cAccumBlueBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cAccumAlphaBits: " << (int)pfd.cAccumAlphaBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cDepthBits: " << (int)pfd.cDepthBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cStencilBits: " << (int)pfd.cStencilBits << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.cAuxBuffers: " << (int)pfd.cAuxBuffers << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.iLayerType: " << (int)pfd.iLayerType << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.bReserved: " << (int)pfd.bReserved << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.dwLayerMask: " << pfd.dwLayerMask << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.dwVisibleMask: " << pfd.dwVisibleMask << LL_ENDL ;
+ LL_INFOS("Window") << "pfd.dwDamageMask: " << pfd.dwDamageMask << LL_ENDL ;
+ LL_INFOS("Window") << "--- end pixel format dump ---" << LL_ENDL ;
+
+ if (!SetPixelFormat(mhDC, pixel_format, &pfd))
+ {
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
- }
+ return FALSE;
+ }
- if (!(mhRC = SafeCreateContext(mhDC)))
- {
- OSMessageBox(mCallbacks->translateString("MBGLContextErr"),
- mCallbacks->translateString("MBError"), OSMB_OK);
+ if (!(mhRC = SafeCreateContext(mhDC)))
+ {
+ OSMessageBox(mCallbacks->translateString("MBGLContextErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
- }
-
- if (!wglMakeCurrent(mhDC, mhRC))
- {
- OSMessageBox(mCallbacks->translateString("MBGLContextActErr"),
- mCallbacks->translateString("MBError"), OSMB_OK);
+ return FALSE;
+ }
+
+ if (!wglMakeCurrent(mhDC, mhRC))
+ {
+ OSMessageBox(mCallbacks->translateString("MBGLContextActErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
- }
-
- LL_INFOS("Window") << "Drawing context is created." << LL_ENDL ;
-
- gGLManager.initWGL();
-
- if (wglChoosePixelFormatARB)
- {
- // OK, at this point, use the ARB wglChoosePixelFormatsARB function to see if we
- // can get exactly what we want.
- GLint attrib_list[256];
- S32 cur_attrib = 0;
-
- attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB;
- attrib_list[cur_attrib++] = 24;
-
- //attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB; //stencil buffer is deprecated (performance penalty)
- //attrib_list[cur_attrib++] = 8;
-
- attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB;
- attrib_list[cur_attrib++] = GL_TRUE;
-
- attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB;
- attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB;
-
- attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB;
- attrib_list[cur_attrib++] = GL_TRUE;
-
- attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB;
- attrib_list[cur_attrib++] = GL_TRUE;
-
- attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
- attrib_list[cur_attrib++] = 24;
-
- attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
- attrib_list[cur_attrib++] = 0;
-
- U32 end_attrib = 0;
- if (mFSAASamples > 0)
- {
- end_attrib = cur_attrib;
- attrib_list[cur_attrib++] = WGL_SAMPLE_BUFFERS_ARB;
- attrib_list[cur_attrib++] = GL_TRUE;
-
- attrib_list[cur_attrib++] = WGL_SAMPLES_ARB;
- attrib_list[cur_attrib++] = mFSAASamples;
- }
-
- // End the list
- attrib_list[cur_attrib++] = 0;
-
- GLint pixel_formats[256];
- U32 num_formats = 0;
-
- // First we try and get a 32 bit depth pixel format
- BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
-
- while(!result && mFSAASamples > 0)
- {
- LL_WARNS() << "FSAASamples: " << mFSAASamples << " not supported." << LL_ENDL ;
-
- mFSAASamples /= 2 ; //try to decrease sample pixel number until to disable anti-aliasing
- if(mFSAASamples < 2)
- {
- mFSAASamples = 0 ;
- }
-
- if (mFSAASamples > 0)
- {
- attrib_list[end_attrib + 3] = mFSAASamples;
- }
- else
- {
- cur_attrib = end_attrib ;
- end_attrib = 0 ;
- attrib_list[cur_attrib++] = 0 ; //end
- }
- result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
-
- if(result)
- {
- LL_WARNS() << "Only support FSAASamples: " << mFSAASamples << LL_ENDL ;
- }
- }
-
- if (!result)
- {
- LL_WARNS() << "mFSAASamples: " << mFSAASamples << LL_ENDL ;
-
- close();
- show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit");
- return FALSE;
- }
-
- if (!num_formats)
- {
- if (end_attrib > 0)
- {
- LL_INFOS("Window") << "No valid pixel format for " << mFSAASamples << "x anti-aliasing." << LL_ENDL;
- attrib_list[end_attrib] = 0;
-
- BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
- if (!result)
- {
- close();
- show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit no AA");
- return FALSE;
- }
- }
-
- if (!num_formats)
- {
- LL_INFOS("Window") << "No 32 bit z-buffer, trying 24 bits instead" << LL_ENDL;
- // Try 24-bit format
- attrib_list[1] = 24;
- BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
- if (!result)
- {
- close();
- show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
- return FALSE;
- }
-
- if (!num_formats)
- {
- LL_WARNS("Window") << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << LL_ENDL;
- attrib_list[1] = 16;
- BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
- if (!result || !num_formats)
- {
- close();
- show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
- return FALSE;
- }
- }
- }
-
- LL_INFOS("Window") << "Choosing pixel formats: " << num_formats << " pixel formats returned" << LL_ENDL;
- }
-
- LL_INFOS("Window") << "pixel formats done." << LL_ENDL ;
-
- S32 swap_method = 0;
- S32 cur_format = 0;
-const S32 max_format = (S32)num_formats - 1;
- GLint swap_query = WGL_SWAP_METHOD_ARB;
-
- // SL-14705 Fix name tags showing in front of objects with AMD GPUs.
- // On AMD hardware we need to iterate from the first pixel format to the end.
- // Spec:
- // https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt
- while (wglGetPixelFormatAttribivARB(mhDC, pixel_formats[cur_format], 0, 1, &swap_query, &swap_method))
- {
- if (swap_method == WGL_SWAP_UNDEFINED_ARB)
- {
- break;
- }
- else if (cur_format >= max_format)
- {
- cur_format = 0;
- break;
- }
-
- ++cur_format;
- }
-
- pixel_format = pixel_formats[cur_format];
-
- if (mhDC != 0) // Does The Window Have A Device Context?
- {
- wglMakeCurrent(mhDC, 0); // Set The Current Active Rendering Context To Zero
- if (mhRC != 0) // Does The Window Have A Rendering Context?
- {
- wglDeleteContext (mhRC); // Release The Rendering Context
- mhRC = 0; // Zero The Rendering Context
- }
- }
+ return FALSE;
+ }
+
+ LL_INFOS("Window") << "Drawing context is created." << LL_ENDL ;
+
+ gGLManager.initWGL();
+
+ if (wglChoosePixelFormatARB)
+ {
+ // OK, at this point, use the ARB wglChoosePixelFormatsARB function to see if we
+ // can get exactly what we want.
+ GLint attrib_list[256];
+ S32 cur_attrib = 0;
+
+ attrib_list[cur_attrib++] = WGL_DEPTH_BITS_ARB;
+ attrib_list[cur_attrib++] = 24;
+
+ //attrib_list[cur_attrib++] = WGL_STENCIL_BITS_ARB; //stencil buffer is deprecated (performance penalty)
+ //attrib_list[cur_attrib++] = 8;
+
+ attrib_list[cur_attrib++] = WGL_DRAW_TO_WINDOW_ARB;
+ attrib_list[cur_attrib++] = GL_TRUE;
+
+ attrib_list[cur_attrib++] = WGL_ACCELERATION_ARB;
+ attrib_list[cur_attrib++] = WGL_FULL_ACCELERATION_ARB;
+
+ attrib_list[cur_attrib++] = WGL_SUPPORT_OPENGL_ARB;
+ attrib_list[cur_attrib++] = GL_TRUE;
+
+ attrib_list[cur_attrib++] = WGL_DOUBLE_BUFFER_ARB;
+ attrib_list[cur_attrib++] = GL_TRUE;
+
+ attrib_list[cur_attrib++] = WGL_COLOR_BITS_ARB;
+ attrib_list[cur_attrib++] = 24;
+
+ attrib_list[cur_attrib++] = WGL_ALPHA_BITS_ARB;
+ attrib_list[cur_attrib++] = 0;
+
+ U32 end_attrib = 0;
+ if (mFSAASamples > 0)
+ {
+ end_attrib = cur_attrib;
+ attrib_list[cur_attrib++] = WGL_SAMPLE_BUFFERS_ARB;
+ attrib_list[cur_attrib++] = GL_TRUE;
+
+ attrib_list[cur_attrib++] = WGL_SAMPLES_ARB;
+ attrib_list[cur_attrib++] = mFSAASamples;
+ }
+
+ // End the list
+ attrib_list[cur_attrib++] = 0;
+
+ GLint pixel_formats[256];
+ U32 num_formats = 0;
+
+ // First we try and get a 32 bit depth pixel format
+ BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
+
+ while(!result && mFSAASamples > 0)
+ {
+ LL_WARNS() << "FSAASamples: " << mFSAASamples << " not supported." << LL_ENDL ;
+
+ mFSAASamples /= 2 ; //try to decrease sample pixel number until to disable anti-aliasing
+ if(mFSAASamples < 2)
+ {
+ mFSAASamples = 0 ;
+ }
+
+ if (mFSAASamples > 0)
+ {
+ attrib_list[end_attrib + 3] = mFSAASamples;
+ }
+ else
+ {
+ cur_attrib = end_attrib ;
+ end_attrib = 0 ;
+ attrib_list[cur_attrib++] = 0 ; //end
+ }
+ result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
+
+ if(result)
+ {
+ LL_WARNS() << "Only support FSAASamples: " << mFSAASamples << LL_ENDL ;
+ }
+ }
+
+ if (!result)
+ {
+ LL_WARNS() << "mFSAASamples: " << mFSAASamples << LL_ENDL ;
+
+ close();
+ show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit");
+ return FALSE;
+ }
+
+ if (!num_formats)
+ {
+ if (end_attrib > 0)
+ {
+ LL_INFOS("Window") << "No valid pixel format for " << mFSAASamples << "x anti-aliasing." << LL_ENDL;
+ attrib_list[end_attrib] = 0;
+
+ BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
+ if (!result)
+ {
+ close();
+ show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit no AA");
+ return FALSE;
+ }
+ }
+
+ if (!num_formats)
+ {
+ LL_INFOS("Window") << "No 32 bit z-buffer, trying 24 bits instead" << LL_ENDL;
+ // Try 24-bit format
+ attrib_list[1] = 24;
+ BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
+ if (!result)
+ {
+ close();
+ show_window_creation_error("Error after wglChoosePixelFormatARB 24-bit");
+ return FALSE;
+ }
+
+ if (!num_formats)
+ {
+ LL_WARNS("Window") << "Couldn't get 24 bit z-buffer,trying 16 bits instead!" << LL_ENDL;
+ attrib_list[1] = 16;
+ BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats);
+ if (!result || !num_formats)
+ {
+ close();
+ show_window_creation_error("Error after wglChoosePixelFormatARB 16-bit");
+ return FALSE;
+ }
+ }
+ }
+
+ LL_INFOS("Window") << "Choosing pixel formats: " << num_formats << " pixel formats returned" << LL_ENDL;
+ }
+
+ LL_INFOS("Window") << "pixel formats done." << LL_ENDL ;
+
+ S32 swap_method = 0;
+ S32 cur_format = 0;
+const S32 max_format = (S32)num_formats - 1;
+ GLint swap_query = WGL_SWAP_METHOD_ARB;
+
+ // SL-14705 Fix name tags showing in front of objects with AMD GPUs.
+ // On AMD hardware we need to iterate from the first pixel format to the end.
+ // Spec:
+ // https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt
+ while (wglGetPixelFormatAttribivARB(mhDC, pixel_formats[cur_format], 0, 1, &swap_query, &swap_method))
+ {
+ if (swap_method == WGL_SWAP_UNDEFINED_ARB)
+ {
+ break;
+ }
+ else if (cur_format >= max_format)
+ {
+ cur_format = 0;
+ break;
+ }
+
+ ++cur_format;
+ }
+
+ pixel_format = pixel_formats[cur_format];
+
+ if (mhDC != 0) // Does The Window Have A Device Context?
+ {
+ wglMakeCurrent(mhDC, 0); // Set The Current Active Rendering Context To Zero
+ if (mhRC != 0) // Does The Window Have A Rendering Context?
+ {
+ wglDeleteContext (mhRC); // Release The Rendering Context
+ mhRC = 0; // Zero The Rendering Context
+ }
+ }
// will release and recreate mhDC, mWindowHandle
- recreateWindow(window_rect, dw_ex_style, dw_style);
-
+ recreateWindow(window_rect, dw_ex_style, dw_style);
+
RECT rect;
RECT client_rect;
//initialize immediately on main thread
@@ -1592,112 +1592,112 @@ const S32 max_format = (S32)num_formats - 1;
mClientRect = client_rect;
};
- if (mWindowHandle)
- {
- LL_INFOS("Window") << "recreate window done." << LL_ENDL ;
- }
- else
- {
- // Note: if value is NULL GetDC retrieves the DC for the entire screen.
- LL_WARNS("Window") << "Window recreation failed, code: " << GetLastError() << LL_ENDL;
- }
-
- if (!mhDC)
- {
- OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
- close();
- return FALSE;
- }
-
- if (!SetPixelFormat(mhDC, pixel_format, &pfd))
- {
- OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
- mCallbacks->translateString("MBError"), OSMB_OK);
- close();
- return FALSE;
- }
-
- if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
- {
- switch (swap_method)
- {
- case WGL_SWAP_EXCHANGE_ARB:
- mSwapMethod = SWAP_METHOD_EXCHANGE;
- LL_DEBUGS("Window") << "Swap Method: Exchange" << LL_ENDL;
- break;
- case WGL_SWAP_COPY_ARB:
- mSwapMethod = SWAP_METHOD_COPY;
- LL_DEBUGS("Window") << "Swap Method: Copy" << LL_ENDL;
- break;
- case WGL_SWAP_UNDEFINED_ARB:
- mSwapMethod = SWAP_METHOD_UNDEFINED;
- LL_DEBUGS("Window") << "Swap Method: Undefined" << LL_ENDL;
- break;
- default:
- mSwapMethod = SWAP_METHOD_UNDEFINED;
- LL_DEBUGS("Window") << "Swap Method: Unknown" << LL_ENDL;
- break;
- }
- }
- }
- else
- {
- LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL;
- }
-
- // Verify what pixel format we actually received.
- if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
- &pfd))
- {
- OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK);
- close();
- return FALSE;
- }
-
- LL_INFOS("Window") << "GL buffer: Color Bits " << S32(pfd.cColorBits)
- << " Alpha Bits " << S32(pfd.cAlphaBits)
- << " Depth Bits " << S32(pfd.cDepthBits)
- << LL_ENDL;
-
- mhRC = 0;
- if (wglCreateContextAttribsARB)
- { //attempt to create a specific versioned context
+ if (mWindowHandle)
+ {
+ LL_INFOS("Window") << "recreate window done." << LL_ENDL ;
+ }
+ else
+ {
+ // Note: if value is NULL GetDC retrieves the DC for the entire screen.
+ LL_WARNS("Window") << "Window recreation failed, code: " << GetLastError() << LL_ENDL;
+ }
+
+ if (!mhDC)
+ {
+ OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
+ close();
+ return FALSE;
+ }
+
+ if (!SetPixelFormat(mhDC, pixel_format, &pfd))
+ {
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
+ close();
+ return FALSE;
+ }
+
+ if (wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
+ {
+ switch (swap_method)
+ {
+ case WGL_SWAP_EXCHANGE_ARB:
+ mSwapMethod = SWAP_METHOD_EXCHANGE;
+ LL_DEBUGS("Window") << "Swap Method: Exchange" << LL_ENDL;
+ break;
+ case WGL_SWAP_COPY_ARB:
+ mSwapMethod = SWAP_METHOD_COPY;
+ LL_DEBUGS("Window") << "Swap Method: Copy" << LL_ENDL;
+ break;
+ case WGL_SWAP_UNDEFINED_ARB:
+ mSwapMethod = SWAP_METHOD_UNDEFINED;
+ LL_DEBUGS("Window") << "Swap Method: Undefined" << LL_ENDL;
+ break;
+ default:
+ mSwapMethod = SWAP_METHOD_UNDEFINED;
+ LL_DEBUGS("Window") << "Swap Method: Unknown" << LL_ENDL;
+ break;
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL;
+ }
+
+ // Verify what pixel format we actually received.
+ if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
+ &pfd))
+ {
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK);
+ close();
+ return FALSE;
+ }
+
+ LL_INFOS("Window") << "GL buffer: Color Bits " << S32(pfd.cColorBits)
+ << " Alpha Bits " << S32(pfd.cAlphaBits)
+ << " Depth Bits " << S32(pfd.cDepthBits)
+ << LL_ENDL;
+
+ mhRC = 0;
+ if (wglCreateContextAttribsARB)
+ { //attempt to create a specific versioned context
mhRC = (HGLRC) createSharedContext();
if (!mhRC)
{
return FALSE;
}
- }
+ }
- if (!wglMakeCurrent(mhDC, mhRC))
- {
- OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK);
+ if (!wglMakeCurrent(mhDC, mhRC))
+ {
+ OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
- }
+ return FALSE;
+ }
- if (!gGLManager.initGL())
- {
- OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
+ if (!gGLManager.initGL())
+ {
+ OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
close();
- return FALSE;
- }
-
- // Disable vertical sync for swap
+ return FALSE;
+ }
+
+ // Disable vertical sync for swap
toggleVSync(enable_vsync);
- SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, (LONG_PTR)this);
+ SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, (LONG_PTR)this);
- // register this window as handling drag/drop events from the OS
- DragAcceptFiles( mWindowHandle, TRUE );
+ // register this window as handling drag/drop events from the OS
+ DragAcceptFiles( mWindowHandle, TRUE );
- mDragDrop->init( mWindowHandle );
+ mDragDrop->init( mWindowHandle );
+
+ //register joystick timer callback
+ SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer
- //register joystick timer callback
- SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer
-
- // ok to post quit messages now
- mPostQuit = TRUE;
+ // ok to post quit messages now
+ mPostQuit = TRUE;
// *HACK: Attempt to prevent startup crashes by deferring memory accounting
// until after some graphics setup. See SL-20177. -Cosmic,2023-09-18
@@ -1706,17 +1706,17 @@ const S32 max_format = (S32)num_formats - 1;
mWindowThread->glReady();
});
- if (auto_show)
- {
- show();
- glClearColor(0.0f, 0.0f, 0.0f, 0.f);
- glClear(GL_COLOR_BUFFER_BIT);
- swapBuffers();
- }
+ if (auto_show)
+ {
+ show();
+ glClearColor(0.0f, 0.0f, 0.0f, 0.f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ swapBuffers();
+ }
LL_PROFILER_GPU_CONTEXT;
- return TRUE;
+ return TRUE;
}
void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style)
@@ -1771,10 +1771,10 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw
windowClassName,
windowTitle,
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
- window_rect.left, // x pos
- window_rect.top, // y pos
- window_rect.right - window_rect.left, // width
- window_rect.bottom - window_rect.top, // height
+ window_rect.left, // x pos
+ window_rect.top, // y pos
+ window_rect.right - window_rect.left, // width
+ window_rect.bottom - window_rect.top, // height
NULL,
NULL,
hInstance,
@@ -1793,7 +1793,7 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw
self->mWindowHandleThrd = handle;
self->mhDCThrd = GetDC(handle);
}
-
+
updateWindowRect();
// It's important to wake up the future either way.
@@ -1909,22 +1909,22 @@ void LLWindowWin32::toggleVSync(bool enable_vsync)
void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size )
{
- if( mIsMouseClipping )
- {
- RECT client_rect_in_screen_space;
- if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
- {
- ClipCursor( &client_rect_in_screen_space );
- }
- }
-
- // if the window was already maximized, MoveWindow seems to still set the maximized flag even if
- // the window is smaller than maximized.
- // So we're going to do a restore first (which is a ShowWindow call) (SL-44655).
-
- // THIS CAUSES DEV-15484 and DEV-15949
- //ShowWindow(mWindowHandle, SW_RESTORE);
- // NOW we can call MoveWindow
+ if( mIsMouseClipping )
+ {
+ RECT client_rect_in_screen_space;
+ if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
+ {
+ ClipCursor( &client_rect_in_screen_space );
+ }
+ }
+
+ // if the window was already maximized, MoveWindow seems to still set the maximized flag even if
+ // the window is smaller than maximized.
+ // So we're going to do a restore first (which is a ShowWindow call) (SL-44655).
+
+ // THIS CAUSES DEV-15484 and DEV-15949
+ //ShowWindow(mWindowHandle, SW_RESTORE);
+ // NOW we can call MoveWindow
mWindowThread->post([=]()
{
MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE);
@@ -1979,7 +1979,7 @@ BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)
}
*position = mCursorPosition;
- return TRUE;
+ return TRUE;
}
BOOL LLWindowWin32::getCursorDelta(LLCoordCommon* delta)
@@ -2006,8 +2006,8 @@ void LLWindowWin32::hideCursor()
}
});
- mCursorHidden = TRUE;
- mHideCursorPermanent = TRUE;
+ mCursorHidden = TRUE;
+ mHideCursorPermanent = TRUE;
}
void LLWindowWin32::showCursor()
@@ -2015,7 +2015,7 @@ void LLWindowWin32::showCursor()
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
ASSERT_MAIN_THREAD();
-
+
mWindowThread->post([=]()
{
// makes sure the cursor shows up
@@ -2025,103 +2025,103 @@ void LLWindowWin32::showCursor()
}
});
- mCursorHidden = FALSE;
- mHideCursorPermanent = FALSE;
+ mCursorHidden = FALSE;
+ mHideCursorPermanent = FALSE;
}
void LLWindowWin32::showCursorFromMouseMove()
{
- if (!mHideCursorPermanent)
- {
- showCursor();
- }
+ if (!mHideCursorPermanent)
+ {
+ showCursor();
+ }
}
void LLWindowWin32::hideCursorUntilMouseMove()
{
- if (!mHideCursorPermanent && mMouseVanish)
- {
- hideCursor();
- mHideCursorPermanent = FALSE;
- }
+ if (!mHideCursorPermanent && mMouseVanish)
+ {
+ hideCursor();
+ mHideCursorPermanent = FALSE;
+ }
}
BOOL LLWindowWin32::isCursorHidden()
{
- return mCursorHidden;
+ return mCursorHidden;
}
HCURSOR LLWindowWin32::loadColorCursor(LPCTSTR name)
{
- return (HCURSOR)LoadImage(mhInstance,
- name,
- IMAGE_CURSOR,
- 0, // default width
- 0, // default height
- LR_DEFAULTCOLOR);
+ return (HCURSOR)LoadImage(mhInstance,
+ name,
+ IMAGE_CURSOR,
+ 0, // default width
+ 0, // default height
+ LR_DEFAULTCOLOR);
}
void LLWindowWin32::initCursors()
{
- mCursor[ UI_CURSOR_ARROW ] = LoadCursor(NULL, IDC_ARROW);
- mCursor[ UI_CURSOR_WAIT ] = LoadCursor(NULL, IDC_WAIT);
- mCursor[ UI_CURSOR_HAND ] = LoadCursor(NULL, IDC_HAND);
- mCursor[ UI_CURSOR_IBEAM ] = LoadCursor(NULL, IDC_IBEAM);
- mCursor[ UI_CURSOR_CROSS ] = LoadCursor(NULL, IDC_CROSS);
- mCursor[ UI_CURSOR_SIZENWSE ] = LoadCursor(NULL, IDC_SIZENWSE);
- mCursor[ UI_CURSOR_SIZENESW ] = LoadCursor(NULL, IDC_SIZENESW);
- mCursor[ UI_CURSOR_SIZEWE ] = LoadCursor(NULL, IDC_SIZEWE);
- mCursor[ UI_CURSOR_SIZENS ] = LoadCursor(NULL, IDC_SIZENS);
- mCursor[ UI_CURSOR_SIZEALL ] = LoadCursor(NULL, IDC_SIZEALL);
- mCursor[ UI_CURSOR_NO ] = LoadCursor(NULL, IDC_NO);
- mCursor[ UI_CURSOR_WORKING ] = LoadCursor(NULL, IDC_APPSTARTING);
-
- HMODULE module = GetModuleHandle(NULL);
- mCursor[ UI_CURSOR_TOOLGRAB ] = LoadCursor(module, TEXT("TOOLGRAB"));
- mCursor[ UI_CURSOR_TOOLLAND ] = LoadCursor(module, TEXT("TOOLLAND"));
- mCursor[ UI_CURSOR_TOOLFOCUS ] = LoadCursor(module, TEXT("TOOLFOCUS"));
- mCursor[ UI_CURSOR_TOOLCREATE ] = LoadCursor(module, TEXT("TOOLCREATE"));
- mCursor[ UI_CURSOR_ARROWDRAG ] = LoadCursor(module, TEXT("ARROWDRAG"));
- mCursor[ UI_CURSOR_ARROWCOPY ] = LoadCursor(module, TEXT("ARROWCOPY"));
- mCursor[ UI_CURSOR_ARROWDRAGMULTI ] = LoadCursor(module, TEXT("ARROWDRAGMULTI"));
- mCursor[ UI_CURSOR_ARROWCOPYMULTI ] = LoadCursor(module, TEXT("ARROWCOPYMULTI"));
- mCursor[ UI_CURSOR_NOLOCKED ] = LoadCursor(module, TEXT("NOLOCKED"));
- mCursor[ UI_CURSOR_ARROWLOCKED ]= LoadCursor(module, TEXT("ARROWLOCKED"));
- mCursor[ UI_CURSOR_GRABLOCKED ] = LoadCursor(module, TEXT("GRABLOCKED"));
- mCursor[ UI_CURSOR_TOOLTRANSLATE ] = LoadCursor(module, TEXT("TOOLTRANSLATE"));
- mCursor[ UI_CURSOR_TOOLROTATE ] = LoadCursor(module, TEXT("TOOLROTATE"));
- mCursor[ UI_CURSOR_TOOLSCALE ] = LoadCursor(module, TEXT("TOOLSCALE"));
- mCursor[ UI_CURSOR_TOOLCAMERA ] = LoadCursor(module, TEXT("TOOLCAMERA"));
- mCursor[ UI_CURSOR_TOOLPAN ] = LoadCursor(module, TEXT("TOOLPAN"));
- mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN"));
- mCursor[ UI_CURSOR_TOOLZOOMOUT ] = LoadCursor(module, TEXT("TOOLZOOMOUT"));
- mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3"));
- mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
- mCursor[ UI_CURSOR_TOOLSIT ] = LoadCursor(module, TEXT("TOOLSIT"));
- mCursor[ UI_CURSOR_TOOLBUY ] = LoadCursor(module, TEXT("TOOLBUY"));
- mCursor[ UI_CURSOR_TOOLOPEN ] = LoadCursor(module, TEXT("TOOLOPEN"));
- mCursor[ UI_CURSOR_TOOLPATHFINDING ] = LoadCursor(module, TEXT("TOOLPATHFINDING"));
- mCursor[ UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD ] = LoadCursor(module, TEXT("TOOLPATHFINDINGPATHSTARTADD"));
- mCursor[ UI_CURSOR_TOOLPATHFINDING_PATH_START ] = LoadCursor(module, TEXT("TOOLPATHFINDINGPATHSTART"));
- mCursor[ UI_CURSOR_TOOLPATHFINDING_PATH_END ] = LoadCursor(module, TEXT("TOOLPATHFINDINGPATHEND"));
- mCursor[ UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD ] = LoadCursor(module, TEXT("TOOLPATHFINDINGPATHENDADD"));
- mCursor[ UI_CURSOR_TOOLNO ] = LoadCursor(module, TEXT("TOOLNO"));
-
- // Color cursors
- mCursor[ UI_CURSOR_TOOLPLAY ] = loadColorCursor(TEXT("TOOLPLAY"));
- mCursor[ UI_CURSOR_TOOLPAUSE ] = loadColorCursor(TEXT("TOOLPAUSE"));
- mCursor[ UI_CURSOR_TOOLMEDIAOPEN ] = loadColorCursor(TEXT("TOOLMEDIAOPEN"));
-
- // Note: custom cursors that are not found make LoadCursor() return NULL.
- for( S32 i = 0; i < UI_CURSOR_COUNT; i++ )
- {
- if( !mCursor[i] )
- {
- mCursor[i] = LoadCursor(NULL, IDC_ARROW);
- }
- }
+ mCursor[ UI_CURSOR_ARROW ] = LoadCursor(NULL, IDC_ARROW);
+ mCursor[ UI_CURSOR_WAIT ] = LoadCursor(NULL, IDC_WAIT);
+ mCursor[ UI_CURSOR_HAND ] = LoadCursor(NULL, IDC_HAND);
+ mCursor[ UI_CURSOR_IBEAM ] = LoadCursor(NULL, IDC_IBEAM);
+ mCursor[ UI_CURSOR_CROSS ] = LoadCursor(NULL, IDC_CROSS);
+ mCursor[ UI_CURSOR_SIZENWSE ] = LoadCursor(NULL, IDC_SIZENWSE);
+ mCursor[ UI_CURSOR_SIZENESW ] = LoadCursor(NULL, IDC_SIZENESW);
+ mCursor[ UI_CURSOR_SIZEWE ] = LoadCursor(NULL, IDC_SIZEWE);
+ mCursor[ UI_CURSOR_SIZENS ] = LoadCursor(NULL, IDC_SIZENS);
+ mCursor[ UI_CURSOR_SIZEALL ] = LoadCursor(NULL, IDC_SIZEALL);
+ mCursor[ UI_CURSOR_NO ] = LoadCursor(NULL, IDC_NO);
+ mCursor[ UI_CURSOR_WORKING ] = LoadCursor(NULL, IDC_APPSTARTING);
+
+ HMODULE module = GetModuleHandle(NULL);
+ mCursor[ UI_CURSOR_TOOLGRAB ] = LoadCursor(module, TEXT("TOOLGRAB"));
+ mCursor[ UI_CURSOR_TOOLLAND ] = LoadCursor(module, TEXT("TOOLLAND"));
+ mCursor[ UI_CURSOR_TOOLFOCUS ] = LoadCursor(module, TEXT("TOOLFOCUS"));
+ mCursor[ UI_CURSOR_TOOLCREATE ] = LoadCursor(module, TEXT("TOOLCREATE"));
+ mCursor[ UI_CURSOR_ARROWDRAG ] = LoadCursor(module, TEXT("ARROWDRAG"));
+ mCursor[ UI_CURSOR_ARROWCOPY ] = LoadCursor(module, TEXT("ARROWCOPY"));
+ mCursor[ UI_CURSOR_ARROWDRAGMULTI ] = LoadCursor(module, TEXT("ARROWDRAGMULTI"));
+ mCursor[ UI_CURSOR_ARROWCOPYMULTI ] = LoadCursor(module, TEXT("ARROWCOPYMULTI"));
+ mCursor[ UI_CURSOR_NOLOCKED ] = LoadCursor(module, TEXT("NOLOCKED"));
+ mCursor[ UI_CURSOR_ARROWLOCKED ]= LoadCursor(module, TEXT("ARROWLOCKED"));
+ mCursor[ UI_CURSOR_GRABLOCKED ] = LoadCursor(module, TEXT("GRABLOCKED"));
+ mCursor[ UI_CURSOR_TOOLTRANSLATE ] = LoadCursor(module, TEXT("TOOLTRANSLATE"));
+ mCursor[ UI_CURSOR_TOOLROTATE ] = LoadCursor(module, TEXT("TOOLROTATE"));
+ mCursor[ UI_CURSOR_TOOLSCALE ] = LoadCursor(module, TEXT("TOOLSCALE"));
+ mCursor[ UI_CURSOR_TOOLCAMERA ] = LoadCursor(module, TEXT("TOOLCAMERA"));
+ mCursor[ UI_CURSOR_TOOLPAN ] = LoadCursor(module, TEXT("TOOLPAN"));
+ mCursor[ UI_CURSOR_TOOLZOOMIN ] = LoadCursor(module, TEXT("TOOLZOOMIN"));
+ mCursor[ UI_CURSOR_TOOLZOOMOUT ] = LoadCursor(module, TEXT("TOOLZOOMOUT"));
+ mCursor[ UI_CURSOR_TOOLPICKOBJECT3 ] = LoadCursor(module, TEXT("TOOLPICKOBJECT3"));
+ mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
+ mCursor[ UI_CURSOR_TOOLSIT ] = LoadCursor(module, TEXT("TOOLSIT"));
+ mCursor[ UI_CURSOR_TOOLBUY ] = LoadCursor(module, TEXT("TOOLBUY"));
+ mCursor[ UI_CURSOR_TOOLOPEN ] = LoadCursor(module, TEXT("TOOLOPEN"));
+ mCursor[ UI_CURSOR_TOOLPATHFINDING ] = LoadCursor(module, TEXT("TOOLPATHFINDING"));
+ mCursor[ UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD ] = LoadCursor(module, TEXT("TOOLPATHFINDINGPATHSTARTADD"));
+ mCursor[ UI_CURSOR_TOOLPATHFINDING_PATH_START ] = LoadCursor(module, TEXT("TOOLPATHFINDINGPATHSTART"));
+ mCursor[ UI_CURSOR_TOOLPATHFINDING_PATH_END ] = LoadCursor(module, TEXT("TOOLPATHFINDINGPATHEND"));
+ mCursor[ UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD ] = LoadCursor(module, TEXT("TOOLPATHFINDINGPATHENDADD"));
+ mCursor[ UI_CURSOR_TOOLNO ] = LoadCursor(module, TEXT("TOOLNO"));
+
+ // Color cursors
+ mCursor[ UI_CURSOR_TOOLPLAY ] = loadColorCursor(TEXT("TOOLPLAY"));
+ mCursor[ UI_CURSOR_TOOLPAUSE ] = loadColorCursor(TEXT("TOOLPAUSE"));
+ mCursor[ UI_CURSOR_TOOLMEDIAOPEN ] = loadColorCursor(TEXT("TOOLMEDIAOPEN"));
+
+ // Note: custom cursors that are not found make LoadCursor() return NULL.
+ for( S32 i = 0; i < UI_CURSOR_COUNT; i++ )
+ {
+ if( !mCursor[i] )
+ {
+ mCursor[i] = LoadCursor(NULL, IDC_ARROW);
+ }
+ }
}
@@ -2130,43 +2130,43 @@ void LLWindowWin32::updateCursor()
{
ASSERT_MAIN_THREAD();
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32
- if (mNextCursor == UI_CURSOR_ARROW
- && mBusyCount > 0)
- {
- mNextCursor = UI_CURSOR_WORKING;
- }
-
- if( mCurrentCursor != mNextCursor )
- {
- mCurrentCursor = mNextCursor;
+ if (mNextCursor == UI_CURSOR_ARROW
+ && mBusyCount > 0)
+ {
+ mNextCursor = UI_CURSOR_WORKING;
+ }
+
+ if( mCurrentCursor != mNextCursor )
+ {
+ mCurrentCursor = mNextCursor;
auto nextCursor = mCursor[mNextCursor];
mWindowThread->post([=]()
{
SetCursor(nextCursor);
});
- }
+ }
}
ECursorType LLWindowWin32::getCursor() const
{
- return mCurrentCursor;
+ return mCurrentCursor;
}
void LLWindowWin32::captureMouse()
{
- SetCapture(mWindowHandle);
+ SetCapture(mWindowHandle);
}
void LLWindowWin32::releaseMouse()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
- ReleaseCapture();
+ ReleaseCapture();
}
void LLWindowWin32::delayInputProcessing()
{
- mInputProcessingPaused = TRUE;
+ mInputProcessingPaused = TRUE;
}
@@ -2190,7 +2190,7 @@ void LLWindowWin32::gatherInput()
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - PostMessage");
kickWindowThread();
}
-
+
while (mWindowThread->mMessageQueue.tryPopBack(msg))
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - message queue");
@@ -2234,7 +2234,7 @@ void LLWindowWin32::gatherInput()
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("gi - mouse move");
mCallbacks->handleMouseMove(this, mCursorPosition.convert(), mMouseMask);
}
-
+
mLastCursorPosition = mCursorPosition;
{
@@ -2247,9 +2247,9 @@ void LLWindowWin32::gatherInput()
}
}
- mInputProcessingPaused = FALSE;
+ mInputProcessingPaused = FALSE;
- updateCursor();
+ updateCursor();
}
static LLTrace::BlockTimerStatHandle FTM_KEYHANDLER("Handle Keyboard");
@@ -2296,9 +2296,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
switch (u_msg)
{
- RECT update_rect;
- S32 update_width;
- S32 update_height;
+ RECT update_rect;
+ S32 update_width;
+ S32 update_height;
case WM_TIMER:
{
@@ -2313,7 +2313,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL)
{
WINDOW_IMP_POST(window_imp->mCallbacks->handleDeviceChange(window_imp));
-
+
return TRUE;
}
break;
@@ -2374,7 +2374,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
if (window_imp->mFullscreen)
{
- // When we run fullscreen, restoring or minimizing the app needs
+ // When we run fullscreen, restoring or minimizing the app needs
// to switch the screen resolution
if (activating)
{
@@ -2410,7 +2410,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->interruptLanguageTextInput();
}
});
-
+
break;
}
@@ -2488,7 +2488,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
gKeyboard->handleKeyDown(w_param, mask);
});
- if (eat_keystroke) return 0; // skip DefWindowProc() handling if we're consuming the keypress
+ if (eat_keystroke) return 0; // skip DefWindowProc() handling if we're consuming the keypress
break;
}
case WM_SYSKEYUP:
@@ -2510,7 +2510,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
gKeyboard->handleKeyUp(w_param, mask);
}
});
- if (eat_keystroke) return 0; // skip DefWindowProc() handling if we're consuming the keypress
+ if (eat_keystroke) return 0; // skip DefWindowProc() handling if we're consuming the keypress
break;
}
case WM_IME_SETCONTEXT:
@@ -2583,7 +2583,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// it is worth trying. The good old WM_CHAR works just fine even for supplementary
// characters. We just need to take care of surrogate pairs sent as two WM_CHAR's
// by ourselves. It is not that tough. -- Alissa Sabre @ SL
-
+
// Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE,
// we *did* processed the event, so I believe we should not pass it to DefWindowProc...
window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE));
@@ -2611,12 +2611,12 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->postMouseButtonEvent([=]()
{
sHandleLeftMouseUp = true;
-
+
if (LLWinImm::isAvailable() && window_imp->mPreeditor)
{
window_imp->interruptLanguageTextInput();
}
-
+
MASK mask = gKeyboard->currentMask(TRUE);
auto gl_coord = window_imp->mCursorPosition.convert();
window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
@@ -2663,7 +2663,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
}
sHandleDoubleClick = true;
-
+
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
window_imp->mCursorPosition = window_coord;
@@ -2711,7 +2711,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
break;
case WM_MBUTTONDOWN:
- // case WM_MBUTTONDBLCLK:
+ // case WM_MBUTTONDBLCLK:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MBUTTONDOWN");
{
@@ -2759,7 +2759,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// Windows uses numbers 1 and 2 for buttons, remap to 4, 5
window_imp->mCallbacks->handleOtherMouseDown(window_imp, window_imp->mCursorPosition.convert(), mask, button + 3);
});
-
+
}
break;
@@ -2784,7 +2784,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MOUSEWHEEL");
static short z_delta = 0;
- RECT client_rect;
+ RECT client_rect;
// eat scroll events that occur outside our window, since we use mouse position to direct scroll
// instead of keyboard focus
@@ -2827,12 +2827,12 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
window_imp->mCallbacks->handleMouseLeave(window_imp);
- // TRACKMOUSEEVENT track_mouse_event;
- // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT );
- // track_mouse_event.dwFlags = TME_LEAVE;
- // track_mouse_event.hwndTrack = h_wnd;
- // track_mouse_event.dwHoverTime = HOVER_DEFAULT;
- // TrackMouseEvent( &track_mouse_event );
+ // TRACKMOUSEEVENT track_mouse_event;
+ // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT );
+ // track_mouse_event.dwFlags = TME_LEAVE;
+ // track_mouse_event.hwndTrack = h_wnd;
+ // track_mouse_event.dwHoverTime = HOVER_DEFAULT;
+ // TrackMouseEvent( &track_mouse_event );
return 0;
}
*/
@@ -2841,7 +2841,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MOUSEHWHEEL");
static short h_delta = 0;
- RECT client_rect;
+ RECT client_rect;
// eat scroll events that occur outside our window, since we use mouse position to direct scroll
// instead of keyboard focus
@@ -2876,7 +2876,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_MOUSEMOVE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_MOUSEMOVE");
- // DO NOT use mouse event queue for move events to ensure cursor position is updated
+ // DO NOT use mouse event queue for move events to ensure cursor position is updated
// when button events are handled
WINDOW_IMP_POST(
{
@@ -2908,12 +2908,12 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SIZE");
window_imp->updateWindowRect();
- // There's an odd behavior with WM_SIZE that I would call a bug. If
+ // There's an odd behavior with WM_SIZE that I would call a bug. If
// the window is maximized, and you call MoveWindow() with a size smaller
- // than a maximized window, it ends up sending WM_SIZE with w_param set
+ // than a maximized window, it ends up sending WM_SIZE with w_param set
// to SIZE_MAXIMIZED -- which isn't true. So the logic below doesn't work.
- // (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see
- // LLWindowWin32::moveWindow in this file).
+ // (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see
+ // LLWindowWin32::moveWindow in this file).
// If we are now restored, but we weren't before, this
// means that the window was un-minimized.
@@ -2957,7 +2957,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
S32 new_width = lprc_new_scale->right - lprc_new_scale->left;
S32 new_height = lprc_new_scale->bottom - lprc_new_scale->top;
WINDOW_IMP_POST(window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height));
-
+
SetWindowPos(h_wnd,
HWND_TOP,
lprc_new_scale->left,
@@ -2965,7 +2965,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
new_width,
new_height,
SWP_NOZORDER | SWP_NOACTIVATE);
-
+
return 0;
}
@@ -3015,17 +3015,17 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
}
}
break;
-
+
case WM_INPUT:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("MWP - WM_INPUT");
-
+
UINT dwSize = 0;
GetRawInputData((HRAWINPUT)l_param, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
llassert(dwSize < 1024);
U8 lpb[1024];
-
+
if (GetRawInputData((HRAWINPUT)l_param, RID_INPUT, (void*)lpb, &dwSize, sizeof(RAWINPUTHEADER)) == dwSize)
{
RAWINPUT* raw = (RAWINPUT*)lpb;
@@ -3121,175 +3121,175 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to)
{
- S32 client_height;
- RECT client_rect;
- LLCoordWindow window_position;
+ S32 client_height;
+ RECT client_rect;
+ LLCoordWindow window_position;
- if (!mWindowHandle ||
- !GetClientRect(mWindowHandle, &client_rect) ||
- NULL == to)
- {
- return FALSE;
- }
+ if (!mWindowHandle ||
+ !GetClientRect(mWindowHandle, &client_rect) ||
+ NULL == to)
+ {
+ return FALSE;
+ }
- to->mX = from.mX;
- client_height = client_rect.bottom - client_rect.top;
- to->mY = client_height - from.mY - 1;
+ to->mX = from.mX;
+ client_height = client_rect.bottom - client_rect.top;
+ to->mY = client_height - from.mY - 1;
- return TRUE;
+ return TRUE;
}
BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to)
{
- S32 client_height;
- RECT client_rect;
+ S32 client_height;
+ RECT client_rect;
- if (!mWindowHandle ||
- !GetClientRect(mWindowHandle, &client_rect) ||
- NULL == to)
- {
- return FALSE;
- }
+ if (!mWindowHandle ||
+ !GetClientRect(mWindowHandle, &client_rect) ||
+ NULL == to)
+ {
+ return FALSE;
+ }
- to->mX = from.mX;
- client_height = client_rect.bottom - client_rect.top;
- to->mY = client_height - from.mY - 1;
+ to->mX = from.mX;
+ client_height = client_rect.bottom - client_rect.top;
+ to->mY = client_height - from.mY - 1;
- return TRUE;
+ return TRUE;
}
BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to)
-{
- POINT mouse_point;
+{
+ POINT mouse_point;
- mouse_point.x = from.mX;
- mouse_point.y = from.mY;
- BOOL result = ScreenToClient(mWindowHandle, &mouse_point);
+ mouse_point.x = from.mX;
+ mouse_point.y = from.mY;
+ BOOL result = ScreenToClient(mWindowHandle, &mouse_point);
- if (result)
- {
- to->mX = mouse_point.x;
- to->mY = mouse_point.y;
- }
+ if (result)
+ {
+ to->mX = mouse_point.x;
+ to->mY = mouse_point.y;
+ }
- return result;
+ return result;
}
BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to)
{
- POINT mouse_point;
+ POINT mouse_point;
- mouse_point.x = from.mX;
- mouse_point.y = from.mY;
- BOOL result = ClientToScreen(mWindowHandle, &mouse_point);
+ mouse_point.x = from.mX;
+ mouse_point.y = from.mY;
+ BOOL result = ClientToScreen(mWindowHandle, &mouse_point);
- if (result)
- {
- to->mX = mouse_point.x;
- to->mY = mouse_point.y;
- }
+ if (result)
+ {
+ to->mX = mouse_point.x;
+ to->mY = mouse_point.y;
+ }
- return result;
+ return result;
}
BOOL LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to)
{
- LLCoordWindow window_coord;
+ LLCoordWindow window_coord;
- if (!mWindowHandle || (NULL == to))
- {
- return FALSE;
- }
+ if (!mWindowHandle || (NULL == to))
+ {
+ return FALSE;
+ }
- convertCoords(from, &window_coord);
- convertCoords(window_coord, to);
- return TRUE;
+ convertCoords(from, &window_coord);
+ convertCoords(window_coord, to);
+ return TRUE;
}
BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to)
{
- LLCoordWindow window_coord;
+ LLCoordWindow window_coord;
- if (!mWindowHandle || (NULL == to))
- {
- return FALSE;
- }
+ if (!mWindowHandle || (NULL == to))
+ {
+ return FALSE;
+ }
- convertCoords(from, &window_coord);
- convertCoords(window_coord, to);
- return TRUE;
+ convertCoords(from, &window_coord);
+ convertCoords(window_coord, to);
+ return TRUE;
}
BOOL LLWindowWin32::isClipboardTextAvailable()
{
- return IsClipboardFormatAvailable(CF_UNICODETEXT);
+ return IsClipboardFormatAvailable(CF_UNICODETEXT);
}
BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst)
{
- BOOL success = FALSE;
+ BOOL success = FALSE;
- if (IsClipboardFormatAvailable(CF_UNICODETEXT))
- {
- if (OpenClipboard(mWindowHandle))
- {
- HGLOBAL h_data = GetClipboardData(CF_UNICODETEXT);
- if (h_data)
- {
- WCHAR *utf16str = (WCHAR*) GlobalLock(h_data);
- if (utf16str)
- {
- dst = utf16str_to_wstring(utf16str);
- LLWStringUtil::removeWindowsCR(dst);
- GlobalUnlock(h_data);
- success = TRUE;
- }
- }
- CloseClipboard();
- }
- }
+ if (IsClipboardFormatAvailable(CF_UNICODETEXT))
+ {
+ if (OpenClipboard(mWindowHandle))
+ {
+ HGLOBAL h_data = GetClipboardData(CF_UNICODETEXT);
+ if (h_data)
+ {
+ WCHAR *utf16str = (WCHAR*) GlobalLock(h_data);
+ if (utf16str)
+ {
+ dst = utf16str_to_wstring(utf16str);
+ LLWStringUtil::removeWindowsCR(dst);
+ GlobalUnlock(h_data);
+ success = TRUE;
+ }
+ }
+ CloseClipboard();
+ }
+ }
- return success;
+ return success;
}
BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr)
{
- BOOL success = FALSE;
+ BOOL success = FALSE;
- if (OpenClipboard(mWindowHandle))
- {
- EmptyClipboard();
+ if (OpenClipboard(mWindowHandle))
+ {
+ EmptyClipboard();
- // Provide a copy of the data in Unicode format.
- LLWString sanitized_string(wstr);
- LLWStringUtil::addCRLF(sanitized_string);
- llutf16string out_utf16 = wstring_to_utf16str(sanitized_string);
- const size_t size_utf16 = (out_utf16.length() + 1) * sizeof(WCHAR);
+ // Provide a copy of the data in Unicode format.
+ LLWString sanitized_string(wstr);
+ LLWStringUtil::addCRLF(sanitized_string);
+ llutf16string out_utf16 = wstring_to_utf16str(sanitized_string);
+ const size_t size_utf16 = (out_utf16.length() + 1) * sizeof(WCHAR);
- // Memory is allocated and then ownership of it is transfered to the system.
- HGLOBAL hglobal_copy_utf16 = GlobalAlloc(GMEM_MOVEABLE, size_utf16);
- if (hglobal_copy_utf16)
- {
- WCHAR* copy_utf16 = (WCHAR*) GlobalLock(hglobal_copy_utf16);
- if (copy_utf16)
- {
- memcpy(copy_utf16, out_utf16.c_str(), size_utf16); /* Flawfinder: ignore */
- GlobalUnlock(hglobal_copy_utf16);
+ // Memory is allocated and then ownership of it is transfered to the system.
+ HGLOBAL hglobal_copy_utf16 = GlobalAlloc(GMEM_MOVEABLE, size_utf16);
+ if (hglobal_copy_utf16)
+ {
+ WCHAR* copy_utf16 = (WCHAR*) GlobalLock(hglobal_copy_utf16);
+ if (copy_utf16)
+ {
+ memcpy(copy_utf16, out_utf16.c_str(), size_utf16); /* Flawfinder: ignore */
+ GlobalUnlock(hglobal_copy_utf16);
- if (SetClipboardData(CF_UNICODETEXT, hglobal_copy_utf16))
- {
- success = TRUE;
- }
- }
- }
+ if (SetClipboardData(CF_UNICODETEXT, hglobal_copy_utf16))
+ {
+ success = TRUE;
+ }
+ }
+ }
- CloseClipboard();
- }
+ CloseClipboard();
+ }
- return success;
+ return success;
}
// Constrains the mouse to the window.
@@ -3297,32 +3297,32 @@ void LLWindowWin32::setMouseClipping( BOOL b )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
ASSERT_MAIN_THREAD();
- if( b != mIsMouseClipping )
- {
- BOOL success = FALSE;
-
- if( b )
- {
- GetClipCursor( &mOldMouseClip );
-
- RECT client_rect_in_screen_space;
- if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
- {
- success = ClipCursor( &client_rect_in_screen_space );
- }
- }
- else
- {
- // Must restore the old mouse clip, which may be set by another window.
- success = ClipCursor( &mOldMouseClip );
- SetRect( &mOldMouseClip, 0, 0, 0, 0 );
- }
-
- if( success )
- {
- mIsMouseClipping = b;
- }
- }
+ if( b != mIsMouseClipping )
+ {
+ BOOL success = FALSE;
+
+ if( b )
+ {
+ GetClipCursor( &mOldMouseClip );
+
+ RECT client_rect_in_screen_space;
+ if( getClientRectInScreenSpace( &client_rect_in_screen_space ) )
+ {
+ success = ClipCursor( &client_rect_in_screen_space );
+ }
+ }
+ else
+ {
+ // Must restore the old mouse clip, which may be set by another window.
+ success = ClipCursor( &mOldMouseClip );
+ SetRect( &mOldMouseClip, 0, 0, 0, 0 );
+ }
+
+ if( success )
+ {
+ mIsMouseClipping = b;
+ }
+ }
}
BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp )
@@ -3371,29 +3371,29 @@ void LLWindowWin32::flashIcon(F32 seconds)
F32 LLWindowWin32::getGamma()
{
- return mCurrentGamma;
+ return mCurrentGamma;
}
BOOL LLWindowWin32::restoreGamma()
{
ASSERT_MAIN_THREAD();
- if (mCustomGammaSet != FALSE)
- {
+ if (mCustomGammaSet != FALSE)
+ {
LL_DEBUGS("Window") << "Restoring gamma" << LL_ENDL;
- mCustomGammaSet = FALSE;
- return SetDeviceGammaRamp(mhDC, mPrevGammaRamp);
- }
- return TRUE;
+ mCustomGammaSet = FALSE;
+ return SetDeviceGammaRamp(mhDC, mPrevGammaRamp);
+ }
+ return TRUE;
}
BOOL LLWindowWin32::setGamma(const F32 gamma)
{
ASSERT_MAIN_THREAD();
- mCurrentGamma = gamma;
+ mCurrentGamma = gamma;
- //Get the previous gamma ramp to restore later.
- if (mCustomGammaSet == FALSE)
- {
+ //Get the previous gamma ramp to restore later.
+ if (mCustomGammaSet == FALSE)
+ {
if (!gGLManager.mIsIntel) // skip for Intel GPUs (see SL-11341)
{
LL_DEBUGS("Window") << "Getting the previous gamma ramp to restore later" << LL_ENDL;
@@ -3403,192 +3403,192 @@ BOOL LLWindowWin32::setGamma(const F32 gamma)
return FALSE;
}
}
- mCustomGammaSet = TRUE;
- }
+ mCustomGammaSet = TRUE;
+ }
- LL_DEBUGS("Window") << "Setting gamma to " << gamma << LL_ENDL;
+ LL_DEBUGS("Window") << "Setting gamma to " << gamma << LL_ENDL;
- for ( int i = 0; i < 256; ++i )
- {
- int mult = 256 - ( int ) ( ( gamma - 1.0f ) * 128.0f );
+ for ( int i = 0; i < 256; ++i )
+ {
+ int mult = 256 - ( int ) ( ( gamma - 1.0f ) * 128.0f );
- int value = mult * i;
+ int value = mult * i;
- if ( value > 0xffff )
- value = 0xffff;
+ if ( value > 0xffff )
+ value = 0xffff;
- mCurrentGammaRamp[0][i] =
- mCurrentGammaRamp[1][i] =
- mCurrentGammaRamp[2][i] = (WORD) value;
- };
+ mCurrentGammaRamp[0][i] =
+ mCurrentGammaRamp[1][i] =
+ mCurrentGammaRamp[2][i] = (WORD) value;
+ };
- return SetDeviceGammaRamp ( mhDC, mCurrentGammaRamp );
+ return SetDeviceGammaRamp ( mhDC, mCurrentGammaRamp );
}
void LLWindowWin32::setFSAASamples(const U32 fsaa_samples)
{
ASSERT_MAIN_THREAD();
- mFSAASamples = fsaa_samples;
+ mFSAASamples = fsaa_samples;
}
U32 LLWindowWin32::getFSAASamples()
{
- return mFSAASamples;
+ return mFSAASamples;
}
LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_resolutions)
{
ASSERT_MAIN_THREAD();
- if (!mSupportedResolutions)
- {
- mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
- DEVMODE dev_mode;
- ::ZeroMemory(&dev_mode, sizeof(DEVMODE));
- dev_mode.dmSize = sizeof(DEVMODE);
-
- mNumSupportedResolutions = 0;
- for (S32 mode_num = 0; mNumSupportedResolutions < MAX_NUM_RESOLUTIONS; mode_num++)
- {
- if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
- {
- break;
- }
-
- if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL &&
- dev_mode.dmPelsWidth >= 800 &&
- dev_mode.dmPelsHeight >= 600)
- {
- BOOL resolution_exists = FALSE;
- for(S32 i = 0; i < mNumSupportedResolutions; i++)
- {
- if (mSupportedResolutions[i].mWidth == dev_mode.dmPelsWidth &&
- mSupportedResolutions[i].mHeight == dev_mode.dmPelsHeight)
- {
- resolution_exists = TRUE;
- }
- }
- if (!resolution_exists)
- {
- mSupportedResolutions[mNumSupportedResolutions].mWidth = dev_mode.dmPelsWidth;
- mSupportedResolutions[mNumSupportedResolutions].mHeight = dev_mode.dmPelsHeight;
- mNumSupportedResolutions++;
- }
- }
- }
- }
-
- num_resolutions = mNumSupportedResolutions;
- return mSupportedResolutions;
+ if (!mSupportedResolutions)
+ {
+ mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
+ DEVMODE dev_mode;
+ ::ZeroMemory(&dev_mode, sizeof(DEVMODE));
+ dev_mode.dmSize = sizeof(DEVMODE);
+
+ mNumSupportedResolutions = 0;
+ for (S32 mode_num = 0; mNumSupportedResolutions < MAX_NUM_RESOLUTIONS; mode_num++)
+ {
+ if (!EnumDisplaySettings(NULL, mode_num, &dev_mode))
+ {
+ break;
+ }
+
+ if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL &&
+ dev_mode.dmPelsWidth >= 800 &&
+ dev_mode.dmPelsHeight >= 600)
+ {
+ BOOL resolution_exists = FALSE;
+ for(S32 i = 0; i < mNumSupportedResolutions; i++)
+ {
+ if (mSupportedResolutions[i].mWidth == dev_mode.dmPelsWidth &&
+ mSupportedResolutions[i].mHeight == dev_mode.dmPelsHeight)
+ {
+ resolution_exists = TRUE;
+ }
+ }
+ if (!resolution_exists)
+ {
+ mSupportedResolutions[mNumSupportedResolutions].mWidth = dev_mode.dmPelsWidth;
+ mSupportedResolutions[mNumSupportedResolutions].mHeight = dev_mode.dmPelsHeight;
+ mNumSupportedResolutions++;
+ }
+ }
+ }
+ }
+
+ num_resolutions = mNumSupportedResolutions;
+ return mSupportedResolutions;
}
F32 LLWindowWin32::getNativeAspectRatio()
{
- if (mOverrideAspectRatio > 0.f)
- {
- return mOverrideAspectRatio;
- }
- else if (mNativeAspectRatio > 0.f)
- {
- // we grabbed this value at startup, based on the user's desktop settings
- return mNativeAspectRatio;
- }
- // RN: this hack presumes that the largest supported resolution is monitor-limited
- // and that pixels in that mode are square, therefore defining the native aspect ratio
- // of the monitor...this seems to work to a close approximation for most CRTs/LCDs
- S32 num_resolutions;
- LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions);
+ if (mOverrideAspectRatio > 0.f)
+ {
+ return mOverrideAspectRatio;
+ }
+ else if (mNativeAspectRatio > 0.f)
+ {
+ // we grabbed this value at startup, based on the user's desktop settings
+ return mNativeAspectRatio;
+ }
+ // RN: this hack presumes that the largest supported resolution is monitor-limited
+ // and that pixels in that mode are square, therefore defining the native aspect ratio
+ // of the monitor...this seems to work to a close approximation for most CRTs/LCDs
+ S32 num_resolutions;
+ LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions);
- return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight);
+ return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight);
}
F32 LLWindowWin32::getPixelAspectRatio()
{
- F32 pixel_aspect = 1.f;
- if (getFullscreen())
- {
- LLCoordScreen screen_size;
- getSize(&screen_size);
- pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
- }
+ F32 pixel_aspect = 1.f;
+ if (getFullscreen())
+ {
+ LLCoordScreen screen_size;
+ getSize(&screen_size);
+ pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
+ }
- return pixel_aspect;
+ return pixel_aspect;
}
// Change display resolution. Returns true if successful.
// protected
BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
{
- DEVMODE dev_mode;
- ::ZeroMemory(&dev_mode, sizeof(DEVMODE));
- dev_mode.dmSize = sizeof(DEVMODE);
- BOOL success = FALSE;
-
- // Don't change anything if we don't have to
- if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
- {
- if (dev_mode.dmPelsWidth == width &&
- dev_mode.dmPelsHeight == height &&
- dev_mode.dmBitsPerPel == bits &&
- dev_mode.dmDisplayFrequency == refresh )
- {
- // ...display mode identical, do nothing
- return TRUE;
- }
- }
-
- memset(&dev_mode, 0, sizeof(dev_mode));
- dev_mode.dmSize = sizeof(dev_mode);
- dev_mode.dmPelsWidth = width;
- dev_mode.dmPelsHeight = height;
- dev_mode.dmBitsPerPel = bits;
- dev_mode.dmDisplayFrequency = refresh;
- dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
-
- // CDS_FULLSCREEN indicates that this is a temporary change to the device mode.
- LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN);
-
- success = (DISP_CHANGE_SUCCESSFUL == cds_result);
-
- if (!success)
- {
- LL_WARNS("Window") << "setDisplayResolution failed, "
- << width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL;
- }
-
- return success;
+ DEVMODE dev_mode;
+ ::ZeroMemory(&dev_mode, sizeof(DEVMODE));
+ dev_mode.dmSize = sizeof(DEVMODE);
+ BOOL success = FALSE;
+
+ // Don't change anything if we don't have to
+ if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
+ {
+ if (dev_mode.dmPelsWidth == width &&
+ dev_mode.dmPelsHeight == height &&
+ dev_mode.dmBitsPerPel == bits &&
+ dev_mode.dmDisplayFrequency == refresh )
+ {
+ // ...display mode identical, do nothing
+ return TRUE;
+ }
+ }
+
+ memset(&dev_mode, 0, sizeof(dev_mode));
+ dev_mode.dmSize = sizeof(dev_mode);
+ dev_mode.dmPelsWidth = width;
+ dev_mode.dmPelsHeight = height;
+ dev_mode.dmBitsPerPel = bits;
+ dev_mode.dmDisplayFrequency = refresh;
+ dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
+
+ // CDS_FULLSCREEN indicates that this is a temporary change to the device mode.
+ LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN);
+
+ success = (DISP_CHANGE_SUCCESSFUL == cds_result);
+
+ if (!success)
+ {
+ LL_WARNS("Window") << "setDisplayResolution failed, "
+ << width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL;
+ }
+
+ return success;
}
// protected
BOOL LLWindowWin32::setFullscreenResolution()
{
- if (mFullscreen)
- {
- return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh);
- }
- else
- {
- return FALSE;
- }
+ if (mFullscreen)
+ {
+ return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh);
+ }
+ else
+ {
+ return FALSE;
+ }
}
// protected
BOOL LLWindowWin32::resetDisplayResolution()
{
- LL_DEBUGS("Window") << "resetDisplayResolution START" << LL_ENDL;
+ LL_DEBUGS("Window") << "resetDisplayResolution START" << LL_ENDL;
- LONG cds_result = ChangeDisplaySettings(NULL, 0);
+ LONG cds_result = ChangeDisplaySettings(NULL, 0);
- BOOL success = (DISP_CHANGE_SUCCESSFUL == cds_result);
+ BOOL success = (DISP_CHANGE_SUCCESSFUL == cds_result);
- if (!success)
- {
- LL_WARNS("Window") << "resetDisplayResolution failed" << LL_ENDL;
- }
+ if (!success)
+ {
+ LL_WARNS("Window") << "resetDisplayResolution failed" << LL_ENDL;
+ }
- LL_DEBUGS("Window") << "resetDisplayResolution END" << LL_ENDL;
+ LL_DEBUGS("Window") << "resetDisplayResolution END" << LL_ENDL;
- return success;
+ return success;
}
void LLWindowWin32::swapBuffers()
@@ -3609,7 +3609,7 @@ void LLWindowWin32::swapBuffers()
// LLSplashScreenImp
//
LLSplashScreenWin32::LLSplashScreenWin32()
-: mWindow(NULL)
+: mWindow(NULL)
{
}
@@ -3619,14 +3619,14 @@ LLSplashScreenWin32::~LLSplashScreenWin32()
void LLSplashScreenWin32::showImpl()
{
- // This appears to work. ???
- HINSTANCE hinst = GetModuleHandle(NULL);
+ // This appears to work. ???
+ HINSTANCE hinst = GetModuleHandle(NULL);
- mWindow = CreateDialog(hinst,
- TEXT("SPLASHSCREEN"),
- NULL, // no parent
- (DLGPROC) LLSplashScreenWin32::windowProc);
- ShowWindow(mWindow, SW_SHOW);
+ mWindow = CreateDialog(hinst,
+ TEXT("SPLASHSCREEN"),
+ NULL, // no parent
+ (DLGPROC) LLSplashScreenWin32::windowProc);
+ ShowWindow(mWindow, SW_SHOW);
// Should set taskbar text without creating a header for the window (caption)
SetWindowTextA(mWindow, "Second Life");
@@ -3635,46 +3635,46 @@ void LLSplashScreenWin32::showImpl()
void LLSplashScreenWin32::updateImpl(const std::string& mesg)
{
- if (!mWindow) return;
+ if (!mWindow) return;
- int output_str_len = MultiByteToWideChar(CP_UTF8, 0, mesg.c_str(), mesg.length(), NULL, 0);
- if( output_str_len>1024 )
- return;
+ int output_str_len = MultiByteToWideChar(CP_UTF8, 0, mesg.c_str(), mesg.length(), NULL, 0);
+ if( output_str_len>1024 )
+ return;
- WCHAR w_mesg[1025];//big enought to keep null terminatos
+ WCHAR w_mesg[1025];//big enought to keep null terminatos
- MultiByteToWideChar (CP_UTF8, 0, mesg.c_str(), mesg.length(), w_mesg, output_str_len);
+ MultiByteToWideChar (CP_UTF8, 0, mesg.c_str(), mesg.length(), w_mesg, output_str_len);
- //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858
- w_mesg[output_str_len] = 0;
+ //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858
+ w_mesg[output_str_len] = 0;
- SendDlgItemMessage(mWindow,
- 666, // HACK: text id
- WM_SETTEXT,
- FALSE,
- (LPARAM)w_mesg);
+ SendDlgItemMessage(mWindow,
+ 666, // HACK: text id
+ WM_SETTEXT,
+ FALSE,
+ (LPARAM)w_mesg);
}
void LLSplashScreenWin32::hideImpl()
{
- if (mWindow)
- {
+ if (mWindow)
+ {
if (!destroy_window_handler(mWindow))
{
LL_WARNS("Window") << "Failed to properly close splash screen window!" << LL_ENDL;
}
- mWindow = NULL;
- }
+ mWindow = NULL;
+ }
}
// static
LRESULT CALLBACK LLSplashScreenWin32::windowProc(HWND h_wnd, UINT u_msg,
- WPARAM w_param, LPARAM l_param)
+ WPARAM w_param, LPARAM l_param)
{
- // Just give it to windows
- return DefWindowProc(h_wnd, u_msg, w_param, l_param);
+ // Just give it to windows
+ return DefWindowProc(h_wnd, u_msg, w_param, l_param);
}
//
@@ -3683,148 +3683,155 @@ LRESULT CALLBACK LLSplashScreenWin32::windowProc(HWND h_wnd, UINT u_msg,
S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type)
{
- UINT uType;
-
- switch(type)
- {
- case OSMB_OK:
- uType = MB_OK;
- break;
- case OSMB_OKCANCEL:
- uType = MB_OKCANCEL;
- break;
- case OSMB_YESNO:
- uType = MB_YESNO;
- break;
- default:
- uType = MB_OK;
- break;
- }
-
- int retval_win = MessageBoxW(NULL, // HWND
- ll_convert_string_to_wide(text).c_str(),
- ll_convert_string_to_wide(caption).c_str(),
- uType);
- S32 retval;
+ UINT uType;
+
+ switch(type)
+ {
+ case OSMB_OK:
+ uType = MB_OK;
+ break;
+ case OSMB_OKCANCEL:
+ uType = MB_OKCANCEL;
+ break;
+ case OSMB_YESNO:
+ uType = MB_YESNO;
+ break;
+ default:
+ uType = MB_OK;
+ break;
+ }
+
+ int retval_win = MessageBoxW(NULL, // HWND
+ ll_convert_string_to_wide(text).c_str(),
+ ll_convert_string_to_wide(caption).c_str(),
+ uType);
+ S32 retval;
+
+ switch(retval_win)
+ {
+ case IDYES:
+ retval = OSBTN_YES;
+ break;
+ case IDNO:
+ retval = OSBTN_NO;
+ break;
+ case IDOK:
+ retval = OSBTN_OK;
+ break;
+ case IDCANCEL:
+ retval = OSBTN_CANCEL;
+ break;
+ default:
+ retval = OSBTN_CANCEL;
+ break;
+ }
+
+ return retval;
+}
+
+void shell_open(const std::string &file, bool async)
+{
+ std::wstring url_utf16 = ll_convert(file);
- switch(retval_win)
+ // let the OS decide what to use to open the URL
+ SHELLEXECUTEINFO sei = {sizeof(sei)};
+ // NOTE: this assumes that SL will stick around long enough to complete the DDE message exchange
+ // necessary for ShellExecuteEx to complete
+ if (async)
{
- case IDYES:
- retval = OSBTN_YES;
- break;
- case IDNO:
- retval = OSBTN_NO;
- break;
- case IDOK:
- retval = OSBTN_OK;
- break;
- case IDCANCEL:
- retval = OSBTN_CANCEL;
- break;
- default:
- retval = OSBTN_CANCEL;
- break;
+ sei.fMask = SEE_MASK_ASYNCOK;
}
-
- return retval;
+ sei.nShow = SW_SHOWNORMAL;
+ sei.lpVerb = L"open";
+ sei.lpFile = url_utf16.c_str();
+ ShellExecuteEx(&sei);
}
-
void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async)
{
- bool found = false;
- S32 i;
- for (i = 0; i < gURLProtocolWhitelistCount; i++)
- {
- if (escaped_url.find(gURLProtocolWhitelist[i]) == 0)
- {
- found = true;
- break;
- }
- }
+ bool found = false;
+ S32 i;
+ for (i = 0; i < gURLProtocolWhitelistCount; i++)
+ {
+ if (escaped_url.find(gURLProtocolWhitelist[i]) == 0)
+ {
+ found = true;
+ break;
+ }
+ }
- if (!found)
- {
- LL_WARNS("Window") << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << LL_ENDL;
- return;
- }
+ if (!found)
+ {
+ LL_WARNS("Window") << "spawn_web_browser() called for url with protocol not on whitelist: " << escaped_url << LL_ENDL;
+ return;
+ }
- LL_INFOS("Window") << "Opening URL " << escaped_url << LL_ENDL;
+ LL_INFOS("Window") << "Opening URL " << escaped_url << LL_ENDL;
- // replaced ShellExecute code with ShellExecuteEx since ShellExecute doesn't work
- // reliablly on Vista.
+ // replaced ShellExecute code with ShellExecuteEx since ShellExecute doesn't work
+ // reliablly on Vista.
- // this is madness.. no, this is..
- LLWString url_wstring = utf8str_to_wstring( escaped_url );
- llutf16string url_utf16 = wstring_to_utf16str( url_wstring );
+ shell_open(escaped_url, async);
+}
- // let the OS decide what to use to open the URL
- SHELLEXECUTEINFO sei = { sizeof( sei ) };
- // NOTE: this assumes that SL will stick around long enough to complete the DDE message exchange
- // necessary for ShellExecuteEx to complete
- if (async)
- {
- sei.fMask = SEE_MASK_ASYNCOK;
- }
- sei.nShow = SW_SHOWNORMAL;
- sei.lpVerb = L"open";
- sei.lpFile = url_utf16.c_str();
- ShellExecuteEx( &sei );
+void LLWindowWin32::openFolder(const std::string &path)
+{
+ shell_open(path, false);
}
/*
- Make the raw keyboard data available - used to poke through to LLQtWebKit so
- that Qt/Webkit has access to the virtual keycodes etc. that it needs
+ Make the raw keyboard data available - used to poke through to LLQtWebKit so
+ that Qt/Webkit has access to the virtual keycodes etc. that it needs
*/
LLSD LLWindowWin32::getNativeKeyData()
{
- LLSD result = LLSD::emptyMap();
+ LLSD result = LLSD::emptyMap();
- result["scan_code"] = (S32)mKeyScanCode;
- result["virtual_key"] = (S32)mKeyVirtualKey;
- result["msg"] = ll_sd_from_U32(mRawMsg);
- result["w_param"] = ll_sd_from_U32(mRawWParam);
- result["l_param"] = ll_sd_from_U32(mRawLParam);
+ result["scan_code"] = (S32)mKeyScanCode;
+ result["virtual_key"] = (S32)mKeyVirtualKey;
+ result["msg"] = ll_sd_from_U32(mRawMsg);
+ result["w_param"] = ll_sd_from_U32(mRawWParam);
+ result["l_param"] = ll_sd_from_U32(mRawLParam);
- return result;
+ return result;
}
BOOL LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b )
{
- BOOL retval = FALSE;
-
- static CHOOSECOLOR cc;
- static COLORREF crCustColors[16];
- cc.lStructSize = sizeof(CHOOSECOLOR);
- cc.hwndOwner = mWindowHandle;
- cc.hInstance = NULL;
- cc.rgbResult = RGB ((*r * 255.f),(*g *255.f),(*b * 255.f));
- //cc.rgbResult = RGB (0x80,0x80,0x80);
- cc.lpCustColors = crCustColors;
- cc.Flags = CC_RGBINIT | CC_FULLOPEN;
- cc.lCustData = 0;
- cc.lpfnHook = NULL;
- cc.lpTemplateName = NULL;
-
- // This call is modal, so pause agent
- //send_agent_pause(); // this is in newview and we don't want to set up a dependency
- {
- retval = ChooseColor(&cc);
- }
- //send_agent_resume(); // this is in newview and we don't want to set up a dependency
-
- *b = ((F32)((cc.rgbResult >> 16) & 0xff)) / 255.f;
-
- *g = ((F32)((cc.rgbResult >> 8) & 0xff)) / 255.f;
-
- *r = ((F32)(cc.rgbResult & 0xff)) / 255.f;
-
- return (retval);
+ BOOL retval = FALSE;
+
+ static CHOOSECOLOR cc;
+ static COLORREF crCustColors[16];
+ cc.lStructSize = sizeof(CHOOSECOLOR);
+ cc.hwndOwner = mWindowHandle;
+ cc.hInstance = NULL;
+ cc.rgbResult = RGB ((*r * 255.f),(*g *255.f),(*b * 255.f));
+ //cc.rgbResult = RGB (0x80,0x80,0x80);
+ cc.lpCustColors = crCustColors;
+ cc.Flags = CC_RGBINIT | CC_FULLOPEN;
+ cc.lCustData = 0;
+ cc.lpfnHook = NULL;
+ cc.lpTemplateName = NULL;
+
+ // This call is modal, so pause agent
+ //send_agent_pause(); // this is in newview and we don't want to set up a dependency
+ {
+ retval = ChooseColor(&cc);
+ }
+ //send_agent_resume(); // this is in newview and we don't want to set up a dependency
+
+ *b = ((F32)((cc.rgbResult >> 16) & 0xff)) / 255.f;
+
+ *g = ((F32)((cc.rgbResult >> 8) & 0xff)) / 255.f;
+
+ *r = ((F32)(cc.rgbResult & 0xff)) / 255.f;
+
+ return (retval);
}
void *LLWindowWin32::getPlatformWindow()
{
- return (void*)mWindowHandle;
+ return (void*)mWindowHandle;
}
void LLWindowWin32::bringToFront()
@@ -3846,40 +3853,40 @@ void LLWindowWin32::focusClient()
void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
{
- if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable())
- {
- return;
- }
-
- if (preeditor != mPreeditor && !b)
- {
- // This condition may occur with a call to
- // setEnabled(BOOL) from LLTextEditor or LLLineEditor
- // when the control is not focused.
- // We need to silently ignore the case so that
- // the language input status of the focused control
- // is not disturbed.
- return;
- }
-
- // Take care of old and new preeditors.
- if (preeditor != mPreeditor || !b)
- {
- if (sLanguageTextInputAllowed)
- {
- interruptLanguageTextInput();
- }
- mPreeditor = (b ? preeditor : NULL);
- }
-
- sLanguageTextInputAllowed = b;
+ if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable())
+ {
+ return;
+ }
+
+ if (preeditor != mPreeditor && !b)
+ {
+ // This condition may occur with a call to
+ // setEnabled(BOOL) from LLTextEditor or LLLineEditor
+ // when the control is not focused.
+ // We need to silently ignore the case so that
+ // the language input status of the focused control
+ // is not disturbed.
+ return;
+ }
+
+ // Take care of old and new preeditors.
+ if (preeditor != mPreeditor || !b)
+ {
+ if (sLanguageTextInputAllowed)
+ {
+ interruptLanguageTextInput();
+ }
+ mPreeditor = (b ? preeditor : NULL);
+ }
+
+ sLanguageTextInputAllowed = b;
if (sLanguageTextInputAllowed)
{
mWindowThread->post([=]()
{
- // Allowing: Restore the previous IME status, so that the user has a feeling that the previous
- // text input continues naturally. Be careful, however, the IME status is meaningful only during the user keeps
+ // Allowing: Restore the previous IME status, so that the user has a feeling that the previous
+ // text input continues naturally. Be careful, however, the IME status is meaningful only during the user keeps
// using same Input Locale (aka Keyboard Layout).
if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale)
{
@@ -3907,7 +3914,7 @@ void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
{
LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode);
- // We need both ImmSetConversionStatus and ImmSetOpenStatus here to surely disable IME's
+ // We need both ImmSetConversionStatus and ImmSetOpenStatus here to surely disable IME's
// keyboard hooking, because Some IME reacts only on the former and some other on the latter...
LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode);
LLWinImm::setOpenStatus(himc, FALSE);
@@ -3918,194 +3925,194 @@ void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
}
}
-void LLWindowWin32::fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds,
- CANDIDATEFORM *form)
+void LLWindowWin32::fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds,
+ CANDIDATEFORM *form)
{
- LLCoordWindow caret_coord, top_left, bottom_right;
- convertCoords(caret, &caret_coord);
- convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left);
- convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right);
+ LLCoordWindow caret_coord, top_left, bottom_right;
+ convertCoords(caret, &caret_coord);
+ convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left);
+ convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right);
- memset(form, 0, sizeof(CANDIDATEFORM));
- form->dwStyle = CFS_EXCLUDE;
- form->ptCurrentPos.x = caret_coord.mX;
- form->ptCurrentPos.y = caret_coord.mY;
- form->rcArea.left = top_left.mX;
- form->rcArea.top = top_left.mY;
- form->rcArea.right = bottom_right.mX;
- form->rcArea.bottom = bottom_right.mY;
+ memset(form, 0, sizeof(CANDIDATEFORM));
+ form->dwStyle = CFS_EXCLUDE;
+ form->ptCurrentPos.x = caret_coord.mX;
+ form->ptCurrentPos.y = caret_coord.mY;
+ form->rcArea.left = top_left.mX;
+ form->rcArea.top = top_left.mY;
+ form->rcArea.right = bottom_right.mX;
+ form->rcArea.bottom = bottom_right.mY;
}
// Put the IME window at the right place (near current text input). Point coordinates should be the top of the current text line.
void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position )
{
- if (sLanguageTextInputAllowed && LLWinImm::isAvailable())
- {
- HIMC himc = LLWinImm::getContext(mWindowHandle);
+ if (sLanguageTextInputAllowed && LLWinImm::isAvailable())
+ {
+ HIMC himc = LLWinImm::getContext(mWindowHandle);
- LLCoordWindow win_pos;
- convertCoords( position, &win_pos );
+ LLCoordWindow win_pos;
+ convertCoords( position, &win_pos );
- if ( win_pos.mX >= 0 && win_pos.mY >= 0 &&
- (win_pos.mX != sWinIMEWindowPosition.mX) || (win_pos.mY != sWinIMEWindowPosition.mY) )
- {
- COMPOSITIONFORM ime_form;
- memset( &ime_form, 0, sizeof(ime_form) );
- ime_form.dwStyle = CFS_POINT;
- ime_form.ptCurrentPos.x = win_pos.mX;
- ime_form.ptCurrentPos.y = win_pos.mY;
+ if ( win_pos.mX >= 0 && win_pos.mY >= 0 &&
+ (win_pos.mX != sWinIMEWindowPosition.mX) || (win_pos.mY != sWinIMEWindowPosition.mY) )
+ {
+ COMPOSITIONFORM ime_form;
+ memset( &ime_form, 0, sizeof(ime_form) );
+ ime_form.dwStyle = CFS_POINT;
+ ime_form.ptCurrentPos.x = win_pos.mX;
+ ime_form.ptCurrentPos.y = win_pos.mY;
- LLWinImm::setCompositionWindow( himc, &ime_form );
+ LLWinImm::setCompositionWindow( himc, &ime_form );
- sWinIMEWindowPosition = win_pos;
- }
+ sWinIMEWindowPosition = win_pos;
+ }
- LLWinImm::releaseContext(mWindowHandle, himc);
- }
+ LLWinImm::releaseContext(mWindowHandle, himc);
+ }
}
void LLWindowWin32::fillCharPosition(const LLCoordGL& caret, const LLRect& bounds, const LLRect& control,
- IMECHARPOSITION *char_position)
+ IMECHARPOSITION *char_position)
{
- LLCoordScreen caret_coord, top_left, bottom_right;
- convertCoords(caret, &caret_coord);
- convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left);
- convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right);
+ LLCoordScreen caret_coord, top_left, bottom_right;
+ convertCoords(caret, &caret_coord);
+ convertCoords(LLCoordGL(bounds.mLeft, bounds.mTop), &top_left);
+ convertCoords(LLCoordGL(bounds.mRight, bounds.mBottom), &bottom_right);
- char_position->pt.x = caret_coord.mX;
- char_position->pt.y = top_left.mY; // Windows wants the coordinate of upper left corner of a character...
- char_position->cLineHeight = bottom_right.mY - top_left.mY;
- char_position->rcDocument.left = top_left.mX;
- char_position->rcDocument.top = top_left.mY;
- char_position->rcDocument.right = bottom_right.mX;
- char_position->rcDocument.bottom = bottom_right.mY;
+ char_position->pt.x = caret_coord.mX;
+ char_position->pt.y = top_left.mY; // Windows wants the coordinate of upper left corner of a character...
+ char_position->cLineHeight = bottom_right.mY - top_left.mY;
+ char_position->rcDocument.left = top_left.mX;
+ char_position->rcDocument.top = top_left.mY;
+ char_position->rcDocument.right = bottom_right.mX;
+ char_position->rcDocument.bottom = bottom_right.mY;
}
void LLWindowWin32::fillCompositionLogfont(LOGFONT *logfont)
{
- // Our font is a list of FreeType recognized font files that may
- // not have a corresponding ones in Windows' fonts. Hence, we
- // can't simply tell Windows which font we are using. We will
- // notify a _standard_ font for a current input locale instead.
- // We use a hard-coded knowledge about the Windows' standard
- // configuration to do so...
-
- memset(logfont, 0, sizeof(LOGFONT));
-
- const WORD lang_id = LOWORD(GetKeyboardLayout(0));
- switch (PRIMARYLANGID(lang_id))
- {
- case LANG_CHINESE:
- // We need to identify one of two Chinese fonts.
- switch (SUBLANGID(lang_id))
- {
- case SUBLANG_CHINESE_SIMPLIFIED:
- case SUBLANG_CHINESE_SINGAPORE:
- logfont->lfCharSet = GB2312_CHARSET;
- lstrcpy(logfont->lfFaceName, TEXT("SimHei"));
- break;
- case SUBLANG_CHINESE_TRADITIONAL:
- case SUBLANG_CHINESE_HONGKONG:
- case SUBLANG_CHINESE_MACAU:
- default:
- logfont->lfCharSet = CHINESEBIG5_CHARSET;
- lstrcpy(logfont->lfFaceName, TEXT("MingLiU"));
- break;
- }
- break;
- case LANG_JAPANESE:
- logfont->lfCharSet = SHIFTJIS_CHARSET;
- lstrcpy(logfont->lfFaceName, TEXT("MS Gothic"));
- break;
- case LANG_KOREAN:
- logfont->lfCharSet = HANGUL_CHARSET;
- lstrcpy(logfont->lfFaceName, TEXT("Gulim"));
- break;
- default:
- logfont->lfCharSet = ANSI_CHARSET;
- lstrcpy(logfont->lfFaceName, TEXT("Tahoma"));
- break;
- }
-
- logfont->lfHeight = mPreeditor->getPreeditFontSize();
- logfont->lfWeight = FW_NORMAL;
-}
+ // Our font is a list of FreeType recognized font files that may
+ // not have a corresponding ones in Windows' fonts. Hence, we
+ // can't simply tell Windows which font we are using. We will
+ // notify a _standard_ font for a current input locale instead.
+ // We use a hard-coded knowledge about the Windows' standard
+ // configuration to do so...
+
+ memset(logfont, 0, sizeof(LOGFONT));
+
+ const WORD lang_id = LOWORD(GetKeyboardLayout(0));
+ switch (PRIMARYLANGID(lang_id))
+ {
+ case LANG_CHINESE:
+ // We need to identify one of two Chinese fonts.
+ switch (SUBLANGID(lang_id))
+ {
+ case SUBLANG_CHINESE_SIMPLIFIED:
+ case SUBLANG_CHINESE_SINGAPORE:
+ logfont->lfCharSet = GB2312_CHARSET;
+ lstrcpy(logfont->lfFaceName, TEXT("SimHei"));
+ break;
+ case SUBLANG_CHINESE_TRADITIONAL:
+ case SUBLANG_CHINESE_HONGKONG:
+ case SUBLANG_CHINESE_MACAU:
+ default:
+ logfont->lfCharSet = CHINESEBIG5_CHARSET;
+ lstrcpy(logfont->lfFaceName, TEXT("MingLiU"));
+ break;
+ }
+ break;
+ case LANG_JAPANESE:
+ logfont->lfCharSet = SHIFTJIS_CHARSET;
+ lstrcpy(logfont->lfFaceName, TEXT("MS Gothic"));
+ break;
+ case LANG_KOREAN:
+ logfont->lfCharSet = HANGUL_CHARSET;
+ lstrcpy(logfont->lfFaceName, TEXT("Gulim"));
+ break;
+ default:
+ logfont->lfCharSet = ANSI_CHARSET;
+ lstrcpy(logfont->lfFaceName, TEXT("Tahoma"));
+ break;
+ }
+
+ logfont->lfHeight = mPreeditor->getPreeditFontSize();
+ logfont->lfWeight = FW_NORMAL;
+}
U32 LLWindowWin32::fillReconvertString(const LLWString &text,
- S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string)
+ S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string)
{
- const llutf16string text_utf16 = wstring_to_utf16str(text);
- const DWORD required_size = sizeof(RECONVERTSTRING) + (text_utf16.length() + 1) * sizeof(WCHAR);
- if (reconvert_string && reconvert_string->dwSize >= required_size)
- {
- const DWORD focus_utf16_at = wstring_utf16_length(text, 0, focus);
- const DWORD focus_utf16_length = wstring_utf16_length(text, focus, focus_length);
-
- reconvert_string->dwVersion = 0;
- reconvert_string->dwStrLen = text_utf16.length();
- reconvert_string->dwStrOffset = sizeof(RECONVERTSTRING);
- reconvert_string->dwCompStrLen = focus_utf16_length;
- reconvert_string->dwCompStrOffset = focus_utf16_at * sizeof(WCHAR);
- reconvert_string->dwTargetStrLen = 0;
- reconvert_string->dwTargetStrOffset = focus_utf16_at * sizeof(WCHAR);
-
- const LPWSTR text = (LPWSTR)((BYTE *)reconvert_string + sizeof(RECONVERTSTRING));
- memcpy(text, text_utf16.c_str(), (text_utf16.length() + 1) * sizeof(WCHAR));
- }
- return required_size;
+ const llutf16string text_utf16 = wstring_to_utf16str(text);
+ const DWORD required_size = sizeof(RECONVERTSTRING) + (text_utf16.length() + 1) * sizeof(WCHAR);
+ if (reconvert_string && reconvert_string->dwSize >= required_size)
+ {
+ const DWORD focus_utf16_at = wstring_utf16_length(text, 0, focus);
+ const DWORD focus_utf16_length = wstring_utf16_length(text, focus, focus_length);
+
+ reconvert_string->dwVersion = 0;
+ reconvert_string->dwStrLen = text_utf16.length();
+ reconvert_string->dwStrOffset = sizeof(RECONVERTSTRING);
+ reconvert_string->dwCompStrLen = focus_utf16_length;
+ reconvert_string->dwCompStrOffset = focus_utf16_at * sizeof(WCHAR);
+ reconvert_string->dwTargetStrLen = 0;
+ reconvert_string->dwTargetStrOffset = focus_utf16_at * sizeof(WCHAR);
+
+ const LPWSTR text = (LPWSTR)((BYTE *)reconvert_string + sizeof(RECONVERTSTRING));
+ memcpy(text, text_utf16.c_str(), (text_utf16.length() + 1) * sizeof(WCHAR));
+ }
+ return required_size;
}
void LLWindowWin32::updateLanguageTextInputArea()
{
- if (!mPreeditor || !LLWinImm::isAvailable())
- {
- return;
- }
-
- LLCoordGL caret_coord;
- LLRect preedit_bounds;
- if (mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL))
- {
- mLanguageTextInputPointGL = caret_coord;
- mLanguageTextInputAreaGL = preedit_bounds;
-
- CANDIDATEFORM candidate_form;
- fillCandidateForm(caret_coord, preedit_bounds, &candidate_form);
-
- HIMC himc = LLWinImm::getContext(mWindowHandle);
- // Win32 document says there may be up to 4 candidate windows.
- // This magic number 4 appears only in the document, and
- // there are no constant/macro for the value...
- for (int i = 3; i >= 0; --i)
- {
- candidate_form.dwIndex = i;
- LLWinImm::setCandidateWindow(himc, &candidate_form);
- }
- LLWinImm::releaseContext(mWindowHandle, himc);
- }
+ if (!mPreeditor || !LLWinImm::isAvailable())
+ {
+ return;
+ }
+
+ LLCoordGL caret_coord;
+ LLRect preedit_bounds;
+ if (mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL))
+ {
+ mLanguageTextInputPointGL = caret_coord;
+ mLanguageTextInputAreaGL = preedit_bounds;
+
+ CANDIDATEFORM candidate_form;
+ fillCandidateForm(caret_coord, preedit_bounds, &candidate_form);
+
+ HIMC himc = LLWinImm::getContext(mWindowHandle);
+ // Win32 document says there may be up to 4 candidate windows.
+ // This magic number 4 appears only in the document, and
+ // there are no constant/macro for the value...
+ for (int i = 3; i >= 0; --i)
+ {
+ candidate_form.dwIndex = i;
+ LLWinImm::setCandidateWindow(himc, &candidate_form);
+ }
+ LLWinImm::releaseContext(mWindowHandle, himc);
+ }
}
void LLWindowWin32::interruptLanguageTextInput()
{
ASSERT_MAIN_THREAD();
- if (mPreeditor && LLWinImm::isAvailable())
- {
- HIMC himc = LLWinImm::getContext(mWindowHandle);
- LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
- LLWinImm::releaseContext(mWindowHandle, himc);
- }
+ if (mPreeditor && LLWinImm::isAvailable())
+ {
+ HIMC himc = LLWinImm::getContext(mWindowHandle);
+ LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
+ LLWinImm::releaseContext(mWindowHandle, himc);
+ }
}
void LLWindowWin32::handleStartCompositionMessage()
{
- // Let IME know the font to use in feedback UI.
- LOGFONT logfont;
- fillCompositionLogfont(&logfont);
- HIMC himc = LLWinImm::getContext(mWindowHandle);
- LLWinImm::setCompositionFont(himc, &logfont);
- LLWinImm::releaseContext(mWindowHandle, himc);
+ // Let IME know the font to use in feedback UI.
+ LOGFONT logfont;
+ fillCompositionLogfont(&logfont);
+ HIMC himc = LLWinImm::getContext(mWindowHandle);
+ LLWinImm::setCompositionFont(himc, &logfont);
+ LLWinImm::releaseContext(mWindowHandle, himc);
}
// Handle WM_IME_COMPOSITION message.
@@ -4116,156 +4123,156 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
{
return;
}
- BOOL needs_update = FALSE;
- LLWString result_string;
- LLWString preedit_string;
- S32 preedit_string_utf16_length = 0;
- LLPreeditor::segment_lengths_t preedit_segment_lengths;
- LLPreeditor::standouts_t preedit_standouts;
-
- // Step I: Receive details of preedits from IME.
-
- HIMC himc = LLWinImm::getContext(mWindowHandle);
-
- if (indexes & GCS_RESULTSTR)
- {
- LONG size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, NULL, 0);
- if (size >= 0)
- {
- const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1];
- size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, data, size);
- if (size > 0)
- {
- result_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
- }
- delete[] data;
- needs_update = TRUE;
- }
- }
-
- if (indexes & GCS_COMPSTR)
- {
- LONG size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, NULL, 0);
- if (size >= 0)
- {
- const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1];
- size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, data, size);
- if (size > 0)
- {
- preedit_string_utf16_length = size / sizeof(WCHAR);
- preedit_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
- }
- delete[] data;
- needs_update = TRUE;
- }
- }
-
- if ((indexes & GCS_COMPCLAUSE) && preedit_string.length() > 0)
- {
- LONG size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, NULL, 0);
- if (size > 0)
- {
- const LPDWORD data = new DWORD[size / sizeof(DWORD)];
- size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, data, size);
- if (size >= sizeof(DWORD) * 2
- && data[0] == 0 && data[size / sizeof(DWORD) - 1] == preedit_string_utf16_length)
- {
- preedit_segment_lengths.resize(size / sizeof(DWORD) - 1);
- S32 offset = 0;
- for (U32 i = 0; i < preedit_segment_lengths.size(); i++)
- {
- const S32 length = wstring_wstring_length_from_utf16_length(preedit_string, offset, data[i + 1] - data[i]);
- preedit_segment_lengths[i] = length;
- offset += length;
- }
- }
- delete[] data;
- }
- }
-
- if ((indexes & GCS_COMPATTR) && preedit_segment_lengths.size() > 1)
- {
- LONG size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, NULL, 0);
- if (size > 0)
- {
- const LPBYTE data = new BYTE[size / sizeof(BYTE)];
- size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, data, size);
- if (size == preedit_string_utf16_length)
- {
- preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
- S32 offset = 0;
- for (U32 i = 0; i < preedit_segment_lengths.size(); i++)
- {
- if (ATTR_TARGET_CONVERTED == data[offset] || ATTR_TARGET_NOTCONVERTED == data[offset])
- {
- preedit_standouts[i] = TRUE;
- }
- offset += wstring_utf16_length(preedit_string, offset, preedit_segment_lengths[i]);
- }
- }
- delete[] data;
- }
- }
-
- S32 caret_position = preedit_string.length();
- if (indexes & GCS_CURSORPOS)
- {
- const S32 caret_position_utf16 = LLWinImm::getCompositionString(himc, GCS_CURSORPOS, NULL, 0);
- if (caret_position_utf16 >= 0 && caret_position <= preedit_string_utf16_length)
- {
- caret_position = wstring_wstring_length_from_utf16_length(preedit_string, 0, caret_position_utf16);
- }
- }
-
- if (indexes == 0)
- {
- // I'm not sure this condition really happens, but
- // Windows SDK document says it is an indication
- // of "reset everything."
- needs_update = TRUE;
- }
-
- LLWinImm::releaseContext(mWindowHandle, himc);
-
- // Step II: Update the active preeditor.
-
- if (needs_update)
- {
+ BOOL needs_update = FALSE;
+ LLWString result_string;
+ LLWString preedit_string;
+ S32 preedit_string_utf16_length = 0;
+ LLPreeditor::segment_lengths_t preedit_segment_lengths;
+ LLPreeditor::standouts_t preedit_standouts;
+
+ // Step I: Receive details of preedits from IME.
+
+ HIMC himc = LLWinImm::getContext(mWindowHandle);
+
+ if (indexes & GCS_RESULTSTR)
+ {
+ LONG size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, NULL, 0);
+ if (size >= 0)
+ {
+ const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1];
+ size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, data, size);
+ if (size > 0)
+ {
+ result_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
+ }
+ delete[] data;
+ needs_update = TRUE;
+ }
+ }
+
+ if (indexes & GCS_COMPSTR)
+ {
+ LONG size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, NULL, 0);
+ if (size >= 0)
+ {
+ const LPWSTR data = new WCHAR[size / sizeof(WCHAR) + 1];
+ size = LLWinImm::getCompositionString(himc, GCS_COMPSTR, data, size);
+ if (size > 0)
+ {
+ preedit_string_utf16_length = size / sizeof(WCHAR);
+ preedit_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
+ }
+ delete[] data;
+ needs_update = TRUE;
+ }
+ }
+
+ if ((indexes & GCS_COMPCLAUSE) && preedit_string.length() > 0)
+ {
+ LONG size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, NULL, 0);
+ if (size > 0)
+ {
+ const LPDWORD data = new DWORD[size / sizeof(DWORD)];
+ size = LLWinImm::getCompositionString(himc, GCS_COMPCLAUSE, data, size);
+ if (size >= sizeof(DWORD) * 2
+ && data[0] == 0 && data[size / sizeof(DWORD) - 1] == preedit_string_utf16_length)
+ {
+ preedit_segment_lengths.resize(size / sizeof(DWORD) - 1);
+ S32 offset = 0;
+ for (U32 i = 0; i < preedit_segment_lengths.size(); i++)
+ {
+ const S32 length = wstring_wstring_length_from_utf16_length(preedit_string, offset, data[i + 1] - data[i]);
+ preedit_segment_lengths[i] = length;
+ offset += length;
+ }
+ }
+ delete[] data;
+ }
+ }
+
+ if ((indexes & GCS_COMPATTR) && preedit_segment_lengths.size() > 1)
+ {
+ LONG size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, NULL, 0);
+ if (size > 0)
+ {
+ const LPBYTE data = new BYTE[size / sizeof(BYTE)];
+ size = LLWinImm::getCompositionString(himc, GCS_COMPATTR, data, size);
+ if (size == preedit_string_utf16_length)
+ {
+ preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
+ S32 offset = 0;
+ for (U32 i = 0; i < preedit_segment_lengths.size(); i++)
+ {
+ if (ATTR_TARGET_CONVERTED == data[offset] || ATTR_TARGET_NOTCONVERTED == data[offset])
+ {
+ preedit_standouts[i] = TRUE;
+ }
+ offset += wstring_utf16_length(preedit_string, offset, preedit_segment_lengths[i]);
+ }
+ }
+ delete[] data;
+ }
+ }
+
+ S32 caret_position = preedit_string.length();
+ if (indexes & GCS_CURSORPOS)
+ {
+ const S32 caret_position_utf16 = LLWinImm::getCompositionString(himc, GCS_CURSORPOS, NULL, 0);
+ if (caret_position_utf16 >= 0 && caret_position <= preedit_string_utf16_length)
+ {
+ caret_position = wstring_wstring_length_from_utf16_length(preedit_string, 0, caret_position_utf16);
+ }
+ }
+
+ if (indexes == 0)
+ {
+ // I'm not sure this condition really happens, but
+ // Windows SDK document says it is an indication
+ // of "reset everything."
+ needs_update = TRUE;
+ }
+
+ LLWinImm::releaseContext(mWindowHandle, himc);
+
+ // Step II: Update the active preeditor.
+
+ if (needs_update)
+ {
if (preedit_string.length() != 0 || result_string.length() != 0)
{
mPreeditor->resetPreedit();
}
- if (result_string.length() > 0)
- {
- for (LLWString::const_iterator i = result_string.begin(); i != result_string.end(); i++)
- {
- mPreeditor->handleUnicodeCharHere(*i);
- }
- }
-
- if (preedit_string.length() == 0)
- {
- preedit_segment_lengths.clear();
- preedit_standouts.clear();
- }
- else
- {
- if (preedit_segment_lengths.size() == 0)
- {
- preedit_segment_lengths.assign(1, preedit_string.length());
- }
- if (preedit_standouts.size() == 0)
- {
- preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
- }
- }
- mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
-
- // Some IME doesn't query char position after WM_IME_COMPOSITION,
- // so we need to update them actively.
- updateLanguageTextInputArea();
- }
+ if (result_string.length() > 0)
+ {
+ for (LLWString::const_iterator i = result_string.begin(); i != result_string.end(); i++)
+ {
+ mPreeditor->handleUnicodeCharHere(*i);
+ }
+ }
+
+ if (preedit_string.length() == 0)
+ {
+ preedit_segment_lengths.clear();
+ preedit_standouts.clear();
+ }
+ else
+ {
+ if (preedit_segment_lengths.size() == 0)
+ {
+ preedit_segment_lengths.assign(1, preedit_string.length());
+ }
+ if (preedit_standouts.size() == 0)
+ {
+ preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
+ }
+ }
+ mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
+
+ // Some IME doesn't query char position after WM_IME_COMPOSITION,
+ // so we need to update them actively.
+ updateLanguageTextInputArea();
+ }
}
// Given a text and a focus range, find_context finds and returns a
@@ -4275,24 +4282,24 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_length, S32 *offset)
{
- static const S32 CONTEXT_EXCESS = 30; // This value is by experiences.
+ static const S32 CONTEXT_EXCESS = 30; // This value is by experiences.
- const S32 e = llmin((S32) wtext.length(), focus + focus_length + CONTEXT_EXCESS);
- S32 end = focus + focus_length;
- while (end < e && '\n' != wtext[end])
- {
- end++;
- }
+ const S32 e = llmin((S32) wtext.length(), focus + focus_length + CONTEXT_EXCESS);
+ S32 end = focus + focus_length;
+ while (end < e && '\n' != wtext[end])
+ {
+ end++;
+ }
- const S32 s = llmax(0, focus - CONTEXT_EXCESS);
- S32 start = focus;
- while (start > s && '\n' != wtext[start - 1])
- {
- --start;
- }
+ const S32 s = llmax(0, focus - CONTEXT_EXCESS);
+ S32 start = focus;
+ while (start > s && '\n' != wtext[start - 1])
+ {
+ --start;
+ }
- *offset = start;
- return wtext.substr(start, end - start);
+ *offset = start;
+ return wtext.substr(start, end - start);
}
// final stage of handling drop requests - both from WM_DROPFILES message
@@ -4300,7 +4307,7 @@ static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_leng
LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url )
{
ASSERT_MAIN_THREAD();
- return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url );
+ return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url );
}
// Handle WM_IME_REQUEST message.
@@ -4310,153 +4317,153 @@ LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( cons
BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *result)
{
- if ( mPreeditor )
- {
- switch (request)
- {
- case IMR_CANDIDATEWINDOW: // http://msdn2.microsoft.com/en-us/library/ms776080.aspx
- {
- LLCoordGL caret_coord;
- LLRect preedit_bounds;
- mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL);
-
- CANDIDATEFORM *const form = (CANDIDATEFORM *)param;
- DWORD const dwIndex = form->dwIndex;
- fillCandidateForm(caret_coord, preedit_bounds, form);
- form->dwIndex = dwIndex;
-
- *result = 1;
- return TRUE;
- }
- case IMR_QUERYCHARPOSITION:
- {
- IMECHARPOSITION *const char_position = (IMECHARPOSITION *)param;
-
- // char_position->dwCharPos counts in number of
- // WCHARs, i.e., UTF-16 encoding units, so we can't simply pass the
- // number to getPreeditLocation.
-
- const LLWString & wtext = mPreeditor->getPreeditString();
- S32 preedit, preedit_length;
- mPreeditor->getPreeditRange(&preedit, &preedit_length);
- LLCoordGL caret_coord;
- LLRect preedit_bounds, text_control;
- const S32 position = wstring_wstring_length_from_utf16_length(wtext, preedit, char_position->dwCharPos);
-
- if (!mPreeditor->getPreeditLocation(position, &caret_coord, &preedit_bounds, &text_control))
- {
- LL_WARNS("Window") << "*** IMR_QUERYCHARPOSITON called but getPreeditLocation failed." << LL_ENDL;
- return FALSE;
- }
-
- fillCharPosition(caret_coord, preedit_bounds, text_control, char_position);
-
- *result = 1;
- return TRUE;
- }
- case IMR_COMPOSITIONFONT:
- {
- fillCompositionLogfont((LOGFONT *)param);
-
- *result = 1;
- return TRUE;
- }
- case IMR_RECONVERTSTRING:
- {
- mPreeditor->resetPreedit();
- const LLWString & wtext = mPreeditor->getPreeditString();
- S32 select, select_length;
- mPreeditor->getSelectionRange(&select, &select_length);
-
- S32 context_offset;
- const LLWString context = find_context(wtext, select, select_length, &context_offset);
-
- RECONVERTSTRING * const reconvert_string = (RECONVERTSTRING *)param;
- const U32 size = fillReconvertString(context, select - context_offset, select_length, reconvert_string);
- if (reconvert_string)
- {
- if (select_length == 0)
- {
- // Let the IME to decide the reconversion range, and
- // adjust the reconvert_string structure accordingly.
- HIMC himc = LLWinImm::getContext(mWindowHandle);
- const BOOL adjusted = LLWinImm::setCompositionString(himc,
- SCS_QUERYRECONVERTSTRING, reconvert_string, size, NULL, 0);
- LLWinImm::releaseContext(mWindowHandle, himc);
- if (adjusted)
- {
- const llutf16string & text_utf16 = wstring_to_utf16str(context);
- const S32 new_preedit_start = reconvert_string->dwCompStrOffset / sizeof(WCHAR);
- const S32 new_preedit_end = new_preedit_start + reconvert_string->dwCompStrLen;
- select = utf16str_wstring_length(text_utf16, new_preedit_start);
- select_length = utf16str_wstring_length(text_utf16, new_preedit_end) - select;
- select += context_offset;
- }
- }
- mPreeditor->markAsPreedit(select, select_length);
- }
-
- *result = size;
- return TRUE;
- }
- case IMR_CONFIRMRECONVERTSTRING:
- {
- *result = FALSE;
- return TRUE;
- }
- case IMR_DOCUMENTFEED:
- {
- const LLWString & wtext = mPreeditor->getPreeditString();
- S32 preedit, preedit_length;
- mPreeditor->getPreeditRange(&preedit, &preedit_length);
-
- S32 context_offset;
- LLWString context = find_context(wtext, preedit, preedit_length, &context_offset);
- preedit -= context_offset;
- preedit_length = llmin(preedit_length, (S32)context.length() - preedit);
- if (preedit_length > 0 && preedit >= 0)
- {
- // IMR_DOCUMENTFEED may be called when we have an active preedit.
- // We should pass the context string *excluding* the preedit string.
- // Otherwise, some IME are confused.
- context.erase(preedit, preedit_length);
- }
-
- RECONVERTSTRING *reconvert_string = (RECONVERTSTRING *)param;
- *result = fillReconvertString(context, preedit, 0, reconvert_string);
- return TRUE;
- }
- default:
- return FALSE;
- }
- }
-
- return FALSE;
+ if ( mPreeditor )
+ {
+ switch (request)
+ {
+ case IMR_CANDIDATEWINDOW: // http://msdn2.microsoft.com/en-us/library/ms776080.aspx
+ {
+ LLCoordGL caret_coord;
+ LLRect preedit_bounds;
+ mPreeditor->getPreeditLocation(-1, &caret_coord, &preedit_bounds, NULL);
+
+ CANDIDATEFORM *const form = (CANDIDATEFORM *)param;
+ DWORD const dwIndex = form->dwIndex;
+ fillCandidateForm(caret_coord, preedit_bounds, form);
+ form->dwIndex = dwIndex;
+
+ *result = 1;
+ return TRUE;
+ }
+ case IMR_QUERYCHARPOSITION:
+ {
+ IMECHARPOSITION *const char_position = (IMECHARPOSITION *)param;
+
+ // char_position->dwCharPos counts in number of
+ // WCHARs, i.e., UTF-16 encoding units, so we can't simply pass the
+ // number to getPreeditLocation.
+
+ const LLWString & wtext = mPreeditor->getPreeditString();
+ S32 preedit, preedit_length;
+ mPreeditor->getPreeditRange(&preedit, &preedit_length);
+ LLCoordGL caret_coord;
+ LLRect preedit_bounds, text_control;
+ const S32 position = wstring_wstring_length_from_utf16_length(wtext, preedit, char_position->dwCharPos);
+
+ if (!mPreeditor->getPreeditLocation(position, &caret_coord, &preedit_bounds, &text_control))
+ {
+ LL_WARNS("Window") << "*** IMR_QUERYCHARPOSITON called but getPreeditLocation failed." << LL_ENDL;
+ return FALSE;
+ }
+
+ fillCharPosition(caret_coord, preedit_bounds, text_control, char_position);
+
+ *result = 1;
+ return TRUE;
+ }
+ case IMR_COMPOSITIONFONT:
+ {
+ fillCompositionLogfont((LOGFONT *)param);
+
+ *result = 1;
+ return TRUE;
+ }
+ case IMR_RECONVERTSTRING:
+ {
+ mPreeditor->resetPreedit();
+ const LLWString & wtext = mPreeditor->getPreeditString();
+ S32 select, select_length;
+ mPreeditor->getSelectionRange(&select, &select_length);
+
+ S32 context_offset;
+ const LLWString context = find_context(wtext, select, select_length, &context_offset);
+
+ RECONVERTSTRING * const reconvert_string = (RECONVERTSTRING *)param;
+ const U32 size = fillReconvertString(context, select - context_offset, select_length, reconvert_string);
+ if (reconvert_string)
+ {
+ if (select_length == 0)
+ {
+ // Let the IME to decide the reconversion range, and
+ // adjust the reconvert_string structure accordingly.
+ HIMC himc = LLWinImm::getContext(mWindowHandle);
+ const BOOL adjusted = LLWinImm::setCompositionString(himc,
+ SCS_QUERYRECONVERTSTRING, reconvert_string, size, NULL, 0);
+ LLWinImm::releaseContext(mWindowHandle, himc);
+ if (adjusted)
+ {
+ const llutf16string & text_utf16 = wstring_to_utf16str(context);
+ const S32 new_preedit_start = reconvert_string->dwCompStrOffset / sizeof(WCHAR);
+ const S32 new_preedit_end = new_preedit_start + reconvert_string->dwCompStrLen;
+ select = utf16str_wstring_length(text_utf16, new_preedit_start);
+ select_length = utf16str_wstring_length(text_utf16, new_preedit_end) - select;
+ select += context_offset;
+ }
+ }
+ mPreeditor->markAsPreedit(select, select_length);
+ }
+
+ *result = size;
+ return TRUE;
+ }
+ case IMR_CONFIRMRECONVERTSTRING:
+ {
+ *result = FALSE;
+ return TRUE;
+ }
+ case IMR_DOCUMENTFEED:
+ {
+ const LLWString & wtext = mPreeditor->getPreeditString();
+ S32 preedit, preedit_length;
+ mPreeditor->getPreeditRange(&preedit, &preedit_length);
+
+ S32 context_offset;
+ LLWString context = find_context(wtext, preedit, preedit_length, &context_offset);
+ preedit -= context_offset;
+ preedit_length = llmin(preedit_length, (S32)context.length() - preedit);
+ if (preedit_length > 0 && preedit >= 0)
+ {
+ // IMR_DOCUMENTFEED may be called when we have an active preedit.
+ // We should pass the context string *excluding* the preedit string.
+ // Otherwise, some IME are confused.
+ context.erase(preedit, preedit_length);
+ }
+
+ RECONVERTSTRING *reconvert_string = (RECONVERTSTRING *)param;
+ *result = fillReconvertString(context, preedit, 0, reconvert_string);
+ return TRUE;
+ }
+ default:
+ return FALSE;
+ }
+ }
+
+ return FALSE;
}
//static
void LLWindowWin32::setDPIAwareness()
{
- HMODULE hShcore = LoadLibrary(L"shcore.dll");
- if (hShcore != NULL)
- {
- SetProcessDpiAwarenessType pSPDA;
- pSPDA = (SetProcessDpiAwarenessType)GetProcAddress(hShcore, "SetProcessDpiAwareness");
- if (pSPDA)
- {
-
- HRESULT hr = pSPDA(PROCESS_PER_MONITOR_DPI_AWARE);
- if (hr != S_OK)
- {
- LL_WARNS() << "SetProcessDpiAwareness() function returned an error. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
- }
- }
- FreeLibrary(hShcore);
- }
- else
- {
- LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
- }
+ HMODULE hShcore = LoadLibrary(L"shcore.dll");
+ if (hShcore != NULL)
+ {
+ SetProcessDpiAwarenessType pSPDA;
+ pSPDA = (SetProcessDpiAwarenessType)GetProcAddress(hShcore, "SetProcessDpiAwareness");
+ if (pSPDA)
+ {
+
+ HRESULT hr = pSPDA(PROCESS_PER_MONITOR_DPI_AWARE);
+ if (hr != S_OK)
+ {
+ LL_WARNS() << "SetProcessDpiAwareness() function returned an error. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
+ }
+ }
+ FreeLibrary(hShcore);
+ }
+ else
+ {
+ LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK. Will use legacy DPI awareness API of Win XP/7" << LL_ENDL;
+ }
}
void* LLWindowWin32::getDirectInput8()
@@ -4483,76 +4490,76 @@ bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_c
F32 LLWindowWin32::getSystemUISize()
{
- F32 scale_value = 1.f;
- HWND hWnd = (HWND)getPlatformWindow();
- HDC hdc = GetDC(hWnd);
- HMONITOR hMonitor;
- HANDLE hProcess = GetCurrentProcess();
- PROCESS_DPI_AWARENESS dpi_awareness;
-
- HMODULE hShcore = LoadLibrary(L"shcore.dll");
-
- if (hShcore != NULL)
- {
- GetProcessDpiAwarenessType pGPDA;
- pGPDA = (GetProcessDpiAwarenessType)GetProcAddress(hShcore, "GetProcessDpiAwareness");
- GetDpiForMonitorType pGDFM;
- pGDFM = (GetDpiForMonitorType)GetProcAddress(hShcore, "GetDpiForMonitor");
- if (pGPDA != NULL && pGDFM != NULL)
- {
- pGPDA(hProcess, &dpi_awareness);
- if (dpi_awareness == PROCESS_PER_MONITOR_DPI_AWARE)
- {
- POINT pt;
- UINT dpix = 0, dpiy = 0;
- HRESULT hr = E_FAIL;
- RECT rect;
-
- GetWindowRect(hWnd, &rect);
- // Get the DPI for the monitor, on which the center of window is displayed and set the scaling factor
- pt.x = (rect.left + rect.right) / 2;
- pt.y = (rect.top + rect.bottom) / 2;
- hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
- hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy);
- if (hr == S_OK)
- {
- scale_value = F32(dpix) / F32(USER_DEFAULT_SCREEN_DPI);
- }
- else
- {
- LL_WARNS() << "Could not determine DPI for monitor. Setting scale to default 100 %" << LL_ENDL;
- scale_value = 1.0f;
- }
- }
- else
- {
- LL_WARNS() << "Process is not per-monitor DPI-aware. Setting scale to default 100 %" << LL_ENDL;
- scale_value = 1.0f;
- }
- }
- FreeLibrary(hShcore);
- }
- else
- {
- LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK). Using legacy DPI awareness API of Win XP/7" << LL_ENDL;
- scale_value = F32(GetDeviceCaps(hdc, LOGPIXELSX)) / F32(USER_DEFAULT_SCREEN_DPI);
- }
-
- ReleaseDC(hWnd, hdc);
- return scale_value;
+ F32 scale_value = 1.f;
+ HWND hWnd = (HWND)getPlatformWindow();
+ HDC hdc = GetDC(hWnd);
+ HMONITOR hMonitor;
+ HANDLE hProcess = GetCurrentProcess();
+ PROCESS_DPI_AWARENESS dpi_awareness;
+
+ HMODULE hShcore = LoadLibrary(L"shcore.dll");
+
+ if (hShcore != NULL)
+ {
+ GetProcessDpiAwarenessType pGPDA;
+ pGPDA = (GetProcessDpiAwarenessType)GetProcAddress(hShcore, "GetProcessDpiAwareness");
+ GetDpiForMonitorType pGDFM;
+ pGDFM = (GetDpiForMonitorType)GetProcAddress(hShcore, "GetDpiForMonitor");
+ if (pGPDA != NULL && pGDFM != NULL)
+ {
+ pGPDA(hProcess, &dpi_awareness);
+ if (dpi_awareness == PROCESS_PER_MONITOR_DPI_AWARE)
+ {
+ POINT pt;
+ UINT dpix = 0, dpiy = 0;
+ HRESULT hr = E_FAIL;
+ RECT rect;
+
+ GetWindowRect(hWnd, &rect);
+ // Get the DPI for the monitor, on which the center of window is displayed and set the scaling factor
+ pt.x = (rect.left + rect.right) / 2;
+ pt.y = (rect.top + rect.bottom) / 2;
+ hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
+ hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy);
+ if (hr == S_OK)
+ {
+ scale_value = F32(dpix) / F32(USER_DEFAULT_SCREEN_DPI);
+ }
+ else
+ {
+ LL_WARNS() << "Could not determine DPI for monitor. Setting scale to default 100 %" << LL_ENDL;
+ scale_value = 1.0f;
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Process is not per-monitor DPI-aware. Setting scale to default 100 %" << LL_ENDL;
+ scale_value = 1.0f;
+ }
+ }
+ FreeLibrary(hShcore);
+ }
+ else
+ {
+ LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK). Using legacy DPI awareness API of Win XP/7" << LL_ENDL;
+ scale_value = F32(GetDeviceCaps(hdc, LOGPIXELSX)) / F32(USER_DEFAULT_SCREEN_DPI);
+ }
+
+ ReleaseDC(hWnd, hdc);
+ return scale_value;
}
//static
std::vector<std::string> LLWindowWin32::getDisplaysResolutionList()
-{
- return sMonitorInfo.getResolutionsList();
+{
+ return sMonitorInfo.getResolutionsList();
}
//static
std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
{
- // Fonts previously in getFontListSans() have moved to fonts.xml.
- return std::vector<std::string>();
+ // Fonts previously in getFontListSans() have moved to fonts.xml.
+ return std::vector<std::string>();
}
U32 LLWindowWin32::getAvailableVRAMMegabytes()
@@ -4736,7 +4743,7 @@ void LLWindowWin32::LLWindowWin32Thread::initD3D()
if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandleThrd != 0)
{
mD3D = Direct3DCreate9(D3D_SDK_VERSION);
-
+
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
@@ -4744,7 +4751,7 @@ void LLWindowWin32::LLWindowWin32Thread::initD3D()
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandleThrd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice);
-
+
if (FAILED(res))
{
LL_WARNS() << "(fallback) CreateDevice failed: 0x" << std::hex << res << LL_ENDL;
@@ -4801,7 +4808,7 @@ void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage()
U32 afr_mb = info.AvailableForReservation / 1024 / 1024;
// correct for systems that misreport budget
if (budget_mb == 0)
- {
+ {
// fall back to available for reservation clamped between 512MB and 2GB
budget_mb = llclamp(afr_mb, (U32) 512, (U32) 2048);
}
@@ -4822,7 +4829,7 @@ void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage()
}
U32 target_mb = budget_mb;
- if (target_mb > 4096) // if 4GB are installed, try to leave 2GB free
+ if (target_mb > 4096) // if 4GB are installed, try to leave 2GB free
{
target_mb -= 2048;
}
@@ -4834,7 +4841,7 @@ void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage()
mAvailableVRAM = cu_mb < target_mb ? target_mb - cu_mb : 0;
#if 0
-
+
F32 eu_error = (F32)((S32)eu_mb - (S32)cu_mb) / (F32)cu_mb;
LL_INFOS("Window") << "\nLocal\nAFR: " << info.AvailableForReservation / 1024 / 1024
<< "\nBudget: " << info.Budget / 1024 / 1024
@@ -4908,7 +4915,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
//process any pending functions
getQueue().runPending();
}
-
+
// update available vram once every 3 seconds
static LLFrameTimer vramTimer;
if (vramTimer.getElapsedTimeF32() > 3.f)
@@ -5064,11 +5071,11 @@ void LLWindowWin32::updateWindowRect()
//called from window thread
RECT rect;
RECT client_rect;
-
+
if (GetWindowRect(mWindowHandle, &rect) &&
GetClientRect(mWindowHandle, &client_rect))
{
- post([=]
+ post([=]
{
mRect = rect;
mClientRect = client_rect;
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 6598215f97..320c1c8b88 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llwindowwin32.h
* @brief Windows implementation of LLWindow class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -45,90 +45,92 @@ typedef void (*LLW32MsgCallback)(const MSG &msg);
class LLWindowWin32 : public LLWindow
{
public:
- /*virtual*/ void show();
- /*virtual*/ void hide();
- /*virtual*/ void close();
- /*virtual*/ BOOL getVisible();
- /*virtual*/ BOOL getMinimized();
- /*virtual*/ BOOL getMaximized();
- /*virtual*/ BOOL maximize();
- /*virtual*/ void minimize();
- /*virtual*/ void restore();
- /*virtual*/ BOOL getFullscreen();
- /*virtual*/ BOOL getPosition(LLCoordScreen *position);
- /*virtual*/ BOOL getSize(LLCoordScreen *size);
- /*virtual*/ BOOL getSize(LLCoordWindow *size);
- /*virtual*/ BOOL setPosition(LLCoordScreen position);
- /*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
- /*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
- /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL);
+ /*virtual*/ void show();
+ /*virtual*/ void hide();
+ /*virtual*/ void close();
+ /*virtual*/ BOOL getVisible();
+ /*virtual*/ BOOL getMinimized();
+ /*virtual*/ BOOL getMaximized();
+ /*virtual*/ BOOL maximize();
+ /*virtual*/ void minimize();
+ /*virtual*/ void restore();
+ /*virtual*/ BOOL getFullscreen();
+ /*virtual*/ BOOL getPosition(LLCoordScreen *position);
+ /*virtual*/ BOOL getSize(LLCoordScreen *size);
+ /*virtual*/ BOOL getSize(LLCoordWindow *size);
+ /*virtual*/ BOOL setPosition(LLCoordScreen position);
+ /*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
+ /*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
+ /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL);
/*virtual*/ void setTitle(const std::string title);
void* createSharedContext() override;
void makeContextCurrent(void* context) override;
void destroySharedContext(void* context) override;
/*virtual*/ void toggleVSync(bool enable_vsync);
- /*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
- /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
+ /*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
+ /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
/*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta);
- /*virtual*/ void showCursor();
- /*virtual*/ void hideCursor();
- /*virtual*/ void showCursorFromMouseMove();
- /*virtual*/ void hideCursorUntilMouseMove();
- /*virtual*/ BOOL isCursorHidden();
- /*virtual*/ void updateCursor();
- /*virtual*/ ECursorType getCursor() const;
- /*virtual*/ void captureMouse();
- /*virtual*/ void releaseMouse();
- /*virtual*/ void setMouseClipping( BOOL b );
- /*virtual*/ BOOL isClipboardTextAvailable();
- /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst);
- /*virtual*/ BOOL copyTextToClipboard(const LLWString &src);
- /*virtual*/ void flashIcon(F32 seconds);
- /*virtual*/ F32 getGamma();
- /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
- /*virtual*/ void setFSAASamples(const U32 fsaa_samples);
- /*virtual*/ U32 getFSAASamples();
- /*virtual*/ BOOL restoreGamma(); // Restore original gamma table (before updating gamma)
- /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
- /*virtual*/ void gatherInput();
- /*virtual*/ void delayInputProcessing();
- /*virtual*/ void swapBuffers();
- /*virtual*/ void restoreGLContext() {};
-
- // handy coordinate space conversion routines
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to);
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to);
- /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to);
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to);
- /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to);
- /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to);
-
- /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
- /*virtual*/ F32 getNativeAspectRatio();
- /*virtual*/ F32 getPixelAspectRatio();
- /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
+ /*virtual*/ void showCursor();
+ /*virtual*/ void hideCursor();
+ /*virtual*/ void showCursorFromMouseMove();
+ /*virtual*/ void hideCursorUntilMouseMove();
+ /*virtual*/ BOOL isCursorHidden();
+ /*virtual*/ void updateCursor();
+ /*virtual*/ ECursorType getCursor() const;
+ /*virtual*/ void captureMouse();
+ /*virtual*/ void releaseMouse();
+ /*virtual*/ void setMouseClipping( BOOL b );
+ /*virtual*/ BOOL isClipboardTextAvailable();
+ /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst);
+ /*virtual*/ BOOL copyTextToClipboard(const LLWString &src);
+ /*virtual*/ void flashIcon(F32 seconds);
+ /*virtual*/ F32 getGamma();
+ /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
+ /*virtual*/ void setFSAASamples(const U32 fsaa_samples);
+ /*virtual*/ U32 getFSAASamples();
+ /*virtual*/ BOOL restoreGamma(); // Restore original gamma table (before updating gamma)
+ /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
+ /*virtual*/ void gatherInput();
+ /*virtual*/ void delayInputProcessing();
+ /*virtual*/ void swapBuffers();
+ /*virtual*/ void restoreGLContext() {};
+
+ // handy coordinate space conversion routines
+ /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to);
+ /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to);
+ /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to);
+ /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to);
+ /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to);
+ /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to);
+
+ /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
+ /*virtual*/ F32 getNativeAspectRatio();
+ /*virtual*/ F32 getPixelAspectRatio();
+ /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
U32 getAvailableVRAMMegabytes() override;
+
+ /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b );
- /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b );
+ /*virtual*/ void *getPlatformWindow();
+ /*virtual*/ void bringToFront();
+ /*virtual*/ void focusClient();
- /*virtual*/ void *getPlatformWindow();
- /*virtual*/ void bringToFront();
- /*virtual*/ void focusClient();
+ /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b);
+ /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos );
+ /*virtual*/ void updateLanguageTextInputArea();
+ /*virtual*/ void interruptLanguageTextInput();
+ /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
- /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b);
- /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos );
- /*virtual*/ void updateLanguageTextInputArea();
- /*virtual*/ void interruptLanguageTextInput();
- /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
+ void openFolder(const std::string &path) override;
- /*virtual*/ F32 getSystemUISize();
+ /*virtual*/ F32 getSystemUISize();
- LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
+ LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
- static std::vector<std::string> getDisplaysResolutionList();
- static std::vector<std::string> getDynamicFallbackFontList();
- static void setDPIAwareness();
+ static std::vector<std::string> getDisplaysResolutionList();
+ static std::vector<std::string> getDynamicFallbackFontList();
+ static void setDPIAwareness();
/*virtual*/ void* getDirectInput8();
/*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata);
@@ -136,67 +138,67 @@ public:
U32 getRawWParam() { return mRawWParam; }
protected:
- LLWindowWin32(LLWindowCallbacks* callbacks,
- const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
- BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl,
- BOOL ignore_pixel_depth, U32 fsaa_samples, U32 max_cores, U32 max_vram, F32 max_gl_version);
- ~LLWindowWin32();
-
- void initCursors();
- void initInputDevices();
- HCURSOR loadColorCursor(LPCTSTR name);
- BOOL isValid();
- void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
- virtual LLSD getNativeKeyData();
-
- // Changes display resolution. Returns true if successful
- BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
-
- // Go back to last fullscreen display resolution.
- BOOL setFullscreenResolution();
-
- // Restore the display resolution to its value before we ran the app.
- BOOL resetDisplayResolution();
-
- BOOL shouldPostQuit() { return mPostQuit; }
-
- void fillCompositionForm(const LLRect& bounds, COMPOSITIONFORM *form);
- void fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds, CANDIDATEFORM *form);
- void fillCharPosition(const LLCoordGL& caret, const LLRect& bounds, const LLRect& control, IMECHARPOSITION *char_position);
- void fillCompositionLogfont(LOGFONT *logfont);
- U32 fillReconvertString(const LLWString &text, S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string);
- void handleStartCompositionMessage();
- void handleCompositionMessage(U32 indexes);
- BOOL handleImeRequests(WPARAM request, LPARAM param, LRESULT *result);
+ LLWindowWin32(LLWindowCallbacks* callbacks,
+ const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
+ BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl,
+ BOOL ignore_pixel_depth, U32 fsaa_samples, U32 max_cores, U32 max_vram, F32 max_gl_version);
+ ~LLWindowWin32();
+
+ void initCursors();
+ void initInputDevices();
+ HCURSOR loadColorCursor(LPCTSTR name);
+ BOOL isValid();
+ void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
+ virtual LLSD getNativeKeyData();
+
+ // Changes display resolution. Returns true if successful
+ BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+
+ // Go back to last fullscreen display resolution.
+ BOOL setFullscreenResolution();
+
+ // Restore the display resolution to its value before we ran the app.
+ BOOL resetDisplayResolution();
+
+ BOOL shouldPostQuit() { return mPostQuit; }
+
+ void fillCompositionForm(const LLRect& bounds, COMPOSITIONFORM *form);
+ void fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds, CANDIDATEFORM *form);
+ void fillCharPosition(const LLCoordGL& caret, const LLRect& bounds, const LLRect& control, IMECHARPOSITION *char_position);
+ void fillCompositionLogfont(LOGFONT *logfont);
+ U32 fillReconvertString(const LLWString &text, S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string);
+ void handleStartCompositionMessage();
+ void handleCompositionMessage(U32 indexes);
+ BOOL handleImeRequests(WPARAM request, LPARAM param, LRESULT *result);
protected:
- //
- // Platform specific methods
- //
+ //
+ // Platform specific methods
+ //
- BOOL getClientRectInScreenSpace(RECT* rectp);
- void updateJoystick( );
+ BOOL getClientRectInScreenSpace(RECT* rectp);
+ void updateJoystick( );
- static LRESULT CALLBACK mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param);
- static BOOL CALLBACK enumChildWindows(HWND h_wnd, LPARAM l_param);
+ static LRESULT CALLBACK mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param);
+ static BOOL CALLBACK enumChildWindows(HWND h_wnd, LPARAM l_param);
- //
- // Platform specific variables
- //
- WCHAR *mWindowTitle;
- WCHAR *mWindowClassName;
+ //
+ // Platform specific variables
+ //
+ WCHAR *mWindowTitle;
+ WCHAR *mWindowClassName;
- HWND mWindowHandle = 0; // window handle
- HGLRC mhRC = 0; // OpenGL rendering context
- HDC mhDC = 0; // Windows Device context handle
- HINSTANCE mhInstance; // handle to application instance
- RECT mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
- WPARAM mLastSizeWParam;
- F32 mOverrideAspectRatio;
- F32 mNativeAspectRatio;
+ HWND mWindowHandle = 0; // window handle
+ HGLRC mhRC = 0; // OpenGL rendering context
+ HDC mhDC = 0; // Windows Device context handle
+ HINSTANCE mhInstance; // handle to application instance
+ RECT mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
+ WPARAM mLastSizeWParam;
+ F32 mOverrideAspectRatio;
+ F32 mNativeAspectRatio;
- HCURSOR mCursor[ UI_CURSOR_COUNT ]; // Array of all mouse cursors
+ HCURSOR mCursor[ UI_CURSOR_COUNT ]; // Array of all mouse cursors
LLCoordWindow mCursorPosition; // mouse cursor position, should only be mutated on main thread
LLMutex mRawMouseMutex;
RAWINPUTDEVICE mRawMouse;
@@ -206,86 +208,86 @@ protected:
MASK mMouseMask;
- static BOOL sIsClassRegistered; // has the window class been registered?
+ static BOOL sIsClassRegistered; // has the window class been registered?
- F32 mCurrentGamma;
- U32 mFSAASamples;
+ F32 mCurrentGamma;
+ U32 mFSAASamples;
U32 mMaxCores; // for debugging only -- maximum number of CPU cores to use, or 0 for no limit
F32 mMaxGLVersion; // maximum OpenGL version to attempt to use (clamps to 3.2 - 4.6)
- WORD mPrevGammaRamp[3][256];
- WORD mCurrentGammaRamp[3][256];
- BOOL mCustomGammaSet;
-
- LPWSTR mIconResource;
- BOOL mInputProcessingPaused;
-
- // The following variables are for Language Text Input control.
- // They are all static, since one context is shared by all LLWindowWin32
- // instances.
- static BOOL sLanguageTextInputAllowed;
- static BOOL sWinIMEOpened;
- static HKL sWinInputLocale;
- static DWORD sWinIMEConversionMode;
- static DWORD sWinIMESentenceMode;
- static LLCoordWindow sWinIMEWindowPosition;
- LLCoordGL mLanguageTextInputPointGL;
- LLRect mLanguageTextInputAreaGL;
-
- LLPreeditor *mPreeditor;
-
- LLDragDropWin32* mDragDrop;
-
- U32 mKeyCharCode;
- U32 mKeyScanCode;
- U32 mKeyVirtualKey;
- U32 mRawMsg;
- U32 mRawWParam;
- U32 mRawLParam;
-
- BOOL mMouseVanish;
+ WORD mPrevGammaRamp[3][256];
+ WORD mCurrentGammaRamp[3][256];
+ BOOL mCustomGammaSet;
+
+ LPWSTR mIconResource;
+ BOOL mInputProcessingPaused;
+
+ // The following variables are for Language Text Input control.
+ // They are all static, since one context is shared by all LLWindowWin32
+ // instances.
+ static BOOL sLanguageTextInputAllowed;
+ static BOOL sWinIMEOpened;
+ static HKL sWinInputLocale;
+ static DWORD sWinIMEConversionMode;
+ static DWORD sWinIMESentenceMode;
+ static LLCoordWindow sWinIMEWindowPosition;
+ LLCoordGL mLanguageTextInputPointGL;
+ LLRect mLanguageTextInputAreaGL;
+
+ LLPreeditor *mPreeditor;
+
+ LLDragDropWin32* mDragDrop;
+
+ U32 mKeyCharCode;
+ U32 mKeyScanCode;
+ U32 mKeyVirtualKey;
+ U32 mRawMsg;
+ U32 mRawWParam;
+ U32 mRawLParam;
+
+ BOOL mMouseVanish;
// Cached values of GetWindowRect and GetClientRect to be used by app thread
void updateWindowRect();
- RECT mRect;
+ RECT mRect;
RECT mClientRect;
- struct LLWindowWin32Thread;
- LLWindowWin32Thread* mWindowThread = nullptr;
- LLThreadSafeQueue<std::function<void()>> mFunctionQueue;
- LLThreadSafeQueue<std::function<void()>> mMouseQueue;
- void post(const std::function<void()>& func);
- void postMouseButtonEvent(const std::function<void()>& func);
- void recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style);
- void kickWindowThread(HWND windowHandle=0);
+ struct LLWindowWin32Thread;
+ LLWindowWin32Thread* mWindowThread = nullptr;
+ LLThreadSafeQueue<std::function<void()>> mFunctionQueue;
+ LLThreadSafeQueue<std::function<void()>> mMouseQueue;
+ void post(const std::function<void()>& func);
+ void postMouseButtonEvent(const std::function<void()>& func);
+ void recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style);
+ void kickWindowThread(HWND windowHandle=0);
- friend class LLWindowManager;
+ friend class LLWindowManager;
};
class LLSplashScreenWin32 : public LLSplashScreen
{
public:
- LLSplashScreenWin32();
- virtual ~LLSplashScreenWin32();
+ LLSplashScreenWin32();
+ virtual ~LLSplashScreenWin32();
- /*virtual*/ void showImpl();
- /*virtual*/ void updateImpl(const std::string& mesg);
- /*virtual*/ void hideImpl();
+ /*virtual*/ void showImpl();
+ /*virtual*/ void updateImpl(const std::string& mesg);
+ /*virtual*/ void hideImpl();
#if LL_WINDOWS
- static LRESULT CALLBACK windowProc(HWND h_wnd, UINT u_msg,
- WPARAM w_param, LPARAM l_param);
+ static LRESULT CALLBACK windowProc(HWND h_wnd, UINT u_msg,
+ WPARAM w_param, LPARAM l_param);
#endif
private:
#if LL_WINDOWS
- HWND mWindow;
+ HWND mWindow;
#endif
};
extern LLW32MsgCallback gAsyncMsgCallback;
extern LPWSTR gIconResource;
-static void handleMessage( const MSG& msg );
+static void handleMessage( const MSG& msg );
S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type);
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index 264bf0c5b4..a2178ed77d 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcontrol.cpp
* @brief Holds global state for viewer.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -109,60 +109,60 @@ std::string SETTINGS_PROFILE = "settings_profile.log";
bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)
{
- bool result = false;
- switch (mType)
- {
- case TYPE_U32:
- case TYPE_S32:
- result = a.asInteger() == b.asInteger();
- break;
- case TYPE_BOOLEAN:
- result = a.asBoolean() == b.asBoolean();
- break;
- case TYPE_F32:
- result = a.asReal() == b.asReal();
- break;
- case TYPE_VEC3:
- case TYPE_VEC3D:
- result = LLVector3d(a) == LLVector3d(b);
- break;
- case TYPE_QUAT:
- result = LLQuaternion(a) == LLQuaternion(b);
- break;
- case TYPE_RECT:
- result = LLRect(a) == LLRect(b);
- break;
- case TYPE_COL4:
- result = LLColor4(a) == LLColor4(b);
- break;
- case TYPE_COL3:
- result = LLColor3(a) == LLColor3(b);
- break;
- case TYPE_STRING:
- result = a.asString() == b.asString();
- break;
- default:
- break;
- }
-
- return result;
+ bool result = false;
+ switch (mType)
+ {
+ case TYPE_U32:
+ case TYPE_S32:
+ result = a.asInteger() == b.asInteger();
+ break;
+ case TYPE_BOOLEAN:
+ result = a.asBoolean() == b.asBoolean();
+ break;
+ case TYPE_F32:
+ result = a.asReal() == b.asReal();
+ break;
+ case TYPE_VEC3:
+ case TYPE_VEC3D:
+ result = LLVector3d(a) == LLVector3d(b);
+ break;
+ case TYPE_QUAT:
+ result = LLQuaternion(a) == LLQuaternion(b);
+ break;
+ case TYPE_RECT:
+ result = LLRect(a) == LLRect(b);
+ break;
+ case TYPE_COL4:
+ result = LLColor4(a) == LLColor4(b);
+ break;
+ case TYPE_COL3:
+ result = LLColor3(a) == LLColor3(b);
+ break;
+ case TYPE_STRING:
+ result = a.asString() == b.asString();
+ break;
+ default:
+ break;
+ }
+
+ return result;
}
LLControlVariable::LLControlVariable(const std::string& name, eControlType type,
- LLSD initial, const std::string& comment,
- ePersist persist, bool hidefromsettingseditor)
- : mName(name),
- mComment(comment),
- mType(type),
- mPersist(persist),
- mHideFromSettingsEditor(hidefromsettingseditor)
-{
- if ((persist != PERSIST_NO) && mComment.empty())
- {
- LL_ERRS() << "Must supply a comment for control " << mName << LL_ENDL;
- }
- //Push back versus setValue'ing here, since we don't want to call a signal yet
- mValues.push_back(initial);
+ LLSD initial, const std::string& comment,
+ ePersist persist, bool hidefromsettingseditor)
+ : mName(name),
+ mComment(comment),
+ mType(type),
+ mPersist(persist),
+ mHideFromSettingsEditor(hidefromsettingseditor)
+{
+ if ((persist != PERSIST_NO) && mComment.empty())
+ {
+ LL_ERRS() << "Must supply a comment for control " << mName << LL_ENDL;
+ }
+ //Push back versus setValue'ing here, since we don't want to call a signal yet
+ mValues.push_back(initial);
}
@@ -173,70 +173,70 @@ LLControlVariable::~LLControlVariable()
LLSD LLControlVariable::getComparableValue(const LLSD& value)
{
- // *FIX:MEP - The following is needed to make the LLSD::ImplString
- // work with boolean controls...
- LLSD storable_value;
- if(TYPE_BOOLEAN == type() && value.isString())
- {
- BOOL temp;
- if(LLStringUtil::convertToBOOL(value.asString(), temp))
- {
- storable_value = (bool)temp;
- }
- else
- {
- storable_value = false;
- }
- }
- else if (TYPE_LLSD == type() && value.isString())
- {
- LLPointer<LLSDNotationParser> parser = new LLSDNotationParser;
- LLSD result;
- std::stringstream value_stream(value.asString());
- if (parser->parse(value_stream, result, LLSDSerialize::SIZE_UNLIMITED) != LLSDParser::PARSE_FAILURE)
- {
- storable_value = result;
- }
- else
- {
- storable_value = value;
- }
- }
- else
- {
- storable_value = value;
- }
-
- return storable_value;
+ // *FIX:MEP - The following is needed to make the LLSD::ImplString
+ // work with boolean controls...
+ LLSD storable_value;
+ if(TYPE_BOOLEAN == type() && value.isString())
+ {
+ BOOL temp;
+ if(LLStringUtil::convertToBOOL(value.asString(), temp))
+ {
+ storable_value = (bool)temp;
+ }
+ else
+ {
+ storable_value = false;
+ }
+ }
+ else if (TYPE_LLSD == type() && value.isString())
+ {
+ LLPointer<LLSDNotationParser> parser = new LLSDNotationParser;
+ LLSD result;
+ std::stringstream value_stream(value.asString());
+ if (parser->parse(value_stream, result, LLSDSerialize::SIZE_UNLIMITED) != LLSDParser::PARSE_FAILURE)
+ {
+ storable_value = result;
+ }
+ else
+ {
+ storable_value = value;
+ }
+ }
+ else
+ {
+ storable_value = value;
+ }
+
+ return storable_value;
}
void LLControlVariable::setValue(const LLSD& new_value, bool saved_value)
{
- if (mValidateSignal(this, new_value) == false)
- {
- // can not set new value, exit
- return;
- }
-
- LLSD storable_value = getComparableValue(new_value);
- LLSD original_value = getValue();
- bool value_changed = llsd_compare(original_value, storable_value) == FALSE;
- if(saved_value)
- {
- // If we're going to save this value, return to default but don't fire
- resetToDefault(false);
- if (llsd_compare(mValues.back(), storable_value) == FALSE)
- {
- mValues.push_back(storable_value);
- }
- }
+ if (mValidateSignal(this, new_value) == false)
+ {
+ // can not set new value, exit
+ return;
+ }
+
+ LLSD storable_value = getComparableValue(new_value);
+ LLSD original_value = getValue();
+ bool value_changed = llsd_compare(original_value, storable_value) == FALSE;
+ if(saved_value)
+ {
+ // If we're going to save this value, return to default but don't fire
+ resetToDefault(false);
+ if (llsd_compare(mValues.back(), storable_value) == FALSE)
+ {
+ mValues.push_back(storable_value);
+ }
+ }
else
{
// This is an unsaved value. Its needs to reside at
- // mValues[2] (or greater). It must not affect
+ // mValues[2] (or greater). It must not affect
// the result of getSaveValue()
- if (llsd_compare(mValues.back(), storable_value) == FALSE)
- {
+ if (llsd_compare(mValues.back(), storable_value) == FALSE)
+ {
while(mValues.size() > 2)
{
// Remove any unsaved values.
@@ -251,107 +251,107 @@ void LLControlVariable::setValue(const LLSD& new_value, bool saved_value)
// Add the 'un-save' value.
mValues.push_back(storable_value);
- }
+ }
}
if(value_changed)
{
- firePropertyChanged(original_value);
+ firePropertyChanged(original_value);
}
}
void LLControlVariable::setDefaultValue(const LLSD& value)
{
- // Set the control variables value and make it
- // the default value. If the active value is changed,
- // send the signal.
- // *NOTE: Default values are not saved, only read.
+ // Set the control variables value and make it
+ // the default value. If the active value is changed,
+ // send the signal.
+ // *NOTE: Default values are not saved, only read.
- LLSD comparable_value = getComparableValue(value);
- LLSD original_value = getValue();
- bool value_changed = (llsd_compare(original_value, comparable_value) == FALSE);
- resetToDefault(false);
- mValues[0] = comparable_value;
- if(value_changed)
- {
- firePropertyChanged(original_value);
- }
+ LLSD comparable_value = getComparableValue(value);
+ LLSD original_value = getValue();
+ bool value_changed = (llsd_compare(original_value, comparable_value) == FALSE);
+ resetToDefault(false);
+ mValues[0] = comparable_value;
+ if(value_changed)
+ {
+ firePropertyChanged(original_value);
+ }
}
void LLControlVariable::setPersist(ePersist state)
{
- mPersist = state;
+ mPersist = state;
}
void LLControlVariable::setHiddenFromSettingsEditor(bool hide)
{
- mHideFromSettingsEditor = hide;
+ mHideFromSettingsEditor = hide;
}
void LLControlVariable::setComment(const std::string& comment)
{
- mComment = comment;
+ mComment = comment;
}
void LLControlVariable::resetToDefault(bool fire_signal)
{
- //The first setting is always the default
- //Pop to it and fire off the listener
- LLSD originalValue = mValues.back();
+ //The first setting is always the default
+ //Pop to it and fire off the listener
+ LLSD originalValue = mValues.back();
- while(mValues.size() > 1)
- {
- mValues.pop_back();
- }
-
- if(fire_signal)
- {
- firePropertyChanged(originalValue);
- }
+ while(mValues.size() > 1)
+ {
+ mValues.pop_back();
+ }
+
+ if(fire_signal)
+ {
+ firePropertyChanged(originalValue);
+ }
}
bool LLControlVariable::shouldSave(bool nondefault_only)
{
- // This method is used to decide whether we should save a given
- // variable. Two of the three values of mPersist are easy.
- if (mPersist == PERSIST_NO)
- return false;
+ // This method is used to decide whether we should save a given
+ // variable. Two of the three values of mPersist are easy.
+ if (mPersist == PERSIST_NO)
+ return false;
- if (mPersist == PERSIST_ALWAYS)
- return true;
+ if (mPersist == PERSIST_ALWAYS)
+ return true;
- // PERSIST_NONDFT
- // If caller doesn't need us to filter, just save.
- if (! nondefault_only)
- return true;
+ // PERSIST_NONDFT
+ // If caller doesn't need us to filter, just save.
+ if (! nondefault_only)
+ return true;
- // PERSIST_NONDFT: caller only wants us to save this variable if its value
- // differs from default.
- if (isDefault()) // never been altered
- return false;
+ // PERSIST_NONDFT: caller only wants us to save this variable if its value
+ // differs from default.
+ if (isDefault()) // never been altered
+ return false;
- // We've set at least one other value: compare it to default. Save only if
- // they differ.
- return ! llsd_compare(getSaveValue(), getDefault());
+ // We've set at least one other value: compare it to default. Save only if
+ // they differ.
+ return ! llsd_compare(getSaveValue(), getDefault());
}
LLSD LLControlVariable::getSaveValue() const
{
- //The first level of the stack is default
- //We assume that the second level is user preferences that should be saved
- if(mValues.size() > 1) return mValues[1];
- return mValues[0];
+ //The first level of the stack is default
+ //We assume that the second level is user preferences that should be saved
+ if(mValues.size() > 1) return mValues[1];
+ return mValues[0];
}
LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)
{
- if (mSettingsProfile)
- {
- incrCount(name);
- }
+ if (mSettingsProfile)
+ {
+ incrCount(name);
+ }
- ctrl_name_table_t::iterator iter = mNameTable.find(name);
- return iter == mNameTable.end() ? LLPointer<LLControlVariable>() : iter->second;
+ ctrl_name_table_t::iterator iter = mNameTable.find(name);
+ return iter == mNameTable.end() ? LLPointer<LLControlVariable>() : iter->second;
}
@@ -373,296 +373,296 @@ const std::string LLControlGroup::mTypeString[TYPE_COUNT] = { "U32"
};
LLControlGroup::LLControlGroup(const std::string& name)
-: LLInstanceTracker<LLControlGroup, std::string>(name),
- mSettingsProfile(false)
+: LLInstanceTracker<LLControlGroup, std::string>(name),
+ mSettingsProfile(false)
{
- if (NULL != getenv("LL_SETTINGS_PROFILE"))
- {
- mSettingsProfile = true;
- }
+ if (NULL != getenv("LL_SETTINGS_PROFILE"))
+ {
+ mSettingsProfile = true;
+ }
}
LLControlGroup::~LLControlGroup()
{
- cleanup();
+ cleanup();
}
static bool compareRoutine(settings_pair_t lhs, settings_pair_t rhs)
{
- return lhs.second > rhs.second;
+ return lhs.second > rhs.second;
};
void LLControlGroup::cleanup()
{
- if(mSettingsProfile && getCount.size() != 0)
- {
- std::string file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, SETTINGS_PROFILE);
- LLFILE* out = LLFile::fopen(file, "w"); /* Flawfinder: ignore */
- if(!out)
- {
- LL_WARNS("SettingsProfile") << "Error opening " << SETTINGS_PROFILE << LL_ENDL;
- }
- else
- {
- F64 end_time = LLTimer::getTotalSeconds();
- U32 total_seconds = (U32)(end_time - start_time);
-
- std::string msg = llformat("Runtime (seconds): %d\n\n No. accesses Avg. accesses/sec Name\n", total_seconds);
- std::ostringstream data_msg;
-
- data_msg << msg;
- size_t data_size = data_msg.str().size();
- if (fwrite(data_msg.str().c_str(), 1, data_size, out) != data_size)
- {
- LL_WARNS("SettingsProfile") << "Failed to write settings profile header" << LL_ENDL;
- }
-
- for (LLSD::map_const_iterator iter = getCount.beginMap(); iter != getCount.endMap(); ++iter)
- {
- getCount_v.push_back(settings_pair_t(iter->first, iter->second.asInteger()));
- }
- sort(getCount_v.begin(), getCount_v.end(), compareRoutine);
-
- for (settings_vec_t::iterator iter = getCount_v.begin(); iter != getCount_v.end(); ++iter)
- {
- U32 access_rate = 0;
- if (total_seconds != 0)
- {
- access_rate = iter->second / total_seconds;
- }
- if (access_rate >= 2)
- {
- std::ostringstream data_msg;
- msg = llformat("%13d %7d %s", iter->second, access_rate, iter->first.c_str());
- data_msg << msg << "\n";
- size_t data_size = data_msg.str().size();
- if (fwrite(data_msg.str().c_str(), 1, data_size, out) != data_size)
- {
- LL_WARNS("SettingsProfile") << "Failed to write settings profile" << LL_ENDL;
- }
- }
- }
- getCount = LLSD::emptyMap();
- fclose(out);
- }
- }
-
- mNameTable.clear();
+ if(mSettingsProfile && getCount.size() != 0)
+ {
+ std::string file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, SETTINGS_PROFILE);
+ LLFILE* out = LLFile::fopen(file, "w"); /* Flawfinder: ignore */
+ if(!out)
+ {
+ LL_WARNS("SettingsProfile") << "Error opening " << SETTINGS_PROFILE << LL_ENDL;
+ }
+ else
+ {
+ F64 end_time = LLTimer::getTotalSeconds();
+ U32 total_seconds = (U32)(end_time - start_time);
+
+ std::string msg = llformat("Runtime (seconds): %d\n\n No. accesses Avg. accesses/sec Name\n", total_seconds);
+ std::ostringstream data_msg;
+
+ data_msg << msg;
+ size_t data_size = data_msg.str().size();
+ if (fwrite(data_msg.str().c_str(), 1, data_size, out) != data_size)
+ {
+ LL_WARNS("SettingsProfile") << "Failed to write settings profile header" << LL_ENDL;
+ }
+
+ for (LLSD::map_const_iterator iter = getCount.beginMap(); iter != getCount.endMap(); ++iter)
+ {
+ getCount_v.push_back(settings_pair_t(iter->first, iter->second.asInteger()));
+ }
+ sort(getCount_v.begin(), getCount_v.end(), compareRoutine);
+
+ for (settings_vec_t::iterator iter = getCount_v.begin(); iter != getCount_v.end(); ++iter)
+ {
+ U32 access_rate = 0;
+ if (total_seconds != 0)
+ {
+ access_rate = iter->second / total_seconds;
+ }
+ if (access_rate >= 2)
+ {
+ std::ostringstream data_msg;
+ msg = llformat("%13d %7d %s", iter->second, access_rate, iter->first.c_str());
+ data_msg << msg << "\n";
+ size_t data_size = data_msg.str().size();
+ if (fwrite(data_msg.str().c_str(), 1, data_size, out) != data_size)
+ {
+ LL_WARNS("SettingsProfile") << "Failed to write settings profile" << LL_ENDL;
+ }
+ }
+ }
+ getCount = LLSD::emptyMap();
+ fclose(out);
+ }
+ }
+
+ mNameTable.clear();
}
eControlType LLControlGroup::typeStringToEnum(const std::string& typestr)
{
- for(int i = 0; i < (int)TYPE_COUNT; ++i)
- {
- if(mTypeString[i] == typestr) return (eControlType)i;
- }
- return (eControlType)-1;
+ for(int i = 0; i < (int)TYPE_COUNT; ++i)
+ {
+ if(mTypeString[i] == typestr) return (eControlType)i;
+ }
+ return (eControlType)-1;
}
std::string LLControlGroup::typeEnumToString(eControlType typeenum)
{
- return mTypeString[typeenum];
+ return mTypeString[typeenum];
}
LLControlVariable* LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor)
{
- LLControlVariable* existing_control = getControl(name);
- if (existing_control)
- {
- if ((persist != LLControlVariable::PERSIST_NO) && existing_control->isType(type))
- {
- if (!existing_control->llsd_compare(existing_control->getDefault(), initial_val))
- {
- // Sometimes we need to declare a control *after* it has been loaded from a settings file.
- LLSD cur_value = existing_control->getValue(); // get the current value
- existing_control->setDefaultValue(initial_val); // set the default to the declared value
- existing_control->setValue(cur_value); // now set to the loaded value
- }
- }
- else
- {
- LL_WARNS("Settings") << "Control named " << name << " already exists, ignoring new declaration." << LL_ENDL;
- }
- return existing_control;
- }
-
- // if not, create the control and add it to the name table
- LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor);
- mNameTable[name] = control;
- return control;
+ LLControlVariable* existing_control = getControl(name);
+ if (existing_control)
+ {
+ if ((persist != LLControlVariable::PERSIST_NO) && existing_control->isType(type))
+ {
+ if (!existing_control->llsd_compare(existing_control->getDefault(), initial_val))
+ {
+ // Sometimes we need to declare a control *after* it has been loaded from a settings file.
+ LLSD cur_value = existing_control->getValue(); // get the current value
+ existing_control->setDefaultValue(initial_val); // set the default to the declared value
+ existing_control->setValue(cur_value); // now set to the loaded value
+ }
+ }
+ else
+ {
+ LL_WARNS("Settings") << "Control named " << name << " already exists, ignoring new declaration." << LL_ENDL;
+ }
+ return existing_control;
+ }
+
+ // if not, create the control and add it to the name table
+ LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor);
+ mNameTable[name] = control;
+ return control;
}
LLControlVariable* LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
- return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist);
+ return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist);
}
LLControlVariable* LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
- return declareControl(name, TYPE_S32, initial_val, comment, persist);
+ return declareControl(name, TYPE_S32, initial_val, comment, persist);
}
LLControlVariable* LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
- return declareControl(name, TYPE_F32, initial_val, comment, persist);
+ return declareControl(name, TYPE_F32, initial_val, comment, persist);
}
LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
- return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist);
+ return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist);
}
LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
- return declareControl(name, TYPE_STRING, initial_val, comment, persist);
+ return declareControl(name, TYPE_STRING, initial_val, comment, persist);
}
LLControlVariable* LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
- return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist);
+ return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist);
}
LLControlVariable* LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
- return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist);
+ return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist);
}
LLControlVariable* LLControlGroup::declareQuat(const std::string& name, const LLQuaternion &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
- return declareControl(name, TYPE_QUAT, initial_val.getValue(), comment, persist);
+ return declareControl(name, TYPE_QUAT, initial_val.getValue(), comment, persist);
}
LLControlVariable* LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist)
{
- return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
+ return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
}
LLControlVariable* LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist )
{
- return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
+ return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
}
LLControlVariable* LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist )
{
- return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);
+ return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);
}
LLControlVariable* LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist )
{
- return declareControl(name, TYPE_LLSD, initial_val, comment, persist);
+ return declareControl(name, TYPE_LLSD, initial_val, comment, persist);
}
void LLControlGroup::incrCount(const std::string& name)
{
- if (0.0 == start_time)
- {
- start_time = LLTimer::getTotalSeconds();
- }
- getCount[name] = getCount[name].asInteger() + 1;
+ if (0.0 == start_time)
+ {
+ start_time = LLTimer::getTotalSeconds();
+ }
+ getCount[name] = getCount[name].asInteger() + 1;
}
BOOL LLControlGroup::getBOOL(const std::string& name)
{
- return (BOOL)get<bool>(name);
+ return (BOOL)get<bool>(name);
}
S32 LLControlGroup::getS32(const std::string& name)
{
- return get<S32>(name);
+ return get<S32>(name);
}
U32 LLControlGroup::getU32(const std::string& name)
{
- return get<U32>(name);
+ return get<U32>(name);
}
F32 LLControlGroup::getF32(const std::string& name)
{
- return get<F32>(name);
+ return get<F32>(name);
}
std::string LLControlGroup::getString(const std::string& name)
{
- return get<std::string>(name);
+ return get<std::string>(name);
}
LLWString LLControlGroup::getWString(const std::string& name)
{
- return get<LLWString>(name);
+ return get<LLWString>(name);
}
std::string LLControlGroup::getText(const std::string& name)
{
- std::string utf8_string = getString(name);
- LLStringUtil::replaceChar(utf8_string, '^', '\n');
- LLStringUtil::replaceChar(utf8_string, '%', ' ');
- return (utf8_string);
+ std::string utf8_string = getString(name);
+ LLStringUtil::replaceChar(utf8_string, '^', '\n');
+ LLStringUtil::replaceChar(utf8_string, '%', ' ');
+ return (utf8_string);
}
LLVector3 LLControlGroup::getVector3(const std::string& name)
{
- return get<LLVector3>(name);
+ return get<LLVector3>(name);
}
LLVector3d LLControlGroup::getVector3d(const std::string& name)
{
- return get<LLVector3d>(name);
+ return get<LLVector3d>(name);
}
LLQuaternion LLControlGroup::getQuaternion(const std::string& name)
{
- return get<LLQuaternion>(name);
+ return get<LLQuaternion>(name);
}
LLRect LLControlGroup::getRect(const std::string& name)
{
- return get<LLRect>(name);
+ return get<LLRect>(name);
}
LLColor4 LLControlGroup::getColor(const std::string& name)
{
- return get<LLColor4>(name);
+ return get<LLColor4>(name);
}
LLColor4 LLControlGroup::getColor4(const std::string& name)
{
- return get<LLColor4>(name);
+ return get<LLColor4>(name);
}
LLColor3 LLControlGroup::getColor3(const std::string& name)
{
- return get<LLColor3>(name);
+ return get<LLColor3>(name);
}
LLSD LLControlGroup::getLLSD(const std::string& name)
{
- return get<LLSD>(name);
+ return get<LLSD>(name);
}
LLSD LLControlGroup::asLLSD(bool diffs_only)
{
- // Dump all stored values as LLSD
- LLSD result = LLSD::emptyArray();
- for (ctrl_name_table_t::iterator iter = mNameTable.begin();
- iter != mNameTable.end(); iter++)
- {
- LLControlVariable *control = iter->second;
- if (!control || control->isType(TYPE_STRING) || (diffs_only && control->isDefault()))
- {
- continue;
- }
- const std::string& name = iter->first;
- result[name] = getLLSD(name);
- }
- return result;
+ // Dump all stored values as LLSD
+ LLSD result = LLSD::emptyArray();
+ for (ctrl_name_table_t::iterator iter = mNameTable.begin();
+ iter != mNameTable.end(); iter++)
+ {
+ LLControlVariable *control = iter->second;
+ if (!control || control->isType(TYPE_STRING) || (diffs_only && control->isDefault()))
+ {
+ continue;
+ }
+ const std::string& name = iter->first;
+ result[name] = getLLSD(name);
+ }
+ return result;
}
BOOL LLControlGroup::controlExists(const std::string& name)
{
- ctrl_name_table_t::iterator iter = mNameTable.find(name);
- return iter != mNameTable.end();
+ ctrl_name_table_t::iterator iter = mNameTable.find(name);
+ return iter != mNameTable.end();
}
@@ -672,81 +672,81 @@ BOOL LLControlGroup::controlExists(const std::string& name)
void LLControlGroup::setBOOL(const std::string& name, BOOL val)
{
- set<bool>(name, val);
+ set<bool>(name, val);
}
void LLControlGroup::setS32(const std::string& name, S32 val)
{
- set(name, val);
+ set(name, val);
}
void LLControlGroup::setF32(const std::string& name, F32 val)
{
- set(name, val);
+ set(name, val);
}
void LLControlGroup::setU32(const std::string& name, U32 val)
{
- set(name, val);
+ set(name, val);
}
void LLControlGroup::setString(const std::string& name, const std::string &val)
{
- set(name, val);
+ set(name, val);
}
void LLControlGroup::setVector3(const std::string& name, const LLVector3 &val)
{
- set(name, val);
+ set(name, val);
}
void LLControlGroup::setVector3d(const std::string& name, const LLVector3d &val)
{
- set(name, val);
+ set(name, val);
}
void LLControlGroup::setQuaternion(const std::string& name, const LLQuaternion &val)
{
- set(name, val);
+ set(name, val);
}
void LLControlGroup::setRect(const std::string& name, const LLRect &val)
{
- set(name, val);
+ set(name, val);
}
void LLControlGroup::setColor4(const std::string& name, const LLColor4 &val)
{
- set(name, val);
+ set(name, val);
}
void LLControlGroup::setLLSD(const std::string& name, const LLSD& val)
{
- set(name, val);
+ set(name, val);
}
-void LLControlGroup::setUntypedValue(const std::string& name, const LLSD& val)
+void LLControlGroup::setUntypedValue(const std::string& name, const LLSD& val, bool saved_value)
{
- if (name.empty())
- {
- return;
- }
-
- LLControlVariable* control = getControl(name);
+ if (name.empty())
+ {
+ return;
+ }
- if (control)
- {
- control->setValue(val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << LL_ENDL;
- }
+ LLControlVariable* control = getControl(name);
+
+ if (control)
+ {
+ control->setValue(val, saved_value);
+ }
+ else
+ {
+ CONTROL_ERRS << "Invalid control " << name << LL_ENDL;
+ }
}
@@ -757,388 +757,388 @@ void LLControlGroup::setUntypedValue(const std::string& name, const LLSD& val)
// Returns number of controls loaded, so 0 if failure
U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require_declaration, eControlType declare_as)
{
- std::string name;
-
- LLXmlTree xml_controls;
-
- if (!xml_controls.parseFile(filename))
- {
- LL_WARNS("Settings") << "Unable to open control file " << filename << LL_ENDL;
- return 0;
- }
-
- LLXmlTreeNode* rootp = xml_controls.getRoot();
- if (!rootp || !rootp->hasAttribute("version"))
- {
- LL_WARNS("Settings") << "No valid settings header found in control file " << filename << LL_ENDL;
- return 0;
- }
-
- U32 validitems = 0;
- S32 version;
-
- rootp->getAttributeS32("version", version);
-
- // Check file version
- if (version != CURRENT_VERSION)
- {
- LL_INFOS("Settings") << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << LL_ENDL;
- return 0;
- }
-
- LLXmlTreeNode* child_nodep = rootp->getFirstChild();
- while(child_nodep)
- {
- name = child_nodep->getName();
-
- BOOL declared = controlExists(name);
-
- if (require_declaration && !declared)
- {
- // Declaration required, but this name not declared.
- // Complain about non-empty names.
- if (!name.empty())
- {
- //read in to end of line
- LL_WARNS("Settings") << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << LL_ENDL;
- }
- child_nodep = rootp->getNextChild();
- continue;
- }
-
- // Got an item. Load it up.
- // If not declared, assume it's a string
- if (!declared)
- {
- switch(declare_as)
- {
- case TYPE_COL4:
- declareColor4(name, LLColor4::white, LLStringUtil::null, LLControlVariable::PERSIST_NO);
- break;
- case TYPE_STRING:
- default:
- declareString(name, LLStringUtil::null, LLStringUtil::null, LLControlVariable::PERSIST_NO);
- break;
- }
- }
-
- // Control name has been declared in code.
- LLControlVariable *control = getControl(name);
-
- llassert(control);
-
- switch(control->mType)
- {
- case TYPE_F32:
- {
- F32 initial = 0.f;
-
- child_nodep->getAttributeF32("value", initial);
-
- control->set(initial);
- validitems++;
- }
- break;
- case TYPE_S32:
- {
- S32 initial = 0;
-
- child_nodep->getAttributeS32("value", initial);
-
- control->set(initial);
- validitems++;
- }
- break;
- case TYPE_U32:
- {
- U32 initial = 0;
- child_nodep->getAttributeU32("value", initial);
- control->set((LLSD::Integer) initial);
- validitems++;
- }
- break;
- case TYPE_BOOLEAN:
- {
- BOOL initial = FALSE;
-
- child_nodep->getAttributeBOOL("value", initial);
- control->set(initial);
-
- validitems++;
- }
- break;
- case TYPE_STRING:
- {
- std::string string;
- child_nodep->getAttributeString("value", string);
- control->set(string);
- validitems++;
- }
- break;
- case TYPE_VEC3:
- {
- LLVector3 vector;
-
- child_nodep->getAttributeVector3("value", vector);
- control->set(vector.getValue());
- validitems++;
- }
- break;
- case TYPE_VEC3D:
- {
- LLVector3d vector;
-
- child_nodep->getAttributeVector3d("value", vector);
-
- control->set(vector.getValue());
- validitems++;
- }
- break;
- case TYPE_QUAT:
- {
- LLQuaternion quat;
-
- child_nodep->getAttributeQuat("value", quat);
-
- control->set(quat.getValue());
- validitems++;
- }
- break;
- case TYPE_RECT:
- {
- //RN: hack to support reading rectangles from a string
- std::string rect_string;
-
- child_nodep->getAttributeString("value", rect_string);
- std::istringstream istream(rect_string);
- S32 left, bottom, width, height;
-
- istream >> left >> bottom >> width >> height;
-
- LLRect rect;
- rect.setOriginAndSize(left, bottom, width, height);
-
- control->set(rect.getValue());
- validitems++;
- }
- break;
- case TYPE_COL4:
- {
- LLColor4 color;
-
- child_nodep->getAttributeColor4("value", color);
- control->set(color.getValue());
- validitems++;
- }
- break;
- case TYPE_COL3:
- {
- LLVector3 color;
-
- child_nodep->getAttributeVector3("value", color);
- control->set(LLColor3(color.mV).getValue());
- validitems++;
- }
- break;
-
- default:
- break;
-
- }
-
- child_nodep = rootp->getNextChild();
- }
-
- return validitems;
+ std::string name;
+
+ LLXmlTree xml_controls;
+
+ if (!xml_controls.parseFile(filename))
+ {
+ LL_WARNS("Settings") << "Unable to open control file " << filename << LL_ENDL;
+ return 0;
+ }
+
+ LLXmlTreeNode* rootp = xml_controls.getRoot();
+ if (!rootp || !rootp->hasAttribute("version"))
+ {
+ LL_WARNS("Settings") << "No valid settings header found in control file " << filename << LL_ENDL;
+ return 0;
+ }
+
+ U32 validitems = 0;
+ S32 version;
+
+ rootp->getAttributeS32("version", version);
+
+ // Check file version
+ if (version != CURRENT_VERSION)
+ {
+ LL_INFOS("Settings") << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << LL_ENDL;
+ return 0;
+ }
+
+ LLXmlTreeNode* child_nodep = rootp->getFirstChild();
+ while(child_nodep)
+ {
+ name = child_nodep->getName();
+
+ BOOL declared = controlExists(name);
+
+ if (require_declaration && !declared)
+ {
+ // Declaration required, but this name not declared.
+ // Complain about non-empty names.
+ if (!name.empty())
+ {
+ //read in to end of line
+ LL_WARNS("Settings") << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << LL_ENDL;
+ }
+ child_nodep = rootp->getNextChild();
+ continue;
+ }
+
+ // Got an item. Load it up.
+ // If not declared, assume it's a string
+ if (!declared)
+ {
+ switch(declare_as)
+ {
+ case TYPE_COL4:
+ declareColor4(name, LLColor4::white, LLStringUtil::null, LLControlVariable::PERSIST_NO);
+ break;
+ case TYPE_STRING:
+ default:
+ declareString(name, LLStringUtil::null, LLStringUtil::null, LLControlVariable::PERSIST_NO);
+ break;
+ }
+ }
+
+ // Control name has been declared in code.
+ LLControlVariable *control = getControl(name);
+
+ llassert(control);
+
+ switch(control->mType)
+ {
+ case TYPE_F32:
+ {
+ F32 initial = 0.f;
+
+ child_nodep->getAttributeF32("value", initial);
+
+ control->set(initial);
+ validitems++;
+ }
+ break;
+ case TYPE_S32:
+ {
+ S32 initial = 0;
+
+ child_nodep->getAttributeS32("value", initial);
+
+ control->set(initial);
+ validitems++;
+ }
+ break;
+ case TYPE_U32:
+ {
+ U32 initial = 0;
+ child_nodep->getAttributeU32("value", initial);
+ control->set((LLSD::Integer) initial);
+ validitems++;
+ }
+ break;
+ case TYPE_BOOLEAN:
+ {
+ BOOL initial = FALSE;
+
+ child_nodep->getAttributeBOOL("value", initial);
+ control->set(initial);
+
+ validitems++;
+ }
+ break;
+ case TYPE_STRING:
+ {
+ std::string string;
+ child_nodep->getAttributeString("value", string);
+ control->set(string);
+ validitems++;
+ }
+ break;
+ case TYPE_VEC3:
+ {
+ LLVector3 vector;
+
+ child_nodep->getAttributeVector3("value", vector);
+ control->set(vector.getValue());
+ validitems++;
+ }
+ break;
+ case TYPE_VEC3D:
+ {
+ LLVector3d vector;
+
+ child_nodep->getAttributeVector3d("value", vector);
+
+ control->set(vector.getValue());
+ validitems++;
+ }
+ break;
+ case TYPE_QUAT:
+ {
+ LLQuaternion quat;
+
+ child_nodep->getAttributeQuat("value", quat);
+
+ control->set(quat.getValue());
+ validitems++;
+ }
+ break;
+ case TYPE_RECT:
+ {
+ //RN: hack to support reading rectangles from a string
+ std::string rect_string;
+
+ child_nodep->getAttributeString("value", rect_string);
+ std::istringstream istream(rect_string);
+ S32 left, bottom, width, height;
+
+ istream >> left >> bottom >> width >> height;
+
+ LLRect rect;
+ rect.setOriginAndSize(left, bottom, width, height);
+
+ control->set(rect.getValue());
+ validitems++;
+ }
+ break;
+ case TYPE_COL4:
+ {
+ LLColor4 color;
+
+ child_nodep->getAttributeColor4("value", color);
+ control->set(color.getValue());
+ validitems++;
+ }
+ break;
+ case TYPE_COL3:
+ {
+ LLVector3 color;
+
+ child_nodep->getAttributeVector3("value", color);
+ control->set(LLColor3(color.mV).getValue());
+ validitems++;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ child_nodep = rootp->getNextChild();
+ }
+
+ return validitems;
}
U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only)
{
- LLSD settings;
- int num_saved = 0;
- for (ctrl_name_table_t::iterator iter = mNameTable.begin();
- iter != mNameTable.end(); iter++)
- {
- LLControlVariable* control = iter->second;
- if (!control)
- {
- LL_WARNS("Settings") << "Tried to save invalid control: " << iter->first << LL_ENDL;
- }
- else if( control->shouldSave(nondefault_only) )
- {
- settings[iter->first]["Type"] = typeEnumToString(control->type());
- settings[iter->first]["Comment"] = control->getComment();
- settings[iter->first]["Value"] = control->getSaveValue();
- ++num_saved;
- }
- }
- llofstream file;
- file.open(filename.c_str());
- if (file.is_open())
- {
- LLSDSerialize::toPrettyXML(settings, file);
- file.close();
- LL_INFOS("Settings") << "Saved to " << filename << LL_ENDL;
- }
- else
- {
+ LLSD settings;
+ int num_saved = 0;
+ for (ctrl_name_table_t::iterator iter = mNameTable.begin();
+ iter != mNameTable.end(); iter++)
+ {
+ LLControlVariable* control = iter->second;
+ if (!control)
+ {
+ LL_WARNS("Settings") << "Tried to save invalid control: " << iter->first << LL_ENDL;
+ }
+ else if( control->shouldSave(nondefault_only) )
+ {
+ settings[iter->first]["Type"] = typeEnumToString(control->type());
+ settings[iter->first]["Comment"] = control->getComment();
+ settings[iter->first]["Value"] = control->getSaveValue();
+ ++num_saved;
+ }
+ }
+ llofstream file;
+ file.open(filename.c_str());
+ if (file.is_open())
+ {
+ LLSDSerialize::toPrettyXML(settings, file);
+ file.close();
+ LL_INFOS("Settings") << "Saved to " << filename << LL_ENDL;
+ }
+ else
+ {
// This is a warning because sometime we want to use settings files which can't be written...
- LL_WARNS("Settings") << "Unable to open settings file: " << filename << LL_ENDL;
- return 0;
- }
- return num_saved;
+ LL_WARNS("Settings") << "Unable to open settings file: " << filename << LL_ENDL;
+ return 0;
+ }
+ return num_saved;
}
U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values)
{
- LLSD settings;
- llifstream infile;
- infile.open(filename.c_str());
- if(!infile.is_open())
- {
- LL_WARNS("Settings") << "Cannot find file " << filename << " to load." << LL_ENDL;
- return 0;
- }
-
- if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(settings, infile))
- {
- infile.close();
- LL_WARNS("Settings") << "Unable to parse LLSD control file " << filename << ". Trying Legacy Method." << LL_ENDL;
- return loadFromFileLegacy(filename, TRUE, TYPE_STRING);
- }
-
- U32 validitems = 0;
- bool hidefromsettingseditor = false;
-
- for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)
- {
- LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT;
- std::string const & name = itr->first;
- LLSD const & control_map = itr->second;
-
- if(control_map.has("Persist"))
- {
- persist = control_map["Persist"].asInteger()?
- LLControlVariable::PERSIST_NONDFT : LLControlVariable::PERSIST_NO;
- }
-
- // Sometimes we want to use the settings system to provide cheap persistence, but we
- // don't want the settings themselves to be easily manipulated in the UI because
- // doing so can cause support problems. So we have this option:
- if(control_map.has("HideFromEditor"))
- {
- hidefromsettingseditor = control_map["HideFromEditor"].asInteger();
- }
- else
- {
- hidefromsettingseditor = false;
- }
-
- // If the control exists just set the value from the input file.
- LLControlVariable* existing_control = getControl(name);
- if(existing_control)
- {
- // set_default_values is true when we're loading the initial,
- // immutable files from app_settings, e.g. settings.xml.
- if(set_default_values)
- {
- // Override all previously set properties of this control.
- // ... except for type. The types must match.
- eControlType new_type = typeStringToEnum(control_map["Type"].asString());
- if(existing_control->isType(new_type))
- {
- existing_control->setDefaultValue(control_map["Value"]);
- existing_control->setPersist(persist);
- existing_control->setHiddenFromSettingsEditor(hidefromsettingseditor);
- existing_control->setComment(control_map["Comment"].asString());
- }
- else
- {
- LL_ERRS() << "Mismatched type of control variable '"
- << name << "' found while loading '"
- << filename << "'." << LL_ENDL;
- }
- }
- else if(existing_control->isPersisted())
- {
- // save_values is specifically false for (e.g.)
- // SessionSettingsFile and UserSessionSettingsFile -- in other
- // words, for a file that's supposed to be transient.
- existing_control->setValue(control_map["Value"], save_values);
- }
- // *NOTE: If not persisted and not setting defaults,
- // the value should not get loaded.
- }
- else
- {
- // We've never seen this control before. Either we're loading up
- // the initial set of default settings files (set_default_values)
- // -- or we're loading user settings last saved by a viewer that
- // supports a superset of the variables we know.
- // CHOP-962: if we're loading an unrecognized user setting, make
- // sure we save it later. If you try an experimental viewer, tweak
- // a new setting, briefly revert to an old viewer, then return to
- // the new one, we don't want the old viewer to discard the
- // setting you changed.
- if (! set_default_values)
- {
- // Using PERSIST_ALWAYS insists that saveToFile() (which calls
- // LLControlVariable::shouldSave()) must save this control
- // variable regardless of its value. We can safely set this
- // LLControlVariable persistent because the 'persistent' flag
- // is not itself persisted!
- persist = LLControlVariable::PERSIST_ALWAYS;
- // We want to mention unrecognized user settings variables
- // (e.g. from a newer version of the viewer) in the log. But
- // we also arrive here for Boolean variables generated by
- // the notifications subsystem when the user checks "Don't
- // show me this again." These aren't declared in settings.xml;
- // they're actually named for the notification they suppress.
- // We don't want to mention those. Apologies, this is a bit of
- // a hack: we happen to know that user settings go into an
- // LLControlGroup whose name is "Global".
- if (getKey() == "Global")
- {
- LL_INFOS("LLControlGroup") << "preserving unrecognized " << getKey()
- << " settings variable " << name << LL_ENDL;
- }
- }
-
- declareControl(name,
- typeStringToEnum(control_map["Type"].asString()),
- control_map["Value"],
- control_map["Comment"].asString(),
- persist,
- hidefromsettingseditor
- );
- }
-
- ++validitems;
- }
-
- LL_DEBUGS("Settings") << "Loaded " << validitems << " settings from " << filename << LL_ENDL;
- return validitems;
+ LLSD settings;
+ llifstream infile;
+ infile.open(filename.c_str());
+ if(!infile.is_open())
+ {
+ LL_WARNS("Settings") << "Cannot find file " << filename << " to load." << LL_ENDL;
+ return 0;
+ }
+
+ if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(settings, infile))
+ {
+ infile.close();
+ LL_WARNS("Settings") << "Unable to parse LLSD control file " << filename << ". Trying Legacy Method." << LL_ENDL;
+ return loadFromFileLegacy(filename, TRUE, TYPE_STRING);
+ }
+
+ U32 validitems = 0;
+ bool hidefromsettingseditor = false;
+
+ for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)
+ {
+ LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT;
+ std::string const & name = itr->first;
+ LLSD const & control_map = itr->second;
+
+ if(control_map.has("Persist"))
+ {
+ persist = control_map["Persist"].asInteger()?
+ LLControlVariable::PERSIST_NONDFT : LLControlVariable::PERSIST_NO;
+ }
+
+ // Sometimes we want to use the settings system to provide cheap persistence, but we
+ // don't want the settings themselves to be easily manipulated in the UI because
+ // doing so can cause support problems. So we have this option:
+ if(control_map.has("HideFromEditor"))
+ {
+ hidefromsettingseditor = control_map["HideFromEditor"].asInteger();
+ }
+ else
+ {
+ hidefromsettingseditor = false;
+ }
+
+ // If the control exists just set the value from the input file.
+ LLControlVariable* existing_control = getControl(name);
+ if(existing_control)
+ {
+ // set_default_values is true when we're loading the initial,
+ // immutable files from app_settings, e.g. settings.xml.
+ if(set_default_values)
+ {
+ // Override all previously set properties of this control.
+ // ... except for type. The types must match.
+ eControlType new_type = typeStringToEnum(control_map["Type"].asString());
+ if(existing_control->isType(new_type))
+ {
+ existing_control->setDefaultValue(control_map["Value"]);
+ existing_control->setPersist(persist);
+ existing_control->setHiddenFromSettingsEditor(hidefromsettingseditor);
+ existing_control->setComment(control_map["Comment"].asString());
+ }
+ else
+ {
+ LL_ERRS() << "Mismatched type of control variable '"
+ << name << "' found while loading '"
+ << filename << "'." << LL_ENDL;
+ }
+ }
+ else if(existing_control->isPersisted())
+ {
+ // save_values is specifically false for (e.g.)
+ // SessionSettingsFile and UserSessionSettingsFile -- in other
+ // words, for a file that's supposed to be transient.
+ existing_control->setValue(control_map["Value"], save_values);
+ }
+ // *NOTE: If not persisted and not setting defaults,
+ // the value should not get loaded.
+ }
+ else
+ {
+ // We've never seen this control before. Either we're loading up
+ // the initial set of default settings files (set_default_values)
+ // -- or we're loading user settings last saved by a viewer that
+ // supports a superset of the variables we know.
+ // CHOP-962: if we're loading an unrecognized user setting, make
+ // sure we save it later. If you try an experimental viewer, tweak
+ // a new setting, briefly revert to an old viewer, then return to
+ // the new one, we don't want the old viewer to discard the
+ // setting you changed.
+ if (! set_default_values)
+ {
+ // Using PERSIST_ALWAYS insists that saveToFile() (which calls
+ // LLControlVariable::shouldSave()) must save this control
+ // variable regardless of its value. We can safely set this
+ // LLControlVariable persistent because the 'persistent' flag
+ // is not itself persisted!
+ persist = LLControlVariable::PERSIST_ALWAYS;
+ // We want to mention unrecognized user settings variables
+ // (e.g. from a newer version of the viewer) in the log. But
+ // we also arrive here for Boolean variables generated by
+ // the notifications subsystem when the user checks "Don't
+ // show me this again." These aren't declared in settings.xml;
+ // they're actually named for the notification they suppress.
+ // We don't want to mention those. Apologies, this is a bit of
+ // a hack: we happen to know that user settings go into an
+ // LLControlGroup whose name is "Global".
+ if (getKey() == "Global")
+ {
+ LL_INFOS("LLControlGroup") << "preserving unrecognized " << getKey()
+ << " settings variable " << name << LL_ENDL;
+ }
+ }
+
+ declareControl(name,
+ typeStringToEnum(control_map["Type"].asString()),
+ control_map["Value"],
+ control_map["Comment"].asString(),
+ persist,
+ hidefromsettingseditor
+ );
+ }
+
+ ++validitems;
+ }
+
+ LL_DEBUGS("Settings") << "Loaded " << validitems << " settings from " << filename << LL_ENDL;
+ return validitems;
}
void LLControlGroup::resetToDefaults()
{
- ctrl_name_table_t::iterator control_iter;
- for (control_iter = mNameTable.begin();
- control_iter != mNameTable.end();
- ++control_iter)
- {
- LLControlVariable* control = (*control_iter).second;
- control->resetToDefault();
- }
+ ctrl_name_table_t::iterator control_iter;
+ for (control_iter = mNameTable.begin();
+ control_iter != mNameTable.end();
+ ++control_iter)
+ {
+ LLControlVariable* control = (*control_iter).second;
+ control->resetToDefault();
+ }
}
void LLControlGroup::applyToAll(ApplyFunctor* func)
{
- for (ctrl_name_table_t::iterator iter = mNameTable.begin();
- iter != mNameTable.end(); iter++)
- {
- func->apply(iter->first, iter->second);
- }
+ for (ctrl_name_table_t::iterator iter = mNameTable.begin();
+ iter != mNameTable.end(); iter++)
+ {
+ func->apply(iter->first, iter->second);
+ }
}
//============================================================================
@@ -1146,335 +1146,335 @@ void LLControlGroup::applyToAll(ApplyFunctor* func)
#ifdef TEST_HARNESS
void main()
{
- F32_CONTROL foo, getfoo;
-
- S32_CONTROL bar, getbar;
+ F32_CONTROL foo, getfoo;
- BOOL_CONTROL baz;
+ S32_CONTROL bar, getbar;
+
+ BOOL_CONTROL baz;
- U32 count = gGlobals.loadFromFile("controls.ini");
- LL_INFOS("Settings") << "Loaded " << count << " controls" << LL_ENDL;
+ U32 count = gGlobals.loadFromFile("controls.ini");
+ LL_INFOS("Settings") << "Loaded " << count << " controls" << LL_ENDL;
- // test insertion
- foo = new LLControlVariable<F32>("gFoo", 5.f, 1.f, 20.f);
- gGlobals.addEntry("gFoo", foo);
+ // test insertion
+ foo = new LLControlVariable<F32>("gFoo", 5.f, 1.f, 20.f);
+ gGlobals.addEntry("gFoo", foo);
- bar = new LLControlVariable<S32>("gBar", 10, 2, 22);
- gGlobals.addEntry("gBar", bar);
+ bar = new LLControlVariable<S32>("gBar", 10, 2, 22);
+ gGlobals.addEntry("gBar", bar);
- baz = new LLControlVariable<BOOL>("gBaz", FALSE);
- gGlobals.addEntry("gBaz", baz);
+ baz = new LLControlVariable<BOOL>("gBaz", FALSE);
+ gGlobals.addEntry("gBaz", baz);
- // test retrieval
- getfoo = (LLControlVariable<F32>*) gGlobals.resolveName("gFoo");
- getfoo->dump();
+ // test retrieval
+ getfoo = (LLControlVariable<F32>*) gGlobals.resolveName("gFoo");
+ getfoo->dump();
- getbar = (S32_CONTROL) gGlobals.resolveName("gBar");
- getbar->dump();
+ getbar = (S32_CONTROL) gGlobals.resolveName("gBar");
+ getbar->dump();
- // change data
- getfoo->set(10.f);
- getfoo->dump();
+ // change data
+ getfoo->set(10.f);
+ getfoo->dump();
- // Failure modes
+ // Failure modes
- // ...min > max
- // badfoo = new LLControlVariable<F32>("gFoo2", 100.f, 20.f, 5.f);
+ // ...min > max
+ // badfoo = new LLControlVariable<F32>("gFoo2", 100.f, 20.f, 5.f);
- // ...initial > max
- // badbar = new LLControlVariable<S32>("gBar2", 10, 20, 100000);
+ // ...initial > max
+ // badbar = new LLControlVariable<S32>("gBar2", 10, 20, 100000);
- // ...misspelled name
- // getfoo = (F32_CONTROL) gGlobals.resolveName("fooMisspelled");
- // getfoo->dump();
+ // ...misspelled name
+ // getfoo = (F32_CONTROL) gGlobals.resolveName("fooMisspelled");
+ // getfoo->dump();
- // ...invalid data type
- getfoo = (F32_CONTROL) gGlobals.resolveName("gFoo");
- getfoo->set(TRUE);
- getfoo->dump();
+ // ...invalid data type
+ getfoo = (F32_CONTROL) gGlobals.resolveName("gFoo");
+ getfoo->set(TRUE);
+ getfoo->dump();
- // ...out of range data
- // getfoo->set(100000000.f);
- // getfoo->dump();
+ // ...out of range data
+ // getfoo->set(100000000.f);
+ // getfoo->dump();
- // Clean Up
- delete foo;
- delete bar;
- delete baz;
+ // Clean Up
+ delete foo;
+ delete bar;
+ delete baz;
}
#endif
-template <> eControlType get_control_type<U32>()
-{
- return TYPE_U32;
+template <> eControlType get_control_type<U32>()
+{
+ return TYPE_U32;
}
-template <> eControlType get_control_type<S32>()
-{
- return TYPE_S32;
+template <> eControlType get_control_type<S32>()
+{
+ return TYPE_S32;
}
-template <> eControlType get_control_type<F32>()
-{
- return TYPE_F32;
+template <> eControlType get_control_type<F32>()
+{
+ return TYPE_F32;
}
-template <> eControlType get_control_type<bool> ()
-{
- return TYPE_BOOLEAN;
+template <> eControlType get_control_type<bool> ()
+{
+ return TYPE_BOOLEAN;
}
/*
// Yay BOOL, its really an S32.
-template <> eControlType get_control_type<BOOL> ()
-{
- return TYPE_BOOLEAN;
+template <> eControlType get_control_type<BOOL> ()
+{
+ return TYPE_BOOLEAN;
}
*/
-template <> eControlType get_control_type<std::string>()
-{
- return TYPE_STRING;
+template <> eControlType get_control_type<std::string>()
+{
+ return TYPE_STRING;
}
-template <> eControlType get_control_type<LLVector3>()
-{
- return TYPE_VEC3;
+template <> eControlType get_control_type<LLVector3>()
+{
+ return TYPE_VEC3;
}
-template <> eControlType get_control_type<LLVector3d>()
-{
- return TYPE_VEC3D;
+template <> eControlType get_control_type<LLVector3d>()
+{
+ return TYPE_VEC3D;
}
template <> eControlType get_control_type<LLQuaternion>()
{
- return TYPE_QUAT;
+ return TYPE_QUAT;
}
-template <> eControlType get_control_type<LLRect>()
-{
- return TYPE_RECT;
+template <> eControlType get_control_type<LLRect>()
+{
+ return TYPE_RECT;
}
-template <> eControlType get_control_type<LLColor4>()
-{
- return TYPE_COL4;
+template <> eControlType get_control_type<LLColor4>()
+{
+ return TYPE_COL4;
}
-template <> eControlType get_control_type<LLColor3>()
-{
- return TYPE_COL3;
+template <> eControlType get_control_type<LLColor3>()
+{
+ return TYPE_COL3;
}
-template <> eControlType get_control_type<LLSD>()
-{
- return TYPE_LLSD;
+template <> eControlType get_control_type<LLSD>()
+{
+ return TYPE_LLSD;
}
-template <> LLSD convert_to_llsd<U32>(const U32& in)
-{
- return (LLSD::Integer)in;
+template <> LLSD convert_to_llsd<U32>(const U32& in)
+{
+ return (LLSD::Integer)in;
}
-template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in)
-{
- return in.getValue();
+template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in)
+{
+ return in.getValue();
}
-template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in)
-{
- return in.getValue();
+template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in)
+{
+ return in.getValue();
}
template <> LLSD convert_to_llsd<LLQuaternion>(const LLQuaternion& in)
{
- return in.getValue();
+ return in.getValue();
}
-template <> LLSD convert_to_llsd<LLRect>(const LLRect& in)
-{
- return in.getValue();
+template <> LLSD convert_to_llsd<LLRect>(const LLRect& in)
+{
+ return in.getValue();
}
-template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in)
-{
- return in.getValue();
+template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in)
+{
+ return in.getValue();
}
-template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in)
-{
- return in.getValue();
+template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in)
+{
+ return in.getValue();
}
-template <> LLSD convert_to_llsd<LLColor4U>(const LLColor4U& in)
-{
- return in.getValue();
+template <> LLSD convert_to_llsd<LLColor4U>(const LLColor4U& in)
+{
+ return in.getValue();
}
template<>
bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_BOOLEAN)
- return sd.asBoolean();
- else
- {
- CONTROL_ERRS << "Invalid BOOL value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return FALSE;
- }
+ if (type == TYPE_BOOLEAN)
+ return sd.asBoolean();
+ else
+ {
+ CONTROL_ERRS << "Invalid BOOL value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return FALSE;
+ }
}
template<>
S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_S32)
- return sd.asInteger();
- else
- {
- CONTROL_ERRS << "Invalid S32 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return 0;
- }
+ if (type == TYPE_S32)
+ return sd.asInteger();
+ else
+ {
+ CONTROL_ERRS << "Invalid S32 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return 0;
+ }
}
template<>
U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_U32)
- return sd.asInteger();
- else
- {
- CONTROL_ERRS << "Invalid U32 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return 0;
- }
+ if (type == TYPE_U32)
+ return sd.asInteger();
+ else
+ {
+ CONTROL_ERRS << "Invalid U32 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return 0;
+ }
}
template<>
F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_F32)
- return (F32) sd.asReal();
- else
- {
- CONTROL_ERRS << "Invalid F32 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return 0.0f;
- }
+ if (type == TYPE_F32)
+ return (F32) sd.asReal();
+ else
+ {
+ CONTROL_ERRS << "Invalid F32 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return 0.0f;
+ }
}
template<>
std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_STRING)
- return sd.asString();
- else
- {
- CONTROL_ERRS << "Invalid string value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return LLStringUtil::null;
- }
+ if (type == TYPE_STRING)
+ return sd.asString();
+ else
+ {
+ CONTROL_ERRS << "Invalid string value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return LLStringUtil::null;
+ }
}
template<>
LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- return utf8str_to_wstring(convert_from_llsd<std::string>(sd, type, control_name));
+ return utf8str_to_wstring(convert_from_llsd<std::string>(sd, type, control_name));
}
template<>
LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_VEC3)
- return (LLVector3)sd;
- else
- {
- CONTROL_ERRS << "Invalid LLVector3 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return LLVector3::zero;
- }
+ if (type == TYPE_VEC3)
+ return (LLVector3)sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLVector3 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return LLVector3::zero;
+ }
}
template<>
LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_VEC3D)
- return (LLVector3d)sd;
- else
- {
- CONTROL_ERRS << "Invalid LLVector3d value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return LLVector3d::zero;
- }
+ if (type == TYPE_VEC3D)
+ return (LLVector3d)sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLVector3d value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return LLVector3d::zero;
+ }
}
template<>
LLQuaternion convert_from_llsd<LLQuaternion>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_QUAT)
- return (LLQuaternion)sd;
- else
- {
- CONTROL_ERRS << "Invalid LLQuaternion value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return LLQuaternion();
- }
+ if (type == TYPE_QUAT)
+ return (LLQuaternion)sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLQuaternion value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return LLQuaternion();
+ }
}
template<>
LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_RECT)
- return LLRect(sd);
- else
- {
- CONTROL_ERRS << "Invalid rect value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return LLRect::null;
- }
+ if (type == TYPE_RECT)
+ return LLRect(sd);
+ else
+ {
+ CONTROL_ERRS << "Invalid rect value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return LLRect::null;
+ }
}
template<>
LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_COL4)
- {
- LLColor4 color(sd);
- if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)
- {
- LL_WARNS("Settings") << "Color " << control_name << " red value out of range: " << color << LL_ENDL;
- }
- else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)
- {
- LL_WARNS("Settings") << "Color " << control_name << " green value out of range: " << color << LL_ENDL;
- }
- else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)
- {
- LL_WARNS("Settings") << "Color " << control_name << " blue value out of range: " << color << LL_ENDL;
- }
- else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)
- {
- LL_WARNS("Settings") << "Color " << control_name << " alpha value out of range: " << color << LL_ENDL;
- }
-
- return LLColor4(sd);
- }
- else
- {
- CONTROL_ERRS << "Control " << control_name << " not a color" << LL_ENDL;
- return LLColor4::white;
- }
+ if (type == TYPE_COL4)
+ {
+ LLColor4 color(sd);
+ if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)
+ {
+ LL_WARNS("Settings") << "Color " << control_name << " red value out of range: " << color << LL_ENDL;
+ }
+ else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)
+ {
+ LL_WARNS("Settings") << "Color " << control_name << " green value out of range: " << color << LL_ENDL;
+ }
+ else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)
+ {
+ LL_WARNS("Settings") << "Color " << control_name << " blue value out of range: " << color << LL_ENDL;
+ }
+ else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)
+ {
+ LL_WARNS("Settings") << "Color " << control_name << " alpha value out of range: " << color << LL_ENDL;
+ }
+
+ return LLColor4(sd);
+ }
+ else
+ {
+ CONTROL_ERRS << "Control " << control_name << " not a color" << LL_ENDL;
+ return LLColor4::white;
+ }
}
template<>
LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- if (type == TYPE_COL3)
- return sd;
- else
- {
- CONTROL_ERRS << "Invalid LLColor3 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
- return LLColor3::white;
- }
+ if (type == TYPE_COL3)
+ return sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLColor3 value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL;
+ return LLColor3::white;
+ }
}
template<>
LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name)
{
- return sd;
+ return sd;
}
@@ -1502,21 +1502,21 @@ static LLCachedControl<std::string> test_BrowserHomePage("BrowserHomePage", "hah
void test_cached_control()
{
#define TEST_LLCC(T, V) if((T)mySetting_##T != V) LL_ERRS() << "Fail "#T << LL_ENDL
- TEST_LLCC(U32, 666);
- TEST_LLCC(S32, (S32)-666);
- TEST_LLCC(F32, (F32)-666.666);
- TEST_LLCC(bool, true);
- TEST_LLCC(BOOL, FALSE);
- if((std::string)mySetting_string != "Default String Value") LL_ERRS() << "Fail string" << LL_ENDL;
- TEST_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f));
- TEST_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f));
- TEST_LLCC(LLRect, LLRect(0, 0, 100, 500));
- TEST_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f));
- TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
- TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
-//There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd);
-
- if((std::string)test_BrowserHomePage != "http://www.secondlife.com") LL_ERRS() << "Fail BrowserHomePage" << LL_ENDL;
+ TEST_LLCC(U32, 666);
+ TEST_LLCC(S32, (S32)-666);
+ TEST_LLCC(F32, (F32)-666.666);
+ TEST_LLCC(bool, true);
+ TEST_LLCC(BOOL, FALSE);
+ if((std::string)mySetting_string != "Default String Value") LL_ERRS() << "Fail string" << LL_ENDL;
+ TEST_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f));
+ TEST_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f));
+ TEST_LLCC(LLRect, LLRect(0, 0, 100, 500));
+ TEST_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f));
+ TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
+ TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
+//There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd);
+
+ if((std::string)test_BrowserHomePage != "http://www.secondlife.com") LL_ERRS() << "Fail BrowserHomePage" << LL_ENDL;
}
#endif // TEST_CACHED_CONTROL
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index 37663a6fb2..5a8d688892 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcontrol.h
* @brief A mechanism for storing "control state" for a program
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -48,13 +48,13 @@
#include <boost/bind.hpp>
#if LL_WINDOWS
- #pragma warning (push)
- #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
- #pragma warning (disable : 4264)
+ #pragma warning (push)
+ #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
+ #pragma warning (disable : 4264)
#endif
#include <boost/signals2.hpp>
#if LL_WINDOWS
- #pragma warning (pop)
+ #pragma warning (pop)
#endif
#if LL_WINDOWS
@@ -72,241 +72,241 @@ class LLColor3;
// if this is changed, also modify mTypeString in llcontrol.h
typedef enum e_control_type
{
- TYPE_U32 = 0,
- TYPE_S32,
- TYPE_F32,
- TYPE_BOOLEAN,
- TYPE_STRING,
- TYPE_VEC3,
- TYPE_VEC3D,
- TYPE_QUAT,
- TYPE_RECT,
- TYPE_COL4,
- TYPE_COL3,
- TYPE_LLSD,
- TYPE_COUNT
+ TYPE_U32 = 0,
+ TYPE_S32,
+ TYPE_F32,
+ TYPE_BOOLEAN,
+ TYPE_STRING,
+ TYPE_VEC3,
+ TYPE_VEC3D,
+ TYPE_QUAT,
+ TYPE_RECT,
+ TYPE_COL4,
+ TYPE_COL3,
+ TYPE_LLSD,
+ TYPE_COUNT
} eControlType;
class LLControlVariable : public LLRefCount
{
- LOG_CLASS(LLControlVariable);
-
- friend class LLControlGroup;
+ LOG_CLASS(LLControlVariable);
+ friend class LLControlGroup;
+
public:
- typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;
- typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&, const LLSD&)> commit_signal_t;
+ typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;
+ typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&, const LLSD&)> commit_signal_t;
- enum ePersist
- {
- PERSIST_NO, // don't save this var
- PERSIST_NONDFT, // save this var if differs from default
- PERSIST_ALWAYS // save this var even if has default value
- };
+ enum ePersist
+ {
+ PERSIST_NO, // don't save this var
+ PERSIST_NONDFT, // save this var if differs from default
+ PERSIST_ALWAYS // save this var even if has default value
+ };
private:
- std::string mName;
- std::string mComment;
- eControlType mType;
- ePersist mPersist;
- bool mHideFromSettingsEditor;
- std::vector<LLSD> mValues;
-
- commit_signal_t mCommitSignal;
- validate_signal_t mValidateSignal;
-
+ std::string mName;
+ std::string mComment;
+ eControlType mType;
+ ePersist mPersist;
+ bool mHideFromSettingsEditor;
+ std::vector<LLSD> mValues;
+
+ commit_signal_t mCommitSignal;
+ validate_signal_t mValidateSignal;
+
public:
- LLControlVariable(const std::string& name, eControlType type,
- LLSD initial, const std::string& comment,
- ePersist persist = PERSIST_NONDFT, bool hidefromsettingseditor = false);
-
- virtual ~LLControlVariable();
-
- const std::string& getName() const { return mName; }
- const std::string& getComment() const { return mComment; }
-
- eControlType type() { return mType; }
- bool isType(eControlType tp) { return tp == mType; }
-
- void resetToDefault(bool fire_signal = false);
-
- commit_signal_t* getSignal() { return &mCommitSignal; } // shorthand for commit signal
- commit_signal_t* getCommitSignal() { return &mCommitSignal; }
- validate_signal_t* getValidateSignal() { return &mValidateSignal; }
-
- bool isDefault() { return (mValues.size() == 1); }
- bool shouldSave(bool nondefault_only);
- bool isPersisted() { return mPersist != PERSIST_NO; }
- bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; }
- LLSD get() const { return getValue(); }
- LLSD getValue() const { return mValues.back(); }
- LLSD getDefault() const { return mValues.front(); }
- LLSD getSaveValue() const;
-
- void set(const LLSD& val) { setValue(val); }
- void setValue(const LLSD& value, bool saved_value = TRUE);
- void setDefaultValue(const LLSD& value);
- void setPersist(ePersist);
- void setHiddenFromSettingsEditor(bool hide);
- void setComment(const std::string& comment);
+ LLControlVariable(const std::string& name, eControlType type,
+ LLSD initial, const std::string& comment,
+ ePersist persist = PERSIST_NONDFT, bool hidefromsettingseditor = false);
+
+ virtual ~LLControlVariable();
+
+ const std::string& getName() const { return mName; }
+ const std::string& getComment() const { return mComment; }
+
+ eControlType type() { return mType; }
+ bool isType(eControlType tp) { return tp == mType; }
+
+ void resetToDefault(bool fire_signal = false);
+
+ commit_signal_t* getSignal() { return &mCommitSignal; } // shorthand for commit signal
+ commit_signal_t* getCommitSignal() { return &mCommitSignal; }
+ validate_signal_t* getValidateSignal() { return &mValidateSignal; }
+
+ bool isDefault() { return (mValues.size() == 1); }
+ bool shouldSave(bool nondefault_only);
+ bool isPersisted() { return mPersist != PERSIST_NO; }
+ bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; }
+ LLSD get() const { return getValue(); }
+ LLSD getValue() const { return mValues.back(); }
+ LLSD getDefault() const { return mValues.front(); }
+ LLSD getSaveValue() const;
+
+ void set(const LLSD& val, bool saved_value = true) { setValue(val, saved_value); }
+ void setValue(const LLSD& value, bool saved_value = TRUE);
+ void setDefaultValue(const LLSD& value);
+ void setPersist(ePersist);
+ void setHiddenFromSettingsEditor(bool hide);
+ void setComment(const std::string& comment);
private:
- void firePropertyChanged(const LLSD &pPreviousValue)
- {
- mCommitSignal(this, mValues.back(), pPreviousValue);
- }
- LLSD getComparableValue(const LLSD& value);
- bool llsd_compare(const LLSD& a, const LLSD & b);
+ void firePropertyChanged(const LLSD &pPreviousValue)
+ {
+ mCommitSignal(this, mValues.back(), pPreviousValue);
+ }
+ LLSD getComparableValue(const LLSD& value);
+ bool llsd_compare(const LLSD& a, const LLSD & b);
};
typedef LLPointer<LLControlVariable> LLControlVariablePtr;
//! Helper functions for converting between static types and LLControl values
-template <class T>
+template <class T>
eControlType get_control_type()
{
- LL_WARNS() << "Usupported control type: " << typeid(T).name() << "." << LL_ENDL;
- return TYPE_COUNT;
+ LL_WARNS() << "Usupported control type: " << typeid(T).name() << "." << LL_ENDL;
+ return TYPE_COUNT;
}
-template <class T>
+template <class T>
LLSD convert_to_llsd(const T& in)
{
- // default implementation
- return LLSD(in);
+ // default implementation
+ return LLSD(in);
}
template <class T>
T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& control_name)
{
- // needs specialization
- return T(sd);
+ // needs specialization
+ return T(sd);
}
//const U32 STRING_CACHE_SIZE = 10000;
class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
{
- LOG_CLASS(LLControlGroup);
+ LOG_CLASS(LLControlGroup);
protected:
- typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;
- ctrl_name_table_t mNameTable;
- static const std::string mTypeString[TYPE_COUNT];
+ typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;
+ ctrl_name_table_t mNameTable;
+ static const std::string mTypeString[TYPE_COUNT];
public:
- static eControlType typeStringToEnum(const std::string& typestr);
- static std::string typeEnumToString(eControlType typeenum);
-
- LLControlGroup(const std::string& name);
- ~LLControlGroup();
- void cleanup();
-
- LLControlVariablePtr getControl(const std::string& name);
-
- struct ApplyFunctor
- {
- virtual ~ApplyFunctor() {};
- virtual void apply(const std::string& name, LLControlVariable* control) = 0;
- };
- void applyToAll(ApplyFunctor* func);
-
- LLControlVariable* declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor = FALSE);
- LLControlVariable* declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareS32(const std::string& name, S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareF32(const std::string& name, F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareQuat(const std::string& name, const LLQuaternion &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
- LLControlVariable* declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
-
- std::string getString(const std::string& name);
- std::string getText(const std::string& name);
- BOOL getBOOL(const std::string& name);
- S32 getS32(const std::string& name);
- F32 getF32(const std::string& name);
- U32 getU32(const std::string& name);
-
- LLWString getWString(const std::string& name);
- LLVector3 getVector3(const std::string& name);
- LLVector3d getVector3d(const std::string& name);
- LLRect getRect(const std::string& name);
- LLSD getLLSD(const std::string& name);
- LLQuaternion getQuaternion(const std::string& name);
-
- LLColor4 getColor(const std::string& name);
- LLColor4 getColor4(const std::string& name);
- LLColor3 getColor3(const std::string& name);
-
- LLSD asLLSD(bool diffs_only);
-
- // generic getter
- template<typename T> T get(const std::string& name)
- {
+ static eControlType typeStringToEnum(const std::string& typestr);
+ static std::string typeEnumToString(eControlType typeenum);
+
+ LLControlGroup(const std::string& name);
+ ~LLControlGroup();
+ void cleanup();
+
+ LLControlVariablePtr getControl(const std::string& name);
+
+ struct ApplyFunctor
+ {
+ virtual ~ApplyFunctor() {};
+ virtual void apply(const std::string& name, LLControlVariable* control) = 0;
+ };
+ void applyToAll(ApplyFunctor* func);
+
+ LLControlVariable* declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor = FALSE);
+ LLControlVariable* declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareS32(const std::string& name, S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareF32(const std::string& name, F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareQuat(const std::string& name, const LLQuaternion &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+ LLControlVariable* declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
+
+ std::string getString(const std::string& name);
+ std::string getText(const std::string& name);
+ BOOL getBOOL(const std::string& name);
+ S32 getS32(const std::string& name);
+ F32 getF32(const std::string& name);
+ U32 getU32(const std::string& name);
+
+ LLWString getWString(const std::string& name);
+ LLVector3 getVector3(const std::string& name);
+ LLVector3d getVector3d(const std::string& name);
+ LLRect getRect(const std::string& name);
+ LLSD getLLSD(const std::string& name);
+ LLQuaternion getQuaternion(const std::string& name);
+
+ LLColor4 getColor(const std::string& name);
+ LLColor4 getColor4(const std::string& name);
+ LLColor3 getColor3(const std::string& name);
+
+ LLSD asLLSD(bool diffs_only);
+
+ // generic getter
+ template<typename T> T get(const std::string& name)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- LLControlVariable* control = getControl(name);
- LLSD value;
- eControlType type = TYPE_COUNT;
-
- if (control)
- {
- value = control->get();
- type = control->type();
- }
- else
- {
- LL_WARNS() << "Control " << name << " not found." << LL_ENDL;
- return T();
- }
- return convert_from_llsd<T>(value, type, name);
- }
-
- void setBOOL(const std::string& name, BOOL val);
- void setS32(const std::string& name, S32 val);
- void setF32(const std::string& name, F32 val);
- void setU32(const std::string& name, U32 val);
- void setString(const std::string& name, const std::string& val);
- void setVector3(const std::string& name, const LLVector3 &val);
- void setVector3d(const std::string& name, const LLVector3d &val);
- void setQuaternion(const std::string& name, const LLQuaternion &val);
- void setRect(const std::string& name, const LLRect &val);
- void setColor4(const std::string& name, const LLColor4 &val);
- void setLLSD(const std::string& name, const LLSD& val);
-
- // type agnostic setter that takes LLSD
- void setUntypedValue(const std::string& name, const LLSD& val);
-
- // generic setter
- template<typename T> void set(const std::string& name, const T& val)
- {
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(get_control_type<T>()))
- {
- control->set(convert_to_llsd(val));
- }
- else
- {
- LL_WARNS() << "Invalid control " << name << LL_ENDL;
- }
- }
-
- BOOL controlExists(const std::string& name);
-
- // Returns number of controls loaded, 0 if failed
- // If require_declaration is false, will auto-declare controls it finds
- // as the given type.
- U32 loadFromFileLegacy(const std::string& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING);
- U32 saveToFile(const std::string& filename, BOOL nondefault_only);
- U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true);
- void resetToDefaults();
- void incrCount(const std::string& name);
-
- bool mSettingsProfile;
+ LLControlVariable* control = getControl(name);
+ LLSD value;
+ eControlType type = TYPE_COUNT;
+
+ if (control)
+ {
+ value = control->get();
+ type = control->type();
+ }
+ else
+ {
+ LL_WARNS() << "Control " << name << " not found." << LL_ENDL;
+ return T();
+ }
+ return convert_from_llsd<T>(value, type, name);
+ }
+
+ void setBOOL(const std::string& name, BOOL val);
+ void setS32(const std::string& name, S32 val);
+ void setF32(const std::string& name, F32 val);
+ void setU32(const std::string& name, U32 val);
+ void setString(const std::string& name, const std::string& val);
+ void setVector3(const std::string& name, const LLVector3 &val);
+ void setVector3d(const std::string& name, const LLVector3d &val);
+ void setQuaternion(const std::string& name, const LLQuaternion &val);
+ void setRect(const std::string& name, const LLRect &val);
+ void setColor4(const std::string& name, const LLColor4 &val);
+ void setLLSD(const std::string& name, const LLSD& val);
+
+ // type agnostic setter that takes LLSD
+ void setUntypedValue(const std::string& name, const LLSD& val, bool saved_value = true);
+
+ // generic setter
+ template<typename T> void set(const std::string& name, const T& val)
+ {
+ LLControlVariable* control = getControl(name);
+
+ if (control && control->isType(get_control_type<T>()))
+ {
+ control->set(convert_to_llsd(val));
+ }
+ else
+ {
+ LL_WARNS() << "Invalid control " << name << LL_ENDL;
+ }
+ }
+
+ BOOL controlExists(const std::string& name);
+
+ // Returns number of controls loaded, 0 if failed
+ // If require_declaration is false, will auto-declare controls it finds
+ // as the given type.
+ U32 loadFromFileLegacy(const std::string& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING);
+ U32 saveToFile(const std::string& filename, BOOL nondefault_only);
+ U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true);
+ void resetToDefaults();
+ void incrCount(const std::string& name);
+
+ bool mSettingsProfile;
};
@@ -319,124 +319,124 @@ template <class T>
class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCache<T>, std::string>
{
public:
- // This constructor will declare a control if it doesn't exist in the contol group
- LLControlCache(LLControlGroup& group,
- const std::string& name,
- const T& default_value,
- const std::string& comment)
- : LLInstanceTracker<LLControlCache<T>, std::string >(name)
- {
- if(!group.controlExists(name))
- {
- if(!declareTypedControl(group, name, default_value, comment))
- {
- LL_ERRS() << "The control could not be created!!!" << LL_ENDL;
- }
- }
-
- bindToControl(group, name);
- }
-
- LLControlCache(LLControlGroup& group,
- const std::string& name)
- : LLInstanceTracker<LLControlCache<T>, std::string >(name)
- {
- if(!group.controlExists(name))
- {
- LL_ERRS() << "Control named " << name << "not found." << LL_ENDL;
- }
-
- bindToControl(group, name);
- }
-
- ~LLControlCache()
- {
- }
-
- const T& getValue() const { return mCachedValue; }
-
+ // This constructor will declare a control if it doesn't exist in the contol group
+ LLControlCache(LLControlGroup& group,
+ const std::string& name,
+ const T& default_value,
+ const std::string& comment)
+ : LLInstanceTracker<LLControlCache<T>, std::string >(name)
+ {
+ if(!group.controlExists(name))
+ {
+ if(!declareTypedControl(group, name, default_value, comment))
+ {
+ LL_ERRS() << "The control could not be created!!!" << LL_ENDL;
+ }
+ }
+
+ bindToControl(group, name);
+ }
+
+ LLControlCache(LLControlGroup& group,
+ const std::string& name)
+ : LLInstanceTracker<LLControlCache<T>, std::string >(name)
+ {
+ if(!group.controlExists(name))
+ {
+ LL_ERRS() << "Control named " << name << "not found." << LL_ENDL;
+ }
+
+ bindToControl(group, name);
+ }
+
+ ~LLControlCache()
+ {
+ }
+
+ const T& getValue() const { return mCachedValue; }
+
private:
- void bindToControl(LLControlGroup& group, const std::string& name)
- {
- LLControlVariablePtr controlp = group.getControl(name);
- mType = controlp->type();
- mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name);
-
- // Add a listener to the controls signal...
- // NOTE: All listeners connected to 0 group, for guaranty that variable handlers (gSavedSettings) call last
- mConnection = controlp->getSignal()->connect(0,
- boost::bind(&LLControlCache<T>::handleValueChange, this, _2)
- );
- mType = controlp->type();
- }
- bool declareTypedControl(LLControlGroup& group,
- const std::string& name,
- const T& default_value,
- const std::string& comment)
- {
- LLSD init_value;
- eControlType type = get_control_type<T>();
- init_value = convert_to_llsd(default_value);
- if(type < TYPE_COUNT)
- {
- group.declareControl(name, type, init_value, comment, LLControlVariable::PERSIST_NO);
- return true;
- }
- return false;
- }
-
- bool handleValueChange(const LLSD& newvalue)
- {
- mCachedValue = convert_from_llsd<T>(newvalue, mType, "");
- return true;
- }
+ void bindToControl(LLControlGroup& group, const std::string& name)
+ {
+ LLControlVariablePtr controlp = group.getControl(name);
+ mType = controlp->type();
+ mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name);
+
+ // Add a listener to the controls signal...
+ // NOTE: All listeners connected to 0 group, for guaranty that variable handlers (gSavedSettings) call last
+ mConnection = controlp->getSignal()->connect(0,
+ boost::bind(&LLControlCache<T>::handleValueChange, this, _2)
+ );
+ mType = controlp->type();
+ }
+ bool declareTypedControl(LLControlGroup& group,
+ const std::string& name,
+ const T& default_value,
+ const std::string& comment)
+ {
+ LLSD init_value;
+ eControlType type = get_control_type<T>();
+ init_value = convert_to_llsd(default_value);
+ if(type < TYPE_COUNT)
+ {
+ group.declareControl(name, type, init_value, comment, LLControlVariable::PERSIST_NO);
+ return true;
+ }
+ return false;
+ }
+
+ bool handleValueChange(const LLSD& newvalue)
+ {
+ mCachedValue = convert_from_llsd<T>(newvalue, mType, "");
+ return true;
+ }
private:
- T mCachedValue;
- eControlType mType;
- boost::signals2::scoped_connection mConnection;
+ T mCachedValue;
+ eControlType mType;
+ boost::signals2::scoped_connection mConnection;
};
template <typename T>
class LLCachedControl
{
public:
- LLCachedControl(LLControlGroup& group,
- const std::string& name,
- const T& default_value,
- const std::string& comment = "Declared In Code")
- {
- mCachedControlPtr = LLControlCache<T>::getInstance(name).get();
- if (! mCachedControlPtr)
- {
- mCachedControlPtr = new LLControlCache<T>(group, name, default_value, comment);
- }
- }
-
- LLCachedControl(LLControlGroup& group,
- const std::string& name)
- {
- mCachedControlPtr = LLControlCache<T>::getInstance(name).get();
- if (! mCachedControlPtr)
- {
- mCachedControlPtr = new LLControlCache<T>(group, name);
- }
- }
-
- operator const T&() const { return mCachedControlPtr->getValue(); }
- operator boost::function<const T&()> () const { return boost::function<const T&()>(*this); }
- const T& operator()() { return mCachedControlPtr->getValue(); }
+ LLCachedControl(LLControlGroup& group,
+ const std::string& name,
+ const T& default_value,
+ const std::string& comment = "Declared In Code")
+ {
+ mCachedControlPtr = LLControlCache<T>::getInstance(name).get();
+ if (! mCachedControlPtr)
+ {
+ mCachedControlPtr = new LLControlCache<T>(group, name, default_value, comment);
+ }
+ }
+
+ LLCachedControl(LLControlGroup& group,
+ const std::string& name)
+ {
+ mCachedControlPtr = LLControlCache<T>::getInstance(name).get();
+ if (! mCachedControlPtr)
+ {
+ mCachedControlPtr = new LLControlCache<T>(group, name);
+ }
+ }
+
+ operator const T&() const { return mCachedControlPtr->getValue(); }
+ operator boost::function<const T&()> () const { return boost::function<const T&()>(*this); }
+ const T& operator()() { return mCachedControlPtr->getValue(); }
private:
- LLPointer<LLControlCache<T> > mCachedControlPtr;
+ LLPointer<LLControlCache<T> > mCachedControlPtr;
};
template <> eControlType get_control_type<U32>();
template <> eControlType get_control_type<S32>();
template <> eControlType get_control_type<F32>();
-template <> eControlType get_control_type<bool>();
+template <> eControlType get_control_type<bool>();
// Yay BOOL, its really an S32.
-//template <> eControlType get_control_type<BOOL> ()
+//template <> eControlType get_control_type<BOOL> ()
template <> eControlType get_control_type<std::string>();
template <> eControlType get_control_type<LLVector3>();
template <> eControlType get_control_type<LLVector3d>();
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index a6ae041935..f2d5ed26ee 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -48,6 +48,7 @@ include(VulkanGltf)
include(ZLIBNG)
include(URIPARSER)
include(LLPrimitive)
+include(Lualibs)
if (NOT HAVOK_TPV)
# When using HAVOK_TPV, the library is precompiled, so no need for this
@@ -242,6 +243,8 @@ set(viewer_SOURCE_FILES
llfloaterlandholdings.cpp
llfloaterlinkreplace.cpp
llfloaterloadprefpreset.cpp
+ llfloaterluadebug.cpp
+ llfloaterluascripts.cpp
llfloatermarketplacelistings.cpp
llfloatermap.cpp
llfloatermediasettings.cpp
@@ -371,6 +374,7 @@ set(viewer_SOURCE_FILES
lllogchat.cpp
llloginhandler.cpp
lllogininstance.cpp
+ llluamanager.cpp
llmachineid.cpp
llmanip.cpp
llmaniprotate.cpp
@@ -899,6 +903,8 @@ set(viewer_HEADER_FILES
llfloaterlandholdings.h
llfloaterlinkreplace.h
llfloaterloadprefpreset.h
+ llfloaterluadebug.h
+ llfloaterluascripts.h
llfloatermap.h
llfloatermarketplacelistings.h
llfloatermediasettings.h
@@ -1026,6 +1032,7 @@ set(viewer_HEADER_FILES
lllogchat.h
llloginhandler.h
lllogininstance.h
+ llluamanager.h
llmachineid.h
llmanip.h
llmaniprotate.h
@@ -1804,20 +1811,6 @@ if (WINDOWS)
if (PACKAGE)
add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.xz
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py
- ${CMAKE_CURRENT_SOURCE_DIR}/..
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_CFG_INTDIR}
- DEPENDS
- lleventhost
- ${EVENT_HOST_SCRIPTS}
- ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py
- )
-
- add_custom_command(
OUTPUT ${CMAKE_CFG_INTDIR}/touched.bat
COMMAND ${PYTHON_EXECUTABLE}
ARGS
@@ -1846,9 +1839,6 @@ if (WINDOWS)
add_custom_target(llpackage ALL DEPENDS
${CMAKE_CFG_INTDIR}/touched.bat
)
- # temporarily disable packaging of event_host until hg subrepos get
- # sorted out on the parabuild cluster...
- #${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.xz)
endif (PACKAGE)
elseif (DARWIN)
@@ -1909,14 +1899,15 @@ target_link_libraries(${VIEWER_BINARY_NAME}
llcorehttp
llcommon
llmeshoptimizer
- ll::ndof
lllogin
llprimitive
llappearance
${LLPHYSICSEXTENSIONS_LIBRARIES}
ll::bugsplat
- ll::tracy
ll::icu4c
+ ll::lualibs
+ ll::ndof
+ ll::tracy
)
if( TARGET ll::intel_memops )
@@ -2315,6 +2306,11 @@ if (LL_TESTS)
"${test_libs}"
)
+ LL_ADD_INTEGRATION_TEST(llluamanager
+ "llluamanager.cpp"
+ "${test_libs};ll::lualibs"
+ )
+
LL_ADD_INTEGRATION_TEST(llsechandler_basic
llsechandler_basic.cpp
"${test_libs}"
@@ -2369,4 +2365,3 @@ if (LL_TESTS)
endif (LL_TESTS)
check_message_template(${VIEWER_BINARY_NAME})
-
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 340334aee8..534d1d594d 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -195,7 +195,33 @@
<string>LogPerformance</string>
</map>
- <key>multiple</key>
+ <key>lua</key>
+ <map>
+ <key>desc</key>
+ <string>Run specified Lua chunk</string>
+ <key>count</key>
+ <integer>1</integer>
+ <!-- you can specify multiple such chunks -->
+ <key>compose</key>
+ <boolean>true</boolean>
+ <key>map-to</key>
+ <string>LuaChunk</string>
+ </map>
+
+ <key>luafile</key>
+ <map>
+ <key>desc</key>
+ <string>Run specified Lua script</string>
+ <key>count</key>
+ <integer>1</integer>
+ <!-- you can specify multiple such scripts -->
+ <key>compose</key>
+ <boolean>true</boolean>
+ <key>map-to</key>
+ <string>LuaScript</string>
+ </map>
+
+ <key>multiple</key>
<map>
<key>desc</key>
<string>Allow multiple viewers.</string>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 2f7c256b49..68eb3093be 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -68,7 +68,7 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>CrashHostUrl</key>
+ <key>CrashHostUrl</key>
<map>
<key>Comment</key>
<string>A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler.</string>
@@ -5398,6 +5398,28 @@
<key>Value</key>
<string>Monospace</string>
</map>
+ <key>LuaChunk</key>
+ <map>
+ <key>Comment</key>
+ <string>Zero or more Lua chunks to run</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>LLSD</string>
+ <key>Value</key>
+ <array />
+ </map>
+ <key>LuaScript</key>
+ <map>
+ <key>Comment</key>
+ <string>Zero or more Lua script files to run</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>LLSD</string>
+ <key>Value</key>
+ <array />
+ </map>
<key>GridStatusRSS</key>
<map>
<key>Comment</key>
@@ -17339,6 +17361,17 @@
<key>Value</key>
<integer>3</integer>
</map>
+ <key>AutorunLuaScriptName</key>
+ <map>
+ <key>Comment</key>
+ <string>Script name to autorun after login.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>default.lua</string>
+ </map>
<key>ResetUIScaleOnFirstRun</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 754ee5aa23..0b566cbc73 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -60,6 +60,7 @@
#include "llslurl.h"
#include "llstartup.h"
#include "llfocusmgr.h"
+#include "llluamanager.h"
#include "llurlfloaterdispatchhandler.h"
#include "llviewerjoystick.h"
#include "llallocator.h"
@@ -108,7 +109,7 @@
#include "llscenemonitor.h"
#include "llavatarrenderinfoaccountant.h"
#include "lllocalbitmaps.h"
-#include "llperfstats.h"
+#include "llperfstats.h"
#include "llgltfmateriallist.h"
// Linden library includes
@@ -148,7 +149,7 @@
#include <boost/throw_exception.hpp>
#if LL_WINDOWS
-# include <share.h> // For _SH_DENYWR in processMarkerFiles
+# include <share.h> // For _SH_DENYWR in processMarkerFiles
#else
# include <sys/file.h> // For processMarkerFiles
#endif
@@ -316,16 +317,16 @@ const char* gPlatform = LL_PLATFORM_KEY;
LLSD gDebugInfo;
-U32 gFrameCount = 0;
+U32 gFrameCount = 0;
U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
LLPumpIO* gServicePump = NULL;
U64MicrosecondsImplicit gFrameTime = 0;
F32SecondsImplicit gFrameTimeSeconds = 0.f;
F32SecondsImplicit gFrameIntervalSeconds = 0.f;
-F32 gFPSClamped = 10.f; // Pretend we start at target rate.
-F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets
-U64MicrosecondsImplicit gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
+F32 gFPSClamped = 10.f; // Pretend we start at target rate.
+F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets
+U64MicrosecondsImplicit gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
LLTimer gRenderStartTime;
LLFrameTimer gForegroundTime;
@@ -338,24 +339,24 @@ F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
S32 gPendingMetricsUploads = 0;
-BOOL gDisconnected = FALSE;
+BOOL gDisconnected = FALSE;
// used to restore texture state after a mode switch
-LLFrameTimer gRestoreGLTimer;
-BOOL gRestoreGL = FALSE;
-bool gUseWireframe = FALSE;
+LLFrameTimer gRestoreGLTimer;
+BOOL gRestoreGL = FALSE;
+bool gUseWireframe = FALSE;
LLMemoryInfo gSysMemory;
U64Bytes gMemoryAllocated(0); // updated in display_stats() in llviewerdisplay.cpp
std::string gLastVersionChannel;
-LLVector3 gWindVec(3.0, 3.0, 0.0);
-LLVector3 gRelativeWindVec(0.0, 0.0, 0.0);
+LLVector3 gWindVec(3.0, 3.0, 0.0);
+LLVector3 gRelativeWindVec(0.0, 0.0, 0.0);
-U32 gPacketsIn = 0;
+U32 gPacketsIn = 0;
-BOOL gPrintMessagesThisFrame = FALSE;
+BOOL gPrintMessagesThisFrame = FALSE;
BOOL gRandomizeFramerate = FALSE;
BOOL gPeriodicSlowFrame = FALSE;
@@ -384,59 +385,62 @@ static std::string gLaunchFileOnQuit;
// Used on Win32 for other apps to identify our window (eg, win_setup)
const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
+void processComposeSwitch(const std::string&, const std::string&,
+ const std::function<void(const LLSD&)>&);
+
//----------------------------------------------------------------------------
// List of entries from strings.xml to always replace
static std::set<std::string> default_trans_args;
void init_default_trans_args()
{
- default_trans_args.insert("SECOND_LIFE"); // World
- default_trans_args.insert("APP_NAME");
- default_trans_args.insert("CAPITALIZED_APP_NAME");
- default_trans_args.insert("SECOND_LIFE_GRID");
- default_trans_args.insert("SUPPORT_SITE");
- // This URL shows up in a surprising number of places in various skin
- // files. We really only want to have to maintain a single copy of it.
- default_trans_args.insert("create_account_url");
+ default_trans_args.insert("SECOND_LIFE"); // World
+ default_trans_args.insert("APP_NAME");
+ default_trans_args.insert("CAPITALIZED_APP_NAME");
+ default_trans_args.insert("SECOND_LIFE_GRID");
+ default_trans_args.insert("SUPPORT_SITE");
+ // This URL shows up in a surprising number of places in various skin
+ // files. We really only want to have to maintain a single copy of it.
+ default_trans_args.insert("create_account_url");
}
struct SettingsFile : public LLInitParam::Block<SettingsFile>
{
- Mandatory<std::string> name;
- Optional<std::string> file_name;
- Optional<bool> required,
- persistent;
- Optional<std::string> file_name_setting;
-
- SettingsFile()
- : name("name"),
- file_name("file_name"),
- required("required", false),
- persistent("persistent", true),
- file_name_setting("file_name_setting")
- {}
+ Mandatory<std::string> name;
+ Optional<std::string> file_name;
+ Optional<bool> required,
+ persistent;
+ Optional<std::string> file_name_setting;
+
+ SettingsFile()
+ : name("name"),
+ file_name("file_name"),
+ required("required", false),
+ persistent("persistent", true),
+ file_name_setting("file_name_setting")
+ {}
};
struct SettingsGroup : public LLInitParam::Block<SettingsGroup>
{
- Mandatory<std::string> name;
- Mandatory<S32> path_index;
- Multiple<SettingsFile> files;
-
- SettingsGroup()
- : name("name"),
- path_index("path_index"),
- files("file")
- {}
+ Mandatory<std::string> name;
+ Mandatory<S32> path_index;
+ Multiple<SettingsFile> files;
+
+ SettingsGroup()
+ : name("name"),
+ path_index("path_index"),
+ files("file")
+ {}
};
struct SettingsFiles : public LLInitParam::Block<SettingsFiles>
{
- Multiple<SettingsGroup> groups;
+ Multiple<SettingsGroup> groups;
- SettingsFiles()
- : groups("group")
- {}
+ SettingsFiles()
+ : groups("group")
+ {}
};
static std::string gWindowTitle;
@@ -451,122 +455,122 @@ static bool app_metrics_qa_mode = false;
void idle_afk_check()
{
- // check idle timers
- F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32();
- F32 afk_timeout = gSavedSettings.getS32("AFKTimeout");
- if (afk_timeout && (current_idle > afk_timeout) && ! gAgent.getAFK())
- {
- LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
- gAgent.setAFK();
- }
+ // check idle timers
+ F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32();
+ F32 afk_timeout = gSavedSettings.getS32("AFKTimeout");
+ if (afk_timeout && (current_idle > afk_timeout) && ! gAgent.getAFK())
+ {
+ LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
+ gAgent.setAFK();
+ }
}
// A callback set in LLAppViewer::init()
static void ui_audio_callback(const LLUUID& uuid)
{
- if (gAudiop)
- {
- SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
- gAudiop->triggerSound(soundData);
- }
+ if (gAudiop)
+ {
+ SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
+ gAudiop->triggerSound(soundData);
+ }
}
// A callback set in LLAppViewer::init()
static void deferred_ui_audio_callback(const LLUUID& uuid)
{
- if (gAudiop)
- {
- SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
- LLDeferredSounds::instance().deferSound(soundData);
- }
+ if (gAudiop)
+ {
+ SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
+ LLDeferredSounds::instance().deferSound(soundData);
+ }
}
-bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
+bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
{
- if(!match || !base || base->getPlainText())
- return false;
-
- LLUUID match_id = match->getID();
-
- LLIconCtrl* icon;
-
- if( match->getMenuName() == "menu_url_group.xml" // See LLUrlEntryGroup constructor
- || gAgent.isInGroup(match_id, TRUE)) //This check seems unfiting, urls are either /agent or /group
- {
- LLGroupIconCtrl::Params icon_params;
- icon_params.group_id = match_id;
- icon_params.rect = LLRect(0, 16, 16, 0);
- icon_params.visible = true;
- icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params);
- }
- else
- {
- LLAvatarIconCtrl::Params icon_params;
- icon_params.avatar_id = match_id;
- icon_params.rect = LLRect(0, 16, 16, 0);
- icon_params.visible = true;
- icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params);
- }
-
- LLInlineViewSegment::Params params;
- params.force_newline = false;
- params.view = icon;
- params.left_pad = 4;
- params.right_pad = 4;
- params.top_pad = -2;
- params.bottom_pad = 2;
-
- base->appendWidget(params," ",false);
-
- return true;
+ if(!match || !base || base->getPlainText())
+ return false;
+
+ LLUUID match_id = match->getID();
+
+ LLIconCtrl* icon;
+
+ if( match->getMenuName() == "menu_url_group.xml" // See LLUrlEntryGroup constructor
+ || gAgent.isInGroup(match_id, TRUE)) //This check seems unfiting, urls are either /agent or /group
+ {
+ LLGroupIconCtrl::Params icon_params;
+ icon_params.group_id = match_id;
+ icon_params.rect = LLRect(0, 16, 16, 0);
+ icon_params.visible = true;
+ icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params);
+ }
+ else
+ {
+ LLAvatarIconCtrl::Params icon_params;
+ icon_params.avatar_id = match_id;
+ icon_params.rect = LLRect(0, 16, 16, 0);
+ icon_params.visible = true;
+ icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params);
+ }
+
+ LLInlineViewSegment::Params params;
+ params.force_newline = false;
+ params.view = icon;
+ params.left_pad = 4;
+ params.right_pad = 4;
+ params.top_pad = -2;
+ params.bottom_pad = 2;
+
+ base->appendWidget(params," ",false);
+
+ return true;
}
// Use these strictly for things that are constructed at startup,
// or for things that are performance critical. JC
static void settings_to_globals()
{
- LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad");
- BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall");
- BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight");
+ LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad");
+ BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall");
+ BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight");
- MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
- MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
+ MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
+ MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
- LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
+ LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
#if LL_DARWIN
LLRender::sGLCoreProfile = true;
#else
LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLContextCoreProfile");
#endif
- LLRender::sNsightDebugSupport = gSavedSettings.getBOOL("RenderNsightDebugSupport");
- LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic");
- LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures");
- LLVOVolume::sLODFactor = llclamp(gSavedSettings.getF32("RenderVolumeLODFactor"), 0.01f, MAX_LOD_FACTOR);
- LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f;
- LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
- LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor");
- LLVOAvatar::sLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR);
- LLVOAvatar::sPhysicsLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarPhysicsLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR);
- LLVOAvatar::updateImpostorRendering(gSavedSettings.getU32("RenderAvatarMaxNonImpostors"));
- LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible");
- // clamp auto-open time to some minimum usable value
- LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
- LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive");
- LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
- LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
-
- gAgentPilot.setNumRuns(gSavedSettings.getS32("StatsNumRuns"));
- gAgentPilot.setQuitAfterRuns(gSavedSettings.getBOOL("StatsQuitAfterRuns"));
- gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
-
- gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
- gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
+ LLRender::sNsightDebugSupport = gSavedSettings.getBOOL("RenderNsightDebugSupport");
+ LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic");
+ LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures");
+ LLVOVolume::sLODFactor = llclamp(gSavedSettings.getF32("RenderVolumeLODFactor"), 0.01f, MAX_LOD_FACTOR);
+ LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f;
+ LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
+ LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor");
+ LLVOAvatar::sLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR);
+ LLVOAvatar::sPhysicsLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarPhysicsLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR);
+ LLVOAvatar::updateImpostorRendering(gSavedSettings.getU32("RenderAvatarMaxNonImpostors"));
+ LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible");
+ // clamp auto-open time to some minimum usable value
+ LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
+ LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive");
+ LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
+ LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
+
+ gAgentPilot.setNumRuns(gSavedSettings.getS32("StatsNumRuns"));
+ gAgentPilot.setQuitAfterRuns(gSavedSettings.getBOOL("StatsQuitAfterRuns"));
+ gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
+
+ gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
+ gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale"));
-
+
#if LL_DARWIN
LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL");
- gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI");
+ gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI");
#endif
}
@@ -584,41 +588,41 @@ static void settings_modify()
class LLFastTimerLogThread : public LLThread
{
public:
- std::string mFile;
-
- LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log")
- {
- std::string file_name = test_name + std::string(".slp");
- mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name);
- }
-
- void run()
- {
- llofstream os(mFile.c_str());
-
- while (!LLAppViewer::instance()->isQuitting())
- {
- LLTrace::BlockTimer::writeLog(os);
- os.flush();
- ms_sleep(32);
- }
-
- os.close();
- }
+ std::string mFile;
+
+ LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log")
+ {
+ std::string file_name = test_name + std::string(".slp");
+ mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name);
+ }
+
+ void run()
+ {
+ llofstream os(mFile.c_str());
+
+ while (!LLAppViewer::instance()->isQuitting())
+ {
+ LLTrace::BlockTimer::writeLog(os);
+ os.flush();
+ ms_sleep(32);
+ }
+
+ os.close();
+ }
};
//virtual
bool LLAppViewer::initSLURLHandler()
{
- // does nothing unless subclassed
- return false;
+ // does nothing unless subclassed
+ return false;
}
//virtual
bool LLAppViewer::sendURLToOtherInstance(const std::string& url)
{
- // does nothing unless subclassed
- return false;
+ // does nothing unless subclassed
+ return false;
}
//----------------------------------------------------------------------------
@@ -634,402 +638,402 @@ LLPurgeDiskCacheThread* LLAppViewer::sPurgeDiskCacheThread = NULL;
std::string getRuntime()
{
- return llformat("%.4f", (F32)LLTimer::getElapsedSeconds().value());
+ return llformat("%.4f", (F32)LLTimer::getElapsedSeconds().value());
}
LLAppViewer::LLAppViewer()
-: mMarkerFile(),
- mLogoutMarkerFile(),
- mReportedCrash(false),
- mNumSessions(0),
+: mMarkerFile(),
+ mLogoutMarkerFile(),
+ mReportedCrash(false),
+ mNumSessions(0),
mGeneralThreadPool(nullptr),
- mPurgeCache(false),
- mPurgeCacheOnExit(false),
- mPurgeUserDataOnExit(false),
- mSecondInstance(false),
- mUpdaterNotFound(false),
- mSavedFinalSnapshot(false),
- mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded.
- mQuitRequested(false),
- mLogoutRequestSent(false),
- mLastAgentControlFlags(0),
- mLastAgentForceUpdate(0),
- mMainloopTimeout(NULL),
- mAgentRegionLastAlive(false),
- mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
- mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
- mFastTimerLogThread(NULL),
- mSettingsLocationList(NULL),
- mIsFirstRun(false)
+ mPurgeCache(false),
+ mPurgeCacheOnExit(false),
+ mPurgeUserDataOnExit(false),
+ mSecondInstance(false),
+ mUpdaterNotFound(false),
+ mSavedFinalSnapshot(false),
+ mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded.
+ mQuitRequested(false),
+ mLogoutRequestSent(false),
+ mLastAgentControlFlags(0),
+ mLastAgentForceUpdate(0),
+ mMainloopTimeout(NULL),
+ mAgentRegionLastAlive(false),
+ mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
+ mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
+ mFastTimerLogThread(NULL),
+ mSettingsLocationList(NULL),
+ mIsFirstRun(false)
{
- if(NULL != sInstance)
- {
- LL_ERRS() << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << LL_ENDL;
- }
+ if(NULL != sInstance)
+ {
+ LL_ERRS() << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << LL_ENDL;
+ }
mDumpPath ="";
- // Need to do this initialization before we do anything else, since anything
- // that touches files should really go through the lldir API
- gDirUtilp->initAppDirs("SecondLife");
- //
- // IMPORTANT! Do NOT put anything that will write
- // into the log files during normal startup until AFTER
- // we run the "program crashed last time" error handler below.
- //
- sInstance = this;
-
- gLoggedInTime.stop();
-
- processMarkerFiles();
- //
- // OK to write stuff to logs now, we've now crash reported if necessary
- //
-
- LLLoginInstance::instance().setPlatformInfo(gPlatform, LLOSInfo::instance().getOSVersionString(), LLOSInfo::instance().getOSStringSimple());
-
- // Under some circumstances we want to read the static_debug_info.log file
- // from the previous viewer run between this constructor call and the
- // init() call, which will overwrite the static_debug_info.log file for
- // THIS run. So setDebugFileNames() early.
+ // Need to do this initialization before we do anything else, since anything
+ // that touches files should really go through the lldir API
+ gDirUtilp->initAppDirs("SecondLife");
+ //
+ // IMPORTANT! Do NOT put anything that will write
+ // into the log files during normal startup until AFTER
+ // we run the "program crashed last time" error handler below.
+ //
+ sInstance = this;
+
+ gLoggedInTime.stop();
+
+ processMarkerFiles();
+ //
+ // OK to write stuff to logs now, we've now crash reported if necessary
+ //
+
+ LLLoginInstance::instance().setPlatformInfo(gPlatform, LLOSInfo::instance().getOSVersionString(), LLOSInfo::instance().getOSStringSimple());
+
+ // Under some circumstances we want to read the static_debug_info.log file
+ // from the previous viewer run between this constructor call and the
+ // init() call, which will overwrite the static_debug_info.log file for
+ // THIS run. So setDebugFileNames() early.
# ifdef LL_BUGSPLAT
- // MAINT-8917: don't create a dump directory just for the
- // static_debug_info.log file
- std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
+ // MAINT-8917: don't create a dump directory just for the
+ // static_debug_info.log file
+ std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
# else // ! LL_BUGSPLAT
- // write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues.
- std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
+ // write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues.
+ std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
# endif // ! LL_BUGSPLAT
- mDumpPath = logdir;
+ mDumpPath = logdir;
- setDebugFileNames(logdir);
+ setDebugFileNames(logdir);
}
LLAppViewer::~LLAppViewer()
{
- delete mSettingsLocationList;
+ delete mSettingsLocationList;
- destroyMainloopTimeout();
+ destroyMainloopTimeout();
- // If we got to this destructor somehow, the app didn't hang.
- removeMarkerFiles();
+ // If we got to this destructor somehow, the app didn't hang.
+ removeMarkerFiles();
}
class LLUITranslationBridge : public LLTranslationBridge
{
public:
- virtual std::string getString(const std::string &xml_desc)
- {
- return LLTrans::getString(xml_desc);
- }
+ virtual std::string getString(const std::string &xml_desc)
+ {
+ return LLTrans::getString(xml_desc);
+ }
};
bool LLAppViewer::init()
{
- setupErrorHandling(mSecondInstance);
+ setupErrorHandling(mSecondInstance);
- //
- // Start of the application
- //
+ //
+ // Start of the application
+ //
// initialize the LLSettingsType translation bridge.
LLTranslationBridge::ptr_t trans = std::make_shared<LLUITranslationBridge>();
LLSettingsType::initParamSingleton(trans);
- // initialize SSE options
- LLVector4a::initClass();
+ // initialize SSE options
+ LLVector4a::initClass();
- //initialize particle index pool
- LLVOPartGroup::initClass();
+ //initialize particle index pool
+ LLVOPartGroup::initClass();
- // set skin search path to default, will be overridden later
- // this allows simple skinned file lookups to work
- gDirUtilp->setSkinFolder("default", "en");
+ // set skin search path to default, will be overridden later
+ // this allows simple skinned file lookups to work
+ gDirUtilp->setSkinFolder("default", "en");
-// initLoggingAndGetLastDuration();
+// initLoggingAndGetLastDuration();
- //
- // OK to write stuff to logs now, we've now crash reported if necessary
- //
- init_default_trans_args();
+ //
+ // OK to write stuff to logs now, we've now crash reported if necessary
+ //
+ init_default_trans_args();
// inits from settings.xml and from strings.xml
- if (!initConfiguration())
- return false;
+ if (!initConfiguration())
+ return false;
- LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ;
+ LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ;
- //set the max heap size.
- initMaxHeapSize() ;
- LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
+ //set the max heap size.
+ initMaxHeapSize() ;
+ LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
- // Although initLoggingAndGetLastDuration() is the right place to mess with
- // setFatalFunction(), we can't query gSavedSettings until after
- // initConfiguration().
- S32 rc(gSavedSettings.getS32("QAModeTermCode"));
- if (rc >= 0)
- {
- // QAModeTermCode set, terminate with that rc on LL_ERRS. Use
- // _exit() rather than exit() because normal cleanup depends too
- // much on successful startup!
- LLError::setFatalFunction([rc](const std::string&){ _exit(rc); });
- }
+ // Although initLoggingAndGetLastDuration() is the right place to mess with
+ // setFatalFunction(), we can't query gSavedSettings until after
+ // initConfiguration().
+ S32 rc(gSavedSettings.getS32("QAModeTermCode"));
+ if (rc >= 0)
+ {
+ // QAModeTermCode set, terminate with that rc on LL_ERRS. Use
+ // _exit() rather than exit() because normal cleanup depends too
+ // much on successful startup!
+ LLError::setFatalFunction([rc](const std::string&){ _exit(rc); });
+ }
mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
- // Initialize the non-LLCurl libcurl library. Should be called
- // before consumers (LLTextureFetch).
- mAppCoreHttp.init();
+ // Initialize the non-LLCurl libcurl library. Should be called
+ // before consumers (LLTextureFetch).
+ mAppCoreHttp.init();
- LL_INFOS("InitInfo") << "LLCore::Http initialized." << LL_ENDL ;
+ LL_INFOS("InitInfo") << "LLCore::Http initialized." << LL_ENDL ;
LLMachineID::init();
- {
- if (gSavedSettings.getBOOL("QAModeMetrics"))
- {
- app_metrics_qa_mode = true;
- app_metrics_interval = METRICS_INTERVAL_QA;
- }
- LLViewerAssetStatsFF::init();
- }
-
- initThreads();
- LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ;
-
- // Initialize settings early so that the defaults for ignorable dialogs are
- // picked up and then correctly re-saved after launching the updater (STORM-1268).
- LLUI::settings_map_t settings_map;
- settings_map["config"] = &gSavedSettings;
- settings_map["ignores"] = &gWarningSettings;
- settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
- settings_map["account"] = &gSavedPerAccountSettings;
-
- LLUI::initParamSingleton(settings_map,
- LLUIImageList::getInstance(),
- ui_audio_callback,
- deferred_ui_audio_callback);
- LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ;
-
- // NOW LLUI::getLanguage() should work. gDirUtilp must know the language
- // for this session ASAP so all the file-loading commands that follow,
- // that use findSkinnedFilenames(), will include the localized files.
- gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), LLUI::getLanguage());
-
- // Setup LLTrans after LLUI::initClass has been called.
- initStrings();
+ {
+ if (gSavedSettings.getBOOL("QAModeMetrics"))
+ {
+ app_metrics_qa_mode = true;
+ app_metrics_interval = METRICS_INTERVAL_QA;
+ }
+ LLViewerAssetStatsFF::init();
+ }
+
+ initThreads();
+ LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ;
+
+ // Initialize settings early so that the defaults for ignorable dialogs are
+ // picked up and then correctly re-saved after launching the updater (STORM-1268).
+ LLUI::settings_map_t settings_map;
+ settings_map["config"] = &gSavedSettings;
+ settings_map["ignores"] = &gWarningSettings;
+ settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
+ settings_map["account"] = &gSavedPerAccountSettings;
+
+ LLUI::initParamSingleton(settings_map,
+ LLUIImageList::getInstance(),
+ ui_audio_callback,
+ deferred_ui_audio_callback);
+ LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ;
+
+ // NOW LLUI::getLanguage() should work. gDirUtilp must know the language
+ // for this session ASAP so all the file-loading commands that follow,
+ // that use findSkinnedFilenames(), will include the localized files.
+ gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), LLUI::getLanguage());
+
+ // Setup LLTrans after LLUI::initClass has been called.
+ initStrings();
// initialize LLWearableType translation bridge.
// Will immediately use LLTranslationBridge to init LLWearableDictionary
LLWearableType::initParamSingleton(trans);
- // Setup notifications after LLUI::initClass() has been called.
- LLNotifications::instance();
- LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ;
+ // Setup notifications after LLUI::initClass() has been called.
+ LLNotifications::instance();
+ LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ;
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // *FIX: The following code isn't grouped into functions yet.
+ //////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////
+ // *FIX: The following code isn't grouped into functions yet.
- //
- // Various introspection concerning the libs we're using - particularly
- // the libs involved in getting to a full login screen.
- //
- LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
- LL_INFOS("InitInfo") << "libcurl version is: " << LLCore::LLHttp::getCURLVersion() << LL_ENDL;
+ //
+ // Various introspection concerning the libs we're using - particularly
+ // the libs involved in getting to a full login screen.
+ //
+ LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
+ LL_INFOS("InitInfo") << "libcurl version is: " << LLCore::LLHttp::getCURLVersion() << LL_ENDL;
- /////////////////////////////////////////////////
- // OS-specific login dialogs
- /////////////////////////////////////////////////
+ /////////////////////////////////////////////////
+ // OS-specific login dialogs
+ /////////////////////////////////////////////////
- //test_cached_control();
+ //test_cached_control();
- // track number of times that app has run
- mNumSessions = gSavedSettings.getS32("NumSessions");
- mNumSessions++;
- gSavedSettings.setS32("NumSessions", mNumSessions);
+ // track number of times that app has run
+ mNumSessions = gSavedSettings.getS32("NumSessions");
+ mNumSessions++;
+ gSavedSettings.setS32("NumSessions", mNumSessions);
- // LLKeyboard relies on LLUI to know what some accelerator keys are called.
- LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
+ // LLKeyboard relies on LLUI to know what some accelerator keys are called.
+ LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
- // Provide the text fields with callbacks for opening Urls
- LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null));
- LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false));
- LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));
- LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
+ // Provide the text fields with callbacks for opening Urls
+ LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null));
+ LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false));
+ LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));
+ LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
- // Let code in llui access the viewer help floater
- LLUI::getInstance()->mHelpImpl = LLViewerHelp::getInstance();
+ // Let code in llui access the viewer help floater
+ LLUI::getInstance()->mHelpImpl = LLViewerHelp::getInstance();
- LL_INFOS("InitInfo") << "UI initialization is done." << LL_ENDL ;
+ LL_INFOS("InitInfo") << "UI initialization is done." << LL_ENDL ;
- // Load translations for tooltips
- LLFloater::initClass();
- LLUrlFloaterDispatchHandler::registerInDispatcher();
+ // Load translations for tooltips
+ LLFloater::initClass();
+ LLUrlFloaterDispatchHandler::registerInDispatcher();
- /////////////////////////////////////////////////
+ /////////////////////////////////////////////////
- LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
+ LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
- LLViewerFloaterReg::registerFloaters();
+ LLViewerFloaterReg::registerFloaters();
- /////////////////////////////////////////////////
- //
- // Load settings files
- //
- //
- LLGroupMgr::parseRoleActions("role_actions.xml");
+ /////////////////////////////////////////////////
+ //
+ // Load settings files
+ //
+ //
+ LLGroupMgr::parseRoleActions("role_actions.xml");
- LLAgent::parseTeleportMessages("teleport_strings.xml");
+ LLAgent::parseTeleportMessages("teleport_strings.xml");
- // load MIME type -> media impl mappings
- std::string mime_types_name;
+ // load MIME type -> media impl mappings
+ std::string mime_types_name;
#if LL_DARWIN
- mime_types_name = "mime_types_mac.xml";
+ mime_types_name = "mime_types_mac.xml";
#elif LL_LINUX
- mime_types_name = "mime_types_linux.xml";
+ mime_types_name = "mime_types_linux.xml";
#else
- mime_types_name = "mime_types.xml";
+ mime_types_name = "mime_types.xml";
#endif
- LLMIMETypes::parseMIMETypes( mime_types_name );
-
- // Copy settings to globals. *TODO: Remove or move to appropriage class initializers
- settings_to_globals();
- // Setup settings listeners
- settings_setup_listeners();
- // Modify settings based on system configuration and compile options
- settings_modify();
-
- // Find partition serial number (Windows) or hardware serial (Mac)
- mSerialNumber = generateSerialNumber();
-
- // do any necessary set-up for accepting incoming SLURLs from apps
- initSLURLHandler();
-
- if(false == initHardwareTest())
- {
- // Early out from user choice.
- return false;
- }
- LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ;
-
- // Prepare for out-of-memory situations, during which we will crash on
- // purpose and save a dump.
+ LLMIMETypes::parseMIMETypes( mime_types_name );
+
+ // Copy settings to globals. *TODO: Remove or move to appropriage class initializers
+ settings_to_globals();
+ // Setup settings listeners
+ settings_setup_listeners();
+ // Modify settings based on system configuration and compile options
+ settings_modify();
+
+ // Find partition serial number (Windows) or hardware serial (Mac)
+ mSerialNumber = generateSerialNumber();
+
+ // do any necessary set-up for accepting incoming SLURLs from apps
+ initSLURLHandler();
+
+ if(false == initHardwareTest())
+ {
+ // Early out from user choice.
+ return false;
+ }
+ LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ;
+
+ // Prepare for out-of-memory situations, during which we will crash on
+ // purpose and save a dump.
#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
- MemSetErrorHandler(first_mem_error_handler);
+ MemSetErrorHandler(first_mem_error_handler);
#endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
- // *Note: this is where gViewerStats used to be created.
+ // *Note: this is where gViewerStats used to be created.
- if (!initCache())
- {
- LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL;
- std::ostringstream msg;
- msg << LLTrans::getString("MBUnableToAccessFile");
- OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
- return 0;
- }
- LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ;
+ if (!initCache())
+ {
+ LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL;
+ std::ostringstream msg;
+ msg << LLTrans::getString("MBUnableToAccessFile");
+ OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
+ return 0;
+ }
+ LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ;
// Initialize event recorder
LLViewerEventRecorder::createInstance();
- //
- // Initialize the window
- //
- gGLActive = TRUE;
- initWindow();
- LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ;
+ //
+ // Initialize the window
+ //
+ gGLActive = TRUE;
+ initWindow();
+ LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ;
// writeSystemInfo can be called after window is initialized (gViewerWindow non-null)
writeSystemInfo();
- // initWindow also initializes the Feature List, so now we can initialize this global.
- LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
+ // initWindow also initializes the Feature List, so now we can initialize this global.
+ LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
- // call all self-registered classes
- LLInitClassList::instance().fireCallbacks();
+ // call all self-registered classes
+ LLInitClassList::instance().fireCallbacks();
- LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts
+ LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts
- gGLManager.getGLInfo(gDebugInfo);
- gGLManager.printGLInfoString();
+ gGLManager.getGLInfo(gDebugInfo);
+ gGLManager.printGLInfoString();
- // If we don't have the right GL requirements, exit.
- if (!gGLManager.mHasRequirements)
- {
+ // If we don't have the right GL requirements, exit.
+ if (!gGLManager.mHasRequirements)
+ {
// already handled with a MBVideoDrvErr
- return 0;
- }
-
- // Without SSE2 support we will crash almost immediately, warn here.
- if (!gSysCPU.hasSSE2())
- {
- // can't use an alert here since we're exiting and
- // all hell breaks lose.
- OSMessageBox(
- LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"),
- LLStringUtil::null,
- OSMB_OK);
- return 0;
- }
-
- // alert the user if they are using unsupported hardware
- if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
- {
- bool unsupported = false;
- LLSD args;
- std::string minSpecs;
-
- // get cpu data from xml
- std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount"));
- S32 minCPU = 0;
- minCPUString >> minCPU;
-
- // get RAM data from XML
- std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount"));
- U64Bytes minRAM;
- minRAMString >> minRAM;
-
- if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
- {
- minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU");
- minSpecs += "\n";
- unsupported = true;
- }
- if(gSysCPU.getMHz() < minCPU)
- {
- minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
- minSpecs += "\n";
- unsupported = true;
- }
- if(gSysMemory.getPhysicalMemoryKB() < minRAM)
- {
- minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM");
- minSpecs += "\n";
- unsupported = true;
- }
-
- if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
- {
- LLNotificationsUtil::add("UnknownGPU");
- }
-
- if(unsupported)
- {
- if(!gSavedSettings.controlExists("WarnUnsupportedHardware")
- || gSavedSettings.getBOOL("WarnUnsupportedHardware"))
- {
- args["MINSPECS"] = minSpecs;
- LLNotificationsUtil::add("UnsupportedHardware", args );
- }
-
- }
- }
+ return 0;
+ }
+
+ // Without SSE2 support we will crash almost immediately, warn here.
+ if (!gSysCPU.hasSSE2())
+ {
+ // can't use an alert here since we're exiting and
+ // all hell breaks lose.
+ OSMessageBox(
+ LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"),
+ LLStringUtil::null,
+ OSMB_OK);
+ return 0;
+ }
+
+ // alert the user if they are using unsupported hardware
+ if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
+ {
+ bool unsupported = false;
+ LLSD args;
+ std::string minSpecs;
+
+ // get cpu data from xml
+ std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount"));
+ S32 minCPU = 0;
+ minCPUString >> minCPU;
+
+ // get RAM data from XML
+ std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount"));
+ U64Bytes minRAM;
+ minRAMString >> minRAM;
+
+ if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
+ {
+ minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU");
+ minSpecs += "\n";
+ unsupported = true;
+ }
+ if(gSysCPU.getMHz() < minCPU)
+ {
+ minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
+ minSpecs += "\n";
+ unsupported = true;
+ }
+ if(gSysMemory.getPhysicalMemoryKB() < minRAM)
+ {
+ minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM");
+ minSpecs += "\n";
+ unsupported = true;
+ }
+
+ if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
+ {
+ LLNotificationsUtil::add("UnknownGPU");
+ }
+
+ if(unsupported)
+ {
+ if(!gSavedSettings.controlExists("WarnUnsupportedHardware")
+ || gSavedSettings.getBOOL("WarnUnsupportedHardware"))
+ {
+ args["MINSPECS"] = minSpecs;
+ LLNotificationsUtil::add("UnsupportedHardware", args );
+ }
+
+ }
+ }
#if LL_WINDOWS && ADDRESS_SIZE == 64
if (gGLManager.mIsIntel)
@@ -1080,54 +1084,54 @@ bool LLAppViewer::init()
// Obsolete? mExpectedGLVersion is always zero
#if LL_WINDOWS
- if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion())
- {
- std::string url;
- if (gGLManager.mIsIntel)
- {
- url = LLTrans::getString("IntelDriverPage");
- }
- else if (gGLManager.mIsNVIDIA)
- {
- url = LLTrans::getString("NvidiaDriverPage");
- }
- else if (gGLManager.mIsAMD)
- {
- url = LLTrans::getString("AMDDriverPage");
- }
-
- if (!url.empty())
- {
- LLNotificationsUtil::add("OldGPUDriver", LLSD().with("URL", url));
- }
- }
+ if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion())
+ {
+ std::string url;
+ if (gGLManager.mIsIntel)
+ {
+ url = LLTrans::getString("IntelDriverPage");
+ }
+ else if (gGLManager.mIsNVIDIA)
+ {
+ url = LLTrans::getString("NvidiaDriverPage");
+ }
+ else if (gGLManager.mIsAMD)
+ {
+ url = LLTrans::getString("AMDDriverPage");
+ }
+
+ if (!url.empty())
+ {
+ LLNotificationsUtil::add("OldGPUDriver", LLSD().with("URL", url));
+ }
+ }
#endif
- // save the graphics card
- gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
+ // save the graphics card
+ gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
- // Save the current version to the prefs file
- gSavedSettings.setString("LastRunVersion",
- LLVersionInfo::instance().getChannelAndVersion());
+ // Save the current version to the prefs file
+ gSavedSettings.setString("LastRunVersion",
+ LLVersionInfo::instance().getChannelAndVersion());
- gSimLastTime = gRenderStartTime.getElapsedTimeF32();
- gSimFrames = (F32)gFrameCount;
+ gSimLastTime = gRenderStartTime.getElapsedTimeF32();
+ gSimFrames = (F32)gFrameCount;
if (gSavedSettings.getBOOL("JoystickEnabled"))
{
LLViewerJoystick::getInstance()->init(false);
}
- try {
- initializeSecHandler();
- }
- catch (LLProtectedDataException&)
- {
- LLNotificationsUtil::add("CorruptedProtectedDataStore");
- }
+ try {
+ initializeSecHandler();
+ }
+ catch (LLProtectedDataException&)
+ {
+ LLNotificationsUtil::add("CorruptedProtectedDataStore");
+ }
- gGLActive = FALSE;
+ gGLActive = FALSE;
#if LL_RELEASE_FOR_DOWNLOAD
// Skip updater if this is a non-interactive instance
@@ -1192,22 +1196,10 @@ bool LLAppViewer::init()
}
#endif //LL_RELEASE_FOR_DOWNLOAD
- {
- // Iterate over --leap command-line options. But this is a bit tricky: if
- // there's only one, it won't be an array at all.
- LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand"));
- LL_DEBUGS("InitInfo") << "LeapCommand: " << LeapCommand << LL_ENDL;
- if (LeapCommand.isDefined() && !LeapCommand.isArray())
- {
- // If LeapCommand is actually a scalar value, make an array of it.
- // Have to do it in two steps because LeapCommand.append(LeapCommand)
- // trashes content! :-P
- LLSD item(LeapCommand);
- LeapCommand.append(item);
- }
- for (const auto& leap : llsd::inArray(LeapCommand))
+ processComposeSwitch(
+ "--leap", "LeapCommand",
+ [](const LLSD& leap)
{
- LL_INFOS("InitInfo") << "processing --leap \"" << leap << '"' << LL_ENDL;
// We don't have any better description of this plugin than the
// user-specified command line. Passing "" causes LLLeap to derive a
// description from the command line itself.
@@ -1215,8 +1207,21 @@ bool LLAppViewer::init()
// don't consider any one --leap command mission-critical, so if one
// fails, log it, shrug and carry on.
LLLeap::create("", leap, false); // exception=false
- }
- }
+ });
+ processComposeSwitch(
+ "--lua", "LuaChunk",
+ [](const LLSD& chunk)
+ {
+ // no completion callback: we don't need to know
+ LLLUAmanager::runScriptLine(chunk);
+ });
+ processComposeSwitch(
+ "--luafile", "LuaScript",
+ [](const LLSD& script)
+ {
+ // no completion callback: we don't need to know
+ LLLUAmanager::runScriptFile(script);
+ });
if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
{
@@ -1225,25 +1230,25 @@ bool LLAppViewer::init()
<< LL_ENDL;
}
- LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
+ LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
- //EXT-7013 - On windows for some locale (Japanese) standard
- //datetime formatting functions didn't support some parameters such as "weekday".
- //Names for days and months localized in xml are also useful for Polish locale(STORM-107).
- std::string language = gSavedSettings.getString("Language");
- if(language == "ja" || language == "pl")
- {
- LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
- LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
- LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
- LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
- LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
-
- LLStringOps::sAM = LLTrans::getString("dateTimeAM");
- LLStringOps::sPM = LLTrans::getString("dateTimePM");
- }
+ //EXT-7013 - On windows for some locale (Japanese) standard
+ //datetime formatting functions didn't support some parameters such as "weekday".
+ //Names for days and months localized in xml are also useful for Polish locale(STORM-107).
+ std::string language = gSavedSettings.getString("Language");
+ if(language == "ja" || language == "pl")
+ {
+ LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
+ LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
+ LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
+ LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
+ LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
- LLAgentLanguage::init();
+ LLStringOps::sAM = LLTrans::getString("dateTimeAM");
+ LLStringOps::sPM = LLTrans::getString("dateTimePM");
+ }
+
+ LLAgentLanguage::init();
/// Tell the Coprocedure manager how to discover and store the pool sizes
// what I wanted
@@ -1251,27 +1256,27 @@ bool LLAppViewer::init()
boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1),
boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS));
- // TODO: consider moving proxy initialization here or LLCopocedureManager after proxy initialization, may be implement
- // some other protection to make sure we don't use network before initializng proxy
+ // TODO: consider moving proxy initialization here or LLCopocedureManager after proxy initialization, may be implement
+ // some other protection to make sure we don't use network before initializng proxy
- /*----------------------------------------------------------------------*/
- // nat 2016-06-29 moved the following here from the former mainLoop().
- mMainloopTimeout = new LLWatchdogTimeout();
+ /*----------------------------------------------------------------------*/
+ // nat 2016-06-29 moved the following here from the former mainLoop().
+ mMainloopTimeout = new LLWatchdogTimeout();
- // Create IO Pump to use for HTTP Requests.
- gServicePump = new LLPumpIO(gAPRPoolp);
+ // Create IO Pump to use for HTTP Requests.
+ gServicePump = new LLPumpIO(gAPRPoolp);
- // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
+ // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
- LLVoiceChannel::initClass();
- LLVoiceClient::initParamSingleton(gServicePump);
- LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
+ LLVoiceChannel::initClass();
+ LLVoiceClient::initParamSingleton(gServicePump);
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
- joystick = LLViewerJoystick::getInstance();
- joystick->setNeedsReset(true);
- /*----------------------------------------------------------------------*/
- // Load User's bindings
- loadKeyBindings();
+ joystick = LLViewerJoystick::getInstance();
+ joystick->setNeedsReset(true);
+ /*----------------------------------------------------------------------*/
+ // Load User's bindings
+ loadKeyBindings();
//LLSimpleton creations
LLEnvironment::createInstance();
@@ -1286,23 +1291,44 @@ bool LLAppViewer::init()
}
#endif
- return true;
+ return true;
+}
+
+void processComposeSwitch(const std::string& option,
+ const std::string& setting,
+ const std::function<void(const LLSD&)>& action)
+{
+ // Iterate over 'option' command-line options. But this is a bit tricky:
+ // if there's only one, it won't be an array at all.
+ LLSD args(gSavedSettings.getLLSD(setting));
+ LL_DEBUGS("InitInfo") << option << ": " << args << LL_ENDL;
+ if (args.isDefined() && ! args.isArray())
+ {
+ // If args is actually a scalar value, make an array of it. Have to do
+ // it in two steps because args.append(args) trashes content! :-P
+ args.append(LLSD(args));
+ }
+ for (const auto& arg : llsd::inArray(args))
+ {
+ LL_INFOS("InitInfo") << "processing " << option << ' ' << arg << LL_ENDL;
+ action(arg);
+ }
}
void LLAppViewer::initMaxHeapSize()
{
- //set the max heap size.
- //here is some info regarding to the max heap size:
- //------------------------------------------------------------------------------------------
- // OS | setting | SL address bits | max manageable memory space | max heap size
- // Win 32 | default | 32-bit | 2GB | < 1.7GB
- // Win 32 | /3G | 32-bit | 3GB | < 1.7GB or 2.7GB
- //Linux 32 | default | 32-bit | 3GB | < 2.7GB
- //Linux 32 |HUGEMEM | 32-bit | 4GB | < 3.7GB
- //64-bit OS |default | 32-bit | 4GB | < 3.7GB
- //64-bit OS |default | 64-bit | N/A (> 4GB) | N/A (> 4GB)
- //------------------------------------------------------------------------------------------
- //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
+ //set the max heap size.
+ //here is some info regarding to the max heap size:
+ //------------------------------------------------------------------------------------------
+ // OS | setting | SL address bits | max manageable memory space | max heap size
+ // Win 32 | default | 32-bit | 2GB | < 1.7GB
+ // Win 32 | /3G | 32-bit | 3GB | < 1.7GB or 2.7GB
+ //Linux 32 | default | 32-bit | 3GB | < 2.7GB
+ //Linux 32 |HUGEMEM | 32-bit | 4GB | < 3.7GB
+ //64-bit OS |default | 32-bit | 4GB | < 3.7GB
+ //64-bit OS |default | 64-bit | N/A (> 4GB) | N/A (> 4GB)
+ //------------------------------------------------------------------------------------------
+ //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
#ifndef LL_X86_64
F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ;
@@ -1319,42 +1345,42 @@ LLTrace::BlockTimerStatHandle FTM_FRAME("Frame");
bool LLAppViewer::frame()
{
- bool ret = false;
-
- if (gSimulateMemLeak)
- {
- try
- {
- ret = doFrame();
- }
- catch (const LLContinueError&)
- {
- LOG_UNHANDLED_EXCEPTION("");
- }
- catch (std::bad_alloc&)
- {
- LLMemory::logMemoryInfo(TRUE);
- LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
- if (mem_leak_instance)
- {
- mem_leak_instance->stop();
- }
- LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL;
- }
- }
- else
- {
- try
- {
- ret = doFrame();
- }
- catch (const LLContinueError&)
- {
- LOG_UNHANDLED_EXCEPTION("");
- }
- }
-
- return ret;
+ bool ret = false;
+
+ if (gSimulateMemLeak)
+ {
+ try
+ {
+ ret = doFrame();
+ }
+ catch (const LLContinueError&)
+ {
+ LOG_UNHANDLED_EXCEPTION("");
+ }
+ catch (std::bad_alloc&)
+ {
+ LLMemory::logMemoryInfo(TRUE);
+ LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if (mem_leak_instance)
+ {
+ mem_leak_instance->stop();
+ }
+ LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL;
+ }
+ }
+ else
+ {
+ try
+ {
+ ret = doFrame();
+ }
+ catch (const LLContinueError&)
+ {
+ LOG_UNHANDLED_EXCEPTION("");
+ }
+ }
+
+ return ret;
}
bool LLAppViewer::doFrame()
@@ -1447,63 +1473,63 @@ bool LLAppViewer::doFrame()
}
}
- if (!LLApp::isExiting())
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df JoystickKeyboard" )
- pingMainloopTimeout("Main:JoystickKeyboard");
-
- // Scan keyboard for movement keys. Command keys and typing
- // are handled by windows callbacks. Don't do this until we're
- // done initializing. JC
- if (gViewerWindow
- && (gHeadlessClient || gViewerWindow->getWindow()->getVisible())
- && gViewerWindow->getActive()
- && !gViewerWindow->getWindow()->getMinimized()
- && LLStartUp::getStartupState() == STATE_STARTED
- && (gHeadlessClient || !gViewerWindow->getShowProgress())
- && !gFocusMgr.focusLocked())
- {
+ if (!LLApp::isExiting())
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df JoystickKeyboard" )
+ pingMainloopTimeout("Main:JoystickKeyboard");
+
+ // Scan keyboard for movement keys. Command keys and typing
+ // are handled by windows callbacks. Don't do this until we're
+ // done initializing. JC
+ if (gViewerWindow
+ && (gHeadlessClient || gViewerWindow->getWindow()->getVisible())
+ && gViewerWindow->getActive()
+ && !gViewerWindow->getWindow()->getMinimized()
+ && LLStartUp::getStartupState() == STATE_STARTED
+ && (gHeadlessClient || !gViewerWindow->getShowProgress())
+ && !gFocusMgr.focusLocked())
+ {
LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE);
- joystick->scanJoystick();
- gKeyboard->scanKeyboard();
+ joystick->scanJoystick();
+ gKeyboard->scanKeyboard();
gViewerInput.scanMouse();
- }
+ }
- // Update state based on messages, user input, object idle.
- {
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df pauseMainloopTimeout" )
- pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
- }
+ // Update state based on messages, user input, object idle.
+ {
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df pauseMainloopTimeout" )
+ pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
+ }
- {
+ {
LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE);
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df idle");
- idle();
- }
+ idle();
+ }
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" )
- resumeMainloopTimeout();
- }
- }
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" )
+ resumeMainloopTimeout();
+ }
+ }
- if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
- {
- pauseMainloopTimeout();
- saveFinalSnapshot();
+ if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
+ {
+ pauseMainloopTimeout();
+ saveFinalSnapshot();
if (LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->terminate();
}
- disconnectViewer();
- resumeMainloopTimeout();
- }
+ disconnectViewer();
+ resumeMainloopTimeout();
+ }
- // Render scene.
- // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
+ // Render scene.
+ // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Display");
@@ -1527,159 +1553,159 @@ bool LLAppViewer::doFrame()
LLViewerStatsRecorder::instance().idle();
}
}
- }
+ }
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df pauseMainloopTimeout" )
- pingMainloopTimeout("Main:Sleep");
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df pauseMainloopTimeout" )
+ pingMainloopTimeout("Main:Sleep");
- pauseMainloopTimeout();
- }
+ pauseMainloopTimeout();
+ }
- // Sleep and run background threads
- {
- //LL_RECORD_BLOCK_TIME(SLEEP2);
- LL_PROFILE_ZONE_WARN( "Sleep2" )
+ // Sleep and run background threads
+ {
+ //LL_RECORD_BLOCK_TIME(SLEEP2);
+ LL_PROFILE_ZONE_WARN( "Sleep2" )
- // yield some time to the os based on command line option
- static LLCachedControl<S32> yield_time(gSavedSettings, "YieldTime", -1);
- if(yield_time >= 0)
- {
+ // yield some time to the os based on command line option
+ static LLCachedControl<S32> yield_time(gSavedSettings, "YieldTime", -1);
+ if(yield_time >= 0)
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Yield");
- LL_PROFILE_ZONE_NUM( yield_time )
- ms_sleep(yield_time);
- }
-
- if (gNonInteractive)
- {
- S32 non_interactive_ms_sleep_time = 100;
- LLAppViewer::getTextureCache()->pause();
- ms_sleep(non_interactive_ms_sleep_time);
- }
-
- // yield cooperatively when not running as foreground window
- // and when not quiting (causes trouble at mac's cleanup stage)
- if (!LLApp::isExiting()
- && ((gViewerWindow && !gViewerWindow->getWindow()->getVisible())
- || !gFocusMgr.getAppHasFocus()))
- {
- // Sleep if we're not rendering, or the window is minimized.
- static LLCachedControl<S32> s_background_yield_time(gSavedSettings, "BackgroundYieldTime", 40);
- S32 milliseconds_to_sleep = llclamp((S32)s_background_yield_time, 0, 1000);
- // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
- // of equal priority on Windows
- if (milliseconds_to_sleep > 0)
- {
+ LL_PROFILE_ZONE_NUM( yield_time )
+ ms_sleep(yield_time);
+ }
+
+ if (gNonInteractive)
+ {
+ S32 non_interactive_ms_sleep_time = 100;
+ LLAppViewer::getTextureCache()->pause();
+ ms_sleep(non_interactive_ms_sleep_time);
+ }
+
+ // yield cooperatively when not running as foreground window
+ // and when not quiting (causes trouble at mac's cleanup stage)
+ if (!LLApp::isExiting()
+ && ((gViewerWindow && !gViewerWindow->getWindow()->getVisible())
+ || !gFocusMgr.getAppHasFocus()))
+ {
+ // Sleep if we're not rendering, or the window is minimized.
+ static LLCachedControl<S32> s_background_yield_time(gSavedSettings, "BackgroundYieldTime", 40);
+ S32 milliseconds_to_sleep = llclamp((S32)s_background_yield_time, 0, 1000);
+ // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
+ // of equal priority on Windows
+ if (milliseconds_to_sleep > 0)
+ {
LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_SLEEP );
ms_sleep(milliseconds_to_sleep);
- // also pause worker threads during this wait period
- LLAppViewer::getTextureCache()->pause();
- }
- }
-
- if (mRandomizeFramerate)
- {
- ms_sleep(rand() % 200);
- }
-
- if (mPeriodicSlowFrame
- && (gFrameCount % 10 == 0))
- {
- LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL;
- ms_sleep(500);
- }
-
- S32 total_work_pending = 0;
- S32 total_io_pending = 0;
- {
- S32 work_pending = 0;
- S32 io_pending = 0;
- F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
-
- work_pending += updateTextureThreads(max_time);
-
- {
+ // also pause worker threads during this wait period
+ LLAppViewer::getTextureCache()->pause();
+ }
+ }
+
+ if (mRandomizeFramerate)
+ {
+ ms_sleep(rand() % 200);
+ }
+
+ if (mPeriodicSlowFrame
+ && (gFrameCount % 10 == 0))
+ {
+ LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL;
+ ms_sleep(500);
+ }
+
+ S32 total_work_pending = 0;
+ S32 total_io_pending = 0;
+ {
+ S32 work_pending = 0;
+ S32 io_pending = 0;
+ F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f);
+
+ work_pending += updateTextureThreads(max_time);
+
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("LFS Thread");
- io_pending += LLLFSThread::updateClass(1);
- }
-
- if (io_pending > 1000)
- {
- ms_sleep(llmin(io_pending/100,100)); // give the lfs some time to catch up
- }
-
- total_work_pending += work_pending ;
- total_io_pending += io_pending ;
-
- }
-
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df gMeshRepo" )
- gMeshRepo.update() ;
- }
-
- if(!total_work_pending) //pause texture fetching threads if nothing to process.
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df getTextureCache" )
- LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getTextureFetch()->pause();
- }
- if(!total_io_pending) //pause file threads if nothing to process.
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df LLVFSThread" )
- LLLFSThread::sLocal->pause();
- }
-
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" )
- resumeMainloopTimeout();
- }
- pingMainloopTimeout("Main:End");
- }
- }
-
- if (LLApp::isExiting())
- {
- // Save snapshot for next time, if we made it through initialization
- if (STATE_STARTED == LLStartUp::getStartupState())
- {
- saveFinalSnapshot();
- }
-
- if (LLVoiceClient::instanceExists())
- {
- LLVoiceClient::getInstance()->terminate();
- }
-
- delete gServicePump;
- gServicePump = NULL;
-
- destroyMainloopTimeout();
-
- LL_INFOS() << "Exiting main_loop" << LL_ENDL;
- }
+ io_pending += LLLFSThread::updateClass(1);
+ }
+
+ if (io_pending > 1000)
+ {
+ ms_sleep(llmin(io_pending/100,100)); // give the lfs some time to catch up
+ }
+
+ total_work_pending += work_pending ;
+ total_io_pending += io_pending ;
+
+ }
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df gMeshRepo" )
+ gMeshRepo.update() ;
+ }
+
+ if(!total_work_pending) //pause texture fetching threads if nothing to process.
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df getTextureCache" )
+ LLAppViewer::getTextureCache()->pause();
+ LLAppViewer::getTextureFetch()->pause();
+ }
+ if(!total_io_pending) //pause file threads if nothing to process.
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df LLVFSThread" )
+ LLLFSThread::sLocal->pause();
+ }
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" )
+ resumeMainloopTimeout();
+ }
+ pingMainloopTimeout("Main:End");
+ }
+ }
+
+ if (LLApp::isExiting())
+ {
+ // Save snapshot for next time, if we made it through initialization
+ if (STATE_STARTED == LLStartUp::getStartupState())
+ {
+ saveFinalSnapshot();
+ }
+
+ if (LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->terminate();
+ }
+
+ delete gServicePump;
+ gServicePump = NULL;
+
+ destroyMainloopTimeout();
+
+ LL_INFOS() << "Exiting main_loop" << LL_ENDL;
+ }
}LLPerfStats::StatsRecorder::endFrame();
LL_PROFILER_FRAME_END
- return ! LLApp::isRunning();
+ return ! LLApp::isRunning();
}
S32 LLAppViewer::updateTextureThreads(F32 max_time)
{
- S32 work_pending = 0;
- {
+ S32 work_pending = 0;
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Texture Cache");
- work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
- }
- {
+ work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
+ }
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Image Decode");
- work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
- }
- {
+ work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
+ }
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Image Fetch");
- work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
- }
- return work_pending;
+ work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
+ }
+ return work_pending;
}
void LLAppViewer::flushLFSIO()
@@ -1704,200 +1730,200 @@ bool LLAppViewer::cleanup()
{
LLAtmosphere::cleanupClass();
- //ditch LLVOAvatarSelf instance
- gAgentAvatarp = NULL;
+ //ditch LLVOAvatarSelf instance
+ gAgentAvatarp = NULL;
LLNotifications::instance().clear();
- // workaround for DEV-35406 crash on shutdown
- LLEventPumps::instance().reset(true);
+ // workaround for DEV-35406 crash on shutdown
+ LLEventPumps::instance().reset(true);
- //dump scene loading monitor results
- if (LLSceneMonitor::instanceExists())
- {
- if (!isSecondInstance())
- {
+ //dump scene loading monitor results
+ if (LLSceneMonitor::instanceExists())
+ {
+ if (!isSecondInstance())
+ {
std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv");
- LLSceneMonitor::instance().dumpToFile(dump_path);
- }
- LLSceneMonitor::deleteSingleton();
- }
-
- // There used to be an 'if (LLFastTimerView::sAnalyzePerformance)' block
- // here, completely redundant with the one that occurs later in this same
- // function. Presumably the duplication was due to an automated merge gone
- // bad. Not knowing which instance to prefer, we chose to retain the later
- // one because it happens just after mFastTimerLogThread is deleted. This
- // comment is in case we guessed wrong, so we can move it here instead.
+ LLSceneMonitor::instance().dumpToFile(dump_path);
+ }
+ LLSceneMonitor::deleteSingleton();
+ }
+
+ // There used to be an 'if (LLFastTimerView::sAnalyzePerformance)' block
+ // here, completely redundant with the one that occurs later in this same
+ // function. Presumably the duplication was due to an automated merge gone
+ // bad. Not knowing which instance to prefer, we chose to retain the later
+ // one because it happens just after mFastTimerLogThread is deleted. This
+ // comment is in case we guessed wrong, so we can move it here instead.
#if LL_LINUX
- // remove any old breakpad minidump files from the log directory
- if (! isError())
- {
- std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
- gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");
- }
+ // remove any old breakpad minidump files from the log directory
+ if (! isError())
+ {
+ std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
+ gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");
+ }
#endif
- // Kill off LLLeap objects. We can find them all because LLLeap is derived
- // from LLInstanceTracker.
- LLLeap::instance_snapshot().deleteAll();
+ // Kill off LLLeap objects. We can find them all because LLLeap is derived
+ // from LLInstanceTracker.
+ LLLeap::instance_snapshot().deleteAll();
- //flag all elements as needing to be destroyed immediately
- // to ensure shutdown order
- LLMortician::setZealous(TRUE);
+ //flag all elements as needing to be destroyed immediately
+ // to ensure shutdown order
+ LLMortician::setZealous(TRUE);
// Give any remaining SLPlugin instances a chance to exit cleanly.
LLPluginProcessParent::shutdown();
- disconnectViewer();
- LLViewerCamera::deleteSingleton();
+ disconnectViewer();
+ LLViewerCamera::deleteSingleton();
- LL_INFOS() << "Viewer disconnected" << LL_ENDL;
+ LL_INFOS() << "Viewer disconnected" << LL_ENDL;
+
+ if (gKeyboard)
+ {
+ gKeyboard->resetKeys();
+ }
- if (gKeyboard)
- {
- gKeyboard->resetKeys();
- }
+ display_cleanup();
- display_cleanup();
+ release_start_screen(); // just in case
- release_start_screen(); // just in case
+ LLError::logToFixedBuffer(NULL); // stop the fixed buffer recorder
- LLError::logToFixedBuffer(NULL); // stop the fixed buffer recorder
+ LL_INFOS() << "Cleaning Up" << LL_ENDL;
- LL_INFOS() << "Cleaning Up" << LL_ENDL;
+ // shut down mesh streamer
+ gMeshRepo.shutdown();
- // shut down mesh streamer
- gMeshRepo.shutdown();
+ // shut down Havok
+ LLPhysicsExtensions::quitSystem();
- // shut down Havok
- LLPhysicsExtensions::quitSystem();
+ // Must clean up texture references before viewer window is destroyed.
+ if(LLHUDManager::instanceExists())
+ {
+ LLHUDManager::getInstance()->updateEffects();
+ LLHUDObject::updateAll();
+ LLHUDManager::getInstance()->cleanupEffects();
+ LLHUDObject::cleanupHUDObjects();
+ LL_INFOS() << "HUD Objects cleaned up" << LL_ENDL;
+ }
- // Must clean up texture references before viewer window is destroyed.
- if(LLHUDManager::instanceExists())
- {
- LLHUDManager::getInstance()->updateEffects();
- LLHUDObject::updateAll();
- LLHUDManager::getInstance()->cleanupEffects();
- LLHUDObject::cleanupHUDObjects();
- LL_INFOS() << "HUD Objects cleaned up" << LL_ENDL;
- }
+ LLKeyframeDataCache::clear();
- LLKeyframeDataCache::clear();
-
- // End TransferManager before deleting systems it depends on (Audio, AssetStorage)
+ // End TransferManager before deleting systems it depends on (Audio, AssetStorage)
#if 0 // this seems to get us stuck in an infinite loop...
- gTransferManager.cleanup();
+ gTransferManager.cleanup();
#endif
- // Note: this is where gWorldMap used to be deleted.
+ // Note: this is where gWorldMap used to be deleted.
- // Note: this is where gHUDManager used to be deleted.
- if(LLHUDManager::instanceExists())
- {
- LLHUDManager::getInstance()->shutdownClass();
- }
+ // Note: this is where gHUDManager used to be deleted.
+ if(LLHUDManager::instanceExists())
+ {
+ LLHUDManager::getInstance()->shutdownClass();
+ }
- delete gAssetStorage;
- gAssetStorage = NULL;
+ delete gAssetStorage;
+ gAssetStorage = NULL;
- LLPolyMesh::freeAllMeshes();
+ LLPolyMesh::freeAllMeshes();
- LLStartUp::cleanupNameCache();
+ LLStartUp::cleanupNameCache();
- // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
+ // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
- if (LLWorldMap::instanceExists())
- {
- LLWorldMap::getInstance()->reset(); // release any images
- }
+ if (LLWorldMap::instanceExists())
+ {
+ LLWorldMap::getInstance()->reset(); // release any images
+ }
- LLCalc::cleanUp();
+ LLCalc::cleanUp();
- LL_INFOS() << "Global stuff deleted" << LL_ENDL;
+ LL_INFOS() << "Global stuff deleted" << LL_ENDL;
- if (gAudiop)
- {
+ if (gAudiop)
+ {
LL_INFOS() << "Shutting down audio" << LL_ENDL;
// be sure to stop the internet stream cleanly BEFORE destroying the interface to stop it.
gAudiop->stopInternetStream();
// shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
- delete sai;
- gAudiop->setStreamingAudioImpl(NULL);
+ delete sai;
+ gAudiop->setStreamingAudioImpl(NULL);
// shut down the audio subsystem
gAudiop->shutdown();
- delete gAudiop;
- gAudiop = NULL;
- }
+ delete gAudiop;
+ gAudiop = NULL;
+ }
- // Note: this is where LLFeatureManager::getInstance()-> used to be deleted.
+ // Note: this is where LLFeatureManager::getInstance()-> used to be deleted.
- // Patch up settings for next time
- // Must do this before we delete the viewer window,
- // such that we can suck rectangle information out of
- // it.
- cleanupSavedSettings();
- LL_INFOS() << "Settings patched up" << LL_ENDL;
+ // Patch up settings for next time
+ // Must do this before we delete the viewer window,
+ // such that we can suck rectangle information out of
+ // it.
+ cleanupSavedSettings();
+ LL_INFOS() << "Settings patched up" << LL_ENDL;
- // delete some of the files left around in the cache.
- removeCacheFiles("*.wav");
- removeCacheFiles("*.tmp");
- removeCacheFiles("*.lso");
- removeCacheFiles("*.out");
- removeCacheFiles("*.dsf");
- removeCacheFiles("*.bodypart");
- removeCacheFiles("*.clothing");
+ // delete some of the files left around in the cache.
+ removeCacheFiles("*.wav");
+ removeCacheFiles("*.tmp");
+ removeCacheFiles("*.lso");
+ removeCacheFiles("*.out");
+ removeCacheFiles("*.dsf");
+ removeCacheFiles("*.bodypart");
+ removeCacheFiles("*.clothing");
- LL_INFOS() << "Cache files removed" << LL_ENDL;
+ LL_INFOS() << "Cache files removed" << LL_ENDL;
- LL_INFOS() << "Shutting down Views" << LL_ENDL;
+ LL_INFOS() << "Shutting down Views" << LL_ENDL;
- // Destroy the UI
- if( gViewerWindow)
- gViewerWindow->shutdownViews();
+ // Destroy the UI
+ if( gViewerWindow)
+ gViewerWindow->shutdownViews();
- LL_INFOS() << "Cleaning up Inventory" << LL_ENDL;
+ LL_INFOS() << "Cleaning up Inventory" << LL_ENDL;
- // Cleanup Inventory after the UI since it will delete any remaining observers
- // (Deleted observers should have already removed themselves)
- gInventory.cleanupInventory();
+ // Cleanup Inventory after the UI since it will delete any remaining observers
+ // (Deleted observers should have already removed themselves)
+ gInventory.cleanupInventory();
- LLCoros::getInstance()->printActiveCoroutines();
+ LLCoros::getInstance()->printActiveCoroutines();
- LL_INFOS() << "Cleaning up Selections" << LL_ENDL;
+ LL_INFOS() << "Cleaning up Selections" << LL_ENDL;
- // Clean up selection managers after UI is destroyed, as UI may be observing them.
- // Clean up before GL is shut down because we might be holding on to objects with texture references
- LLSelectMgr::cleanupGlobals();
+ // Clean up selection managers after UI is destroyed, as UI may be observing them.
+ // Clean up before GL is shut down because we might be holding on to objects with texture references
+ LLSelectMgr::cleanupGlobals();
- LL_INFOS() << "Shutting down OpenGL" << LL_ENDL;
+ LL_INFOS() << "Shutting down OpenGL" << LL_ENDL;
- // Shut down OpenGL
- if( gViewerWindow)
- {
- gViewerWindow->shutdownGL();
-
- // Destroy window, and make sure we're not fullscreen
- // This may generate window reshape and activation events.
- // Therefore must do this before destroying the message system.
- delete gViewerWindow;
- gViewerWindow = NULL;
- LL_INFOS() << "ViewerWindow deleted" << LL_ENDL;
- }
+ // Shut down OpenGL
+ if( gViewerWindow)
+ {
+ gViewerWindow->shutdownGL();
+
+ // Destroy window, and make sure we're not fullscreen
+ // This may generate window reshape and activation events.
+ // Therefore must do this before destroying the message system.
+ delete gViewerWindow;
+ gViewerWindow = NULL;
+ LL_INFOS() << "ViewerWindow deleted" << LL_ENDL;
+ }
LLSplashScreen::show();
LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
- LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
+ LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
- // viewer UI relies on keyboard so keep it aound until viewer UI isa gone
- delete gKeyboard;
- gKeyboard = NULL;
+ // viewer UI relies on keyboard so keep it aound until viewer UI isa gone
+ delete gKeyboard;
+ gKeyboard = NULL;
if (LLViewerJoystick::instanceExists())
{
@@ -1905,142 +1931,142 @@ bool LLAppViewer::cleanup()
LLViewerJoystick::getInstance()->terminate();
}
- LL_INFOS() << "Cleaning up Objects" << LL_ENDL;
+ LL_INFOS() << "Cleaning up Objects" << LL_ENDL;
- LLViewerObject::cleanupVOClasses();
+ LLViewerObject::cleanupVOClasses();
- SUBSYSTEM_CLEANUP(LLAvatarAppearance);
+ SUBSYSTEM_CLEANUP(LLAvatarAppearance);
- SUBSYSTEM_CLEANUP(LLPostProcess);
+ SUBSYSTEM_CLEANUP(LLPostProcess);
- LLTracker::cleanupInstance();
+ LLTracker::cleanupInstance();
- // *FIX: This is handled in LLAppViewerWin32::cleanup().
- // I'm keeping the comment to remember its order in cleanup,
- // in case of unforseen dependency.
- //#if LL_WINDOWS
- // gDXHardware.cleanup();
- //#endif // LL_WINDOWS
+ // *FIX: This is handled in LLAppViewerWin32::cleanup().
+ // I'm keeping the comment to remember its order in cleanup,
+ // in case of unforseen dependency.
+ //#if LL_WINDOWS
+ // gDXHardware.cleanup();
+ //#endif // LL_WINDOWS
- LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager();
- if (!volume_manager->cleanup())
- {
- LL_WARNS() << "Remaining references in the volume manager!" << LL_ENDL;
- }
- LLPrimitive::cleanupVolumeManager();
+ LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager();
+ if (!volume_manager->cleanup())
+ {
+ LL_WARNS() << "Remaining references in the volume manager!" << LL_ENDL;
+ }
+ LLPrimitive::cleanupVolumeManager();
- LL_INFOS() << "Additional Cleanup..." << LL_ENDL;
+ LL_INFOS() << "Additional Cleanup..." << LL_ENDL;
- LLViewerParcelMgr::cleanupGlobals();
+ LLViewerParcelMgr::cleanupGlobals();
- // *Note: this is where gViewerStats used to be deleted.
+ // *Note: this is where gViewerStats used to be deleted.
- //end_messaging_system();
+ //end_messaging_system();
- LLPrimitive::cleanupVolumeManager();
- SUBSYSTEM_CLEANUP(LLWorldMapView);
- SUBSYSTEM_CLEANUP(LLFolderViewItem);
+ LLPrimitive::cleanupVolumeManager();
+ SUBSYSTEM_CLEANUP(LLWorldMapView);
+ SUBSYSTEM_CLEANUP(LLFolderViewItem);
- LL_INFOS() << "Saving Data" << LL_ENDL;
+ LL_INFOS() << "Saving Data" << LL_ENDL;
- // Store the time of our current logoff
- gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
+ // Store the time of our current logoff
+ gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
if (LLEnvironment::instanceExists())
{
- //Store environment settings if necessary
+ //Store environment settings if necessary
LLEnvironment::getInstance()->saveToSettings();
}
- // Must do this after all panels have been deleted because panels that have persistent rects
- // save their rects on delete.
- gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
-
- LLUIColorTable::instance().saveUserSettings();
-
- // PerAccountSettingsFile should be empty if no user has been logged on.
- // *FIX:Mani This should get really saved in a "logoff" mode.
- if (gSavedSettings.getString("PerAccountSettingsFile").empty())
- {
- LL_INFOS() << "Not saving per-account settings; don't know the account name yet." << LL_ENDL;
- }
- // Only save per account settings if the previous login succeeded, otherwise
- // we might end up with a cleared out settings file in case a previous login
- // failed after loading per account settings.
- else if (!mSavePerAccountSettings)
- {
- LL_INFOS() << "Not saving per-account settings; last login was not successful." << LL_ENDL;
- }
- else
- {
- gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
- LL_INFOS() << "Saved settings" << LL_ENDL;
-
- if (LLViewerParcelAskPlay::instanceExists())
- {
- LLViewerParcelAskPlay::getInstance()->saveSettings();
- }
- }
-
- std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings"));
- gWarningSettings.saveToFile(warnings_settings_filename, TRUE);
-
- // Save URL history file
- LLURLHistory::saveFile("url_history.xml");
-
- // save mute list. gMuteList used to also be deleted here too.
- if (gAgent.isInitialized() && LLMuteList::instanceExists())
- {
- LLMuteList::getInstance()->cache(gAgent.getID());
- }
-
- //save call log list
- if (LLConversationLog::instanceExists())
- {
- LLConversationLog::instance().cache();
+ // Must do this after all panels have been deleted because panels that have persistent rects
+ // save their rects on delete.
+ gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
+
+ LLUIColorTable::instance().saveUserSettings();
+
+ // PerAccountSettingsFile should be empty if no user has been logged on.
+ // *FIX:Mani This should get really saved in a "logoff" mode.
+ if (gSavedSettings.getString("PerAccountSettingsFile").empty())
+ {
+ LL_INFOS() << "Not saving per-account settings; don't know the account name yet." << LL_ENDL;
+ }
+ // Only save per account settings if the previous login succeeded, otherwise
+ // we might end up with a cleared out settings file in case a previous login
+ // failed after loading per account settings.
+ else if (!mSavePerAccountSettings)
+ {
+ LL_INFOS() << "Not saving per-account settings; last login was not successful." << LL_ENDL;
+ }
+ else
+ {
+ gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
+ LL_INFOS() << "Saved settings" << LL_ENDL;
+
+ if (LLViewerParcelAskPlay::instanceExists())
+ {
+ LLViewerParcelAskPlay::getInstance()->saveSettings();
+ }
+ }
+
+ std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings"));
+ gWarningSettings.saveToFile(warnings_settings_filename, TRUE);
+
+ // Save URL history file
+ LLURLHistory::saveFile("url_history.xml");
+
+ // save mute list. gMuteList used to also be deleted here too.
+ if (gAgent.isInitialized() && LLMuteList::instanceExists())
+ {
+ LLMuteList::getInstance()->cache(gAgent.getID());
+ }
+
+ //save call log list
+ if (LLConversationLog::instanceExists())
+ {
+ LLConversationLog::instance().cache();
}
clearSecHandler();
- if (mPurgeCacheOnExit)
- {
- LL_INFOS() << "Purging all cache files on exit" << LL_ENDL;
- gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*");
- }
-
- writeDebugInfo();
-
- LLLocationHistory::getInstance()->save();
-
- LLAvatarIconIDCache::getInstance()->save();
-
- // Stop the plugin read thread if it's running.
- LLPluginProcessParent::setUseReadThread(false);
-
- LL_INFOS() << "Shutting down Threads" << LL_ENDL;
-
- // Let threads finish
- LLTimer idleTimer;
- idleTimer.reset();
- const F64 max_idle_time = 5.f; // 5 seconds
- while(1)
- {
- S32 pending = 0;
- pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread
- pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
- pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
- pending += LLLFSThread::updateClass(0);
- F64 idle_time = idleTimer.getElapsedTimeF64();
- if(!pending)
- {
- break ; //done
- }
- else if(idle_time >= max_idle_time)
- {
- LL_WARNS() << "Quitting with pending background tasks." << LL_ENDL;
- break;
- }
- }
+ if (mPurgeCacheOnExit)
+ {
+ LL_INFOS() << "Purging all cache files on exit" << LL_ENDL;
+ gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*");
+ }
+
+ writeDebugInfo();
+
+ LLLocationHistory::getInstance()->save();
+
+ LLAvatarIconIDCache::getInstance()->save();
+
+ // Stop the plugin read thread if it's running.
+ LLPluginProcessParent::setUseReadThread(false);
+
+ LL_INFOS() << "Shutting down Threads" << LL_ENDL;
+
+ // Let threads finish
+ LLTimer idleTimer;
+ idleTimer.reset();
+ const F64 max_idle_time = 5.f; // 5 seconds
+ while(1)
+ {
+ S32 pending = 0;
+ pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread
+ pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
+ pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
+ pending += LLLFSThread::updateClass(0);
+ F64 idle_time = idleTimer.getElapsedTimeF64();
+ if(!pending)
+ {
+ break ; //done
+ }
+ else if(idle_time >= max_idle_time)
+ {
+ LL_WARNS() << "Quitting with pending background tasks." << LL_ENDL;
+ break;
+ }
+ }
if (mPurgeUserDataOnExit)
{
@@ -2050,32 +2076,32 @@ bool LLAppViewer::cleanup()
gDirUtilp->deleteDirAndContents(user_path);
}
- // Delete workers first
- // shotdown all worker threads before deleting them in case of co-dependencies
- mAppCoreHttp.requestStop();
- sTextureFetch->shutdown();
- sTextureCache->shutdown();
- sImageDecodeThread->shutdown();
- sPurgeDiskCacheThread->shutdown();
- if (mGeneralThreadPool)
- {
- mGeneralThreadPool->close();
- }
+ // Delete workers first
+ // shotdown all worker threads before deleting them in case of co-dependencies
+ mAppCoreHttp.requestStop();
+ sTextureFetch->shutdown();
+ sTextureCache->shutdown();
+ sImageDecodeThread->shutdown();
+ sPurgeDiskCacheThread->shutdown();
+ if (mGeneralThreadPool)
+ {
+ mGeneralThreadPool->close();
+ }
- sTextureFetch->shutDownTextureCacheThread() ;
+ sTextureFetch->shutDownTextureCacheThread() ;
LLLFSThread::sLocal->shutdown();
- LL_INFOS() << "Shutting down message system" << LL_ENDL;
- end_messaging_system();
+ LL_INFOS() << "Shutting down message system" << LL_ENDL;
+ end_messaging_system();
- // Non-LLCurl libcurl library
- mAppCoreHttp.cleanup();
+ // Non-LLCurl libcurl library
+ mAppCoreHttp.cleanup();
- SUBSYSTEM_CLEANUP(LLFilePickerThread);
- SUBSYSTEM_CLEANUP(LLDirPickerThread);
+ SUBSYSTEM_CLEANUP(LLFilePickerThread);
+ SUBSYSTEM_CLEANUP(LLDirPickerThread);
- //MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)
- delete sTextureCache;
+ //MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)
+ delete sTextureCache;
sTextureCache = NULL;
if (sTextureFetch)
{
@@ -2084,101 +2110,101 @@ bool LLAppViewer::cleanup()
delete sTextureFetch;
sTextureFetch = NULL;
}
- delete sImageDecodeThread;
+ delete sImageDecodeThread;
sImageDecodeThread = NULL;
- delete mFastTimerLogThread;
- mFastTimerLogThread = NULL;
- delete sPurgeDiskCacheThread;
- sPurgeDiskCacheThread = NULL;
+ delete mFastTimerLogThread;
+ mFastTimerLogThread = NULL;
+ delete sPurgeDiskCacheThread;
+ sPurgeDiskCacheThread = NULL;
delete mGeneralThreadPool;
mGeneralThreadPool = NULL;
- if (LLFastTimerView::sAnalyzePerformance)
- {
- LL_INFOS() << "Analyzing performance" << LL_ENDL;
+ if (LLFastTimerView::sAnalyzePerformance)
+ {
+ LL_INFOS() << "Analyzing performance" << LL_ENDL;
- std::string baseline_name = LLTrace::BlockTimer::sLogName + "_baseline.slp";
- std::string current_name = LLTrace::BlockTimer::sLogName + ".slp";
- std::string report_name = LLTrace::BlockTimer::sLogName + "_report.csv";
+ std::string baseline_name = LLTrace::BlockTimer::sLogName + "_baseline.slp";
+ std::string current_name = LLTrace::BlockTimer::sLogName + ".slp";
+ std::string report_name = LLTrace::BlockTimer::sLogName + "_report.csv";
- LLFastTimerView::doAnalysis(
- gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
- gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
- gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
- }
+ LLFastTimerView::doAnalysis(
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
+ }
- SUBSYSTEM_CLEANUP(LLMetricPerformanceTesterBasic) ;
+ SUBSYSTEM_CLEANUP(LLMetricPerformanceTesterBasic) ;
- LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL;
+ LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL;
- //Note:
- //SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown()
- //because some new image might be generated during cleaning up media. --bao
- gTextureList.shutdown(); // shutdown again in case a callback added something
- LLUIImageList::getInstance()->cleanUp();
+ //Note:
+ //SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown()
+ //because some new image might be generated during cleaning up media. --bao
+ gTextureList.shutdown(); // shutdown again in case a callback added something
+ LLUIImageList::getInstance()->cleanUp();
- SUBSYSTEM_CLEANUP(LLImage);
- SUBSYSTEM_CLEANUP(LLLFSThread);
+ SUBSYSTEM_CLEANUP(LLImage);
+ SUBSYSTEM_CLEANUP(LLLFSThread);
- LL_INFOS() << "Misc Cleanup" << LL_ENDL;
+ LL_INFOS() << "Misc Cleanup" << LL_ENDL;
- gSavedSettings.cleanup();
- LLUIColorTable::instance().clear();
+ gSavedSettings.cleanup();
+ LLUIColorTable::instance().clear();
- LLWatchdog::getInstance()->cleanup();
+ LLWatchdog::getInstance()->cleanup();
- LLViewerAssetStatsFF::cleanup();
+ LLViewerAssetStatsFF::cleanup();
- // If we're exiting to launch an URL, do that here so the screen
- // is at the right resolution before we launch IE.
- if (!gLaunchFileOnQuit.empty())
- {
- LL_INFOS() << "Launch file on quit." << LL_ENDL;
+ // If we're exiting to launch an URL, do that here so the screen
+ // is at the right resolution before we launch IE.
+ if (!gLaunchFileOnQuit.empty())
+ {
+ LL_INFOS() << "Launch file on quit." << LL_ENDL;
#if LL_WINDOWS
- // Indicate an application is starting.
- SetCursor(LoadCursor(NULL, IDC_WAIT));
+ // Indicate an application is starting.
+ SetCursor(LoadCursor(NULL, IDC_WAIT));
#endif
- // HACK: Attempt to wait until the screen res. switch is complete.
- ms_sleep(1000);
+ // HACK: Attempt to wait until the screen res. switch is complete.
+ ms_sleep(1000);
- LLWeb::loadURLExternal( gLaunchFileOnQuit, false );
- LL_INFOS() << "File launched." << LL_ENDL;
- }
- // make sure nothing uses applyProxySettings by this point.
- LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL;
- SUBSYSTEM_CLEANUP(LLProxy);
+ LLWeb::loadURLExternal( gLaunchFileOnQuit, false );
+ LL_INFOS() << "File launched." << LL_ENDL;
+ }
+ // make sure nothing uses applyProxySettings by this point.
+ LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL;
+ SUBSYSTEM_CLEANUP(LLProxy);
LLCore::LLHttp::cleanup();
- ll_close_fail_log();
+ ll_close_fail_log();
- LLError::LLCallStacks::cleanup();
+ LLError::LLCallStacks::cleanup();
- LLEnvironment::deleteSingleton();
- LLSelectMgr::deleteSingleton();
- LLViewerEventRecorder::deleteSingleton();
+ LLEnvironment::deleteSingleton();
+ LLSelectMgr::deleteSingleton();
+ LLViewerEventRecorder::deleteSingleton();
LLWorld::deleteSingleton();
LLVoiceClient::deleteSingleton();
- // It's not at first obvious where, in this long sequence, a generic cleanup
- // call OUGHT to go. So let's say this: as we migrate cleanup from
- // explicit hand-placed calls into the generic mechanism, eventually
- // all cleanup will get subsumed into the generic call. So the calls you
- // still see above are calls that MUST happen before the generic cleanup
- // kicks in.
+ // It's not at first obvious where, in this long sequence, a generic cleanup
+ // call OUGHT to go. So let's say this: as we migrate cleanup from
+ // explicit hand-placed calls into the generic mechanism, eventually
+ // all cleanup will get subsumed into the generic call. So the calls you
+ // still see above are calls that MUST happen before the generic cleanup
+ // kicks in.
- // This calls every remaining LLSingleton's cleanupSingleton() and
- // deleteSingleton() methods.
- LLSingletonBase::deleteAll();
+ // This calls every remaining LLSingleton's cleanupSingleton() and
+ // deleteSingleton() methods.
+ LLSingletonBase::deleteAll();
LLSplashScreen::hide();
LL_INFOS() << "Goodbye!" << LL_ENDL;
- removeDumpDir();
+ removeDumpDir();
- // return 0;
- return true;
+ // return 0;
+ return true;
}
void LLAppViewer::initGeneralThread()
@@ -2194,11 +2220,11 @@ void LLAppViewer::initGeneralThread()
bool LLAppViewer::initThreads()
{
- static const bool enable_threads = true;
+ static const bool enable_threads = true;
- LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
+ LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
- LLLFSThread::initClass(enable_threads && true); // TODO: fix crashes associated with this shutdo
+ LLLFSThread::initClass(enable_threads && true); // TODO: fix crashes associated with this shutdo
//auto configure thread count
LLSD threadCounts = gSavedSettings.getLLSD("ThreadPoolSizes");
@@ -2213,39 +2239,39 @@ bool LLAppViewer::initThreads()
}
// The only configurable thread count right now is ImageDecode
- // The viewer typically starts around 8 threads not including image decode,
+ // The viewer typically starts around 8 threads not including image decode,
// so try to leave at least one core free
S32 image_decode_count = llclamp(cores - 9, 1, 8);
threadCounts["ImageDecode"] = image_decode_count;
gSavedSettings.setLLSD("ThreadPoolSizes", threadCounts);
- // Image decoding
- LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
- LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
- LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(),
- enable_threads && true,
- app_metrics_qa_mode);
+ // Image decoding
+ LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
+ LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
+ LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(),
+ enable_threads && true,
+ app_metrics_qa_mode);
// general task background thread (LLPerfStats, etc)
LLAppViewer::instance()->initGeneralThread();
- LLAppViewer::sPurgeDiskCacheThread = new LLPurgeDiskCacheThread();
+ LLAppViewer::sPurgeDiskCacheThread = new LLPurgeDiskCacheThread();
- if (LLTrace::BlockTimer::sLog || LLTrace::BlockTimer::sMetricLog)
- {
- LLTrace::BlockTimer::setLogLock(new LLMutex());
- mFastTimerLogThread = new LLFastTimerLogThread(LLTrace::BlockTimer::sLogName);
- mFastTimerLogThread->start();
- }
+ if (LLTrace::BlockTimer::sLog || LLTrace::BlockTimer::sMetricLog)
+ {
+ LLTrace::BlockTimer::setLogLock(new LLMutex());
+ mFastTimerLogThread = new LLFastTimerLogThread(LLTrace::BlockTimer::sLogName);
+ mFastTimerLogThread->start();
+ }
- // Mesh streaming and caching
- gMeshRepo.init();
+ // Mesh streaming and caching
+ gMeshRepo.init();
- LLFilePickerThread::initClass();
- LLDirPickerThread::initClass();
+ LLFilePickerThread::initClass();
+ LLDirPickerThread::initClass();
- // *FIX: no error handling here!
- return true;
+ // *FIX: no error handling here!
+ return true;
}
void errorCallback(LLError::ELevel level, const std::string &error_string)
@@ -2289,7 +2315,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
if (mSecondInstance)
{
LLFile::mkdir(gDirUtilp->getDumpLogsDirPath());
-
+
LLUUID uid;
uid.generate();
LLError::logToFile(gDirUtilp->getDumpLogsDirPath(uid.asString() + ".log"));
@@ -2360,123 +2386,123 @@ void LLAppViewer::initLoggingAndGetLastDuration()
}
bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
- bool set_defaults)
+ bool set_defaults)
{
- if (!mSettingsLocationList)
- {
- LL_ERRS() << "Invalid settings location list" << LL_ENDL;
- }
-
- for (const SettingsGroup& group : mSettingsLocationList->groups)
- {
- // skip settings groups that aren't the one we requested
- if (group.name() != location_key) continue;
-
- ELLPath path_index = (ELLPath)group.path_index();
- if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
- {
- LL_ERRS() << "Out of range path index in app_settings/settings_files.xml" << LL_ENDL;
- return false;
- }
-
- for (const SettingsFile& file : group.files)
- {
- LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name()
- << " - from location " << location_key << LL_ENDL;
-
- auto settings_group = LLControlGroup::getInstance(file.name);
- if(!settings_group)
- {
- LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL;
- continue;
- }
-
- std::string full_settings_path;
-
- if (file.file_name_setting.isProvided()
- && gSavedSettings.controlExists(file.file_name_setting))
- {
- // try to find filename stored in file_name_setting control
- full_settings_path = gSavedSettings.getString(file.file_name_setting);
- if (full_settings_path.empty())
- {
- continue;
- }
- else if (!gDirUtilp->fileExists(full_settings_path))
- {
- // search in default path
- full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, full_settings_path);
- }
- }
- else
- {
- // by default, use specified file name
- full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name());
- }
-
- if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent))
- { // success!
- LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL;
- }
- else
- { // failed to load
- if(file.required)
- {
+ if (!mSettingsLocationList)
+ {
+ LL_ERRS() << "Invalid settings location list" << LL_ENDL;
+ }
+
+ for (const SettingsGroup& group : mSettingsLocationList->groups)
+ {
+ // skip settings groups that aren't the one we requested
+ if (group.name() != location_key) continue;
+
+ ELLPath path_index = (ELLPath)group.path_index();
+ if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
+ {
+ LL_ERRS() << "Out of range path index in app_settings/settings_files.xml" << LL_ENDL;
+ return false;
+ }
+
+ for (const SettingsFile& file : group.files)
+ {
+ LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name()
+ << " - from location " << location_key << LL_ENDL;
+
+ auto settings_group = LLControlGroup::getInstance(file.name);
+ if(!settings_group)
+ {
+ LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL;
+ continue;
+ }
+
+ std::string full_settings_path;
+
+ if (file.file_name_setting.isProvided()
+ && gSavedSettings.controlExists(file.file_name_setting))
+ {
+ // try to find filename stored in file_name_setting control
+ full_settings_path = gSavedSettings.getString(file.file_name_setting);
+ if (full_settings_path.empty())
+ {
+ continue;
+ }
+ else if (!gDirUtilp->fileExists(full_settings_path))
+ {
+ // search in default path
+ full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, full_settings_path);
+ }
+ }
+ else
+ {
+ // by default, use specified file name
+ full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name());
+ }
+
+ if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent))
+ { // success!
+ LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL;
+ }
+ else
+ { // failed to load
+ if(file.required)
+ {
LLError::LLUserWarningMsg::showMissingFiles();
- LL_ERRS() << "Error: Cannot load required settings file from: " << full_settings_path << LL_ENDL;
- return false;
- }
- else
- {
- // only complain if we actually have a filename at this point
- if (!full_settings_path.empty())
- {
- LL_INFOS("Settings") << "Cannot load " << full_settings_path << " - No settings found." << LL_ENDL;
- }
- }
- }
- }
- }
-
- return true;
+ LL_ERRS() << "Error: Cannot load required settings file from: " << full_settings_path << LL_ENDL;
+ return false;
+ }
+ else
+ {
+ // only complain if we actually have a filename at this point
+ if (!full_settings_path.empty())
+ {
+ LL_INFOS("Settings") << "Cannot load " << full_settings_path << " - No settings found." << LL_ENDL;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
}
std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
- const std::string& file)
+ const std::string& file)
{
- for (const SettingsGroup& group : mSettingsLocationList->groups)
- {
- if (group.name() == location_key)
- {
- for (const SettingsFile& settings_file : group.files)
- {
- if (settings_file.name() == file)
- {
- return settings_file.file_name;
- }
- }
- }
- }
-
- return std::string();
+ for (const SettingsGroup& group : mSettingsLocationList->groups)
+ {
+ if (group.name() == location_key)
+ {
+ for (const SettingsFile& settings_file : group.files)
+ {
+ if (settings_file.name() == file)
+ {
+ return settings_file.file_name;
+ }
+ }
+ }
+ }
+
+ return std::string();
}
void LLAppViewer::loadColorSettings()
{
- LLUIColorTable::instance().loadFromSettings();
+ LLUIColorTable::instance().loadFromSettings();
}
namespace
{
void handleCommandLineError(LLControlGroupCLP& clp)
{
- LL_WARNS() << "Error parsing command line options. Command Line options ignored." << LL_ENDL;
+ LL_WARNS() << "Error parsing command line options. Command Line options ignored." << LL_ENDL;
- LL_INFOS() << "Command line usage:\n" << clp << LL_ENDL;
+ LL_INFOS() << "Command line usage:\n" << clp << LL_ENDL;
- OSMessageBox(STRINGIZE(LLTrans::getString("MBCmdLineError") << clp.getErrorMessage()),
- LLStringUtil::null,
- OSMB_OK);
+ OSMessageBox(STRINGIZE(LLTrans::getString("MBCmdLineError") << clp.getErrorMessage()),
+ LLStringUtil::null,
+ OSMB_OK);
}
} // anonymous namespace
@@ -2484,42 +2510,42 @@ namespace
// Name can be specified as "<control_group>.<control_name>", with default group being Global.
bool tempSetControl(const std::string& name, const std::string& value)
{
- std::string name_part;
- std::string group_part;
- LLControlVariable* control = NULL;
-
- // Name can be further split into ControlGroup.Name, with the default control group being Global
- size_t pos = name.find('.');
- if (pos != std::string::npos)
- {
- group_part = name.substr(0, pos);
- name_part = name.substr(pos+1);
- LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL;
- auto g = LLControlGroup::getInstance(group_part);
- if (g) control = g->getControl(name_part);
- }
- else
- {
- LL_INFOS() << "Setting Global." << name << " to " << value << LL_ENDL;
- control = gSavedSettings.getControl(name);
- }
-
- if (control)
- {
- control->setValue(value, false);
- return true;
- }
- return false;
+ std::string name_part;
+ std::string group_part;
+ LLControlVariable* control = NULL;
+
+ // Name can be further split into ControlGroup.Name, with the default control group being Global
+ size_t pos = name.find('.');
+ if (pos != std::string::npos)
+ {
+ group_part = name.substr(0, pos);
+ name_part = name.substr(pos+1);
+ LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL;
+ auto g = LLControlGroup::getInstance(group_part);
+ if (g) control = g->getControl(name_part);
+ }
+ else
+ {
+ LL_INFOS() << "Setting Global." << name << " to " << value << LL_ENDL;
+ control = gSavedSettings.getControl(name);
+ }
+
+ if (control)
+ {
+ control->setValue(value, false);
+ return true;
+ }
+ return false;
}
bool LLAppViewer::initConfiguration()
{
- //Load settings files list
- std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
- LLXMLNodePtr root;
- BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL);
- if (!success)
- {
+ //Load settings files list
+ std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
+ LLXMLNodePtr root;
+ BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL);
+ if (!success)
+ {
LL_WARNS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL;
LLError::LLUserWarningMsg::showMissingFiles();
if (gDirUtilp->fileExists(settings_file_list))
@@ -2536,175 +2562,175 @@ bool LLAppViewer::initConfiguration()
<< "and contact https://support.secondlife.com if issue persists after reinstall."
<< LL_ENDL;
}
- }
+ }
- mSettingsLocationList = new SettingsFiles();
+ mSettingsLocationList = new SettingsFiles();
- LLXUIParser parser;
- parser.readXUI(root, *mSettingsLocationList, settings_file_list);
+ LLXUIParser parser;
+ parser.readXUI(root, *mSettingsLocationList, settings_file_list);
- if (!mSettingsLocationList->validateBlock())
- {
+ if (!mSettingsLocationList->validateBlock())
+ {
LLError::LLUserWarningMsg::showMissingFiles();
LL_ERRS() << "Invalid settings file list " << settings_file_list << LL_ENDL;
- }
-
- // The settings and command line parsing have a fragile
- // order-of-operation:
- // - load defaults from app_settings
- // - set procedural settings values
- // - read command line settings
- // - selectively apply settings needed to load user settings.
+ }
+
+ // The settings and command line parsing have a fragile
+ // order-of-operation:
+ // - load defaults from app_settings
+ // - set procedural settings values
+ // - read command line settings
+ // - selectively apply settings needed to load user settings.
// - load overrides from user_settings
- // - apply command line settings (to override the overrides)
- // - load per account settings (happens in llstartup
-
- // - load defaults
- bool set_defaults = true;
- if(!loadSettingsFromDirectory("Default", set_defaults))
- {
- OSMessageBox(
- "Unable to load default settings file. The installation may be corrupted.",
- LLStringUtil::null,OSMB_OK);
- return false;
- }
-
- initStrings(); // setup paths for LLTrans based on settings files only
- // - set procedural settings
- // Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet
- gSavedSettings.setString("ClientSettingsFile",
+ // - apply command line settings (to override the overrides)
+ // - load per account settings (happens in llstartup
+
+ // - load defaults
+ bool set_defaults = true;
+ if(!loadSettingsFromDirectory("Default", set_defaults))
+ {
+ OSMessageBox(
+ "Unable to load default settings file. The installation may be corrupted.",
+ LLStringUtil::null,OSMB_OK);
+ return false;
+ }
+
+ initStrings(); // setup paths for LLTrans based on settings files only
+ // - set procedural settings
+ // Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet
+ gSavedSettings.setString("ClientSettingsFile",
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global")));
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- // provide developer build only overrides for these control variables that are not
- // persisted to settings.xml
- LLControlVariable* c = gSavedSettings.getControl("AllowMultipleViewers");
- if (c)
- {
- c->setValue(true, false);
- }
-
- gSavedSettings.setBOOL("QAMode", TRUE );
- gSavedSettings.setS32("WatchdogEnabled", 0);
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ // provide developer build only overrides for these control variables that are not
+ // persisted to settings.xml
+ LLControlVariable* c = gSavedSettings.getControl("AllowMultipleViewers");
+ if (c)
+ {
+ c->setValue(true, false);
+ }
+
+ gSavedSettings.setBOOL("QAMode", TRUE );
+ gSavedSettings.setS32("WatchdogEnabled", 0);
#endif
- // These are warnings that appear on the first experience of that condition.
- // They are already set in the settings_default.xml file, but still need to be added to LLFirstUse
- // for disable/reset ability
-// LLFirstUse::addConfigVariable("FirstBalanceIncrease");
-// LLFirstUse::addConfigVariable("FirstBalanceDecrease");
-// LLFirstUse::addConfigVariable("FirstSit");
-// LLFirstUse::addConfigVariable("FirstMap");
-// LLFirstUse::addConfigVariable("FirstGoTo");
-// LLFirstUse::addConfigVariable("FirstBuild");
-// LLFirstUse::addConfigVariable("FirstLeftClickNoHit");
-// LLFirstUse::addConfigVariable("FirstTeleport");
-// LLFirstUse::addConfigVariable("FirstOverrideKeys");
-// LLFirstUse::addConfigVariable("FirstAttach");
-// LLFirstUse::addConfigVariable("FirstAppearance");
-// LLFirstUse::addConfigVariable("FirstInventory");
-// LLFirstUse::addConfigVariable("FirstSandbox");
-// LLFirstUse::addConfigVariable("FirstFlexible");
-// LLFirstUse::addConfigVariable("FirstDebugMenus");
-// LLFirstUse::addConfigVariable("FirstSculptedPrim");
-// LLFirstUse::addConfigVariable("FirstVoice");
-// LLFirstUse::addConfigVariable("FirstMedia");
-
- // - read command line settings.
- LLControlGroupCLP clp;
- std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
- "cmd_line.xml");
-
- clp.configure(cmd_line_config, &gSavedSettings);
-
- if(!initParseCommandLine(clp))
- {
- handleCommandLineError(clp);
- return false;
- }
-
- // - selectively apply settings
-
- // If the user has specified a alternate settings file name.
- // Load it now before loading the user_settings/settings.xml
- if(clp.hasOption("settings"))
- {
- std::string user_settings_filename =
- gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
- clp.getOption("settings")[0]);
- gSavedSettings.setString("ClientSettingsFile", user_settings_filename);
- LL_INFOS("Settings") << "Using command line specified settings filename: "
- << user_settings_filename << LL_ENDL;
- }
-
- // - load overrides from user_settings
- loadSettingsFromDirectory("User");
-
- if (gSavedSettings.getBOOL("FirstRunThisInstall"))
- {
- // Set firstrun flag to indicate that some further init actiona should be taken
- // like determining screen DPI value and so on
- mIsFirstRun = true;
-
- gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);
- }
-
- if (clp.hasOption("sessionsettings"))
- {
- std::string session_settings_filename = clp.getOption("sessionsettings")[0];
- gSavedSettings.setString("SessionSettingsFile", session_settings_filename);
- LL_INFOS("Settings") << "Using session settings filename: "
- << session_settings_filename << LL_ENDL;
- }
- loadSettingsFromDirectory("Session");
-
- if (clp.hasOption("usersessionsettings"))
- {
- std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0];
- gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename);
- LL_INFOS("Settings") << "Using user session settings filename: "
- << user_session_settings_filename << LL_ENDL;
-
- }
- loadSettingsFromDirectory("UserSession");
-
- // - apply command line settings
- if (! clp.notify())
- {
- handleCommandLineError(clp);
- return false;
- }
-
- // Register the core crash option as soon as we can
- // if we want gdb post-mortem on cores we need to be up and running
- // ASAP or we might miss init issue etc.
- if(gSavedSettings.getBOOL("DisableCrashLogger"))
- {
- LL_WARNS() << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << LL_ENDL;
- disableCrashlogger();
- }
-
- gNonInteractive = gSavedSettings.getBOOL("NonInteractive");
- // Handle initialization from settings.
- // Start up the debugging console before handling other options.
- if (gSavedSettings.getBOOL("ShowConsoleWindow") && !gNonInteractive)
- {
- initConsole();
- }
-
- if(clp.hasOption("help"))
- {
- std::ostringstream msg;
- msg << LLTrans::getString("MBCmdLineUsg") << "\n" << clp;
- LL_INFOS() << msg.str() << LL_ENDL;
-
- OSMessageBox(
- msg.str(),
- LLStringUtil::null,
- OSMB_OK);
-
- return false;
- }
+ // These are warnings that appear on the first experience of that condition.
+ // They are already set in the settings_default.xml file, but still need to be added to LLFirstUse
+ // for disable/reset ability
+// LLFirstUse::addConfigVariable("FirstBalanceIncrease");
+// LLFirstUse::addConfigVariable("FirstBalanceDecrease");
+// LLFirstUse::addConfigVariable("FirstSit");
+// LLFirstUse::addConfigVariable("FirstMap");
+// LLFirstUse::addConfigVariable("FirstGoTo");
+// LLFirstUse::addConfigVariable("FirstBuild");
+// LLFirstUse::addConfigVariable("FirstLeftClickNoHit");
+// LLFirstUse::addConfigVariable("FirstTeleport");
+// LLFirstUse::addConfigVariable("FirstOverrideKeys");
+// LLFirstUse::addConfigVariable("FirstAttach");
+// LLFirstUse::addConfigVariable("FirstAppearance");
+// LLFirstUse::addConfigVariable("FirstInventory");
+// LLFirstUse::addConfigVariable("FirstSandbox");
+// LLFirstUse::addConfigVariable("FirstFlexible");
+// LLFirstUse::addConfigVariable("FirstDebugMenus");
+// LLFirstUse::addConfigVariable("FirstSculptedPrim");
+// LLFirstUse::addConfigVariable("FirstVoice");
+// LLFirstUse::addConfigVariable("FirstMedia");
+
+ // - read command line settings.
+ LLControlGroupCLP clp;
+ std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
+ "cmd_line.xml");
+
+ clp.configure(cmd_line_config, &gSavedSettings);
+
+ if(!initParseCommandLine(clp))
+ {
+ handleCommandLineError(clp);
+ return false;
+ }
+
+ // - selectively apply settings
+
+ // If the user has specified a alternate settings file name.
+ // Load it now before loading the user_settings/settings.xml
+ if(clp.hasOption("settings"))
+ {
+ std::string user_settings_filename =
+ gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
+ clp.getOption("settings")[0]);
+ gSavedSettings.setString("ClientSettingsFile", user_settings_filename);
+ LL_INFOS("Settings") << "Using command line specified settings filename: "
+ << user_settings_filename << LL_ENDL;
+ }
+
+ // - load overrides from user_settings
+ loadSettingsFromDirectory("User");
+
+ if (gSavedSettings.getBOOL("FirstRunThisInstall"))
+ {
+ // Set firstrun flag to indicate that some further init actiona should be taken
+ // like determining screen DPI value and so on
+ mIsFirstRun = true;
+
+ gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);
+ }
+
+ if (clp.hasOption("sessionsettings"))
+ {
+ std::string session_settings_filename = clp.getOption("sessionsettings")[0];
+ gSavedSettings.setString("SessionSettingsFile", session_settings_filename);
+ LL_INFOS("Settings") << "Using session settings filename: "
+ << session_settings_filename << LL_ENDL;
+ }
+ loadSettingsFromDirectory("Session");
+
+ if (clp.hasOption("usersessionsettings"))
+ {
+ std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0];
+ gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename);
+ LL_INFOS("Settings") << "Using user session settings filename: "
+ << user_session_settings_filename << LL_ENDL;
+
+ }
+ loadSettingsFromDirectory("UserSession");
+
+ // - apply command line settings
+ if (! clp.notify())
+ {
+ handleCommandLineError(clp);
+ return false;
+ }
+
+ // Register the core crash option as soon as we can
+ // if we want gdb post-mortem on cores we need to be up and running
+ // ASAP or we might miss init issue etc.
+ if(gSavedSettings.getBOOL("DisableCrashLogger"))
+ {
+ LL_WARNS() << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << LL_ENDL;
+ disableCrashlogger();
+ }
+
+ gNonInteractive = gSavedSettings.getBOOL("NonInteractive");
+ // Handle initialization from settings.
+ // Start up the debugging console before handling other options.
+ if (gSavedSettings.getBOOL("ShowConsoleWindow") && !gNonInteractive)
+ {
+ initConsole();
+ }
+
+ if(clp.hasOption("help"))
+ {
+ std::ostringstream msg;
+ msg << LLTrans::getString("MBCmdLineUsg") << "\n" << clp;
+ LL_INFOS() << msg.str() << LL_ENDL;
+
+ OSMessageBox(
+ msg.str(),
+ LLStringUtil::null,
+ OSMB_OK);
+
+ return false;
+ }
if(clp.hasOption("set"))
{
@@ -2722,43 +2748,43 @@ bool LLAppViewer::initConfiguration()
const std::string& value = *(++itr);
if (!tempSetControl(name,value))
{
- LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL;
+ LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL;
}
}
}
}
if (clp.hasOption("logevents")) {
- LLViewerEventRecorder::instance().setEventLoggingOn();
+ LLViewerEventRecorder::instance().setEventLoggingOn();
}
- std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));
- if(! CmdLineChannel.empty())
+ std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));
+ if(! CmdLineChannel.empty())
{
- LLVersionInfo::instance().resetChannel(CmdLineChannel);
- }
+ LLVersionInfo::instance().resetChannel(CmdLineChannel);
+ }
- // If we have specified crash on startup, set the global so we'll trigger the crash at the right time
- gCrashOnStartup = gSavedSettings.getBOOL("CrashOnStartup");
+ // If we have specified crash on startup, set the global so we'll trigger the crash at the right time
+ gCrashOnStartup = gSavedSettings.getBOOL("CrashOnStartup");
- if (gSavedSettings.getBOOL("LogPerformance"))
- {
- LLTrace::BlockTimer::sLog = true;
- LLTrace::BlockTimer::sLogName = std::string("performance");
- }
+ if (gSavedSettings.getBOOL("LogPerformance"))
+ {
+ LLTrace::BlockTimer::sLog = true;
+ LLTrace::BlockTimer::sLogName = std::string("performance");
+ }
- std::string test_name(gSavedSettings.getString("LogMetrics"));
- if (! test_name.empty())
- {
- LLTrace::BlockTimer::sMetricLog = TRUE;
- // '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test
- // In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...)
- LL_INFOS() << "'--logmetrics' argument : " << test_name << LL_ENDL;
- LLTrace::BlockTimer::sLogName = test_name;
- }
+ std::string test_name(gSavedSettings.getString("LogMetrics"));
+ if (! test_name.empty())
+ {
+ LLTrace::BlockTimer::sMetricLog = TRUE;
+ // '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test
+ // In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...)
+ LL_INFOS() << "'--logmetrics' argument : " << test_name << LL_ENDL;
+ LLTrace::BlockTimer::sLogName = test_name;
+ }
- if (clp.hasOption("graphicslevel"))
- {
+ if (clp.hasOption("graphicslevel"))
+ {
// User explicitly requested --graphicslevel on the command line. We
// expect this switch has already set RenderQualityPerformance. Check
// that value for validity later.
@@ -2767,18 +2793,18 @@ bool LLAppViewer::initConfiguration()
// will call LLFeatureManager::applyRecommendedSettings(), which
// overwrites this settings variable!
mForceGraphicsLevel = gSavedSettings.getU32("RenderQualityPerformance");
- }
+ }
- LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance");
- gAgentPilot.setReplaySession(gSavedSettings.getBOOL("ReplaySession"));
+ LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance");
+ gAgentPilot.setReplaySession(gSavedSettings.getBOOL("ReplaySession"));
- if (gSavedSettings.getBOOL("DebugSession"))
- {
- gDebugSession = TRUE;
- gDebugGL = TRUE;
+ if (gSavedSettings.getBOOL("DebugSession"))
+ {
+ gDebugSession = TRUE;
+ gDebugGL = TRUE;
- ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log"));
- }
+ ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log"));
+ }
if (gSavedSettings.getBOOL("RenderDebugGLSession"))
{
@@ -2789,47 +2815,47 @@ bool LLAppViewer::initConfiguration()
gSavedSettings.setBOOL("RenderDebugGLSession", FALSE);
}
- const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
- if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
- {
- // Examining "Language" may not suffice -- see LLUI::getLanguage()
- // logic. Unfortunately LLUI::getLanguage() doesn't yet do us much
- // good because we haven't yet called LLUI::initClass().
- gDirUtilp->setSkinFolder(skinfolder->getValue().asString(),
- gSavedSettings.getString("Language"));
- }
-
- if (gSavedSettings.getBOOL("SpellCheck"))
- {
- std::list<std::string> dict_list;
- std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary");
- boost::split(dict_list, dict_setting, boost::is_any_of(std::string(",")));
- if (!dict_list.empty())
- {
- LLSpellChecker::setUseSpellCheck(dict_list.front());
- dict_list.pop_front();
- LLSpellChecker::instance().setSecondaryDictionaries(dict_list);
- }
- }
-
- if (gNonInteractive)
- {
- tempSetControl("AllowMultipleViewers", "TRUE");
- tempSetControl("SLURLPassToOtherInstance", "FALSE");
- tempSetControl("RenderWater", "FALSE");
- tempSetControl("FlyingAtExit", "FALSE");
- tempSetControl("WindowWidth", "1024");
- tempSetControl("WindowHeight", "200");
- LLError::setEnabledLogTypesMask(0);
- llassert_always(!gSavedSettings.getBOOL("SLURLPassToOtherInstance"));
- }
-
-
- // Handle slurl use. NOTE: Don't let SL-55321 reappear.
- // This initial-SLURL logic, up through the call to
- // sendURLToOtherInstance(), must precede LLSplashScreen::show() --
- // because if sendURLToOtherInstance() succeeds, we take a fast exit,
- // SKIPPING the splash screen and everything else.
+ const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
+ if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
+ {
+ // Examining "Language" may not suffice -- see LLUI::getLanguage()
+ // logic. Unfortunately LLUI::getLanguage() doesn't yet do us much
+ // good because we haven't yet called LLUI::initClass().
+ gDirUtilp->setSkinFolder(skinfolder->getValue().asString(),
+ gSavedSettings.getString("Language"));
+ }
+
+ if (gSavedSettings.getBOOL("SpellCheck"))
+ {
+ std::list<std::string> dict_list;
+ std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary");
+ boost::split(dict_list, dict_setting, boost::is_any_of(std::string(",")));
+ if (!dict_list.empty())
+ {
+ LLSpellChecker::setUseSpellCheck(dict_list.front());
+ dict_list.pop_front();
+ LLSpellChecker::instance().setSecondaryDictionaries(dict_list);
+ }
+ }
+
+ if (gNonInteractive)
+ {
+ tempSetControl("AllowMultipleViewers", "TRUE");
+ tempSetControl("SLURLPassToOtherInstance", "FALSE");
+ tempSetControl("RenderWater", "FALSE");
+ tempSetControl("FlyingAtExit", "FALSE");
+ tempSetControl("WindowWidth", "1024");
+ tempSetControl("WindowHeight", "200");
+ LLError::setEnabledLogTypesMask(0);
+ llassert_always(!gSavedSettings.getBOOL("SLURLPassToOtherInstance"));
+ }
+
+
+ // Handle slurl use. NOTE: Don't let SL-55321 reappear.
+ // This initial-SLURL logic, up through the call to
+ // sendURLToOtherInstance(), must precede LLSplashScreen::show() --
+ // because if sendURLToOtherInstance() succeeds, we take a fast exit,
+ // SKIPPING the splash screen and everything else.
// *FIX: This init code should be made more robust to prevent
// the issue SL-55321 from returning. One thought is to allow
@@ -2847,143 +2873,143 @@ bool LLAppViewer::initConfiguration()
// other browsers) and do the rough equivalent of command
// injection and steal passwords. Phoenix. SL-55321
- std::string starting_location;
-
- std::string cmd_line_login_location(gSavedSettings.getString("CmdLineLoginLocation"));
- if(! cmd_line_login_location.empty())
- {
- starting_location = cmd_line_login_location;
- }
- else
- {
- std::string default_login_location(gSavedSettings.getString("DefaultLoginLocation"));
- if (! default_login_location.empty())
- {
- starting_location = default_login_location;
- }
- }
-
- LLSLURL start_slurl;
- if (! starting_location.empty())
- {
- start_slurl = starting_location;
- LLStartUp::setStartSLURL(start_slurl);
- if(start_slurl.getType() == LLSLURL::LOCATION)
- {
- LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid());
- }
- }
-
- // NextLoginLocation is set as a side effect of LLStartUp::setStartSLURL()
- std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
- if ( !nextLoginLocation.empty() )
- {
- LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
- LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
- }
- else if ( ( clp.hasOption("login") || clp.hasOption("autologin"))
- && gSavedSettings.getString("CmdLineLoginLocation").empty())
- {
- // If automatic login from command line with --login switch
- // init StartSLURL location.
- std::string start_slurl_setting = gSavedSettings.getString("LoginLocation");
- LL_DEBUGS("AppInit") << "start slurl setting '" << start_slurl_setting << "'" << LL_ENDL;
- LLStartUp::setStartSLURL(LLSLURL(start_slurl_setting));
- }
- else
- {
- // the login location will be set by the login panel (see LLPanelLogin)
- }
-
- //RN: if we received a URL, hand it off to the existing instance.
- // don't call anotherInstanceRunning() when doing URL handoff, as
- // it relies on checking a marker file which will not work when running
- // out of different directories
-
- if (start_slurl.isValid() &&
- (gSavedSettings.getBOOL("SLURLPassToOtherInstance")))
- {
- if (sendURLToOtherInstance(start_slurl.getSLURLString()))
- {
- // successfully handed off URL to existing instance, exit
- return false;
- }
- }
-
- // Display splash screen. Must be after above check for previous
- // crash as this dialog is always frontmost.
- std::string splash_msg;
- LLStringUtil::format_map_t args;
- args["[APP_NAME]"] = LLTrans::getString("SECOND_LIFE");
- splash_msg = LLTrans::getString("StartupLoading", args);
- LLSplashScreen::show();
- LLSplashScreen::update(splash_msg);
-
- //LLVolumeMgr::initClass();
- LLVolumeMgr* volume_manager = new LLVolumeMgr();
- volume_manager->useMutex(); // LLApp and LLMutex magic must be manually enabled
- LLPrimitive::setVolumeManager(volume_manager);
-
- // Note: this is where we used to initialize gFeatureManagerp.
-
- gStartTime = totalTime();
-
- //
- // Set the name of the window
- //
- gWindowTitle = LLTrans::getString("APP_NAME");
+ std::string starting_location;
+
+ std::string cmd_line_login_location(gSavedSettings.getString("CmdLineLoginLocation"));
+ if(! cmd_line_login_location.empty())
+ {
+ starting_location = cmd_line_login_location;
+ }
+ else
+ {
+ std::string default_login_location(gSavedSettings.getString("DefaultLoginLocation"));
+ if (! default_login_location.empty())
+ {
+ starting_location = default_login_location;
+ }
+ }
+
+ LLSLURL start_slurl;
+ if (! starting_location.empty())
+ {
+ start_slurl = starting_location;
+ LLStartUp::setStartSLURL(start_slurl);
+ if(start_slurl.getType() == LLSLURL::LOCATION)
+ {
+ LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid());
+ }
+ }
+
+ // NextLoginLocation is set as a side effect of LLStartUp::setStartSLURL()
+ std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
+ if ( !nextLoginLocation.empty() )
+ {
+ LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
+ LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
+ }
+ else if ( ( clp.hasOption("login") || clp.hasOption("autologin"))
+ && gSavedSettings.getString("CmdLineLoginLocation").empty())
+ {
+ // If automatic login from command line with --login switch
+ // init StartSLURL location.
+ std::string start_slurl_setting = gSavedSettings.getString("LoginLocation");
+ LL_DEBUGS("AppInit") << "start slurl setting '" << start_slurl_setting << "'" << LL_ENDL;
+ LLStartUp::setStartSLURL(LLSLURL(start_slurl_setting));
+ }
+ else
+ {
+ // the login location will be set by the login panel (see LLPanelLogin)
+ }
+
+ //RN: if we received a URL, hand it off to the existing instance.
+ // don't call anotherInstanceRunning() when doing URL handoff, as
+ // it relies on checking a marker file which will not work when running
+ // out of different directories
+
+ if (start_slurl.isValid() &&
+ (gSavedSettings.getBOOL("SLURLPassToOtherInstance")))
+ {
+ if (sendURLToOtherInstance(start_slurl.getSLURLString()))
+ {
+ // successfully handed off URL to existing instance, exit
+ return false;
+ }
+ }
+
+ // Display splash screen. Must be after above check for previous
+ // crash as this dialog is always frontmost.
+ std::string splash_msg;
+ LLStringUtil::format_map_t args;
+ args["[APP_NAME]"] = LLTrans::getString("SECOND_LIFE");
+ splash_msg = LLTrans::getString("StartupLoading", args);
+ LLSplashScreen::show();
+ LLSplashScreen::update(splash_msg);
+
+ //LLVolumeMgr::initClass();
+ LLVolumeMgr* volume_manager = new LLVolumeMgr();
+ volume_manager->useMutex(); // LLApp and LLMutex magic must be manually enabled
+ LLPrimitive::setVolumeManager(volume_manager);
+
+ // Note: this is where we used to initialize gFeatureManagerp.
+
+ gStartTime = totalTime();
+
+ //
+ // Set the name of the window
+ //
+ gWindowTitle = LLTrans::getString("APP_NAME");
#if LL_DEBUG
- gWindowTitle += std::string(" [DEBUG]");
+ gWindowTitle += std::string(" [DEBUG]");
#endif
- if (!gArgs.empty())
- {
- gWindowTitle += std::string(" ") + gArgs;
- }
- LLStringUtil::truncate(gWindowTitle, 255);
-
- //
- // Check for another instance of the app running
- // This happens AFTER LLSplashScreen::show(). That may or may not be
- // important.
- //
- if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers"))
- {
- OSMessageBox(
- LLTrans::getString("MBAlreadyRunning"),
- LLStringUtil::null,
- OSMB_OK);
- return false;
- }
-
- if (mSecondInstance)
- {
- // This is the second instance of SL. Mute voice,
- // but make sure the setting is *not* persisted.
- // Also see LLVivoxVoiceClient::voiceEnabled()
- LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat");
- if(enable_voice)
- {
- const BOOL DO_NOT_PERSIST = FALSE;
- enable_voice->setValue(LLSD(FALSE), DO_NOT_PERSIST);
- }
- }
-
- gLastRunVersion = gSavedSettings.getString("LastRunVersion");
-
- loadColorSettings();
-
- // Let anyone else who cares know that we've populated our settings
- // variables.
- for (const auto& key : LLControlGroup::key_snapshot())
- {
- // For each named instance of LLControlGroup, send an event saying
- // we've initialized an LLControlGroup instance by that name.
- LLEventPumps::instance().obtain("LLControlGroup").post(LLSDMap("init", key));
- }
+ if (!gArgs.empty())
+ {
+ gWindowTitle += std::string(" ") + gArgs;
+ }
+ LLStringUtil::truncate(gWindowTitle, 255);
+
+ //
+ // Check for another instance of the app running
+ // This happens AFTER LLSplashScreen::show(). That may or may not be
+ // important.
+ //
+ if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers"))
+ {
+ OSMessageBox(
+ LLTrans::getString("MBAlreadyRunning"),
+ LLStringUtil::null,
+ OSMB_OK);
+ return false;
+ }
+
+ if (mSecondInstance)
+ {
+ // This is the second instance of SL. Mute voice,
+ // but make sure the setting is *not* persisted.
+ // Also see LLVivoxVoiceClient::voiceEnabled()
+ LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat");
+ if(enable_voice)
+ {
+ const BOOL DO_NOT_PERSIST = FALSE;
+ enable_voice->setValue(LLSD(FALSE), DO_NOT_PERSIST);
+ }
+ }
+
+ gLastRunVersion = gSavedSettings.getString("LastRunVersion");
+
+ loadColorSettings();
+
+ // Let anyone else who cares know that we've populated our settings
+ // variables.
+ for (const auto& key : LLControlGroup::key_snapshot())
+ {
+ // For each named instance of LLControlGroup, send an event saying
+ // we've initialized an LLControlGroup instance by that name.
+ LLEventPumps::instance().obtain("LLControlGroup").post(LLSDMap("init", key));
+ }
LLError::LLUserWarningMsg::setOutOfMemoryStrings(LLTrans::getString("MBOutOfMemoryTitle"), LLTrans::getString("MBOutOfMemoryErr"));
- return true; // Config was successful.
+ return true; // Config was successful.
}
// The following logic is replicated in initConfiguration() (to be able to get
@@ -2992,214 +3018,214 @@ bool LLAppViewer::initConfiguration()
// keeps growing, necessitating a method all its own.
void LLAppViewer::initStrings()
{
- std::string strings_file = "strings.xml";
- std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file);
- if (strings_path_full.empty() || !LLFile::isfile(strings_path_full))
- {
- if (strings_path_full.empty())
- {
- LL_WARNS() << "The file '" << strings_file << "' is not found" << LL_ENDL;
- }
- else
- {
- llstat st;
- int rc = LLFile::stat(strings_path_full, &st);
- if (rc != 0)
- {
- LL_WARNS() << "The file '" << strings_path_full << "' failed to get status. Error code: " << rc << LL_ENDL;
- }
- else if (S_ISDIR(st.st_mode))
- {
- LL_WARNS() << "The filename '" << strings_path_full << "' is a directory name" << LL_ENDL;
- }
- else
- {
- LL_WARNS() << "The filename '" << strings_path_full << "' doesn't seem to be a regular file name" << LL_ENDL;
- }
- }
-
- // initial check to make sure files are there failed
- gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
+ std::string strings_file = "strings.xml";
+ std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file);
+ if (strings_path_full.empty() || !LLFile::isfile(strings_path_full))
+ {
+ if (strings_path_full.empty())
+ {
+ LL_WARNS() << "The file '" << strings_file << "' is not found" << LL_ENDL;
+ }
+ else
+ {
+ llstat st;
+ int rc = LLFile::stat(strings_path_full, &st);
+ if (rc != 0)
+ {
+ LL_WARNS() << "The file '" << strings_path_full << "' failed to get status. Error code: " << rc << LL_ENDL;
+ }
+ else if (S_ISDIR(st.st_mode))
+ {
+ LL_WARNS() << "The filename '" << strings_path_full << "' is a directory name" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "The filename '" << strings_path_full << "' doesn't seem to be a regular file name" << LL_ENDL;
+ }
+ }
+
+ // initial check to make sure files are there failed
+ gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
LLError::LLUserWarningMsg::showMissingFiles();
- LL_ERRS() << "Viewer failed to find localization and UI files."
- << " Please reinstall viewer from https://secondlife.com/support/downloads"
- << " and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
- }
- LLTransUtil::parseStrings(strings_file, default_trans_args);
- LLTransUtil::parseLanguageStrings("language_settings.xml");
-
- // parseStrings() sets up the LLTrans substitution table. Add this one item.
- LLTrans::setDefaultArg("[sourceid]", gSavedSettings.getString("sourceid"));
-
- // Now that we've set "[sourceid]", have to go back through
- // default_trans_args and reinitialize all those other keys because some
- // of them, in turn, reference "[sourceid]".
- for (const std::string& key : default_trans_args)
- {
- std::string brackets(key), nobrackets(key);
- // Invalid to inspect key[0] if key is empty(). But then, the entire
- // body of this loop is pointless if key is empty().
- if (key.empty())
- continue;
-
- if (key[0] != '[')
- {
- // key was passed without brackets. That means that 'nobrackets'
- // is correct but 'brackets' is not.
- brackets = STRINGIZE('[' << brackets << ']');
- }
- else
- {
- // key was passed with brackets. That means that 'brackets' is
- // correct but 'nobrackets' is not. Erase the left bracket.
- nobrackets.erase(0, 1);
- std::string::size_type length(nobrackets.length());
- if (length && nobrackets[length - 1] == ']')
- {
- nobrackets.erase(length - 1);
- }
- }
- // Calling LLTrans::getString() is what embeds the other default
- // translation strings into this one.
- LLTrans::setDefaultArg(brackets, LLTrans::getString(nobrackets));
- }
+ LL_ERRS() << "Viewer failed to find localization and UI files."
+ << " Please reinstall viewer from https://secondlife.com/support/downloads"
+ << " and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
+ }
+ LLTransUtil::parseStrings(strings_file, default_trans_args);
+ LLTransUtil::parseLanguageStrings("language_settings.xml");
+
+ // parseStrings() sets up the LLTrans substitution table. Add this one item.
+ LLTrans::setDefaultArg("[sourceid]", gSavedSettings.getString("sourceid"));
+
+ // Now that we've set "[sourceid]", have to go back through
+ // default_trans_args and reinitialize all those other keys because some
+ // of them, in turn, reference "[sourceid]".
+ for (const std::string& key : default_trans_args)
+ {
+ std::string brackets(key), nobrackets(key);
+ // Invalid to inspect key[0] if key is empty(). But then, the entire
+ // body of this loop is pointless if key is empty().
+ if (key.empty())
+ continue;
+
+ if (key[0] != '[')
+ {
+ // key was passed without brackets. That means that 'nobrackets'
+ // is correct but 'brackets' is not.
+ brackets = STRINGIZE('[' << brackets << ']');
+ }
+ else
+ {
+ // key was passed with brackets. That means that 'brackets' is
+ // correct but 'nobrackets' is not. Erase the left bracket.
+ nobrackets.erase(0, 1);
+ std::string::size_type length(nobrackets.length());
+ if (length && nobrackets[length - 1] == ']')
+ {
+ nobrackets.erase(length - 1);
+ }
+ }
+ // Calling LLTrans::getString() is what embeds the other default
+ // translation strings into this one.
+ LLTrans::setDefaultArg(brackets, LLTrans::getString(nobrackets));
+ }
}
bool LLAppViewer::meetsRequirementsForMaximizedStart()
{
bool maximizedOk = (gSysMemory.getPhysicalMemoryKB() >= U32Gigabytes(1));
- return maximizedOk;
+ return maximizedOk;
}
bool LLAppViewer::initWindow()
{
- LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL;
-
- // store setting in a global for easy access and modification
- gHeadlessClient = gSavedSettings.getBOOL("HeadlessClient");
-
- // always start windowed
- BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");
-
- LLViewerWindow::Params window_params;
- window_params
- .title(gWindowTitle)
- .name(VIEWER_WINDOW_CLASSNAME)
- .x(gSavedSettings.getS32("WindowX"))
- .y(gSavedSettings.getS32("WindowY"))
- .width(gSavedSettings.getU32("WindowWidth"))
- .height(gSavedSettings.getU32("WindowHeight"))
- .min_width(gSavedSettings.getU32("MinWindowWidth"))
- .min_height(gSavedSettings.getU32("MinWindowHeight"))
- .fullscreen(gSavedSettings.getBOOL("FullScreen"))
- .ignore_pixel_depth(ignorePixelDepth)
- .first_run(mIsFirstRun);
-
- gViewerWindow = new LLViewerWindow(window_params);
-
- LL_INFOS("AppInit") << "gViewerwindow created." << LL_ENDL;
-
- // Need to load feature table before cheking to start watchdog.
- bool use_watchdog = false;
- int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled");
- if (watchdog_enabled_setting == -1)
- {
- use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled");
- }
- else
- {
- // The user has explicitly set this setting; always use that value.
- use_watchdog = bool(watchdog_enabled_setting);
- }
-
- LL_INFOS("AppInit") << "watchdog"
- << (use_watchdog ? " " : " NOT ")
- << "enabled"
- << " (setting = " << watchdog_enabled_setting << ")"
- << LL_ENDL;
-
- if (use_watchdog)
- {
- LLWatchdog::getInstance()->init();
- }
-
- LLNotificationsUI::LLNotificationManager::getInstance();
+ LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL;
+
+ // store setting in a global for easy access and modification
+ gHeadlessClient = gSavedSettings.getBOOL("HeadlessClient");
+
+ // always start windowed
+ BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");
+
+ LLViewerWindow::Params window_params;
+ window_params
+ .title(gWindowTitle)
+ .name(VIEWER_WINDOW_CLASSNAME)
+ .x(gSavedSettings.getS32("WindowX"))
+ .y(gSavedSettings.getS32("WindowY"))
+ .width(gSavedSettings.getU32("WindowWidth"))
+ .height(gSavedSettings.getU32("WindowHeight"))
+ .min_width(gSavedSettings.getU32("MinWindowWidth"))
+ .min_height(gSavedSettings.getU32("MinWindowHeight"))
+ .fullscreen(gSavedSettings.getBOOL("FullScreen"))
+ .ignore_pixel_depth(ignorePixelDepth)
+ .first_run(mIsFirstRun);
+
+ gViewerWindow = new LLViewerWindow(window_params);
+
+ LL_INFOS("AppInit") << "gViewerwindow created." << LL_ENDL;
+
+ // Need to load feature table before cheking to start watchdog.
+ bool use_watchdog = false;
+ int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled");
+ if (watchdog_enabled_setting == -1)
+ {
+ use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled");
+ }
+ else
+ {
+ // The user has explicitly set this setting; always use that value.
+ use_watchdog = bool(watchdog_enabled_setting);
+ }
+
+ LL_INFOS("AppInit") << "watchdog"
+ << (use_watchdog ? " " : " NOT ")
+ << "enabled"
+ << " (setting = " << watchdog_enabled_setting << ")"
+ << LL_ENDL;
+
+ if (use_watchdog)
+ {
+ LLWatchdog::getInstance()->init();
+ }
+
+ LLNotificationsUI::LLNotificationManager::getInstance();
#ifdef LL_DARWIN
- //Satisfy both MAINT-3135 (OSX 10.6 and earlier) MAINT-3288 (OSX 10.7 and later)
- LLOSInfo& os_info = LLOSInfo::instance();
- if (os_info.mMajorVer == 10 && os_info.mMinorVer < 7)
- {
- if ( os_info.mMinorVer == 6 && os_info.mBuild < 8 )
- gViewerWindow->getWindow()->setOldResize(true);
- }
+ //Satisfy both MAINT-3135 (OSX 10.6 and earlier) MAINT-3288 (OSX 10.7 and later)
+ LLOSInfo& os_info = LLOSInfo::instance();
+ if (os_info.mMajorVer == 10 && os_info.mMinorVer < 7)
+ {
+ if ( os_info.mMinorVer == 6 && os_info.mBuild < 8 )
+ gViewerWindow->getWindow()->setOldResize(true);
+ }
#endif
- if (gSavedSettings.getBOOL("WindowMaximized"))
- {
- gViewerWindow->getWindow()->maximize();
- }
+ if (gSavedSettings.getBOOL("WindowMaximized"))
+ {
+ gViewerWindow->getWindow()->maximize();
+ }
- //
- // Initialize GL stuff
- //
+ //
+ // Initialize GL stuff
+ //
- if (mForceGraphicsLevel && (LLFeatureManager::instance().isValidGraphicsLevel(*mForceGraphicsLevel)))
- {
- LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false);
- gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel);
- }
+ if (mForceGraphicsLevel && (LLFeatureManager::instance().isValidGraphicsLevel(*mForceGraphicsLevel)))
+ {
+ LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false);
+ gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel);
+ }
- // Set this flag in case we crash while initializing GL
- gSavedSettings.setBOOL("RenderInitError", TRUE);
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
+ // Set this flag in case we crash while initializing GL
+ gSavedSettings.setBOOL("RenderInitError", TRUE);
+ gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
- gPipeline.init();
- LL_INFOS("AppInit") << "gPipeline Initialized" << LL_ENDL;
+ gPipeline.init();
+ LL_INFOS("AppInit") << "gPipeline Initialized" << LL_ENDL;
- stop_glerror();
- gViewerWindow->initGLDefaults();
+ stop_glerror();
+ gViewerWindow->initGLDefaults();
- gSavedSettings.setBOOL("RenderInitError", FALSE);
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
+ gSavedSettings.setBOOL("RenderInitError", FALSE);
+ gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
- //If we have a startup crash, it's usually near GL initialization, so simulate that.
- if(gCrashOnStartup)
- {
- LLAppViewer::instance()->forceErrorLLError();
- }
+ //If we have a startup crash, it's usually near GL initialization, so simulate that.
+ if(gCrashOnStartup)
+ {
+ LLAppViewer::instance()->forceErrorLLError();
+ }
- //
- // Determine if the window should start maximized on initial run based
- // on graphics capability
- //
- if (gSavedSettings.getBOOL("FirstLoginThisInstall") && meetsRequirementsForMaximizedStart())
- {
- LL_INFOS("AppInit") << "This client met the requirements for a maximized initial screen." << LL_ENDL;
- gSavedSettings.setBOOL("WindowMaximized", TRUE);
- }
+ //
+ // Determine if the window should start maximized on initial run based
+ // on graphics capability
+ //
+ if (gSavedSettings.getBOOL("FirstLoginThisInstall") && meetsRequirementsForMaximizedStart())
+ {
+ LL_INFOS("AppInit") << "This client met the requirements for a maximized initial screen." << LL_ENDL;
+ gSavedSettings.setBOOL("WindowMaximized", TRUE);
+ }
- if (gSavedSettings.getBOOL("WindowMaximized"))
- {
- gViewerWindow->getWindow()->maximize();
- }
+ if (gSavedSettings.getBOOL("WindowMaximized"))
+ {
+ gViewerWindow->getWindow()->maximize();
+ }
- LLUI::getInstance()->mWindow = gViewerWindow->getWindow();
+ LLUI::getInstance()->mWindow = gViewerWindow->getWindow();
- // Show watch cursor
- gViewerWindow->setCursor(UI_CURSOR_WAIT);
+ // Show watch cursor
+ gViewerWindow->setCursor(UI_CURSOR_WAIT);
- // Finish view initialization
- gViewerWindow->initBase();
+ // Finish view initialization
+ gViewerWindow->initBase();
- // show viewer window
- //gViewerWindow->getWindow()->show();
+ // show viewer window
+ //gViewerWindow->getWindow()->show();
- LL_INFOS("AppInit") << "Window initialization done." << LL_ENDL;
+ LL_INFOS("AppInit") << "Window initialization done." << LL_ENDL;
- return true;
+ return true;
}
bool LLAppViewer::isUpdaterMissing()
@@ -3238,28 +3264,28 @@ void LLAppViewer::writeDebugInfo(bool isStatic)
LLSD LLAppViewer::getViewerInfo() const
{
- // The point of having one method build an LLSD info block and the other
- // construct the user-visible About string is to ensure that the same info
- // is available to a getInfo() caller as to the user opening
- // LLFloaterAbout.
- LLSD info;
- auto& versionInfo(LLVersionInfo::instance());
- // With GitHub builds, the build number is too big to fit in a 32-bit int,
- // and LLSD doesn't deal with integers wider than int. Use string.
- info["VIEWER_VERSION"] = llsd::array(versionInfo.getMajor(), versionInfo.getMinor(),
- versionInfo.getPatch(), stringize(versionInfo.getBuild()));
- info["VIEWER_VERSION_STR"] = versionInfo.getVersion();
- info["CHANNEL"] = versionInfo.getChannel();
- info["ADDRESS_SIZE"] = ADDRESS_SIZE;
- std::string build_config = versionInfo.getBuildConfig();
- if (build_config != "Release")
- {
- info["BUILD_CONFIG"] = build_config;
- }
-
- // return a URL to the release notes for this viewer, such as:
- // https://releasenotes.secondlife.com/viewer/2.1.0.123456.html
- std::string url = versionInfo.getReleaseNotes(); // VVM supplied
+ // The point of having one method build an LLSD info block and the other
+ // construct the user-visible About string is to ensure that the same info
+ // is available to a getInfo() caller as to the user opening
+ // LLFloaterAbout.
+ LLSD info;
+ auto& versionInfo(LLVersionInfo::instance());
+ // With GitHub builds, the build number is too big to fit in a 32-bit int,
+ // and LLSD doesn't deal with integers wider than int. Use string.
+ info["VIEWER_VERSION"] = llsd::array(versionInfo.getMajor(), versionInfo.getMinor(),
+ versionInfo.getPatch(), stringize(versionInfo.getBuild()));
+ info["VIEWER_VERSION_STR"] = versionInfo.getVersion();
+ info["CHANNEL"] = versionInfo.getChannel();
+ info["ADDRESS_SIZE"] = ADDRESS_SIZE;
+ std::string build_config = versionInfo.getBuildConfig();
+ if (build_config != "Release")
+ {
+ info["BUILD_CONFIG"] = build_config;
+ }
+
+ // return a URL to the release notes for this viewer, such as:
+ // https://releasenotes.secondlife.com/viewer/2.1.0.123456.html
+ std::string url = versionInfo.getReleaseNotes(); // VVM supplied
if (url.empty())
{
url = LLTrans::getString("RELEASE_NOTES_BASE_URL");
@@ -3267,32 +3293,32 @@ LLSD LLAppViewer::getViewerInfo() const
url += "/";
url += LLURI::escape(versionInfo.getVersion()) + ".html";
}
- info["VIEWER_RELEASE_NOTES_URL"] = url;
-
- // Position
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- LLVector3d pos = gAgent.getPositionGlobal();
- info["POSITION"] = ll_sd_from_vector3d(pos);
- info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos));
- info["REGION"] = gAgent.getRegion()->getName();
-
- boost::regex regex("\\.(secondlife|lindenlab)\\..*");
- info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getSimHostName(), regex, "");
- info["SERVER_VERSION"] = gLastVersionChannel;
- LLSLURL slurl;
- LLAgentUI::buildSLURL(slurl);
- info["SLURL"] = slurl.getSLURLString();
- }
-
- // CPU
- info["CPU"] = gSysCPU.getCPUString();
- info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().valueInUnits<LLUnits::Megabytes>());
- // Moved hack adjustment to Windows memory size into llsys.cpp
- info["OS_VERSION"] = LLOSInfo::instance().getOSString();
- info["GRAPHICS_CARD_VENDOR"] = ll_safe_string((const char*)(glGetString(GL_VENDOR)));
- info["GRAPHICS_CARD"] = ll_safe_string((const char*)(glGetString(GL_RENDERER)));
+ info["VIEWER_RELEASE_NOTES_URL"] = url;
+
+ // Position
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ LLVector3d pos = gAgent.getPositionGlobal();
+ info["POSITION"] = ll_sd_from_vector3d(pos);
+ info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos));
+ info["REGION"] = gAgent.getRegion()->getName();
+
+ boost::regex regex("\\.(secondlife|lindenlab)\\..*");
+ info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getSimHostName(), regex, "");
+ info["SERVER_VERSION"] = gLastVersionChannel;
+ LLSLURL slurl;
+ LLAgentUI::buildSLURL(slurl);
+ info["SLURL"] = slurl.getSLURLString();
+ }
+
+ // CPU
+ info["CPU"] = gSysCPU.getCPUString();
+ info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().valueInUnits<LLUnits::Megabytes>());
+ // Moved hack adjustment to Windows memory size into llsys.cpp
+ info["OS_VERSION"] = LLOSInfo::instance().getOSString();
+ info["GRAPHICS_CARD_VENDOR"] = ll_safe_string((const char*)(glGetString(GL_VENDOR)));
+ info["GRAPHICS_CARD"] = ll_safe_string((const char*)(glGetString(GL_RENDERER)));
#if LL_WINDOWS
std::string drvinfo;
@@ -3317,22 +3343,22 @@ LLSD LLAppViewer::getViewerInfo() const
drvinfo = gDXHardware.getDriverVersionWMI(LLDXHardware::GPU_ANY);
}
- if (!drvinfo.empty())
- {
- info["GRAPHICS_DRIVER_VERSION"] = drvinfo;
- }
- else
- {
- LL_WARNS("DriverVersion")<< "Cannot get driver version from getDriverVersionWMI" << LL_ENDL;
- LLSD driver_info = gDXHardware.getDisplayInfo();
- if (driver_info.has("DriverVersion"))
- {
- info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
- }
- }
+ if (!drvinfo.empty())
+ {
+ info["GRAPHICS_DRIVER_VERSION"] = drvinfo;
+ }
+ else
+ {
+ LL_WARNS("DriverVersion")<< "Cannot get driver version from getDriverVersionWMI" << LL_ENDL;
+ LLSD driver_info = gDXHardware.getDisplayInfo();
+ if (driver_info.has("DriverVersion"))
+ {
+ info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
+ }
+ }
#endif
- info["OPENGL_VERSION"] = ll_safe_string((const char*)(glGetString(GL_VERSION)));
+ info["OPENGL_VERSION"] = ll_safe_string((const char*)(glGetString(GL_VERSION)));
// Settings
@@ -3351,16 +3377,16 @@ LLSD LLAppViewer::getViewerInfo() const
info["HIDPI"] = gHiDPISupport;
#endif
- // Libraries
+ // Libraries
- info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
- bool want_fullname = true;
- info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : "Undefined";
- if(LLVoiceClient::getInstance()->voiceEnabled())
- {
+ info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
+ bool want_fullname = true;
+ info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : "Undefined";
+ if(LLVoiceClient::getInstance()->voiceEnabled())
+ {
LLVoiceVersionInfo version = LLVoiceClient::getInstance()->getVersion();
const std::string build_version = version.mBuildVersion;
- std::ostringstream version_string;
+ std::ostringstream version_string;
if (std::equal(build_version.begin(), build_version.begin() + version.serverVersion.size(),
version.serverVersion.begin()))
{ // Normal case: Show type and build version.
@@ -3370,210 +3396,210 @@ LLSD LLAppViewer::getViewerInfo() const
{ // Mismatch: Show both versions.
version_string << version.serverVersion << "/" << build_version << std::endl;
}
- info["VOICE_VERSION"] = version_string.str();
- }
- else
- {
- info["VOICE_VERSION"] = LLTrans::getString("NotConnected");
- }
+ info["VOICE_VERSION"] = version_string.str();
+ }
+ else
+ {
+ info["VOICE_VERSION"] = LLTrans::getString("NotConnected");
+ }
#if !LL_LINUX
- std::ostringstream cef_ver_codec;
- cef_ver_codec << "Dullahan: ";
- cef_ver_codec << DULLAHAN_VERSION_MAJOR;
- cef_ver_codec << ".";
- cef_ver_codec << DULLAHAN_VERSION_MINOR;
- cef_ver_codec << ".";
- cef_ver_codec << DULLAHAN_VERSION_POINT;
- cef_ver_codec << ".";
- cef_ver_codec << DULLAHAN_VERSION_BUILD;
-
- cef_ver_codec << std::endl;
- cef_ver_codec << " CEF: ";
- cef_ver_codec << CEF_VERSION;
-
- cef_ver_codec << std::endl;
- cef_ver_codec << " Chromium: ";
- cef_ver_codec << CHROME_VERSION_MAJOR;
- cef_ver_codec << ".";
- cef_ver_codec << CHROME_VERSION_MINOR;
- cef_ver_codec << ".";
- cef_ver_codec << CHROME_VERSION_BUILD;
- cef_ver_codec << ".";
- cef_ver_codec << CHROME_VERSION_PATCH;
-
- info["LIBCEF_VERSION"] = cef_ver_codec.str();
+ std::ostringstream cef_ver_codec;
+ cef_ver_codec << "Dullahan: ";
+ cef_ver_codec << DULLAHAN_VERSION_MAJOR;
+ cef_ver_codec << ".";
+ cef_ver_codec << DULLAHAN_VERSION_MINOR;
+ cef_ver_codec << ".";
+ cef_ver_codec << DULLAHAN_VERSION_POINT;
+ cef_ver_codec << ".";
+ cef_ver_codec << DULLAHAN_VERSION_BUILD;
+
+ cef_ver_codec << std::endl;
+ cef_ver_codec << " CEF: ";
+ cef_ver_codec << CEF_VERSION;
+
+ cef_ver_codec << std::endl;
+ cef_ver_codec << " Chromium: ";
+ cef_ver_codec << CHROME_VERSION_MAJOR;
+ cef_ver_codec << ".";
+ cef_ver_codec << CHROME_VERSION_MINOR;
+ cef_ver_codec << ".";
+ cef_ver_codec << CHROME_VERSION_BUILD;
+ cef_ver_codec << ".";
+ cef_ver_codec << CHROME_VERSION_PATCH;
+
+ info["LIBCEF_VERSION"] = cef_ver_codec.str();
#else
- info["LIBCEF_VERSION"] = "Undefined";
+ info["LIBCEF_VERSION"] = "Undefined";
#endif
#if !LL_LINUX
- std::ostringstream vlc_ver_codec;
- vlc_ver_codec << LIBVLC_VERSION_MAJOR;
- vlc_ver_codec << ".";
- vlc_ver_codec << LIBVLC_VERSION_MINOR;
- vlc_ver_codec << ".";
- vlc_ver_codec << LIBVLC_VERSION_REVISION;
- info["LIBVLC_VERSION"] = vlc_ver_codec.str();
+ std::ostringstream vlc_ver_codec;
+ vlc_ver_codec << LIBVLC_VERSION_MAJOR;
+ vlc_ver_codec << ".";
+ vlc_ver_codec << LIBVLC_VERSION_MINOR;
+ vlc_ver_codec << ".";
+ vlc_ver_codec << LIBVLC_VERSION_REVISION;
+ info["LIBVLC_VERSION"] = vlc_ver_codec.str();
#else
- info["LIBVLC_VERSION"] = "Undefined";
+ info["LIBVLC_VERSION"] = "Undefined";
#endif
- S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN);
- if (packets_in > 0)
- {
- info["PACKETS_LOST"] = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_LOST);
- info["PACKETS_IN"] = packets_in;
- info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal();
- }
-
- if (mServerReleaseNotesURL.empty())
- {
- if (gAgent.getRegion())
- {
- info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("RetrievingData");
- }
- else
- {
- info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("NotConnected");
- }
- }
- else if (LLStringUtil::startsWith(mServerReleaseNotesURL, "http")) // it's an URL
- {
- info["SERVER_RELEASE_NOTES_URL"] = "[" + LLWeb::escapeURL(mServerReleaseNotesURL) + " " + LLTrans::getString("ReleaseNotes") + "]";
- }
- else
- {
- info["SERVER_RELEASE_NOTES_URL"] = mServerReleaseNotesURL;
- }
+ S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN);
+ if (packets_in > 0)
+ {
+ info["PACKETS_LOST"] = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_LOST);
+ info["PACKETS_IN"] = packets_in;
+ info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal();
+ }
+
+ if (mServerReleaseNotesURL.empty())
+ {
+ if (gAgent.getRegion())
+ {
+ info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("RetrievingData");
+ }
+ else
+ {
+ info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("NotConnected");
+ }
+ }
+ else if (LLStringUtil::startsWith(mServerReleaseNotesURL, "http")) // it's an URL
+ {
+ info["SERVER_RELEASE_NOTES_URL"] = "[" + LLWeb::escapeURL(mServerReleaseNotesURL) + " " + LLTrans::getString("ReleaseNotes") + "]";
+ }
+ else
+ {
+ info["SERVER_RELEASE_NOTES_URL"] = mServerReleaseNotesURL;
+ }
// populate field for new local disk cache with some details
info["DISK_CACHE_INFO"] = LLDiskCache::getInstance()->getCacheInfo();
- return info;
+ return info;
}
std::string LLAppViewer::getViewerInfoString(bool default_string) const
{
- std::ostringstream support;
-
- LLSD info(getViewerInfo());
-
- // Render the LLSD from getInfo() as a format_map_t
- LLStringUtil::format_map_t args;
-
- // allow the "Release Notes" URL label to be localized
- args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes", default_string);
-
- for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap());
- ii != iend; ++ii)
- {
- if (! ii->second.isArray())
- {
- // Scalar value
- if (ii->second.isUndefined())
- {
- args[ii->first] = LLTrans::getString("none_text", default_string);
- }
- else
- {
- // don't forget to render value asString()
- args[ii->first] = ii->second.asString();
- }
- }
- else
- {
- // array value: build KEY_0, KEY_1 etc. entries
- for (LLSD::Integer n(0), size(ii->second.size()); n < size; ++n)
- {
- args[STRINGIZE(ii->first << '_' << n)] = ii->second[n].asString();
- }
- }
- }
-
- // Now build the various pieces
- support << LLTrans::getString("AboutHeader", args, default_string);
- if (info.has("BUILD_CONFIG"))
- {
- support << "\n" << LLTrans::getString("BuildConfig", args, default_string);
- }
- if (info.has("REGION"))
- {
- support << "\n\n" << LLTrans::getString("AboutPosition", args, default_string);
- }
- support << "\n\n" << LLTrans::getString("AboutSystem", args, default_string);
- support << "\n";
- if (info.has("GRAPHICS_DRIVER_VERSION"))
- {
- support << "\n" << LLTrans::getString("AboutDriver", args, default_string);
- }
- support << "\n" << LLTrans::getString("AboutOGL", args, default_string);
- support << "\n\n" << LLTrans::getString("AboutSettings", args, default_string);
+ std::ostringstream support;
+
+ LLSD info(getViewerInfo());
+
+ // Render the LLSD from getInfo() as a format_map_t
+ LLStringUtil::format_map_t args;
+
+ // allow the "Release Notes" URL label to be localized
+ args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes", default_string);
+
+ for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap());
+ ii != iend; ++ii)
+ {
+ if (! ii->second.isArray())
+ {
+ // Scalar value
+ if (ii->second.isUndefined())
+ {
+ args[ii->first] = LLTrans::getString("none_text", default_string);
+ }
+ else
+ {
+ // don't forget to render value asString()
+ args[ii->first] = ii->second.asString();
+ }
+ }
+ else
+ {
+ // array value: build KEY_0, KEY_1 etc. entries
+ for (LLSD::Integer n(0), size(ii->second.size()); n < size; ++n)
+ {
+ args[STRINGIZE(ii->first << '_' << n)] = ii->second[n].asString();
+ }
+ }
+ }
+
+ // Now build the various pieces
+ support << LLTrans::getString("AboutHeader", args, default_string);
+ if (info.has("BUILD_CONFIG"))
+ {
+ support << "\n" << LLTrans::getString("BuildConfig", args, default_string);
+ }
+ if (info.has("REGION"))
+ {
+ support << "\n\n" << LLTrans::getString("AboutPosition", args, default_string);
+ }
+ support << "\n\n" << LLTrans::getString("AboutSystem", args, default_string);
+ support << "\n";
+ if (info.has("GRAPHICS_DRIVER_VERSION"))
+ {
+ support << "\n" << LLTrans::getString("AboutDriver", args, default_string);
+ }
+ support << "\n" << LLTrans::getString("AboutOGL", args, default_string);
+ support << "\n\n" << LLTrans::getString("AboutSettings", args, default_string);
#if LL_DARWIN
- support << "\n" << LLTrans::getString("AboutOSXHiDPI", args, default_string);
+ support << "\n" << LLTrans::getString("AboutOSXHiDPI", args, default_string);
#endif
- support << "\n\n" << LLTrans::getString("AboutLibs", args, default_string);
- if (info.has("COMPILER"))
- {
- support << "\n" << LLTrans::getString("AboutCompiler", args, default_string);
- }
- if (info.has("PACKETS_IN"))
- {
- support << '\n' << LLTrans::getString("AboutTraffic", args, default_string);
- }
-
- // SLT timestamp
- LLSD substitution;
- substitution["datetime"] = (S32)time(NULL);//(S32)time_corrected();
- support << "\n" << LLTrans::getString("AboutTime", substitution, default_string);
-
- return support.str();
+ support << "\n\n" << LLTrans::getString("AboutLibs", args, default_string);
+ if (info.has("COMPILER"))
+ {
+ support << "\n" << LLTrans::getString("AboutCompiler", args, default_string);
+ }
+ if (info.has("PACKETS_IN"))
+ {
+ support << '\n' << LLTrans::getString("AboutTraffic", args, default_string);
+ }
+
+ // SLT timestamp
+ LLSD substitution;
+ substitution["datetime"] = (S32)time(NULL);//(S32)time_corrected();
+ support << "\n" << LLTrans::getString("AboutTime", substitution, default_string);
+
+ return support.str();
}
void LLAppViewer::cleanupSavedSettings()
{
- gSavedSettings.setBOOL("MouseSun", FALSE);
+ gSavedSettings.setBOOL("MouseSun", FALSE);
- gSavedSettings.setBOOL("UseEnergy", TRUE); // force toggle to turn off, since sends message to simulator
+ gSavedSettings.setBOOL("UseEnergy", TRUE); // force toggle to turn off, since sends message to simulator
- gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
+ gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
- gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
+ gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
- if (gDebugView)
- {
- gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible());
- }
+ if (gDebugView)
+ {
+ gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible());
+ }
- // save window position if not maximized
- // as we don't track it in callbacks
- if(NULL != gViewerWindow)
- {
- BOOL maximized = gViewerWindow->getWindow()->getMaximized();
- if (!maximized)
- {
- LLCoordScreen window_pos;
+ // save window position if not maximized
+ // as we don't track it in callbacks
+ if(NULL != gViewerWindow)
+ {
+ BOOL maximized = gViewerWindow->getWindow()->getMaximized();
+ if (!maximized)
+ {
+ LLCoordScreen window_pos;
- if (gViewerWindow->getWindow()->getPosition(&window_pos))
- {
- gSavedSettings.setS32("WindowX", window_pos.mX);
- gSavedSettings.setS32("WindowY", window_pos.mY);
- }
- }
- }
+ if (gViewerWindow->getWindow()->getPosition(&window_pos))
+ {
+ gSavedSettings.setS32("WindowX", window_pos.mX);
+ gSavedSettings.setS32("WindowY", window_pos.mY);
+ }
+ }
+ }
gSavedSettings.setF32("MapScale", LLWorldMapView::getScaleSetting());
- // Some things are cached in LLAgent.
- if (gAgent.isInitialized())
- {
- gSavedSettings.setF32("RenderFarClip", gAgentCamera.mDrawDistance);
- }
+ // Some things are cached in LLAgent.
+ if (gAgent.isInitialized())
+ {
+ gSavedSettings.setF32("RenderFarClip", gAgentCamera.mDrawDistance);
+ }
}
void LLAppViewer::removeCacheFiles(const std::string& file_mask)
{
- gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), file_mask);
+ gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), file_mask);
}
void LLAppViewer::writeSystemInfo()
@@ -3583,96 +3609,96 @@ void LLAppViewer::writeSystemInfo()
gDebugInfo["Dynamic"] = LLSD::emptyMap();
#if LL_WINDOWS && !LL_BUGSPLAT
- gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log");
+ gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log");
#else
//Not ideal but sufficient for good reporting.
gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.old"); //LLError::logFileName();
#endif
- gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel();
- gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor();
- gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor();
- gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch();
- gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild());
- gDebugInfo["ClientInfo"]["AddressSize"] = LLVersionInfo::instance().getAddressSize();
+ gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel();
+ gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor();
+ gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor();
+ gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch();
+ gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild());
+ gDebugInfo["ClientInfo"]["AddressSize"] = LLVersionInfo::instance().getAddressSize();
- gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
+ gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
- gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString();
- gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily();
- gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz();
- gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec();
- gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
- gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
+ gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString();
+ gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily();
+ gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz();
+ gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec();
+ gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
+ gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
- gDebugInfo["RAMInfo"]["Physical"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().value());
- gDebugInfo["RAMInfo"]["Allocated"] = LLSD::Integer(gMemoryAllocated.valueInUnits<LLUnits::Kilobytes>());
- gDebugInfo["OSInfo"] = LLOSInfo::instance().getOSStringSimple();
+ gDebugInfo["RAMInfo"]["Physical"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().value());
+ gDebugInfo["RAMInfo"]["Allocated"] = LLSD::Integer(gMemoryAllocated.valueInUnits<LLUnits::Kilobytes>());
+ gDebugInfo["OSInfo"] = LLOSInfo::instance().getOSStringSimple();
- // The user is not logged on yet, but record the current grid choice login url
- // which may have been the intended grid.
- gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId();
+ // The user is not logged on yet, but record the current grid choice login url
+ // which may have been the intended grid.
+ gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId();
- // *FIX:Mani - move this down in llappviewerwin32
+ // *FIX:Mani - move this down in llappviewerwin32
#ifdef LL_WINDOWS
- DWORD thread_id = GetCurrentThreadId();
- gDebugInfo["MainloopThreadID"] = (S32)thread_id;
+ DWORD thread_id = GetCurrentThreadId();
+ gDebugInfo["MainloopThreadID"] = (S32)thread_id;
#endif
#ifndef LL_BUGSPLAT
- // "CrashNotHandled" is set here, while things are running well,
- // in case of a freeze. If there is a freeze, the crash logger will be launched
- // and can read this value from the debug_info.log.
- gDebugInfo["CrashNotHandled"] = LLSD::Boolean(true);
+ // "CrashNotHandled" is set here, while things are running well,
+ // in case of a freeze. If there is a freeze, the crash logger will be launched
+ // and can read this value from the debug_info.log.
+ gDebugInfo["CrashNotHandled"] = LLSD::Boolean(true);
#else // LL_BUGSPLAT
- // "CrashNotHandled" is obsolete; it used (not very successsfully)
+ // "CrashNotHandled" is obsolete; it used (not very successsfully)
// to try to distinguish crashes from freezes - the intent here to to avoid calling it a freeze
- gDebugInfo["CrashNotHandled"] = LLSD::Boolean(false);
+ gDebugInfo["CrashNotHandled"] = LLSD::Boolean(false);
#endif // ! LL_BUGSPLAT
- // Insert crash host url (url to post crash log to) if configured. This insures
- // that the crash report will go to the proper location in the case of a
- // prior freeze.
- std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
- if(crashHostUrl != "")
- {
- gDebugInfo["CrashHostUrl"] = crashHostUrl;
- }
-
- // Dump some debugging info
- LL_INFOS("SystemInfo") << "Application: " << LLTrans::getString("APP_NAME") << LL_ENDL;
- LL_INFOS("SystemInfo") << "Version: " << LLVersionInfo::instance().getChannelAndVersion() << LL_ENDL;
-
- // Dump the local time and time zone
- time_t now;
- time(&now);
- char tbuffer[256]; /* Flawfinder: ignore */
- strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now));
- LL_INFOS("SystemInfo") << "Local time: " << tbuffer << LL_ENDL;
-
- // query some system information
- LL_INFOS("SystemInfo") << "CPU info:\n" << gSysCPU << LL_ENDL;
- LL_INFOS("SystemInfo") << "Memory info:\n" << gSysMemory << LL_ENDL;
- LL_INFOS("SystemInfo") << "OS: " << LLOSInfo::instance().getOSStringSimple() << LL_ENDL;
- LL_INFOS("SystemInfo") << "OS info: " << LLOSInfo::instance() << LL_ENDL;
+ // Insert crash host url (url to post crash log to) if configured. This insures
+ // that the crash report will go to the proper location in the case of a
+ // prior freeze.
+ std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
+ if(crashHostUrl != "")
+ {
+ gDebugInfo["CrashHostUrl"] = crashHostUrl;
+ }
+
+ // Dump some debugging info
+ LL_INFOS("SystemInfo") << "Application: " << LLTrans::getString("APP_NAME") << LL_ENDL;
+ LL_INFOS("SystemInfo") << "Version: " << LLVersionInfo::instance().getChannelAndVersion() << LL_ENDL;
+
+ // Dump the local time and time zone
+ time_t now;
+ time(&now);
+ char tbuffer[256]; /* Flawfinder: ignore */
+ strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now));
+ LL_INFOS("SystemInfo") << "Local time: " << tbuffer << LL_ENDL;
+
+ // query some system information
+ LL_INFOS("SystemInfo") << "CPU info:\n" << gSysCPU << LL_ENDL;
+ LL_INFOS("SystemInfo") << "Memory info:\n" << gSysMemory << LL_ENDL;
+ LL_INFOS("SystemInfo") << "OS: " << LLOSInfo::instance().getOSStringSimple() << LL_ENDL;
+ LL_INFOS("SystemInfo") << "OS info: " << LLOSInfo::instance() << LL_ENDL;
gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
- gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
- gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
- gDebugInfo["FirstLogin"] = LLSD::Boolean(gAgent.isFirstLogin());
- gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
+ gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
+ gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
+ gDebugInfo["FirstLogin"] = LLSD::Boolean(gAgent.isFirstLogin());
+ gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
if (gViewerWindow)
{
- std::vector<std::string> resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList();
- for (auto res_iter : resolutions)
- {
- gDebugInfo["DisplayInfo"].append(res_iter);
- }
+ std::vector<std::string> resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList();
+ for (auto res_iter : resolutions)
+ {
+ gDebugInfo["DisplayInfo"].append(res_iter);
+ }
}
- writeDebugInfo(); // Save out debug_info.log early, in case of crash.
+ writeDebugInfo(); // Save out debug_info.log early, in case of crash.
}
#ifdef LL_WINDOWS
@@ -3684,265 +3710,265 @@ void LLAppViewer::writeSystemInfo()
// TODO make this a member function.
void getFileList()
{
- std::stringstream filenames;
-
- typedef std::vector<std::string> vec;
- std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"");
- vec file_vec = gDirUtilp->getFilesInDir(pathname);
- for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter)
- {
- filenames << *iter << " ";
- if ( ( iter->length() > 30 ) && (iter->rfind(".dmp") == (iter->length()-4) ) )
- {
- std::string fullname = pathname + *iter;
- llifstream fdat( fullname.c_str(), std::ifstream::binary);
- if (fdat)
- {
- char buf[5];
- fdat.read(buf,4);
- fdat.close();
- if (!strncmp(buf,"MDMP",4))
- {
- gDebugInfo["Dynamic"]["MinidumpPath"] = fullname;
- break;
- }
- }
- }
- }
- filenames << std::endl;
- gDebugInfo["Dynamic"]["DumpDirContents"] = filenames.str();
+ std::stringstream filenames;
+
+ typedef std::vector<std::string> vec;
+ std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"");
+ vec file_vec = gDirUtilp->getFilesInDir(pathname);
+ for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter)
+ {
+ filenames << *iter << " ";
+ if ( ( iter->length() > 30 ) && (iter->rfind(".dmp") == (iter->length()-4) ) )
+ {
+ std::string fullname = pathname + *iter;
+ llifstream fdat( fullname.c_str(), std::ifstream::binary);
+ if (fdat)
+ {
+ char buf[5];
+ fdat.read(buf,4);
+ fdat.close();
+ if (!strncmp(buf,"MDMP",4))
+ {
+ gDebugInfo["Dynamic"]["MinidumpPath"] = fullname;
+ break;
+ }
+ }
+ }
+ }
+ filenames << std::endl;
+ gDebugInfo["Dynamic"]["DumpDirContents"] = filenames.str();
}
#endif
// static
void LLAppViewer::recordMarkerVersion(LLAPRFile& marker_file)
{
- std::string marker_version(LLVersionInfo::instance().getChannelAndVersion());
- if ( marker_version.length() > MAX_MARKER_LENGTH )
- {
- LL_WARNS_ONCE("MarkerFile") << "Version length ("<< marker_version.length()<< ")"
- << " greater than maximum (" << MAX_MARKER_LENGTH << ")"
- << ": marker matching may be incorrect"
- << LL_ENDL;
- }
-
- // record the viewer version in the marker file
- marker_file.write(marker_version.data(), marker_version.length());
+ std::string marker_version(LLVersionInfo::instance().getChannelAndVersion());
+ if ( marker_version.length() > MAX_MARKER_LENGTH )
+ {
+ LL_WARNS_ONCE("MarkerFile") << "Version length ("<< marker_version.length()<< ")"
+ << " greater than maximum (" << MAX_MARKER_LENGTH << ")"
+ << ": marker matching may be incorrect"
+ << LL_ENDL;
+ }
+
+ // record the viewer version in the marker file
+ marker_file.write(marker_version.data(), marker_version.length());
}
bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const
{
- bool sameVersion = false;
-
- std::string my_version(LLVersionInfo::instance().getChannelAndVersion());
- char marker_version[MAX_MARKER_LENGTH];
- S32 marker_version_length;
-
- LLAPRFile marker_file;
- marker_file.open(marker_name, LL_APR_RB);
- if (marker_file.getFileHandle())
- {
- marker_version_length = marker_file.read(marker_version, sizeof(marker_version));
- std::string marker_string(marker_version, marker_version_length);
- if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) )
- {
- sameVersion = true;
- }
- LL_DEBUGS("MarkerFile") << "Compare markers for '" << marker_name << "': "
- << "\n mine '" << my_version << "'"
- << "\n marker '" << marker_string << "'"
- << "\n " << ( sameVersion ? "same" : "different" ) << " version"
- << LL_ENDL;
- marker_file.close();
- }
- return sameVersion;
+ bool sameVersion = false;
+
+ std::string my_version(LLVersionInfo::instance().getChannelAndVersion());
+ char marker_version[MAX_MARKER_LENGTH];
+ S32 marker_version_length;
+
+ LLAPRFile marker_file;
+ marker_file.open(marker_name, LL_APR_RB);
+ if (marker_file.getFileHandle())
+ {
+ marker_version_length = marker_file.read(marker_version, sizeof(marker_version));
+ std::string marker_string(marker_version, marker_version_length);
+ if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) )
+ {
+ sameVersion = true;
+ }
+ LL_DEBUGS("MarkerFile") << "Compare markers for '" << marker_name << "': "
+ << "\n mine '" << my_version << "'"
+ << "\n marker '" << marker_string << "'"
+ << "\n " << ( sameVersion ? "same" : "different" ) << " version"
+ << LL_ENDL;
+ marker_file.close();
+ }
+ return sameVersion;
}
void LLAppViewer::processMarkerFiles()
{
- //We've got 4 things to test for here
- // - Other Process Running (SecondLife.exec_marker present, locked)
- // - Freeze (SecondLife.exec_marker present, not locked)
- // - LLError Crash (SecondLife.llerror_marker present)
- // - Other Crash (SecondLife.error_marker present)
- // These checks should also remove these files for the last 2 cases if they currently exist
-
- std::ostringstream marker_log_stream;
- bool marker_is_same_version = true;
- // first, look for the marker created at startup and deleted on a clean exit
- mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME);
- if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB))
- {
- // File exists...
- // first, read it to see if it was created by the same version (we need this later)
- marker_is_same_version = markerIsSameVersion(mMarkerFileName);
-
- // now test to see if this file is locked by a running process (try to open for write)
- marker_log_stream << "Checking exec marker file for lock...";
- mMarkerFile.open(mMarkerFileName, LL_APR_WB);
- apr_file_t* fMarker = mMarkerFile.getFileHandle() ;
- if (!fMarker)
- {
- marker_log_stream << "Exec marker file open failed - assume it is locked.";
- mSecondInstance = true; // lock means that instance is running.
- }
- else
- {
- // We were able to open it, now try to lock it ourselves...
- if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS)
- {
- marker_log_stream << "Locking exec marker failed.";
- mSecondInstance = true; // lost a race? be conservative
- }
- else
- {
- // No other instances; we've locked this file now, so record our version; delete on quit.
- recordMarkerVersion(mMarkerFile);
- marker_log_stream << "Exec marker file existed but was not locked; rewritten.";
- }
- }
- initLoggingAndGetLastDuration();
-
- std::string marker_log_msg(marker_log_stream.str());
- LL_INFOS("MarkerFile") << marker_log_msg << LL_ENDL;
-
- if (mSecondInstance)
- {
- LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' owned by another instance" << LL_ENDL;
- }
- else if (marker_is_same_version)
- {
- // the file existed, is ours, and matched our version, so we can report on what it says
- LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL;
- gLastExecEvent = LAST_EXEC_OTHER_CRASH;
- }
- else
- {
- LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found, but versions did not match" << LL_ENDL;
- }
- }
- else // marker did not exist... last exec (if any) did not freeze
- {
- initLoggingAndGetLastDuration();
- // Create the marker file for this execution & lock it; it will be deleted on a clean exit
- apr_status_t s;
- s = mMarkerFile.open(mMarkerFileName, LL_APR_WB, TRUE);
-
- if (s == APR_SUCCESS && mMarkerFile.getFileHandle())
- {
- LL_DEBUGS("MarkerFile") << "Exec marker file '"<< mMarkerFileName << "' created." << LL_ENDL;
- if (APR_SUCCESS == apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE))
- {
- recordMarkerVersion(mMarkerFile);
- LL_DEBUGS("MarkerFile") << "Exec marker file locked." << LL_ENDL;
- }
- else
- {
- LL_WARNS("MarkerFile") << "Exec marker file cannot be locked." << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("MarkerFile") << "Failed to create exec marker file '"<< mMarkerFileName << "'." << LL_ENDL;
- }
- }
-
- // now check for cases in which the exec marker may have been cleaned up by crash handlers
-
- // check for any last exec event report based on whether or not it happened during logout
- // (the logout marker is created when logout begins)
- std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
- if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB))
- {
- if (markerIsSameVersion(logout_marker_file))
- {
- gLastExecEvent = LAST_EXEC_LOGOUT_FROZE;
- LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL;
- }
- else
- {
- LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "' found, but versions did not match" << LL_ENDL;
- }
- LLAPRFile::remove(logout_marker_file);
- }
- // further refine based on whether or not a marker created during an llerr crash is found
- std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
- if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB))
- {
- if (markerIsSameVersion(llerror_marker_file))
- {
- if ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE )
- {
- gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
- LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
- }
- else
- {
- gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
- LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL;
- }
- }
- else
- {
- LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL;
- }
- LLAPRFile::remove(llerror_marker_file);
- }
- // and last refine based on whether or not a marker created during a non-llerr crash is found
- std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
- if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
- {
- if (markerIsSameVersion(error_marker_file))
- {
- if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
- {
- gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
- LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
- }
- else
- {
- gLastExecEvent = LAST_EXEC_OTHER_CRASH;
- LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
- }
- }
- else
- {
- LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL;
- }
- LLAPRFile::remove(error_marker_file);
- }
+ //We've got 4 things to test for here
+ // - Other Process Running (SecondLife.exec_marker present, locked)
+ // - Freeze (SecondLife.exec_marker present, not locked)
+ // - LLError Crash (SecondLife.llerror_marker present)
+ // - Other Crash (SecondLife.error_marker present)
+ // These checks should also remove these files for the last 2 cases if they currently exist
+
+ std::ostringstream marker_log_stream;
+ bool marker_is_same_version = true;
+ // first, look for the marker created at startup and deleted on a clean exit
+ mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME);
+ if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB))
+ {
+ // File exists...
+ // first, read it to see if it was created by the same version (we need this later)
+ marker_is_same_version = markerIsSameVersion(mMarkerFileName);
+
+ // now test to see if this file is locked by a running process (try to open for write)
+ marker_log_stream << "Checking exec marker file for lock...";
+ mMarkerFile.open(mMarkerFileName, LL_APR_WB);
+ apr_file_t* fMarker = mMarkerFile.getFileHandle() ;
+ if (!fMarker)
+ {
+ marker_log_stream << "Exec marker file open failed - assume it is locked.";
+ mSecondInstance = true; // lock means that instance is running.
+ }
+ else
+ {
+ // We were able to open it, now try to lock it ourselves...
+ if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS)
+ {
+ marker_log_stream << "Locking exec marker failed.";
+ mSecondInstance = true; // lost a race? be conservative
+ }
+ else
+ {
+ // No other instances; we've locked this file now, so record our version; delete on quit.
+ recordMarkerVersion(mMarkerFile);
+ marker_log_stream << "Exec marker file existed but was not locked; rewritten.";
+ }
+ }
+ initLoggingAndGetLastDuration();
+
+ std::string marker_log_msg(marker_log_stream.str());
+ LL_INFOS("MarkerFile") << marker_log_msg << LL_ENDL;
+
+ if (mSecondInstance)
+ {
+ LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' owned by another instance" << LL_ENDL;
+ }
+ else if (marker_is_same_version)
+ {
+ // the file existed, is ours, and matched our version, so we can report on what it says
+ LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL;
+ gLastExecEvent = LAST_EXEC_OTHER_CRASH;
+ }
+ else
+ {
+ LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found, but versions did not match" << LL_ENDL;
+ }
+ }
+ else // marker did not exist... last exec (if any) did not freeze
+ {
+ initLoggingAndGetLastDuration();
+ // Create the marker file for this execution & lock it; it will be deleted on a clean exit
+ apr_status_t s;
+ s = mMarkerFile.open(mMarkerFileName, LL_APR_WB, TRUE);
+
+ if (s == APR_SUCCESS && mMarkerFile.getFileHandle())
+ {
+ LL_DEBUGS("MarkerFile") << "Exec marker file '"<< mMarkerFileName << "' created." << LL_ENDL;
+ if (APR_SUCCESS == apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE))
+ {
+ recordMarkerVersion(mMarkerFile);
+ LL_DEBUGS("MarkerFile") << "Exec marker file locked." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "Exec marker file cannot be locked." << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "Failed to create exec marker file '"<< mMarkerFileName << "'." << LL_ENDL;
+ }
+ }
+
+ // now check for cases in which the exec marker may have been cleaned up by crash handlers
+
+ // check for any last exec event report based on whether or not it happened during logout
+ // (the logout marker is created when logout begins)
+ std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
+ if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB))
+ {
+ if (markerIsSameVersion(logout_marker_file))
+ {
+ gLastExecEvent = LAST_EXEC_LOGOUT_FROZE;
+ LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "' found, but versions did not match" << LL_ENDL;
+ }
+ LLAPRFile::remove(logout_marker_file);
+ }
+ // further refine based on whether or not a marker created during an llerr crash is found
+ std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
+ if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB))
+ {
+ if (markerIsSameVersion(llerror_marker_file))
+ {
+ if ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE )
+ {
+ gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
+ LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
+ }
+ else
+ {
+ gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
+ LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL;
+ }
+ LLAPRFile::remove(llerror_marker_file);
+ }
+ // and last refine based on whether or not a marker created during a non-llerr crash is found
+ std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
+ if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
+ {
+ if (markerIsSameVersion(error_marker_file))
+ {
+ if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
+ {
+ gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
+ LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
+ }
+ else
+ {
+ gLastExecEvent = LAST_EXEC_OTHER_CRASH;
+ LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL;
+ }
+ LLAPRFile::remove(error_marker_file);
+ }
}
void LLAppViewer::removeMarkerFiles()
{
- if (!mSecondInstance)
- {
- if (mMarkerFile.getFileHandle())
- {
- mMarkerFile.close() ;
- LLAPRFile::remove( mMarkerFileName );
- LL_DEBUGS("MarkerFile") << "removed exec marker '"<<mMarkerFileName<<"'"<< LL_ENDL;
- }
- else
- {
- LL_WARNS("MarkerFile") << "marker '"<<mMarkerFileName<<"' not open"<< LL_ENDL;
- }
-
- if (mLogoutMarkerFile.getFileHandle())
- {
- mLogoutMarkerFile.close();
- LLAPRFile::remove( mLogoutMarkerFileName );
- LL_DEBUGS("MarkerFile") << "removed logout marker '"<<mLogoutMarkerFileName<<"'"<< LL_ENDL;
- }
- else
- {
- LL_WARNS("MarkerFile") << "logout marker '"<<mLogoutMarkerFileName<<"' not open"<< LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("MarkerFile") << "leaving markers because this is a second instance" << LL_ENDL;
- }
+ if (!mSecondInstance)
+ {
+ if (mMarkerFile.getFileHandle())
+ {
+ mMarkerFile.close() ;
+ LLAPRFile::remove( mMarkerFileName );
+ LL_DEBUGS("MarkerFile") << "removed exec marker '"<<mMarkerFileName<<"'"<< LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "marker '"<<mMarkerFileName<<"' not open"<< LL_ENDL;
+ }
+
+ if (mLogoutMarkerFile.getFileHandle())
+ {
+ mLogoutMarkerFile.close();
+ LLAPRFile::remove( mLogoutMarkerFileName );
+ LL_DEBUGS("MarkerFile") << "removed logout marker '"<<mLogoutMarkerFileName<<"'"<< LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "logout marker '"<<mLogoutMarkerFileName<<"' not open"<< LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "leaving markers because this is a second instance" << LL_ENDL;
+ }
}
void LLAppViewer::removeDumpDir()
@@ -3965,212 +3991,212 @@ void LLAppViewer::removeDumpDir()
void LLAppViewer::forceQuit()
{
- LLApp::setQuitting();
+ LLApp::setQuitting();
}
//TODO: remove
void LLAppViewer::fastQuit(S32 error_code)
{
- // finish pending transfers
- flushLFSIO();
- // let sim know we're logging out
- sendLogoutRequest();
- // flush network buffers by shutting down messaging system
- end_messaging_system();
- // figure out the error code
- S32 final_error_code = error_code ? error_code : (S32)isError();
- // this isn't a crash
- removeMarkerFiles();
- // get outta here
- _exit(final_error_code);
+ // finish pending transfers
+ flushLFSIO();
+ // let sim know we're logging out
+ sendLogoutRequest();
+ // flush network buffers by shutting down messaging system
+ end_messaging_system();
+ // figure out the error code
+ S32 final_error_code = error_code ? error_code : (S32)isError();
+ // this isn't a crash
+ removeMarkerFiles();
+ // get outta here
+ _exit(final_error_code);
}
void LLAppViewer::requestQuit()
{
- LL_INFOS() << "requestQuit" << LL_ENDL;
-
- LLViewerRegion* region = gAgent.getRegion();
-
- if( (LLStartUp::getStartupState() < STATE_STARTED) || !region )
- {
- // If we have a region, make some attempt to send a logout request first.
- // This prevents the halfway-logged-in avatar from hanging around inworld for a couple minutes.
- if(region)
- {
- sendLogoutRequest();
- }
-
- // Quit immediately
- forceQuit();
- return;
- }
-
- // Try to send metrics back to the grid
- metricsSend(!gDisconnected);
-
- // Try to send last batch of avatar rez metrics.
- if (!gDisconnected && isAgentAvatarValid())
- {
- gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent.
- }
-
- LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
- effectp->setPositionGlobal(gAgent.getPositionGlobal());
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- LLHUDManager::getInstance()->sendEffects();
- effectp->markDead() ;//remove it.
-
- // Attempt to close all floaters that might be
- // editing things.
- if (gFloaterView)
- {
- // application is quitting
- gFloaterView->closeAllChildren(true);
- }
-
- // Send preferences once, when exiting
- bool include_preferences = true;
- send_viewer_stats(include_preferences);
-
- gLogoutTimer.reset();
- mQuitRequested = true;
+ LL_INFOS() << "requestQuit" << LL_ENDL;
+
+ LLViewerRegion* region = gAgent.getRegion();
+
+ if( (LLStartUp::getStartupState() < STATE_STARTED) || !region )
+ {
+ // If we have a region, make some attempt to send a logout request first.
+ // This prevents the halfway-logged-in avatar from hanging around inworld for a couple minutes.
+ if(region)
+ {
+ sendLogoutRequest();
+ }
+
+ // Quit immediately
+ forceQuit();
+ return;
+ }
+
+ // Try to send metrics back to the grid
+ metricsSend(!gDisconnected);
+
+ // Try to send last batch of avatar rez metrics.
+ if (!gDisconnected && isAgentAvatarValid())
+ {
+ gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent.
+ }
+
+ LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
+ effectp->setPositionGlobal(gAgent.getPositionGlobal());
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+ LLHUDManager::getInstance()->sendEffects();
+ effectp->markDead() ;//remove it.
+
+ // Attempt to close all floaters that might be
+ // editing things.
+ if (gFloaterView)
+ {
+ // application is quitting
+ gFloaterView->closeAllChildren(true);
+ }
+
+ // Send preferences once, when exiting
+ bool include_preferences = true;
+ send_viewer_stats(include_preferences);
+
+ gLogoutTimer.reset();
+ mQuitRequested = true;
}
static bool finish_quit(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option == 0)
- {
- LLAppViewer::instance()->requestQuit();
- }
- return false;
+ if (option == 0)
+ {
+ LLAppViewer::instance()->requestQuit();
+ }
+ return false;
}
static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_quit);
void LLAppViewer::userQuit()
{
- LL_INFOS() << "User requested quit" << LL_ENDL;
- if (gDisconnected
- || !gViewerWindow
- || !gViewerWindow->getProgressView()
- || gViewerWindow->getProgressView()->getVisible())
- {
- requestQuit();
- }
- else
- {
- LLNotificationsUtil::add("ConfirmQuit");
- }
+ LL_INFOS() << "User requested quit" << LL_ENDL;
+ if (gDisconnected
+ || !gViewerWindow
+ || !gViewerWindow->getProgressView()
+ || gViewerWindow->getProgressView()->getVisible())
+ {
+ requestQuit();
+ }
+ else
+ {
+ LLNotificationsUtil::add("ConfirmQuit");
+ }
}
static bool finish_early_exit(const LLSD& notification, const LLSD& response)
{
- LLAppViewer::instance()->forceQuit();
- return false;
+ LLAppViewer::instance()->forceQuit();
+ return false;
}
void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions)
{
- LL_WARNS() << "app_early_exit: " << name << LL_ENDL;
- gDoDisconnect = TRUE;
- LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit);
+ LL_WARNS() << "app_early_exit: " << name << LL_ENDL;
+ gDoDisconnect = TRUE;
+ LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit);
}
// case where we need the viewer to exit without any need for notifications
void LLAppViewer::earlyExitNoNotify()
{
- LL_WARNS() << "app_early_exit with no notification: " << LL_ENDL;
- gDoDisconnect = TRUE;
- finish_early_exit( LLSD(), LLSD() );
+ LL_WARNS() << "app_early_exit with no notification: " << LL_ENDL;
+ gDoDisconnect = TRUE;
+ finish_early_exit( LLSD(), LLSD() );
}
void LLAppViewer::abortQuit()
{
LL_INFOS() << "abortQuit()" << LL_ENDL;
- mQuitRequested = false;
+ mQuitRequested = false;
}
void LLAppViewer::migrateCacheDirectory()
{
#if LL_WINDOWS || LL_DARWIN
- // NOTE: (Nyx) as of 1.21, cache for mac is moving to /library/caches/SecondLife from
- // /library/application support/SecondLife/cache This should clear/delete the old dir.
-
- // As of 1.23 the Windows cache moved from
- // C:\Documents and Settings\James\Application Support\SecondLife\cache
- // to
- // C:\Documents and Settings\James\Local Settings\Application Support\SecondLife
- //
- // The Windows Vista equivalent is from
- // C:\Users\James\AppData\Roaming\SecondLife\cache
- // to
- // C:\Users\James\AppData\Local\SecondLife
- //
- // Note the absence of \cache on the second path. James.
-
- // Only do this once per fresh install of this version.
- if (gSavedSettings.getBOOL("MigrateCacheDirectory"))
- {
- gSavedSettings.setBOOL("MigrateCacheDirectory", FALSE);
-
- std::string old_cache_dir = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "cache");
- std::string new_cache_dir = gDirUtilp->getCacheDir(true);
-
- if (gDirUtilp->fileExists(old_cache_dir))
- {
- LL_INFOS() << "Migrating cache from " << old_cache_dir << " to " << new_cache_dir << LL_ENDL;
-
- // Migrate inventory cache to avoid pain to inventory database after mass update
- S32 file_count = 0;
- std::string file_name;
- std::string mask = "*.*";
-
- LLDirIterator iter(old_cache_dir, mask);
- while (iter.next(file_name))
- {
- if (file_name == "." || file_name == "..") continue;
- std::string source_path = gDirUtilp->add(old_cache_dir, file_name);
- std::string dest_path = gDirUtilp->add(new_cache_dir, file_name);
- if (!LLFile::rename(source_path, dest_path))
- {
- file_count++;
- }
- }
- LL_INFOS() << "Moved " << file_count << " files" << LL_ENDL;
-
- // Nuke the old cache
- gDirUtilp->setCacheDir(old_cache_dir);
- purgeCache();
- gDirUtilp->setCacheDir(new_cache_dir);
+ // NOTE: (Nyx) as of 1.21, cache for mac is moving to /library/caches/SecondLife from
+ // /library/application support/SecondLife/cache This should clear/delete the old dir.
+
+ // As of 1.23 the Windows cache moved from
+ // C:\Documents and Settings\James\Application Support\SecondLife\cache
+ // to
+ // C:\Documents and Settings\James\Local Settings\Application Support\SecondLife
+ //
+ // The Windows Vista equivalent is from
+ // C:\Users\James\AppData\Roaming\SecondLife\cache
+ // to
+ // C:\Users\James\AppData\Local\SecondLife
+ //
+ // Note the absence of \cache on the second path. James.
+
+ // Only do this once per fresh install of this version.
+ if (gSavedSettings.getBOOL("MigrateCacheDirectory"))
+ {
+ gSavedSettings.setBOOL("MigrateCacheDirectory", FALSE);
+
+ std::string old_cache_dir = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "cache");
+ std::string new_cache_dir = gDirUtilp->getCacheDir(true);
+
+ if (gDirUtilp->fileExists(old_cache_dir))
+ {
+ LL_INFOS() << "Migrating cache from " << old_cache_dir << " to " << new_cache_dir << LL_ENDL;
+
+ // Migrate inventory cache to avoid pain to inventory database after mass update
+ S32 file_count = 0;
+ std::string file_name;
+ std::string mask = "*.*";
+
+ LLDirIterator iter(old_cache_dir, mask);
+ while (iter.next(file_name))
+ {
+ if (file_name == "." || file_name == "..") continue;
+ std::string source_path = gDirUtilp->add(old_cache_dir, file_name);
+ std::string dest_path = gDirUtilp->add(new_cache_dir, file_name);
+ if (!LLFile::rename(source_path, dest_path))
+ {
+ file_count++;
+ }
+ }
+ LL_INFOS() << "Moved " << file_count << " files" << LL_ENDL;
+
+ // Nuke the old cache
+ gDirUtilp->setCacheDir(old_cache_dir);
+ purgeCache();
+ gDirUtilp->setCacheDir(new_cache_dir);
#if LL_DARWIN
- // Clean up Mac files not deleted by removing *.*
- std::string ds_store = old_cache_dir + "/.DS_Store";
- if (gDirUtilp->fileExists(ds_store))
- {
- LLFile::remove(ds_store);
- }
+ // Clean up Mac files not deleted by removing *.*
+ std::string ds_store = old_cache_dir + "/.DS_Store";
+ if (gDirUtilp->fileExists(ds_store))
+ {
+ LLFile::remove(ds_store);
+ }
#endif
- if (LLFile::rmdir(old_cache_dir) != 0)
- {
- LL_WARNS() << "could not delete old cache directory " << old_cache_dir << LL_ENDL;
- }
- }
- }
+ if (LLFile::rmdir(old_cache_dir) != 0)
+ {
+ LL_WARNS() << "could not delete old cache directory " << old_cache_dir << LL_ENDL;
+ }
+ }
+ }
#endif // LL_WINDOWS || LL_DARWIN
}
//static
U32 LLAppViewer::getTextureCacheVersion()
{
- // Viewer texture cache version, change if the texture cache format changes.
- // 2021-03-10 Bumping up by one to help obviate texture cache issues with
- // Simple Cache Viewer - see SL-14985 for more information
- //const U32 TEXTURE_CACHE_VERSION = 8;
- const U32 TEXTURE_CACHE_VERSION = 9;
+ // Viewer texture cache version, change if the texture cache format changes.
+ // 2021-03-10 Bumping up by one to help obviate texture cache issues with
+ // Simple Cache Viewer - see SL-14985 for more information
+ //const U32 TEXTURE_CACHE_VERSION = 8;
+ const U32 TEXTURE_CACHE_VERSION = 9;
- return TEXTURE_CACHE_VERSION ;
+ return TEXTURE_CACHE_VERSION ;
}
//static
@@ -4185,92 +4211,92 @@ U32 LLAppViewer::getDiskCacheVersion()
//static
U32 LLAppViewer::getObjectCacheVersion()
{
- // Viewer object cache version, change if object update
- // format changes. JC
- const U32 INDRA_OBJECT_CACHE_VERSION = 17;
+ // Viewer object cache version, change if object update
+ // format changes. JC
+ const U32 INDRA_OBJECT_CACHE_VERSION = 17;
- return INDRA_OBJECT_CACHE_VERSION;
+ return INDRA_OBJECT_CACHE_VERSION;
}
bool LLAppViewer::initCache()
{
- mPurgeCache = false;
- BOOL read_only = mSecondInstance ? TRUE : FALSE;
- LLAppViewer::getTextureCache()->setReadOnly(read_only) ;
- LLVOCache::initParamSingleton(read_only);
+ mPurgeCache = false;
+ BOOL read_only = mSecondInstance ? TRUE : FALSE;
+ LLAppViewer::getTextureCache()->setReadOnly(read_only) ;
+ LLVOCache::initParamSingleton(read_only);
- // initialize the new disk cache using saved settings
- const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName");
+ // initialize the new disk cache using saved settings
+ const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName");
- const U32 MB = 1024 * 1024;
+ const U32 MB = 1024 * 1024;
const uintmax_t MIN_CACHE_SIZE = 256 * MB;
- const uintmax_t MAX_CACHE_SIZE = 9984ll * MB;
+ const uintmax_t MAX_CACHE_SIZE = 9984ll * MB;
const uintmax_t setting_cache_total_size = uintmax_t(gSavedSettings.getU32("CacheSize")) * MB;
const uintmax_t cache_total_size = llclamp(setting_cache_total_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE);
const F64 disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal");
const F64 texture_cache_percent = 100.0 - disk_cache_percent;
- // note that the maximum size of this cache is defined as a percentage of the
- // total cache size - the 'CacheSize' pref - for all caches.
+ // note that the maximum size of this cache is defined as a percentage of the
+ // total cache size - the 'CacheSize' pref - for all caches.
const uintmax_t disk_cache_size = uintmax_t(cache_total_size * disk_cache_percent / 100);
- const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo");
+ const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo");
- bool texture_cache_mismatch = false;
+ bool texture_cache_mismatch = false;
bool remove_vfs_files = false;
- if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion())
- {
- texture_cache_mismatch = true;
- if(!read_only)
- {
- gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion());
+ if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion())
+ {
+ texture_cache_mismatch = true;
+ if(!read_only)
+ {
+ gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion());
//texture cache version was bumped up in Simple Cache Viewer, and at this point old vfs files are not needed
- remove_vfs_files = true;
- }
- }
-
- if(!read_only)
- {
- // Purge cache if user requested it
- if (gSavedSettings.getBOOL("PurgeCacheOnStartup") ||
- gSavedSettings.getBOOL("PurgeCacheOnNextStartup"))
- {
- LL_INFOS("AppCache") << "Startup cache purge requested: " << (gSavedSettings.getBOOL("PurgeCacheOnStartup") ? "ALWAYS" : "ONCE") << LL_ENDL;
- gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false);
- mPurgeCache = true;
- // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad
- texture_cache_mismatch = true;
- }
-
- // We have moved the location of the cache directory over time.
- migrateCacheDirectory();
-
- // Setup and verify the cache location
- std::string cache_location = gSavedSettings.getString("CacheLocation");
- std::string new_cache_location = gSavedSettings.getString("NewCacheLocation");
- if (new_cache_location != cache_location)
- {
- LL_INFOS("AppCache") << "Cache location changed, cache needs purging" << LL_ENDL;
- gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
- purgeCache(); // purge old cache
- gDirUtilp->deleteDirAndContents(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name));
- gSavedSettings.setString("CacheLocation", new_cache_location);
- gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location));
- }
- }
-
- if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")))
- {
- LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL;
- gSavedSettings.setString("CacheLocation", "");
- gSavedSettings.setString("CacheLocationTopFolder", "");
- }
-
- const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name);
+ remove_vfs_files = true;
+ }
+ }
+
+ if(!read_only)
+ {
+ // Purge cache if user requested it
+ if (gSavedSettings.getBOOL("PurgeCacheOnStartup") ||
+ gSavedSettings.getBOOL("PurgeCacheOnNextStartup"))
+ {
+ LL_INFOS("AppCache") << "Startup cache purge requested: " << (gSavedSettings.getBOOL("PurgeCacheOnStartup") ? "ALWAYS" : "ONCE") << LL_ENDL;
+ gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false);
+ mPurgeCache = true;
+ // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad
+ texture_cache_mismatch = true;
+ }
+
+ // We have moved the location of the cache directory over time.
+ migrateCacheDirectory();
+
+ // Setup and verify the cache location
+ std::string cache_location = gSavedSettings.getString("CacheLocation");
+ std::string new_cache_location = gSavedSettings.getString("NewCacheLocation");
+ if (new_cache_location != cache_location)
+ {
+ LL_INFOS("AppCache") << "Cache location changed, cache needs purging" << LL_ENDL;
+ gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
+ purgeCache(); // purge old cache
+ gDirUtilp->deleteDirAndContents(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name));
+ gSavedSettings.setString("CacheLocation", new_cache_location);
+ gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location));
+ }
+ }
+
+ if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")))
+ {
+ LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL;
+ gSavedSettings.setString("CacheLocation", "");
+ gSavedSettings.setString("CacheLocationTopFolder", "");
+ }
+
+ const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name);
LLDiskCache::initParamSingleton(cache_dir, disk_cache_size, enable_cache_debug_info);
- if (!read_only)
- {
+ if (!read_only)
+ {
if (gSavedSettings.getS32("DiskCacheVersion") != LLAppViewer::getDiskCacheVersion())
{
LLDiskCache::getInstance()->clearCache();
@@ -4282,166 +4308,166 @@ bool LLAppViewer::initCache()
{
LLDiskCache::getInstance()->removeOldVFSFiles();
}
-
+
if (mPurgeCache)
- {
- LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
- purgeCache();
-
- // clear the new C++ file system based cache
- LLDiskCache::getInstance()->clearCache();
- }
- else
- {
- // purge excessive files from the new file system based cache
- LLDiskCache::getInstance()->purge();
- }
- }
- LLAppViewer::getPurgeDiskCacheThread()->start();
-
- LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache"));
-
- // Init the texture cache
+ {
+ LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
+ purgeCache();
+
+ // clear the new C++ file system based cache
+ LLDiskCache::getInstance()->clearCache();
+ }
+ else
+ {
+ // purge excessive files from the new file system based cache
+ LLDiskCache::getInstance()->purge();
+ }
+ }
+ LLAppViewer::getPurgeDiskCacheThread()->start();
+
+ LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache"));
+
+ // Init the texture cache
// Allocate the remaining percent which is not allocated to the disk cache
const S64 texture_cache_size = S64(cache_total_size * texture_cache_percent / 100);
LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
- LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion());
+ LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion());
return true;
}
void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb)
{
- gMainloopWork.post(cb);
+ gMainloopWork.post(cb);
}
void LLAppViewer::loadKeyBindings()
{
- std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml");
- if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))
- {
- // Failed to load custom bindings, try default ones
- key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml");
- if (!gViewerInput.loadBindingsXML(key_bindings_file))
- {
+ std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml");
+ if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))
+ {
+ // Failed to load custom bindings, try default ones
+ key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml");
+ if (!gViewerInput.loadBindingsXML(key_bindings_file))
+ {
LLError::LLUserWarningMsg::showMissingFiles();
- LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;
- }
- }
+ LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;
+ }
+ }
LLUrlRegistry::instance().setKeybindingHandler(&gViewerInput);
}
void LLAppViewer::purgeCache()
{
- LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL;
- LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE);
- LLVOCache::getInstance()->removeCache(LL_PATH_CACHE);
- LLViewerShaderMgr::instance()->clearShaderCache();
- std::string browser_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "cef_cache");
- if (LLFile::isdir(browser_cache))
- {
- // cef does not support clear_cache and clear_cookies, so clear what we can manually.
- gDirUtilp->deleteDirAndContents(browser_cache);
- }
- gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*");
+ LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL;
+ LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE);
+ LLVOCache::getInstance()->removeCache(LL_PATH_CACHE);
+ LLViewerShaderMgr::instance()->clearShaderCache();
+ std::string browser_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "cef_cache");
+ if (LLFile::isdir(browser_cache))
+ {
+ // cef does not support clear_cache and clear_cookies, so clear what we can manually.
+ gDirUtilp->deleteDirAndContents(browser_cache);
+ }
+ gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*");
}
//purge cache immediately, do not wait until the next login.
void LLAppViewer::purgeCacheImmediate()
{
- LL_INFOS("AppCache") << "Purging Object Cache and Texture Cache immediately..." << LL_ENDL;
- LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE, false);
- LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true);
+ LL_INFOS("AppCache") << "Purging Object Cache and Texture Cache immediately..." << LL_ENDL;
+ LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE, false);
+ LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true);
}
std::string LLAppViewer::getSecondLifeTitle() const
{
- return LLTrans::getString("APP_NAME");
+ return LLTrans::getString("APP_NAME");
}
std::string LLAppViewer::getWindowTitle() const
{
- return gWindowTitle;
+ return gWindowTitle;
}
// Callback from a dialog indicating user was logged out.
bool finish_disconnect(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (1 == option)
- {
+ if (1 == option)
+ {
LLAppViewer::instance()->forceQuit();
- }
- return false;
+ }
+ return false;
}
// Callback from an early disconnect dialog, force an exit
bool finish_forced_disconnect(const LLSD& notification, const LLSD& response)
{
- LLAppViewer::instance()->forceQuit();
- return false;
+ LLAppViewer::instance()->forceQuit();
+ return false;
}
void LLAppViewer::forceDisconnect(const std::string& mesg)
{
- if (gDoDisconnect)
- {
- // Already popped up one of these dialogs, don't
- // do this again.
- return;
- }
-
- // *TODO: Translate the message if possible
- std::string big_reason = LLAgent::sTeleportErrorMessages[mesg];
- if ( big_reason.size() == 0 )
- {
- big_reason = mesg;
- }
-
- LLSD args;
- gDoDisconnect = TRUE;
-
- if (LLStartUp::getStartupState() < STATE_STARTED)
- {
- // Tell users what happened
- args["ERROR_MESSAGE"] = big_reason;
- LLNotificationsUtil::add("ErrorMessage", args, LLSD(), &finish_forced_disconnect);
- }
- else
- {
- args["MESSAGE"] = big_reason;
- LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect );
- }
+ if (gDoDisconnect)
+ {
+ // Already popped up one of these dialogs, don't
+ // do this again.
+ return;
+ }
+
+ // *TODO: Translate the message if possible
+ std::string big_reason = LLAgent::sTeleportErrorMessages[mesg];
+ if ( big_reason.size() == 0 )
+ {
+ big_reason = mesg;
+ }
+
+ LLSD args;
+ gDoDisconnect = TRUE;
+
+ if (LLStartUp::getStartupState() < STATE_STARTED)
+ {
+ // Tell users what happened
+ args["ERROR_MESSAGE"] = big_reason;
+ LLNotificationsUtil::add("ErrorMessage", args, LLSD(), &finish_forced_disconnect);
+ }
+ else
+ {
+ args["MESSAGE"] = big_reason;
+ LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect );
+ }
}
void LLAppViewer::badNetworkHandler()
{
- // Dump the packet
- gMessageSystem->dumpPacketToLog();
-
- // Flush all of our caches on exit in the case of disconnect due to
- // invalid packets.
-
- mPurgeCacheOnExit = TRUE;
-
- std::ostringstream message;
- message <<
- "The viewer has detected mangled network data indicative\n"
- "of a bad upstream network connection or an incomplete\n"
- "local installation of " << LLAppViewer::instance()->getSecondLifeTitle() << ". \n"
- " \n"
- "Try uninstalling and reinstalling to see if this resolves \n"
- "the issue. \n"
- " \n"
- "If the problem continues, see the Tech Support FAQ at: \n"
- "www.secondlife.com/support";
- forceDisconnect(message.str());
-
- LLApp::instance()->writeMiniDump();
+ // Dump the packet
+ gMessageSystem->dumpPacketToLog();
+
+ // Flush all of our caches on exit in the case of disconnect due to
+ // invalid packets.
+
+ mPurgeCacheOnExit = TRUE;
+
+ std::ostringstream message;
+ message <<
+ "The viewer has detected mangled network data indicative\n"
+ "of a bad upstream network connection or an incomplete\n"
+ "local installation of " << LLAppViewer::instance()->getSecondLifeTitle() << ". \n"
+ " \n"
+ "Try uninstalling and reinstalling to see if this resolves \n"
+ "the issue. \n"
+ " \n"
+ "If the problem continues, see the Tech Support FAQ at: \n"
+ "www.secondlife.com/support";
+ forceDisconnect(message.str());
+
+ LLApp::instance()->writeMiniDump();
}
// This routine may get called more than once during the shutdown process.
@@ -4449,93 +4475,93 @@ void LLAppViewer::badNetworkHandler()
// is destroyed.
void LLAppViewer::saveFinalSnapshot()
{
- if (!mSavedFinalSnapshot)
- {
- gSavedSettings.setVector3d("FocusPosOnLogout", gAgentCamera.calcFocusPositionTargetGlobal());
- gSavedSettings.setVector3d("CameraPosOnLogout", gAgentCamera.calcCameraPositionTargetGlobal());
- gViewerWindow->setCursor(UI_CURSOR_WAIT);
- gAgentCamera.changeCameraToThirdPerson( FALSE ); // don't animate, need immediate switch
- gSavedSettings.setBOOL("ShowParcelOwners", FALSE);
- idle();
-
- std::string snap_filename = gDirUtilp->getLindenUserDir();
- snap_filename += gDirUtilp->getDirDelimiter();
- snap_filename += LLStartUp::getScreenLastFilename();
- // use full pixel dimensions of viewer window (not post-scale dimensions)
- gViewerWindow->saveSnapshot(snap_filename,
- gViewerWindow->getWindowWidthRaw(),
- gViewerWindow->getWindowHeightRaw(),
- FALSE,
- gSavedSettings.getBOOL("RenderHUDInSnapshot"),
- TRUE,
- LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
- LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
- mSavedFinalSnapshot = TRUE;
-
- if (gAgent.isInHomeRegion())
- {
- LLVector3d home;
- if (gAgent.getHomePosGlobal(&home) && dist_vec(home, gAgent.getPositionGlobal()) < 10)
- {
- // We are at home position or close to it, see if we need to create home screenshot
- // Notes:
- // 1. It might be beneficial to also replace home if file is too old
- // 2. This is far from best way/place to update screenshot since location might be not fully loaded,
- // but we don't have many options
- std::string snap_home = gDirUtilp->getLindenUserDir();
- snap_home += gDirUtilp->getDirDelimiter();
- snap_home += LLStartUp::getScreenHomeFilename();
- if (!gDirUtilp->fileExists(snap_home))
- {
- // We are at home position yet no home image exist, fix it
- LLFile::copy(snap_filename, snap_home);
- }
- }
- }
- }
+ if (!mSavedFinalSnapshot)
+ {
+ gSavedSettings.setVector3d("FocusPosOnLogout", gAgentCamera.calcFocusPositionTargetGlobal());
+ gSavedSettings.setVector3d("CameraPosOnLogout", gAgentCamera.calcCameraPositionTargetGlobal());
+ gViewerWindow->setCursor(UI_CURSOR_WAIT);
+ gAgentCamera.changeCameraToThirdPerson( FALSE ); // don't animate, need immediate switch
+ gSavedSettings.setBOOL("ShowParcelOwners", FALSE);
+ idle();
+
+ std::string snap_filename = gDirUtilp->getLindenUserDir();
+ snap_filename += gDirUtilp->getDirDelimiter();
+ snap_filename += LLStartUp::getScreenLastFilename();
+ // use full pixel dimensions of viewer window (not post-scale dimensions)
+ gViewerWindow->saveSnapshot(snap_filename,
+ gViewerWindow->getWindowWidthRaw(),
+ gViewerWindow->getWindowHeightRaw(),
+ FALSE,
+ gSavedSettings.getBOOL("RenderHUDInSnapshot"),
+ TRUE,
+ LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
+ LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
+ mSavedFinalSnapshot = TRUE;
+
+ if (gAgent.isInHomeRegion())
+ {
+ LLVector3d home;
+ if (gAgent.getHomePosGlobal(&home) && dist_vec(home, gAgent.getPositionGlobal()) < 10)
+ {
+ // We are at home position or close to it, see if we need to create home screenshot
+ // Notes:
+ // 1. It might be beneficial to also replace home if file is too old
+ // 2. This is far from best way/place to update screenshot since location might be not fully loaded,
+ // but we don't have many options
+ std::string snap_home = gDirUtilp->getLindenUserDir();
+ snap_home += gDirUtilp->getDirDelimiter();
+ snap_home += LLStartUp::getScreenHomeFilename();
+ if (!gDirUtilp->fileExists(snap_home))
+ {
+ // We are at home position yet no home image exist, fix it
+ LLFile::copy(snap_filename, snap_home);
+ }
+ }
+ }
+ }
}
void LLAppViewer::loadNameCache()
{
- // display names cache
- std::string filename =
- gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
- LL_INFOS("AvNameCache") << filename << LL_ENDL;
- llifstream name_cache_stream(filename.c_str());
- if(name_cache_stream.is_open())
- {
- if ( ! LLAvatarNameCache::getInstance()->importFile(name_cache_stream))
+ // display names cache
+ std::string filename =
+ gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+ LL_INFOS("AvNameCache") << filename << LL_ENDL;
+ llifstream name_cache_stream(filename.c_str());
+ if(name_cache_stream.is_open())
+ {
+ if ( ! LLAvatarNameCache::getInstance()->importFile(name_cache_stream))
{
LL_WARNS("AppInit") << "removing invalid '" << filename << "'" << LL_ENDL;
name_cache_stream.close();
LLFile::remove(filename);
}
- }
+ }
- if (!gCacheName) return;
+ if (!gCacheName) return;
- std::string name_cache;
- name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
- llifstream cache_file(name_cache.c_str());
- if(cache_file.is_open())
- {
- if(gCacheName->importFile(cache_file)) return;
- }
+ std::string name_cache;
+ name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
+ llifstream cache_file(name_cache.c_str());
+ if(cache_file.is_open())
+ {
+ if(gCacheName->importFile(cache_file)) return;
+ }
}
void LLAppViewer::saveNameCache()
{
- // display names cache
- std::string filename =
- gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
- llofstream name_cache_stream(filename.c_str());
- if(name_cache_stream.is_open())
- {
- LLAvatarNameCache::getInstance()->exportFile(name_cache_stream);
+ // display names cache
+ std::string filename =
+ gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+ llofstream name_cache_stream(filename.c_str());
+ if(name_cache_stream.is_open())
+ {
+ LLAvatarNameCache::getInstance()->exportFile(name_cache_stream);
}
// real names cache
- if (gCacheName)
+ if (gCacheName)
{
std::string name_cache;
name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
@@ -4544,24 +4570,24 @@ void LLAppViewer::saveNameCache()
{
gCacheName->exportFile(cache_file);
}
- }
+ }
}
-/*! @brief This class is an LLFrameTimer that can be created with
- an elapsed time that starts counting up from the given value
- rather than 0.0.
+/*! @brief This class is an LLFrameTimer that can be created with
+ an elapsed time that starts counting up from the given value
+ rather than 0.0.
- Otherwise it behaves the same way as LLFrameTimer.
+ Otherwise it behaves the same way as LLFrameTimer.
*/
class LLFrameStatsTimer : public LLFrameTimer
{
public:
- LLFrameStatsTimer(F64 elapsed_already = 0.0)
- : LLFrameTimer()
- {
- mStartTime -= elapsed_already;
- }
+ LLFrameStatsTimer(F64 elapsed_already = 0.0)
+ : LLFrameTimer()
+ {
+ mStartTime -= elapsed_already;
+ }
};
static LLTrace::BlockTimerStatHandle FTM_AUDIO_UPDATE("Update Audio");
@@ -4587,118 +4613,118 @@ static LLTrace::BlockTimerStatHandle FTM_HUD_EFFECTS("HUD Effects");
void LLAppViewer::idle()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
- pingMainloopTimeout("Main:Idle");
+ pingMainloopTimeout("Main:Idle");
- // Update frame timers
- static LLTimer idle_timer;
+ // Update frame timers
+ static LLTimer idle_timer;
- LLFrameTimer::updateFrameTime();
- LLFrameTimer::updateFrameCount();
- LLEventTimer::updateClass();
+ LLFrameTimer::updateFrameTime();
+ LLFrameTimer::updateFrameCount();
+ LLEventTimer::updateClass();
LLPerfStats::updateClass();
- // LLApp::stepFrame() performs the above three calls plus mRunner.run().
- // Not sure why we don't call stepFrame() here, except that LLRunner seems
- // completely redundant with LLEventTimer.
- LLNotificationsUI::LLToast::updateClass();
- LLSmoothInterpolation::updateInterpolants();
- LLMortician::updateClass();
- LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify()
- LLDirPickerThread::clearDead();
- F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
+ // LLApp::stepFrame() performs the above three calls plus mRunner.run().
+ // Not sure why we don't call stepFrame() here, except that LLRunner seems
+ // completely redundant with LLEventTimer.
+ LLNotificationsUI::LLToast::updateClass();
+ LLSmoothInterpolation::updateInterpolants();
+ LLMortician::updateClass();
+ LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify()
+ LLDirPickerThread::clearDead();
+ F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
LLGLTFMaterialList::flushUpdates();
- // Service the WorkQueue we use for replies from worker threads.
- // Use function statics for the timeslice setting so we only have to fetch
- // and convert MainWorkTime once.
- static F32 MainWorkTimeRaw = gSavedSettings.getF32("MainWorkTime");
- static F32Milliseconds MainWorkTimeMs(MainWorkTimeRaw);
- // MainWorkTime is specified in fractional milliseconds, but std::chrono
- // uses integer representations. What if we want less than a microsecond?
- // Use nanoseconds. We're very sure we will never need to specify a
- // MainWorkTime that would be larger than we could express in
- // std::chrono::nanoseconds.
- static std::chrono::nanoseconds MainWorkTimeNanoSec{
- std::chrono::nanoseconds::rep(MainWorkTimeMs.value() * 1000000)};
- gMainloopWork.runFor(MainWorkTimeNanoSec);
-
- // Cap out-of-control frame times
- // Too low because in menus, swapping, debugger, etc.
- // Too high because idle called with no objects in view, etc.
- const F32 MIN_FRAME_RATE = 1.f;
- const F32 MAX_FRAME_RATE = 200.f;
-
- F32 frame_rate_clamped = 1.f / dt_raw;
- frame_rate_clamped = llclamp(frame_rate_clamped, MIN_FRAME_RATE, MAX_FRAME_RATE);
- gFrameDTClamped = 1.f / frame_rate_clamped;
-
- // Global frame timer
- // Smoothly weight toward current frame
- gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f;
-
- F32 qas = gSavedSettings.getF32("QuitAfterSeconds");
- if (qas > 0.f)
- {
- if (gRenderStartTime.getElapsedTimeF32() > qas)
- {
- LL_INFOS() << "Quitting after " << qas << " seconds. See setting \"QuitAfterSeconds\"." << LL_ENDL;
- LLAppViewer::instance()->forceQuit();
- }
- }
-
- // Must wait until both have avatar object and mute list, so poll
- // here.
- LLIMProcessing::requestOfflineMessages();
-
- ///////////////////////////////////
- //
- // Special case idle if still starting up
- //
- if (LLStartUp::getStartupState() < STATE_STARTED)
- {
- // Skip rest if idle startup returns false (essentially, no world yet)
- gGLActive = TRUE;
- if (!idle_startup())
- {
- gGLActive = FALSE;
- return;
- }
- gGLActive = FALSE;
- }
-
-
- F32 yaw = 0.f; // radians
-
- if (!gDisconnected)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("network"); //LL_RECORD_BLOCK_TIME(FTM_NETWORK);
- // Update spaceserver timeinfo
- LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + LLUnits::Seconds::fromValue(dt_raw));
-
-
- //////////////////////////////////////
- //
- // Update simulator agent state
- //
-
- if (gSavedSettings.getBOOL("RotateRight"))
- {
- gAgent.moveYaw(-1.f);
- }
-
- {
+ // Service the WorkQueue we use for replies from worker threads.
+ // Use function statics for the timeslice setting so we only have to fetch
+ // and convert MainWorkTime once.
+ static F32 MainWorkTimeRaw = gSavedSettings.getF32("MainWorkTime");
+ static F32Milliseconds MainWorkTimeMs(MainWorkTimeRaw);
+ // MainWorkTime is specified in fractional milliseconds, but std::chrono
+ // uses integer representations. What if we want less than a microsecond?
+ // Use nanoseconds. We're very sure we will never need to specify a
+ // MainWorkTime that would be larger than we could express in
+ // std::chrono::nanoseconds.
+ static std::chrono::nanoseconds MainWorkTimeNanoSec{
+ std::chrono::nanoseconds::rep(MainWorkTimeMs.value() * 1000000)};
+ gMainloopWork.runFor(MainWorkTimeNanoSec);
+
+ // Cap out-of-control frame times
+ // Too low because in menus, swapping, debugger, etc.
+ // Too high because idle called with no objects in view, etc.
+ const F32 MIN_FRAME_RATE = 1.f;
+ const F32 MAX_FRAME_RATE = 200.f;
+
+ F32 frame_rate_clamped = 1.f / dt_raw;
+ frame_rate_clamped = llclamp(frame_rate_clamped, MIN_FRAME_RATE, MAX_FRAME_RATE);
+ gFrameDTClamped = 1.f / frame_rate_clamped;
+
+ // Global frame timer
+ // Smoothly weight toward current frame
+ gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f;
+
+ F32 qas = gSavedSettings.getF32("QuitAfterSeconds");
+ if (qas > 0.f)
+ {
+ if (gRenderStartTime.getElapsedTimeF32() > qas)
+ {
+ LL_INFOS() << "Quitting after " << qas << " seconds. See setting \"QuitAfterSeconds\"." << LL_ENDL;
+ LLAppViewer::instance()->forceQuit();
+ }
+ }
+
+ // Must wait until both have avatar object and mute list, so poll
+ // here.
+ LLIMProcessing::requestOfflineMessages();
+
+ ///////////////////////////////////
+ //
+ // Special case idle if still starting up
+ //
+ if (LLStartUp::getStartupState() < STATE_STARTED)
+ {
+ // Skip rest if idle startup returns false (essentially, no world yet)
+ gGLActive = TRUE;
+ if (!idle_startup())
+ {
+ gGLActive = FALSE;
+ return;
+ }
+ gGLActive = FALSE;
+ }
+
+
+ F32 yaw = 0.f; // radians
+
+ if (!gDisconnected)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("network"); //LL_RECORD_BLOCK_TIME(FTM_NETWORK);
+ // Update spaceserver timeinfo
+ LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + LLUnits::Seconds::fromValue(dt_raw));
+
+
+ //////////////////////////////////////
+ //
+ // Update simulator agent state
+ //
+
+ if (gSavedSettings.getBOOL("RotateRight"))
+ {
+ gAgent.moveYaw(-1.f);
+ }
+
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Autopilot");
- // Handle automatic walking towards points
- gAgentPilot.updateTarget();
- gAgent.autoPilot(&yaw);
- }
+ // Handle automatic walking towards points
+ gAgentPilot.updateTarget();
+ gAgent.autoPilot(&yaw);
+ }
- static LLFrameTimer agent_update_timer;
+ static LLFrameTimer agent_update_timer;
- // When appropriate, update agent location to the simulator.
- F32 agent_update_time = agent_update_timer.getElapsedTimeF32();
- F32 agent_force_update_time = mLastAgentForceUpdate + agent_update_time;
+ // When appropriate, update agent location to the simulator.
+ F32 agent_update_time = agent_update_timer.getElapsedTimeF32();
+ F32 agent_force_update_time = mLastAgentForceUpdate + agent_update_time;
bool timed_out = agent_update_time > (1.0f / (F32)AGENT_UPDATES_PER_SECOND);
BOOL force_send =
// if there is something to send
@@ -4709,111 +4735,111 @@ void LLAppViewer::idle()
|| (agent_force_update_time > (1.0f / (F32) AGENT_FORCE_UPDATES_PER_SECOND));
// timing out doesn't warranty that an update will be sent,
// just that it will be checked.
- if (force_send || timed_out)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
- // Send avatar and camera info
- mLastAgentControlFlags = gAgent.getControlFlags();
- mLastAgentForceUpdate = force_send ? 0 : agent_force_update_time;
- send_agent_update(force_send);
- agent_update_timer.reset();
- }
- }
-
- //////////////////////////////////////
- //
- // Manage statistics
- //
- //
- {
- // Initialize the viewer_stats_timer with an already elapsed time
- // of SEND_STATS_PERIOD so that the initial stats report will
- // be sent immediately.
- static LLFrameStatsTimer viewer_stats_timer(SEND_STATS_PERIOD);
-
- // Update session stats every large chunk of time
- // *FIX: (?) SAMANTHA
- if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected)
- {
- LL_INFOS() << "Transmitting sessions stats" << LL_ENDL;
- bool include_preferences = false;
- send_viewer_stats(include_preferences);
- viewer_stats_timer.reset();
- }
-
- // Print the object debugging stats
- static LLFrameTimer object_debug_timer;
- if (object_debug_timer.getElapsedTimeF32() > 5.f)
- {
- object_debug_timer.reset();
- if (gObjectList.mNumDeadObjectUpdates)
- {
- LL_INFOS() << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << LL_ENDL;
- gObjectList.mNumDeadObjectUpdates = 0;
- }
- if (gObjectList.mNumUnknownUpdates)
- {
- LL_INFOS() << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << LL_ENDL;
- gObjectList.mNumUnknownUpdates = 0;
- }
-
- }
- }
-
- if (!gDisconnected)
- {
+ if (force_send || timed_out)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ // Send avatar and camera info
+ mLastAgentControlFlags = gAgent.getControlFlags();
+ mLastAgentForceUpdate = force_send ? 0 : agent_force_update_time;
+ send_agent_update(force_send);
+ agent_update_timer.reset();
+ }
+ }
+
+ //////////////////////////////////////
+ //
+ // Manage statistics
+ //
+ //
+ {
+ // Initialize the viewer_stats_timer with an already elapsed time
+ // of SEND_STATS_PERIOD so that the initial stats report will
+ // be sent immediately.
+ static LLFrameStatsTimer viewer_stats_timer(SEND_STATS_PERIOD);
+
+ // Update session stats every large chunk of time
+ // *FIX: (?) SAMANTHA
+ if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected)
+ {
+ LL_INFOS() << "Transmitting sessions stats" << LL_ENDL;
+ bool include_preferences = false;
+ send_viewer_stats(include_preferences);
+ viewer_stats_timer.reset();
+ }
+
+ // Print the object debugging stats
+ static LLFrameTimer object_debug_timer;
+ if (object_debug_timer.getElapsedTimeF32() > 5.f)
+ {
+ object_debug_timer.reset();
+ if (gObjectList.mNumDeadObjectUpdates)
+ {
+ LL_INFOS() << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << LL_ENDL;
+ gObjectList.mNumDeadObjectUpdates = 0;
+ }
+ if (gObjectList.mNumUnknownUpdates)
+ {
+ LL_INFOS() << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << LL_ENDL;
+ gObjectList.mNumUnknownUpdates = 0;
+ }
+
+ }
+ }
+
+ if (!gDisconnected)
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Network");
- ////////////////////////////////////////////////
- //
- // Network processing
- //
- // NOTE: Starting at this point, we may still have pointers to "dead" objects
- // floating throughout the various object lists.
- //
- idleNameCache();
- idleNetwork();
+ ////////////////////////////////////////////////
+ //
+ // Network processing
+ //
+ // NOTE: Starting at this point, we may still have pointers to "dead" objects
+ // floating throughout the various object lists.
+ //
+ idleNameCache();
+ idleNetwork();
- // Check for away from keyboard, kick idle agents.
- idle_afk_check();
+ // Check for away from keyboard, kick idle agents.
+ idle_afk_check();
- // Update statistics for this frame
- update_statistics();
- }
+ // Update statistics for this frame
+ update_statistics();
+ }
- ////////////////////////////////////////
- //
- // Handle the regular UI idle callbacks as well as
- // hover callbacks
- //
+ ////////////////////////////////////////
+ //
+ // Handle the regular UI idle callbacks as well as
+ // hover callbacks
+ //
#ifdef LL_DARWIN
- if (!mQuitRequested) //MAINT-4243
+ if (!mQuitRequested) //MAINT-4243
#endif
- {
-// LL_RECORD_BLOCK_TIME(FTM_IDLE_CB);
+ {
+// LL_RECORD_BLOCK_TIME(FTM_IDLE_CB);
- // Do event notifications if necessary. Yes, we may want to move this elsewhere.
- gEventNotifier.update();
+ // Do event notifications if necessary. Yes, we may want to move this elsewhere.
+ gEventNotifier.update();
- gIdleCallbacks.callFunctions();
- gInventory.idleNotifyObservers();
- LLAvatarTracker::instance().idleNotifyObservers();
- }
+ gIdleCallbacks.callFunctions();
+ gInventory.idleNotifyObservers();
+ LLAvatarTracker::instance().idleNotifyObservers();
+ }
- // Metrics logging (LLViewerAssetStats, etc.)
- {
- static LLTimer report_interval;
+ // Metrics logging (LLViewerAssetStats, etc.)
+ {
+ static LLTimer report_interval;
- // *TODO: Add configuration controls for this
- F32 seconds = report_interval.getElapsedTimeF32();
- if (seconds >= app_metrics_interval)
- {
- metricsSend(! gDisconnected);
- report_interval.reset();
- }
- }
+ // *TODO: Add configuration controls for this
+ F32 seconds = report_interval.getElapsedTimeF32();
+ if (seconds >= app_metrics_interval)
+ {
+ metricsSend(! gDisconnected);
+ report_interval.reset();
+ }
+ }
// Update layonts, handle mouse events, tooltips, e t c
@@ -4822,335 +4848,335 @@ void LLAppViewer::idle()
// opening chat.
gViewerWindow->updateUI();
- if (gDisconnected)
+ if (gDisconnected)
{
- return;
+ return;
}
- if (gTeleportDisplay)
+ if (gTeleportDisplay)
{
- return;
+ return;
}
- ///////////////////////////////////////
- // Agent and camera movement
- //
- LLCoordGL current_mouse = gViewerWindow->getCurrentMouse();
+ ///////////////////////////////////////
+ // Agent and camera movement
+ //
+ LLCoordGL current_mouse = gViewerWindow->getCurrentMouse();
- {
- // After agent and camera moved, figure out if we need to
- // deselect objects.
- LLSelectMgr::getInstance()->deselectAllIfTooFar();
+ {
+ // After agent and camera moved, figure out if we need to
+ // deselect objects.
+ LLSelectMgr::getInstance()->deselectAllIfTooFar();
- }
+ }
- {
- // Handle pending gesture processing
- LL_RECORD_BLOCK_TIME(FTM_AGENT_POSITION);
- LLGestureMgr::instance().update();
+ {
+ // Handle pending gesture processing
+ LL_RECORD_BLOCK_TIME(FTM_AGENT_POSITION);
+ LLGestureMgr::instance().update();
- gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY);
- }
+ gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY);
+ }
- {
- LL_RECORD_BLOCK_TIME(FTM_OBJECTLIST_UPDATE);
+ {
+ LL_RECORD_BLOCK_TIME(FTM_OBJECTLIST_UPDATE);
if (!(logoutRequestSent() && hasSavedFinalSnapshot()))
- {
- gObjectList.update(gAgent);
- }
- }
-
- //////////////////////////////////////
- //
- // Deletes objects...
- // Has to be done after doing idleUpdates (which can kill objects)
- //
-
- {
- LL_RECORD_BLOCK_TIME(FTM_CLEANUP);
- {
- gObjectList.cleanDeadObjects();
- }
- {
- LL_RECORD_BLOCK_TIME(FTM_CLEANUP_DRAWABLES);
- LLDrawable::cleanupDeadDrawables();
- }
- }
-
- //
- // After this point, in theory we should never see a dead object
- // in the various object/drawable lists.
- //
-
- //////////////////////////////////////
- //
- // Update/send HUD effects
- //
- // At this point, HUD effects may clean up some references to
- // dead objects.
- //
-
- {
- LL_RECORD_BLOCK_TIME(FTM_HUD_EFFECTS);
- LLSelectMgr::getInstance()->updateEffects();
- LLHUDManager::getInstance()->cleanupEffects();
- LLHUDManager::getInstance()->sendEffects();
- }
-
- ////////////////////////////////////////
- //
- // Unpack layer data that we've received
- //
-
- {
- LL_RECORD_BLOCK_TIME(FTM_NETWORK);
- gVLManager.unpackData();
- }
-
- /////////////////////////
- //
- // Update surfaces, and surface textures as well.
- //
-
- LLWorld::getInstance()->updateVisibilities();
- {
- const F32 max_region_update_time = .001f; // 1ms
- LL_RECORD_BLOCK_TIME(FTM_REGION_UPDATE);
- LLWorld::getInstance()->updateRegions(max_region_update_time);
- }
-
- /////////////////////////
- //
- // Update weather effects
- //
-
- // Update wind vector
- LLVector3 wind_position_region;
- static LLVector3 average_wind;
-
- LLViewerRegion *regionp;
- regionp = LLWorld::getInstance()->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal()); // puts agent's local coords into wind_position
- if (regionp)
- {
- gWindVec = regionp->mWind.getVelocity(wind_position_region);
-
- // Compute average wind and use to drive motion of water
-
- average_wind = regionp->mWind.getAverage();
- gSky.setWind(average_wind);
- //LLVOWater::setWind(average_wind);
- }
- else
- {
- gWindVec.setVec(0.0f, 0.0f, 0.0f);
- }
-
- //////////////////////////////////////
- //
- // Sort and cull in the new renderer are moved to pipeline.cpp
- // Here, particles are updated and drawables are moved.
- //
-
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP("world update"); //LL_RECORD_BLOCK_TIME(FTM_WORLD_UPDATE);
- gPipeline.updateMove();
- }
-
- LLWorld::getInstance()->updateParticles();
-
- if (gAgentPilot.isPlaying() && gAgentPilot.getOverrideCamera())
- {
- gAgentPilot.moveCamera();
- }
- else if (LLViewerJoystick::getInstance()->getOverrideCamera())
- {
- LLViewerJoystick::getInstance()->moveFlycam();
- }
- else
- {
- if (LLToolMgr::getInstance()->inBuildMode())
- {
- LLViewerJoystick::getInstance()->moveObjects();
- }
-
- gAgentCamera.updateCamera();
- }
-
- // update media focus
- LLViewerMediaFocus::getInstance()->update();
-
- // Update marketplace
- LLMarketplaceInventoryImporter::update();
- LLMarketplaceInventoryNotifications::update();
-
- // objects and camera should be in sync, do LOD calculations now
- {
- LL_RECORD_BLOCK_TIME(FTM_LOD_UPDATE);
- gObjectList.updateApparentAngles(gAgent);
- }
-
- // Update AV render info
- LLAvatarRenderInfoAccountant::getInstance()->idle();
-
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP("audio update"); //LL_RECORD_BLOCK_TIME(FTM_AUDIO_UPDATE);
-
- if (gAudiop)
- {
- audio_update_volume(false);
- audio_update_listener();
- audio_update_wind(false);
-
- // this line actually commits the changes we've made to source positions, etc.
- gAudiop->idle();
- }
- }
-
- // Handle shutdown process, for example,
- // wait for floaters to close, send quit message,
- // forcibly quit if it has taken too long
- if (mQuitRequested)
- {
- gGLActive = TRUE;
- idleShutdown();
- }
+ {
+ gObjectList.update(gAgent);
+ }
+ }
+
+ //////////////////////////////////////
+ //
+ // Deletes objects...
+ // Has to be done after doing idleUpdates (which can kill objects)
+ //
+
+ {
+ LL_RECORD_BLOCK_TIME(FTM_CLEANUP);
+ {
+ gObjectList.cleanDeadObjects();
+ }
+ {
+ LL_RECORD_BLOCK_TIME(FTM_CLEANUP_DRAWABLES);
+ LLDrawable::cleanupDeadDrawables();
+ }
+ }
+
+ //
+ // After this point, in theory we should never see a dead object
+ // in the various object/drawable lists.
+ //
+
+ //////////////////////////////////////
+ //
+ // Update/send HUD effects
+ //
+ // At this point, HUD effects may clean up some references to
+ // dead objects.
+ //
+
+ {
+ LL_RECORD_BLOCK_TIME(FTM_HUD_EFFECTS);
+ LLSelectMgr::getInstance()->updateEffects();
+ LLHUDManager::getInstance()->cleanupEffects();
+ LLHUDManager::getInstance()->sendEffects();
+ }
+
+ ////////////////////////////////////////
+ //
+ // Unpack layer data that we've received
+ //
+
+ {
+ LL_RECORD_BLOCK_TIME(FTM_NETWORK);
+ gVLManager.unpackData();
+ }
+
+ /////////////////////////
+ //
+ // Update surfaces, and surface textures as well.
+ //
+
+ LLWorld::getInstance()->updateVisibilities();
+ {
+ const F32 max_region_update_time = .001f; // 1ms
+ LL_RECORD_BLOCK_TIME(FTM_REGION_UPDATE);
+ LLWorld::getInstance()->updateRegions(max_region_update_time);
+ }
+
+ /////////////////////////
+ //
+ // Update weather effects
+ //
+
+ // Update wind vector
+ LLVector3 wind_position_region;
+ static LLVector3 average_wind;
+
+ LLViewerRegion *regionp;
+ regionp = LLWorld::getInstance()->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal()); // puts agent's local coords into wind_position
+ if (regionp)
+ {
+ gWindVec = regionp->mWind.getVelocity(wind_position_region);
+
+ // Compute average wind and use to drive motion of water
+
+ average_wind = regionp->mWind.getAverage();
+ gSky.setWind(average_wind);
+ //LLVOWater::setWind(average_wind);
+ }
+ else
+ {
+ gWindVec.setVec(0.0f, 0.0f, 0.0f);
+ }
+
+ //////////////////////////////////////
+ //
+ // Sort and cull in the new renderer are moved to pipeline.cpp
+ // Here, particles are updated and drawables are moved.
+ //
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("world update"); //LL_RECORD_BLOCK_TIME(FTM_WORLD_UPDATE);
+ gPipeline.updateMove();
+ }
+
+ LLWorld::getInstance()->updateParticles();
+
+ if (gAgentPilot.isPlaying() && gAgentPilot.getOverrideCamera())
+ {
+ gAgentPilot.moveCamera();
+ }
+ else if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ {
+ LLViewerJoystick::getInstance()->moveFlycam();
+ }
+ else
+ {
+ if (LLToolMgr::getInstance()->inBuildMode())
+ {
+ LLViewerJoystick::getInstance()->moveObjects();
+ }
+
+ gAgentCamera.updateCamera();
+ }
+
+ // update media focus
+ LLViewerMediaFocus::getInstance()->update();
+
+ // Update marketplace
+ LLMarketplaceInventoryImporter::update();
+ LLMarketplaceInventoryNotifications::update();
+
+ // objects and camera should be in sync, do LOD calculations now
+ {
+ LL_RECORD_BLOCK_TIME(FTM_LOD_UPDATE);
+ gObjectList.updateApparentAngles(gAgent);
+ }
+
+ // Update AV render info
+ LLAvatarRenderInfoAccountant::getInstance()->idle();
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("audio update"); //LL_RECORD_BLOCK_TIME(FTM_AUDIO_UPDATE);
+
+ if (gAudiop)
+ {
+ audio_update_volume(false);
+ audio_update_listener();
+ audio_update_wind(false);
+
+ // this line actually commits the changes we've made to source positions, etc.
+ gAudiop->idle();
+ }
+ }
+
+ // Handle shutdown process, for example,
+ // wait for floaters to close, send quit message,
+ // forcibly quit if it has taken too long
+ if (mQuitRequested)
+ {
+ gGLActive = TRUE;
+ idleShutdown();
+ }
}
void LLAppViewer::idleShutdown()
{
- // Wait for all modal alerts to get resolved
- if (LLModalDialog::activeCount() > 0)
- {
- return;
- }
-
- // close IM interface
- if(gIMMgr)
- {
- gIMMgr->disconnectAllSessions();
- }
-
- // Wait for all floaters to get resolved
- if (gFloaterView
- && !gFloaterView->allChildrenClosed())
- {
- return;
- }
-
-
-
-
- // ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup()
- // *TODO: ugly
- static bool saved_teleport_history = false;
- if (!saved_teleport_history)
- {
- saved_teleport_history = true;
- LLTeleportHistory::getInstance()->dump();
- LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this
- return;
- }
-
- static bool saved_snapshot = false;
- if (!saved_snapshot)
- {
- saved_snapshot = true;
- saveFinalSnapshot();
- return;
- }
-
- const F32 SHUTDOWN_UPLOAD_SAVE_TIME = 5.f;
-
- S32 pending_uploads = gAssetStorage->getNumPendingUploads();
- if (pending_uploads > 0
- && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
- && !logoutRequestSent())
- {
- static S32 total_uploads = 0;
- // Sometimes total upload count can change during logout.
- total_uploads = llmax(total_uploads, pending_uploads);
- gViewerWindow->setShowProgress(TRUE);
- S32 finished_uploads = total_uploads - pending_uploads;
- F32 percent = 100.f * finished_uploads / total_uploads;
- gViewerWindow->setProgressPercent(percent);
- gViewerWindow->setProgressString(LLTrans::getString("SavingSettings"));
- return;
- }
-
- if (gPendingMetricsUploads > 0
- && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
- && !logoutRequestSent())
- {
- gViewerWindow->setShowProgress(TRUE);
- gViewerWindow->setProgressPercent(100.f);
- gViewerWindow->setProgressString(LLTrans::getString("LoggingOut"));
- return;
- }
-
- // All floaters are closed. Tell server we want to quit.
- if( !logoutRequestSent() )
- {
- sendLogoutRequest();
-
- // Wait for a LogoutReply message
+ // Wait for all modal alerts to get resolved
+ if (LLModalDialog::activeCount() > 0)
+ {
+ return;
+ }
+
+ // close IM interface
+ if(gIMMgr)
+ {
+ gIMMgr->disconnectAllSessions();
+ }
+
+ // Wait for all floaters to get resolved
+ if (gFloaterView
+ && !gFloaterView->allChildrenClosed())
+ {
+ return;
+ }
+
+
+
+
+ // ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup()
+ // *TODO: ugly
+ static bool saved_teleport_history = false;
+ if (!saved_teleport_history)
+ {
+ saved_teleport_history = true;
+ LLTeleportHistory::getInstance()->dump();
+ LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this
+ return;
+ }
+
+ static bool saved_snapshot = false;
+ if (!saved_snapshot)
+ {
+ saved_snapshot = true;
+ saveFinalSnapshot();
+ return;
+ }
+
+ const F32 SHUTDOWN_UPLOAD_SAVE_TIME = 5.f;
+
+ S32 pending_uploads = gAssetStorage->getNumPendingUploads();
+ if (pending_uploads > 0
+ && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
+ && !logoutRequestSent())
+ {
+ static S32 total_uploads = 0;
+ // Sometimes total upload count can change during logout.
+ total_uploads = llmax(total_uploads, pending_uploads);
+ gViewerWindow->setShowProgress(TRUE);
+ S32 finished_uploads = total_uploads - pending_uploads;
+ F32 percent = 100.f * finished_uploads / total_uploads;
+ gViewerWindow->setProgressPercent(percent);
+ gViewerWindow->setProgressString(LLTrans::getString("SavingSettings"));
+ return;
+ }
+
+ if (gPendingMetricsUploads > 0
+ && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
+ && !logoutRequestSent())
+ {
gViewerWindow->setShowProgress(TRUE);
gViewerWindow->setProgressPercent(100.f);
gViewerWindow->setProgressString(LLTrans::getString("LoggingOut"));
- return;
- }
-
- // Make sure that we quit if we haven't received a reply from the server.
- if( logoutRequestSent()
- && gLogoutTimer.getElapsedTimeF32() > gLogoutMaxTime )
- {
- forceQuit();
- return;
- }
+ return;
+ }
+
+ // All floaters are closed. Tell server we want to quit.
+ if( !logoutRequestSent() )
+ {
+ sendLogoutRequest();
+
+ // Wait for a LogoutReply message
+ gViewerWindow->setShowProgress(TRUE);
+ gViewerWindow->setProgressPercent(100.f);
+ gViewerWindow->setProgressString(LLTrans::getString("LoggingOut"));
+ return;
+ }
+
+ // Make sure that we quit if we haven't received a reply from the server.
+ if( logoutRequestSent()
+ && gLogoutTimer.getElapsedTimeF32() > gLogoutMaxTime )
+ {
+ forceQuit();
+ return;
+ }
}
void LLAppViewer::sendLogoutRequest()
{
- if(!mLogoutRequestSent && gMessageSystem)
- {
- //Set internal status variables and marker files before actually starting the logout process
- gLogoutInProgress = TRUE;
- if (!mSecondInstance)
- {
- mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
-
- mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB);
- if (mLogoutMarkerFile.getFileHandle())
- {
- LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL;
- recordMarkerVersion(mLogoutMarkerFile);
- }
- else
- {
- LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL;
- }
- }
- else
- {
- LL_INFOS("MarkerFile") << "Did not logout marker file because this is a second instance" << LL_ENDL;
- }
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_LogoutRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gAgent.sendReliableMessage();
-
- gLogoutTimer.reset();
- gLogoutMaxTime = LOGOUT_REQUEST_TIME;
- mLogoutRequestSent = TRUE;
-
- if(LLVoiceClient::instanceExists())
- {
- LLVoiceClient::getInstance()->leaveChannel();
- }
- }
+ if(!mLogoutRequestSent && gMessageSystem)
+ {
+ //Set internal status variables and marker files before actually starting the logout process
+ gLogoutInProgress = TRUE;
+ if (!mSecondInstance)
+ {
+ mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
+
+ mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB);
+ if (mLogoutMarkerFile.getFileHandle())
+ {
+ LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL;
+ recordMarkerVersion(mLogoutMarkerFile);
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_INFOS("MarkerFile") << "Did not logout marker file because this is a second instance" << LL_ENDL;
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_LogoutRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gAgent.sendReliableMessage();
+
+ gLogoutTimer.reset();
+ gLogoutMaxTime = LOGOUT_REQUEST_TIME;
+ mLogoutRequestSent = TRUE;
+
+ if(LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->leaveChannel();
+ }
+ }
}
void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * regionp)
@@ -5196,19 +5222,19 @@ void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * regionp)
void LLAppViewer::idleNameCache()
{
- // Neither old nor new name cache can function before agent has a region
- LLViewerRegion* region = gAgent.getRegion();
+ // Neither old nor new name cache can function before agent has a region
+ LLViewerRegion* region = gAgent.getRegion();
if (!region)
{
return;
}
- // deal with any queued name requests and replies.
- gCacheName->processPending();
+ // deal with any queued name requests and replies.
+ gCacheName->processPending();
- // Can't run the new cache until we have the list of capabilities
- // for the agent region, and can therefore decide whether to use
- // display names or fall back to the old name system.
+ // Can't run the new cache until we have the list of capabilities
+ // for the agent region, and can therefore decide whether to use
+ // display names or fall back to the old name system.
if (!region->capabilitiesReceived())
{
return;
@@ -5238,141 +5264,141 @@ static LLTrace::BlockTimerStatHandle FTM_CHECK_REGION_CIRCUIT("Check Region Circ
void LLAppViewer::idleNetwork()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
- pingMainloopTimeout("idleNetwork");
-
- gObjectList.mNumNewObjects = 0;
- S32 total_decoded = 0;
-
- if (!gSavedSettings.getBOOL("SpeedTest"))
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("idle network"); //LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode
-
- LLTimer check_message_timer;
- // Read all available packets from network
- const S64 frame_count = gFrameCount; // U32->S64
- F32 total_time = 0.0f;
-
- {
- LockMessageChecker lmc(gMessageSystem);
- while (lmc.checkAllMessages(frame_count, gServicePump))
- {
- if (gDoDisconnect)
- {
- // We're disconnecting, don't process any more messages from the server
- // We're usually disconnecting due to either network corruption or a
- // server going down, so this is OK.
- break;
- }
-
- total_decoded++;
- gPacketsIn++;
-
- if (total_decoded > MESSAGE_MAX_PER_FRAME)
- {
- break;
- }
+ pingMainloopTimeout("idleNetwork");
+
+ gObjectList.mNumNewObjects = 0;
+ S32 total_decoded = 0;
+
+ if (!gSavedSettings.getBOOL("SpeedTest"))
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("idle network"); //LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode
+
+ LLTimer check_message_timer;
+ // Read all available packets from network
+ const S64 frame_count = gFrameCount; // U32->S64
+ F32 total_time = 0.0f;
+
+ {
+ LockMessageChecker lmc(gMessageSystem);
+ while (lmc.checkAllMessages(frame_count, gServicePump))
+ {
+ if (gDoDisconnect)
+ {
+ // We're disconnecting, don't process any more messages from the server
+ // We're usually disconnecting due to either network corruption or a
+ // server going down, so this is OK.
+ break;
+ }
+
+ total_decoded++;
+ gPacketsIn++;
+
+ if (total_decoded > MESSAGE_MAX_PER_FRAME)
+ {
+ break;
+ }
#ifdef TIME_THROTTLE_MESSAGES
- // Prevent slow packets from completely destroying the frame rate.
- // This usually happens due to clumps of avatars taking huge amount
- // of network processing time (which needs to be fixed, but this is
- // a good limit anyway).
- total_time = check_message_timer.getElapsedTimeF32();
- if (total_time >= CheckMessagesMaxTime)
- break;
+ // Prevent slow packets from completely destroying the frame rate.
+ // This usually happens due to clumps of avatars taking huge amount
+ // of network processing time (which needs to be fixed, but this is
+ // a good limit anyway).
+ total_time = check_message_timer.getElapsedTimeF32();
+ if (total_time >= CheckMessagesMaxTime)
+ break;
#endif
- }
+ }
- // Handle per-frame message system processing.
- lmc.processAcks(gSavedSettings.getF32("AckCollectTime"));
- }
+ // Handle per-frame message system processing.
+ lmc.processAcks(gSavedSettings.getF32("AckCollectTime"));
+ }
#ifdef TIME_THROTTLE_MESSAGES
- if (total_time >= CheckMessagesMaxTime)
- {
- // Increase CheckMessagesMaxTime so that we will eventually catch up
- CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames
- }
- else
- {
- // Reset CheckMessagesMaxTime to default value
- CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
- }
+ if (total_time >= CheckMessagesMaxTime)
+ {
+ // Increase CheckMessagesMaxTime so that we will eventually catch up
+ CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames
+ }
+ else
+ {
+ // Reset CheckMessagesMaxTime to default value
+ CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
+ }
#endif
- // we want to clear the control after sending out all necessary agent updates
- gAgent.resetControlFlags();
-
- // Decode enqueued messages...
- S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
-
- if( remaining_possible_decodes <= 0 )
- {
- LL_INFOS() << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << LL_ENDL;
- }
-
- if (gPrintMessagesThisFrame)
- {
- LL_INFOS() << "Decoded " << total_decoded << " msgs this frame!" << LL_ENDL;
- gPrintMessagesThisFrame = FALSE;
- }
- }
- add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects);
-
- // Retransmit unacknowledged packets.
- gXferManager->retransmitUnackedPackets();
- gAssetStorage->checkForTimeouts();
- gViewerThrottle.updateDynamicThrottle();
-
- // Check that the circuit between the viewer and the agent's current
- // region is still alive
- LLViewerRegion *agent_region = gAgent.getRegion();
- if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED))
- {
- LLUUID this_region_id = agent_region->getRegionID();
- bool this_region_alive = agent_region->isAlive();
- if ((mAgentRegionLastAlive && !this_region_alive) // newly dead
- && (mAgentRegionLastID == this_region_id)) // same region
- {
- forceDisconnect(LLTrans::getString("AgentLostConnection"));
- }
- mAgentRegionLastID = this_region_id;
- mAgentRegionLastAlive = this_region_alive;
- }
+ // we want to clear the control after sending out all necessary agent updates
+ gAgent.resetControlFlags();
+
+ // Decode enqueued messages...
+ S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
+
+ if( remaining_possible_decodes <= 0 )
+ {
+ LL_INFOS() << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << LL_ENDL;
+ }
+
+ if (gPrintMessagesThisFrame)
+ {
+ LL_INFOS() << "Decoded " << total_decoded << " msgs this frame!" << LL_ENDL;
+ gPrintMessagesThisFrame = FALSE;
+ }
+ }
+ add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects);
+
+ // Retransmit unacknowledged packets.
+ gXferManager->retransmitUnackedPackets();
+ gAssetStorage->checkForTimeouts();
+ gViewerThrottle.updateDynamicThrottle();
+
+ // Check that the circuit between the viewer and the agent's current
+ // region is still alive
+ LLViewerRegion *agent_region = gAgent.getRegion();
+ if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED))
+ {
+ LLUUID this_region_id = agent_region->getRegionID();
+ bool this_region_alive = agent_region->isAlive();
+ if ((mAgentRegionLastAlive && !this_region_alive) // newly dead
+ && (mAgentRegionLastID == this_region_id)) // same region
+ {
+ forceDisconnect(LLTrans::getString("AgentLostConnection"));
+ }
+ mAgentRegionLastID = this_region_id;
+ mAgentRegionLastAlive = this_region_alive;
+ }
}
void LLAppViewer::disconnectViewer()
{
- if (gDisconnected)
- {
- return;
- }
- //
- // Cleanup after quitting.
- //
- // Save snapshot for next time, if we made it through initialization
-
- LL_INFOS() << "Disconnecting viewer!" << LL_ENDL;
-
- // Dump our frame statistics
-
- // Remember if we were flying
- gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() );
-
- // Un-minimize all windows so they don't get saved minimized
- if (gFloaterView)
- {
- gFloaterView->restoreAll();
- }
-
- if (LLSelectMgr::instanceExists())
- {
- LLSelectMgr::getInstance()->deselectAll();
- }
-
- // save inventory if appropriate
+ if (gDisconnected)
+ {
+ return;
+ }
+ //
+ // Cleanup after quitting.
+ //
+ // Save snapshot for next time, if we made it through initialization
+
+ LL_INFOS() << "Disconnecting viewer!" << LL_ENDL;
+
+ // Dump our frame statistics
+
+ // Remember if we were flying
+ gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() );
+
+ // Un-minimize all windows so they don't get saved minimized
+ if (gFloaterView)
+ {
+ gFloaterView->restoreAll();
+ }
+
+ if (LLSelectMgr::instanceExists())
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ }
+
+ // save inventory if appropriate
if (gInventory.isInventoryUsable()
&& gAgent.getID().notNull()) // Shouldn't be null at this stage
{
@@ -5387,44 +5413,44 @@ void LLAppViewer::disconnectViewer()
}
}
- saveNameCache();
- if (LLExperienceCache::instanceExists())
- {
- // TODO: LLExperienceCache::cleanup() logic should be moved to
- // cleanupSingleton().
- LLExperienceCache::instance().cleanup();
- }
+ saveNameCache();
+ if (LLExperienceCache::instanceExists())
+ {
+ // TODO: LLExperienceCache::cleanup() logic should be moved to
+ // cleanupSingleton().
+ LLExperienceCache::instance().cleanup();
+ }
- // close inventory interface, close all windows
- LLSidepanelInventory::cleanup();
+ // close inventory interface, close all windows
+ LLSidepanelInventory::cleanup();
- gAgentWearables.cleanup();
- gAgentCamera.cleanup();
- // Also writes cached agent settings to gSavedSettings
- gAgent.cleanup();
+ gAgentWearables.cleanup();
+ gAgentCamera.cleanup();
+ // Also writes cached agent settings to gSavedSettings
+ gAgent.cleanup();
- // This is where we used to call gObjectList.destroy() and then delete gWorldp.
- // Now we just ask the LLWorld singleton to cleanly shut down.
- if(LLWorld::instanceExists())
- {
- LLWorld::getInstance()->resetClass();
- }
- LLVOCache::deleteSingleton();
+ // This is where we used to call gObjectList.destroy() and then delete gWorldp.
+ // Now we just ask the LLWorld singleton to cleanly shut down.
+ if(LLWorld::instanceExists())
+ {
+ LLWorld::getInstance()->resetClass();
+ }
+ LLVOCache::deleteSingleton();
- // call all self-registered classes
- LLDestroyClassList::instance().fireCallbacks();
+ // call all self-registered classes
+ LLDestroyClassList::instance().fireCallbacks();
- cleanup_xfer_manager();
- gDisconnected = TRUE;
+ cleanup_xfer_manager();
+ gDisconnected = TRUE;
- // Pass the connection state to LLUrlEntryParcel not to attempt
- // parcel info requests while disconnected.
- LLUrlEntryParcel::setDisconnected(gDisconnected);
+ // Pass the connection state to LLUrlEntryParcel not to attempt
+ // parcel info requests while disconnected.
+ LLUrlEntryParcel::setDisconnected(gDisconnected);
}
void LLAppViewer::forceErrorLLError()
{
- LL_ERRS() << "This is a deliberate llerror" << LL_ENDL;
+ LL_ERRS() << "This is a deliberate llerror" << LL_ENDL;
}
void LLAppViewer::forceErrorLLErrorMsg()
@@ -5437,7 +5463,7 @@ void LLAppViewer::forceErrorLLErrorMsg()
void LLAppViewer::forceErrorBreakpoint()
{
- LL_WARNS() << "Forcing a deliberate breakpoint" << LL_ENDL;
+ LL_WARNS() << "Forcing a deliberate breakpoint" << LL_ENDL;
#ifdef LL_WINDOWS
DebugBreak();
#else
@@ -5448,7 +5474,7 @@ void LLAppViewer::forceErrorBreakpoint()
void LLAppViewer::forceErrorBadMemoryAccess()
{
- LL_WARNS() << "Forcing a deliberate bad memory access" << LL_ENDL;
+ LL_WARNS() << "Forcing a deliberate bad memory access" << LL_ENDL;
S32* crash = NULL;
*crash = 0xDEADBEEF;
return;
@@ -5456,7 +5482,7 @@ void LLAppViewer::forceErrorBadMemoryAccess()
void LLAppViewer::forceErrorInfiniteLoop()
{
- LL_WARNS() << "Forcing a deliberate infinite loop" << LL_ENDL;
+ LL_WARNS() << "Forcing a deliberate infinite loop" << LL_ENDL;
// Loop is intentionally complicated to fool basic loop detection
LLTimer timer_total;
LLTimer timer_expiry;
@@ -5475,7 +5501,7 @@ void LLAppViewer::forceErrorInfiniteLoop()
void LLAppViewer::forceErrorSoftwareException()
{
- LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL;
+ LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL;
LLTHROW(LLException("User selected Force Software Exception"));
}
@@ -5488,8 +5514,8 @@ void LLAppViewer::forceErrorOSSpecificException()
void LLAppViewer::forceErrorDriverCrash()
{
- LL_WARNS() << "Forcing a deliberate driver crash" << LL_ENDL;
- glDeleteTextures(1, NULL);
+ LL_WARNS() << "Forcing a deliberate driver crash" << LL_ENDL;
+ glDeleteTextures(1, NULL);
}
void LLAppViewer::forceErrorCoroutineCrash()
@@ -5521,120 +5547,120 @@ void LLAppViewer::forceErrorThreadCrash()
void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
{
- if(!mMainloopTimeout)
- {
- mMainloopTimeout = new LLWatchdogTimeout();
- resumeMainloopTimeout(state, secs);
- }
+ if(!mMainloopTimeout)
+ {
+ mMainloopTimeout = new LLWatchdogTimeout();
+ resumeMainloopTimeout(state, secs);
+ }
}
void LLAppViewer::destroyMainloopTimeout()
{
- if(mMainloopTimeout)
- {
- delete mMainloopTimeout;
- mMainloopTimeout = NULL;
- }
+ if(mMainloopTimeout)
+ {
+ delete mMainloopTimeout;
+ mMainloopTimeout = NULL;
+ }
}
void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
{
- if(mMainloopTimeout)
- {
- if(secs < 0.0f)
- {
- static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
- secs = mainloop_timeout;
- }
-
- mMainloopTimeout->setTimeout(secs);
- mMainloopTimeout->start(state);
- }
+ if(mMainloopTimeout)
+ {
+ if(secs < 0.0f)
+ {
+ static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
+ secs = mainloop_timeout;
+ }
+
+ mMainloopTimeout->setTimeout(secs);
+ mMainloopTimeout->start(state);
+ }
}
void LLAppViewer::pauseMainloopTimeout()
{
- if(mMainloopTimeout)
- {
- mMainloopTimeout->stop();
- }
+ if(mMainloopTimeout)
+ {
+ mMainloopTimeout->stop();
+ }
}
void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
- if(mMainloopTimeout)
- {
- if(secs < 0.0f)
- {
- static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
- secs = mainloop_timeout;
- }
-
- mMainloopTimeout->setTimeout(secs);
- mMainloopTimeout->ping(state);
- }
+ if(mMainloopTimeout)
+ {
+ if(secs < 0.0f)
+ {
+ static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
+ secs = mainloop_timeout;
+ }
+
+ mMainloopTimeout->setTimeout(secs);
+ mMainloopTimeout->ping(state);
+ }
}
void LLAppViewer::handleLoginComplete()
{
- gLoggedInTime.start();
- initMainloopTimeout("Mainloop Init");
-
- // Store some data to DebugInfo in case of a freeze.
- gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel();
-
- gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor();
- gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor();
- gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch();
- gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild());
-
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if ( parcel && parcel->getMusicURL()[0])
- {
- gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
- }
- if ( parcel && parcel->getMediaURL()[0])
- {
- gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
- }
-
- gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
- gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
- gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
- gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
-
- if(gAgent.getRegion())
- {
- gDebugInfo["CurrentSimHost"] = gAgent.getRegion()->getSimHostName();
- gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
- }
-
- if(LLAppViewer::instance()->mMainloopTimeout)
- {
- gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
- }
-
- mOnLoginCompleted();
-
- writeDebugInfo();
-
- // we logged in successfully, so save settings on logout
- LL_INFOS() << "Login successful, per account settings will be saved on log out." << LL_ENDL;
- mSavePerAccountSettings=true;
+ gLoggedInTime.start();
+ initMainloopTimeout("Mainloop Init");
+
+ // Store some data to DebugInfo in case of a freeze.
+ gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel();
+
+ gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor();
+ gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor();
+ gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch();
+ gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild());
+
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if ( parcel && parcel->getMusicURL()[0])
+ {
+ gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
+ }
+ if ( parcel && parcel->getMediaURL()[0])
+ {
+ gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
+ }
+
+ gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
+ gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
+ gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
+ gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
+
+ if(gAgent.getRegion())
+ {
+ gDebugInfo["CurrentSimHost"] = gAgent.getRegion()->getSimHostName();
+ gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
+ }
+
+ if(LLAppViewer::instance()->mMainloopTimeout)
+ {
+ gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
+ }
+
+ mOnLoginCompleted();
+
+ writeDebugInfo();
+
+ // we logged in successfully, so save settings on logout
+ LL_INFOS() << "Login successful, per account settings will be saved on log out." << LL_ENDL;
+ mSavePerAccountSettings=true;
}
//virtual
void LLAppViewer::setMasterSystemAudioMute(bool mute)
{
- gSavedSettings.setBOOL("MuteAudio", mute);
+ gSavedSettings.setBOOL("MuteAudio", mute);
}
//virtual
bool LLAppViewer::getMasterSystemAudioMute()
{
- return gSavedSettings.getBOOL("MuteAudio");
+ return gSavedSettings.getBOOL("MuteAudio");
}
//----------------------------------------------------------------------------
@@ -5650,10 +5676,10 @@ bool LLAppViewer::getMasterSystemAudioMute()
*/
void LLAppViewer::metricsUpdateRegion(U64 region_handle)
{
- if (0 != region_handle)
- {
- LLViewerAssetStatsFF::set_region(region_handle);
- }
+ if (0 != region_handle)
+ {
+ LLViewerAssetStatsFF::set_region(region_handle);
+ }
}
/**
@@ -5662,35 +5688,35 @@ void LLAppViewer::metricsUpdateRegion(U64 region_handle)
*/
void LLAppViewer::metricsSend(bool enable_reporting)
{
- if (! gViewerAssetStats)
- return;
+ if (! gViewerAssetStats)
+ return;
- if (LLAppViewer::sTextureFetch)
- {
- LLViewerRegion * regionp = gAgent.getRegion();
+ if (LLAppViewer::sTextureFetch)
+ {
+ LLViewerRegion * regionp = gAgent.getRegion();
- if (enable_reporting && regionp)
- {
- std::string caps_url = regionp->getCapability("ViewerMetrics");
+ if (enable_reporting && regionp)
+ {
+ std::string caps_url = regionp->getCapability("ViewerMetrics");
LLSD sd = gViewerAssetStats->asLLSD(true);
- // Send a report request into 'thread1' to get the rest of the data
- // and provide some additional parameters while here.
- LLAppViewer::sTextureFetch->commandSendMetrics(caps_url,
- gAgentSessionID,
- gAgentID,
- sd);
- }
- else
- {
- LLAppViewer::sTextureFetch->commandDataBreak();
- }
- }
-
- // Reset even if we can't report. Rather than gather up a huge chunk of
- // data, we'll keep to our sampling interval and retain the data
- // resolution in time.
- gViewerAssetStats->restart();
+ // Send a report request into 'thread1' to get the rest of the data
+ // and provide some additional parameters while here.
+ LLAppViewer::sTextureFetch->commandSendMetrics(caps_url,
+ gAgentSessionID,
+ gAgentID,
+ sd);
+ }
+ else
+ {
+ LLAppViewer::sTextureFetch->commandDataBreak();
+ }
+ }
+
+ // Reset even if we can't report. Rather than gather up a huge chunk of
+ // data, we'll keep to our sampling interval and retain the data
+ // resolution in time.
+ gViewerAssetStats->restart();
}
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index bfdede37bc..68952c96c5 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfilepicker.cpp
* @brief OS-specific file picker
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -34,7 +34,7 @@
#include "llframetimer.h"
#include "lltrans.h"
#include "llviewercontrol.h"
-#include "llwindow.h" // beforeDialog()
+#include "llwindow.h" // beforeDialog()
#if LL_SDL
#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers
@@ -64,6 +64,7 @@ LLFilePicker LLFilePicker::sInstance;
#define MATERIAL_TEXTURES_FILTER L"GLTF Import (*.gltf; *.glb; *.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.gltf;*.glb;*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
#define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0"
#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"
+#define LUA_FILTER L"Script files (*.lua)\0*.lua\0"
#endif
#ifdef LL_DARWIN
@@ -75,149 +76,149 @@ LLFilePicker LLFilePicker::sInstance;
// Implementation
//
LLFilePicker::LLFilePicker()
- : mCurrentFile(0),
- mLocked(false)
+ : mCurrentFile(0),
+ mLocked(false)
{
- reset();
+ reset();
#if LL_WINDOWS
- mOFN.lStructSize = sizeof(OPENFILENAMEW);
- mOFN.hwndOwner = NULL; // Set later
- mOFN.hInstance = NULL;
- mOFN.lpstrCustomFilter = NULL;
- mOFN.nMaxCustFilter = 0;
- mOFN.lpstrFile = NULL; // set in open and close
- mOFN.nMaxFile = LL_MAX_PATH;
- mOFN.lpstrFileTitle = NULL;
- mOFN.nMaxFileTitle = 0;
- mOFN.lpstrInitialDir = NULL;
- mOFN.lpstrTitle = NULL;
- mOFN.Flags = 0; // set in open and close
- mOFN.nFileOffset = 0;
- mOFN.nFileExtension = 0;
- mOFN.lpstrDefExt = NULL;
- mOFN.lCustData = 0L;
- mOFN.lpfnHook = NULL;
- mOFN.lpTemplateName = NULL;
- mFilesW[0] = '\0';
+ mOFN.lStructSize = sizeof(OPENFILENAMEW);
+ mOFN.hwndOwner = NULL; // Set later
+ mOFN.hInstance = NULL;
+ mOFN.lpstrCustomFilter = NULL;
+ mOFN.nMaxCustFilter = 0;
+ mOFN.lpstrFile = NULL; // set in open and close
+ mOFN.nMaxFile = LL_MAX_PATH;
+ mOFN.lpstrFileTitle = NULL;
+ mOFN.nMaxFileTitle = 0;
+ mOFN.lpstrInitialDir = NULL;
+ mOFN.lpstrTitle = NULL;
+ mOFN.Flags = 0; // set in open and close
+ mOFN.nFileOffset = 0;
+ mOFN.nFileExtension = 0;
+ mOFN.lpstrDefExt = NULL;
+ mOFN.lCustData = 0L;
+ mOFN.lpfnHook = NULL;
+ mOFN.lpTemplateName = NULL;
+ mFilesW[0] = '\0';
#elif LL_DARWIN
- mPickOptions = 0;
+ mPickOptions = 0;
#endif
}
LLFilePicker::~LLFilePicker()
{
- // nothing
+ // nothing
}
-// utility function to check if access to local file system via file browser
+// utility function to check if access to local file system via file browser
// is enabled and if not, tidy up and indicate we're not allowed to do this.
bool LLFilePicker::check_local_file_access_enabled()
{
- // if local file browsing is turned off, return without opening dialog
- bool local_file_system_browsing_enabled = gSavedSettings.getBOOL("LocalFileSystemBrowsingEnabled");
- if ( ! local_file_system_browsing_enabled )
- {
- mFiles.clear();
- return false;
- }
-
- return true;
+ // if local file browsing is turned off, return without opening dialog
+ bool local_file_system_browsing_enabled = gSavedSettings.getBOOL("LocalFileSystemBrowsingEnabled");
+ if ( ! local_file_system_browsing_enabled )
+ {
+ mFiles.clear();
+ return false;
+ }
+
+ return true;
}
const std::string LLFilePicker::getFirstFile()
{
- mCurrentFile = 0;
- return getNextFile();
+ mCurrentFile = 0;
+ return getNextFile();
}
const std::string LLFilePicker::getNextFile()
{
- if (mCurrentFile >= getFileCount())
- {
- mLocked = false;
- return std::string();
- }
- else
- {
- return mFiles[mCurrentFile++];
- }
+ if (mCurrentFile >= getFileCount())
+ {
+ mLocked = false;
+ return std::string();
+ }
+ else
+ {
+ return mFiles[mCurrentFile++];
+ }
}
const std::string LLFilePicker::getCurFile()
{
- if (mCurrentFile >= getFileCount())
- {
- mLocked = false;
- return std::string();
- }
- else
- {
- return mFiles[mCurrentFile];
- }
+ if (mCurrentFile >= getFileCount())
+ {
+ mLocked = false;
+ return std::string();
+ }
+ else
+ {
+ return mFiles[mCurrentFile];
+ }
}
void LLFilePicker::reset()
{
- mLocked = false;
- mFiles.clear();
- mCurrentFile = 0;
+ mLocked = false;
+ mFiles.clear();
+ mCurrentFile = 0;
}
#if LL_WINDOWS
BOOL LLFilePicker::setupFilter(ELoadFilter filter)
{
- BOOL res = TRUE;
- switch (filter)
- {
+ BOOL res = TRUE;
+ switch (filter)
+ {
case FFLOAD_ALL:
case FFLOAD_EXE:
- mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \
- SOUND_FILTER \
- IMAGE_FILTER \
- ANIM_FILTER \
- MATERIAL_FILTER \
- L"\0";
- break;
- case FFLOAD_WAV:
- mOFN.lpstrFilter = SOUND_FILTER \
- L"\0";
- break;
- case FFLOAD_IMAGE:
- mOFN.lpstrFilter = IMAGE_FILTER \
- L"\0";
- break;
- case FFLOAD_ANIM:
- mOFN.lpstrFilter = ANIM_FILTER \
- L"\0";
- break;
- case FFLOAD_GLTF:
- mOFN.lpstrFilter = GLTF_FILTER \
- L"\0";
- break;
- case FFLOAD_COLLADA:
- mOFN.lpstrFilter = COLLADA_FILTER \
- L"\0";
- break;
- case FFLOAD_XML:
- mOFN.lpstrFilter = XML_FILTER \
- L"\0";
- break;
- case FFLOAD_SLOBJECT:
- mOFN.lpstrFilter = SLOBJECT_FILTER \
- L"\0";
- break;
- case FFLOAD_RAW:
- mOFN.lpstrFilter = RAW_FILTER \
- L"\0";
- break;
- case FFLOAD_MODEL:
- mOFN.lpstrFilter = MODEL_FILTER \
- L"\0";
- break;
+ mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \
+ SOUND_FILTER \
+ IMAGE_FILTER \
+ ANIM_FILTER \
+ MATERIAL_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_WAV:
+ mOFN.lpstrFilter = SOUND_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_IMAGE:
+ mOFN.lpstrFilter = IMAGE_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_ANIM:
+ mOFN.lpstrFilter = ANIM_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_GLTF:
+ mOFN.lpstrFilter = GLTF_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_COLLADA:
+ mOFN.lpstrFilter = COLLADA_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_XML:
+ mOFN.lpstrFilter = XML_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_SLOBJECT:
+ mOFN.lpstrFilter = SLOBJECT_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_RAW:
+ mOFN.lpstrFilter = RAW_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_MODEL:
+ mOFN.lpstrFilter = MODEL_FILTER \
+ L"\0";
+ break;
case FFLOAD_MATERIAL:
mOFN.lpstrFilter = MATERIAL_FILTER \
L"\0";
@@ -228,70 +229,74 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
IMAGE_FILTER \
L"\0";
break;
- case FFLOAD_SCRIPT:
- mOFN.lpstrFilter = SCRIPT_FILTER \
+ case FFLOAD_SCRIPT:
+ mOFN.lpstrFilter = SCRIPT_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_DICTIONARY:
+ mOFN.lpstrFilter = DICTIONARY_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_LUA:
+ mOFN.lpstrFilter = LUA_FILTER \
L"\0";
break;
- case FFLOAD_DICTIONARY:
- mOFN.lpstrFilter = DICTIONARY_FILTER \
- L"\0";
- break;
- default:
- res = FALSE;
- break;
- }
- return res;
+ default:
+ res = FALSE;
+ break;
+ }
+ return res;
}
BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
{
- if( mLocked )
- {
- return FALSE;
- }
- BOOL success = FALSE;
-
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
- // don't provide default file selection
- mFilesW[0] = '\0';
-
- mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
- mOFN.lpstrFile = mFilesW;
- mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
- mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR ;
- mOFN.nFilterIndex = 1;
-
- setupFilter(filter);
-
- if (blocking)
- {
- // Modal, so pause agent
- send_agent_pause();
- }
-
- reset();
-
- // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
- success = GetOpenFileName(&mOFN);
- if (success)
- {
- std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
- mFiles.push_back(filename);
- }
-
- if (blocking)
- {
- send_agent_resume();
- // Account for the fact that the app has been stalled.
- LLFrameTimer::updateFrameTime();
- }
-
- return success;
+ if( mLocked )
+ {
+ return FALSE;
+ }
+ BOOL success = FALSE;
+
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
+ // don't provide default file selection
+ mFilesW[0] = '\0';
+
+ mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
+ mOFN.lpstrFile = mFilesW;
+ mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
+ mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR ;
+ mOFN.nFilterIndex = 1;
+
+ setupFilter(filter);
+
+ if (blocking)
+ {
+ // Modal, so pause agent
+ send_agent_pause();
+ }
+
+ reset();
+
+ // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
+ success = GetOpenFileName(&mOFN);
+ if (success)
+ {
+ std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
+ mFiles.push_back(filename);
+ }
+
+ if (blocking)
+ {
+ send_agent_resume();
+ // Account for the fact that the app has been stalled.
+ LLFrameTimer::updateFrameTime();
+ }
+
+ return success;
}
BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter,
@@ -305,79 +310,79 @@ BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter,
BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking)
{
- if( mLocked )
- {
- return FALSE;
- }
- BOOL success = FALSE;
-
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
- // don't provide default file selection
- mFilesW[0] = '\0';
-
- mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
- mOFN.lpstrFile = mFilesW;
- mOFN.nFilterIndex = 1;
- mOFN.nMaxFile = FILENAME_BUFFER_SIZE;
- mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR |
- OFN_EXPLORER | OFN_ALLOWMULTISELECT;
-
- setupFilter(filter);
-
- reset();
-
- if (blocking)
- {
- // Modal, so pause agent
- send_agent_pause();
- }
-
- // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
- success = GetOpenFileName(&mOFN); // pauses until ok or cancel.
- if( success )
- {
- // The getopenfilename api doesn't tell us if we got more than
- // one file, so we have to test manually by checking string
- // lengths.
- if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) /*Flawfinder: ignore*/
- {
- std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
- mFiles.push_back(filename);
- }
- else
- {
- mLocked = true;
- WCHAR* tptrw = mFilesW;
- std::string dirname;
- while(1)
- {
- if (*tptrw == 0 && *(tptrw+1) == 0) // double '\0'
- break;
- if (*tptrw == 0)
- tptrw++; // shouldn't happen?
- std::string filename = utf16str_to_utf8str(llutf16string(tptrw));
- if (dirname.empty())
- dirname = filename + "\\";
- else
- mFiles.push_back(dirname + filename);
- tptrw += wcslen(tptrw);
- }
- }
- }
-
- if (blocking)
- {
- send_agent_resume();
- }
-
- // Account for the fact that the app has been stalled.
- LLFrameTimer::updateFrameTime();
- return success;
+ if( mLocked )
+ {
+ return FALSE;
+ }
+ BOOL success = FALSE;
+
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
+ // don't provide default file selection
+ mFilesW[0] = '\0';
+
+ mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
+ mOFN.lpstrFile = mFilesW;
+ mOFN.nFilterIndex = 1;
+ mOFN.nMaxFile = FILENAME_BUFFER_SIZE;
+ mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR |
+ OFN_EXPLORER | OFN_ALLOWMULTISELECT;
+
+ setupFilter(filter);
+
+ reset();
+
+ if (blocking)
+ {
+ // Modal, so pause agent
+ send_agent_pause();
+ }
+
+ // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
+ success = GetOpenFileName(&mOFN); // pauses until ok or cancel.
+ if( success )
+ {
+ // The getopenfilename api doesn't tell us if we got more than
+ // one file, so we have to test manually by checking string
+ // lengths.
+ if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) /*Flawfinder: ignore*/
+ {
+ std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
+ mFiles.push_back(filename);
+ }
+ else
+ {
+ mLocked = true;
+ WCHAR* tptrw = mFilesW;
+ std::string dirname;
+ while(1)
+ {
+ if (*tptrw == 0 && *(tptrw+1) == 0) // double '\0'
+ break;
+ if (*tptrw == 0)
+ tptrw++; // shouldn't happen?
+ std::string filename = utf16str_to_utf8str(llutf16string(tptrw));
+ if (dirname.empty())
+ dirname = filename + "\\";
+ else
+ mFiles.push_back(dirname + filename);
+ tptrw += wcslen(tptrw);
+ }
+ }
+ }
+
+ if (blocking)
+ {
+ send_agent_resume();
+ }
+
+ // Account for the fact that the app has been stalled.
+ LLFrameTimer::updateFrameTime();
+ return success;
}
BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
@@ -391,222 +396,222 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, bool blocking)
{
- if( mLocked )
- {
- return FALSE;
- }
- BOOL success = FALSE;
-
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
- mOFN.lpstrFile = mFilesW;
- if (!filename.empty())
- {
- llutf16string tstring = utf8str_to_utf16str(filename);
- wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/
- else
- {
- mFilesW[0] = '\0';
- }
- mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
-
- switch( filter )
- {
- case FFSAVE_ALL:
- mOFN.lpstrDefExt = NULL;
- mOFN.lpstrFilter =
- L"All Files (*.*)\0*.*\0" \
- L"WAV Sounds (*.wav)\0*.wav\0" \
- L"Targa, Bitmap Images (*.tga; *.bmp)\0*.tga;*.bmp\0" \
- L"\0";
- break;
- case FFSAVE_WAV:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"wav";
- mOFN.lpstrFilter =
- L"WAV Sounds (*.wav)\0*.wav\0" \
- L"\0";
- break;
- case FFSAVE_TGA:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"tga";
- mOFN.lpstrFilter =
- L"Targa Images (*.tga)\0*.tga\0" \
- L"\0";
- break;
- case FFSAVE_BMP:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"bmp";
- mOFN.lpstrFilter =
- L"Bitmap Images (*.bmp)\0*.bmp\0" \
- L"\0";
- break;
- case FFSAVE_PNG:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"png";
- mOFN.lpstrFilter =
- L"PNG Images (*.png)\0*.png\0" \
- L"\0";
- break;
- case FFSAVE_TGAPNG:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- //PNG by default
- }
- mOFN.lpstrDefExt = L"png";
- mOFN.lpstrFilter =
- L"PNG Images (*.png)\0*.png\0" \
- L"Targa Images (*.tga)\0*.tga\0" \
- L"\0";
- break;
-
- case FFSAVE_JPEG:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.jpeg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"jpg";
- mOFN.lpstrFilter =
- L"JPEG Images (*.jpg *.jpeg)\0*.jpg;*.jpeg\0" \
- L"\0";
- break;
- case FFSAVE_AVI:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"avi";
- mOFN.lpstrFilter =
- L"AVI Movie File (*.avi)\0*.avi\0" \
- L"\0";
- break;
- case FFSAVE_ANIM:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"xaf";
- mOFN.lpstrFilter =
- L"XAF Anim File (*.xaf)\0*.xaf\0" \
- L"\0";
- break;
- case FFSAVE_GLTF:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.glb", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"glb";
- mOFN.lpstrFilter =
- L"glTF Asset File (*.gltf *.glb)\0*.gltf;*.glb\0" \
- L"\0";
- break;
- case FFSAVE_XML:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
-
- mOFN.lpstrDefExt = L"xml";
- mOFN.lpstrFilter =
- L"XML File (*.xml)\0*.xml\0" \
- L"\0";
- break;
- case FFSAVE_COLLADA:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"collada";
- mOFN.lpstrFilter =
- L"COLLADA File (*.collada)\0*.collada\0" \
- L"\0";
- break;
- case FFSAVE_RAW:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
- }
- mOFN.lpstrDefExt = L"raw";
- mOFN.lpstrFilter = RAW_FILTER \
- L"\0";
- break;
- case FFSAVE_J2C:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE);
- }
- mOFN.lpstrDefExt = L"j2c";
- mOFN.lpstrFilter =
- L"Compressed Images (*.j2c)\0*.j2c\0" \
- L"\0";
- break;
- case FFSAVE_SCRIPT:
- if (filename.empty())
- {
- wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE);
- }
- mOFN.lpstrDefExt = L"txt";
- mOFN.lpstrFilter = L"LSL Files (*.lsl)\0*.lsl\0" L"\0";
- break;
- default:
- return FALSE;
- }
-
-
- mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
- mOFN.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
-
- reset();
-
- if (blocking)
- {
- // Modal, so pause agent
- send_agent_pause();
- }
-
- {
- // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
- try
- {
- success = GetSaveFileName(&mOFN);
- if (success)
- {
- std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
- mFiles.push_back(filename);
- }
- }
- catch (...)
- {
- LOG_UNHANDLED_EXCEPTION("");
- }
- gKeyboard->resetKeys();
- }
-
- if (blocking)
- {
- send_agent_resume();
- }
-
- // Account for the fact that the app has been stalled.
- LLFrameTimer::updateFrameTime();
- return success;
+ if( mLocked )
+ {
+ return FALSE;
+ }
+ BOOL success = FALSE;
+
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
+ mOFN.lpstrFile = mFilesW;
+ if (!filename.empty())
+ {
+ llutf16string tstring = utf8str_to_utf16str(filename);
+ wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/
+ else
+ {
+ mFilesW[0] = '\0';
+ }
+ mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
+
+ switch( filter )
+ {
+ case FFSAVE_ALL:
+ mOFN.lpstrDefExt = NULL;
+ mOFN.lpstrFilter =
+ L"All Files (*.*)\0*.*\0" \
+ L"WAV Sounds (*.wav)\0*.wav\0" \
+ L"Targa, Bitmap Images (*.tga; *.bmp)\0*.tga;*.bmp\0" \
+ L"\0";
+ break;
+ case FFSAVE_WAV:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"wav";
+ mOFN.lpstrFilter =
+ L"WAV Sounds (*.wav)\0*.wav\0" \
+ L"\0";
+ break;
+ case FFSAVE_TGA:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"tga";
+ mOFN.lpstrFilter =
+ L"Targa Images (*.tga)\0*.tga\0" \
+ L"\0";
+ break;
+ case FFSAVE_BMP:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"bmp";
+ mOFN.lpstrFilter =
+ L"Bitmap Images (*.bmp)\0*.bmp\0" \
+ L"\0";
+ break;
+ case FFSAVE_PNG:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"png";
+ mOFN.lpstrFilter =
+ L"PNG Images (*.png)\0*.png\0" \
+ L"\0";
+ break;
+ case FFSAVE_TGAPNG:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ //PNG by default
+ }
+ mOFN.lpstrDefExt = L"png";
+ mOFN.lpstrFilter =
+ L"PNG Images (*.png)\0*.png\0" \
+ L"Targa Images (*.tga)\0*.tga\0" \
+ L"\0";
+ break;
+
+ case FFSAVE_JPEG:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.jpeg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"jpg";
+ mOFN.lpstrFilter =
+ L"JPEG Images (*.jpg *.jpeg)\0*.jpg;*.jpeg\0" \
+ L"\0";
+ break;
+ case FFSAVE_AVI:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"avi";
+ mOFN.lpstrFilter =
+ L"AVI Movie File (*.avi)\0*.avi\0" \
+ L"\0";
+ break;
+ case FFSAVE_ANIM:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"xaf";
+ mOFN.lpstrFilter =
+ L"XAF Anim File (*.xaf)\0*.xaf\0" \
+ L"\0";
+ break;
+ case FFSAVE_GLTF:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.glb", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"glb";
+ mOFN.lpstrFilter =
+ L"glTF Asset File (*.gltf *.glb)\0*.gltf;*.glb\0" \
+ L"\0";
+ break;
+ case FFSAVE_XML:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+
+ mOFN.lpstrDefExt = L"xml";
+ mOFN.lpstrFilter =
+ L"XML File (*.xml)\0*.xml\0" \
+ L"\0";
+ break;
+ case FFSAVE_COLLADA:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"collada";
+ mOFN.lpstrFilter =
+ L"COLLADA File (*.collada)\0*.collada\0" \
+ L"\0";
+ break;
+ case FFSAVE_RAW:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"raw";
+ mOFN.lpstrFilter = RAW_FILTER \
+ L"\0";
+ break;
+ case FFSAVE_J2C:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE);
+ }
+ mOFN.lpstrDefExt = L"j2c";
+ mOFN.lpstrFilter =
+ L"Compressed Images (*.j2c)\0*.j2c\0" \
+ L"\0";
+ break;
+ case FFSAVE_SCRIPT:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE);
+ }
+ mOFN.lpstrDefExt = L"txt";
+ mOFN.lpstrFilter = L"LSL Files (*.lsl)\0*.lsl\0" L"\0";
+ break;
+ default:
+ return FALSE;
+ }
+
+
+ mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
+ mOFN.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
+
+ reset();
+
+ if (blocking)
+ {
+ // Modal, so pause agent
+ send_agent_pause();
+ }
+
+ {
+ // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
+ try
+ {
+ success = GetSaveFileName(&mOFN);
+ if (success)
+ {
+ std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
+ mFiles.push_back(filename);
+ }
+ }
+ catch (...)
+ {
+ LOG_UNHANDLED_EXCEPTION("");
+ }
+ gKeyboard->resetKeys();
+ }
+
+ if (blocking)
+ {
+ send_agent_resume();
+ }
+
+ // Account for the fact that the app has been stalled.
+ LLFrameTimer::updateFrameTime();
+ return success;
}
BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
@@ -685,25 +690,25 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
LL_WARNS() << "Unsupported format." << LL_ENDL;
}
- return allowedv;
+ return allowedv;
}
-bool LLFilePicker::doNavChooseDialog(ELoadFilter filter)
+bool LLFilePicker::doNavChooseDialog(ELoadFilter filter)
{
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return false;
- }
-
- gViewerWindow->getWindow()->beforeDialog();
-
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return false;
+ }
+
+ gViewerWindow->getWindow()->beforeDialog();
+
std::unique_ptr<std::vector<std::string>> allowed_types = navOpenFilterProc(filter);
-
+
std::unique_ptr<std::vector<std::string>> filev = doLoadDialog(allowed_types.get(),
mPickOptions);
- gViewerWindow->getWindow()->afterDialog();
+ gViewerWindow->getWindow()->afterDialog();
if (filev && filev->size() > 0)
@@ -711,8 +716,8 @@ bool LLFilePicker::doNavChooseDialog(ELoadFilter filter)
mFiles.insert(mFiles.end(), filev->begin(), filev->end());
return true;
}
-
- return false;
+
+ return false;
}
bool LLFilePicker::doNavChooseDialogModeless(ELoadFilter filter,
@@ -724,14 +729,14 @@ bool LLFilePicker::doNavChooseDialogModeless(ELoadFilter filter,
{
return false;
}
-
+
std::unique_ptr<std::vector<std::string>> allowed_types=navOpenFilterProc(filter);
-
+
doLoadDialogModeless(allowed_types.get(),
mPickOptions,
callback,
userdata);
-
+
return true;
}
@@ -785,13 +790,13 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension,
creator = "\?\?\?\?";
extension = "glb";
break;
-
+
case LLFilePicker::FFSAVE_XML:
type = "\?\?\?\?";
creator = "\?\?\?\?";
extension = "xml";
break;
-
+
case LLFilePicker::FFSAVE_RAW:
type = "\?\?\?\?";
creator = "\?\?\?\?";
@@ -803,13 +808,13 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension,
creator = "prvw";
extension = "j2c";
break;
-
+
case LLFilePicker::FFSAVE_SCRIPT:
type = "LSL ";
creator = "\?\?\?\?";
extension = "lsl";
break;
-
+
case LLFilePicker::FFSAVE_ALL:
default:
type = "\?\?\?\?";
@@ -819,34 +824,34 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension,
}
}
-bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename)
+bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename)
{
- // Setup the type, creator, and extension
- std::string extension, type, creator;
-
+ // Setup the type, creator, and extension
+ std::string extension, type, creator;
+
set_nav_save_data(filter, extension, type, creator);
-
+
std::string namestring = filename;
if (namestring.empty()) namestring="Untitled";
+
+ gViewerWindow->getWindow()->beforeDialog();
- gViewerWindow->getWindow()->beforeDialog();
-
- // Run the dialog
- std::unique_ptr<std::string> filev = doSaveDialog(&namestring,
+ // Run the dialog
+ std::unique_ptr<std::string> filev = doSaveDialog(&namestring,
&type,
&creator,
&extension,
mPickOptions);
- gViewerWindow->getWindow()->afterDialog();
+ gViewerWindow->getWindow()->afterDialog();
- if ( filev && !filev->empty() )
- {
+ if ( filev && !filev->empty() )
+ {
mFiles.push_back(*filev);
- return true;
+ return true;
}
-
- return false;
+
+ return false;
}
bool LLFilePicker::doNavSaveDialogModeless(ESaveFilter filter,
@@ -856,9 +861,9 @@ bool LLFilePicker::doNavSaveDialogModeless(ESaveFilter filter,
{
// Setup the type, creator, and extension
std::string extension, type, creator;
-
+
set_nav_save_data(filter, extension, type, creator);
-
+
std::string namestring = filename;
if (namestring.empty()) namestring="Untitled";
@@ -875,57 +880,57 @@ bool LLFilePicker::doNavSaveDialogModeless(ESaveFilter filter,
BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
{
- if( mLocked )
- return FALSE;
-
- BOOL success = FALSE;
+ if( mLocked )
+ return FALSE;
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
+ BOOL success = FALSE;
- reset();
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+ reset();
+
mPickOptions &= ~F_MULTIPLE;
mPickOptions |= F_FILE;
-
- if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker.
+
+ if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker.
{
mPickOptions |= ( F_NAV_SUPPORT | F_DIRECTORY );
mPickOptions &= ~F_FILE;
}
- if (filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
- {
+ if (filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
+ {
mPickOptions |= F_NAV_SUPPORT;
- }
-
- if (blocking) // always true for linux/mac
- {
- // Modal, so pause agent
- send_agent_pause();
- }
-
-
- success = doNavChooseDialog(filter);
-
- if (success)
- {
- if (!getFileCount())
- success = false;
- }
-
- if (blocking)
- {
- send_agent_resume();
- // Account for the fact that the app has been stalled.
- LLFrameTimer::updateFrameTime();
- }
-
- return success;
+ }
+
+ if (blocking) // always true for linux/mac
+ {
+ // Modal, so pause agent
+ send_agent_pause();
+ }
+
+
+ success = doNavChooseDialog(filter);
+
+ if (success)
+ {
+ if (!getFileCount())
+ success = false;
+ }
+
+ if (blocking)
+ {
+ send_agent_resume();
+ // Account for the fact that the app has been stalled.
+ LLFrameTimer::updateFrameTime();
+ }
+
+ return success;
}
@@ -943,10 +948,10 @@ BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter,
}
reset();
-
+
mPickOptions &= ~F_MULTIPLE;
mPickOptions |= F_FILE;
-
+
if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker.
{
@@ -964,47 +969,47 @@ BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter,
BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking)
{
- if( mLocked )
- return FALSE;
-
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
+ if( mLocked )
+ return FALSE;
+
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
BOOL success = FALSE;
- reset();
-
+ reset();
+
mPickOptions |= F_FILE;
mPickOptions |= F_MULTIPLE;
- if (blocking) // always true for linux/mac
- {
- // Modal, so pause agent
- send_agent_pause();
- }
-
- success = doNavChooseDialog(filter);
-
- if (blocking)
- {
- send_agent_resume();
- }
-
- if (success)
- {
- if (!getFileCount())
- success = false;
- if (getFileCount() > 1)
- mLocked = true;
- }
-
- // Account for the fact that the app has been stalled.
- LLFrameTimer::updateFrameTime();
- return success;
+ if (blocking) // always true for linux/mac
+ {
+ // Modal, so pause agent
+ send_agent_pause();
+ }
+
+ success = doNavChooseDialog(filter);
+
+ if (blocking)
+ {
+ send_agent_resume();
+ }
+
+ if (success)
+ {
+ if (!getFileCount())
+ success = false;
+ if (getFileCount() > 1)
+ mLocked = true;
+ }
+
+ // Account for the fact that the app has been stalled.
+ LLFrameTimer::updateFrameTime();
+ return success;
}
@@ -1022,7 +1027,7 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
}
reset();
-
+
mPickOptions |= F_FILE;
mPickOptions |= F_MULTIPLE;
@@ -1033,42 +1038,42 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, bool blocking)
{
- if( mLocked )
- return false;
- BOOL success = false;
+ if( mLocked )
+ return false;
+ BOOL success = false;
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return false;
- }
-
- reset();
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return false;
+ }
+ reset();
+
mPickOptions &= ~F_MULTIPLE;
- if (blocking)
- {
- // Modal, so pause agent
- send_agent_pause();
- }
+ if (blocking)
+ {
+ // Modal, so pause agent
+ send_agent_pause();
+ }
success = doNavSaveDialog(filter, filename);
if (success)
- {
- if (!getFileCount())
- success = false;
- }
-
- if (blocking)
- {
- send_agent_resume();
- }
-
- // Account for the fact that the app has been stalled.
- LLFrameTimer::updateFrameTime();
- return success;
+ {
+ if (!getFileCount())
+ success = false;
+ }
+
+ if (blocking)
+ {
+ send_agent_resume();
+ }
+
+ // Account for the fact that the app has been stalled.
+ LLFrameTimer::updateFrameTime();
+ return success;
}
BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
@@ -1078,7 +1083,7 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
{
if( mLocked )
return false;
-
+
// if local file browsing is turned off, return without opening dialog
if ( check_local_file_access_enabled() == false )
{
@@ -1086,7 +1091,7 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
}
reset();
-
+
mPickOptions &= ~F_MULTIPLE;
return doNavSaveDialogModeless(filter, filename, callback, userdata);
@@ -1100,414 +1105,414 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
// static
void LLFilePicker::add_to_selectedfiles(gpointer data, gpointer user_data)
{
- // We need to run g_filename_to_utf8 in the user's locale
- std::string saved_locale(setlocale(LC_ALL, NULL));
- setlocale(LC_ALL, "");
-
- LLFilePicker* picker = (LLFilePicker*) user_data;
- GError *error = NULL;
- gchar* filename_utf8 = g_filename_to_utf8((gchar*)data,
- -1, NULL, NULL, &error);
- if (error)
- {
- // *FIXME.
- // This condition should really be notified to the user, e.g.
- // through a message box. Just logging it is inappropriate.
-
- // g_filename_display_name is ideal, but >= glib 2.6, so:
- // a hand-rolled hacky makeASCII which disallows control chars
- std::string display_name;
- for (const gchar *str = (const gchar *)data; *str; str++)
- {
- display_name += (char)((*str >= 0x20 && *str <= 0x7E) ? *str : '?');
- }
- LL_WARNS() << "g_filename_to_utf8 failed on \"" << display_name << "\": " << error->message << LL_ENDL;
- }
-
- if (filename_utf8)
- {
- picker->mFiles.push_back(std::string(filename_utf8));
- LL_DEBUGS() << "ADDED FILE " << filename_utf8 << LL_ENDL;
- g_free(filename_utf8);
- }
-
- setlocale(LC_ALL, saved_locale.c_str());
+ // We need to run g_filename_to_utf8 in the user's locale
+ std::string saved_locale(setlocale(LC_ALL, NULL));
+ setlocale(LC_ALL, "");
+
+ LLFilePicker* picker = (LLFilePicker*) user_data;
+ GError *error = NULL;
+ gchar* filename_utf8 = g_filename_to_utf8((gchar*)data,
+ -1, NULL, NULL, &error);
+ if (error)
+ {
+ // *FIXME.
+ // This condition should really be notified to the user, e.g.
+ // through a message box. Just logging it is inappropriate.
+
+ // g_filename_display_name is ideal, but >= glib 2.6, so:
+ // a hand-rolled hacky makeASCII which disallows control chars
+ std::string display_name;
+ for (const gchar *str = (const gchar *)data; *str; str++)
+ {
+ display_name += (char)((*str >= 0x20 && *str <= 0x7E) ? *str : '?');
+ }
+ LL_WARNS() << "g_filename_to_utf8 failed on \"" << display_name << "\": " << error->message << LL_ENDL;
+ }
+
+ if (filename_utf8)
+ {
+ picker->mFiles.push_back(std::string(filename_utf8));
+ LL_DEBUGS() << "ADDED FILE " << filename_utf8 << LL_ENDL;
+ g_free(filename_utf8);
+ }
+
+ setlocale(LC_ALL, saved_locale.c_str());
}
// static
void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer user_data)
{
- LLFilePicker* picker = (LLFilePicker*)user_data;
-
- LL_DEBUGS() << "GTK DIALOG RESPONSE " << response << LL_ENDL;
-
- if (response == GTK_RESPONSE_ACCEPT)
- {
- GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
- g_slist_foreach(file_list, (GFunc)add_to_selectedfiles, user_data);
- g_slist_foreach(file_list, (GFunc)g_free, NULL);
- g_slist_free (file_list);
- }
-
- // let's save the extension of the last added file(considering current filter)
- GtkFileFilter *gfilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(widget));
- if(gfilter)
- {
- std::string filter = gtk_file_filter_get_name(gfilter);
-
- if(filter == LLTrans::getString("png_image_files"))
- {
- picker->mCurrentExtension = ".png";
- }
- else if(filter == LLTrans::getString("targa_image_files"))
- {
- picker->mCurrentExtension = ".tga";
- }
- }
-
- // set the default path for this usage context.
- const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
- if (cur_folder != NULL)
- {
- picker->mContextToPathMap[picker->mCurContextName] = cur_folder;
- }
-
- gtk_widget_destroy(widget);
- gtk_main_quit();
+ LLFilePicker* picker = (LLFilePicker*)user_data;
+
+ LL_DEBUGS() << "GTK DIALOG RESPONSE " << response << LL_ENDL;
+
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
+ g_slist_foreach(file_list, (GFunc)add_to_selectedfiles, user_data);
+ g_slist_foreach(file_list, (GFunc)g_free, NULL);
+ g_slist_free (file_list);
+ }
+
+ // let's save the extension of the last added file(considering current filter)
+ GtkFileFilter *gfilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(widget));
+ if(gfilter)
+ {
+ std::string filter = gtk_file_filter_get_name(gfilter);
+
+ if(filter == LLTrans::getString("png_image_files"))
+ {
+ picker->mCurrentExtension = ".png";
+ }
+ else if(filter == LLTrans::getString("targa_image_files"))
+ {
+ picker->mCurrentExtension = ".tga";
+ }
+ }
+
+ // set the default path for this usage context.
+ const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
+ if (cur_folder != NULL)
+ {
+ picker->mContextToPathMap[picker->mCurContextName] = cur_folder;
+ }
+
+ gtk_widget_destroy(widget);
+ gtk_main_quit();
}
GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::string context)
{
#ifndef LL_MESA_HEADLESS
- if (LLWindowSDL::ll_try_gtk_init())
- {
- GtkWidget *win = NULL;
- GtkFileChooserAction pickertype =
- is_save?
- (is_folder?
- GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER :
- GTK_FILE_CHOOSER_ACTION_SAVE) :
- (is_folder?
- GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER :
- GTK_FILE_CHOOSER_ACTION_OPEN);
-
- win = gtk_file_chooser_dialog_new(NULL, NULL,
- pickertype,
- GTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL,
- is_folder ?
- GTK_STOCK_APPLY :
- (is_save ?
- GTK_STOCK_SAVE :
- GTK_STOCK_OPEN),
- GTK_RESPONSE_ACCEPT,
- (gchar *)NULL);
- mCurContextName = context;
-
- // get the default path for this usage context if it's been
- // seen before.
- std::map<std::string,std::string>::iterator
- this_path = mContextToPathMap.find(context);
- if (this_path != mContextToPathMap.end())
- {
- gtk_file_chooser_set_current_folder
- (GTK_FILE_CHOOSER(win),
- this_path->second.c_str());
- }
+ if (LLWindowSDL::ll_try_gtk_init())
+ {
+ GtkWidget *win = NULL;
+ GtkFileChooserAction pickertype =
+ is_save?
+ (is_folder?
+ GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER :
+ GTK_FILE_CHOOSER_ACTION_SAVE) :
+ (is_folder?
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER :
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+
+ win = gtk_file_chooser_dialog_new(NULL, NULL,
+ pickertype,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ is_folder ?
+ GTK_STOCK_APPLY :
+ (is_save ?
+ GTK_STOCK_SAVE :
+ GTK_STOCK_OPEN),
+ GTK_RESPONSE_ACCEPT,
+ (gchar *)NULL);
+ mCurContextName = context;
+
+ // get the default path for this usage context if it's been
+ // seen before.
+ std::map<std::string,std::string>::iterator
+ this_path = mContextToPathMap.find(context);
+ if (this_path != mContextToPathMap.end())
+ {
+ gtk_file_chooser_set_current_folder
+ (GTK_FILE_CHOOSER(win),
+ this_path->second.c_str());
+ }
# if LL_X11
- // Make GTK tell the window manager to associate this
- // dialog with our non-GTK raw X11 window, which should try
- // to keep it on top etc.
- Window XWindowID = LLWindowSDL::get_SDL_XWindowID();
- if (None != XWindowID)
- {
- gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
- GdkWindow *gdkwin = gdk_window_foreign_new(XWindowID);
- gdk_window_set_transient_for(GTK_WIDGET(win)->window,
- gdkwin);
- }
- else
- {
- LL_WARNS() << "Hmm, couldn't get xwid to use for transient." << LL_ENDL;
- }
+ // Make GTK tell the window manager to associate this
+ // dialog with our non-GTK raw X11 window, which should try
+ // to keep it on top etc.
+ Window XWindowID = LLWindowSDL::get_SDL_XWindowID();
+ if (None != XWindowID)
+ {
+ gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
+ GdkWindow *gdkwin = gdk_window_foreign_new(XWindowID);
+ gdk_window_set_transient_for(GTK_WIDGET(win)->window,
+ gdkwin);
+ }
+ else
+ {
+ LL_WARNS() << "Hmm, couldn't get xwid to use for transient." << LL_ENDL;
+ }
# endif //LL_X11
- g_signal_connect (GTK_FILE_CHOOSER(win),
- "response",
- G_CALLBACK(LLFilePicker::chooser_responder),
- this);
+ g_signal_connect (GTK_FILE_CHOOSER(win),
+ "response",
+ G_CALLBACK(LLFilePicker::chooser_responder),
+ this);
- gtk_window_set_modal(GTK_WINDOW(win), TRUE);
+ gtk_window_set_modal(GTK_WINDOW(win), TRUE);
- /* GTK 2.6: if (is_folder)
- gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win),
- TRUE); */
+ /* GTK 2.6: if (is_folder)
+ gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win),
+ TRUE); */
- return GTK_WINDOW(win);
- }
- else
- {
- return NULL;
- }
+ return GTK_WINDOW(win);
+ }
+ else
+ {
+ return NULL;
+ }
#else
- return NULL;
+ return NULL;
#endif //LL_MESA_HEADLESS
}
static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter,
- GtkWindow *picker,
- std::string filtername)
-{
- gtk_file_filter_set_name(gfilter, filtername.c_str());
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
- gfilter);
- GtkFileFilter *allfilter = gtk_file_filter_new();
- gtk_file_filter_add_pattern(allfilter, "*");
- gtk_file_filter_set_name(allfilter, LLTrans::getString("all_files").c_str());
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter);
- gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter);
+ GtkWindow *picker,
+ std::string filtername)
+{
+ gtk_file_filter_set_name(gfilter, filtername.c_str());
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
+ gfilter);
+ GtkFileFilter *allfilter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(allfilter, "*");
+ gtk_file_filter_set_name(allfilter, LLTrans::getString("all_files").c_str());
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter);
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter);
}
static std::string add_simple_pattern_filter_to_gtkchooser(GtkWindow *picker,
- std::string pattern,
- std::string filtername)
+ std::string pattern,
+ std::string filtername)
{
- GtkFileFilter *gfilter = gtk_file_filter_new();
- gtk_file_filter_add_pattern(gfilter, pattern.c_str());
- add_common_filters_to_gtkchooser(gfilter, picker, filtername);
- return filtername;
+ GtkFileFilter *gfilter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(gfilter, pattern.c_str());
+ add_common_filters_to_gtkchooser(gfilter, picker, filtername);
+ return filtername;
}
static std::string add_simple_mime_filter_to_gtkchooser(GtkWindow *picker,
- std::string mime,
- std::string filtername)
+ std::string mime,
+ std::string filtername)
{
- GtkFileFilter *gfilter = gtk_file_filter_new();
- gtk_file_filter_add_mime_type(gfilter, mime.c_str());
- add_common_filters_to_gtkchooser(gfilter, picker, filtername);
- return filtername;
+ GtkFileFilter *gfilter = gtk_file_filter_new();
+ gtk_file_filter_add_mime_type(gfilter, mime.c_str());
+ add_common_filters_to_gtkchooser(gfilter, picker, filtername);
+ return filtername;
}
static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker)
{
- return add_simple_mime_filter_to_gtkchooser(picker, "audio/x-wav",
- LLTrans::getString("sound_files") + " (*.wav)");
+ return add_simple_mime_filter_to_gtkchooser(picker, "audio/x-wav",
+ LLTrans::getString("sound_files") + " (*.wav)");
}
static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker)
{
- GtkFileFilter *gfilter = gtk_file_filter_new();
- gtk_file_filter_add_pattern(gfilter, "*.bvh");
- gtk_file_filter_add_pattern(gfilter, "*.anim");
- std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)";
- add_common_filters_to_gtkchooser(gfilter, picker, filtername);
- return filtername;
+ GtkFileFilter *gfilter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(gfilter, "*.bvh");
+ gtk_file_filter_add_pattern(gfilter, "*.anim");
+ std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)";
+ add_common_filters_to_gtkchooser(gfilter, picker, filtername);
+ return filtername;
}
static std::string add_xml_filter_to_gtkchooser(GtkWindow *picker)
{
- return add_simple_pattern_filter_to_gtkchooser(picker, "*.xml",
- LLTrans::getString("xml_files") + " (*.xml)");
+ return add_simple_pattern_filter_to_gtkchooser(picker, "*.xml",
+ LLTrans::getString("xml_files") + " (*.xml)");
}
static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker)
{
- return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae",
- LLTrans::getString("scene_files") + " (*.dae)");
+ return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae",
+ LLTrans::getString("scene_files") + " (*.dae)");
}
static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
{
- GtkFileFilter *gfilter = gtk_file_filter_new();
- gtk_file_filter_add_pattern(gfilter, "*.tga");
- gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str());
- gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str());
- gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str());
- std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)";
- add_common_filters_to_gtkchooser(gfilter, picker, filtername);
- return filtername;
+ GtkFileFilter *gfilter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(gfilter, "*.tga");
+ gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str());
+ gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str());
+ gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str());
+ std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)";
+ add_common_filters_to_gtkchooser(gfilter, picker, filtername);
+ return filtername;
}
-
+
static std::string add_script_filter_to_gtkchooser(GtkWindow *picker)
{
- return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN,
- LLTrans::getString("script_files") + " (*.lsl)");
+ return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN,
+ LLTrans::getString("script_files") + " (*.lsl)");
}
static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker)
{
- return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN,
- LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)");
+ return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN,
+ LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)");
}
static std::string add_save_texture_filter_to_gtkchooser(GtkWindow *picker)
{
- GtkFileFilter *gfilter_tga = gtk_file_filter_new();
- GtkFileFilter *gfilter_png = gtk_file_filter_new();
-
- gtk_file_filter_add_pattern(gfilter_tga, "*.tga");
- gtk_file_filter_add_mime_type(gfilter_png, "image/png");
- std::string caption = LLTrans::getString("save_texture_image_files") + " (*.tga; *.png)";
- gtk_file_filter_set_name(gfilter_tga, LLTrans::getString("targa_image_files").c_str());
- gtk_file_filter_set_name(gfilter_png, LLTrans::getString("png_image_files").c_str());
-
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
- gfilter_png);
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
- gfilter_tga);
- return caption;
+ GtkFileFilter *gfilter_tga = gtk_file_filter_new();
+ GtkFileFilter *gfilter_png = gtk_file_filter_new();
+
+ gtk_file_filter_add_pattern(gfilter_tga, "*.tga");
+ gtk_file_filter_add_mime_type(gfilter_png, "image/png");
+ std::string caption = LLTrans::getString("save_texture_image_files") + " (*.tga; *.png)";
+ gtk_file_filter_set_name(gfilter_tga, LLTrans::getString("targa_image_files").c_str());
+ gtk_file_filter_set_name(gfilter_png, LLTrans::getString("png_image_files").c_str());
+
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
+ gfilter_png);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
+ gfilter_tga);
+ return caption;
}
BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking )
{
- BOOL rtn = FALSE;
-
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
- gViewerWindow->getWindow()->beforeDialog();
-
- reset();
-
- GtkWindow* picker = buildFilePicker(true, false, "savefile");
-
- if (picker)
- {
- std::string suggest_name = "untitled";
- std::string suggest_ext = "";
- std::string caption = LLTrans::getString("save_file_verb") + " ";
- switch (filter)
- {
- case FFSAVE_WAV:
- caption += add_wav_filter_to_gtkchooser(picker);
- suggest_ext = ".wav";
- break;
- case FFSAVE_TGA:
- caption += add_simple_pattern_filter_to_gtkchooser
- (picker, "*.tga", LLTrans::getString("targa_image_files") + " (*.tga)");
- suggest_ext = ".tga";
- break;
- case FFSAVE_BMP:
- caption += add_simple_mime_filter_to_gtkchooser
- (picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)");
- suggest_ext = ".bmp";
- break;
- case FFSAVE_PNG:
- caption += add_simple_mime_filter_to_gtkchooser
- (picker, "image/png", LLTrans::getString("png_image_files") + " (*.png)");
- suggest_ext = ".png";
- break;
- case FFSAVE_TGAPNG:
- caption += add_save_texture_filter_to_gtkchooser(picker);
- suggest_ext = ".png";
- break;
- case FFSAVE_AVI:
- caption += add_simple_mime_filter_to_gtkchooser
- (picker, "video/x-msvideo",
- LLTrans::getString("avi_movie_file") + " (*.avi)");
- suggest_ext = ".avi";
- break;
- case FFSAVE_ANIM:
- caption += add_simple_pattern_filter_to_gtkchooser
- (picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)");
- suggest_ext = ".xaf";
- break;
- case FFSAVE_XML:
- caption += add_simple_pattern_filter_to_gtkchooser
- (picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)");
- suggest_ext = ".xml";
- break;
- case FFSAVE_RAW:
- caption += add_simple_pattern_filter_to_gtkchooser
- (picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)");
- suggest_ext = ".raw";
- break;
- case FFSAVE_J2C:
- // *TODO: Should this be 'image/j2c' ?
- caption += add_simple_mime_filter_to_gtkchooser
- (picker, "images/jp2",
- LLTrans::getString("compressed_image_files") + " (*.j2c)");
- suggest_ext = ".j2c";
- break;
- case FFSAVE_SCRIPT:
- caption += add_script_filter_to_gtkchooser(picker);
- suggest_ext = ".lsl";
- break;
- default:;
- break;
- }
-
- gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
-
- if (filename.empty())
- {
- suggest_name += suggest_ext;
-
- gtk_file_chooser_set_current_name
- (GTK_FILE_CHOOSER(picker),
- suggest_name.c_str());
- }
- else
- {
- gtk_file_chooser_set_current_name
- (GTK_FILE_CHOOSER(picker), filename.c_str());
- }
-
- gtk_widget_show_all(GTK_WIDGET(picker));
-
- gtk_main();
-
- rtn = (getFileCount() == 1);
-
- if(rtn && filter == FFSAVE_TGAPNG)
- {
- std::string selected_file = mFiles.back();
- mFiles.pop_back();
- mFiles.push_back(selected_file + mCurrentExtension);
- }
- }
-
- gViewerWindow->getWindow()->afterDialog();
-
- return rtn;
+ BOOL rtn = FALSE;
+
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
+ gViewerWindow->getWindow()->beforeDialog();
+
+ reset();
+
+ GtkWindow* picker = buildFilePicker(true, false, "savefile");
+
+ if (picker)
+ {
+ std::string suggest_name = "untitled";
+ std::string suggest_ext = "";
+ std::string caption = LLTrans::getString("save_file_verb") + " ";
+ switch (filter)
+ {
+ case FFSAVE_WAV:
+ caption += add_wav_filter_to_gtkchooser(picker);
+ suggest_ext = ".wav";
+ break;
+ case FFSAVE_TGA:
+ caption += add_simple_pattern_filter_to_gtkchooser
+ (picker, "*.tga", LLTrans::getString("targa_image_files") + " (*.tga)");
+ suggest_ext = ".tga";
+ break;
+ case FFSAVE_BMP:
+ caption += add_simple_mime_filter_to_gtkchooser
+ (picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)");
+ suggest_ext = ".bmp";
+ break;
+ case FFSAVE_PNG:
+ caption += add_simple_mime_filter_to_gtkchooser
+ (picker, "image/png", LLTrans::getString("png_image_files") + " (*.png)");
+ suggest_ext = ".png";
+ break;
+ case FFSAVE_TGAPNG:
+ caption += add_save_texture_filter_to_gtkchooser(picker);
+ suggest_ext = ".png";
+ break;
+ case FFSAVE_AVI:
+ caption += add_simple_mime_filter_to_gtkchooser
+ (picker, "video/x-msvideo",
+ LLTrans::getString("avi_movie_file") + " (*.avi)");
+ suggest_ext = ".avi";
+ break;
+ case FFSAVE_ANIM:
+ caption += add_simple_pattern_filter_to_gtkchooser
+ (picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)");
+ suggest_ext = ".xaf";
+ break;
+ case FFSAVE_XML:
+ caption += add_simple_pattern_filter_to_gtkchooser
+ (picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)");
+ suggest_ext = ".xml";
+ break;
+ case FFSAVE_RAW:
+ caption += add_simple_pattern_filter_to_gtkchooser
+ (picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)");
+ suggest_ext = ".raw";
+ break;
+ case FFSAVE_J2C:
+ // *TODO: Should this be 'image/j2c' ?
+ caption += add_simple_mime_filter_to_gtkchooser
+ (picker, "images/jp2",
+ LLTrans::getString("compressed_image_files") + " (*.j2c)");
+ suggest_ext = ".j2c";
+ break;
+ case FFSAVE_SCRIPT:
+ caption += add_script_filter_to_gtkchooser(picker);
+ suggest_ext = ".lsl";
+ break;
+ default:;
+ break;
+ }
+
+ gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
+
+ if (filename.empty())
+ {
+ suggest_name += suggest_ext;
+
+ gtk_file_chooser_set_current_name
+ (GTK_FILE_CHOOSER(picker),
+ suggest_name.c_str());
+ }
+ else
+ {
+ gtk_file_chooser_set_current_name
+ (GTK_FILE_CHOOSER(picker), filename.c_str());
+ }
+
+ gtk_widget_show_all(GTK_WIDGET(picker));
+
+ gtk_main();
+
+ rtn = (getFileCount() == 1);
+
+ if(rtn && filter == FFSAVE_TGAPNG)
+ {
+ std::string selected_file = mFiles.back();
+ mFiles.pop_back();
+ mFiles.push_back(selected_file + mCurrentExtension);
+ }
+ }
+
+ gViewerWindow->getWindow()->afterDialog();
+
+ return rtn;
}
BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
{
- BOOL rtn = FALSE;
-
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
- gViewerWindow->getWindow()->beforeDialog();
-
- reset();
-
- GtkWindow* picker = buildFilePicker(false, false, "openfile");
-
- if (picker)
- {
- std::string caption = LLTrans::getString("load_file_verb") + " ";
- std::string filtername = "";
- switch (filter)
- {
- case FFLOAD_WAV:
- filtername = add_wav_filter_to_gtkchooser(picker);
- break;
- case FFLOAD_ANIM:
- filtername = add_anim_filter_to_gtkchooser(picker);
- break;
- case FFLOAD_XML:
- filtername = add_xml_filter_to_gtkchooser(picker);
- break;
+ BOOL rtn = FALSE;
+
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
+ gViewerWindow->getWindow()->beforeDialog();
+
+ reset();
+
+ GtkWindow* picker = buildFilePicker(false, false, "openfile");
+
+ if (picker)
+ {
+ std::string caption = LLTrans::getString("load_file_verb") + " ";
+ std::string filtername = "";
+ switch (filter)
+ {
+ case FFLOAD_WAV:
+ filtername = add_wav_filter_to_gtkchooser(picker);
+ break;
+ case FFLOAD_ANIM:
+ filtername = add_anim_filter_to_gtkchooser(picker);
+ break;
+ case FFLOAD_XML:
+ filtername = add_xml_filter_to_gtkchooser(picker);
+ break;
case FFLOAD_GLTF:
filtername = dead_code_should_blow_up_here(picker);
break;
@@ -1515,64 +1520,64 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
filtername = add_collada_filter_to_gtkchooser(picker);
break;
case FFLOAD_IMAGE:
- filtername = add_imageload_filter_to_gtkchooser(picker);
- break;
- case FFLOAD_SCRIPT:
- filtername = add_script_filter_to_gtkchooser(picker);
- break;
- case FFLOAD_DICTIONARY:
- filtername = add_dictionary_filter_to_gtkchooser(picker);
- break;
- default:;
- break;
- }
-
- caption += filtername;
-
- gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
-
- gtk_widget_show_all(GTK_WIDGET(picker));
- gtk_main();
-
- rtn = (getFileCount() == 1);
- }
-
- gViewerWindow->getWindow()->afterDialog();
-
- return rtn;
+ filtername = add_imageload_filter_to_gtkchooser(picker);
+ break;
+ case FFLOAD_SCRIPT:
+ filtername = add_script_filter_to_gtkchooser(picker);
+ break;
+ case FFLOAD_DICTIONARY:
+ filtername = add_dictionary_filter_to_gtkchooser(picker);
+ break;
+ default:;
+ break;
+ }
+
+ caption += filtername;
+
+ gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
+
+ gtk_widget_show_all(GTK_WIDGET(picker));
+ gtk_main();
+
+ rtn = (getFileCount() == 1);
+ }
+
+ gViewerWindow->getWindow()->afterDialog();
+
+ return rtn;
}
BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
{
- BOOL rtn = FALSE;
-
- // if local file browsing is turned off, return without opening dialog
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
+ BOOL rtn = FALSE;
- gViewerWindow->getWindow()->beforeDialog();
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
- reset();
+ gViewerWindow->getWindow()->beforeDialog();
- GtkWindow* picker = buildFilePicker(false, false, "openfile");
+ reset();
+
+ GtkWindow* picker = buildFilePicker(false, false, "openfile");
- if (picker)
- {
- gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker),
- TRUE);
+ if (picker)
+ {
+ gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker),
+ TRUE);
- gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str());
+ gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str());
- gtk_widget_show_all(GTK_WIDGET(picker));
- gtk_main();
- rtn = !mFiles.empty();
- }
+ gtk_widget_show_all(GTK_WIDGET(picker));
+ gtk_main();
+ rtn = !mFiles.empty();
+ }
- gViewerWindow->getWindow()->afterDialog();
+ gViewerWindow->getWindow()->afterDialog();
- return rtn;
+ return rtn;
}
# else // LL_GTK
@@ -1582,23 +1587,23 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking )
{
- // if local file browsing is turned off, return without opening dialog
- // (Even though this is a stub, I think we still should not return anything at all)
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
- reset();
-
- LL_INFOS() << "getSaveFile suggested filename is [" << filename
- << "]" << LL_ENDL;
- if (!filename.empty())
- {
- mFiles.push_back(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + filename);
- return TRUE;
- }
- return FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ // (Even though this is a stub, I think we still should not return anything at all)
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
+ reset();
+
+ LL_INFOS() << "getSaveFile suggested filename is [" << filename
+ << "]" << LL_ENDL;
+ if (!filename.empty())
+ {
+ mFiles.push_back(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + filename);
+ return TRUE;
+ }
+ return FALSE;
}
BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
@@ -1612,27 +1617,27 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
{
- // if local file browsing is turned off, return without opening dialog
- // (Even though this is a stub, I think we still should not return anything at all)
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
- reset();
-
- // HACK: Static filenames for 'open' until we implement filepicker
- std::string filename = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + "upload";
- switch (filter)
- {
- case FFLOAD_WAV: filename += ".wav"; break;
- case FFLOAD_IMAGE: filename += ".tga"; break;
- case FFLOAD_ANIM: filename += ".bvh"; break;
- default: break;
- }
- mFiles.push_back(filename);
- LL_INFOS() << "getOpenFile: Will try to open file: " << filename << LL_ENDL;
- return TRUE;
+ // if local file browsing is turned off, return without opening dialog
+ // (Even though this is a stub, I think we still should not return anything at all)
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
+ reset();
+
+ // HACK: Static filenames for 'open' until we implement filepicker
+ std::string filename = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + "upload";
+ switch (filter)
+ {
+ case FFLOAD_WAV: filename += ".wav"; break;
+ case FFLOAD_IMAGE: filename += ".tga"; break;
+ case FFLOAD_ANIM: filename += ".bvh"; break;
+ default: break;
+ }
+ mFiles.push_back(filename);
+ LL_INFOS() << "getOpenFile: Will try to open file: " << filename << LL_ENDL;
+ return TRUE;
}
BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter,
@@ -1645,15 +1650,15 @@ BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter,
BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
{
- // if local file browsing is turned off, return without opening dialog
- // (Even though this is a stub, I think we still should not return anything at all)
- if ( check_local_file_access_enabled() == false )
- {
- return FALSE;
- }
-
- reset();
- return FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ // (Even though this is a stub, I think we still should not return anything at all)
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
+ reset();
+ return FALSE;
}
BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
@@ -1670,20 +1675,20 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )
{
- reset();
- return FALSE;
+ reset();
+ return FALSE;
}
BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
{
- reset();
- return FALSE;
+ reset();
+ return FALSE;
}
BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
{
- reset();
- return FALSE;
+ reset();
+ return FALSE;
}
#endif // LL_LINUX
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 7149ced34a..f00f076d1c 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfilepicker.h
* @brief OS-specific file picker
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -64,118 +64,119 @@ extern "C" {
class LLFilePicker
{
#ifdef LL_GTK
- friend class LLDirPicker;
- friend void chooser_responder(GtkWidget *, gint, gpointer);
+ friend class LLDirPicker;
+ friend void chooser_responder(GtkWidget *, gint, gpointer);
#endif // LL_GTK
public:
- // calling this before main() is undefined
- static LLFilePicker& instance( void ) { return sInstance; }
-
- enum ELoadFilter
- {
- FFLOAD_ALL = 1,
- FFLOAD_WAV = 2,
- FFLOAD_IMAGE = 3,
- FFLOAD_ANIM = 4,
- FFLOAD_GLTF = 5,
- FFLOAD_XML = 6,
- FFLOAD_SLOBJECT = 7,
- FFLOAD_RAW = 8,
- FFLOAD_MODEL = 9,
- FFLOAD_COLLADA = 10,
- FFLOAD_SCRIPT = 11,
- FFLOAD_DICTIONARY = 12,
+ // calling this before main() is undefined
+ static LLFilePicker& instance( void ) { return sInstance; }
+
+ enum ELoadFilter
+ {
+ FFLOAD_ALL = 1,
+ FFLOAD_WAV = 2,
+ FFLOAD_IMAGE = 3,
+ FFLOAD_ANIM = 4,
+ FFLOAD_GLTF = 5,
+ FFLOAD_XML = 6,
+ FFLOAD_SLOBJECT = 7,
+ FFLOAD_RAW = 8,
+ FFLOAD_MODEL = 9,
+ FFLOAD_COLLADA = 10,
+ FFLOAD_SCRIPT = 11,
+ FFLOAD_DICTIONARY = 12,
FFLOAD_DIRECTORY = 13, // To call from lldirpicker.
FFLOAD_EXE = 14, // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin
FFLOAD_MATERIAL = 15,
FFLOAD_MATERIAL_TEXTURE = 16,
- };
-
- enum ESaveFilter
- {
- FFSAVE_ALL = 1,
- FFSAVE_WAV = 3,
- FFSAVE_TGA = 4,
- FFSAVE_BMP = 5,
- FFSAVE_AVI = 6,
- FFSAVE_ANIM = 7,
- FFSAVE_GLTF = 8,
- FFSAVE_XML = 9,
- FFSAVE_COLLADA = 10,
- FFSAVE_RAW = 11,
- FFSAVE_J2C = 12,
- FFSAVE_PNG = 13,
- FFSAVE_JPEG = 14,
- FFSAVE_SCRIPT = 15,
- FFSAVE_TGAPNG = 16
- };
-
- // open the dialog. This is a modal operation
- BOOL getSaveFile( ESaveFilter filter = FFSAVE_ALL, const std::string& filename = LLStringUtil::null, bool blocking = true);
+ FFLOAD_LUA = 17,
+ };
+
+ enum ESaveFilter
+ {
+ FFSAVE_ALL = 1,
+ FFSAVE_WAV = 3,
+ FFSAVE_TGA = 4,
+ FFSAVE_BMP = 5,
+ FFSAVE_AVI = 6,
+ FFSAVE_ANIM = 7,
+ FFSAVE_GLTF = 8,
+ FFSAVE_XML = 9,
+ FFSAVE_COLLADA = 10,
+ FFSAVE_RAW = 11,
+ FFSAVE_J2C = 12,
+ FFSAVE_PNG = 13,
+ FFSAVE_JPEG = 14,
+ FFSAVE_SCRIPT = 15,
+ FFSAVE_TGAPNG = 16
+ };
+
+ // open the dialog. This is a modal operation
+ BOOL getSaveFile( ESaveFilter filter = FFSAVE_ALL, const std::string& filename = LLStringUtil::null, bool blocking = true);
BOOL getSaveFileModeless(ESaveFilter filter,
const std::string& filename,
void (*callback)(bool, std::string&, void*),
void *userdata);
- BOOL getOpenFile( ELoadFilter filter = FFLOAD_ALL, bool blocking = true );
+ BOOL getOpenFile( ELoadFilter filter = FFLOAD_ALL, bool blocking = true );
// Todo: implement getOpenFileModeless and getMultipleOpenFilesModeless
// for windows and use directly instead of ugly LLFilePickerThread
BOOL getOpenFileModeless( ELoadFilter filter, void (*callback)(bool, std::vector<std::string> &, void*), void *userdata); // MAC only.
- BOOL getMultipleOpenFiles( ELoadFilter filter = FFLOAD_ALL, bool blocking = true );
+ BOOL getMultipleOpenFiles( ELoadFilter filter = FFLOAD_ALL, bool blocking = true );
BOOL getMultipleOpenFilesModeless( ELoadFilter filter, void (*callback)(bool, std::vector<std::string> &, void*), void *userdata ); // MAC only
- // Get the filename(s) found. getFirstFile() sets the pointer to
- // the start of the structure and allows the start of iteration.
- const std::string getFirstFile();
-
- // getNextFile() increments the internal representation and
- // returns the next file specified by the user. Returns NULL when
- // no more files are left. Further calls to getNextFile() are
- // undefined.
- const std::string getNextFile();
+ // Get the filename(s) found. getFirstFile() sets the pointer to
+ // the start of the structure and allows the start of iteration.
+ const std::string getFirstFile();
- // This utility function extracts the current file name without
- // doing any incrementing.
- const std::string getCurFile();
+ // getNextFile() increments the internal representation and
+ // returns the next file specified by the user. Returns NULL when
+ // no more files are left. Further calls to getNextFile() are
+ // undefined.
+ const std::string getNextFile();
- // Returns the index of the current file.
- S32 getCurFileNum() const { return mCurrentFile; }
+ // This utility function extracts the current file name without
+ // doing any incrementing.
+ const std::string getCurFile();
- S32 getFileCount() const { return (S32)mFiles.size(); }
+ // Returns the index of the current file.
+ S32 getCurFileNum() const { return mCurrentFile; }
- // see lldir.h : getBaseFileName and getDirName to extract base or directory names
+ S32 getFileCount() const { return (S32)mFiles.size(); }
- // clear any lists of buffers or whatever, and make sure the file
- // picker isn't locked.
- void reset();
+ // see lldir.h : getBaseFileName and getDirName to extract base or directory names
+
+ // clear any lists of buffers or whatever, and make sure the file
+ // picker isn't locked.
+ void reset();
private:
- enum
- {
- SINGLE_FILENAME_BUFFER_SIZE = 1024,
- //FILENAME_BUFFER_SIZE = 65536
- FILENAME_BUFFER_SIZE = 65000
- };
-
- // utility function to check if access to local file system via file browser
- // is enabled and if not, tidy up and indicate we're not allowed to do this.
- bool check_local_file_access_enabled();
-
+ enum
+ {
+ SINGLE_FILENAME_BUFFER_SIZE = 1024,
+ //FILENAME_BUFFER_SIZE = 65536
+ FILENAME_BUFFER_SIZE = 65000
+ };
+
+ // utility function to check if access to local file system via file browser
+ // is enabled and if not, tidy up and indicate we're not allowed to do this.
+ bool check_local_file_access_enabled();
+
#if LL_WINDOWS
- OPENFILENAMEW mOFN; // for open and save dialogs
- WCHAR mFilesW[FILENAME_BUFFER_SIZE];
+ OPENFILENAMEW mOFN; // for open and save dialogs
+ WCHAR mFilesW[FILENAME_BUFFER_SIZE];
- BOOL setupFilter(ELoadFilter filter);
+ BOOL setupFilter(ELoadFilter filter);
#endif
#if LL_DARWIN
S32 mPickOptions;
- std::vector<std::string> mFileVector;
-
- bool doNavChooseDialog(ELoadFilter filter);
- bool doNavChooseDialogModeless(ELoadFilter filter,
+ std::vector<std::string> mFileVector;
+
+ bool doNavChooseDialog(ELoadFilter filter);
+ bool doNavChooseDialogModeless(ELoadFilter filter,
void (*callback)(bool, std::vector<std::string>&, void*),
void *userdata);
- bool doNavSaveDialog(ESaveFilter filter, const std::string& filename);
+ bool doNavSaveDialog(ESaveFilter filter, const std::string& filename);
std::unique_ptr<std::vector<std::string>> navOpenFilterProc(ELoadFilter filter);
bool doNavSaveDialogModeless(ESaveFilter filter,
const std::string& filename,
@@ -184,31 +185,31 @@ private:
#endif
#if LL_GTK
- static void add_to_selectedfiles(gpointer data, gpointer user_data);
- static void chooser_responder(GtkWidget *widget, gint response, gpointer user_data);
- // we remember the last path that was accessed for a particular usage
- std::map <std::string, std::string> mContextToPathMap;
- std::string mCurContextName;
- // we also remember the extension of the last added file.
- std::string mCurrentExtension;
+ static void add_to_selectedfiles(gpointer data, gpointer user_data);
+ static void chooser_responder(GtkWidget *widget, gint response, gpointer user_data);
+ // we remember the last path that was accessed for a particular usage
+ std::map <std::string, std::string> mContextToPathMap;
+ std::string mCurContextName;
+ // we also remember the extension of the last added file.
+ std::string mCurrentExtension;
#endif
- std::vector<std::string> mFiles;
- S32 mCurrentFile;
- bool mLocked;
-
- static LLFilePicker sInstance;
+ std::vector<std::string> mFiles;
+ S32 mCurrentFile;
+ bool mLocked;
+ static LLFilePicker sInstance;
+
protected:
#if LL_GTK
GtkWindow* buildFilePicker(bool is_save, bool is_folder,
- std::string context = "generic");
+ std::string context = "generic");
#endif
public:
- // don't call these directly please.
- LLFilePicker();
- ~LLFilePicker();
+ // don't call these directly please.
+ LLFilePicker();
+ ~LLFilePicker();
};
#endif
diff --git a/indra/newview/llfloaterluadebug.cpp b/indra/newview/llfloaterluadebug.cpp
new file mode 100644
index 0000000000..6fd11dd1c7
--- /dev/null
+++ b/indra/newview/llfloaterluadebug.cpp
@@ -0,0 +1,155 @@
+/**
+ * @file llfloaterluadebug.cpp
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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 "llfloaterluadebug.h"
+
+#include "llcheckboxctrl.h"
+#include "lllineeditor.h"
+#include "lltexteditor.h"
+#include "llviewermenufile.h" // LLFilePickerReplyThread
+
+#include "llagent.h"
+#include "llappearancemgr.h"
+#include "llfloaterreg.h"
+#include "llfloaterimnearbychat.h"
+
+#include "llluamanager.h"
+#include "llsdutil.h"
+#include "lua_function.h"
+#include "stringize.h"
+
+
+LLFloaterLUADebug::LLFloaterLUADebug(const LLSD &key)
+ : LLFloater(key)
+{
+}
+
+
+BOOL LLFloaterLUADebug::postBuild()
+{
+ mResultOutput = getChild<LLTextEditor>("result_text");
+ mLineInput = getChild<LLLineEditor>("lua_cmd");
+ mScriptPath = getChild<LLLineEditor>("script_path");
+ mOutConnection = LLEventPumps::instance().obtain("lua output")
+ .listen("LLFloaterLUADebug",
+ [mResultOutput=mResultOutput](const LLSD& data)
+ {
+ mResultOutput->pasteTextWithLinebreaks(data.asString());
+ mResultOutput->addLineBreakChar(true);
+ return false;
+ });
+
+ getChild<LLButton>("execute_btn")->setClickedCallback(boost::bind(&LLFloaterLUADebug::onExecuteClicked, this));
+ getChild<LLButton>("browse_btn")->setClickedCallback(boost::bind(&LLFloaterLUADebug::onBtnBrowse, this));
+ getChild<LLButton>("run_btn")->setClickedCallback(boost::bind(&LLFloaterLUADebug::onBtnRun, this));
+ mLineInput->setCommitCallback(boost::bind(&LLFloaterLUADebug::onExecuteClicked, this));
+ mLineInput->setSelectAllonCommit(false);
+
+ return TRUE;
+}
+
+LLFloaterLUADebug::~LLFloaterLUADebug()
+{}
+
+void LLFloaterLUADebug::onExecuteClicked()
+{
+ mResultOutput->setValue("");
+
+ std::string cmd = mLineInput->getText();
+ cleanLuaState();
+ LLLUAmanager::runScriptLine(mState, cmd, [this](int count, const LLSD& result)
+ {
+ completion(count, result);
+ });
+}
+
+void LLFloaterLUADebug::onBtnBrowse()
+{
+ LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterLUADebug::runSelectedScript, this, _1), LLFilePicker::FFLOAD_LUA, false);
+}
+
+void LLFloaterLUADebug::onBtnRun()
+{
+ std::vector<std::string> filenames;
+ std::string filepath = mScriptPath->getText();
+ if (!filepath.empty())
+ {
+ filenames.push_back(filepath);
+ runSelectedScript(filenames);
+ }
+}
+
+void LLFloaterLUADebug::runSelectedScript(const std::vector<std::string> &filenames)
+{
+ mResultOutput->setValue("");
+
+ std::string filepath = filenames[0];
+ if (!filepath.empty())
+ {
+ mScriptPath->setText(filepath);
+ LLLUAmanager::runScriptFile(filepath, [this](int count, const LLSD &result)
+ {
+ completion(count, result);
+ });
+ }
+}
+
+void LLFloaterLUADebug::completion(int count, const LLSD& result)
+{
+ if (count < 0)
+ {
+ // error: show error message
+ LLStyle::Params params;
+ params.readonly_color = LLUIColorTable::instance().getColor("LtRed");
+ mResultOutput->appendText(result.asString(), false, params);
+ mResultOutput->endOfDoc();
+ return;
+ }
+ if (count == 1)
+ {
+ // single result
+ mResultOutput->pasteTextWithLinebreaks(stringize(result));
+ return;
+ }
+ // 0 or multiple results
+ const char* sep = "";
+ for (const auto& item : llsd::inArray(result))
+ {
+ mResultOutput->insertText(sep);
+ mResultOutput->pasteTextWithLinebreaks(stringize(item));
+ sep = ", ";
+ }
+}
+
+void LLFloaterLUADebug::cleanLuaState()
+{
+ if(getChild<LLCheckBoxCtrl>("clean_lua_state")->get())
+ {
+ //Reinit to clean lua_State
+ mState.initLuaState();
+ }
+}
diff --git a/indra/newview/llfloaterluadebug.h b/indra/newview/llfloaterluadebug.h
new file mode 100644
index 0000000000..7418174570
--- /dev/null
+++ b/indra/newview/llfloaterluadebug.h
@@ -0,0 +1,72 @@
+/**
+ * @file llfloaterluadebug.h
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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_LLFLOATERLUADEBUG_H
+#define LL_LLFLOATERLUADEBUG_H
+
+#include "llevents.h"
+#include "llfloater.h"
+#include "lua_function.h"
+
+extern "C"
+{
+#include "luau/luacode.h"
+#include "luau/lua.h"
+#include "luau/luaconf.h"
+#include "luau/lualib.h"
+}
+
+class LLLineEditor;
+class LLTextEditor;
+
+class LLFloaterLUADebug :
+ public LLFloater
+{
+ public:
+ LLFloaterLUADebug(const LLSD& key);
+ virtual ~LLFloaterLUADebug();
+
+ /*virtual*/ BOOL postBuild();
+
+ void onExecuteClicked();
+ void onBtnBrowse();
+ void onBtnRun();
+
+ void runSelectedScript(const std::vector<std::string> &filenames);
+
+private:
+ void completion(int count, const LLSD& result);
+ void cleanLuaState();
+
+ LLTempBoundListener mOutConnection;
+
+ LLTextEditor* mResultOutput;
+ LLLineEditor* mLineInput;
+ LLLineEditor* mScriptPath;
+ LuaState mState;
+};
+
+#endif // LL_LLFLOATERLUADEBUG_H
+
diff --git a/indra/newview/llfloaterluascripts.cpp b/indra/newview/llfloaterluascripts.cpp
new file mode 100644
index 0000000000..39d5816b0d
--- /dev/null
+++ b/indra/newview/llfloaterluascripts.cpp
@@ -0,0 +1,131 @@
+/**
+ * @file llfloaterluascriptsinfo.cpp
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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 "llfloaterluascripts.h"
+#include "llevents.h"
+#include <filesystem>
+#include "llluamanager.h"
+#include "llscrolllistctrl.h"
+#include "llviewerwindow.h"
+#include "llwindow.h"
+#include "llviewermenu.h"
+
+const F32 REFRESH_INTERVAL = 1.0f;
+
+LLFloaterLUAScripts::LLFloaterLUAScripts(const LLSD &key)
+ : LLFloater(key),
+ mUpdateTimer(new LLTimer()),
+ mContextMenuHandle()
+{
+ mCommitCallbackRegistrar.add("Script.OpenFolder", [this](LLUICtrl*, const LLSD &userdata)
+ {
+ if (mScriptList->hasSelectedItem())
+ {
+ std::string target_folder_path = std::filesystem::path((mScriptList->getFirstSelected()->getColumn(1)->getValue().asString())).parent_path().string();
+ gViewerWindow->getWindow()->openFolder(target_folder_path);
+ }
+ });
+ mCommitCallbackRegistrar.add("Script.Terminate", [this](LLUICtrl*, const LLSD &userdata)
+ {
+ if (mScriptList->hasSelectedItem())
+ {
+ std::string coro_name = mScriptList->getSelectedValue();
+ LLCoros::instance().killreq(coro_name);
+ }
+ });
+}
+
+
+BOOL LLFloaterLUAScripts::postBuild()
+{
+ mScriptList = getChild<LLScrollListCtrl>("scripts_list");
+ mScriptList->setRightMouseDownCallback([this](LLUICtrl *ctrl, S32 x, S32 y, MASK mask) { onScrollListRightClicked(ctrl, x, y);});
+
+ LLContextMenu *menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+ "menu_lua_scripts.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mContextMenuHandle = menu->getHandle();
+ }
+
+ return TRUE;
+}
+
+LLFloaterLUAScripts::~LLFloaterLUAScripts()
+{
+ auto menu = mContextMenuHandle.get();
+ if (menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
+}
+
+void LLFloaterLUAScripts::draw()
+{
+ if (mUpdateTimer->checkExpirationAndReset(REFRESH_INTERVAL))
+ {
+ populateScriptList();
+ }
+ LLFloater::draw();
+}
+
+void LLFloaterLUAScripts::populateScriptList()
+{
+ S32 prev_pos = mScriptList->getScrollPos();
+ LLSD prev_selected = mScriptList->getSelectedValue();
+ mScriptList->clearRows();
+ mScriptList->updateColumns(true);
+ std::map<std::string, std::string> scripts = LLLUAmanager::getScriptNames();
+ for (auto &it : scripts)
+ {
+ LLSD row;
+ row["value"] = it.first;
+ row["columns"][0]["value"] = std::filesystem::path((it.second)).stem().string();
+ row["columns"][0]["column"] = "script_name";
+ row["columns"][1]["value"] = it.second;
+ row["columns"][1]["column"] = "script_path";
+ mScriptList->addElement(row);
+ }
+ mScriptList->setScrollPos(prev_pos);
+ mScriptList->setSelectedByValue(prev_selected, true);
+}
+
+void LLFloaterLUAScripts::onScrollListRightClicked(LLUICtrl *ctrl, S32 x, S32 y)
+{
+ LLScrollListItem *item = mScriptList->hitItem(x, y);
+ if (item)
+ {
+ mScriptList->selectItemAt(x, y, MASK_NONE);
+ auto menu = mContextMenuHandle.get();
+ if (menu)
+ {
+ menu->show(x, y);
+ LLMenuGL::showPopup(this, menu, x, y);
+ }
+ }
+}
diff --git a/indra/newview/llfloaterluascripts.h b/indra/newview/llfloaterluascripts.h
new file mode 100644
index 0000000000..932c5c78dd
--- /dev/null
+++ b/indra/newview/llfloaterluascripts.h
@@ -0,0 +1,54 @@
+/**
+ * @file llfloaterluascriptsinfo.h
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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_LLFLOATERLUASCRIPTS_H
+#define LL_LLFLOATERLUASCRIPTS_H
+
+#include "llfloater.h"
+
+class LLScrollListCtrl;
+
+class LLFloaterLUAScripts :
+ public LLFloater
+{
+ public:
+ LLFloaterLUAScripts(const LLSD &key);
+ virtual ~LLFloaterLUAScripts();
+
+ BOOL postBuild();
+ void draw();
+
+private:
+ void populateScriptList();
+ void onScrollListRightClicked(LLUICtrl *ctrl, S32 x, S32 y);
+
+ std::unique_ptr<LLTimer> mUpdateTimer;
+ LLScrollListCtrl* mScriptList;
+
+ LLHandle<LLContextMenu> mContextMenuHandle;
+};
+
+#endif // LL_LLFLOATERLUASCRIPTS_H
+
diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp
index 0c5762e4b1..e1df6a4b1f 100644
--- a/indra/newview/llfloatersettingsdebug.cpp
+++ b/indra/newview/llfloatersettingsdebug.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfloatersettingsdebug.cpp
* @brief floater for debugging internal viewer settings
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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$
*/
@@ -34,14 +34,15 @@
#include "llcolorswatch.h"
#include "llviewercontrol.h"
#include "lltexteditor.h"
+#include "llclipboard.h"
-LLFloaterSettingsDebug::LLFloaterSettingsDebug(const LLSD& key)
+LLFloaterSettingsDebug::LLFloaterSettingsDebug(const LLSD& key)
: LLFloater(key),
mSettingList(NULL)
{
- mCommitCallbackRegistrar.add("CommitSettings", boost::bind(&LLFloaterSettingsDebug::onCommitSettings, this));
- mCommitCallbackRegistrar.add("ClickDefault", boost::bind(&LLFloaterSettingsDebug::onClickDefault, this));
+ mCommitCallbackRegistrar.add("CommitSettings", boost::bind(&LLFloaterSettingsDebug::onCommitSettings, this));
+ mCommitCallbackRegistrar.add("ClickDefault", boost::bind(&LLFloaterSettingsDebug::onClickDefault, this));
}
LLFloaterSettingsDebug::~LLFloaterSettingsDebug()
@@ -52,6 +53,8 @@ BOOL LLFloaterSettingsDebug::postBuild()
enableResizeCtrls(true, false, true);
mComment = getChild<LLTextEditor>("comment_text");
+ mSettingName = getChild<LLTextBox>("setting_name_txt");
+ mCopyBtn = getChild<LLButton>("copy_btn");
getChild<LLFilterEditor>("filter_input")->setCommitCallback(boost::bind(&LLFloaterSettingsDebug::setSearchFilter, this, _2));
@@ -59,11 +62,13 @@ BOOL LLFloaterSettingsDebug::postBuild()
mSettingList->setCommitOnSelectionChange(TRUE);
mSettingList->setCommitCallback(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this));
+ mCopyBtn->setCommitCallback([this](LLUICtrl *ctrl, const LLSD &param) { onClickCopy(); });
+
updateList();
gSavedSettings.getControl("DebugSettingsHideDefault")->getCommitSignal()->connect(boost::bind(&LLFloaterSettingsDebug::updateList, this, false));
- return TRUE;
+ return TRUE;
}
void LLFloaterSettingsDebug::draw()
@@ -75,7 +80,7 @@ void LLFloaterSettingsDebug::draw()
updateControl(controlp);
}
- LLFloater::draw();
+ LLFloater::draw();
}
void LLFloaterSettingsDebug::onCommitSettings()
@@ -87,78 +92,78 @@ void LLFloaterSettingsDebug::onCommitSettings()
}
LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata();
- if (!controlp)
- {
- return;
- }
-
- LLVector3 vector;
- LLVector3d vectord;
- LLQuaternion quat;
- LLRect rect;
- LLColor4 col4;
- LLColor3 col3;
- LLColor4U col4U;
- LLColor4 color_with_alpha;
-
- switch(controlp->type())
- {
- case TYPE_U32:
- controlp->set(getChild<LLUICtrl>("val_spinner_1")->getValue());
- break;
- case TYPE_S32:
- controlp->set(getChild<LLUICtrl>("val_spinner_1")->getValue());
- break;
- case TYPE_F32:
- controlp->set(LLSD(getChild<LLUICtrl>("val_spinner_1")->getValue().asReal()));
- break;
- case TYPE_BOOLEAN:
- controlp->set(getChild<LLUICtrl>("boolean_combo")->getValue());
- break;
- case TYPE_STRING:
- controlp->set(LLSD(getChild<LLUICtrl>("val_text")->getValue().asString()));
- break;
- case TYPE_VEC3:
- vector.mV[VX] = (F32)getChild<LLUICtrl>("val_spinner_1")->getValue().asReal();
- vector.mV[VY] = (F32)getChild<LLUICtrl>("val_spinner_2")->getValue().asReal();
- vector.mV[VZ] = (F32)getChild<LLUICtrl>("val_spinner_3")->getValue().asReal();
- controlp->set(vector.getValue());
- break;
- case TYPE_VEC3D:
- vectord.mdV[VX] = getChild<LLUICtrl>("val_spinner_1")->getValue().asReal();
- vectord.mdV[VY] = getChild<LLUICtrl>("val_spinner_2")->getValue().asReal();
- vectord.mdV[VZ] = getChild<LLUICtrl>("val_spinner_3")->getValue().asReal();
- controlp->set(vectord.getValue());
- break;
- case TYPE_QUAT:
- quat.mQ[VX] = getChild<LLUICtrl>("val_spinner_1")->getValue().asReal();
- quat.mQ[VY] = getChild<LLUICtrl>("val_spinner_2")->getValue().asReal();
- quat.mQ[VZ] = getChild<LLUICtrl>("val_spinner_3")->getValue().asReal();
- quat.mQ[VS] = getChild<LLUICtrl>("val_spinner_4")->getValue().asReal();;
- controlp->set(quat.getValue());
- break;
- case TYPE_RECT:
- rect.mLeft = getChild<LLUICtrl>("val_spinner_1")->getValue().asInteger();
- rect.mRight = getChild<LLUICtrl>("val_spinner_2")->getValue().asInteger();
- rect.mBottom = getChild<LLUICtrl>("val_spinner_3")->getValue().asInteger();
- rect.mTop = getChild<LLUICtrl>("val_spinner_4")->getValue().asInteger();
- controlp->set(rect.getValue());
- break;
- case TYPE_COL4:
- col3.setValue(getChild<LLUICtrl>("val_color_swatch")->getValue());
- col4 = LLColor4(col3, (F32)getChild<LLUICtrl>("val_spinner_4")->getValue().asReal());
- controlp->set(col4.getValue());
- break;
- case TYPE_COL3:
- controlp->set(getChild<LLUICtrl>("val_color_swatch")->getValue());
- //col3.mV[VRED] = (F32)floaterp->getChild<LLUICtrl>("val_spinner_1")->getValue().asC();
- //col3.mV[VGREEN] = (F32)floaterp->getChild<LLUICtrl>("val_spinner_2")->getValue().asReal();
- //col3.mV[VBLUE] = (F32)floaterp->getChild<LLUICtrl>("val_spinner_3")->getValue().asReal();
- //controlp->set(col3.getValue());
- break;
- default:
- break;
- }
+ if (!controlp)
+ {
+ return;
+ }
+
+ LLVector3 vector;
+ LLVector3d vectord;
+ LLQuaternion quat;
+ LLRect rect;
+ LLColor4 col4;
+ LLColor3 col3;
+ LLColor4U col4U;
+ LLColor4 color_with_alpha;
+
+ switch(controlp->type())
+ {
+ case TYPE_U32:
+ controlp->set(getChild<LLUICtrl>("val_spinner_1")->getValue());
+ break;
+ case TYPE_S32:
+ controlp->set(getChild<LLUICtrl>("val_spinner_1")->getValue());
+ break;
+ case TYPE_F32:
+ controlp->set(LLSD(getChild<LLUICtrl>("val_spinner_1")->getValue().asReal()));
+ break;
+ case TYPE_BOOLEAN:
+ controlp->set(getChild<LLUICtrl>("boolean_combo")->getValue());
+ break;
+ case TYPE_STRING:
+ controlp->set(LLSD(getChild<LLUICtrl>("val_text")->getValue().asString()));
+ break;
+ case TYPE_VEC3:
+ vector.mV[VX] = (F32)getChild<LLUICtrl>("val_spinner_1")->getValue().asReal();
+ vector.mV[VY] = (F32)getChild<LLUICtrl>("val_spinner_2")->getValue().asReal();
+ vector.mV[VZ] = (F32)getChild<LLUICtrl>("val_spinner_3")->getValue().asReal();
+ controlp->set(vector.getValue());
+ break;
+ case TYPE_VEC3D:
+ vectord.mdV[VX] = getChild<LLUICtrl>("val_spinner_1")->getValue().asReal();
+ vectord.mdV[VY] = getChild<LLUICtrl>("val_spinner_2")->getValue().asReal();
+ vectord.mdV[VZ] = getChild<LLUICtrl>("val_spinner_3")->getValue().asReal();
+ controlp->set(vectord.getValue());
+ break;
+ case TYPE_QUAT:
+ quat.mQ[VX] = getChild<LLUICtrl>("val_spinner_1")->getValue().asReal();
+ quat.mQ[VY] = getChild<LLUICtrl>("val_spinner_2")->getValue().asReal();
+ quat.mQ[VZ] = getChild<LLUICtrl>("val_spinner_3")->getValue().asReal();
+ quat.mQ[VS] = getChild<LLUICtrl>("val_spinner_4")->getValue().asReal();;
+ controlp->set(quat.getValue());
+ break;
+ case TYPE_RECT:
+ rect.mLeft = getChild<LLUICtrl>("val_spinner_1")->getValue().asInteger();
+ rect.mRight = getChild<LLUICtrl>("val_spinner_2")->getValue().asInteger();
+ rect.mBottom = getChild<LLUICtrl>("val_spinner_3")->getValue().asInteger();
+ rect.mTop = getChild<LLUICtrl>("val_spinner_4")->getValue().asInteger();
+ controlp->set(rect.getValue());
+ break;
+ case TYPE_COL4:
+ col3.setValue(getChild<LLUICtrl>("val_color_swatch")->getValue());
+ col4 = LLColor4(col3, (F32)getChild<LLUICtrl>("val_spinner_4")->getValue().asReal());
+ controlp->set(col4.getValue());
+ break;
+ case TYPE_COL3:
+ controlp->set(getChild<LLUICtrl>("val_color_swatch")->getValue());
+ //col3.mV[VRED] = (F32)floaterp->getChild<LLUICtrl>("val_spinner_1")->getValue().asC();
+ //col3.mV[VGREEN] = (F32)floaterp->getChild<LLUICtrl>("val_spinner_2")->getValue().asReal();
+ //col3.mV[VBLUE] = (F32)floaterp->getChild<LLUICtrl>("val_spinner_3")->getValue().asReal();
+ //controlp->set(col3.getValue());
+ break;
+ default:
+ break;
+ }
updateDefaultColumn(controlp);
}
@@ -181,31 +186,32 @@ void LLFloaterSettingsDebug::onClickDefault()
// we've switched controls, or doing per-frame update, so update spinners, etc.
void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp)
{
- LLSpinCtrl* spinner1 = getChild<LLSpinCtrl>("val_spinner_1");
- LLSpinCtrl* spinner2 = getChild<LLSpinCtrl>("val_spinner_2");
- LLSpinCtrl* spinner3 = getChild<LLSpinCtrl>("val_spinner_3");
- LLSpinCtrl* spinner4 = getChild<LLSpinCtrl>("val_spinner_4");
- LLColorSwatchCtrl* color_swatch = getChild<LLColorSwatchCtrl>("val_color_swatch");
-
- if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch)
- {
- LL_WARNS() << "Could not find all desired controls by name"
- << LL_ENDL;
- return;
- }
+ LLSpinCtrl* spinner1 = getChild<LLSpinCtrl>("val_spinner_1");
+ LLSpinCtrl* spinner2 = getChild<LLSpinCtrl>("val_spinner_2");
+ LLSpinCtrl* spinner3 = getChild<LLSpinCtrl>("val_spinner_3");
+ LLSpinCtrl* spinner4 = getChild<LLSpinCtrl>("val_spinner_4");
+ LLColorSwatchCtrl* color_swatch = getChild<LLColorSwatchCtrl>("val_color_swatch");
+
+ if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch)
+ {
+ LL_WARNS() << "Could not find all desired controls by name"
+ << LL_ENDL;
+ return;
+ }
hideUIControls();
- if (controlp && !isSettingHidden(controlp))
- {
- eControlType type = controlp->type();
+ if (controlp && !isSettingHidden(controlp))
+ {
+ eControlType type = controlp->type();
- //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame
- getChildView("boolean_combo")->setVisible( type == TYPE_BOOLEAN);
+ //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame
+ getChildView("boolean_combo")->setVisible( type == TYPE_BOOLEAN);
getChildView("default_btn")->setVisible(true);
- getChildView("setting_name_txt")->setVisible(true);
- getChild<LLTextBox>("setting_name_txt")->setText(controlp->getName());
- getChild<LLTextBox>("setting_name_txt")->setToolTip(controlp->getName());
+ mSettingName->setVisible(true);
+ mSettingName->setText(controlp->getName());
+ mSettingName->setToolTip(controlp->getName());
+ mCopyBtn->setVisible(true);
mComment->setVisible(true);
std::string old_text = mComment->getText();
@@ -218,259 +224,259 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp)
mComment->setText(controlp->getComment());
}
- spinner1->setMaxValue(F32_MAX);
- spinner2->setMaxValue(F32_MAX);
- spinner3->setMaxValue(F32_MAX);
- spinner4->setMaxValue(F32_MAX);
- spinner1->setMinValue(-F32_MAX);
- spinner2->setMinValue(-F32_MAX);
- spinner3->setMinValue(-F32_MAX);
- spinner4->setMinValue(-F32_MAX);
- if (!spinner1->hasFocus())
- {
- spinner1->setIncrement(0.1f);
- }
- if (!spinner2->hasFocus())
- {
- spinner2->setIncrement(0.1f);
- }
- if (!spinner3->hasFocus())
- {
- spinner3->setIncrement(0.1f);
- }
- if (!spinner4->hasFocus())
- {
- spinner4->setIncrement(0.1f);
- }
-
- LLSD sd = controlp->get();
- switch(type)
- {
- case TYPE_U32:
- spinner1->setVisible(TRUE);
- spinner1->setLabel(std::string("value")); // Debug, don't translate
- if (!spinner1->hasFocus())
- {
- spinner1->setValue(sd);
- spinner1->setMinValue((F32)U32_MIN);
- spinner1->setMaxValue((F32)U32_MAX);
- spinner1->setIncrement(1.f);
- spinner1->setPrecision(0);
- }
- break;
- case TYPE_S32:
- spinner1->setVisible(TRUE);
- spinner1->setLabel(std::string("value")); // Debug, don't translate
- if (!spinner1->hasFocus())
- {
- spinner1->setValue(sd);
- spinner1->setMinValue((F32)S32_MIN);
- spinner1->setMaxValue((F32)S32_MAX);
- spinner1->setIncrement(1.f);
- spinner1->setPrecision(0);
- }
- break;
- case TYPE_F32:
- spinner1->setVisible(TRUE);
- spinner1->setLabel(std::string("value")); // Debug, don't translate
- if (!spinner1->hasFocus())
- {
- spinner1->setPrecision(3);
- spinner1->setValue(sd);
- }
- break;
- case TYPE_BOOLEAN:
- if (!getChild<LLUICtrl>("boolean_combo")->hasFocus())
- {
- if (sd.asBoolean())
- {
- getChild<LLUICtrl>("boolean_combo")->setValue(LLSD("true"));
- }
- else
- {
- getChild<LLUICtrl>("boolean_combo")->setValue(LLSD(""));
- }
- }
- break;
- case TYPE_STRING:
- getChildView("val_text")->setVisible( TRUE);
- if (!getChild<LLUICtrl>("val_text")->hasFocus())
- {
- getChild<LLUICtrl>("val_text")->setValue(sd);
- }
- break;
- case TYPE_VEC3:
- {
- LLVector3 v;
- v.setValue(sd);
- spinner1->setVisible(TRUE);
- spinner1->setLabel(std::string("X"));
- spinner2->setVisible(TRUE);
- spinner2->setLabel(std::string("Y"));
- spinner3->setVisible(TRUE);
- spinner3->setLabel(std::string("Z"));
- if (!spinner1->hasFocus())
- {
- spinner1->setPrecision(3);
- spinner1->setValue(v[VX]);
- }
- if (!spinner2->hasFocus())
- {
- spinner2->setPrecision(3);
- spinner2->setValue(v[VY]);
- }
- if (!spinner3->hasFocus())
- {
- spinner3->setPrecision(3);
- spinner3->setValue(v[VZ]);
- }
- break;
- }
- case TYPE_VEC3D:
- {
- LLVector3d v;
- v.setValue(sd);
- spinner1->setVisible(TRUE);
- spinner1->setLabel(std::string("X"));
- spinner2->setVisible(TRUE);
- spinner2->setLabel(std::string("Y"));
- spinner3->setVisible(TRUE);
- spinner3->setLabel(std::string("Z"));
- if (!spinner1->hasFocus())
- {
- spinner1->setPrecision(3);
- spinner1->setValue(v[VX]);
- }
- if (!spinner2->hasFocus())
- {
- spinner2->setPrecision(3);
- spinner2->setValue(v[VY]);
- }
- if (!spinner3->hasFocus())
- {
- spinner3->setPrecision(3);
- spinner3->setValue(v[VZ]);
- }
- break;
- }
- case TYPE_QUAT:
- {
- LLQuaternion q;
- q.setValue(sd);
- spinner1->setVisible(TRUE);
- spinner1->setLabel(std::string("X"));
- spinner2->setVisible(TRUE);
- spinner2->setLabel(std::string("Y"));
- spinner3->setVisible(TRUE);
- spinner3->setLabel(std::string("Z"));
- spinner4->setVisible(TRUE);
- spinner4->setLabel(std::string("S"));
- if (!spinner1->hasFocus())
- {
- spinner1->setPrecision(4);
- spinner1->setValue(q.mQ[VX]);
- }
- if (!spinner2->hasFocus())
- {
- spinner2->setPrecision(4);
- spinner2->setValue(q.mQ[VY]);
- }
- if (!spinner3->hasFocus())
- {
- spinner3->setPrecision(4);
- spinner3->setValue(q.mQ[VZ]);
- }
- if (!spinner4->hasFocus())
- {
- spinner4->setPrecision(4);
- spinner4->setValue(q.mQ[VS]);
- }
- break;
- }
- case TYPE_RECT:
- {
- LLRect r;
- r.setValue(sd);
- spinner1->setVisible(TRUE);
- spinner1->setLabel(std::string("Left"));
- spinner2->setVisible(TRUE);
- spinner2->setLabel(std::string("Right"));
- spinner3->setVisible(TRUE);
- spinner3->setLabel(std::string("Bottom"));
- spinner4->setVisible(TRUE);
- spinner4->setLabel(std::string("Top"));
- if (!spinner1->hasFocus())
- {
- spinner1->setPrecision(0);
- spinner1->setValue(r.mLeft);
- }
- if (!spinner2->hasFocus())
- {
- spinner2->setPrecision(0);
- spinner2->setValue(r.mRight);
- }
- if (!spinner3->hasFocus())
- {
- spinner3->setPrecision(0);
- spinner3->setValue(r.mBottom);
- }
- if (!spinner4->hasFocus())
- {
- spinner4->setPrecision(0);
- spinner4->setValue(r.mTop);
- }
-
- spinner1->setMinValue((F32)S32_MIN);
- spinner1->setMaxValue((F32)S32_MAX);
- spinner1->setIncrement(1.f);
-
- spinner2->setMinValue((F32)S32_MIN);
- spinner2->setMaxValue((F32)S32_MAX);
- spinner2->setIncrement(1.f);
-
- spinner3->setMinValue((F32)S32_MIN);
- spinner3->setMaxValue((F32)S32_MAX);
- spinner3->setIncrement(1.f);
-
- spinner4->setMinValue((F32)S32_MIN);
- spinner4->setMaxValue((F32)S32_MAX);
- spinner4->setIncrement(1.f);
- break;
- }
- case TYPE_COL4:
- {
- LLColor4 clr;
- clr.setValue(sd);
- color_swatch->setVisible(TRUE);
- // only set if changed so color picker doesn't update
- if(clr != LLColor4(color_swatch->getValue()))
- {
- color_swatch->set(LLColor4(sd), TRUE, FALSE);
- }
- spinner4->setVisible(TRUE);
- spinner4->setLabel(std::string("Alpha"));
- if (!spinner4->hasFocus())
- {
- spinner4->setPrecision(3);
- spinner4->setMinValue(0.0);
- spinner4->setMaxValue(1.f);
- spinner4->setValue(clr.mV[VALPHA]);
- }
- break;
- }
- case TYPE_COL3:
- {
- LLColor3 clr;
- clr.setValue(sd);
- color_swatch->setVisible(TRUE);
- color_swatch->setValue(sd);
- break;
- }
- default:
- mComment->setText(std::string("unknown"));
- break;
- }
- }
+ spinner1->setMaxValue(F32_MAX);
+ spinner2->setMaxValue(F32_MAX);
+ spinner3->setMaxValue(F32_MAX);
+ spinner4->setMaxValue(F32_MAX);
+ spinner1->setMinValue(-F32_MAX);
+ spinner2->setMinValue(-F32_MAX);
+ spinner3->setMinValue(-F32_MAX);
+ spinner4->setMinValue(-F32_MAX);
+ if (!spinner1->hasFocus())
+ {
+ spinner1->setIncrement(0.1f);
+ }
+ if (!spinner2->hasFocus())
+ {
+ spinner2->setIncrement(0.1f);
+ }
+ if (!spinner3->hasFocus())
+ {
+ spinner3->setIncrement(0.1f);
+ }
+ if (!spinner4->hasFocus())
+ {
+ spinner4->setIncrement(0.1f);
+ }
+
+ LLSD sd = controlp->get();
+ switch(type)
+ {
+ case TYPE_U32:
+ spinner1->setVisible(TRUE);
+ spinner1->setLabel(std::string("value")); // Debug, don't translate
+ if (!spinner1->hasFocus())
+ {
+ spinner1->setValue(sd);
+ spinner1->setMinValue((F32)U32_MIN);
+ spinner1->setMaxValue((F32)U32_MAX);
+ spinner1->setIncrement(1.f);
+ spinner1->setPrecision(0);
+ }
+ break;
+ case TYPE_S32:
+ spinner1->setVisible(TRUE);
+ spinner1->setLabel(std::string("value")); // Debug, don't translate
+ if (!spinner1->hasFocus())
+ {
+ spinner1->setValue(sd);
+ spinner1->setMinValue((F32)S32_MIN);
+ spinner1->setMaxValue((F32)S32_MAX);
+ spinner1->setIncrement(1.f);
+ spinner1->setPrecision(0);
+ }
+ break;
+ case TYPE_F32:
+ spinner1->setVisible(TRUE);
+ spinner1->setLabel(std::string("value")); // Debug, don't translate
+ if (!spinner1->hasFocus())
+ {
+ spinner1->setPrecision(3);
+ spinner1->setValue(sd);
+ }
+ break;
+ case TYPE_BOOLEAN:
+ if (!getChild<LLUICtrl>("boolean_combo")->hasFocus())
+ {
+ if (sd.asBoolean())
+ {
+ getChild<LLUICtrl>("boolean_combo")->setValue(LLSD("true"));
+ }
+ else
+ {
+ getChild<LLUICtrl>("boolean_combo")->setValue(LLSD(""));
+ }
+ }
+ break;
+ case TYPE_STRING:
+ getChildView("val_text")->setVisible( TRUE);
+ if (!getChild<LLUICtrl>("val_text")->hasFocus())
+ {
+ getChild<LLUICtrl>("val_text")->setValue(sd);
+ }
+ break;
+ case TYPE_VEC3:
+ {
+ LLVector3 v;
+ v.setValue(sd);
+ spinner1->setVisible(TRUE);
+ spinner1->setLabel(std::string("X"));
+ spinner2->setVisible(TRUE);
+ spinner2->setLabel(std::string("Y"));
+ spinner3->setVisible(TRUE);
+ spinner3->setLabel(std::string("Z"));
+ if (!spinner1->hasFocus())
+ {
+ spinner1->setPrecision(3);
+ spinner1->setValue(v[VX]);
+ }
+ if (!spinner2->hasFocus())
+ {
+ spinner2->setPrecision(3);
+ spinner2->setValue(v[VY]);
+ }
+ if (!spinner3->hasFocus())
+ {
+ spinner3->setPrecision(3);
+ spinner3->setValue(v[VZ]);
+ }
+ break;
+ }
+ case TYPE_VEC3D:
+ {
+ LLVector3d v;
+ v.setValue(sd);
+ spinner1->setVisible(TRUE);
+ spinner1->setLabel(std::string("X"));
+ spinner2->setVisible(TRUE);
+ spinner2->setLabel(std::string("Y"));
+ spinner3->setVisible(TRUE);
+ spinner3->setLabel(std::string("Z"));
+ if (!spinner1->hasFocus())
+ {
+ spinner1->setPrecision(3);
+ spinner1->setValue(v[VX]);
+ }
+ if (!spinner2->hasFocus())
+ {
+ spinner2->setPrecision(3);
+ spinner2->setValue(v[VY]);
+ }
+ if (!spinner3->hasFocus())
+ {
+ spinner3->setPrecision(3);
+ spinner3->setValue(v[VZ]);
+ }
+ break;
+ }
+ case TYPE_QUAT:
+ {
+ LLQuaternion q;
+ q.setValue(sd);
+ spinner1->setVisible(TRUE);
+ spinner1->setLabel(std::string("X"));
+ spinner2->setVisible(TRUE);
+ spinner2->setLabel(std::string("Y"));
+ spinner3->setVisible(TRUE);
+ spinner3->setLabel(std::string("Z"));
+ spinner4->setVisible(TRUE);
+ spinner4->setLabel(std::string("S"));
+ if (!spinner1->hasFocus())
+ {
+ spinner1->setPrecision(4);
+ spinner1->setValue(q.mQ[VX]);
+ }
+ if (!spinner2->hasFocus())
+ {
+ spinner2->setPrecision(4);
+ spinner2->setValue(q.mQ[VY]);
+ }
+ if (!spinner3->hasFocus())
+ {
+ spinner3->setPrecision(4);
+ spinner3->setValue(q.mQ[VZ]);
+ }
+ if (!spinner4->hasFocus())
+ {
+ spinner4->setPrecision(4);
+ spinner4->setValue(q.mQ[VS]);
+ }
+ break;
+ }
+ case TYPE_RECT:
+ {
+ LLRect r;
+ r.setValue(sd);
+ spinner1->setVisible(TRUE);
+ spinner1->setLabel(std::string("Left"));
+ spinner2->setVisible(TRUE);
+ spinner2->setLabel(std::string("Right"));
+ spinner3->setVisible(TRUE);
+ spinner3->setLabel(std::string("Bottom"));
+ spinner4->setVisible(TRUE);
+ spinner4->setLabel(std::string("Top"));
+ if (!spinner1->hasFocus())
+ {
+ spinner1->setPrecision(0);
+ spinner1->setValue(r.mLeft);
+ }
+ if (!spinner2->hasFocus())
+ {
+ spinner2->setPrecision(0);
+ spinner2->setValue(r.mRight);
+ }
+ if (!spinner3->hasFocus())
+ {
+ spinner3->setPrecision(0);
+ spinner3->setValue(r.mBottom);
+ }
+ if (!spinner4->hasFocus())
+ {
+ spinner4->setPrecision(0);
+ spinner4->setValue(r.mTop);
+ }
+
+ spinner1->setMinValue((F32)S32_MIN);
+ spinner1->setMaxValue((F32)S32_MAX);
+ spinner1->setIncrement(1.f);
+
+ spinner2->setMinValue((F32)S32_MIN);
+ spinner2->setMaxValue((F32)S32_MAX);
+ spinner2->setIncrement(1.f);
+
+ spinner3->setMinValue((F32)S32_MIN);
+ spinner3->setMaxValue((F32)S32_MAX);
+ spinner3->setIncrement(1.f);
+
+ spinner4->setMinValue((F32)S32_MIN);
+ spinner4->setMaxValue((F32)S32_MAX);
+ spinner4->setIncrement(1.f);
+ break;
+ }
+ case TYPE_COL4:
+ {
+ LLColor4 clr;
+ clr.setValue(sd);
+ color_swatch->setVisible(TRUE);
+ // only set if changed so color picker doesn't update
+ if(clr != LLColor4(color_swatch->getValue()))
+ {
+ color_swatch->set(LLColor4(sd), TRUE, FALSE);
+ }
+ spinner4->setVisible(TRUE);
+ spinner4->setLabel(std::string("Alpha"));
+ if (!spinner4->hasFocus())
+ {
+ spinner4->setPrecision(3);
+ spinner4->setMinValue(0.0);
+ spinner4->setMaxValue(1.f);
+ spinner4->setValue(clr.mV[VALPHA]);
+ }
+ break;
+ }
+ case TYPE_COL3:
+ {
+ LLColor3 clr;
+ clr.setValue(sd);
+ color_swatch->setVisible(TRUE);
+ color_swatch->setValue(sd);
+ break;
+ }
+ default:
+ mComment->setText(std::string("unknown"));
+ break;
+ }
+ }
}
@@ -494,7 +500,7 @@ void LLFloaterSettingsDebug::updateList(bool skip_selection)
LLFloaterSettingsDebug* floater;
std::string selected_setting;
bool skip_selection;
- f(LLScrollListCtrl* list, LLFloaterSettingsDebug* floater, std::string setting, bool skip_selection)
+ f(LLScrollListCtrl* list, LLFloaterSettingsDebug* floater, std::string setting, bool skip_selection)
: setting_list(list), floater(floater), selected_setting(setting), skip_selection(skip_selection) {}
virtual void apply(const std::string& name, LLControlVariable* control)
{
@@ -632,7 +638,13 @@ void LLFloaterSettingsDebug::hideUIControls()
getChildView("val_text")->setVisible(false);
getChildView("default_btn")->setVisible(false);
getChildView("boolean_combo")->setVisible(false);
- getChildView("setting_name_txt")->setVisible(false);
+ mSettingName->setVisible(false);
+ mCopyBtn->setVisible(false);
mComment->setVisible(false);
}
+void LLFloaterSettingsDebug::onClickCopy()
+{
+ std::string setting_name = mSettingName->getText();
+ LLClipboard::instance().copyToClipboard(utf8str_to_wstring(setting_name), 0, setting_name.size());
+}
diff --git a/indra/newview/llfloatersettingsdebug.h b/indra/newview/llfloatersettingsdebug.h
index 5a392e766c..6ff3e344b4 100644
--- a/indra/newview/llfloatersettingsdebug.h
+++ b/indra/newview/llfloatersettingsdebug.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfloatersettingsdebug.h
* @brief floater for debugging internal viewer settings
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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$
*/
@@ -31,30 +31,32 @@
#include "llfloater.h"
class LLScrollListCtrl;
+class LLTextBox;
-class LLFloaterSettingsDebug
-: public LLFloater
+class LLFloaterSettingsDebug
+: public LLFloater
{
- friend class LLFloaterReg;
+ friend class LLFloaterReg;
public:
- virtual BOOL postBuild();
- virtual void draw();
+ virtual BOOL postBuild();
+ virtual void draw();
- void updateControl(LLControlVariable* control);
+ void updateControl(LLControlVariable* control);
- void onCommitSettings();
- void onClickDefault();
+ void onCommitSettings();
+ void onClickDefault();
+ void onClickCopy();
bool matchesSearchFilter(std::string setting_name);
bool isSettingHidden(LLControlVariable* control);
private:
- // key - selects which settings to show, one of:
- // "all", "base", "account", "skin"
- LLFloaterSettingsDebug(const LLSD& key);
- virtual ~LLFloaterSettingsDebug();
+ // key - selects which settings to show, one of:
+ // "all", "base", "account", "skin"
+ LLFloaterSettingsDebug(const LLSD& key);
+ virtual ~LLFloaterSettingsDebug();
void updateList(bool skip_selection = false);
void onSettingSelect();
@@ -64,9 +66,11 @@ private:
void hideUIControls();
LLScrollListCtrl* mSettingList;
-
+
protected:
- class LLTextEditor* mComment;
+ class LLTextEditor* mComment;
+ LLTextBox* mSettingName;
+ LLButton* mCopyBtn;
std::string mSearchFilter;
};
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 168099f1e7..7d1252ee31 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llinventoryfunctions.cpp
* @brief Implementation of the inventory view and associated stuff.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -152,19 +152,19 @@ S32 count_stock_folders(LLInventoryModel::cat_array_t& categories)
// Helper funtion : Count the number of items (not folders) in the descending hierarchy
S32 count_descendants_items(const LLUUID& cat_id)
{
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array);
-
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array);
+
S32 count = item_array->size();
-
+
LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
- for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
+ for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
{
- LLViewerInventoryCategory* category = *iter;
+ LLViewerInventoryCategory* category = *iter;
count += count_descendants_items(category->getUUID());
}
-
+
return count;
}
@@ -179,7 +179,7 @@ bool contains_nocopy_items(const LLUUID& id)
LLInventoryModel::cat_array_t* cat_array;
LLInventoryModel::item_array_t* item_array;
gInventory.getDirectDescendentsOf(id,cat_array,item_array);
-
+
// Check all the items: returns true upon encountering a nocopy item
for (LLInventoryModel::item_array_t::iterator iter = item_array->begin(); iter != item_array->end(); iter++)
{
@@ -190,7 +190,7 @@ bool contains_nocopy_items(const LLUUID& id)
return true;
}
}
-
+
// Check all the sub folders recursively
for (LLInventoryModel::cat_array_t::iterator iter = cat_array->begin(); iter != cat_array->end(); iter++)
{
@@ -203,14 +203,14 @@ bool contains_nocopy_items(const LLUUID& id)
}
else
{
- LLInventoryItem* item = gInventory.getItem(id);
+ LLInventoryItem* item = gInventory.getItem(id);
LLViewerInventoryItem * inv_item = (LLViewerInventoryItem *) item;
if (!inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
{
return true;
}
}
-
+
// Exit without meeting a nocopy item
return false;
}
@@ -218,21 +218,21 @@ bool contains_nocopy_items(const LLUUID& id)
// Generates a string containing the path to the item specified by id.
void append_path(const LLUUID& id, std::string& path)
{
- std::string temp;
- const LLInventoryObject* obj = gInventory.getObject(id);
- LLUUID parent_id;
- if(obj) parent_id = obj->getParentUUID();
- std::string forward_slash("/");
- while(obj)
- {
- obj = gInventory.getCategory(parent_id);
- if(obj)
- {
- temp.assign(forward_slash + obj->getName() + temp);
- parent_id = obj->getParentUUID();
- }
- }
- path.append(temp);
+ std::string temp;
+ const LLInventoryObject* obj = gInventory.getObject(id);
+ LLUUID parent_id;
+ if(obj) parent_id = obj->getParentUUID();
+ std::string forward_slash("/");
+ while(obj)
+ {
+ obj = gInventory.getCategory(parent_id);
+ if(obj)
+ {
+ temp.assign(forward_slash + obj->getName() + temp);
+ parent_id = obj->getParentUUID();
+ }
+ }
+ path.append(temp);
}
// Generates a string containing the path name of the object.
@@ -273,10 +273,10 @@ void update_marketplace_folder_hierarchy(const LLUUID cat_id)
gInventory.addChangedMask(LLInventoryObserver::LABEL, cat_id);
// Update all descendent folders down
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array);
-
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array);
+
LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
{
@@ -291,9 +291,9 @@ void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistenc
// When changing the marketplace status of an item, we usually have to change the status of all
// folders in the same listing. This is because the display of each folder is affected by the
// overall status of the whole listing.
- // Consequently, the only way to correctly update an item anywhere in the marketplace is to
+ // Consequently, the only way to correctly update an item anywhere in the marketplace is to
// update the whole listing from its listing root.
- // This is not as bad as it seems as we only update folders, not items, and the folder nesting depth
+ // This is not as bad as it seems as we only update folders, not items, and the folder nesting depth
// is limited to 4.
// We also take care of degenerated cases so we don't update all folders in the inventory by mistake.
@@ -303,7 +303,7 @@ void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistenc
{
return;
}
-
+
// Grab marketplace listing data for this item
S32 depth = depth_nesting_in_marketplace(cur_uuid);
if (depth > 0)
@@ -312,7 +312,7 @@ void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistenc
LLUUID listing_uuid = nested_parent_id(cur_uuid, depth);
LLViewerInventoryCategory* listing_cat = gInventory.getCategory(listing_uuid);
bool listing_cat_loaded = listing_cat != NULL && listing_cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
-
+
// Verify marketplace data consistency for this listing
if (perform_consistency_enforcement
&& listing_cat_loaded
@@ -336,7 +336,7 @@ void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistenc
LLMarketplaceData::instance().activateListing(listing_uuid, false,1);
}
}
-
+
// Check if the count on hand needs to be updated on SLM
if (perform_consistency_enforcement
&& listing_cat_loaded
@@ -377,10 +377,10 @@ void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistenc
void update_all_marketplace_count(const LLUUID& cat_id)
{
// Get all descendent folders down
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array);
-
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array);
+
LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
{
@@ -412,19 +412,19 @@ void update_all_marketplace_count()
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name)
{
- LLViewerInventoryCategory* cat;
+ LLViewerInventoryCategory* cat;
- if (!model ||
- !get_is_category_renameable(model, cat_id) ||
- (cat = model->getCategory(cat_id)) == NULL ||
- cat->getName() == new_name)
- {
- return;
- }
+ if (!model ||
+ !get_is_category_renameable(model, cat_id) ||
+ (cat = model->getCategory(cat_id)) == NULL ||
+ cat->getName() == new_name)
+ {
+ return;
+ }
- LLSD updates;
- updates["name"] = new_name;
- update_inventory_category(cat_id, updates, NULL);
+ LLSD updates;
+ updates["name"] = new_name;
+ update_inventory_category(cat_id, updates, NULL);
}
void copy_inventory_category(LLInventoryModel* model,
@@ -448,7 +448,7 @@ void copy_inventory_category(LLInventoryModel* model,
bool move_no_copy_items,
inventory_func_type callback)
{
- // Create the initial folder
+ // Create the initial folder
inventory_func_type func = [model, cat, root_copy_id, move_no_copy_items, callback](const LLUUID &new_id)
{
copy_inventory_category_content(new_id, model, cat, root_copy_id, move_no_copy_items);
@@ -457,7 +457,7 @@ void copy_inventory_category(LLInventoryModel* model,
callback(new_id);
}
};
- gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID());
+ gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID());
}
void copy_cb(const LLUUID& dest_folder, const LLUUID& root_id)
@@ -469,21 +469,21 @@ void copy_cb(const LLUUID& dest_folder, const LLUUID& root_id)
void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& root_copy_id, bool move_no_copy_items)
{
- model->notifyObservers();
+ model->notifyObservers();
- // We need to exclude the initial root of the copy to avoid recursively copying the copy, etc...
- LLUUID root_id = (root_copy_id.isNull() ? new_cat_uuid : root_copy_id);
+ // We need to exclude the initial root of the copy to avoid recursively copying the copy, etc...
+ LLUUID root_id = (root_copy_id.isNull() ? new_cat_uuid : root_copy_id);
- // Get the content of the folder
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- gInventory.getDirectDescendentsOf(cat->getUUID(), cat_array, item_array);
+ // Get the content of the folder
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat->getUUID(), cat_array, item_array);
- // If root_copy_id is null, tell the marketplace model we'll be waiting for new items to be copied over for this folder
- if (root_copy_id.isNull())
- {
- LLMarketplaceData::instance().setValidationWaiting(root_id, count_descendants_items(cat->getUUID()));
- }
+ // If root_copy_id is null, tell the marketplace model we'll be waiting for new items to be copied over for this folder
+ if (root_copy_id.isNull())
+ {
+ LLMarketplaceData::instance().setValidationWaiting(root_id, count_descendants_items(cat->getUUID()));
+ }
LLPointer<LLInventoryCallback> cb;
if (root_copy_id.isNull())
@@ -495,348 +495,348 @@ void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryMode
cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, new_cat_uuid));
}
- // Copy all the items
- LLInventoryModel::item_array_t item_array_copy = *item_array;
- for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
- {
- LLInventoryItem* item = *iter;
-
- if (item->getIsLinkType())
- {
- link_inventory_object(new_cat_uuid, item->getLinkedUUID(), cb);
- }
- else if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
- {
- // If the item is nocopy, we do nothing or, optionally, move it
- if (move_no_copy_items)
- {
- // Reparent the item
- LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *)item;
- gInventory.changeItemParent(viewer_inv_item, new_cat_uuid, true);
- }
+ // Copy all the items
+ LLInventoryModel::item_array_t item_array_copy = *item_array;
+ for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
+ {
+ LLInventoryItem* item = *iter;
+
+ if (item->getIsLinkType())
+ {
+ link_inventory_object(new_cat_uuid, item->getLinkedUUID(), cb);
+ }
+ else if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
+ {
+ // If the item is nocopy, we do nothing or, optionally, move it
+ if (move_no_copy_items)
+ {
+ // Reparent the item
+ LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *)item;
+ gInventory.changeItemParent(viewer_inv_item, new_cat_uuid, true);
+ }
if (root_copy_id.isNull())
{
// Decrement the count in root_id since that one item won't be copied over
LLMarketplaceData::instance().decrementValidationWaiting(root_id);
}
- }
- else
- {
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- new_cat_uuid,
- std::string(),
- cb);
- }
- }
-
- // Copy all the folders
- LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
- for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
- {
- LLViewerInventoryCategory* category = *iter;
- if (category->getUUID() != root_id)
- {
- copy_inventory_category(model, category, new_cat_uuid, root_id, move_no_copy_items);
- }
- }
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ new_cat_uuid,
+ std::string(),
+ cb);
+ }
+ }
+
+ // Copy all the folders
+ LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
+ for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
+ {
+ LLViewerInventoryCategory* category = *iter;
+ if (category->getUUID() != root_id)
+ {
+ copy_inventory_category(model, category, new_cat_uuid, root_id, move_no_copy_items);
+ }
+ }
}
class LLInventoryCollectAllItems : public LLInventoryCollectFunctor
{
public:
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
- {
- return true;
- }
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ return true;
+ }
};
BOOL get_is_parent_to_worn_item(const LLUUID& id)
{
- const LLViewerInventoryCategory* cat = gInventory.getCategory(id);
- if (!cat)
- {
- return FALSE;
- }
+ const LLViewerInventoryCategory* cat = gInventory.getCategory(id);
+ if (!cat)
+ {
+ return FALSE;
+ }
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- LLInventoryCollectAllItems collect_all;
- gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), cats, items, LLInventoryModel::EXCLUDE_TRASH, collect_all);
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLInventoryCollectAllItems collect_all;
+ gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), cats, items, LLInventoryModel::EXCLUDE_TRASH, collect_all);
- for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it)
- {
- const LLViewerInventoryItem * const item = *it;
+ for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it)
+ {
+ const LLViewerInventoryItem * const item = *it;
- llassert(item->getIsLinkType());
+ llassert(item->getIsLinkType());
- LLUUID linked_id = item->getLinkedUUID();
- const LLViewerInventoryItem * const linked_item = gInventory.getItem(linked_id);
+ LLUUID linked_id = item->getLinkedUUID();
+ const LLViewerInventoryItem * const linked_item = gInventory.getItem(linked_id);
- if (linked_item)
- {
- LLUUID parent_id = linked_item->getParentUUID();
+ if (linked_item)
+ {
+ LLUUID parent_id = linked_item->getParentUUID();
- while (!parent_id.isNull())
- {
- LLInventoryCategory * parent_cat = gInventory.getCategory(parent_id);
+ while (!parent_id.isNull())
+ {
+ LLInventoryCategory * parent_cat = gInventory.getCategory(parent_id);
- if (cat == parent_cat)
- {
- return TRUE;
- }
+ if (cat == parent_cat)
+ {
+ return TRUE;
+ }
- parent_id = parent_cat->getParentUUID();
- }
- }
- }
+ parent_id = parent_cat->getParentUUID();
+ }
+ }
+ }
- return FALSE;
+ return FALSE;
}
BOOL get_is_item_worn(const LLUUID& id)
{
- const LLViewerInventoryItem* item = gInventory.getItem(id);
- if (!item)
- return FALSE;
+ const LLViewerInventoryItem* item = gInventory.getItem(id);
+ if (!item)
+ return FALSE;
if (item->getIsLinkType() && !gInventory.getItem(item->getLinkedUUID()))
{
return FALSE;
}
- // Consider the item as worn if it has links in COF.
- if (LLAppearanceMgr::instance().isLinkedInCOF(id))
- {
- return TRUE;
- }
-
- switch(item->getType())
- {
- case LLAssetType::AT_OBJECT:
- {
- if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
- return TRUE;
- break;
- }
- case LLAssetType::AT_BODYPART:
- case LLAssetType::AT_CLOTHING:
- if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
- return TRUE;
- break;
- case LLAssetType::AT_GESTURE:
- if (LLGestureMgr::instance().isGestureActive(item->getLinkedUUID()))
- return TRUE;
- break;
- default:
- break;
- }
- return FALSE;
+ // Consider the item as worn if it has links in COF.
+ if (LLAppearanceMgr::instance().isLinkedInCOF(id))
+ {
+ return TRUE;
+ }
+
+ switch(item->getType())
+ {
+ case LLAssetType::AT_OBJECT:
+ {
+ if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
+ return TRUE;
+ break;
+ }
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_CLOTHING:
+ if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
+ return TRUE;
+ break;
+ case LLAssetType::AT_GESTURE:
+ if (LLGestureMgr::instance().isGestureActive(item->getLinkedUUID()))
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
}
BOOL get_can_item_be_worn(const LLUUID& id)
{
- const LLViewerInventoryItem* item = gInventory.getItem(id);
- if (!item)
- return FALSE;
-
- if (LLAppearanceMgr::instance().isLinkedInCOF(item->getLinkedUUID()))
- {
- // an item having links in COF (i.e. a worn item)
- return FALSE;
- }
-
- if (gInventory.isObjectDescendentOf(id, LLAppearanceMgr::instance().getCOF()))
- {
- // a non-link object in COF (should not normally happen)
- return FALSE;
- }
-
- const LLUUID trash_id = gInventory.findCategoryUUIDForType(
- LLFolderType::FT_TRASH);
-
- // item can't be worn if base obj in trash, see EXT-7015
- if (gInventory.isObjectDescendentOf(item->getLinkedUUID(),
- trash_id))
- {
- return false;
- }
-
- switch(item->getType())
- {
- case LLAssetType::AT_OBJECT:
- {
- if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
- {
- // Already being worn
- return FALSE;
- }
- else
- {
- // Not being worn yet.
- return TRUE;
- }
- break;
- }
- case LLAssetType::AT_BODYPART:
- case LLAssetType::AT_CLOTHING:
- if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
- {
- // Already being worn
- return FALSE;
- }
- else
- {
- // Not being worn yet.
- return TRUE;
- }
- break;
- default:
- break;
- }
- return FALSE;
+ const LLViewerInventoryItem* item = gInventory.getItem(id);
+ if (!item)
+ return FALSE;
+
+ if (LLAppearanceMgr::instance().isLinkedInCOF(item->getLinkedUUID()))
+ {
+ // an item having links in COF (i.e. a worn item)
+ return FALSE;
+ }
+
+ if (gInventory.isObjectDescendentOf(id, LLAppearanceMgr::instance().getCOF()))
+ {
+ // a non-link object in COF (should not normally happen)
+ return FALSE;
+ }
+
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(
+ LLFolderType::FT_TRASH);
+
+ // item can't be worn if base obj in trash, see EXT-7015
+ if (gInventory.isObjectDescendentOf(item->getLinkedUUID(),
+ trash_id))
+ {
+ return false;
+ }
+
+ switch(item->getType())
+ {
+ case LLAssetType::AT_OBJECT:
+ {
+ if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
+ {
+ // Already being worn
+ return FALSE;
+ }
+ else
+ {
+ // Not being worn yet.
+ return TRUE;
+ }
+ break;
+ }
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_CLOTHING:
+ if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
+ {
+ // Already being worn
+ return FALSE;
+ }
+ else
+ {
+ // Not being worn yet.
+ return TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ return FALSE;
}
BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
{
- if (!model)
- {
- return FALSE;
- }
-
- // Can't delete an item that's in the library.
- if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
- {
- return FALSE;
- }
-
- // Disable delete from COF folder; have users explicitly choose "detach/take off",
- // unless the item is not worn but in the COF (i.e. is bugged).
- if (LLAppearanceMgr::instance().getIsProtectedCOFItem(id))
- {
- if (get_is_item_worn(id))
- {
- return FALSE;
- }
- }
-
- const LLInventoryObject *obj = model->getItem(id);
- if (obj && obj->getIsLinkType())
- {
- return TRUE;
- }
- if (get_is_item_worn(id))
- {
- return FALSE;
- }
- return TRUE;
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ // Can't delete an item that's in the library.
+ if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
+ {
+ return FALSE;
+ }
+
+ // Disable delete from COF folder; have users explicitly choose "detach/take off",
+ // unless the item is not worn but in the COF (i.e. is bugged).
+ if (LLAppearanceMgr::instance().getIsProtectedCOFItem(id))
+ {
+ if (get_is_item_worn(id))
+ {
+ return FALSE;
+ }
+ }
+
+ const LLInventoryObject *obj = model->getItem(id);
+ if (obj && obj->getIsLinkType())
+ {
+ return TRUE;
+ }
+ if (get_is_item_worn(id))
+ {
+ return FALSE;
+ }
+ return TRUE;
}
bool get_is_item_editable(const LLUUID& inv_item_id)
{
- if (const LLInventoryItem* inv_item = gInventory.getLinkedItem(inv_item_id))
- {
- switch (inv_item->getType())
- {
- case LLAssetType::AT_BODYPART:
- case LLAssetType::AT_CLOTHING:
- return gAgentWearables.isWearableModifiable(inv_item_id);
- case LLAssetType::AT_OBJECT:
- return true;
- default:
+ if (const LLInventoryItem* inv_item = gInventory.getLinkedItem(inv_item_id))
+ {
+ switch (inv_item->getType())
+ {
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_CLOTHING:
+ return gAgentWearables.isWearableModifiable(inv_item_id);
+ case LLAssetType::AT_OBJECT:
+ return true;
+ default:
return false;;
- }
- }
- return gAgentAvatarp->getWornAttachment(inv_item_id) != nullptr;
+ }
+ }
+ return gAgentAvatarp->getWornAttachment(inv_item_id) != nullptr;
}
void handle_item_edit(const LLUUID& inv_item_id)
{
- if (get_is_item_editable(inv_item_id))
- {
- if (const LLInventoryItem* inv_item = gInventory.getLinkedItem(inv_item_id))
- {
- switch (inv_item->getType())
- {
- case LLAssetType::AT_BODYPART:
- case LLAssetType::AT_CLOTHING:
- LLAgentWearables::editWearable(inv_item_id);
- break;
- case LLAssetType::AT_OBJECT:
- handle_attachment_edit(inv_item_id);
- break;
- default:
- break;
- }
- }
- else
- {
- handle_attachment_edit(inv_item_id);
- }
- }
+ if (get_is_item_editable(inv_item_id))
+ {
+ if (const LLInventoryItem* inv_item = gInventory.getLinkedItem(inv_item_id))
+ {
+ switch (inv_item->getType())
+ {
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_CLOTHING:
+ LLAgentWearables::editWearable(inv_item_id);
+ break;
+ case LLAssetType::AT_OBJECT:
+ handle_attachment_edit(inv_item_id);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ handle_attachment_edit(inv_item_id);
+ }
+ }
}
BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)
{
- // NOTE: This function doesn't check the folder's children.
- // See LLFolderBridge::isItemRemovable for a function that does
- // consider the children.
-
- if (!model)
- {
- return FALSE;
- }
+ // NOTE: This function doesn't check the folder's children.
+ // See LLFolderBridge::isItemRemovable for a function that does
+ // consider the children.
- if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
- {
- return FALSE;
- }
+ if (!model)
+ {
+ return FALSE;
+ }
- if (!isAgentAvatarValid()) return FALSE;
+ if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
+ {
+ return FALSE;
+ }
- const LLInventoryCategory* category = model->getCategory(id);
- if (!category)
- {
- return FALSE;
- }
+ if (!isAgentAvatarValid()) return FALSE;
- const LLFolderType::EType folder_type = category->getPreferredType();
+ const LLInventoryCategory* category = model->getCategory(id);
+ if (!category)
+ {
+ return FALSE;
+ }
- if (LLFolderType::lookupIsProtectedType(folder_type))
- {
- return FALSE;
- }
+ const LLFolderType::EType folder_type = category->getPreferredType();
+
+ if (LLFolderType::lookupIsProtectedType(folder_type))
+ {
+ return FALSE;
+ }
- // Can't delete the outfit that is currently being worn.
- if (folder_type == LLFolderType::FT_OUTFIT)
- {
- const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
- if (base_outfit_link && (category == base_outfit_link->getLinkedCategory()))
- {
- return FALSE;
- }
- }
+ // Can't delete the outfit that is currently being worn.
+ if (folder_type == LLFolderType::FT_OUTFIT)
+ {
+ const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
+ if (base_outfit_link && (category == base_outfit_link->getLinkedCategory()))
+ {
+ return FALSE;
+ }
+ }
- return TRUE;
+ return TRUE;
}
BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
{
- if (!model)
- {
- return FALSE;
- }
+ if (!model)
+ {
+ return FALSE;
+ }
- LLViewerInventoryCategory* cat = model->getCategory(id);
+ LLViewerInventoryCategory* cat = model->getCategory(id);
- if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) &&
- cat->getOwnerID() == gAgent.getID())
- {
- return TRUE;
- }
- return FALSE;
+ if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) &&
+ cat->getOwnerID() == gAgent.getID())
+ {
+ return TRUE;
+ }
+ return FALSE;
}
void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id)
@@ -844,13 +844,13 @@ void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id)
LLSD params;
params["id"] = item_uuid;
params["object"] = object_id;
-
+
LLFloaterReg::showInstance("item_properties", params);
}
void show_item_profile(const LLUUID& item_uuid)
{
- LLUUID linked_uuid = gInventory.getLinkedItemID(item_uuid);
+ LLUUID linked_uuid = gInventory.getLinkedItemID(item_uuid);
LLFloaterReg::showInstance("item_properties", LLSD().with("id", linked_uuid));
}
@@ -877,7 +877,7 @@ void show_item_original(const LLUUID& item_uuid)
LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL;
return;
}
- LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
+ LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
if (sidepanel_inventory)
{
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
@@ -920,20 +920,20 @@ void show_item_original(const LLUUID& item_uuid)
void reset_inventory_filter()
{
- LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
- if (sidepanel_inventory)
- {
- LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
- if (main_inventory)
- {
- main_inventory->onFilterEdit("");
- }
- }
+ LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
+ if (sidepanel_inventory)
+ {
+ LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
+ if (main_inventory)
+ {
+ main_inventory->onFilterEdit("");
+ }
+ }
}
void open_marketplace_listings()
{
- LLFloaterReg::showInstance("marketplace_listings");
+ LLFloaterReg::showInstance("marketplace_listings");
}
///----------------------------------------------------------------------------
@@ -960,7 +960,7 @@ S32 depth_nesting_in_marketplace(LLUUID cur_uuid)
{
return -1;
}
-
+
// Iterate through the parents till we hit the marketplace listings root
// Note that the marketplace listings root itself will return 0
S32 depth = 0;
@@ -1062,13 +1062,13 @@ S32 compute_stock_count(LLUUID cat_uuid, bool force_count /* false */)
}
}
}
-
+
// In all other cases, the stock count is the min of stock folders count found in the descendents
// "COMPUTE_STOCK_NOT_EVALUATED" denotes that a stock folder in the hierarchy has a count that cannot be evaluated at this time (folder not up to date)
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- gInventory.getDirectDescendentsOf(cat_uuid,cat_array,item_array);
-
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat_uuid,cat_array,item_array);
+
// "COMPUTE_STOCK_INFINITE" denotes a folder that doesn't countain any stock folders in its descendents
S32 curr_count = COMPUTE_STOCK_INFINITE;
@@ -1083,147 +1083,147 @@ S32 compute_stock_count(LLUUID cat_uuid, bool force_count /* false */)
curr_count = count;
}
}
-
+
return curr_count;
}
// local helper
bool can_move_to_marketplace(LLInventoryItem* inv_item, std::string& tooltip_msg, bool resolve_links)
{
- // Collapse links directly to items/folders
- LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
- LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
+ // Collapse links directly to items/folders
+ LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
+ LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
// Linked items and folders cannot be put for sale
if (linked_category || linked_item)
{
- tooltip_msg = LLTrans::getString("TooltipOutboxLinked");
+ tooltip_msg = LLTrans::getString("TooltipOutboxLinked");
return false;
}
-
+
// A category is always considered as passing...
if (linked_category != NULL)
- {
+ {
return true;
- }
-
+ }
+
// Take the linked item if necessary
if (linked_item != NULL)
- {
- inv_item = linked_item;
- }
-
+ {
+ inv_item = linked_item;
+ }
+
// Check that the agent has transfer permission on the item: this is required as a resident cannot
// put on sale items she cannot transfer. Proceed with move if we have permission.
- bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
- if (!allow_transfer)
- {
- tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer");
- return false;
- }
-
+ bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
+ if (!allow_transfer)
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer");
+ return false;
+ }
+
// Check worn/not worn status: worn items cannot be put on the marketplace
- bool worn = get_is_item_worn(inv_item->getUUID());
- if (worn)
- {
- tooltip_msg = LLTrans::getString("TooltipOutboxWorn");
- return false;
- }
+ bool worn = get_is_item_worn(inv_item->getUUID());
+ if (worn)
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxWorn");
+ return false;
+ }
// Check library status: library items cannot be put on the marketplace
- if (!gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.getRootFolderID()))
+ if (!gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.getRootFolderID()))
{
- tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
- return false;
+ tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
+ return false;
}
// Check type: for the moment, calling cards cannot be put on the marketplace
- bool calling_card = (LLAssetType::AT_CALLINGCARD == inv_item->getType());
- if (calling_card)
- {
- tooltip_msg = LLTrans::getString("TooltipOutboxCallingCard");
- return false;
- }
-
- return true;
+ bool calling_card = (LLAssetType::AT_CALLINGCARD == inv_item->getType());
+ if (calling_card)
+ {
+ tooltip_msg = LLTrans::getString("TooltipOutboxCallingCard");
+ return false;
+ }
+
+ return true;
}
// local helper
// Returns the max tree length (in folder nodes) down from the argument folder
int get_folder_levels(LLInventoryCategory* inv_cat)
{
- LLInventoryModel::cat_array_t* cats;
- LLInventoryModel::item_array_t* items;
- gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items);
-
- int max_child_levels = 0;
-
- for (S32 i=0; i < cats->size(); ++i)
- {
- LLInventoryCategory* category = cats->at(i);
- max_child_levels = llmax(max_child_levels, get_folder_levels(category));
- }
-
- return 1 + max_child_levels;
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items);
+
+ int max_child_levels = 0;
+
+ for (S32 i=0; i < cats->size(); ++i)
+ {
+ LLInventoryCategory* category = cats->at(i);
+ max_child_levels = llmax(max_child_levels, get_folder_levels(category));
+ }
+
+ return 1 + max_child_levels;
}
// local helper
// Returns the distance (in folder nodes) between the ancestor and its descendant. Returns -1 if not related.
int get_folder_path_length(const LLUUID& ancestor_id, const LLUUID& descendant_id)
{
- int depth = 0;
-
- if (ancestor_id == descendant_id) return depth;
-
- const LLInventoryCategory* category = gInventory.getCategory(descendant_id);
-
- while (category)
- {
- LLUUID parent_id = category->getParentUUID();
-
- if (parent_id.isNull()) break;
-
- depth++;
-
- if (parent_id == ancestor_id) return depth;
-
- category = gInventory.getCategory(parent_id);
- }
-
- LL_WARNS("SLM") << "get_folder_path_length() couldn't trace a path from the descendant to the ancestor" << LL_ENDL;
- return -1;
+ int depth = 0;
+
+ if (ancestor_id == descendant_id) return depth;
+
+ const LLInventoryCategory* category = gInventory.getCategory(descendant_id);
+
+ while (category)
+ {
+ LLUUID parent_id = category->getParentUUID();
+
+ if (parent_id.isNull()) break;
+
+ depth++;
+
+ if (parent_id == ancestor_id) return depth;
+
+ category = gInventory.getCategory(parent_id);
+ }
+
+ LL_WARNS("SLM") << "get_folder_path_length() couldn't trace a path from the descendant to the ancestor" << LL_ENDL;
+ return -1;
}
// local helper
// Returns true if all items within the argument folder are fit for sale, false otherwise
bool has_correct_permissions_for_sale(LLInventoryCategory* cat, std::string& error_msg)
{
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
-
- LLInventoryModel::item_array_t item_array_copy = *item_array;
-
- for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
- {
- LLInventoryItem* item = *iter;
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
+
+ LLInventoryModel::item_array_t item_array_copy = *item_array;
+
+ for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
+ {
+ LLInventoryItem* item = *iter;
if (!can_move_to_marketplace(item, error_msg, false))
{
return false;
}
- }
-
- LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
-
- for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
- {
- LLInventoryCategory* category = *iter;
- if (!has_correct_permissions_for_sale(category, error_msg))
+ }
+
+ LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
+
+ for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
+ {
+ LLInventoryCategory* category = *iter;
+ if (!has_correct_permissions_for_sale(category, error_msg))
{
return false;
}
- }
+ }
return true;
}
@@ -1246,18 +1246,18 @@ bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInve
{
accept = can_move_to_marketplace(inv_item, tooltip_msg, true);
}
-
+
// Check that the total amount of items won't violate the max limit on the marketplace
if (accept)
{
// If the dest folder is a stock folder, we do not count the incoming items toward the total (stock items are seen as one)
int existing_item_count = (move_in_stock ? 0 : bundle_size);
-
+
// If the dest folder is a stock folder, we do assume that the incoming items are also stock items (they should anyway)
int existing_stock_count = (move_in_stock ? bundle_size : 0);
-
+
int existing_folder_count = 0;
-
+
// Get the version folder: that's where the counts start from
const LLViewerInventoryCategory * version_folder = ((root_folder && (root_folder != dest_folder)) ? gInventory.getFirstDescendantOf(root_folder->getUUID(), dest_folder->getUUID()) : NULL);
@@ -1271,13 +1271,13 @@ bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInve
LLInventoryModel::cat_array_t existing_categories;
LLInventoryModel::item_array_t existing_items;
-
+
gInventory.collectDescendents(version_folder->getUUID(), existing_categories, existing_items, FALSE);
-
+
existing_item_count += count_copyable_items(existing_items) + count_stock_folders(existing_categories);
existing_stock_count += count_stock_items(existing_items);
existing_folder_count += existing_categories.size();
-
+
// If the incoming item is a nocopy (stock) item, we need to consider that it will create a stock folder
if (!inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) && !move_in_stock)
{
@@ -1285,7 +1285,7 @@ bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInve
existing_folder_count += 1;
}
}
-
+
if (existing_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount"))
{
LLStringUtil::format_map_t args;
@@ -1321,7 +1321,7 @@ bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInve
bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size, bool check_items, bool from_paste)
{
bool accept = true;
-
+
// Compute the nested folders level we'll add into with that incoming folder
int incoming_folder_depth = get_folder_levels(inv_cat);
// Compute the nested folders level we're inserting ourselves in
@@ -1330,7 +1330,7 @@ bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLIn
// Get the version folder: that's where the folders and items counts start from
const LLViewerInventoryCategory * version_folder = (insertion_point_folder_depth >= 2 ? gInventory.getFirstDescendantOf(root_folder->getUUID(), dest_folder->getUUID()) : NULL);
-
+
// Compare the whole with the nested folders depth limit
// Note: substract 2 as we leave root and version folder out of the count threshold
if ((incoming_folder_depth + insertion_point_folder_depth - 2) > (S32)(gSavedSettings.getU32("InventoryOutboxMaxFolderDepth")))
@@ -1341,20 +1341,20 @@ bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLIn
tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels", args);
accept = false;
}
-
+
if (accept)
{
LLInventoryModel::cat_array_t descendent_categories;
LLInventoryModel::item_array_t descendent_items;
gInventory.collectDescendents(inv_cat->getUUID(), descendent_categories, descendent_items, FALSE);
-
+
int dragged_folder_count = descendent_categories.size() + bundle_size; // Note: We assume that we're moving a bunch of folders in. That might be wrong...
int dragged_item_count = count_copyable_items(descendent_items) + count_stock_folders(descendent_categories);
int dragged_stock_count = count_stock_items(descendent_items);
int existing_item_count = 0;
int existing_stock_count = 0;
int existing_folder_count = 0;
-
+
if (version_folder)
{
if (!from_paste && gInventory.isObjectDescendentOf(inv_cat->getUUID(), version_folder->getUUID()))
@@ -1364,21 +1364,21 @@ bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLIn
dragged_item_count = 0;
dragged_stock_count = 0;
}
-
+
// Tally the total number of categories and items inside the root folder
LLInventoryModel::cat_array_t existing_categories;
LLInventoryModel::item_array_t existing_items;
gInventory.collectDescendents(version_folder->getUUID(), existing_categories, existing_items, FALSE);
-
+
existing_folder_count += existing_categories.size();
existing_item_count += count_copyable_items(existing_items) + count_stock_folders(existing_categories);
existing_stock_count += count_stock_items(existing_items);
}
-
+
const int total_folder_count = existing_folder_count + dragged_folder_count;
const int total_item_count = existing_item_count + dragged_item_count;
const int total_stock_count = existing_stock_count + dragged_stock_count;
-
+
if (total_folder_count > gSavedSettings.getU32("InventoryOutboxMaxFolderCount"))
{
LLStringUtil::format_map_t args;
@@ -1403,7 +1403,7 @@ bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLIn
tooltip_msg = LLTrans::getString("TooltipOutboxTooManyStockItems", args);
accept = false;
}
-
+
// Now check that each item in the folder can be moved in the marketplace
if (accept && check_items)
{
@@ -1418,7 +1418,7 @@ bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLIn
}
}
}
-
+
return accept;
}
@@ -1429,33 +1429,33 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
S32 depth = depth_nesting_in_marketplace(dest_folder);
if (depth < 0)
{
- LLSD subs;
- subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Merchant");
- LLNotificationsUtil::add("MerchantPasteFailed", subs);
+ LLSD subs;
+ subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Merchant");
+ LLNotificationsUtil::add("MerchantPasteFailed", subs);
return false;
}
// We will collapse links into items/folders
- LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
- LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
-
- if (linked_category != NULL)
- {
+ LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
+ LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
+
+ if (linked_category != NULL)
+ {
// Move the linked folder directly
- return move_folder_to_marketplacelistings(linked_category, dest_folder, copy);
- }
- else
- {
+ return move_folder_to_marketplacelistings(linked_category, dest_folder, copy);
+ }
+ else
+ {
// Grab the linked item if any
- LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
+ LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
viewer_inv_item = (linked_item != NULL ? linked_item : viewer_inv_item);
-
+
// If we want to copy but the item is no copy, fail silently (this is a common case that doesn't warrant notification)
if (copy && !viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
{
return false;
}
-
+
// Check that the agent has transfer permission on the item: this is required as a resident cannot
// put on sale items she cannot transfer. Proceed with move if we have permission.
std::string error_msg;
@@ -1585,7 +1585,7 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
return false;
}
}
-
+
open_marketplace_listings();
return true;
}
@@ -1607,7 +1607,7 @@ bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUU
LLNotificationsUtil::add("MerchantPasteFailed", subs);
return false;
}
-
+
// Get the parent folder of the moved item : we may have to update it
LLUUID src_folder = inv_cat->getParentUUID();
@@ -1638,14 +1638,14 @@ bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUU
LLNotificationsUtil::add("MerchantPasteFailed", subs);
return false;
}
-
+
open_marketplace_listings();
return true;
}
bool sort_alpha(const LLViewerInventoryCategory* cat1, const LLViewerInventoryCategory* cat2)
{
- return cat1->getName().compare(cat2->getName()) < 0;
+ return cat1->getName().compare(cat2->getName()) < 0;
}
// Make all relevant business logic checks on the marketplace listings starting with the folder as argument.
@@ -1667,7 +1667,7 @@ void validate_marketplacelistings(
{
// Get the type and the depth of the folder
LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (cat);
- const LLFolderType::EType folder_type = cat->getPreferredType();
+ const LLFolderType::EType folder_type = cat->getPreferredType();
if (depth < 0)
{
// If the depth argument was not provided, evaluate the depth directly
@@ -1680,7 +1680,7 @@ void validate_marketplacelistings(
depth = 1;
fix_hierarchy = false;
}
-
+
// Set the indentation for print output (typically, audit button in marketplace folder floater)
std::string indent;
for (int i = 1; i < depth; i++)
@@ -1703,7 +1703,7 @@ void validate_marketplacelistings(
}
}
}
-
+
// Check out that stock folders are at the right level
if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth <= 2))
{
@@ -1752,28 +1752,28 @@ void validate_marketplacelistings(
}
}
}
-
+
// Item sorting and validation : sorting and moving the various stock items is complicated as the set of constraints is high
// We need to:
// * separate non stock items, stock items per types in different folders
// * have stock items nested at depth 2 at least
// * never ever move the non-stock items
-
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
-
+
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
+
// We use a composite (type,permission) key on that map to store UUIDs of items of same (type,permissions)
std::map<U32, std::vector<LLUUID> > items_vector;
// Parse the items and create vectors of item UUIDs sorting copyable items and stock items of various types
bool has_bad_items = false;
- LLInventoryModel::item_array_t item_array_copy = *item_array;
- for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
- {
- LLInventoryItem* item = *iter;
+ LLInventoryModel::item_array_t item_array_copy = *item_array;
+ for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
+ {
+ LLInventoryItem* item = *iter;
LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) item;
-
+
// Test but skip items that shouldn't be there to start with, raise an error message for those
std::string error_msg;
if (!can_move_to_marketplace(item, error_msg, false))
@@ -1797,13 +1797,13 @@ void validate_marketplacelistings(
}
U32 key = (((U32)(type) & 0xFF) << 24) | (perms & 0xFFFFFF);
items_vector[key].push_back(viewer_inv_item->getUUID());
- }
-
+ }
+
// How many types of items? Which type is it if only one?
S32 count = items_vector.size();
U32 default_key = (U32)(LLInventoryType::IT_COUNT) << 24; // This is the key for any normal copyable item
U32 unique_key = (count == 1 ? items_vector.begin()->first : default_key); // The key in the case of one item type only
-
+
// If we have no items in there (only folders or empty), analyze a bit further
if ((count == 0) && !has_bad_items)
{
@@ -2029,7 +2029,7 @@ void validate_marketplacelistings(
}
}
}
-
+
// Clean up
if (viewer_cat->getDescendentCount() == 0)
{
@@ -2051,15 +2051,15 @@ void validate_marketplacelistings(
// Recursion : Perform the same validation on each nested folder
gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
- LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
+ LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
// Sort the folders in alphabetical order first
std::sort(cat_array_copy.begin(), cat_array_copy.end(), sort_alpha);
-
- for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
- {
- LLInventoryCategory* category = *iter;
- validate_marketplacelistings(category, cb_result, cb_msg, fix_hierarchy, depth + 1, false, pending_callbacks, result);
- }
+
+ for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
+ {
+ LLInventoryCategory* category = *iter;
+ validate_marketplacelistings(category, cb_result, cb_msg, fix_hierarchy, depth + 1, false, pending_callbacks, result);
+ }
update_marketplace_category(cat->getUUID(), true, true);
if (notify_observers)
@@ -2071,22 +2071,22 @@ void validate_marketplacelistings(
void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id)
{
- LLInventoryItem* inv_item = gInventory.getItem(item_id);
- if (inv_item)
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
+ LLInventoryItem* inv_item = gInventory.getItem(item_id);
+ if (inv_item)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
- new_item->setParent(new_parent_id);
- new_item->updateParentOnServer(FALSE);
- gInventory.updateItem(new_item);
- gInventory.notifyObservers();
- }
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
+ new_item->setParent(new_parent_id);
+ new_item->updateParentOnServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
}
void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids)
@@ -2114,7 +2114,7 @@ void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected
LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL;
return;
}
- LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
+ LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
if (sidepanel_inventory)
{
if (sidepanel_inventory->getActivePanel())
@@ -2301,7 +2301,7 @@ std::string get_localized_folder_name(LLUUID cat_uuid)
LLTrans::findString(localized_root_name, std::string("InvFolder ") + cat->getName(), LLSD());
}
}
-
+
return localized_root_name;
}
@@ -2531,62 +2531,62 @@ LLMarketplaceValidator::ValidationRequest::ValidationRequest(
// static
bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryItem* item)
{
- if (!item)
- return false;
+ if (!item)
+ return false;
- switch(item->getType())
- {
- case LLAssetType::AT_OBJECT:
- case LLAssetType::AT_BODYPART:
- case LLAssetType::AT_CLOTHING:
- if (!get_is_item_worn(item->getUUID()))
- return true;
- break;
- default:
- return true;
- break;
- }
- return false;
+ switch(item->getType())
+ {
+ case LLAssetType::AT_OBJECT:
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_CLOTHING:
+ if (!get_is_item_worn(item->getUUID()))
+ return true;
+ break;
+ default:
+ return true;
+ break;
+ }
+ return false;
}
bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- if(mType == LLAssetType::AT_CATEGORY)
- {
- if(cat) return TRUE;
- }
- if(item)
- {
- if(item->getType() == mType) return TRUE;
- }
- return FALSE;
+ if(mType == LLAssetType::AT_CATEGORY)
+ {
+ if(cat) return TRUE;
+ }
+ if(item)
+ {
+ if(item->getType() == mType) return TRUE;
+ }
+ return FALSE;
}
bool LLIsNotType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- if(mType == LLAssetType::AT_CATEGORY)
- {
- if(cat) return FALSE;
- }
- if(item)
- {
- if(item->getType() == mType) return FALSE;
- else return TRUE;
- }
- return TRUE;
+ if(mType == LLAssetType::AT_CATEGORY)
+ {
+ if(cat) return FALSE;
+ }
+ if(item)
+ {
+ if(item->getType() == mType) return FALSE;
+ else return TRUE;
+ }
+ return TRUE;
}
bool LLIsOfAssetType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- if(mType == LLAssetType::AT_CATEGORY)
- {
- if(cat) return TRUE;
- }
- if(item)
- {
- if(item->getActualType() == mType) return TRUE;
- }
- return FALSE;
+ if(mType == LLAssetType::AT_CATEGORY)
+ {
+ if(cat) return TRUE;
+ }
+ if(item)
+ {
+ if(item->getActualType() == mType) return TRUE;
+ }
+ return FALSE;
}
bool LLAssetIDAndTypeMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
@@ -2597,120 +2597,133 @@ bool LLAssetIDAndTypeMatches::operator()(LLInventoryCategory* cat, LLInventoryIt
bool LLIsValidItemLink::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
- if (!vitem) return false;
- return (vitem->getActualType() == LLAssetType::AT_LINK && !vitem->getIsBrokenLink());
+ LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
+ if (!vitem) return false;
+ return (vitem->getActualType() == LLAssetType::AT_LINK && !vitem->getIsBrokenLink());
}
bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- if(mType == LLAssetType::AT_CATEGORY)
- {
- if(cat)
- {
- return TRUE;
- }
- }
- if(item)
- {
- if(item->getType() == mType)
- {
- LLPermissions perm = item->getPermissions();
- if ((perm.getMaskBase() & mPerm) == mPerm)
- {
- return TRUE;
- }
- }
- }
- return FALSE;
+ if(mType == LLAssetType::AT_CATEGORY)
+ {
+ if(cat)
+ {
+ return TRUE;
+ }
+ }
+ if(item)
+ {
+ if(item->getType() == mType)
+ {
+ LLPermissions perm = item->getPermissions();
+ if ((perm.getMaskBase() & mPerm) == mPerm)
+ {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
}
bool LLBuddyCollector::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
+ LLInventoryItem* item)
{
- if(item)
- {
- if((LLAssetType::AT_CALLINGCARD == item->getType())
- && (!item->getCreatorUUID().isNull())
- && (item->getCreatorUUID() != gAgent.getID()))
- {
- return true;
- }
- }
- return false;
+ if(item)
+ {
+ if((LLAssetType::AT_CALLINGCARD == item->getType())
+ && (!item->getCreatorUUID().isNull())
+ && (item->getCreatorUUID() != gAgent.getID()))
+ {
+ return true;
+ }
+ }
+ return false;
}
bool LLUniqueBuddyCollector::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
+ LLInventoryItem* item)
{
- if(item)
- {
- if((LLAssetType::AT_CALLINGCARD == item->getType())
- && (item->getCreatorUUID().notNull())
- && (item->getCreatorUUID() != gAgent.getID()))
- {
- mSeen.insert(item->getCreatorUUID());
- return true;
- }
- }
- return false;
+ if(item)
+ {
+ if((LLAssetType::AT_CALLINGCARD == item->getType())
+ && (item->getCreatorUUID().notNull())
+ && (item->getCreatorUUID() != gAgent.getID()))
+ {
+ mSeen.insert(item->getCreatorUUID());
+ return true;
+ }
+ }
+ return false;
}
bool LLParticularBuddyCollector::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
+ LLInventoryItem* item)
{
- if(item)
- {
- if((LLAssetType::AT_CALLINGCARD == item->getType())
- && (item->getCreatorUUID() == mBuddyID))
- {
- return TRUE;
- }
- }
- return FALSE;
+ if(item)
+ {
+ if((LLAssetType::AT_CALLINGCARD == item->getType())
+ && (item->getCreatorUUID() == mBuddyID))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
}
bool LLNameCategoryCollector::operator()(
- LLInventoryCategory* cat, LLInventoryItem* item)
+ LLInventoryCategory* cat, LLInventoryItem* item)
{
- if(cat)
- {
- if (!LLStringUtil::compareInsensitive(mName, cat->getName()))
- {
- return true;
- }
- }
- return false;
+ if(cat)
+ {
+ if (!LLStringUtil::compareInsensitive(mName, cat->getName()))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool LLNameItemCollector::operator()(
+ LLInventoryCategory* cat, LLInventoryItem* item)
+{
+ if(item)
+ {
+ if (!LLStringUtil::compareInsensitive(mName, item->getName()))
+ {
+ return true;
+ }
+ }
+ return false;
}
bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
-{
- // Valid COF items are:
- // - links to wearables (body parts or clothing)
- // - links to attachments
- // - links to gestures
- // - links to ensemble folders
- LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem();
- if (linked_item)
- {
- LLAssetType::EType type = linked_item->getType();
- return (type == LLAssetType::AT_CLOTHING ||
- type == LLAssetType::AT_BODYPART ||
- type == LLAssetType::AT_GESTURE ||
- type == LLAssetType::AT_OBJECT);
- }
- else
- {
- LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory();
- // BAP remove AT_NONE support after ensembles are fully working?
- return (linked_category &&
- ((linked_category->getPreferredType() == LLFolderType::FT_NONE) ||
- (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType()))));
- }
+ LLInventoryItem* item)
+{
+ // Valid COF items are:
+ // - links to wearables (body parts or clothing)
+ // - links to attachments
+ // - links to gestures
+ // - links to ensemble folders
+ LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem();
+ if (linked_item)
+ {
+ LLAssetType::EType type = linked_item->getType();
+ return (type == LLAssetType::AT_CLOTHING ||
+ type == LLAssetType::AT_BODYPART ||
+ type == LLAssetType::AT_GESTURE ||
+ type == LLAssetType::AT_OBJECT);
+ }
+ else
+ {
+ LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory();
+ // BAP remove AT_NONE support after ensembles are fully working?
+ return (linked_category &&
+ ((linked_category->getPreferredType() == LLFolderType::FT_NONE) ||
+ (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType()))));
+ }
}
bool LLFindBrokenLinks::operator()(LLInventoryCategory* cat,
@@ -2727,68 +2740,68 @@ bool LLFindBrokenLinks::operator()(LLInventoryCategory* cat,
}
bool LLFindWearables::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
+ LLInventoryItem* item)
{
- if(item)
- {
- if((item->getType() == LLAssetType::AT_CLOTHING)
- || (item->getType() == LLAssetType::AT_BODYPART))
- {
- return TRUE;
- }
- }
- return FALSE;
+ if(item)
+ {
+ if((item->getType() == LLAssetType::AT_CLOTHING)
+ || (item->getType() == LLAssetType::AT_BODYPART))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
}
LLFindWearablesEx::LLFindWearablesEx(bool is_worn, bool include_body_parts)
-: mIsWorn(is_worn)
-, mIncludeBodyParts(include_body_parts)
+: mIsWorn(is_worn)
+, mIncludeBodyParts(include_body_parts)
{}
bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
- if (!vitem) return false;
+ LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
+ if (!vitem) return false;
- // Skip non-wearables.
- if (!vitem->isWearableType() && vitem->getType() != LLAssetType::AT_OBJECT && vitem->getType() != LLAssetType::AT_GESTURE)
- {
- return false;
- }
+ // Skip non-wearables.
+ if (!vitem->isWearableType() && vitem->getType() != LLAssetType::AT_OBJECT && vitem->getType() != LLAssetType::AT_GESTURE)
+ {
+ return false;
+ }
- // Skip body parts if requested.
- if (!mIncludeBodyParts && vitem->getType() == LLAssetType::AT_BODYPART)
- {
- return false;
- }
+ // Skip body parts if requested.
+ if (!mIncludeBodyParts && vitem->getType() == LLAssetType::AT_BODYPART)
+ {
+ return false;
+ }
- // Skip broken links.
- if (vitem->getIsBrokenLink())
- {
- return false;
- }
+ // Skip broken links.
+ if (vitem->getIsBrokenLink())
+ {
+ return false;
+ }
- return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;
+ return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;
}
bool LLFindWearablesOfType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- if (!item) return false;
- if (item->getType() != LLAssetType::AT_CLOTHING &&
- item->getType() != LLAssetType::AT_BODYPART)
- {
- return false;
- }
+ if (!item) return false;
+ if (item->getType() != LLAssetType::AT_CLOTHING &&
+ item->getType() != LLAssetType::AT_BODYPART)
+ {
+ return false;
+ }
- LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
- if (!vitem || vitem->getWearableType() != mWearableType) return false;
+ LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
+ if (!vitem || vitem->getWearableType() != mWearableType) return false;
- return true;
+ return true;
}
void LLFindWearablesOfType::setType(LLWearableType::EType type)
{
- mWearableType = type;
+ mWearableType = type;
}
bool LLIsTextureType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
@@ -2798,141 +2811,141 @@ bool LLIsTextureType::operator()(LLInventoryCategory* cat, LLInventoryItem* item
bool LLFindNonRemovableObjects::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- if (item)
- {
- return !get_is_item_removable(&gInventory, item->getUUID());
- }
- if (cat)
- {
- return !get_is_category_removable(&gInventory, cat->getUUID());
- }
+ if (item)
+ {
+ return !get_is_item_removable(&gInventory, item->getUUID());
+ }
+ if (cat)
+ {
+ return !get_is_category_removable(&gInventory, cat->getUUID());
+ }
- LL_WARNS() << "Not a category and not an item?" << LL_ENDL;
- return false;
+ LL_WARNS() << "Not a category and not an item?" << LL_ENDL;
+ return false;
}
///----------------------------------------------------------------------------
-/// LLAssetIDMatches
+/// LLAssetIDMatches
///----------------------------------------------------------------------------
bool LLAssetIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- return (item && item->getAssetUUID() == mAssetID);
+ return (item && item->getAssetUUID() == mAssetID);
}
///----------------------------------------------------------------------------
-/// LLLinkedItemIDMatches
+/// LLLinkedItemIDMatches
///----------------------------------------------------------------------------
bool LLLinkedItemIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- return (item &&
- (item->getIsLinkType()) &&
- (item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
+ return (item &&
+ (item->getIsLinkType()) &&
+ (item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
}
void LLSaveFolderState::setApply(BOOL apply)
{
- mApply = apply;
- // before generating new list of open folders, clear the old one
- if(!apply)
- {
- clearOpenFolders();
- }
+ mApply = apply;
+ // before generating new list of open folders, clear the old one
+ if(!apply)
+ {
+ clearOpenFolders();
+ }
}
void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
{
- LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getViewModelItem();
- if(!bridge) return;
-
- if(mApply)
- {
- // we're applying the open state
- LLUUID id(bridge->getUUID());
- if(mOpenFolders.find(id) != mOpenFolders.end())
- {
- if (!folder->isOpen())
- {
- folder->setOpen(TRUE);
- }
- }
- else
- {
- // keep selected filter in its current state, this is less jarring to user
- if (!folder->isSelected() && folder->isOpen())
- {
- folder->setOpen(FALSE);
- }
- }
- }
- else
- {
- // we're recording state at this point
- if(folder->isOpen())
- {
- mOpenFolders.insert(bridge->getUUID());
- }
- }
+ LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getViewModelItem();
+ if(!bridge) return;
+
+ if(mApply)
+ {
+ // we're applying the open state
+ LLUUID id(bridge->getUUID());
+ if(mOpenFolders.find(id) != mOpenFolders.end())
+ {
+ if (!folder->isOpen())
+ {
+ folder->setOpen(TRUE);
+ }
+ }
+ else
+ {
+ // keep selected filter in its current state, this is less jarring to user
+ if (!folder->isSelected() && folder->isOpen())
+ {
+ folder->setOpen(FALSE);
+ }
+ }
+ }
+ else
+ {
+ // we're recording state at this point
+ if(folder->isOpen())
+ {
+ mOpenFolders.insert(bridge->getUUID());
+ }
+ }
}
void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)
{
- if (item->passedFilter())
- {
- item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
- }
+ if (item->passedFilter())
+ {
+ item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
}
void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)
{
- if (folder->LLFolderViewItem::passedFilter() && folder->getParentFolder())
- {
- folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
- }
- // if this folder didn't pass the filter, and none of its descendants did
- else if (!folder->getViewModelItem()->passedFilter() && !folder->getViewModelItem()->descendantsPassedFilter())
- {
- folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);
- }
+ if (folder->LLFolderViewItem::passedFilter() && folder->getParentFolder())
+ {
+ folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+ // if this folder didn't pass the filter, and none of its descendants did
+ else if (!folder->getViewModelItem()->passedFilter() && !folder->getViewModelItem()->descendantsPassedFilter())
+ {
+ folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);
+ }
}
void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)
{
- if (item->passedFilter() && !mItemSelected)
- {
- item->getRoot()->setSelection(item, FALSE, FALSE);
- if (item->getParentFolder())
- {
- item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
- }
- mItemSelected = TRUE;
- }
+ if (item->passedFilter() && !mItemSelected)
+ {
+ item->getRoot()->setSelection(item, FALSE, FALSE);
+ if (item->getParentFolder())
+ {
+ item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+ mItemSelected = TRUE;
+ }
}
void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)
{
- // Skip if folder or item already found, if not filtered or if no parent (root folder is not selectable)
- if (!mFolderSelected && !mItemSelected && folder->LLFolderViewItem::passedFilter() && folder->getParentFolder())
- {
- folder->getRoot()->setSelection(folder, FALSE, FALSE);
- folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
- mFolderSelected = TRUE;
- }
+ // Skip if folder or item already found, if not filtered or if no parent (root folder is not selectable)
+ if (!mFolderSelected && !mItemSelected && folder->LLFolderViewItem::passedFilter() && folder->getParentFolder())
+ {
+ folder->getRoot()->setSelection(folder, FALSE, FALSE);
+ folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ mFolderSelected = TRUE;
+ }
}
void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item)
{
- if (item->getParentFolder() && item->isSelected())
- {
- item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
- }
+ if (item->getParentFolder() && item->isSelected())
+ {
+ item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
}
void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)
{
- if (folder->getParentFolder() && folder->isSelected())
- {
- folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
- }
+ if (folder->getParentFolder() && folder->isSelected())
+ {
+ folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
}
// Callback for doToSelected if DAMA required...
@@ -2962,34 +2975,34 @@ void LLInventoryAction::callback_copySelected(const LLSD& notification, const LL
// case returns their corresponding uuids.
bool get_selection_object_uuids(LLFolderView *root, uuid_vec_t& ids)
{
- uuid_vec_t results;
- S32 non_object = 0;
- LLFolderView::selected_items_t selectedItems = root->getSelectedItems();
- for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
- {
- LLObjectBridge *view_model = dynamic_cast<LLObjectBridge *>((*it)->getViewModelItem());
-
- if(view_model && view_model->getUUID().notNull())
- {
- results.push_back(view_model->getUUID());
- }
- else
- {
- non_object++;
- }
- }
- if (non_object == 0)
- {
- ids = results;
- return true;
- }
- return false;
+ uuid_vec_t results;
+ S32 non_object = 0;
+ LLFolderView::selected_items_t selectedItems = root->getSelectedItems();
+ for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
+ {
+ LLObjectBridge *view_model = dynamic_cast<LLObjectBridge *>((*it)->getViewModelItem());
+
+ if(view_model && view_model->getUUID().notNull())
+ {
+ results.push_back(view_model->getUUID());
+ }
+ else
+ {
+ non_object++;
+ }
+ }
+ if (non_object == 0)
+ {
+ ids = results;
+ return true;
+ }
+ return false;
}
void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action, BOOL user_confirm)
{
- std::set<LLFolderViewItem*> selected_items = root->getSelectionList();
+ std::set<LLFolderViewItem*> selected_items = root->getSelectionList();
if (selected_items.empty()
&& action != "wear"
&& action != "wear_add"
@@ -3007,9 +3020,9 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
return;
}
-
+
// Prompt the user and check for authorization for some marketplace active listing edits
- if (user_confirm && (("delete" == action) || ("cut" == action) || ("rename" == action) || ("properties" == action) || ("task_properties" == action) || ("open" == action)))
+ if (user_confirm && (("delete" == action) || ("cut" == action) || ("rename" == action) || ("properties" == action) || ("task_properties" == action) || ("open" == action)))
{
std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin();
LLFolderViewModelItemInventory * viewModel = NULL;
@@ -3066,138 +3079,138 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
return;
}
}
-
+
// Keep track of the marketplace folders that will need update of their status/name after the operation is performed
buildMarketplaceFolders(root);
-
- if ("rename" == action)
- {
- root->startRenamingSelectedItem();
+
+ if ("rename" == action)
+ {
+ root->startRenamingSelectedItem();
// Update the marketplace listings that have been affected by the operation
updateMarketplaceFolders();
- return;
- }
-
- if ("delete" == action)
- {
- const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
- bool marketplacelistings_item = false;
- LLAllDescendentsPassedFilter f;
- for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(); (it != selected_items.end()) && (f.allDescendentsPassedFilter()); ++it)
- {
- if (LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(*it))
- {
- folder->applyFunctorRecursively(f);
- }
- LLFolderViewModelItemInventory * viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*it)->getViewModelItem());
- if (viewModel && gInventory.isObjectDescendentOf(viewModel->getUUID(), marketplacelistings_id))
- {
- marketplacelistings_item = true;
- break;
- }
- }
- // Fall through to the generic confirmation if the user choose to ignore the specialized one
- if ( (!f.allDescendentsPassedFilter()) && !marketplacelistings_item && (!LLNotifications::instance().getIgnored("DeleteFilteredItems")) )
- {
- LLNotificationsUtil::add("DeleteFilteredItems", LLSD(), LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
- }
- else
- {
- if (!sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session
- {
- LLNotifications::instance().setIgnored("DeleteItems", false);
- sDeleteConfirmationDisplayed = true;
- }
-
- LLSD args;
- args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" : "DeleteItem");
- LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
- }
+ return;
+ }
+
+ if ("delete" == action)
+ {
+ const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ bool marketplacelistings_item = false;
+ LLAllDescendentsPassedFilter f;
+ for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(); (it != selected_items.end()) && (f.allDescendentsPassedFilter()); ++it)
+ {
+ if (LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(*it))
+ {
+ folder->applyFunctorRecursively(f);
+ }
+ LLFolderViewModelItemInventory * viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*it)->getViewModelItem());
+ if (viewModel && gInventory.isObjectDescendentOf(viewModel->getUUID(), marketplacelistings_id))
+ {
+ marketplacelistings_item = true;
+ break;
+ }
+ }
+ // Fall through to the generic confirmation if the user choose to ignore the specialized one
+ if ( (!f.allDescendentsPassedFilter()) && !marketplacelistings_item && (!LLNotifications::instance().getIgnored("DeleteFilteredItems")) )
+ {
+ LLNotificationsUtil::add("DeleteFilteredItems", LLSD(), LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
+ }
+ else
+ {
+ if (!sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session
+ {
+ LLNotifications::instance().setIgnored("DeleteItems", false);
+ sDeleteConfirmationDisplayed = true;
+ }
+
+ LLSD args;
+ args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" : "DeleteItem");
+ LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
+ }
// Note: marketplace listings will be updated in the callback if delete confirmed
- return;
- }
- if (("copy" == action) || ("cut" == action))
- {
- // Clear the clipboard before we start adding things on it
- LLClipboard::instance().reset();
- }
- if ("replace_links" == action)
- {
- LLSD params;
- if (root->getSelectedCount() == 1)
- {
- LLFolderViewItem* folder_item = root->getSelectedItems().front();
- LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
-
- if (bridge)
- {
- LLInventoryObject* obj = bridge->getInventoryObject();
- if (obj && obj->getType() != LLAssetType::AT_CATEGORY && obj->getActualType() != LLAssetType::AT_LINK_FOLDER)
- {
- params = LLSD(obj->getUUID());
- }
- }
- }
- LLFloaterReg::showInstance("linkreplace", params);
- return;
- }
-
- static const std::string change_folder_string = "change_folder_type_";
- if (action.length() > change_folder_string.length() &&
- (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0))
- {
- LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length()));
- LLFolderViewModelItemInventory* inventory_item = static_cast<LLFolderViewModelItemInventory*>(root->getViewModelItem());
- LLViewerInventoryCategory *cat = model->getCategory(inventory_item->getUUID());
- if (!cat) return;
- cat->changeType(new_folder_type);
+ return;
+ }
+ if (("copy" == action) || ("cut" == action))
+ {
+ // Clear the clipboard before we start adding things on it
+ LLClipboard::instance().reset();
+ }
+ if ("replace_links" == action)
+ {
+ LLSD params;
+ if (root->getSelectedCount() == 1)
+ {
+ LLFolderViewItem* folder_item = root->getSelectedItems().front();
+ LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
+
+ if (bridge)
+ {
+ LLInventoryObject* obj = bridge->getInventoryObject();
+ if (obj && obj->getType() != LLAssetType::AT_CATEGORY && obj->getActualType() != LLAssetType::AT_LINK_FOLDER)
+ {
+ params = LLSD(obj->getUUID());
+ }
+ }
+ }
+ LLFloaterReg::showInstance("linkreplace", params);
+ return;
+ }
+
+ static const std::string change_folder_string = "change_folder_type_";
+ if (action.length() > change_folder_string.length() &&
+ (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0))
+ {
+ LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length()));
+ LLFolderViewModelItemInventory* inventory_item = static_cast<LLFolderViewModelItemInventory*>(root->getViewModelItem());
+ LLViewerInventoryCategory *cat = model->getCategory(inventory_item->getUUID());
+ if (!cat) return;
+ cat->changeType(new_folder_type);
// Update the marketplace listings that have been affected by the operation
updateMarketplaceFolders();
- return;
- }
-
-
- LLMultiPreview* multi_previewp = NULL;
- LLMultiItemProperties* multi_itempropertiesp = nullptr;
-
- if (("task_open" == action || "open" == action) && selected_items.size() > 1)
- {
- bool open_multi_preview = true;
-
- if ("open" == action)
- {
- for (std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
- {
- LLFolderViewItem* folder_item = *set_iter;
- if (folder_item)
- {
- LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(folder_item->getViewModelItem());
- if (!bridge || !bridge->isMultiPreviewAllowed())
- {
- open_multi_preview = false;
- break;
- }
- }
- }
- }
-
- if (open_multi_preview)
- {
- multi_previewp = new LLMultiPreview();
- gFloaterView->addChild(multi_previewp);
-
- LLFloater::setFloaterHost(multi_previewp);
- }
-
- }
- else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1)
- {
- multi_itempropertiesp = new LLMultiItemProperties("item_properties");
- gFloaterView->addChild(multi_itempropertiesp);
- LLFloater::setFloaterHost(multi_itempropertiesp);
- }
-
- std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs();
+ return;
+ }
+
+
+ LLMultiPreview* multi_previewp = NULL;
+ LLMultiItemProperties* multi_itempropertiesp = nullptr;
+
+ if (("task_open" == action || "open" == action) && selected_items.size() > 1)
+ {
+ bool open_multi_preview = true;
+
+ if ("open" == action)
+ {
+ for (std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
+ {
+ LLFolderViewItem* folder_item = *set_iter;
+ if (folder_item)
+ {
+ LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(folder_item->getViewModelItem());
+ if (!bridge || !bridge->isMultiPreviewAllowed())
+ {
+ open_multi_preview = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (open_multi_preview)
+ {
+ multi_previewp = new LLMultiPreview();
+ gFloaterView->addChild(multi_previewp);
+
+ LLFloater::setFloaterHost(multi_previewp);
+ }
+
+ }
+ else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1)
+ {
+ multi_itempropertiesp = new LLMultiItemProperties("item_properties");
+ gFloaterView->addChild(multi_itempropertiesp);
+ LLFloater::setFloaterHost(multi_itempropertiesp);
+ }
+
+ std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs();
// copy list of applicable items into a vector for bulk handling
uuid_vec_t ids;
@@ -3294,10 +3307,10 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
return;
}
}
-
+
LLSD args;
args["DESC"] = LLTrans::getString("New Folder");
-
+
LLNotificationsUtil::add("CreateSubfolder", args, LLSD(),
[ids](const LLSD& notification, const LLSD& response)
{
@@ -3345,22 +3358,22 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
// Update the marketplace listings that have been affected by the operation
updateMarketplaceFolders();
-
- LLFloater::setFloaterHost(NULL);
- if (multi_previewp)
- {
- multi_previewp->openFloater(LLSD());
- }
- else if (multi_itempropertiesp)
- {
- multi_itempropertiesp->openFloater(LLSD());
- }
+
+ LLFloater::setFloaterHost(NULL);
+ if (multi_previewp)
+ {
+ multi_previewp->openFloater(LLSD());
+ }
+ else if (multi_itempropertiesp)
+ {
+ multi_itempropertiesp->openFloater(LLSD());
+ }
}
void LLInventoryAction::saveMultipleTextures(const std::vector<std::string>& filenames, std::set<LLFolderViewItem*> selected_items, LLInventoryModel* model)
{
gSavedSettings.setString("TextureSaveLocation", filenames[0]);
-
+
LLMultiPreview* multi_previewp = new LLMultiPreview();
gFloaterView->addChild(multi_previewp);
@@ -3368,7 +3381,7 @@ void LLInventoryAction::saveMultipleTextures(const std::vector<std::string>& fil
std::map<std::string, S32> tex_names_map;
std::set<LLFolderViewItem*>::iterator set_iter;
-
+
for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
{
LLFolderViewItem* folder_item = *set_iter;
@@ -3377,10 +3390,10 @@ void LLInventoryAction::saveMultipleTextures(const std::vector<std::string>& fil
if(!bridge) continue;
std::string tex_name = bridge->getName();
- if(!tex_names_map.insert(std::pair<std::string, S32>(tex_name, 0)).second)
- {
+ if(!tex_names_map.insert(std::pair<std::string, S32>(tex_name, 0)).second)
+ {
tex_names_map[tex_name]++;
- bridge->setFileName(tex_name + llformat("_%.3d", tex_names_map[tex_name]));
+ bridge->setFileName(tex_name + llformat("_%.3d", tex_names_map[tex_name]));
}
bridge->performAction(model, "save_selected_as");
}
@@ -3417,18 +3430,18 @@ void LLInventoryAction::removeItemFromDND(LLFolderView* root)
void LLInventoryAction::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option == 0 && !root.isDead() && !root.get()->isDead())
- {
- LLFolderView* folder_root = root.get();
- //Need to remove item from DND before item is removed from root folder view
- //because once removed from root folder view the item is no longer a selected item
- removeItemFromDND(folder_root);
- folder_root->removeSelectedItems();
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0 && !root.isDead() && !root.get()->isDead())
+ {
+ LLFolderView* folder_root = root.get();
+ //Need to remove item from DND before item is removed from root folder view
+ //because once removed from root folder view the item is no longer a selected item
+ removeItemFromDND(folder_root);
+ folder_root->removeSelectedItems();
- // Update the marketplace listings that have been affected by the operation
- updateMarketplaceFolders();
- }
+ // Update the marketplace listings that have been affected by the operation
+ updateMarketplaceFolders();
+ }
}
void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root)
@@ -3444,7 +3457,7 @@ void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root)
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
if (marketplacelistings_id.isNull())
{
- return;
+ return;
}
std::set<LLFolderViewItem*> selected_items = root->getSelectionList();
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 0c4b64586d..edc83147f2 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llinventoryfunctions.h
* @brief Miscellaneous inventory-related functions and classes
* class definition
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -184,10 +184,10 @@ private:
class LLInventoryCollectFunctor
{
public:
- virtual ~LLInventoryCollectFunctor(){};
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) = 0;
+ virtual ~LLInventoryCollectFunctor(){};
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) = 0;
- static bool itemTransferCommonlyAllowed(const LLInventoryItem* item);
+ static bool itemTransferCommonlyAllowed(const LLInventoryItem* item);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -200,12 +200,12 @@ class LLViewerInventoryItem;
class LLAssetIDMatches : public LLInventoryCollectFunctor
{
public:
- LLAssetIDMatches(const LLUUID& asset_id) : mAssetID(asset_id) {}
- virtual ~LLAssetIDMatches() {}
- bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
-
+ LLAssetIDMatches(const LLUUID& asset_id) : mAssetID(asset_id) {}
+ virtual ~LLAssetIDMatches() {}
+ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+
protected:
- LLUUID mAssetID;
+ LLUUID mAssetID;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -217,12 +217,12 @@ protected:
class LLLinkedItemIDMatches : public LLInventoryCollectFunctor
{
public:
- LLLinkedItemIDMatches(const LLUUID& item_id) : mBaseItemID(item_id) {}
- virtual ~LLLinkedItemIDMatches() {}
- bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
-
+ LLLinkedItemIDMatches(const LLUUID& item_id) : mBaseItemID(item_id) {}
+ virtual ~LLLinkedItemIDMatches() {}
+ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+
protected:
- LLUUID mBaseItemID;
+ LLUUID mBaseItemID;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -235,12 +235,12 @@ protected:
class LLIsType : public LLInventoryCollectFunctor
{
public:
- LLIsType(LLAssetType::EType type) : mType(type) {}
- virtual ~LLIsType() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ LLIsType(LLAssetType::EType type) : mType(type) {}
+ virtual ~LLIsType() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
protected:
- LLAssetType::EType mType;
+ LLAssetType::EType mType;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -252,12 +252,12 @@ protected:
class LLIsNotType : public LLInventoryCollectFunctor
{
public:
- LLIsNotType(LLAssetType::EType type) : mType(type) {}
- virtual ~LLIsNotType() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ LLIsNotType(LLAssetType::EType type) : mType(type) {}
+ virtual ~LLIsNotType() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
protected:
- LLAssetType::EType mType;
+ LLAssetType::EType mType;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -271,12 +271,12 @@ protected:
class LLIsOfAssetType : public LLInventoryCollectFunctor
{
public:
- LLIsOfAssetType(LLAssetType::EType type) : mType(type) {}
- virtual ~LLIsOfAssetType() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ LLIsOfAssetType(LLAssetType::EType type) : mType(type) {}
+ virtual ~LLIsOfAssetType() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
protected:
- LLAssetType::EType mType;
+ LLAssetType::EType mType;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -304,23 +304,23 @@ protected:
class LLIsValidItemLink : public LLInventoryCollectFunctor
{
public:
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
};
class LLIsTypeWithPermissions : public LLInventoryCollectFunctor
{
public:
- LLIsTypeWithPermissions(LLAssetType::EType type, const PermissionBit perms, const LLUUID &agent_id, const LLUUID &group_id)
- : mType(type), mPerm(perms), mAgentID(agent_id), mGroupID(group_id) {}
- virtual ~LLIsTypeWithPermissions() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ LLIsTypeWithPermissions(LLAssetType::EType type, const PermissionBit perms, const LLUUID &agent_id, const LLUUID &group_id)
+ : mType(type), mPerm(perms), mAgentID(agent_id), mGroupID(group_id) {}
+ virtual ~LLIsTypeWithPermissions() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
protected:
- LLAssetType::EType mType;
- PermissionBit mPerm;
- LLUUID mAgentID;
- LLUUID mGroupID;
+ LLAssetType::EType mType;
+ PermissionBit mPerm;
+ LLUUID mAgentID;
+ LLUUID mGroupID;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -332,10 +332,10 @@ protected:
class LLBuddyCollector : public LLInventoryCollectFunctor
{
public:
- LLBuddyCollector() {}
- virtual ~LLBuddyCollector() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ LLBuddyCollector() {}
+ virtual ~LLBuddyCollector() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -347,13 +347,13 @@ public:
class LLUniqueBuddyCollector : public LLInventoryCollectFunctor
{
public:
- LLUniqueBuddyCollector() {}
- virtual ~LLUniqueBuddyCollector() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ LLUniqueBuddyCollector() {}
+ virtual ~LLUniqueBuddyCollector() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
protected:
- std::set<LLUUID> mSeen;
+ std::set<LLUUID> mSeen;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -365,12 +365,12 @@ protected:
class LLParticularBuddyCollector : public LLInventoryCollectFunctor
{
public:
- LLParticularBuddyCollector(const LLUUID& id) : mBuddyID(id) {}
- virtual ~LLParticularBuddyCollector() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ LLParticularBuddyCollector(const LLUUID& id) : mBuddyID(id) {}
+ virtual ~LLParticularBuddyCollector() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
protected:
- LLUUID mBuddyID;
+ LLUUID mBuddyID;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -381,12 +381,28 @@ protected:
class LLNameCategoryCollector : public LLInventoryCollectFunctor
{
public:
- LLNameCategoryCollector(const std::string& name) : mName(name) {}
- virtual ~LLNameCategoryCollector() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ LLNameCategoryCollector(const std::string& name) : mName(name) {}
+ virtual ~LLNameCategoryCollector() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
+protected:
+ std::string mName;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLNameItemCollector
+//
+// Collects items based on case-insensitive match of prefix
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLNameItemCollector : public LLInventoryCollectFunctor
+{
+public:
+ LLNameItemCollector(const std::string& name) : mName(name) {}
+ virtual ~LLNameItemCollector() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
protected:
- std::string mName;
+ std::string mName;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -397,11 +413,11 @@ protected:
class LLFindCOFValidItems : public LLInventoryCollectFunctor
{
public:
- LLFindCOFValidItems() {}
- virtual ~LLFindCOFValidItems() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
-
+ LLFindCOFValidItems() {}
+ virtual ~LLFindCOFValidItems() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
+
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -424,23 +440,23 @@ public:
class LLFindByMask : public LLInventoryCollectFunctor
{
public:
- LLFindByMask(U64 mask)
- : mFilterMask(mask)
- {}
+ LLFindByMask(U64 mask)
+ : mFilterMask(mask)
+ {}
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
- {
- //converting an inventory type to a bitmap filter mask
- if(item && (mFilterMask & (1LL << item->getInventoryType())) )
- {
- return true;
- }
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ //converting an inventory type to a bitmap filter mask
+ if(item && (mFilterMask & (1LL << item->getInventoryType())) )
+ {
+ return true;
+ }
- return false;
- }
+ return false;
+ }
private:
- U64 mFilterMask;
+ U64 mFilterMask;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -451,27 +467,27 @@ private:
class LLFindNonLinksByMask : public LLInventoryCollectFunctor
{
public:
- LLFindNonLinksByMask(U64 mask)
- : mFilterMask(mask)
- {}
+ LLFindNonLinksByMask(U64 mask)
+ : mFilterMask(mask)
+ {}
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
- {
- if(item && !item->getIsLinkType() && (mFilterMask & (1LL << item->getInventoryType())) )
- {
- return true;
- }
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ if(item && !item->getIsLinkType() && (mFilterMask & (1LL << item->getInventoryType())) )
+ {
+ return true;
+ }
- return false;
- }
+ return false;
+ }
- void setFilterMask(U64 mask)
- {
- mFilterMask = mask;
- }
+ void setFilterMask(U64 mask)
+ {
+ mFilterMask = mask;
+ }
private:
- U64 mFilterMask;
+ U64 mFilterMask;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -482,10 +498,10 @@ private:
class LLFindWearables : public LLInventoryCollectFunctor
{
public:
- LLFindWearables() {}
- virtual ~LLFindWearables() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
+ LLFindWearables() {}
+ virtual ~LLFindWearables() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -496,24 +512,24 @@ public:
class LLFindWearablesEx : public LLInventoryCollectFunctor
{
public:
- LLFindWearablesEx(bool is_worn, bool include_body_parts = true);
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+ LLFindWearablesEx(bool is_worn, bool include_body_parts = true);
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
private:
- bool mIncludeBodyParts;
- bool mIsWorn;
+ bool mIncludeBodyParts;
+ bool mIsWorn;
};
//Inventory collect functor collecting wearables of a specific wearable type
class LLFindWearablesOfType : public LLInventoryCollectFunctor
{
public:
- LLFindWearablesOfType(LLWearableType::EType type) : mWearableType(type) {}
- virtual ~LLFindWearablesOfType() {}
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
- void setType(LLWearableType::EType type);
+ LLFindWearablesOfType(LLWearableType::EType type) : mWearableType(type) {}
+ virtual ~LLFindWearablesOfType() {}
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+ void setType(LLWearableType::EType type);
private:
- LLWearableType::EType mWearableType;
+ LLWearableType::EType mWearableType;
};
class LLIsTextureType : public LLInventoryCollectFunctor
@@ -529,33 +545,33 @@ public:
class LLFindActualWearablesOfType : public LLFindWearablesOfType
{
public:
- LLFindActualWearablesOfType(LLWearableType::EType type) : LLFindWearablesOfType(type) {}
- virtual ~LLFindActualWearablesOfType() {}
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
- {
- if (item && item->getIsLinkType()) return false;
- return LLFindWearablesOfType::operator()(cat, item);
- }
+ LLFindActualWearablesOfType(LLWearableType::EType type) : LLFindWearablesOfType(type) {}
+ virtual ~LLFindActualWearablesOfType() {}
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ if (item && item->getIsLinkType()) return false;
+ return LLFindWearablesOfType::operator()(cat, item);
+ }
};
/* Filters out items of a particular asset type */
class LLIsTypeActual : public LLIsType
{
public:
- LLIsTypeActual(LLAssetType::EType type) : LLIsType(type) {}
- virtual ~LLIsTypeActual() {}
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
- {
- if (item && item->getIsLinkType()) return false;
- return LLIsType::operator()(cat, item);
- }
+ LLIsTypeActual(LLAssetType::EType type) : LLIsType(type) {}
+ virtual ~LLIsTypeActual() {}
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ if (item && item->getIsLinkType()) return false;
+ return LLIsType::operator()(cat, item);
+ }
};
// Collect non-removable folders and items.
class LLFindNonRemovableObjects : public LLInventoryCollectFunctor
{
public:
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
};
/** Inventory Collector Functions
@@ -569,27 +585,27 @@ class LLFolderView;
class LLInventoryState
{
public:
- // HACK: Until we can route this info through the instant message hierarchy
- static BOOL sWearNewClothing;
- static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction
+ // HACK: Until we can route this info through the instant message hierarchy
+ static BOOL sWearNewClothing;
+ static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction
};
struct LLInventoryAction
{
- static void doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action, BOOL user_confirm = TRUE);
- static void callback_doToSelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action);
- static void callback_copySelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action);
- static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root);
- static void removeItemFromDND(LLFolderView* root);
+ static void doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action, BOOL user_confirm = TRUE);
+ static void callback_doToSelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action);
+ static void callback_copySelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action);
+ static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root);
+ static void removeItemFromDND(LLFolderView* root);
static void saveMultipleTextures(const std::vector<std::string>& filenames, std::set<LLFolderViewItem*> selected_items, LLInventoryModel* model);
static bool sDeleteConfirmationDisplayed;
private:
- static void buildMarketplaceFolders(LLFolderView* root);
- static void updateMarketplaceFolders();
- static std::list<LLUUID> sMarketplaceFolders; // Marketplace folders that will need update once the action is completed
+ static void buildMarketplaceFolders(LLFolderView* root);
+ static void updateMarketplaceFolders();
+ static std::list<LLUUID> sMarketplaceFolders; // Marketplace folders that will need update once the action is completed
};
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 0787266adb..3a930684a4 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llinventorymodel.cpp
* @brief Implementation of the inventory model used to track agent inventory.
*
* $LicenseInfo:firstyear=2002&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$
*/
@@ -50,7 +50,7 @@
#include "llwindow.h"
#include "llviewercontrol.h"
#include "llviewernetwork.h"
-#include "llpreview.h"
+#include "llpreview.h"
#include "llviewergenericmessage.h"
#include "llviewermessage.h"
#include "llviewerfoldertype.h"
@@ -94,49 +94,49 @@ static const char * const LOG_INV("Inventory");
struct InventoryIDPtrLess
{
- bool operator()(const LLViewerInventoryCategory* i1, const LLViewerInventoryCategory* i2) const
- {
- return (i1->getUUID() < i2->getUUID());
- }
+ bool operator()(const LLViewerInventoryCategory* i1, const LLViewerInventoryCategory* i2) const
+ {
+ return (i1->getUUID() < i2->getUUID());
+ }
};
-class LLCanCache : public LLInventoryCollectFunctor
+class LLCanCache : public LLInventoryCollectFunctor
{
public:
- LLCanCache(LLInventoryModel* model) : mModel(model) {}
- virtual ~LLCanCache() {}
- virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+ LLCanCache(LLInventoryModel* model) : mModel(model) {}
+ virtual ~LLCanCache() {}
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
protected:
- LLInventoryModel* mModel;
- std::set<LLUUID> mCachedCatIDs;
+ LLInventoryModel* mModel;
+ std::set<LLUUID> mCachedCatIDs;
};
bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- bool rv = false;
- if(item)
- {
- if(mCachedCatIDs.find(item->getParentUUID()) != mCachedCatIDs.end())
- {
- rv = true;
- }
- }
- else if(cat)
- {
- // HACK: downcast
- LLViewerInventoryCategory* c = (LLViewerInventoryCategory*)cat;
- if(c->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
- {
- S32 descendents_server = c->getDescendentCount();
- S32 descendents_actual = c->getViewerDescendentCount();
- if(descendents_server == descendents_actual)
- {
- mCachedCatIDs.insert(c->getUUID());
- rv = true;
- }
- }
- }
- return rv;
+ bool rv = false;
+ if(item)
+ {
+ if(mCachedCatIDs.find(item->getParentUUID()) != mCachedCatIDs.end())
+ {
+ rv = true;
+ }
+ }
+ else if(cat)
+ {
+ // HACK: downcast
+ LLViewerInventoryCategory* c = (LLViewerInventoryCategory*)cat;
+ if(c->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
+ {
+ S32 descendents_server = c->getDescendentCount();
+ S32 descendents_actual = c->getViewerDescendentCount();
+ if(descendents_server == descendents_actual)
+ {
+ mCachedCatIDs.insert(c->getUUID());
+ rv = true;
+ }
+ }
+ }
+ return rv;
}
struct InventoryCallbackInfo
@@ -364,7 +364,7 @@ LLInventoryValidationInfo::LLInventoryValidationInfo()
void LLInventoryValidationInfo::toOstream(std::ostream& os) const
{
- os << "mFatalErrorCount " << mFatalErrorCount
+ os << "mFatalErrorCount " << mFatalErrorCount
<< " mWarningCount " << mWarningCount
<< " mLoopCount " << mLoopCount
<< " mOrphanedCount " << mOrphanedCount;
@@ -373,52 +373,52 @@ void LLInventoryValidationInfo::toOstream(std::ostream& os) const
std::ostream& operator<<(std::ostream& os, const LLInventoryValidationInfo& v)
{
- v.toOstream(os);
- return os;
+ v.toOstream(os);
+ return os;
}
void LLInventoryValidationInfo::asLLSD(LLSD& sd) const
{
- sd["fatal_error_count"] = mFatalErrorCount;
+ sd["fatal_error_count"] = mFatalErrorCount;
sd["loop_count"] = mLoopCount;
sd["orphaned_count"] = mOrphanedCount;
- sd["initialized"] = mInitialized;
- sd["missing_system_folders_count"] = LLSD::Integer(mMissingRequiredSystemFolders.size());
- sd["fatal_no_root_folder"] = mFatalNoRootFolder;
- sd["fatal_no_library_root_folder"] = mFatalNoLibraryRootFolder;
- sd["fatal_qa_debug_mode"] = mFatalQADebugMode;
-
- sd["warning_count"] = mWarningCount;
- if (mWarningCount>0)
- {
- sd["warnings"] = LLSD::emptyArray();
- for (auto const& it : mWarnings)
- {
- S32 val =LLSD::Integer(it.second);
- if (val>0)
- {
- sd["warnings"][it.first] = val;
- }
- }
- }
- if (mMissingRequiredSystemFolders.size()>0)
- {
- sd["missing_system_folders"] = LLSD::emptyArray();
- for(auto ft: mMissingRequiredSystemFolders)
- {
- sd["missing_system_folders"].append(LLFolderType::lookup(ft));
- }
- }
- sd["duplicate_system_folders_count"] = LLSD::Integer(mDuplicateRequiredSystemFolders.size());
- if (mDuplicateRequiredSystemFolders.size()>0)
- {
- sd["duplicate_system_folders"] = LLSD::emptyArray();
- for(auto ft: mDuplicateRequiredSystemFolders)
- {
- sd["duplicate_system_folders"].append(LLFolderType::lookup(ft));
- }
- }
-
+ sd["initialized"] = mInitialized;
+ sd["missing_system_folders_count"] = LLSD::Integer(mMissingRequiredSystemFolders.size());
+ sd["fatal_no_root_folder"] = mFatalNoRootFolder;
+ sd["fatal_no_library_root_folder"] = mFatalNoLibraryRootFolder;
+ sd["fatal_qa_debug_mode"] = mFatalQADebugMode;
+
+ sd["warning_count"] = mWarningCount;
+ if (mWarningCount>0)
+ {
+ sd["warnings"] = LLSD::emptyArray();
+ for (auto const& it : mWarnings)
+ {
+ S32 val =LLSD::Integer(it.second);
+ if (val>0)
+ {
+ sd["warnings"][it.first] = val;
+ }
+ }
+ }
+ if (mMissingRequiredSystemFolders.size()>0)
+ {
+ sd["missing_system_folders"] = LLSD::emptyArray();
+ for(auto ft: mMissingRequiredSystemFolders)
+ {
+ sd["missing_system_folders"].append(LLFolderType::lookup(ft));
+ }
+ }
+ sd["duplicate_system_folders_count"] = LLSD::Integer(mDuplicateRequiredSystemFolders.size());
+ if (mDuplicateRequiredSystemFolders.size()>0)
+ {
+ sd["duplicate_system_folders"] = LLSD::emptyArray();
+ for(auto ft: mDuplicateRequiredSystemFolders)
+ {
+ sd["duplicate_system_folders"].append(LLFolderType::lookup(ft));
+ }
+ }
+
}
///----------------------------------------------------------------------------
@@ -431,117 +431,117 @@ LLInventoryModel gInventory;
// Default constructor
LLInventoryModel::LLInventoryModel()
: // These are now ordered, keep them that way.
- mBacklinkMMap(),
- mIsAgentInvUsable(false),
- mRootFolderID(),
- mLibraryRootFolderID(),
- mLibraryOwnerID(),
- mCategoryMap(),
- mItemMap(),
- mParentChildCategoryTree(),
- mParentChildItemTree(),
- mLastItem(NULL),
- mIsNotifyObservers(FALSE),
- mModifyMask(LLInventoryObserver::ALL),
- mChangedItemIDs(),
+ mBacklinkMMap(),
+ mIsAgentInvUsable(false),
+ mRootFolderID(),
+ mLibraryRootFolderID(),
+ mLibraryOwnerID(),
+ mCategoryMap(),
+ mItemMap(),
+ mParentChildCategoryTree(),
+ mParentChildItemTree(),
+ mLastItem(NULL),
+ mIsNotifyObservers(FALSE),
+ mModifyMask(LLInventoryObserver::ALL),
+ mChangedItemIDs(),
mBulkFecthCallbackSlot(),
- mObservers(),
- mHttpRequestFG(NULL),
- mHttpRequestBG(NULL),
- mHttpOptions(),
- mHttpHeaders(),
- mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mCategoryLock(),
- mItemLock(),
- mValidationInfo(new LLInventoryValidationInfo)
+ mObservers(),
+ mHttpRequestFG(NULL),
+ mHttpRequestBG(NULL),
+ mHttpOptions(),
+ mHttpHeaders(),
+ mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
+ mCategoryLock(),
+ mItemLock(),
+ mValidationInfo(new LLInventoryValidationInfo)
{}
// Destroys the object
LLInventoryModel::~LLInventoryModel()
{
- cleanupInventory();
+ cleanupInventory();
}
void LLInventoryModel::cleanupInventory()
{
- empty();
- // Deleting one observer might erase others from the list, so always pop off the front
- while (!mObservers.empty())
- {
- observer_list_t::iterator iter = mObservers.begin();
- LLInventoryObserver* observer = *iter;
- mObservers.erase(iter);
- delete observer;
- }
+ empty();
+ // Deleting one observer might erase others from the list, so always pop off the front
+ while (!mObservers.empty())
+ {
+ observer_list_t::iterator iter = mObservers.begin();
+ LLInventoryObserver* observer = *iter;
+ mObservers.erase(iter);
+ delete observer;
+ }
if (mBulkFecthCallbackSlot.connected())
{
mBulkFecthCallbackSlot.disconnect();
}
- mObservers.clear();
+ mObservers.clear();
- // Run down HTTP transport
+ // Run down HTTP transport
mHttpHeaders.reset();
mHttpOptions.reset();
- delete mHttpRequestFG;
- mHttpRequestFG = NULL;
- delete mHttpRequestBG;
- mHttpRequestBG = NULL;
+ delete mHttpRequestFG;
+ mHttpRequestFG = NULL;
+ delete mHttpRequestBG;
+ mHttpRequestBG = NULL;
}
// This is a convenience function to check if one object has a parent
// chain up to the category specified by UUID.
BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id,
- const LLUUID& cat_id) const
+ const LLUUID& cat_id) const
{
- if (obj_id == cat_id) return TRUE;
-
- const LLInventoryObject* obj = getObject(obj_id);
- while(obj)
- {
- const LLUUID& parent_id = obj->getParentUUID();
- if( parent_id.isNull() )
- {
- return FALSE;
- }
- if(parent_id == cat_id)
- {
- return TRUE;
- }
- // Since we're scanning up the parents, we only need to check
- // in the category list.
- obj = getCategory(parent_id);
- }
- return FALSE;
+ if (obj_id == cat_id) return TRUE;
+
+ const LLInventoryObject* obj = getObject(obj_id);
+ while(obj)
+ {
+ const LLUUID& parent_id = obj->getParentUUID();
+ if( parent_id.isNull() )
+ {
+ return FALSE;
+ }
+ if(parent_id == cat_id)
+ {
+ return TRUE;
+ }
+ // Since we're scanning up the parents, we only need to check
+ // in the category list.
+ obj = getCategory(parent_id);
+ }
+ return FALSE;
}
const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(const LLUUID& obj_id) const
{
- const LLInventoryObject* obj = getObject(obj_id);
- if(!obj)
- {
- LL_WARNS(LOG_INV) << "Non-existent object [ id: " << obj_id << " ] " << LL_ENDL;
- return NULL;
- }
- // Search up the parent chain until we get to root or an acceptable folder.
- // This assumes there are no cycles in the tree else we'll get a hang.
- LLUUID parent_id = obj->getParentUUID();
- while (!parent_id.isNull())
- {
- const LLViewerInventoryCategory *cat = getCategory(parent_id);
- if (!cat) break;
- const LLFolderType::EType folder_type = cat->getPreferredType();
- if (folder_type != LLFolderType::FT_NONE &&
- folder_type != LLFolderType::FT_ROOT_INVENTORY &&
- !LLFolderType::lookupIsEnsembleType(folder_type))
- {
- return cat;
- }
- parent_id = cat->getParentUUID();
- }
- return NULL;
+ const LLInventoryObject* obj = getObject(obj_id);
+ if(!obj)
+ {
+ LL_WARNS(LOG_INV) << "Non-existent object [ id: " << obj_id << " ] " << LL_ENDL;
+ return NULL;
+ }
+ // Search up the parent chain until we get to root or an acceptable folder.
+ // This assumes there are no cycles in the tree else we'll get a hang.
+ LLUUID parent_id = obj->getParentUUID();
+ while (!parent_id.isNull())
+ {
+ const LLViewerInventoryCategory *cat = getCategory(parent_id);
+ if (!cat) break;
+ const LLFolderType::EType folder_type = cat->getPreferredType();
+ if (folder_type != LLFolderType::FT_NONE &&
+ folder_type != LLFolderType::FT_ROOT_INVENTORY &&
+ !LLFolderType::lookupIsEnsembleType(folder_type))
+ {
+ return cat;
+ }
+ parent_id = cat->getParentUUID();
+ }
+ return NULL;
}
//
@@ -549,36 +549,36 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons
//
const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LLUUID& master_parent_id, const LLUUID& obj_id) const
{
- if (master_parent_id == obj_id)
- {
- return NULL;
- }
-
- const LLViewerInventoryCategory* current_cat = getCategory(obj_id);
-
- if (current_cat == NULL)
- {
- current_cat = getCategory(getObject(obj_id)->getParentUUID());
- }
-
- while (current_cat != NULL)
- {
- const LLUUID& current_parent_id = current_cat->getParentUUID();
-
- if (current_parent_id == master_parent_id)
- {
- return current_cat;
- }
-
- current_cat = getCategory(current_parent_id);
- }
-
- return NULL;
+ if (master_parent_id == obj_id)
+ {
+ return NULL;
+ }
+
+ const LLViewerInventoryCategory* current_cat = getCategory(obj_id);
+
+ if (current_cat == NULL)
+ {
+ current_cat = getCategory(getObject(obj_id)->getParentUUID());
+ }
+
+ while (current_cat != NULL)
+ {
+ const LLUUID& current_parent_id = current_cat->getParentUUID();
+
+ if (current_parent_id == master_parent_id)
+ {
+ return current_cat;
+ }
+
+ current_cat = getCategory(current_parent_id);
+ }
+
+ return NULL;
}
LLInventoryModel::EAncestorResult LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
{
- LLInventoryObject *object = getObject(object_id);
+ LLInventoryObject *object = getObject(object_id);
if (!object)
{
LL_WARNS(LOG_INV) << "Unable to trace topmost ancestor, initial object " << object_id << " does not exist" << LL_ENDL;
@@ -596,73 +596,73 @@ LLInventoryModel::EAncestorResult LLInventoryModel::getObjectTopmostAncestor(con
}
object_ids.insert(parent_id);
LLInventoryObject *parent_object = getObject(parent_id);
- if (!parent_object)
- {
- LL_WARNS(LOG_INV) << "unable to trace topmost ancestor of " << object_id << ", missing item for uuid " << parent_id << LL_ENDL;
- return ANCESTOR_MISSING;
- }
- object = parent_object;
- }
- result = object->getUUID();
- return ANCESTOR_OK;
+ if (!parent_object)
+ {
+ LL_WARNS(LOG_INV) << "unable to trace topmost ancestor of " << object_id << ", missing item for uuid " << parent_id << LL_ENDL;
+ return ANCESTOR_MISSING;
+ }
+ object = parent_object;
+ }
+ result = object->getUUID();
+ return ANCESTOR_OK;
}
// Get the object by id. Returns NULL if not found.
LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const
{
- LLViewerInventoryCategory* cat = getCategory(id);
- if (cat)
- {
- return cat;
- }
- LLViewerInventoryItem* item = getItem(id);
- if (item)
- {
- return item;
- }
- return NULL;
+ LLViewerInventoryCategory* cat = getCategory(id);
+ if (cat)
+ {
+ return cat;
+ }
+ LLViewerInventoryItem* item = getItem(id);
+ if (item)
+ {
+ return item;
+ }
+ return NULL;
}
// Get the item by id. Returns NULL if not found.
LLViewerInventoryItem* LLInventoryModel::getItem(const LLUUID& id) const
{
- LLViewerInventoryItem* item = NULL;
- if(mLastItem.notNull() && mLastItem->getUUID() == id)
- {
- item = mLastItem;
- }
- else
- {
- item_map_t::const_iterator iter = mItemMap.find(id);
- if (iter != mItemMap.end())
- {
- item = iter->second;
- mLastItem = item;
- }
- }
- return item;
+ LLViewerInventoryItem* item = NULL;
+ if(mLastItem.notNull() && mLastItem->getUUID() == id)
+ {
+ item = mLastItem;
+ }
+ else
+ {
+ item_map_t::const_iterator iter = mItemMap.find(id);
+ if (iter != mItemMap.end())
+ {
+ item = iter->second;
+ mLastItem = item;
+ }
+ }
+ return item;
}
// Get the category by id. Returns NULL if not found
LLViewerInventoryCategory* LLInventoryModel::getCategory(const LLUUID& id) const
{
- LLViewerInventoryCategory* category = NULL;
- cat_map_t::const_iterator iter = mCategoryMap.find(id);
- if (iter != mCategoryMap.end())
- {
- category = iter->second;
- }
- return category;
+ LLViewerInventoryCategory* category = NULL;
+ cat_map_t::const_iterator iter = mCategoryMap.find(id);
+ if (iter != mCategoryMap.end())
+ {
+ category = iter->second;
+ }
+ return category;
}
S32 LLInventoryModel::getItemCount() const
{
- return mItemMap.size();
+ return mItemMap.size();
}
S32 LLInventoryModel::getCategoryCount() const
{
- return mCategoryMap.size();
+ return mCategoryMap.size();
}
// Return the direct descendents of the id provided. The array
@@ -671,11 +671,11 @@ S32 LLInventoryModel::getCategoryCount() const
// may invalidate the internal state of the inventory. Set passed
// in values to NULL if the call fails.
void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id,
- cat_array_t*& categories,
- item_array_t*& items) const
+ cat_array_t*& categories,
+ item_array_t*& items) const
{
- categories = get_ptr_in_map(mParentChildCategoryTree, cat_id);
- items = get_ptr_in_map(mParentChildItemTree, cat_id);
+ categories = get_ptr_in_map(mParentChildCategoryTree, cat_id);
+ items = get_ptr_in_map(mParentChildItemTree, cat_id);
}
void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, cat_array_t& categories, item_array_t& items, LLInventoryCollectFunctor& f) const
@@ -684,10 +684,10 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, cat_array_t&
{
for (LLViewerInventoryCategory* pFolder : *categoriesp)
{
- if (f(pFolder, nullptr))
- {
- categories.push_back(pFolder);
- }
+ if (f(pFolder, nullptr))
+ {
+ categories.push_back(pFolder);
+ }
}
}
@@ -695,56 +695,56 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, cat_array_t&
{
for (LLViewerInventoryItem* pItem : *itemsp)
{
- if (f(nullptr, pItem))
- {
- items.push_back(pItem);
- }
+ if (f(nullptr, pItem))
+ {
+ items.push_back(pItem);
+ }
}
}
}
LLInventoryModel::digest_t LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const
{
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- getDirectDescendentsOf(cat_id,cat_array,item_array);
- if (!item_array)
- {
- return LLUUID::null;
- }
- HBXXH128 item_name_hash;
- for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin();
- iter != item_array->end();
- iter++)
- {
- const LLViewerInventoryItem *item = (*iter);
- if (!item)
- continue;
- item_name_hash.update(item->getName());
- }
- return item_name_hash.digest();
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ getDirectDescendentsOf(cat_id,cat_array,item_array);
+ if (!item_array)
+ {
+ return LLUUID::null;
+ }
+ HBXXH128 item_name_hash;
+ for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin();
+ iter != item_array->end();
+ iter++)
+ {
+ const LLViewerInventoryItem *item = (*iter);
+ if (!item)
+ continue;
+ item_name_hash.update(item->getName());
+ }
+ return item_name_hash.digest();
}
// SJB: Added version to lock the arrays to catch potential logic bugs
void LLInventoryModel::lockDirectDescendentArrays(const LLUUID& cat_id,
- cat_array_t*& categories,
- item_array_t*& items)
+ cat_array_t*& categories,
+ item_array_t*& items)
{
- getDirectDescendentsOf(cat_id, categories, items);
- if (categories)
- {
- mCategoryLock[cat_id] = true;
- }
- if (items)
- {
- mItemLock[cat_id] = true;
- }
+ getDirectDescendentsOf(cat_id, categories, items);
+ if (categories)
+ {
+ mCategoryLock[cat_id] = true;
+ }
+ if (items)
+ {
+ mItemLock[cat_id] = true;
+ }
}
void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id)
{
- mCategoryLock[cat_id] = false;
- mItemLock[cat_id] = false;
+ mCategoryLock[cat_id] = false;
+ mItemLock[cat_id] = false;
}
void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::EType type)
@@ -761,15 +761,15 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E
}
// Iterate through those folders
- for (std::vector<LLUUID>::iterator folder_ids_it = folder_ids.begin(); folder_ids_it != folder_ids.end(); ++folder_ids_it)
- {
- LLUUID folder_id = (*folder_ids_it);
-
+ for (std::vector<LLUUID>::iterator folder_ids_it = folder_ids.begin(); folder_ids_it != folder_ids.end(); ++folder_ids_it)
+ {
+ LLUUID folder_id = (*folder_ids_it);
+
// Get the content of this folder
cat_array_t* cats;
item_array_t* items;
getDirectDescendentsOf(folder_id, cats, items);
-
+
// Move all items to the main folder
// Note : we get the list of UUIDs and iterate on them instead of iterating directly on item_array_t
// elements. This is because moving elements modify the maps and, consequently, invalidate iterators on them.
@@ -809,7 +809,7 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E
}
}
remove_inventory_category(folder_id, NULL);
- }
+ }
}
void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred_type)
@@ -881,49 +881,49 @@ void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred
}
const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
- LLFolderType::EType preferred_type,
- const LLUUID& root_id) const
+ LLFolderType::EType preferred_type,
+ const LLUUID& root_id) const
{
- LLUUID rv = LLUUID::null;
- if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)
- {
- rv = root_id;
- }
- else if (root_id.notNull())
- {
- cat_array_t* cats = NULL;
- cats = get_ptr_in_map(mParentChildCategoryTree, root_id);
- if(cats)
- {
- S32 count = cats->size();
- for(S32 i = 0; i < count; ++i)
- {
- LLViewerInventoryCategory* p_cat = cats->at(i);
- if(p_cat && p_cat->getPreferredType() == preferred_type)
- {
- const LLUUID& folder_id = cats->at(i)->getUUID();
- if (rv.isNull() || folder_id < rv)
- {
- rv = folder_id;
- }
- }
- }
- }
- }
-
- if(rv.isNull()
+ LLUUID rv = LLUUID::null;
+ if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)
+ {
+ rv = root_id;
+ }
+ else if (root_id.notNull())
+ {
+ cat_array_t* cats = NULL;
+ cats = get_ptr_in_map(mParentChildCategoryTree, root_id);
+ if(cats)
+ {
+ S32 count = cats->size();
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLViewerInventoryCategory* p_cat = cats->at(i);
+ if(p_cat && p_cat->getPreferredType() == preferred_type)
+ {
+ const LLUUID& folder_id = cats->at(i)->getUUID();
+ if (rv.isNull() || folder_id < rv)
+ {
+ rv = folder_id;
+ }
+ }
+ }
+ }
+ }
+
+ if(rv.isNull()
&& root_id.notNull()
&& preferred_type != LLFolderType::FT_MARKETPLACE_LISTINGS
&& preferred_type != LLFolderType::FT_OUTBOX)
- {
+ {
// if it does not exists, it should either be added
// to createCommonSystemCategories or server should
// have set it
llassert(!isInventoryUsable());
LL_WARNS("Inventory") << "Tried to find folder, type " << preferred_type
- << " but category does not exist" << LL_ENDL;
- }
- return rv;
+ << " but category does not exist" << LL_ENDL;
+ }
+ return rv;
}
// findCategoryUUIDForType() returns the uuid of the category that
@@ -932,7 +932,7 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
// inventory category on the fly if one does not exist.
const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type) const
{
- return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getRootFolderID());
+ return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getRootFolderID());
}
const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type) const
@@ -968,7 +968,7 @@ const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::
default:
break;
}
-
+
if (cat_id.isNull() || !getCategory(cat_id))
{
cat_id = findCategoryUUIDForTypeInRoot(preferred_type, getRootFolderID());
@@ -978,7 +978,7 @@ const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::
const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type) const
{
- return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getLibraryRootFolderID());
+ return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getLibraryRootFolderID());
}
// Convenience function to create a new category. You could call
@@ -986,56 +986,56 @@ const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::ETyp
// version will take care of details like what the name should be
// based on preferred type.
void LLInventoryModel::createNewCategory(const LLUUID& parent_id,
- LLFolderType::EType preferred_type,
- const std::string& pname,
- inventory_func_type callback,
- const LLUUID& thumbnail_id)
+ LLFolderType::EType preferred_type,
+ const std::string& pname,
+ inventory_func_type callback,
+ const LLUUID& thumbnail_id)
{
- LL_DEBUGS(LOG_INV) << "Create '" << pname << "' in '" << make_inventory_path(parent_id) << "'" << LL_ENDL;
- if (!isInventoryUsable())
- {
- LL_WARNS(LOG_INV) << "Inventory is not usable; can't create requested category of type "
- << preferred_type << LL_ENDL;
+ LL_DEBUGS(LOG_INV) << "Create '" << pname << "' in '" << make_inventory_path(parent_id) << "'" << LL_ENDL;
+ if (!isInventoryUsable())
+ {
+ LL_WARNS(LOG_INV) << "Inventory is not usable; can't create requested category of type "
+ << preferred_type << LL_ENDL;
if (callback)
{
callback(LLUUID::null);
}
- return;
- }
+ return;
+ }
- if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup())
- {
- LL_DEBUGS(LOG_INV) << "Attempt to create undefined category." << LL_ENDL;
+ if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup())
+ {
+ LL_DEBUGS(LOG_INV) << "Attempt to create undefined category." << LL_ENDL;
if (callback)
{
callback(LLUUID::null);
}
- return;
- }
-
- if (preferred_type != LLFolderType::FT_NONE)
- {
- // Ultimately this should only be done for non-singleton
- // types. Requires back-end changes to guarantee that others
- // already exist.
- LL_WARNS(LOG_INV) << "Creating new system folder, type " << preferred_type << LL_ENDL;
- }
-
- std::string name = pname;
- if (pname.empty())
- {
- name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
- }
-
- if (AISAPI::isAvailable())
- {
- LLSD new_inventory = LLSD::emptyMap();
- new_inventory["categories"] = LLSD::emptyArray();
- LLViewerInventoryCategory cat(LLUUID::null, parent_id, preferred_type, name, gAgent.getID());
+ return;
+ }
+
+ if (preferred_type != LLFolderType::FT_NONE)
+ {
+ // Ultimately this should only be done for non-singleton
+ // types. Requires back-end changes to guarantee that others
+ // already exist.
+ LL_WARNS(LOG_INV) << "Creating new system folder, type " << preferred_type << LL_ENDL;
+ }
+
+ std::string name = pname;
+ if (pname.empty())
+ {
+ name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
+ }
+
+ if (AISAPI::isAvailable())
+ {
+ LLSD new_inventory = LLSD::emptyMap();
+ new_inventory["categories"] = LLSD::emptyArray();
+ LLViewerInventoryCategory cat(LLUUID::null, parent_id, preferred_type, name, gAgent.getID());
cat.setThumbnailUUID(thumbnail_id);
- LLSD cat_sd = cat.asAISCreateCatLLSD();
- new_inventory["categories"].append(cat_sd);
- AISAPI::CreateInventory(
+ LLSD cat_sd = cat.asAISCreateCatLLSD();
+ new_inventory["categories"].append(cat_sd);
+ AISAPI::CreateInventory(
parent_id,
new_inventory,
[this, callback, parent_id, preferred_type, name] (const LLUUID& new_category)
@@ -1075,32 +1075,32 @@ void LLInventoryModel::createNewCategory(const LLUUID& parent_id,
}
});
return;
- }
-
- LLViewerRegion* viewer_region = gAgent.getRegion();
- std::string url;
- if ( viewer_region )
- url = viewer_region->getCapability("CreateInventoryCategory");
-
- if (!url.empty())
- {
- //Let's use the new capability.
+ }
+
+ LLViewerRegion* viewer_region = gAgent.getRegion();
+ std::string url;
+ if ( viewer_region )
+ url = viewer_region->getCapability("CreateInventoryCategory");
+
+ if (!url.empty())
+ {
+ //Let's use the new capability.
LLUUID id;
- id.generate();
- LLSD request, body;
- body["folder_id"] = id;
- body["parent_id"] = parent_id;
- body["type"] = (LLSD::Integer) preferred_type;
- body["name"] = name;
-
- request["message"] = "CreateInventoryCategory";
- request["payload"] = body;
-
- LL_DEBUGS(LOG_INV) << "Creating category via request: " << ll_pretty_print_sd(request) << LL_ENDL;
+ id.generate();
+ LLSD request, body;
+ body["folder_id"] = id;
+ body["parent_id"] = parent_id;
+ body["type"] = (LLSD::Integer) preferred_type;
+ body["name"] = name;
+
+ request["message"] = "CreateInventoryCategory";
+ request["payload"] = body;
+
+ LL_DEBUGS(LOG_INV) << "Creating category via request: " << ll_pretty_print_sd(request) << LL_ENDL;
LLCoros::instance().launch("LLInventoryModel::createNewCategoryCoro",
boost::bind(&LLInventoryModel::createNewCategoryCoro, this, url, body, callback));
return;
- }
+ }
if (callback)
{
@@ -1115,7 +1115,7 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("createNewCategoryCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
-
+
httpOpts->setWantHeaders(true);
@@ -1213,36 +1213,36 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv
// category has any immediate children meeting a condition, without
// needing to recurse or build up any lists.
bool LLInventoryModel::hasMatchingDirectDescendent(const LLUUID& cat_id,
- LLInventoryCollectFunctor& filter)
+ LLInventoryCollectFunctor& filter)
{
- LLInventoryModel::cat_array_t *cats;
- LLInventoryModel::item_array_t *items;
- getDirectDescendentsOf(cat_id, cats, items);
- if (cats)
- {
- for (LLInventoryModel::cat_array_t::const_iterator it = cats->begin();
- it != cats->end(); ++it)
- {
- if (filter(*it,NULL))
- {
- return true;
- }
- }
- }
- if (items)
- {
- for (LLInventoryModel::item_array_t::const_iterator it = items->begin();
- it != items->end(); ++it)
- {
- if (filter(NULL,*it))
- {
- return true;
- }
- }
- }
- return false;
+ LLInventoryModel::cat_array_t *cats;
+ LLInventoryModel::item_array_t *items;
+ getDirectDescendentsOf(cat_id, cats, items);
+ if (cats)
+ {
+ for (LLInventoryModel::cat_array_t::const_iterator it = cats->begin();
+ it != cats->end(); ++it)
+ {
+ if (filter(*it,NULL))
+ {
+ return true;
+ }
+ }
+ }
+ if (items)
+ {
+ for (LLInventoryModel::item_array_t::const_iterator it = items->begin();
+ it != items->end(); ++it)
+ {
+ if (filter(NULL,*it))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
}
-
+
// Starting with the object specified, add its descendents to the
// array provided, but do not add the inventory object specified by
// id. There is no guaranteed order. Neither array will be erased
@@ -1253,135 +1253,135 @@ bool LLInventoryModel::hasMatchingDirectDescendent(const LLUUID& cat_id,
class LLAlwaysCollect : public LLInventoryCollectFunctor
{
public:
- virtual ~LLAlwaysCollect() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
- {
- return TRUE;
- }
+ virtual ~LLAlwaysCollect() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+ {
+ return TRUE;
+ }
};
void LLInventoryModel::collectDescendents(const LLUUID& id,
- cat_array_t& cats,
- item_array_t& items,
- BOOL include_trash)
+ cat_array_t& cats,
+ item_array_t& items,
+ BOOL include_trash)
{
- LLAlwaysCollect always;
- collectDescendentsIf(id, cats, items, include_trash, always);
+ LLAlwaysCollect always;
+ collectDescendentsIf(id, cats, items, include_trash, always);
}
void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
- cat_array_t& cats,
- item_array_t& items,
- BOOL include_trash,
- LLInventoryCollectFunctor& add)
+ cat_array_t& cats,
+ item_array_t& items,
+ BOOL include_trash,
+ LLInventoryCollectFunctor& add)
{
- // Start with categories
- if(!include_trash)
- {
- const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
- if(trash_id.notNull() && (trash_id == id))
- return;
- }
- cat_array_t* cat_array = get_ptr_in_map(mParentChildCategoryTree, id);
- if(cat_array)
- {
- S32 count = cat_array->size();
- for(S32 i = 0; i < count; ++i)
- {
- LLViewerInventoryCategory* cat = cat_array->at(i);
- if(add(cat,NULL))
- {
- cats.push_back(cat);
- }
- collectDescendentsIf(cat->getUUID(), cats, items, include_trash, add);
- }
- }
-
- LLViewerInventoryItem* item = NULL;
- item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
-
- // Move onto items
- if(item_array)
- {
- S32 count = item_array->size();
- for(S32 i = 0; i < count; ++i)
- {
- item = item_array->at(i);
- if(add(NULL, item))
- {
- items.push_back(item);
- }
- }
- }
+ // Start with categories
+ if(!include_trash)
+ {
+ const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if(trash_id.notNull() && (trash_id == id))
+ return;
+ }
+ cat_array_t* cat_array = get_ptr_in_map(mParentChildCategoryTree, id);
+ if(cat_array)
+ {
+ S32 count = cat_array->size();
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLViewerInventoryCategory* cat = cat_array->at(i);
+ if(add(cat,NULL))
+ {
+ cats.push_back(cat);
+ }
+ collectDescendentsIf(cat->getUUID(), cats, items, include_trash, add);
+ }
+ }
+
+ LLViewerInventoryItem* item = NULL;
+ item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
+
+ // Move onto items
+ if(item_array)
+ {
+ S32 count = item_array->size();
+ for(S32 i = 0; i < count; ++i)
+ {
+ item = item_array->at(i);
+ if(add(NULL, item))
+ {
+ items.push_back(item);
+ }
+ }
+ }
}
void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
{
- const LLInventoryObject *obj = getObject(object_id);
- if (!obj || obj->getIsLinkType())
- return;
-
- LLInventoryModel::item_array_t item_array = collectLinksTo(object_id);
- for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
- iter != item_array.end();
- iter++)
- {
- LLViewerInventoryItem *linked_item = (*iter);
- addChangedMask(mask, linked_item->getUUID());
- };
+ const LLInventoryObject *obj = getObject(object_id);
+ if (!obj || obj->getIsLinkType())
+ return;
+
+ LLInventoryModel::item_array_t item_array = collectLinksTo(object_id);
+ for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
+ iter != item_array.end();
+ iter++)
+ {
+ LLViewerInventoryItem *linked_item = (*iter);
+ addChangedMask(mask, linked_item->getUUID());
+ };
}
const LLUUID& LLInventoryModel::getLinkedItemID(const LLUUID& object_id) const
{
- const LLInventoryItem *item = gInventory.getItem(object_id);
- if (!item)
- {
- return object_id;
- }
-
- // Find the base item in case this a link (if it's not a link,
- // this will just be inv_item_id)
- return item->getLinkedUUID();
+ const LLInventoryItem *item = gInventory.getItem(object_id);
+ if (!item)
+ {
+ return object_id;
+ }
+
+ // Find the base item in case this a link (if it's not a link,
+ // this will just be inv_item_id)
+ return item->getLinkedUUID();
}
LLViewerInventoryItem* LLInventoryModel::getLinkedItem(const LLUUID& object_id) const
{
- return object_id.notNull() ? getItem(getLinkedItemID(object_id)) : NULL;
+ return object_id.notNull() ? getItem(getLinkedItemID(object_id)) : NULL;
}
LLInventoryModel::item_array_t LLInventoryModel::collectLinksTo(const LLUUID& id)
{
- // Get item list via collectDescendents (slow!)
- item_array_t items;
- const LLInventoryObject *obj = getObject(id);
- // FIXME - should be as in next line, but this is causing a
- // stack-smashing crash of cause TBD... check in the REBUILD code.
- //if (obj && obj->getIsLinkType())
- if (!obj || obj->getIsLinkType())
- return items;
-
- std::pair<backlink_mmap_t::iterator, backlink_mmap_t::iterator> range = mBacklinkMMap.equal_range(id);
- for (backlink_mmap_t::iterator it = range.first; it != range.second; ++it)
- {
- LLViewerInventoryItem *item = getItem(it->second);
- if (item)
- {
- items.push_back(item);
- }
- }
-
- return items;
+ // Get item list via collectDescendents (slow!)
+ item_array_t items;
+ const LLInventoryObject *obj = getObject(id);
+ // FIXME - should be as in next line, but this is causing a
+ // stack-smashing crash of cause TBD... check in the REBUILD code.
+ //if (obj && obj->getIsLinkType())
+ if (!obj || obj->getIsLinkType())
+ return items;
+
+ std::pair<backlink_mmap_t::iterator, backlink_mmap_t::iterator> range = mBacklinkMMap.equal_range(id);
+ for (backlink_mmap_t::iterator it = range.first; it != range.second; ++it)
+ {
+ LLViewerInventoryItem *item = getItem(it->second);
+ if (item)
+ {
+ items.push_back(item);
+ }
+ }
+
+ return items;
}
bool LLInventoryModel::isInventoryUsable() const
{
- bool result = false;
- if(gInventory.getRootFolderID().notNull() && mIsAgentInvUsable)
- {
- result = true;
- }
- return result;
+ bool result = false;
+ if(gInventory.getRootFolderID().notNull() && mIsAgentInvUsable)
+ {
+ result = true;
+ }
+ return result;
}
// Calling this method with an inventory item will either change an
@@ -1389,34 +1389,34 @@ bool LLInventoryModel::isInventoryUsable() const
// current inventory.
U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)
{
- if(item->getUUID().isNull())
- {
- return mask;
- }
-
- if(!isInventoryUsable())
- {
- LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL;
- return mask;
- }
-
- if (item->getType() == LLAssetType::AT_MESH)
- {
- return mask;
- }
-
- LLPointer<LLViewerInventoryItem> old_item = getItem(item->getUUID());
- LLPointer<LLViewerInventoryItem> new_item;
- if(old_item)
- {
- // We already have an old item, modify its values
- new_item = old_item;
- LLUUID old_parent_id = old_item->getParentUUID();
- LLUUID new_parent_id = item->getParentUUID();
- bool update_parent_on_server = false;
-
- if (new_parent_id.isNull() && !LLApp::isExiting())
- {
+ if(item->getUUID().isNull())
+ {
+ return mask;
+ }
+
+ if(!isInventoryUsable())
+ {
+ LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL;
+ return mask;
+ }
+
+ if (item->getType() == LLAssetType::AT_MESH)
+ {
+ return mask;
+ }
+
+ LLPointer<LLViewerInventoryItem> old_item = getItem(item->getUUID());
+ LLPointer<LLViewerInventoryItem> new_item;
+ if(old_item)
+ {
+ // We already have an old item, modify its values
+ new_item = old_item;
+ LLUUID old_parent_id = old_item->getParentUUID();
+ LLUUID new_parent_id = item->getParentUUID();
+ bool update_parent_on_server = false;
+
+ if (new_parent_id.isNull() && !LLApp::isExiting())
+ {
if (old_parent_id.isNull())
{
// Item with null parent will end in random location and then in Lost&Found,
@@ -1438,359 +1438,359 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)
new_parent_id = old_parent_id;
update_parent_on_server = true;
}
- }
-
- if(old_parent_id != new_parent_id)
- {
- // need to update the parent-child tree
- item_array_t* item_array;
- item_array = get_ptr_in_map(mParentChildItemTree, old_parent_id);
- if(item_array)
- {
- vector_replace_with_last(*item_array, old_item);
- }
- item_array = get_ptr_in_map(mParentChildItemTree, new_parent_id);
- if(item_array)
- {
- if (update_parent_on_server)
- {
- LLInventoryModel::LLCategoryUpdate update(new_parent_id, 1);
- gInventory.accountForUpdate(update);
- }
- item_array->push_back(old_item);
- }
- mask |= LLInventoryObserver::STRUCTURE;
- }
- if(old_item->getName() != item->getName())
- {
- mask |= LLInventoryObserver::LABEL;
- }
+ }
+
+ if(old_parent_id != new_parent_id)
+ {
+ // need to update the parent-child tree
+ item_array_t* item_array;
+ item_array = get_ptr_in_map(mParentChildItemTree, old_parent_id);
+ if(item_array)
+ {
+ vector_replace_with_last(*item_array, old_item);
+ }
+ item_array = get_ptr_in_map(mParentChildItemTree, new_parent_id);
+ if(item_array)
+ {
+ if (update_parent_on_server)
+ {
+ LLInventoryModel::LLCategoryUpdate update(new_parent_id, 1);
+ gInventory.accountForUpdate(update);
+ }
+ item_array->push_back(old_item);
+ }
+ mask |= LLInventoryObserver::STRUCTURE;
+ }
+ if(old_item->getName() != item->getName())
+ {
+ mask |= LLInventoryObserver::LABEL;
+ }
if (old_item->getPermissions() != item->getPermissions())
{
mask |= LLInventoryObserver::INTERNAL;
}
- old_item->copyViewerItem(item);
- if (update_parent_on_server)
- {
- // Parent id at server is null, so update server even if item already is in the same folder
- old_item->setParent(new_parent_id);
- new_item->updateParentOnServer(FALSE);
- }
- mask |= LLInventoryObserver::INTERNAL;
- }
- else
- {
- // Simply add this item
- new_item = new LLViewerInventoryItem(item);
- addItem(new_item);
-
- if(item->getParentUUID().isNull())
- {
- const LLUUID category_id = findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(new_item->getType()));
- new_item->setParent(category_id);
- item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, category_id);
- if( item_array )
- {
- LLInventoryModel::LLCategoryUpdate update(category_id, 1);
- gInventory.accountForUpdate(update);
-
- // *FIX: bit of a hack to call update server from here...
- new_item->updateParentOnServer(FALSE);
- item_array->push_back(new_item);
- }
- else
- {
- LL_WARNS(LOG_INV) << "Couldn't find parent-child item tree for " << new_item->getName() << LL_ENDL;
- }
- }
- else
- {
- // *NOTE: The general scheme is that if every byte of the
- // uuid is 0, except for the last one or two,the use the
- // last two bytes of the parent id, and match that up
- // against the type. For now, we're only worried about
- // lost & found.
- LLUUID parent_id = item->getParentUUID();
- if(parent_id == CATEGORIZE_LOST_AND_FOUND_ID)
- {
- parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
- new_item->setParent(parent_id);
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate new_folder(parent_id, 1);
- update.push_back(new_folder);
- accountForUpdate(update);
-
- }
- item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, parent_id);
- if(item_array)
- {
- item_array->push_back(new_item);
- }
- else
- {
- // Whoops! No such parent, make one.
- LL_INFOS(LOG_INV) << "Lost item: " << new_item->getUUID() << " - "
- << new_item->getName() << LL_ENDL;
- parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
- new_item->setParent(parent_id);
- item_array = get_ptr_in_map(mParentChildItemTree, parent_id);
- if(item_array)
- {
- LLInventoryModel::LLCategoryUpdate update(parent_id, 1);
- gInventory.accountForUpdate(update);
- // *FIX: bit of a hack to call update server from
- // here...
- new_item->updateParentOnServer(FALSE);
- item_array->push_back(new_item);
- }
- else
- {
- LL_WARNS(LOG_INV) << "Lost and found Not there!!" << LL_ENDL;
- }
- }
- }
- mask |= LLInventoryObserver::ADD;
- }
- if(new_item->getType() == LLAssetType::AT_CALLINGCARD)
- {
- mask |= LLInventoryObserver::CALLING_CARD;
- // Handle user created calling cards.
- // Target ID is stored in the description field of the card.
- LLUUID id;
- std::string desc = new_item->getDescription();
- BOOL isId = desc.empty() ? FALSE : id.set(desc, FALSE);
- if (isId)
- {
- // Valid UUID; set the item UUID and rename it
- new_item->setCreator(id);
- LLAvatarName av_name;
-
- if (LLAvatarNameCache::get(id, &av_name))
- {
- new_item->rename(av_name.getUserName());
- mask |= LLInventoryObserver::LABEL;
- }
- else
- {
- // Fetch the current name
- LLAvatarNameCache::get(id,
- boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(),
- _1, _2));
- }
-
- }
- }
- else if (new_item->getType() == LLAssetType::AT_GESTURE)
- {
- mask |= LLInventoryObserver::GESTURE;
- }
- addChangedMask(mask, new_item->getUUID());
- return mask;
+ old_item->copyViewerItem(item);
+ if (update_parent_on_server)
+ {
+ // Parent id at server is null, so update server even if item already is in the same folder
+ old_item->setParent(new_parent_id);
+ new_item->updateParentOnServer(FALSE);
+ }
+ mask |= LLInventoryObserver::INTERNAL;
+ }
+ else
+ {
+ // Simply add this item
+ new_item = new LLViewerInventoryItem(item);
+ addItem(new_item);
+
+ if(item->getParentUUID().isNull())
+ {
+ const LLUUID category_id = findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(new_item->getType()));
+ new_item->setParent(category_id);
+ item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, category_id);
+ if( item_array )
+ {
+ LLInventoryModel::LLCategoryUpdate update(category_id, 1);
+ gInventory.accountForUpdate(update);
+
+ // *FIX: bit of a hack to call update server from here...
+ new_item->updateParentOnServer(FALSE);
+ item_array->push_back(new_item);
+ }
+ else
+ {
+ LL_WARNS(LOG_INV) << "Couldn't find parent-child item tree for " << new_item->getName() << LL_ENDL;
+ }
+ }
+ else
+ {
+ // *NOTE: The general scheme is that if every byte of the
+ // uuid is 0, except for the last one or two,the use the
+ // last two bytes of the parent id, and match that up
+ // against the type. For now, we're only worried about
+ // lost & found.
+ LLUUID parent_id = item->getParentUUID();
+ if(parent_id == CATEGORIZE_LOST_AND_FOUND_ID)
+ {
+ parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+ new_item->setParent(parent_id);
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate new_folder(parent_id, 1);
+ update.push_back(new_folder);
+ accountForUpdate(update);
+
+ }
+ item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, parent_id);
+ if(item_array)
+ {
+ item_array->push_back(new_item);
+ }
+ else
+ {
+ // Whoops! No such parent, make one.
+ LL_INFOS(LOG_INV) << "Lost item: " << new_item->getUUID() << " - "
+ << new_item->getName() << LL_ENDL;
+ parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+ new_item->setParent(parent_id);
+ item_array = get_ptr_in_map(mParentChildItemTree, parent_id);
+ if(item_array)
+ {
+ LLInventoryModel::LLCategoryUpdate update(parent_id, 1);
+ gInventory.accountForUpdate(update);
+ // *FIX: bit of a hack to call update server from
+ // here...
+ new_item->updateParentOnServer(FALSE);
+ item_array->push_back(new_item);
+ }
+ else
+ {
+ LL_WARNS(LOG_INV) << "Lost and found Not there!!" << LL_ENDL;
+ }
+ }
+ }
+ mask |= LLInventoryObserver::ADD;
+ }
+ if(new_item->getType() == LLAssetType::AT_CALLINGCARD)
+ {
+ mask |= LLInventoryObserver::CALLING_CARD;
+ // Handle user created calling cards.
+ // Target ID is stored in the description field of the card.
+ LLUUID id;
+ std::string desc = new_item->getDescription();
+ BOOL isId = desc.empty() ? FALSE : id.set(desc, FALSE);
+ if (isId)
+ {
+ // Valid UUID; set the item UUID and rename it
+ new_item->setCreator(id);
+ LLAvatarName av_name;
+
+ if (LLAvatarNameCache::get(id, &av_name))
+ {
+ new_item->rename(av_name.getUserName());
+ mask |= LLInventoryObserver::LABEL;
+ }
+ else
+ {
+ // Fetch the current name
+ LLAvatarNameCache::get(id,
+ boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(),
+ _1, _2));
+ }
+
+ }
+ }
+ else if (new_item->getType() == LLAssetType::AT_GESTURE)
+ {
+ mask |= LLInventoryObserver::GESTURE;
+ }
+ addChangedMask(mask, new_item->getUUID());
+ return mask;
}
LLInventoryModel::cat_array_t* LLInventoryModel::getUnlockedCatArray(const LLUUID& id)
{
- cat_array_t* cat_array = get_ptr_in_map(mParentChildCategoryTree, id);
- if (cat_array)
- {
- llassert_always(mCategoryLock[id] == false);
- }
- return cat_array;
+ cat_array_t* cat_array = get_ptr_in_map(mParentChildCategoryTree, id);
+ if (cat_array)
+ {
+ llassert_always(mCategoryLock[id] == false);
+ }
+ return cat_array;
}
LLInventoryModel::item_array_t* LLInventoryModel::getUnlockedItemArray(const LLUUID& id)
{
- item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
- if (item_array)
- {
- llassert_always(mItemLock[id] == false);
- }
- return item_array;
+ item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
+ if (item_array)
+ {
+ llassert_always(mItemLock[id] == false);
+ }
+ return item_array;
}
// Calling this method with an inventory category will either change
// an existing item with the matching id, or it will add the category.
void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 mask)
{
- if(!cat || cat->getUUID().isNull())
- {
- return;
- }
-
- if(!isInventoryUsable())
- {
- LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL;
- return;
- }
-
- LLPointer<LLViewerInventoryCategory> old_cat = getCategory(cat->getUUID());
- if(old_cat)
- {
- // We already have an old category, modify its values
- LLUUID old_parent_id = old_cat->getParentUUID();
- LLUUID new_parent_id = cat->getParentUUID();
- if(old_parent_id != new_parent_id)
- {
- // need to update the parent-child tree
- cat_array_t* cat_array;
- cat_array = getUnlockedCatArray(old_parent_id);
- if(cat_array)
- {
- vector_replace_with_last(*cat_array, old_cat);
- }
- cat_array = getUnlockedCatArray(new_parent_id);
- if(cat_array)
- {
- cat_array->push_back(old_cat);
- }
- mask |= LLInventoryObserver::STRUCTURE;
+ if(!cat || cat->getUUID().isNull())
+ {
+ return;
+ }
+
+ if(!isInventoryUsable())
+ {
+ LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL;
+ return;
+ }
+
+ LLPointer<LLViewerInventoryCategory> old_cat = getCategory(cat->getUUID());
+ if(old_cat)
+ {
+ // We already have an old category, modify its values
+ LLUUID old_parent_id = old_cat->getParentUUID();
+ LLUUID new_parent_id = cat->getParentUUID();
+ if(old_parent_id != new_parent_id)
+ {
+ // need to update the parent-child tree
+ cat_array_t* cat_array;
+ cat_array = getUnlockedCatArray(old_parent_id);
+ if(cat_array)
+ {
+ vector_replace_with_last(*cat_array, old_cat);
+ }
+ cat_array = getUnlockedCatArray(new_parent_id);
+ if(cat_array)
+ {
+ cat_array->push_back(old_cat);
+ }
+ mask |= LLInventoryObserver::STRUCTURE;
mask |= LLInventoryObserver::INTERNAL;
- }
- if(old_cat->getName() != cat->getName())
- {
- mask |= LLInventoryObserver::LABEL;
- }
+ }
+ if(old_cat->getName() != cat->getName())
+ {
+ mask |= LLInventoryObserver::LABEL;
+ }
// Under marketplace, category labels are quite complex and need extra upate
const LLUUID marketplace_id = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
if (marketplace_id.notNull() && isObjectDescendentOf(cat->getUUID(), marketplace_id))
{
- mask |= LLInventoryObserver::LABEL;
+ mask |= LLInventoryObserver::LABEL;
}
old_cat->copyViewerCategory(cat);
- addChangedMask(mask, cat->getUUID());
- }
- else
- {
- // add this category
- LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat->getOwnerID());
- new_cat->copyViewerCategory(cat);
- addCategory(new_cat);
-
- // make sure this category is correctly referenced by its parent.
- cat_array_t* cat_array;
- cat_array = getUnlockedCatArray(cat->getParentUUID());
- if(cat_array)
- {
- cat_array->push_back(new_cat);
- }
-
- // make space in the tree for this category's children.
- llassert_always(mCategoryLock[new_cat->getUUID()] == false);
- llassert_always(mItemLock[new_cat->getUUID()] == false);
- cat_array_t* catsp = new cat_array_t;
- item_array_t* itemsp = new item_array_t;
- mParentChildCategoryTree[new_cat->getUUID()] = catsp;
- mParentChildItemTree[new_cat->getUUID()] = itemsp;
- mask |= LLInventoryObserver::ADD;
- addChangedMask(mask, cat->getUUID());
- }
+ addChangedMask(mask, cat->getUUID());
+ }
+ else
+ {
+ // add this category
+ LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat->getOwnerID());
+ new_cat->copyViewerCategory(cat);
+ addCategory(new_cat);
+
+ // make sure this category is correctly referenced by its parent.
+ cat_array_t* cat_array;
+ cat_array = getUnlockedCatArray(cat->getParentUUID());
+ if(cat_array)
+ {
+ cat_array->push_back(new_cat);
+ }
+
+ // make space in the tree for this category's children.
+ llassert_always(mCategoryLock[new_cat->getUUID()] == false);
+ llassert_always(mItemLock[new_cat->getUUID()] == false);
+ cat_array_t* catsp = new cat_array_t;
+ item_array_t* itemsp = new item_array_t;
+ mParentChildCategoryTree[new_cat->getUUID()] = catsp;
+ mParentChildItemTree[new_cat->getUUID()] = itemsp;
+ mask |= LLInventoryObserver::ADD;
+ addChangedMask(mask, cat->getUUID());
+ }
}
void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id)
{
- LL_DEBUGS(LOG_INV) << "LLInventoryModel::moveObject()" << LL_ENDL;
- if(!isInventoryUsable())
- {
- LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL;
- return;
- }
-
- if((object_id == cat_id) || !is_in_map(mCategoryMap, cat_id))
- {
- LL_WARNS(LOG_INV) << "Could not move inventory object " << object_id << " to "
- << cat_id << LL_ENDL;
- return;
- }
- LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id);
- if(cat && (cat->getParentUUID() != cat_id))
- {
- LL_DEBUGS(LOG_INV) << "Move category '" << make_path(cat) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL;
- cat_array_t* cat_array;
- cat_array = getUnlockedCatArray(cat->getParentUUID());
- if(cat_array) vector_replace_with_last(*cat_array, cat);
- cat_array = getUnlockedCatArray(cat_id);
- cat->setParent(cat_id);
- if(cat_array) cat_array->push_back(cat);
- addChangedMask(LLInventoryObserver::STRUCTURE, object_id);
- return;
- }
- LLPointer<LLViewerInventoryItem> item = getItem(object_id);
- if(item && (item->getParentUUID() != cat_id))
- {
- LL_DEBUGS(LOG_INV) << "Move item '" << make_path(item) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL;
- item_array_t* item_array;
- item_array = getUnlockedItemArray(item->getParentUUID());
- if(item_array) vector_replace_with_last(*item_array, item);
- item_array = getUnlockedItemArray(cat_id);
- item->setParent(cat_id);
- if(item_array) item_array->push_back(item);
- addChangedMask(LLInventoryObserver::STRUCTURE, object_id);
- return;
- }
+ LL_DEBUGS(LOG_INV) << "LLInventoryModel::moveObject()" << LL_ENDL;
+ if(!isInventoryUsable())
+ {
+ LL_WARNS(LOG_INV) << "Inventory is broken." << LL_ENDL;
+ return;
+ }
+
+ if((object_id == cat_id) || !is_in_map(mCategoryMap, cat_id))
+ {
+ LL_WARNS(LOG_INV) << "Could not move inventory object " << object_id << " to "
+ << cat_id << LL_ENDL;
+ return;
+ }
+ LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id);
+ if(cat && (cat->getParentUUID() != cat_id))
+ {
+ LL_DEBUGS(LOG_INV) << "Move category '" << make_path(cat) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL;
+ cat_array_t* cat_array;
+ cat_array = getUnlockedCatArray(cat->getParentUUID());
+ if(cat_array) vector_replace_with_last(*cat_array, cat);
+ cat_array = getUnlockedCatArray(cat_id);
+ cat->setParent(cat_id);
+ if(cat_array) cat_array->push_back(cat);
+ addChangedMask(LLInventoryObserver::STRUCTURE, object_id);
+ return;
+ }
+ LLPointer<LLViewerInventoryItem> item = getItem(object_id);
+ if(item && (item->getParentUUID() != cat_id))
+ {
+ LL_DEBUGS(LOG_INV) << "Move item '" << make_path(item) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL;
+ item_array_t* item_array;
+ item_array = getUnlockedItemArray(item->getParentUUID());
+ if(item_array) vector_replace_with_last(*item_array, item);
+ item_array = getUnlockedItemArray(cat_id);
+ item->setParent(cat_id);
+ if(item_array) item_array->push_back(item);
+ addChangedMask(LLInventoryObserver::STRUCTURE, object_id);
+ return;
+ }
}
// Migrated from llinventoryfunctions
void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item,
- const LLUUID& new_parent_id,
- BOOL restamp)
+ const LLUUID& new_parent_id,
+ BOOL restamp)
{
- if (item->getParentUUID() == new_parent_id)
- {
- LL_DEBUGS(LOG_INV) << make_info(item) << " is already in folder " << make_inventory_info(new_parent_id) << LL_ENDL;
- }
- else
- {
- LL_INFOS(LOG_INV) << "Move item " << make_info(item)
- << " from " << make_inventory_info(item->getParentUUID())
- << " to " << make_inventory_info(new_parent_id) << LL_ENDL;
-
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
- update.push_back(new_folder);
- accountForUpdate(update);
-
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->setParent(new_parent_id);
- new_item->updateParentOnServer(restamp);
- updateItem(new_item);
- notifyObservers();
- }
+ if (item->getParentUUID() == new_parent_id)
+ {
+ LL_DEBUGS(LOG_INV) << make_info(item) << " is already in folder " << make_inventory_info(new_parent_id) << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS(LOG_INV) << "Move item " << make_info(item)
+ << " from " << make_inventory_info(item->getParentUUID())
+ << " to " << make_inventory_info(new_parent_id) << LL_ENDL;
+
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
+ update.push_back(new_folder);
+ accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->setParent(new_parent_id);
+ new_item->updateParentOnServer(restamp);
+ updateItem(new_item);
+ notifyObservers();
+ }
}
// Migrated from llinventoryfunctions
void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
- const LLUUID& new_parent_id,
- BOOL restamp)
+ const LLUUID& new_parent_id,
+ BOOL restamp)
{
- if (!cat)
- {
- return;
- }
-
- // Can't move a folder into a child of itself.
- if (isObjectDescendentOf(new_parent_id, cat->getUUID()))
- {
- return;
- }
-
- LL_INFOS(LOG_INV) << "Move category " << make_info(cat)
- << " from " << make_inventory_info(cat->getParentUUID())
- << " to " << make_inventory_info(new_parent_id) << LL_ENDL;
-
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
- update.push_back(new_folder);
- accountForUpdate(update);
-
- LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
- new_cat->setParent(new_parent_id);
- new_cat->updateParentOnServer(restamp);
- updateCategory(new_cat);
- notifyObservers();
+ if (!cat)
+ {
+ return;
+ }
+
+ // Can't move a folder into a child of itself.
+ if (isObjectDescendentOf(new_parent_id, cat->getUUID()))
+ {
+ return;
+ }
+
+ LL_INFOS(LOG_INV) << "Move category " << make_info(cat)
+ << " from " << make_inventory_info(cat->getParentUUID())
+ << " to " << make_inventory_info(new_parent_id) << LL_ENDL;
+
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
+ update.push_back(new_folder);
+ accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
+ new_cat->setParent(new_parent_id);
+ new_cat->updateParentOnServer(restamp);
+ updateCategory(new_cat);
+ notifyObservers();
}
void LLInventoryModel::rebuildBrockenLinks()
@@ -1817,262 +1817,262 @@ void LLInventoryModel::rebuildBrockenLinks()
// Does not appear to be used currently.
void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version)
{
- U32 mask = LLInventoryObserver::NONE;
-
- LLPointer<LLViewerInventoryItem> item = gInventory.getItem(item_id);
- LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << LL_ENDL;
- if(item)
- {
- for (LLSD::map_const_iterator it = updates.beginMap();
- it != updates.endMap(); ++it)
- {
- if (it->first == "name")
- {
- LL_INFOS(LOG_INV) << "Updating name from " << item->getName() << " to " << it->second.asString() << LL_ENDL;
- item->rename(it->second.asString());
- mask |= LLInventoryObserver::LABEL;
- }
- else if (it->first == "desc")
- {
- LL_INFOS(LOG_INV) << "Updating description from " << item->getActualDescription()
- << " to " << it->second.asString() << LL_ENDL;
- item->setDescription(it->second.asString());
- }
- else
- {
- LL_ERRS(LOG_INV) << "unhandled updates for field: " << it->first << LL_ENDL;
- }
- }
- mask |= LLInventoryObserver::INTERNAL;
- addChangedMask(mask, item->getUUID());
- if (update_parent_version)
- {
- // Descendent count is unchanged, but folder version incremented.
- LLInventoryModel::LLCategoryUpdate up(item->getParentUUID(), 0);
- accountForUpdate(up);
- }
- notifyObservers(); // do we want to be able to make this optional?
- }
+ U32 mask = LLInventoryObserver::NONE;
+
+ LLPointer<LLViewerInventoryItem> item = gInventory.getItem(item_id);
+ LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (item ? item->getName() : "(NOT FOUND)") << LL_ENDL;
+ if(item)
+ {
+ for (LLSD::map_const_iterator it = updates.beginMap();
+ it != updates.endMap(); ++it)
+ {
+ if (it->first == "name")
+ {
+ LL_INFOS(LOG_INV) << "Updating name from " << item->getName() << " to " << it->second.asString() << LL_ENDL;
+ item->rename(it->second.asString());
+ mask |= LLInventoryObserver::LABEL;
+ }
+ else if (it->first == "desc")
+ {
+ LL_INFOS(LOG_INV) << "Updating description from " << item->getActualDescription()
+ << " to " << it->second.asString() << LL_ENDL;
+ item->setDescription(it->second.asString());
+ }
+ else
+ {
+ LL_ERRS(LOG_INV) << "unhandled updates for field: " << it->first << LL_ENDL;
+ }
+ }
+ mask |= LLInventoryObserver::INTERNAL;
+ addChangedMask(mask, item->getUUID());
+ if (update_parent_version)
+ {
+ // Descendent count is unchanged, but folder version incremented.
+ LLInventoryModel::LLCategoryUpdate up(item->getParentUUID(), 0);
+ accountForUpdate(up);
+ }
+ notifyObservers(); // do we want to be able to make this optional?
+ }
}
// Not used?
void LLInventoryModel::onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates)
{
- U32 mask = LLInventoryObserver::NONE;
-
- LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(cat_id);
- LL_DEBUGS(LOG_INV) << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << LL_ENDL;
- if(cat)
- {
- for (LLSD::map_const_iterator it = updates.beginMap();
- it != updates.endMap(); ++it)
- {
- if (it->first == "name")
- {
- LL_INFOS(LOG_INV) << "Updating name from " << cat->getName() << " to " << it->second.asString() << LL_ENDL;
- cat->rename(it->second.asString());
- mask |= LLInventoryObserver::LABEL;
- }
- else
- {
- LL_ERRS(LOG_INV) << "unhandled updates for field: " << it->first << LL_ENDL;
- }
- }
- mask |= LLInventoryObserver::INTERNAL;
- addChangedMask(mask, cat->getUUID());
- notifyObservers(); // do we want to be able to make this optional?
- }
+ U32 mask = LLInventoryObserver::NONE;
+
+ LLPointer<LLViewerInventoryCategory> cat = gInventory.getCategory(cat_id);
+ LL_DEBUGS(LOG_INV) << "cat_id: [" << cat_id << "] name " << (cat ? cat->getName() : "(NOT FOUND)") << LL_ENDL;
+ if(cat)
+ {
+ for (LLSD::map_const_iterator it = updates.beginMap();
+ it != updates.endMap(); ++it)
+ {
+ if (it->first == "name")
+ {
+ LL_INFOS(LOG_INV) << "Updating name from " << cat->getName() << " to " << it->second.asString() << LL_ENDL;
+ cat->rename(it->second.asString());
+ mask |= LLInventoryObserver::LABEL;
+ }
+ else
+ {
+ LL_ERRS(LOG_INV) << "unhandled updates for field: " << it->first << LL_ENDL;
+ }
+ }
+ mask |= LLInventoryObserver::INTERNAL;
+ addChangedMask(mask, cat->getUUID());
+ notifyObservers(); // do we want to be able to make this optional?
+ }
}
// Update model after descendents have been purged.
void LLInventoryModel::onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links)
{
- LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id);
- if (cat.notNull())
- {
- // do the cache accounting
- S32 descendents = cat->getDescendentCount();
- if(descendents > 0)
- {
- LLInventoryModel::LLCategoryUpdate up(object_id, -descendents);
- accountForUpdate(up);
- }
-
- // we know that descendent count is 0, however since the
- // accounting may actually not do an update, we should force
- // it here.
- cat->setDescendentCount(0);
-
- // unceremoniously remove anything we have locally stored.
- LLInventoryModel::cat_array_t categories;
- LLInventoryModel::item_array_t items;
- collectDescendents(object_id,
- categories,
- items,
- LLInventoryModel::INCLUDE_TRASH);
- S32 count = items.size();
-
- LLUUID uu_id;
- for(S32 i = 0; i < count; ++i)
- {
- uu_id = items.at(i)->getUUID();
-
- // This check prevents the deletion of a previously deleted item.
- // This is necessary because deletion is not done in a hierarchical
- // order. The current item may have been already deleted as a child
- // of its deleted parent.
- if (getItem(uu_id))
- {
- deleteObject(uu_id, fix_broken_links);
- }
- }
-
- count = categories.size();
- // Slightly kludgy way to make sure categories are removed
- // only after their child categories have gone away.
-
- // FIXME: Would probably make more sense to have this whole
- // descendent-clearing thing be a post-order recursive
- // function to get the leaf-up behavior automatically.
- S32 deleted_count;
- S32 total_deleted_count = 0;
- do
- {
- deleted_count = 0;
- for(S32 i = 0; i < count; ++i)
- {
- uu_id = categories.at(i)->getUUID();
- if (getCategory(uu_id))
- {
- cat_array_t* cat_list = getUnlockedCatArray(uu_id);
- if (!cat_list || (cat_list->size() == 0))
- {
- deleteObject(uu_id, fix_broken_links);
- deleted_count++;
- }
- }
- }
- total_deleted_count += deleted_count;
- }
- while (deleted_count > 0);
- if (total_deleted_count != count)
- {
- LL_WARNS(LOG_INV) << "Unexpected count of categories deleted, got "
- << total_deleted_count << " expected " << count << LL_ENDL;
- }
- //gInventory.validate();
- }
+ LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id);
+ if (cat.notNull())
+ {
+ // do the cache accounting
+ S32 descendents = cat->getDescendentCount();
+ if(descendents > 0)
+ {
+ LLInventoryModel::LLCategoryUpdate up(object_id, -descendents);
+ accountForUpdate(up);
+ }
+
+ // we know that descendent count is 0, however since the
+ // accounting may actually not do an update, we should force
+ // it here.
+ cat->setDescendentCount(0);
+
+ // unceremoniously remove anything we have locally stored.
+ LLInventoryModel::cat_array_t categories;
+ LLInventoryModel::item_array_t items;
+ collectDescendents(object_id,
+ categories,
+ items,
+ LLInventoryModel::INCLUDE_TRASH);
+ S32 count = items.size();
+
+ LLUUID uu_id;
+ for(S32 i = 0; i < count; ++i)
+ {
+ uu_id = items.at(i)->getUUID();
+
+ // This check prevents the deletion of a previously deleted item.
+ // This is necessary because deletion is not done in a hierarchical
+ // order. The current item may have been already deleted as a child
+ // of its deleted parent.
+ if (getItem(uu_id))
+ {
+ deleteObject(uu_id, fix_broken_links);
+ }
+ }
+
+ count = categories.size();
+ // Slightly kludgy way to make sure categories are removed
+ // only after their child categories have gone away.
+
+ // FIXME: Would probably make more sense to have this whole
+ // descendent-clearing thing be a post-order recursive
+ // function to get the leaf-up behavior automatically.
+ S32 deleted_count;
+ S32 total_deleted_count = 0;
+ do
+ {
+ deleted_count = 0;
+ for(S32 i = 0; i < count; ++i)
+ {
+ uu_id = categories.at(i)->getUUID();
+ if (getCategory(uu_id))
+ {
+ cat_array_t* cat_list = getUnlockedCatArray(uu_id);
+ if (!cat_list || (cat_list->size() == 0))
+ {
+ deleteObject(uu_id, fix_broken_links);
+ deleted_count++;
+ }
+ }
+ }
+ total_deleted_count += deleted_count;
+ }
+ while (deleted_count > 0);
+ if (total_deleted_count != count)
+ {
+ LL_WARNS(LOG_INV) << "Unexpected count of categories deleted, got "
+ << total_deleted_count << " expected " << count << LL_ENDL;
+ }
+ //gInventory.validate();
+ }
}
// Update model after an item is confirmed as removed from
// server. Works for categories or items.
void LLInventoryModel::onObjectDeletedFromServer(const LLUUID& object_id, bool fix_broken_links, bool update_parent_version, bool do_notify_observers)
{
- LLPointer<LLInventoryObject> obj = getObject(object_id);
- if(obj)
- {
- if (getCategory(object_id))
- {
- // For category, need to delete/update all children first.
- onDescendentsPurgedFromServer(object_id, fix_broken_links);
- }
-
-
- // From item/cat removeFromServer()
- if (update_parent_version)
- {
- LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
- accountForUpdate(up);
- }
-
- // From purgeObject()
- LLViewerInventoryItem *item = getItem(object_id);
- if (item && (item->getType() != LLAssetType::AT_LSL_TEXT))
- {
- LLPreview::hide(object_id, TRUE);
- }
- deleteObject(object_id, fix_broken_links, do_notify_observers);
- }
+ LLPointer<LLInventoryObject> obj = getObject(object_id);
+ if(obj)
+ {
+ if (getCategory(object_id))
+ {
+ // For category, need to delete/update all children first.
+ onDescendentsPurgedFromServer(object_id, fix_broken_links);
+ }
+
+
+ // From item/cat removeFromServer()
+ if (update_parent_version)
+ {
+ LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1);
+ accountForUpdate(up);
+ }
+
+ // From purgeObject()
+ LLViewerInventoryItem *item = getItem(object_id);
+ if (item && (item->getType() != LLAssetType::AT_LSL_TEXT))
+ {
+ LLPreview::hide(object_id, TRUE);
+ }
+ deleteObject(object_id, fix_broken_links, do_notify_observers);
+ }
}
// Delete a particular inventory object by ID.
void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, bool do_notify_observers)
{
- LL_DEBUGS(LOG_INV) << "LLInventoryModel::deleteObject()" << LL_ENDL;
- LLPointer<LLInventoryObject> obj = getObject(id);
- if (!obj)
- {
- LL_WARNS(LOG_INV) << "Deleting non-existent object [ id: " << id << " ] " << LL_ENDL;
- return;
- }
+ LL_DEBUGS(LOG_INV) << "LLInventoryModel::deleteObject()" << LL_ENDL;
+ LLPointer<LLInventoryObject> obj = getObject(id);
+ if (!obj)
+ {
+ LL_WARNS(LOG_INV) << "Deleting non-existent object [ id: " << id << " ] " << LL_ENDL;
+ return;
+ }
//collect the links before removing the item from mItemMap
LLInventoryModel::item_array_t links = collectLinksTo(id);
-
- LL_DEBUGS(LOG_INV) << "Deleting inventory object " << id << LL_ENDL;
- mLastItem = NULL;
- LLUUID parent_id = obj->getParentUUID();
- mCategoryMap.erase(id);
- mItemMap.erase(id);
- //mInventory.erase(id);
- item_array_t* item_list = getUnlockedItemArray(parent_id);
- if(item_list)
- {
- LLPointer<LLViewerInventoryItem> item = (LLViewerInventoryItem*)((LLInventoryObject*)obj);
- vector_replace_with_last(*item_list, item);
- }
- cat_array_t* cat_list = getUnlockedCatArray(parent_id);
- if(cat_list)
- {
- LLPointer<LLViewerInventoryCategory> cat = (LLViewerInventoryCategory*)((LLInventoryObject*)obj);
- vector_replace_with_last(*cat_list, cat);
- }
-
+
+ LL_DEBUGS(LOG_INV) << "Deleting inventory object " << id << LL_ENDL;
+ mLastItem = NULL;
+ LLUUID parent_id = obj->getParentUUID();
+ mCategoryMap.erase(id);
+ mItemMap.erase(id);
+ //mInventory.erase(id);
+ item_array_t* item_list = getUnlockedItemArray(parent_id);
+ if(item_list)
+ {
+ LLPointer<LLViewerInventoryItem> item = (LLViewerInventoryItem*)((LLInventoryObject*)obj);
+ vector_replace_with_last(*item_list, item);
+ }
+ cat_array_t* cat_list = getUnlockedCatArray(parent_id);
+ if(cat_list)
+ {
+ LLPointer<LLViewerInventoryCategory> cat = (LLViewerInventoryCategory*)((LLInventoryObject*)obj);
+ vector_replace_with_last(*cat_list, cat);
+ }
+
// Note : We need to tell the inventory observers that those things are going to be deleted *before* the tree is cleared or they won't know what to delete (in views and view models)
- addChangedMask(LLInventoryObserver::REMOVE, id);
- gInventory.notifyObservers();
-
- item_list = getUnlockedItemArray(id);
- if(item_list)
- {
- if (item_list->size())
- {
- LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child items" << LL_ENDL;
- }
- delete item_list;
- mParentChildItemTree.erase(id);
- }
- cat_list = getUnlockedCatArray(id);
- if(cat_list)
- {
- if (cat_list->size())
- {
- LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child cats" << LL_ENDL;
- }
- delete cat_list;
- mParentChildCategoryTree.erase(id);
- }
- addChangedMask(LLInventoryObserver::REMOVE, id);
-
- bool is_link_type = obj->getIsLinkType();
- if (is_link_type)
- {
- removeBacklinkInfo(obj->getUUID(), obj->getLinkedUUID());
- }
-
- // Can't have links to links, so there's no need for this update
- // if the item removed is a link. Can also skip if source of the
- // update is getting broken link info separately.
- if (fix_broken_links && !is_link_type)
- {
+ addChangedMask(LLInventoryObserver::REMOVE, id);
+ gInventory.notifyObservers();
+
+ item_list = getUnlockedItemArray(id);
+ if(item_list)
+ {
+ if (item_list->size())
+ {
+ LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child items" << LL_ENDL;
+ }
+ delete item_list;
+ mParentChildItemTree.erase(id);
+ }
+ cat_list = getUnlockedCatArray(id);
+ if(cat_list)
+ {
+ if (cat_list->size())
+ {
+ LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child cats" << LL_ENDL;
+ }
+ delete cat_list;
+ mParentChildCategoryTree.erase(id);
+ }
+ addChangedMask(LLInventoryObserver::REMOVE, id);
+
+ bool is_link_type = obj->getIsLinkType();
+ if (is_link_type)
+ {
+ removeBacklinkInfo(obj->getUUID(), obj->getLinkedUUID());
+ }
+
+ // Can't have links to links, so there's no need for this update
+ // if the item removed is a link. Can also skip if source of the
+ // update is getting broken link info separately.
+ if (fix_broken_links && !is_link_type)
+ {
rebuildLinkItems(links);
- }
- obj = nullptr; // delete obj
- if (do_notify_observers)
- {
- notifyObservers();
- }
+ }
+ obj = nullptr; // delete obj
+ if (do_notify_observers)
+ {
+ notifyObservers();
+ }
}
void LLInventoryModel::rebuildLinkItems(LLInventoryModel::item_array_t& items)
@@ -2100,23 +2100,23 @@ void LLInventoryModel::rebuildLinkItems(LLInventoryModel::item_array_t& items)
// remove it.
void LLInventoryModel::addObserver(LLInventoryObserver* observer)
{
- mObservers.insert(observer);
+ mObservers.insert(observer);
}
-
+
void LLInventoryModel::removeObserver(LLInventoryObserver* observer)
{
- mObservers.erase(observer);
+ mObservers.erase(observer);
}
BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const
{
- return mObservers.find(observer) != mObservers.end();
+ return mObservers.find(observer) != mObservers.end();
}
void LLInventoryModel::idleNotifyObservers()
{
- // *FIX: Think I want this conditional or moved elsewhere...
- handleResponses(true);
+ // *FIX: Think I want this conditional or moved elsewhere...
+ handleResponses(true);
if (mLinksRebuildList.size() > 0)
{
@@ -2131,78 +2131,78 @@ void LLInventoryModel::idleNotifyObservers()
mLinksRebuildList.clear();
notifyObservers();
}
-
- if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.size() == 0))
- {
- return;
- }
- notifyObservers();
+
+ if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.size() == 0))
+ {
+ return;
+ }
+ notifyObservers();
}
// Call this method when it's time to update everyone on a new state.
void LLInventoryModel::notifyObservers()
{
- if (mIsNotifyObservers)
- {
- // Within notifyObservers, something called notifyObservers
- // again. This type of recursion is unsafe because it causes items to be
- // processed twice, and this can easily lead to infinite loops.
- LL_WARNS(LOG_INV) << "Call was made to notifyObservers within notifyObservers!" << LL_ENDL;
- return;
- }
-
- mIsNotifyObservers = TRUE;
- for (observer_list_t::iterator iter = mObservers.begin();
- iter != mObservers.end(); )
- {
- LLInventoryObserver* observer = *iter;
- observer->changed(mModifyMask);
-
- // safe way to increment since changed may delete entries! (@!##%@!@&*!)
- iter = mObservers.upper_bound(observer);
- }
-
- // If there were any changes that arrived during notifyObservers,
- // shedule them for next loop
- mModifyMask = mModifyMaskBacklog;
- mChangedItemIDs.clear();
- mChangedItemIDs.insert(mChangedItemIDsBacklog.begin(), mChangedItemIDsBacklog.end());
- mAddedItemIDs.clear();
- mAddedItemIDs.insert(mAddedItemIDsBacklog.begin(), mAddedItemIDsBacklog.end());
-
- mModifyMaskBacklog = LLInventoryObserver::NONE;
- mChangedItemIDsBacklog.clear();
- mAddedItemIDsBacklog.clear();
-
- mIsNotifyObservers = FALSE;
+ if (mIsNotifyObservers)
+ {
+ // Within notifyObservers, something called notifyObservers
+ // again. This type of recursion is unsafe because it causes items to be
+ // processed twice, and this can easily lead to infinite loops.
+ LL_WARNS(LOG_INV) << "Call was made to notifyObservers within notifyObservers!" << LL_ENDL;
+ return;
+ }
+
+ mIsNotifyObservers = TRUE;
+ for (observer_list_t::iterator iter = mObservers.begin();
+ iter != mObservers.end(); )
+ {
+ LLInventoryObserver* observer = *iter;
+ observer->changed(mModifyMask);
+
+ // safe way to increment since changed may delete entries! (@!##%@!@&*!)
+ iter = mObservers.upper_bound(observer);
+ }
+
+ // If there were any changes that arrived during notifyObservers,
+ // shedule them for next loop
+ mModifyMask = mModifyMaskBacklog;
+ mChangedItemIDs.clear();
+ mChangedItemIDs.insert(mChangedItemIDsBacklog.begin(), mChangedItemIDsBacklog.end());
+ mAddedItemIDs.clear();
+ mAddedItemIDs.insert(mAddedItemIDsBacklog.begin(), mAddedItemIDsBacklog.end());
+
+ mModifyMaskBacklog = LLInventoryObserver::NONE;
+ mChangedItemIDsBacklog.clear();
+ mAddedItemIDsBacklog.clear();
+
+ mIsNotifyObservers = FALSE;
}
// store flag for change
// and id of object change applies to
-void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
-{
- if (mIsNotifyObservers)
- {
- // Something marked an item for change within a call to notifyObservers
- // (which is in the process of processing the list of items marked for change).
- // This means the change will have to be processed later.
- // It's preferable for this not to happen, but it's not an issue unless code
- // specifically wants to notifyObservers immediately (changes won't happen untill later)
- LL_WARNS(LOG_INV) << "Adding changed mask within notify observers! Change's processing will be performed on idle." << LL_ENDL;
- LLViewerInventoryItem *item = getItem(referent);
- if (item)
- {
- LL_WARNS(LOG_INV) << "Item " << item->getName() << LL_ENDL;
- }
- else
- {
- LLViewerInventoryCategory *cat = getCategory(referent);
- if (cat)
- {
- LL_WARNS(LOG_INV) << "Category " << cat->getName() << LL_ENDL;
- }
- }
- }
+void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
+{
+ if (mIsNotifyObservers)
+ {
+ // Something marked an item for change within a call to notifyObservers
+ // (which is in the process of processing the list of items marked for change).
+ // This means the change will have to be processed later.
+ // It's preferable for this not to happen, but it's not an issue unless code
+ // specifically wants to notifyObservers immediately (changes won't happen untill later)
+ LL_WARNS(LOG_INV) << "Adding changed mask within notify observers! Change's processing will be performed on idle." << LL_ENDL;
+ LLViewerInventoryItem *item = getItem(referent);
+ if (item)
+ {
+ LL_WARNS(LOG_INV) << "Item " << item->getName() << LL_ENDL;
+ }
+ else
+ {
+ LLViewerInventoryCategory *cat = getCategory(referent);
+ if (cat)
+ {
+ LL_WARNS(LOG_INV) << "Category " << cat->getName() << LL_ENDL;
+ }
+ }
+ }
if (mIsNotifyObservers)
{
@@ -2227,7 +2227,7 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
}
if (needs_update)
- {
+ {
if (mIsNotifyObservers)
{
mChangedItemIDsBacklog.insert(referent);
@@ -2256,42 +2256,42 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
mAddedItemIDs.insert(referent);
}
}
-
- // Update all linked items. Starting with just LABEL because I'm
- // not sure what else might need to be accounted for this.
- if (mask & LLInventoryObserver::LABEL)
- {
- addChangedMaskForLinks(referent, LLInventoryObserver::LABEL);
- }
- }
+
+ // Update all linked items. Starting with just LABEL because I'm
+ // not sure what else might need to be accounted for this.
+ if (mask & LLInventoryObserver::LABEL)
+ {
+ addChangedMaskForLinks(referent, LLInventoryObserver::LABEL);
+ }
+ }
}
bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) const
{
- if(folder_id.isNull())
- {
- LL_WARNS(LOG_INV) << "Calling fetch descendents on NULL folder id!" << LL_ENDL;
- return false;
- }
- LLViewerInventoryCategory* cat = getCategory(folder_id);
- if(!cat)
- {
- LL_WARNS(LOG_INV) << "Asked to fetch descendents of non-existent folder: "
- << folder_id << LL_ENDL;
- return false;
- }
- //S32 known_descendents = 0;
- ///cat_array_t* categories = get_ptr_in_map(mParentChildCategoryTree, folder_id);
- //item_array_t* items = get_ptr_in_map(mParentChildItemTree, folder_id);
- //if(categories)
- //{
- // known_descendents += categories->size();
- //}
- //if(items)
- //{
- // known_descendents += items->size();
- //}
- return cat->fetch();
+ if(folder_id.isNull())
+ {
+ LL_WARNS(LOG_INV) << "Calling fetch descendents on NULL folder id!" << LL_ENDL;
+ return false;
+ }
+ LLViewerInventoryCategory* cat = getCategory(folder_id);
+ if(!cat)
+ {
+ LL_WARNS(LOG_INV) << "Asked to fetch descendents of non-existent folder: "
+ << folder_id << LL_ENDL;
+ return false;
+ }
+ //S32 known_descendents = 0;
+ ///cat_array_t* categories = get_ptr_in_map(mParentChildCategoryTree, folder_id);
+ //item_array_t* items = get_ptr_in_map(mParentChildItemTree, folder_id);
+ //if(categories)
+ //{
+ // known_descendents += categories->size();
+ //}
+ //if(items)
+ //{
+ // known_descendents += items->size();
+ //}
+ return cat->fetch();
}
//static
@@ -2318,138 +2318,138 @@ std::string LLInventoryModel::getInvCacheAddres(const LLUUID& owner_id)
}
void LLInventoryModel::cache(
- const LLUUID& parent_folder_id,
- const LLUUID& agent_id)
+ const LLUUID& parent_folder_id,
+ const LLUUID& agent_id)
{
- LL_DEBUGS(LOG_INV) << "Caching " << parent_folder_id << " for " << agent_id
- << LL_ENDL;
- LLViewerInventoryCategory* root_cat = getCategory(parent_folder_id);
- if(!root_cat) return;
- cat_array_t categories;
- categories.push_back(root_cat);
- item_array_t items;
-
- LLCanCache can_cache(this);
- can_cache(root_cat, NULL);
- collectDescendentsIf(
- parent_folder_id,
- categories,
- items,
- INCLUDE_TRASH,
- can_cache);
+ LL_DEBUGS(LOG_INV) << "Caching " << parent_folder_id << " for " << agent_id
+ << LL_ENDL;
+ LLViewerInventoryCategory* root_cat = getCategory(parent_folder_id);
+ if(!root_cat) return;
+ cat_array_t categories;
+ categories.push_back(root_cat);
+ item_array_t items;
+
+ LLCanCache can_cache(this);
+ can_cache(root_cat, NULL);
+ collectDescendentsIf(
+ parent_folder_id,
+ categories,
+ items,
+ INCLUDE_TRASH,
+ can_cache);
// Use temporary file to avoid potential conflicts with other
// instances (even a 'read only' instance unzips into a file)
std::string temp_file = gDirUtilp->getTempFilename();
- saveToFile(temp_file, categories, items);
+ saveToFile(temp_file, categories, items);
std::string gzip_filename = getInvCacheAddres(agent_id);
- gzip_filename.append(".gz");
- if(gzip_file(temp_file, gzip_filename))
- {
- LL_DEBUGS(LOG_INV) << "Successfully compressed " << temp_file << " to " << gzip_filename << LL_ENDL;
- LLFile::remove(temp_file);
- }
- else
- {
- LL_WARNS(LOG_INV) << "Unable to compress " << temp_file << " into " << gzip_filename << LL_ENDL;
- }
+ gzip_filename.append(".gz");
+ if(gzip_file(temp_file, gzip_filename))
+ {
+ LL_DEBUGS(LOG_INV) << "Successfully compressed " << temp_file << " to " << gzip_filename << LL_ENDL;
+ LLFile::remove(temp_file);
+ }
+ else
+ {
+ LL_WARNS(LOG_INV) << "Unable to compress " << temp_file << " into " << gzip_filename << LL_ENDL;
+ }
}
void LLInventoryModel::addCategory(LLViewerInventoryCategory* category)
{
- //LL_INFOS(LOG_INV) << "LLInventoryModel::addCategory()" << LL_ENDL;
- if(category)
- {
- // We aren't displaying the Meshes folder
- if (category->mPreferredType == LLFolderType::FT_MESH)
- {
- return;
- }
-
- // try to localize default names first. See EXT-8319, EXT-7051.
- category->localizeName();
-
- // Insert category uniquely into the map
- mCategoryMap[category->getUUID()] = category; // LLPointer will deref and delete the old one
- //mInventory[category->getUUID()] = category;
- }
+ //LL_INFOS(LOG_INV) << "LLInventoryModel::addCategory()" << LL_ENDL;
+ if(category)
+ {
+ // We aren't displaying the Meshes folder
+ if (category->mPreferredType == LLFolderType::FT_MESH)
+ {
+ return;
+ }
+
+ // try to localize default names first. See EXT-8319, EXT-7051.
+ category->localizeName();
+
+ // Insert category uniquely into the map
+ mCategoryMap[category->getUUID()] = category; // LLPointer will deref and delete the old one
+ //mInventory[category->getUUID()] = category;
+ }
}
bool LLInventoryModel::hasBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id) const
{
- std::pair <backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range;
- range = mBacklinkMMap.equal_range(target_id);
- for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
- {
- if (it->second == link_id)
- {
- return true;
- }
- }
- return false;
+ std::pair <backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range;
+ range = mBacklinkMMap.equal_range(target_id);
+ for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
+ {
+ if (it->second == link_id)
+ {
+ return true;
+ }
+ }
+ return false;
}
void LLInventoryModel::addBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id)
{
- if (!hasBacklinkInfo(link_id, target_id))
- {
- mBacklinkMMap.insert(std::make_pair(target_id, link_id));
- }
+ if (!hasBacklinkInfo(link_id, target_id))
+ {
+ mBacklinkMMap.insert(std::make_pair(target_id, link_id));
+ }
}
void LLInventoryModel::removeBacklinkInfo(const LLUUID& link_id, const LLUUID& target_id)
{
- std::pair <backlink_mmap_t::iterator, backlink_mmap_t::iterator> range;
- range = mBacklinkMMap.equal_range(target_id);
- for (backlink_mmap_t::iterator it = range.first; it != range.second; )
- {
- if (it->second == link_id)
- {
- backlink_mmap_t::iterator delete_it = it; // iterator will be invalidated by erase.
- ++it;
- mBacklinkMMap.erase(delete_it);
- }
- else
- {
- ++it;
- }
- }
+ std::pair <backlink_mmap_t::iterator, backlink_mmap_t::iterator> range;
+ range = mBacklinkMMap.equal_range(target_id);
+ for (backlink_mmap_t::iterator it = range.first; it != range.second; )
+ {
+ if (it->second == link_id)
+ {
+ backlink_mmap_t::iterator delete_it = it; // iterator will be invalidated by erase.
+ ++it;
+ mBacklinkMMap.erase(delete_it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
}
void LLInventoryModel::addItem(LLViewerInventoryItem* item)
{
- llassert(item);
- if(item)
- {
- if (item->getType() <= LLAssetType::AT_NONE)
- {
- LL_WARNS(LOG_INV) << "Got bad asset type for item [ name: " << item->getName()
- << " type: " << item->getType()
- << " inv-type: " << item->getInventoryType() << " ], ignoring." << LL_ENDL;
- return;
- }
-
- if (LLAssetType::lookup(item->getType()) == LLAssetType::BADLOOKUP)
- {
- if (item->getType() >= LLAssetType::AT_COUNT)
- {
- // Not yet supported.
- LL_DEBUGS(LOG_INV) << "Got unknown asset type for item [ name: " << item->getName()
- << " type: " << item->getType()
- << " inv-type: " << item->getInventoryType() << " ]." << LL_ENDL;
- }
- else
- {
- LL_WARNS(LOG_INV) << "Got unknown asset type for item [ name: " << item->getName()
- << " type: " << item->getType()
- << " inv-type: " << item->getInventoryType() << " ]." << LL_ENDL;
- }
- }
-
- // This condition means that we tried to add a link without the baseobj being in memory.
- // The item will show up as a broken link.
- if (item->getIsBrokenLink())
- {
+ llassert(item);
+ if(item)
+ {
+ if (item->getType() <= LLAssetType::AT_NONE)
+ {
+ LL_WARNS(LOG_INV) << "Got bad asset type for item [ name: " << item->getName()
+ << " type: " << item->getType()
+ << " inv-type: " << item->getInventoryType() << " ], ignoring." << LL_ENDL;
+ return;
+ }
+
+ if (LLAssetType::lookup(item->getType()) == LLAssetType::BADLOOKUP)
+ {
+ if (item->getType() >= LLAssetType::AT_COUNT)
+ {
+ // Not yet supported.
+ LL_DEBUGS(LOG_INV) << "Got unknown asset type for item [ name: " << item->getName()
+ << " type: " << item->getType()
+ << " inv-type: " << item->getInventoryType() << " ]." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS(LOG_INV) << "Got unknown asset type for item [ name: " << item->getName()
+ << " type: " << item->getType()
+ << " inv-type: " << item->getInventoryType() << " ]." << LL_ENDL;
+ }
+ }
+
+ // This condition means that we tried to add a link without the baseobj being in memory.
+ // The item will show up as a broken link.
+ if (item->getIsBrokenLink())
+ {
if (item->getAssetUUID().notNull()
&& LLInventoryModelBackgroundFetch::getInstance()->folderFetchActive())
{
@@ -2485,7 +2485,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
<< " itemID: " << item->getUUID()
<< " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << LL_ENDL;
}
- }
+ }
if (!mPossiblyBrockenLinks.empty())
{
// check if we are waiting for this item
@@ -2496,705 +2496,705 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
mPossiblyBrockenLinks.erase(iter);
}
}
- if (item->getIsLinkType())
- {
- // Add back-link from linked-to UUID.
- const LLUUID& link_id = item->getUUID();
- const LLUUID& target_id = item->getLinkedUUID();
- addBacklinkInfo(link_id, target_id);
- }
- mItemMap[item->getUUID()] = item;
- }
+ if (item->getIsLinkType())
+ {
+ // Add back-link from linked-to UUID.
+ const LLUUID& link_id = item->getUUID();
+ const LLUUID& target_id = item->getLinkedUUID();
+ addBacklinkInfo(link_id, target_id);
+ }
+ mItemMap[item->getUUID()] = item;
+ }
}
// Empty the entire contents
void LLInventoryModel::empty()
{
-// LL_INFOS(LOG_INV) << "LLInventoryModel::empty()" << LL_ENDL;
- std::for_each(
- mParentChildCategoryTree.begin(),
- mParentChildCategoryTree.end(),
- DeletePairedPointer());
- mParentChildCategoryTree.clear();
- std::for_each(
- mParentChildItemTree.begin(),
- mParentChildItemTree.end(),
- DeletePairedPointer());
- mParentChildItemTree.clear();
- mBacklinkMMap.clear(); // forget all backlink information.
- mCategoryMap.clear(); // remove all references (should delete entries)
- mItemMap.clear(); // remove all references (should delete entries)
- mLastItem = NULL;
- //mInventory.clear();
+// LL_INFOS(LOG_INV) << "LLInventoryModel::empty()" << LL_ENDL;
+ std::for_each(
+ mParentChildCategoryTree.begin(),
+ mParentChildCategoryTree.end(),
+ DeletePairedPointer());
+ mParentChildCategoryTree.clear();
+ std::for_each(
+ mParentChildItemTree.begin(),
+ mParentChildItemTree.end(),
+ DeletePairedPointer());
+ mParentChildItemTree.clear();
+ mBacklinkMMap.clear(); // forget all backlink information.
+ mCategoryMap.clear(); // remove all references (should delete entries)
+ mItemMap.clear(); // remove all references (should delete entries)
+ mLastItem = NULL;
+ //mInventory.clear();
}
void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const
{
- LLViewerInventoryCategory* cat = getCategory(update.mCategoryID);
- if(cat)
- {
- S32 version = cat->getVersion();
- if(version != LLViewerInventoryCategory::VERSION_UNKNOWN)
- {
- S32 descendents_server = cat->getDescendentCount();
- S32 descendents_actual = cat->getViewerDescendentCount();
- if(descendents_server == descendents_actual)
- {
- descendents_actual += update.mDescendentDelta;
- cat->setDescendentCount(descendents_actual);
- cat->setVersion(++version);
- LL_DEBUGS(LOG_INV) << "accounted: '" << cat->getName() << "' "
- << version << " with " << descendents_actual
- << " descendents." << LL_ENDL;
- }
- else
- {
- // Error condition, this means that the category did not register that
- // it got new descendents (perhaps because it is still being loaded)
- // which means its descendent count will be wrong.
- LL_WARNS(LOG_INV) << "Accounting failed for '" << cat->getName() << "' version:"
- << version << " due to mismatched descendent count: server == "
- << descendents_server << ", viewer == " << descendents_actual << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS(LOG_INV) << "Accounting failed for '" << cat->getName() << "' version: unknown ("
- << version << ")" << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS(LOG_INV) << "No category found for update " << update.mCategoryID << LL_ENDL;
- }
+ LLViewerInventoryCategory* cat = getCategory(update.mCategoryID);
+ if(cat)
+ {
+ S32 version = cat->getVersion();
+ if(version != LLViewerInventoryCategory::VERSION_UNKNOWN)
+ {
+ S32 descendents_server = cat->getDescendentCount();
+ S32 descendents_actual = cat->getViewerDescendentCount();
+ if(descendents_server == descendents_actual)
+ {
+ descendents_actual += update.mDescendentDelta;
+ cat->setDescendentCount(descendents_actual);
+ cat->setVersion(++version);
+ LL_DEBUGS(LOG_INV) << "accounted: '" << cat->getName() << "' "
+ << version << " with " << descendents_actual
+ << " descendents." << LL_ENDL;
+ }
+ else
+ {
+ // Error condition, this means that the category did not register that
+ // it got new descendents (perhaps because it is still being loaded)
+ // which means its descendent count will be wrong.
+ LL_WARNS(LOG_INV) << "Accounting failed for '" << cat->getName() << "' version:"
+ << version << " due to mismatched descendent count: server == "
+ << descendents_server << ", viewer == " << descendents_actual << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS(LOG_INV) << "Accounting failed for '" << cat->getName() << "' version: unknown ("
+ << version << ")" << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS(LOG_INV) << "No category found for update " << update.mCategoryID << LL_ENDL;
+ }
}
void LLInventoryModel::accountForUpdate(
- const LLInventoryModel::update_list_t& update)
+ const LLInventoryModel::update_list_t& update)
{
- update_list_t::const_iterator it = update.begin();
- update_list_t::const_iterator end = update.end();
- for(; it != end; ++it)
- {
- accountForUpdate(*it);
- }
+ update_list_t::const_iterator it = update.begin();
+ update_list_t::const_iterator end = update.end();
+ for(; it != end; ++it)
+ {
+ accountForUpdate(*it);
+ }
}
void LLInventoryModel::accountForUpdate(
- const LLInventoryModel::update_map_t& update)
+ const LLInventoryModel::update_map_t& update)
{
- LLCategoryUpdate up;
- update_map_t::const_iterator it = update.begin();
- update_map_t::const_iterator end = update.end();
- for(; it != end; ++it)
- {
- up.mCategoryID = (*it).first;
- up.mDescendentDelta = (*it).second.mValue;
- accountForUpdate(up);
- }
+ LLCategoryUpdate up;
+ update_map_t::const_iterator it = update.begin();
+ update_map_t::const_iterator end = update.end();
+ for(; it != end; ++it)
+ {
+ up.mCategoryID = (*it).first;
+ up.mDescendentDelta = (*it).second.mValue;
+ accountForUpdate(up);
+ }
}
LLInventoryModel::EHasChildren LLInventoryModel::categoryHasChildren(
- const LLUUID& cat_id) const
+ const LLUUID& cat_id) const
{
- LLViewerInventoryCategory* cat = getCategory(cat_id);
- if(!cat) return CHILDREN_NO;
- if(cat->getDescendentCount() > 0)
- {
- return CHILDREN_YES;
- }
- if(cat->getDescendentCount() == 0)
- {
- return CHILDREN_NO;
- }
- if((cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
- || (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN))
- {
- return CHILDREN_MAYBE;
- }
-
- // Shouldn't have to run this, but who knows.
- parent_cat_map_t::const_iterator cat_it = mParentChildCategoryTree.find(cat->getUUID());
- if (cat_it != mParentChildCategoryTree.end() && cat_it->second->size() > 0)
- {
- return CHILDREN_YES;
- }
- parent_item_map_t::const_iterator item_it = mParentChildItemTree.find(cat->getUUID());
- if (item_it != mParentChildItemTree.end() && item_it->second->size() > 0)
- {
- return CHILDREN_YES;
- }
-
- return CHILDREN_NO;
+ LLViewerInventoryCategory* cat = getCategory(cat_id);
+ if(!cat) return CHILDREN_NO;
+ if(cat->getDescendentCount() > 0)
+ {
+ return CHILDREN_YES;
+ }
+ if(cat->getDescendentCount() == 0)
+ {
+ return CHILDREN_NO;
+ }
+ if((cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
+ || (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN))
+ {
+ return CHILDREN_MAYBE;
+ }
+
+ // Shouldn't have to run this, but who knows.
+ parent_cat_map_t::const_iterator cat_it = mParentChildCategoryTree.find(cat->getUUID());
+ if (cat_it != mParentChildCategoryTree.end() && cat_it->second->size() > 0)
+ {
+ return CHILDREN_YES;
+ }
+ parent_item_map_t::const_iterator item_it = mParentChildItemTree.find(cat->getUUID());
+ if (item_it != mParentChildItemTree.end() && item_it->second->size() > 0)
+ {
+ return CHILDREN_YES;
+ }
+
+ return CHILDREN_NO;
}
bool LLInventoryModel::isCategoryComplete(const LLUUID& cat_id) const
{
- LLViewerInventoryCategory* cat = getCategory(cat_id);
- if(cat && (cat->getVersion()!=LLViewerInventoryCategory::VERSION_UNKNOWN))
- {
- S32 descendents_server = cat->getDescendentCount();
- S32 descendents_actual = cat->getViewerDescendentCount();
- if(descendents_server == descendents_actual)
- {
- return true;
- }
- }
- return false;
+ LLViewerInventoryCategory* cat = getCategory(cat_id);
+ if(cat && (cat->getVersion()!=LLViewerInventoryCategory::VERSION_UNKNOWN))
+ {
+ S32 descendents_server = cat->getDescendentCount();
+ S32 descendents_actual = cat->getViewerDescendentCount();
+ if(descendents_server == descendents_actual)
+ {
+ return true;
+ }
+ }
+ return false;
}
bool LLInventoryModel::loadSkeleton(
- const LLSD& options,
- const LLUUID& owner_id)
+ const LLSD& options,
+ const LLUUID& owner_id)
{
LL_PROFILE_ZONE_SCOPED;
- LL_DEBUGS(LOG_INV) << "importing inventory skeleton for " << owner_id << LL_ENDL;
-
- typedef std::set<LLPointer<LLViewerInventoryCategory>, InventoryIDPtrLess> cat_set_t;
- cat_set_t temp_cats;
- bool rv = true;
-
- for(LLSD::array_const_iterator it = options.beginArray(),
- end = options.endArray(); it != end; ++it)
- {
- LLSD name = (*it)["name"];
- LLSD folder_id = (*it)["folder_id"];
- LLSD parent_id = (*it)["parent_id"];
- LLSD version = (*it)["version"];
- if(name.isDefined()
- && folder_id.isDefined()
- && parent_id.isDefined()
- && version.isDefined()
- && folder_id.asUUID().notNull() // if an id is null, it locks the viewer.
- )
- {
- LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id);
- cat->rename(name.asString());
- cat->setUUID(folder_id.asUUID());
- cat->setParent(parent_id.asUUID());
-
- LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
- LLSD type_default = (*it)["type_default"];
- if(type_default.isDefined())
+ LL_DEBUGS(LOG_INV) << "importing inventory skeleton for " << owner_id << LL_ENDL;
+
+ typedef std::set<LLPointer<LLViewerInventoryCategory>, InventoryIDPtrLess> cat_set_t;
+ cat_set_t temp_cats;
+ bool rv = true;
+
+ for(LLSD::array_const_iterator it = options.beginArray(),
+ end = options.endArray(); it != end; ++it)
+ {
+ LLSD name = (*it)["name"];
+ LLSD folder_id = (*it)["folder_id"];
+ LLSD parent_id = (*it)["parent_id"];
+ LLSD version = (*it)["version"];
+ if(name.isDefined()
+ && folder_id.isDefined()
+ && parent_id.isDefined()
+ && version.isDefined()
+ && folder_id.asUUID().notNull() // if an id is null, it locks the viewer.
+ )
+ {
+ LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id);
+ cat->rename(name.asString());
+ cat->setUUID(folder_id.asUUID());
+ cat->setParent(parent_id.asUUID());
+
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ LLSD type_default = (*it)["type_default"];
+ if(type_default.isDefined())
{
- preferred_type = (LLFolderType::EType)type_default.asInteger();
+ preferred_type = (LLFolderType::EType)type_default.asInteger();
}
cat->setPreferredType(preferred_type);
- cat->setVersion(version.asInteger());
+ cat->setVersion(version.asInteger());
temp_cats.insert(cat);
- }
- else
- {
- LL_WARNS(LOG_INV) << "Unable to import near " << name.asString() << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS(LOG_INV) << "Unable to import near " << name.asString() << LL_ENDL;
rv = false;
- }
- }
-
- S32 cached_category_count = 0;
- S32 cached_item_count = 0;
- if(!temp_cats.empty())
- {
- update_map_t child_counts;
- cat_array_t categories;
- item_array_t items;
- changed_items_t categories_to_update;
- item_array_t possible_broken_links;
- cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
- std::string inventory_filename = getInvCacheAddres(owner_id);
- const S32 NO_VERSION = LLViewerInventoryCategory::VERSION_UNKNOWN;
- std::string gzip_filename(inventory_filename);
- gzip_filename.append(".gz");
- LLFILE* fp = LLFile::fopen(gzip_filename, "rb");
- bool remove_inventory_file = false;
- if(fp)
- {
- fclose(fp);
- fp = NULL;
- if(gunzip_file(gzip_filename, inventory_filename))
- {
- // we only want to remove the inventory file if it was
- // gzipped before we loaded, and we successfully
- // gunziped it.
- remove_inventory_file = true;
- }
- else
- {
- LL_INFOS(LOG_INV) << "Unable to gunzip " << gzip_filename << LL_ENDL;
- }
- }
- bool is_cache_obsolete = false;
- if (loadFromFile(inventory_filename, categories, items, categories_to_update, is_cache_obsolete))
- {
- // We were able to find a cache of files. So, use what we
- // found to generate a set of categories we should add. We
- // will go through each category loaded and if the version
- // does not match, invalidate the version.
- S32 count = categories.size();
- cat_set_t::iterator not_cached = temp_cats.end();
- std::set<LLUUID> cached_ids;
- for(S32 i = 0; i < count; ++i)
- {
- LLViewerInventoryCategory* cat = categories[i];
- cat_set_t::iterator cit = temp_cats.find(cat);
- if (cit == temp_cats.end())
- {
- continue; // cache corruption?? not sure why this happens -SJB
- }
- LLViewerInventoryCategory* tcat = *cit;
-
- if (categories_to_update.find(tcat->getUUID()) != categories_to_update.end())
- {
- tcat->setVersion(NO_VERSION);
- LL_WARNS() << "folder to update: " << tcat->getName() << LL_ENDL;
- }
-
- // we can safely ignore anything loaded from file, but
- // not sent down in the skeleton. Must have been removed from inventory.
- if (cit == not_cached)
- {
- continue;
- }
- else if (cat->getVersion() != tcat->getVersion())
- {
- // if the cached version does not match the server version,
- // throw away the version we have so we can fetch the
- // correct contents the next time the viewer opens the folder.
- tcat->setVersion(NO_VERSION);
- }
- else
- {
- cached_ids.insert(tcat->getUUID());
+ }
+ }
+
+ S32 cached_category_count = 0;
+ S32 cached_item_count = 0;
+ if(!temp_cats.empty())
+ {
+ update_map_t child_counts;
+ cat_array_t categories;
+ item_array_t items;
+ changed_items_t categories_to_update;
+ item_array_t possible_broken_links;
+ cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
+ std::string inventory_filename = getInvCacheAddres(owner_id);
+ const S32 NO_VERSION = LLViewerInventoryCategory::VERSION_UNKNOWN;
+ std::string gzip_filename(inventory_filename);
+ gzip_filename.append(".gz");
+ LLFILE* fp = LLFile::fopen(gzip_filename, "rb");
+ bool remove_inventory_file = false;
+ if(fp)
+ {
+ fclose(fp);
+ fp = NULL;
+ if(gunzip_file(gzip_filename, inventory_filename))
+ {
+ // we only want to remove the inventory file if it was
+ // gzipped before we loaded, and we successfully
+ // gunziped it.
+ remove_inventory_file = true;
+ }
+ else
+ {
+ LL_INFOS(LOG_INV) << "Unable to gunzip " << gzip_filename << LL_ENDL;
+ }
+ }
+ bool is_cache_obsolete = false;
+ if (loadFromFile(inventory_filename, categories, items, categories_to_update, is_cache_obsolete))
+ {
+ // We were able to find a cache of files. So, use what we
+ // found to generate a set of categories we should add. We
+ // will go through each category loaded and if the version
+ // does not match, invalidate the version.
+ S32 count = categories.size();
+ cat_set_t::iterator not_cached = temp_cats.end();
+ std::set<LLUUID> cached_ids;
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLViewerInventoryCategory* cat = categories[i];
+ cat_set_t::iterator cit = temp_cats.find(cat);
+ if (cit == temp_cats.end())
+ {
+ continue; // cache corruption?? not sure why this happens -SJB
+ }
+ LLViewerInventoryCategory* tcat = *cit;
+
+ if (categories_to_update.find(tcat->getUUID()) != categories_to_update.end())
+ {
+ tcat->setVersion(NO_VERSION);
+ LL_WARNS() << "folder to update: " << tcat->getName() << LL_ENDL;
+ }
+
+ // we can safely ignore anything loaded from file, but
+ // not sent down in the skeleton. Must have been removed from inventory.
+ if (cit == not_cached)
+ {
+ continue;
+ }
+ else if (cat->getVersion() != tcat->getVersion())
+ {
+ // if the cached version does not match the server version,
+ // throw away the version we have so we can fetch the
+ // correct contents the next time the viewer opens the folder.
+ tcat->setVersion(NO_VERSION);
+ }
+ else
+ {
+ cached_ids.insert(tcat->getUUID());
// At the moment download does not provide a thumbnail
// uuid, use the one from cache
tcat->setThumbnailUUID(cat->getThumbnailUUID());
- }
- }
-
- // go ahead and add the cats returned during the download
- std::set<LLUUID>::const_iterator not_cached_id = cached_ids.end();
- cached_category_count = cached_ids.size();
- for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
- {
- if(cached_ids.find((*it)->getUUID()) == not_cached_id)
- {
- // this check is performed so that we do not
- // mark new folders in the skeleton (and not in cache)
- // as being cached.
- LLViewerInventoryCategory *llvic = (*it);
- llvic->setVersion(NO_VERSION);
- }
- addCategory(*it);
- ++child_counts[(*it)->getParentUUID()];
- }
-
- // Add all the items loaded which are parented to a
- // category with a correctly cached parent
- S32 bad_link_count = 0;
- S32 good_link_count = 0;
- S32 recovered_link_count = 0;
- cat_map_t::iterator unparented = mCategoryMap.end();
- for(item_array_t::const_iterator item_iter = items.begin();
- item_iter != items.end();
- ++item_iter)
- {
- LLViewerInventoryItem *item = (*item_iter).get();
- const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
-
- if(cit != unparented)
- {
- const LLViewerInventoryCategory* cat = cit->second.get();
- if(cat->getVersion() != NO_VERSION)
- {
- // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
- if (item->getIsBrokenLink())
- {
- //bad_link_count++;
- LL_DEBUGS(LOG_INV) << "Attempted to add cached link item without baseobj present ( name: "
- << item->getName() << " itemID: " << item->getUUID()
- << " assetID: " << item->getAssetUUID()
- << " ). Ignoring and invalidating " << cat->getName() << " . " << LL_ENDL;
- possible_broken_links.push_back(item);
- continue;
- }
- else if (item->getIsLinkType())
- {
- good_link_count++;
- }
- addItem(item);
- cached_item_count += 1;
- ++child_counts[cat->getUUID()];
- }
- }
- }
- if (possible_broken_links.size() > 0)
- {
- for(item_array_t::const_iterator item_iter = possible_broken_links.begin();
- item_iter != possible_broken_links.end();
- ++item_iter)
- {
- LLViewerInventoryItem *item = (*item_iter).get();
- const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
- const LLViewerInventoryCategory* cat = cit->second.get();
- if (item->getIsBrokenLink())
- {
- bad_link_count++;
- invalid_categories.insert(cit->second);
- //LL_INFOS(LOG_INV) << "link still broken: " << item->getName() << " in folder " << cat->getName() << LL_ENDL;
- }
- else
- {
- // was marked as broken because of loading order, its actually fine to load
- addItem(item);
- cached_item_count += 1;
- ++child_counts[cat->getUUID()];
- recovered_link_count++;
- }
- }
-
- LL_DEBUGS(LOG_INV) << "Attempted to add " << bad_link_count
- << " cached link items without baseobj present. "
- << good_link_count << " link items were successfully added. "
- << recovered_link_count << " links added in recovery. "
- << "The corresponding categories were invalidated." << LL_ENDL;
- }
-
- }
- else
- {
- // go ahead and add everything after stripping the version
- // information.
- for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
- {
- LLViewerInventoryCategory *llvic = (*it);
- llvic->setVersion(NO_VERSION);
- addCategory(*it);
- }
- }
-
- // Invalidate all categories that failed fetching descendents for whatever
- // reason (e.g. one of the descendents was a broken link).
- for (cat_set_t::iterator invalid_cat_it = invalid_categories.begin();
- invalid_cat_it != invalid_categories.end();
- invalid_cat_it++)
- {
- LLViewerInventoryCategory* cat = (*invalid_cat_it).get();
- cat->setVersion(NO_VERSION);
- LL_DEBUGS(LOG_INV) << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << LL_ENDL;
- }
- if (invalid_categories.size() > 0)
- {
- LL_DEBUGS(LOG_INV) << "Invalidated " << invalid_categories.size() << " categories due to invalid descendents cache" << LL_ENDL;
- }
-
- // At this point, we need to set the known descendents for each
- // category which successfully cached so that we do not
- // needlessly fetch descendents for categories which we have.
- update_map_t::const_iterator no_child_counts = child_counts.end();
- for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
- {
- LLViewerInventoryCategory* cat = (*it).get();
- if(cat->getVersion() != NO_VERSION)
- {
- update_map_t::const_iterator the_count = child_counts.find(cat->getUUID());
- if(the_count != no_child_counts)
- {
- const S32 num_descendents = (*the_count).second.mValue;
- cat->setDescendentCount(num_descendents);
- }
- else
- {
- cat->setDescendentCount(0);
- }
- }
- }
-
- if(remove_inventory_file)
- {
- // clean up the gunzipped file.
- LLFile::remove(inventory_filename);
- }
- if(is_cache_obsolete)
- {
- // If out of date, remove the gzipped file too.
- LL_WARNS(LOG_INV) << "Inv cache out of date, removing" << LL_ENDL;
- LLFile::remove(gzip_filename);
- }
- categories.clear(); // will unref and delete entries
- }
-
- LL_INFOS(LOG_INV) << "Successfully loaded " << cached_category_count
- << " categories and " << cached_item_count << " items from cache."
- << LL_ENDL;
-
- return rv;
+ }
+ }
+
+ // go ahead and add the cats returned during the download
+ std::set<LLUUID>::const_iterator not_cached_id = cached_ids.end();
+ cached_category_count = cached_ids.size();
+ for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
+ {
+ if(cached_ids.find((*it)->getUUID()) == not_cached_id)
+ {
+ // this check is performed so that we do not
+ // mark new folders in the skeleton (and not in cache)
+ // as being cached.
+ LLViewerInventoryCategory *llvic = (*it);
+ llvic->setVersion(NO_VERSION);
+ }
+ addCategory(*it);
+ ++child_counts[(*it)->getParentUUID()];
+ }
+
+ // Add all the items loaded which are parented to a
+ // category with a correctly cached parent
+ S32 bad_link_count = 0;
+ S32 good_link_count = 0;
+ S32 recovered_link_count = 0;
+ cat_map_t::iterator unparented = mCategoryMap.end();
+ for(item_array_t::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
+ {
+ LLViewerInventoryItem *item = (*item_iter).get();
+ const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
+
+ if(cit != unparented)
+ {
+ const LLViewerInventoryCategory* cat = cit->second.get();
+ if(cat->getVersion() != NO_VERSION)
+ {
+ // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
+ if (item->getIsBrokenLink())
+ {
+ //bad_link_count++;
+ LL_DEBUGS(LOG_INV) << "Attempted to add cached link item without baseobj present ( name: "
+ << item->getName() << " itemID: " << item->getUUID()
+ << " assetID: " << item->getAssetUUID()
+ << " ). Ignoring and invalidating " << cat->getName() << " . " << LL_ENDL;
+ possible_broken_links.push_back(item);
+ continue;
+ }
+ else if (item->getIsLinkType())
+ {
+ good_link_count++;
+ }
+ addItem(item);
+ cached_item_count += 1;
+ ++child_counts[cat->getUUID()];
+ }
+ }
+ }
+ if (possible_broken_links.size() > 0)
+ {
+ for(item_array_t::const_iterator item_iter = possible_broken_links.begin();
+ item_iter != possible_broken_links.end();
+ ++item_iter)
+ {
+ LLViewerInventoryItem *item = (*item_iter).get();
+ const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
+ const LLViewerInventoryCategory* cat = cit->second.get();
+ if (item->getIsBrokenLink())
+ {
+ bad_link_count++;
+ invalid_categories.insert(cit->second);
+ //LL_INFOS(LOG_INV) << "link still broken: " << item->getName() << " in folder " << cat->getName() << LL_ENDL;
+ }
+ else
+ {
+ // was marked as broken because of loading order, its actually fine to load
+ addItem(item);
+ cached_item_count += 1;
+ ++child_counts[cat->getUUID()];
+ recovered_link_count++;
+ }
+ }
+
+ LL_DEBUGS(LOG_INV) << "Attempted to add " << bad_link_count
+ << " cached link items without baseobj present. "
+ << good_link_count << " link items were successfully added. "
+ << recovered_link_count << " links added in recovery. "
+ << "The corresponding categories were invalidated." << LL_ENDL;
+ }
+
+ }
+ else
+ {
+ // go ahead and add everything after stripping the version
+ // information.
+ for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
+ {
+ LLViewerInventoryCategory *llvic = (*it);
+ llvic->setVersion(NO_VERSION);
+ addCategory(*it);
+ }
+ }
+
+ // Invalidate all categories that failed fetching descendents for whatever
+ // reason (e.g. one of the descendents was a broken link).
+ for (cat_set_t::iterator invalid_cat_it = invalid_categories.begin();
+ invalid_cat_it != invalid_categories.end();
+ invalid_cat_it++)
+ {
+ LLViewerInventoryCategory* cat = (*invalid_cat_it).get();
+ cat->setVersion(NO_VERSION);
+ LL_DEBUGS(LOG_INV) << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << LL_ENDL;
+ }
+ if (invalid_categories.size() > 0)
+ {
+ LL_DEBUGS(LOG_INV) << "Invalidated " << invalid_categories.size() << " categories due to invalid descendents cache" << LL_ENDL;
+ }
+
+ // At this point, we need to set the known descendents for each
+ // category which successfully cached so that we do not
+ // needlessly fetch descendents for categories which we have.
+ update_map_t::const_iterator no_child_counts = child_counts.end();
+ for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
+ {
+ LLViewerInventoryCategory* cat = (*it).get();
+ if(cat->getVersion() != NO_VERSION)
+ {
+ update_map_t::const_iterator the_count = child_counts.find(cat->getUUID());
+ if(the_count != no_child_counts)
+ {
+ const S32 num_descendents = (*the_count).second.mValue;
+ cat->setDescendentCount(num_descendents);
+ }
+ else
+ {
+ cat->setDescendentCount(0);
+ }
+ }
+ }
+
+ if(remove_inventory_file)
+ {
+ // clean up the gunzipped file.
+ LLFile::remove(inventory_filename);
+ }
+ if(is_cache_obsolete)
+ {
+ // If out of date, remove the gzipped file too.
+ LL_WARNS(LOG_INV) << "Inv cache out of date, removing" << LL_ENDL;
+ LLFile::remove(gzip_filename);
+ }
+ categories.clear(); // will unref and delete entries
+ }
+
+ LL_INFOS(LOG_INV) << "Successfully loaded " << cached_category_count
+ << " categories and " << cached_item_count << " items from cache."
+ << LL_ENDL;
+
+ return rv;
}
// This is a brute force method to rebuild the entire parent-child
// relations. The overall operation has O(NlogN) performance, which
-// should be sufficient for our needs.
+// should be sufficient for our needs.
void LLInventoryModel::buildParentChildMap()
{
- LL_INFOS(LOG_INV) << "LLInventoryModel::buildParentChildMap()" << LL_ENDL;
-
- // *NOTE: I am skipping the logic around folder version
- // synchronization here because it seems if a folder is lost, we
- // might actually want to invalidate it at that point - not
- // attempt to cache. More time & thought is necessary.
-
- // First the categories. We'll copy all of the categories into a
- // temporary container to iterate over (oh for real iterators.)
- // While we're at it, we'll allocate the arrays in the trees.
- cat_array_t cats;
- cat_array_t* catsp;
- item_array_t* itemsp;
-
- for(cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
- {
- LLViewerInventoryCategory* cat = cit->second;
- cats.push_back(cat);
- if (mParentChildCategoryTree.count(cat->getUUID()) == 0)
- {
- llassert_always(mCategoryLock[cat->getUUID()] == false);
- catsp = new cat_array_t;
- mParentChildCategoryTree[cat->getUUID()] = catsp;
- }
- if (mParentChildItemTree.count(cat->getUUID()) == 0)
- {
- llassert_always(mItemLock[cat->getUUID()] == false);
- itemsp = new item_array_t;
- mParentChildItemTree[cat->getUUID()] = itemsp;
- }
- }
-
- // Insert a special parent for the root - so that lookups on
- // LLUUID::null as the parent work correctly. This is kind of a
- // blatent wastes of space since we allocate a block of memory for
- // the array, but whatever - it's not that much space.
- if (mParentChildCategoryTree.count(LLUUID::null) == 0)
- {
- catsp = new cat_array_t;
- mParentChildCategoryTree[LLUUID::null] = catsp;
- }
-
- // Now we have a structure with all of the categories that we can
- // iterate over and insert into the correct place in the child
- // category tree.
- S32 count = cats.size();
- S32 i;
- S32 lost = 0;
- cat_array_t lost_cats;
- for(i = 0; i < count; ++i)
- {
- LLViewerInventoryCategory* cat = cats.at(i);
- catsp = getUnlockedCatArray(cat->getParentUUID());
- if(catsp &&
- // Only the two root folders should be children of null.
- // Others should go to lost & found.
- (cat->getParentUUID().notNull() ||
- cat->getPreferredType() == LLFolderType::FT_ROOT_INVENTORY ))
- {
- catsp->push_back(cat);
- }
- else
- {
- // *NOTE: This process could be a lot more efficient if we
- // used the new MoveInventoryFolder message, but we would
- // have to continue to do the update & build here. So, to
- // implement it, we would need a set or map of uuid pairs
- // which would be (folder_id, new_parent_id) to be sent up
- // to the server.
- LL_INFOS(LOG_INV) << "Lost category: " << cat->getUUID() << " - "
- << cat->getName() << LL_ENDL;
- ++lost;
- lost_cats.push_back(cat);
- }
- }
- if(lost)
- {
- LL_WARNS(LOG_INV) << "Found " << lost << " lost categories." << LL_ENDL;
- }
-
- // Do moves in a separate pass to make sure we've properly filed
- // the FT_LOST_AND_FOUND category before we try to find its UUID.
- for(i = 0; i<lost_cats.size(); ++i)
- {
- LLViewerInventoryCategory *cat = lost_cats.at(i);
-
- // plop it into the lost & found.
- LLFolderType::EType pref = cat->getPreferredType();
- if(LLFolderType::FT_NONE == pref)
- {
- cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
- }
- else if(LLFolderType::FT_ROOT_INVENTORY == pref)
- {
- // it's the root
- cat->setParent(LLUUID::null);
- }
- else
- {
- // it's a protected folder.
- cat->setParent(gInventory.getRootFolderID());
- }
- // FIXME note that updateServer() fails with protected
- // types, so this will not work as intended in that case.
- // UpdateServer uses AIS, AIS cat move is not implemented yet
- // cat->updateServer(TRUE);
-
- // MoveInventoryFolder message, intentionally per item
- cat->updateParentOnServer(FALSE);
- catsp = getUnlockedCatArray(cat->getParentUUID());
- if(catsp)
- {
- catsp->push_back(cat);
- }
- else
- {
- LL_WARNS(LOG_INV) << "Lost and found Not there!!" << LL_ENDL;
- }
- }
-
- const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) != LLUUID::null);
- sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin();
-
-
- // Now the items. We allocated in the last step, so now all we
- // have to do is iterate over the items and put them in the right
- // place.
- item_array_t items;
- if(!mItemMap.empty())
- {
- LLPointer<LLViewerInventoryItem> item;
- for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
- {
- item = (*iit).second;
- items.push_back(item);
- }
- }
- count = items.size();
- lost = 0;
- uuid_vec_t lost_item_ids;
- for(i = 0; i < count; ++i)
- {
- LLPointer<LLViewerInventoryItem> item;
- item = items.at(i);
- itemsp = getUnlockedItemArray(item->getParentUUID());
- if(itemsp)
- {
- itemsp->push_back(item);
- }
- else
- {
- LL_INFOS(LOG_INV) << "Lost item: " << item->getUUID() << " - "
- << item->getName() << LL_ENDL;
- ++lost;
- // plop it into the lost & found.
- //
- item->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
- // move it later using a special message to move items. If
- // we update server here, the client might crash.
- //item->updateServer();
- lost_item_ids.push_back(item->getUUID());
- itemsp = getUnlockedItemArray(item->getParentUUID());
- if(itemsp)
- {
- itemsp->push_back(item);
- }
- else
- {
- LL_WARNS(LOG_INV) << "Lost and found Not there!!" << LL_ENDL;
- }
- }
- }
- if(lost)
- {
- LL_WARNS(LOG_INV) << "Found " << lost << " lost items." << LL_ENDL;
- LLMessageSystem* msg = gMessageSystem;
- BOOL start_new_message = TRUE;
- const LLUUID lnf = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
- for(uuid_vec_t::iterator it = lost_item_ids.begin() ; it < lost_item_ids.end(); ++it)
- {
- if(start_new_message)
- {
- start_new_message = FALSE;
- msg->newMessageFast(_PREHASH_MoveInventoryItem);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addBOOLFast(_PREHASH_Stamp, FALSE);
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_ItemID, (*it));
- msg->addUUIDFast(_PREHASH_FolderID, lnf);
- msg->addString("NewName", NULL);
- if(msg->isSendFull(NULL))
- {
- start_new_message = TRUE;
- gAgent.sendReliableMessage();
- }
- }
- if(!start_new_message)
- {
- gAgent.sendReliableMessage();
- }
- }
-
- const LLUUID &agent_inv_root_id = gInventory.getRootFolderID();
- if (agent_inv_root_id.notNull())
- {
- cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);
- if(catsp)
- {
- // *HACK - fix root inventory folder
- // some accounts has pbroken inventory root folders
-
- std::string name = "My Inventory";
- for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(),
- it_end = mParentChildCategoryTree.end(); it != it_end; ++it)
- {
- cat_array_t* cat_array = it->second;
- for (cat_array_t::const_iterator cat_it = cat_array->begin(),
- cat_it_end = cat_array->end(); cat_it != cat_it_end; ++cat_it)
- {
- LLPointer<LLViewerInventoryCategory> category = *cat_it;
-
- if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY)
- continue;
- if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) )
- {
- if(category->getUUID()!=mRootFolderID)
- {
- LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID);
- new_inv_root_folder_id = category->getUUID();
- }
- }
- }
- }
-
- LLPointer<LLInventoryValidationInfo> validation_info = validate();
- if (validation_info->mFatalErrorCount > 0)
- {
- // Fatal inventory error. Will not be able to engage in many inventory operations.
- // This should be followed by an error dialog leading to logout.
- LL_WARNS("Inventory") << "Fatal errors were found in validate(): unable to initialize inventory! "
- << "Will not be able to do normal inventory operations in this session."
- << LL_ENDL;
- mIsAgentInvUsable = false;
- }
- else
- {
- mIsAgentInvUsable = true;
- }
- validation_info->mInitialized = true;
- mValidationInfo = validation_info;
-
- // notifyObservers() has been moved to
- // llstartup/idle_startup() after this func completes.
- // Allows some system categories to be created before
- // observers start firing.
- }
- }
+ LL_INFOS(LOG_INV) << "LLInventoryModel::buildParentChildMap()" << LL_ENDL;
+
+ // *NOTE: I am skipping the logic around folder version
+ // synchronization here because it seems if a folder is lost, we
+ // might actually want to invalidate it at that point - not
+ // attempt to cache. More time & thought is necessary.
+
+ // First the categories. We'll copy all of the categories into a
+ // temporary container to iterate over (oh for real iterators.)
+ // While we're at it, we'll allocate the arrays in the trees.
+ cat_array_t cats;
+ cat_array_t* catsp;
+ item_array_t* itemsp;
+
+ for(cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
+ {
+ LLViewerInventoryCategory* cat = cit->second;
+ cats.push_back(cat);
+ if (mParentChildCategoryTree.count(cat->getUUID()) == 0)
+ {
+ llassert_always(mCategoryLock[cat->getUUID()] == false);
+ catsp = new cat_array_t;
+ mParentChildCategoryTree[cat->getUUID()] = catsp;
+ }
+ if (mParentChildItemTree.count(cat->getUUID()) == 0)
+ {
+ llassert_always(mItemLock[cat->getUUID()] == false);
+ itemsp = new item_array_t;
+ mParentChildItemTree[cat->getUUID()] = itemsp;
+ }
+ }
+
+ // Insert a special parent for the root - so that lookups on
+ // LLUUID::null as the parent work correctly. This is kind of a
+ // blatent wastes of space since we allocate a block of memory for
+ // the array, but whatever - it's not that much space.
+ if (mParentChildCategoryTree.count(LLUUID::null) == 0)
+ {
+ catsp = new cat_array_t;
+ mParentChildCategoryTree[LLUUID::null] = catsp;
+ }
+
+ // Now we have a structure with all of the categories that we can
+ // iterate over and insert into the correct place in the child
+ // category tree.
+ S32 count = cats.size();
+ S32 i;
+ S32 lost = 0;
+ cat_array_t lost_cats;
+ for(i = 0; i < count; ++i)
+ {
+ LLViewerInventoryCategory* cat = cats.at(i);
+ catsp = getUnlockedCatArray(cat->getParentUUID());
+ if(catsp &&
+ // Only the two root folders should be children of null.
+ // Others should go to lost & found.
+ (cat->getParentUUID().notNull() ||
+ cat->getPreferredType() == LLFolderType::FT_ROOT_INVENTORY ))
+ {
+ catsp->push_back(cat);
+ }
+ else
+ {
+ // *NOTE: This process could be a lot more efficient if we
+ // used the new MoveInventoryFolder message, but we would
+ // have to continue to do the update & build here. So, to
+ // implement it, we would need a set or map of uuid pairs
+ // which would be (folder_id, new_parent_id) to be sent up
+ // to the server.
+ LL_INFOS(LOG_INV) << "Lost category: " << cat->getUUID() << " - "
+ << cat->getName() << LL_ENDL;
+ ++lost;
+ lost_cats.push_back(cat);
+ }
+ }
+ if(lost)
+ {
+ LL_WARNS(LOG_INV) << "Found " << lost << " lost categories." << LL_ENDL;
+ }
+
+ // Do moves in a separate pass to make sure we've properly filed
+ // the FT_LOST_AND_FOUND category before we try to find its UUID.
+ for(i = 0; i<lost_cats.size(); ++i)
+ {
+ LLViewerInventoryCategory *cat = lost_cats.at(i);
+
+ // plop it into the lost & found.
+ LLFolderType::EType pref = cat->getPreferredType();
+ if(LLFolderType::FT_NONE == pref)
+ {
+ cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
+ }
+ else if(LLFolderType::FT_ROOT_INVENTORY == pref)
+ {
+ // it's the root
+ cat->setParent(LLUUID::null);
+ }
+ else
+ {
+ // it's a protected folder.
+ cat->setParent(gInventory.getRootFolderID());
+ }
+ // FIXME note that updateServer() fails with protected
+ // types, so this will not work as intended in that case.
+ // UpdateServer uses AIS, AIS cat move is not implemented yet
+ // cat->updateServer(TRUE);
+
+ // MoveInventoryFolder message, intentionally per item
+ cat->updateParentOnServer(FALSE);
+ catsp = getUnlockedCatArray(cat->getParentUUID());
+ if(catsp)
+ {
+ catsp->push_back(cat);
+ }
+ else
+ {
+ LL_WARNS(LOG_INV) << "Lost and found Not there!!" << LL_ENDL;
+ }
+ }
+
+ const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) != LLUUID::null);
+ sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin();
+
+
+ // Now the items. We allocated in the last step, so now all we
+ // have to do is iterate over the items and put them in the right
+ // place.
+ item_array_t items;
+ if(!mItemMap.empty())
+ {
+ LLPointer<LLViewerInventoryItem> item;
+ for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
+ {
+ item = (*iit).second;
+ items.push_back(item);
+ }
+ }
+ count = items.size();
+ lost = 0;
+ uuid_vec_t lost_item_ids;
+ for(i = 0; i < count; ++i)
+ {
+ LLPointer<LLViewerInventoryItem> item;
+ item = items.at(i);
+ itemsp = getUnlockedItemArray(item->getParentUUID());
+ if(itemsp)
+ {
+ itemsp->push_back(item);
+ }
+ else
+ {
+ LL_INFOS(LOG_INV) << "Lost item: " << item->getUUID() << " - "
+ << item->getName() << LL_ENDL;
+ ++lost;
+ // plop it into the lost & found.
+ //
+ item->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
+ // move it later using a special message to move items. If
+ // we update server here, the client might crash.
+ //item->updateServer();
+ lost_item_ids.push_back(item->getUUID());
+ itemsp = getUnlockedItemArray(item->getParentUUID());
+ if(itemsp)
+ {
+ itemsp->push_back(item);
+ }
+ else
+ {
+ LL_WARNS(LOG_INV) << "Lost and found Not there!!" << LL_ENDL;
+ }
+ }
+ }
+ if(lost)
+ {
+ LL_WARNS(LOG_INV) << "Found " << lost << " lost items." << LL_ENDL;
+ LLMessageSystem* msg = gMessageSystem;
+ BOOL start_new_message = TRUE;
+ const LLUUID lnf = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+ for(uuid_vec_t::iterator it = lost_item_ids.begin() ; it < lost_item_ids.end(); ++it)
+ {
+ if(start_new_message)
+ {
+ start_new_message = FALSE;
+ msg->newMessageFast(_PREHASH_MoveInventoryItem);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addBOOLFast(_PREHASH_Stamp, FALSE);
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_ItemID, (*it));
+ msg->addUUIDFast(_PREHASH_FolderID, lnf);
+ msg->addString("NewName", NULL);
+ if(msg->isSendFull(NULL))
+ {
+ start_new_message = TRUE;
+ gAgent.sendReliableMessage();
+ }
+ }
+ if(!start_new_message)
+ {
+ gAgent.sendReliableMessage();
+ }
+ }
+
+ const LLUUID &agent_inv_root_id = gInventory.getRootFolderID();
+ if (agent_inv_root_id.notNull())
+ {
+ cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);
+ if(catsp)
+ {
+ // *HACK - fix root inventory folder
+ // some accounts has pbroken inventory root folders
+
+ std::string name = "My Inventory";
+ for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(),
+ it_end = mParentChildCategoryTree.end(); it != it_end; ++it)
+ {
+ cat_array_t* cat_array = it->second;
+ for (cat_array_t::const_iterator cat_it = cat_array->begin(),
+ cat_it_end = cat_array->end(); cat_it != cat_it_end; ++cat_it)
+ {
+ LLPointer<LLViewerInventoryCategory> category = *cat_it;
+
+ if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY)
+ continue;
+ if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) )
+ {
+ if(category->getUUID()!=mRootFolderID)
+ {
+ LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID);
+ new_inv_root_folder_id = category->getUUID();
+ }
+ }
+ }
+ }
+
+ LLPointer<LLInventoryValidationInfo> validation_info = validate();
+ if (validation_info->mFatalErrorCount > 0)
+ {
+ // Fatal inventory error. Will not be able to engage in many inventory operations.
+ // This should be followed by an error dialog leading to logout.
+ LL_WARNS("Inventory") << "Fatal errors were found in validate(): unable to initialize inventory! "
+ << "Will not be able to do normal inventory operations in this session."
+ << LL_ENDL;
+ mIsAgentInvUsable = false;
+ }
+ else
+ {
+ mIsAgentInvUsable = true;
+ }
+ validation_info->mInitialized = true;
+ mValidationInfo = validation_info;
+
+ // notifyObservers() has been moved to
+ // llstartup/idle_startup() after this func completes.
+ // Allows some system categories to be created before
+ // observers start firing.
+ }
+ }
}
// Would normally do this at construction but that's too early
@@ -3202,22 +3202,22 @@ void LLInventoryModel::buildParentChildMap()
// call set things up.
void LLInventoryModel::initHttpRequest()
{
- if (! mHttpRequestFG)
- {
- // Haven't initialized, get to it
- LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
-
- mHttpRequestFG = new LLCore::HttpRequest;
- mHttpRequestBG = new LLCore::HttpRequest;
- mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
- mHttpOptions->setTransferTimeout(300);
- mHttpOptions->setUseRetryAfter(true);
- // mHttpOptions->setTrace(2); // Do tracing of requests
+ if (! mHttpRequestFG)
+ {
+ // Haven't initialized, get to it
+ LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
+
+ mHttpRequestFG = new LLCore::HttpRequest;
+ mHttpRequestBG = new LLCore::HttpRequest;
+ mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+ mHttpOptions->setTransferTimeout(300);
+ mHttpOptions->setUseRetryAfter(true);
+ // mHttpOptions->setTrace(2); // Do tracing of requests
mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
- mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
- mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
- mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_INVENTORY);
- }
+ mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
+ mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
+ mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_INVENTORY);
+ }
if (!gGenericDispatcher.isHandlerPresent("BulkUpdateInventory"))
{
@@ -3227,49 +3227,49 @@ void LLInventoryModel::initHttpRequest()
void LLInventoryModel::handleResponses(bool foreground)
{
- if (foreground && mHttpRequestFG)
- {
- mHttpRequestFG->update(0);
- }
- else if (! foreground && mHttpRequestBG)
- {
- mHttpRequestBG->update(50000L);
- }
+ if (foreground && mHttpRequestFG)
+ {
+ mHttpRequestFG->update(0);
+ }
+ else if (! foreground && mHttpRequestBG)
+ {
+ mHttpRequestBG->update(50000L);
+ }
}
LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground,
- const std::string & url,
- const LLSD & body,
- const LLCore::HttpHandler::ptr_t &handler,
- const char * const message)
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpHandler::ptr_t &handler,
+ const char * const message)
{
- if (! mHttpRequestFG)
- {
- // We do the initialization late and lazily as this class is
- // statically-constructed and not all the bits are ready at
- // that time.
- initHttpRequest();
- }
-
- LLCore::HttpRequest * request(foreground ? mHttpRequestFG : mHttpRequestBG);
- LLCore::HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
-
- handle = LLCoreHttpUtil::requestPostWithLLSD(request,
- mHttpPolicyClass,
- url,
- body,
- mHttpOptions,
- mHttpHeaders,
- handler);
- if (LLCORE_HTTP_HANDLE_INVALID == handle)
- {
- LLCore::HttpStatus status(request->getStatus());
- LL_WARNS(LOG_INV) << "HTTP POST request failed for " << message
- << ", Status: " << status.toTerseString()
- << " Reason: '" << status.toString() << "'"
- << LL_ENDL;
- }
- return handle;
+ if (! mHttpRequestFG)
+ {
+ // We do the initialization late and lazily as this class is
+ // statically-constructed and not all the bits are ready at
+ // that time.
+ initHttpRequest();
+ }
+
+ LLCore::HttpRequest * request(foreground ? mHttpRequestFG : mHttpRequestBG);
+ LLCore::HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+ handle = LLCoreHttpUtil::requestPostWithLLSD(request,
+ mHttpPolicyClass,
+ url,
+ body,
+ mHttpOptions,
+ mHttpHeaders,
+ handler);
+ if (LLCORE_HTTP_HANDLE_INVALID == handle)
+ {
+ LLCore::HttpStatus status(request->getStatus());
+ LL_WARNS(LOG_INV) << "HTTP POST request failed for " << message
+ << ", Status: " << status.toTerseString()
+ << " Reason: '" << status.toString() << "'"
+ << LL_ENDL;
+ }
+ return handle;
}
void LLInventoryModel::createCommonSystemCategories()
@@ -3277,12 +3277,12 @@ void LLInventoryModel::createCommonSystemCategories()
//amount of System Folder we should wait for
sPendingSystemFolders = 9;
- gInventory.ensureCategoryForTypeExists(LLFolderType::FT_TRASH);
- gInventory.ensureCategoryForTypeExists(LLFolderType::FT_FAVORITE);
- gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CALLINGCARD);
- gInventory.ensureCategoryForTypeExists(LLFolderType::FT_MY_OUTFITS);
- gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT);
- gInventory.ensureCategoryForTypeExists(LLFolderType::FT_LANDMARK); // folder should exist before user tries to 'landmark this'
+ gInventory.ensureCategoryForTypeExists(LLFolderType::FT_TRASH);
+ gInventory.ensureCategoryForTypeExists(LLFolderType::FT_FAVORITE);
+ gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CALLINGCARD);
+ gInventory.ensureCategoryForTypeExists(LLFolderType::FT_MY_OUTFITS);
+ gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT);
+ gInventory.ensureCategoryForTypeExists(LLFolderType::FT_LANDMARK); // folder should exist before user tries to 'landmark this'
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_SETTINGS);
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_MATERIAL); // probably should be server created
gInventory.ensureCategoryForTypeExists(LLFolderType::FT_INBOX);
@@ -3290,154 +3290,154 @@ void LLInventoryModel::createCommonSystemCategories()
struct LLUUIDAndName
{
- LLUUIDAndName() {}
- LLUUIDAndName(const LLUUID& id, const std::string& name);
- bool operator==(const LLUUIDAndName& rhs) const;
- bool operator<(const LLUUIDAndName& rhs) const;
- bool operator>(const LLUUIDAndName& rhs) const;
-
- LLUUID mID;
- std::string mName;
+ LLUUIDAndName() {}
+ LLUUIDAndName(const LLUUID& id, const std::string& name);
+ bool operator==(const LLUUIDAndName& rhs) const;
+ bool operator<(const LLUUIDAndName& rhs) const;
+ bool operator>(const LLUUIDAndName& rhs) const;
+
+ LLUUID mID;
+ std::string mName;
};
LLUUIDAndName::LLUUIDAndName(const LLUUID& id, const std::string& name) :
- mID(id), mName(name)
+ mID(id), mName(name)
{
}
bool LLUUIDAndName::operator==(const LLUUIDAndName& rhs) const
{
- return ((mID == rhs.mID) && (mName == rhs.mName));
+ return ((mID == rhs.mID) && (mName == rhs.mName));
}
bool LLUUIDAndName::operator<(const LLUUIDAndName& rhs) const
{
- return (mID < rhs.mID);
+ return (mID < rhs.mID);
}
bool LLUUIDAndName::operator>(const LLUUIDAndName& rhs) const
{
- return (mID > rhs.mID);
+ return (mID > rhs.mID);
}
// static
bool LLInventoryModel::loadFromFile(const std::string& filename,
- LLInventoryModel::cat_array_t& categories,
- LLInventoryModel::item_array_t& items,
- LLInventoryModel::changed_items_t& cats_to_update,
- bool &is_cache_obsolete)
+ LLInventoryModel::cat_array_t& categories,
+ LLInventoryModel::item_array_t& items,
+ LLInventoryModel::changed_items_t& cats_to_update,
+ bool &is_cache_obsolete)
{
LL_PROFILE_ZONE_NAMED("inventory load from file");
- if(filename.empty())
- {
- LL_ERRS(LOG_INV) << "filename is Null!" << LL_ENDL;
- return false;
- }
- LL_INFOS(LOG_INV) << "loading inventory from: (" << filename << ")" << LL_ENDL;
-
- llifstream file(filename.c_str());
-
- if (!file.is_open())
- {
- LL_INFOS(LOG_INV) << "unable to load inventory from: " << filename << LL_ENDL;
- return false;
- }
-
- is_cache_obsolete = true; // Obsolete until proven current
-
- //U64 lines_count = 0U;
- std::string line;
- LLPointer<LLSDParser> parser = new LLSDNotationParser();
- while (std::getline(file, line))
- {
- LLSD s_item;
- std::istringstream iss(line);
- if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
- {
- LL_WARNS(LOG_INV)<< "Parsing inventory cache failed" << LL_ENDL;
- break;
- }
-
- if (s_item.has("inv_cache_version"))
- {
- S32 version = s_item["inv_cache_version"].asInteger();
- if (version == sCurrentInvCacheVersion)
- {
- // Cache is up to date
- is_cache_obsolete = false;
- continue;
- }
- else
- {
- LL_WARNS(LOG_INV)<< "Inventory cache is out of date" << LL_ENDL;
- break;
- }
- }
- else if (s_item.has("cat_id"))
- {
- if (is_cache_obsolete)
- break;
-
- LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null);
- if(inv_cat->importLLSD(s_item))
- {
- categories.push_back(inv_cat);
- }
- }
- else if (s_item.has("item_id"))
- {
- if (is_cache_obsolete)
- break;
-
- LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem;
- if( inv_item->fromLLSD(s_item) )
- {
- if(inv_item->getUUID().isNull())
- {
- LL_DEBUGS(LOG_INV) << "Ignoring inventory with null item id: "
- << inv_item->getName() << LL_ENDL;
- }
- else
- {
- if (inv_item->getType() == LLAssetType::AT_UNKNOWN)
- {
- cats_to_update.insert(inv_item->getParentUUID());
- }
- else
- {
- items.push_back(inv_item);
- }
- }
- }
- }
+ if(filename.empty())
+ {
+ LL_ERRS(LOG_INV) << "filename is Null!" << LL_ENDL;
+ return false;
+ }
+ LL_INFOS(LOG_INV) << "loading inventory from: (" << filename << ")" << LL_ENDL;
+
+ llifstream file(filename.c_str());
+
+ if (!file.is_open())
+ {
+ LL_INFOS(LOG_INV) << "unable to load inventory from: " << filename << LL_ENDL;
+ return false;
+ }
+
+ is_cache_obsolete = true; // Obsolete until proven current
+
+ //U64 lines_count = 0U;
+ std::string line;
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+ while (std::getline(file, line))
+ {
+ LLSD s_item;
+ std::istringstream iss(line);
+ if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ LL_WARNS(LOG_INV)<< "Parsing inventory cache failed" << LL_ENDL;
+ break;
+ }
+
+ if (s_item.has("inv_cache_version"))
+ {
+ S32 version = s_item["inv_cache_version"].asInteger();
+ if (version == sCurrentInvCacheVersion)
+ {
+ // Cache is up to date
+ is_cache_obsolete = false;
+ continue;
+ }
+ else
+ {
+ LL_WARNS(LOG_INV)<< "Inventory cache is out of date" << LL_ENDL;
+ break;
+ }
+ }
+ else if (s_item.has("cat_id"))
+ {
+ if (is_cache_obsolete)
+ break;
+
+ LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null);
+ if(inv_cat->importLLSD(s_item))
+ {
+ categories.push_back(inv_cat);
+ }
+ }
+ else if (s_item.has("item_id"))
+ {
+ if (is_cache_obsolete)
+ break;
+
+ LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem;
+ if( inv_item->fromLLSD(s_item) )
+ {
+ if(inv_item->getUUID().isNull())
+ {
+ LL_DEBUGS(LOG_INV) << "Ignoring inventory with null item id: "
+ << inv_item->getName() << LL_ENDL;
+ }
+ else
+ {
+ if (inv_item->getType() == LLAssetType::AT_UNKNOWN)
+ {
+ cats_to_update.insert(inv_item->getParentUUID());
+ }
+ else
+ {
+ items.push_back(inv_item);
+ }
+ }
+ }
+ }
// TODO(brad) - figure out how to reenable this without breaking everything else
-// static constexpr U64 BATCH_SIZE = 512U;
-// if ((++lines_count % BATCH_SIZE) == 0)
-// {
-// // SL-19968 - make sure message system code gets a chance to run every so often
-// pump_idle_startup_network();
-// }
- }
+// static constexpr U64 BATCH_SIZE = 512U;
+// if ((++lines_count % BATCH_SIZE) == 0)
+// {
+// // SL-19968 - make sure message system code gets a chance to run every so often
+// pump_idle_startup_network();
+// }
+ }
- file.close();
+ file.close();
- return !is_cache_obsolete;
+ return !is_cache_obsolete;
}
// static
bool LLInventoryModel::saveToFile(const std::string& filename,
- const cat_array_t& categories,
- const item_array_t& items)
+ const cat_array_t& categories,
+ const item_array_t& items)
{
- if (filename.empty())
- {
- LL_ERRS(LOG_INV) << "Filename is Null!" << LL_ENDL;
- return false;
- }
+ if (filename.empty())
+ {
+ LL_ERRS(LOG_INV) << "Filename is Null!" << LL_ENDL;
+ return false;
+ }
- LL_INFOS(LOG_INV) << "saving inventory to: (" << filename << ")" << LL_ENDL;
+ LL_INFOS(LOG_INV) << "saving inventory to: (" << filename << ")" << LL_ENDL;
try
{
@@ -3509,46 +3509,46 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
// static
void LLInventoryModel::registerCallbacks(LLMessageSystem* msg)
{
- //msg->setHandlerFuncFast(_PREHASH_InventoryUpdate,
- // processInventoryUpdate,
- // NULL);
- //msg->setHandlerFuncFast(_PREHASH_UseCachedInventory,
- // processUseCachedInventory,
- // NULL);
- msg->setHandlerFuncFast(_PREHASH_UpdateCreateInventoryItem,
- processUpdateCreateInventoryItem,
- NULL);
- msg->setHandlerFuncFast(_PREHASH_RemoveInventoryItem,
- processRemoveInventoryItem,
- NULL);
- msg->setHandlerFuncFast(_PREHASH_RemoveInventoryFolder,
- processRemoveInventoryFolder,
- NULL);
- msg->setHandlerFuncFast(_PREHASH_RemoveInventoryObjects,
- processRemoveInventoryObjects,
- NULL);
- msg->setHandlerFuncFast(_PREHASH_SaveAssetIntoInventory,
- processSaveAssetIntoInventory,
- NULL);
- msg->setHandlerFuncFast(_PREHASH_BulkUpdateInventory,
- processBulkUpdateInventory,
- NULL);
- msg->setHandlerFunc("MoveInventoryItem", processMoveInventoryItem);
+ //msg->setHandlerFuncFast(_PREHASH_InventoryUpdate,
+ // processInventoryUpdate,
+ // NULL);
+ //msg->setHandlerFuncFast(_PREHASH_UseCachedInventory,
+ // processUseCachedInventory,
+ // NULL);
+ msg->setHandlerFuncFast(_PREHASH_UpdateCreateInventoryItem,
+ processUpdateCreateInventoryItem,
+ NULL);
+ msg->setHandlerFuncFast(_PREHASH_RemoveInventoryItem,
+ processRemoveInventoryItem,
+ NULL);
+ msg->setHandlerFuncFast(_PREHASH_RemoveInventoryFolder,
+ processRemoveInventoryFolder,
+ NULL);
+ msg->setHandlerFuncFast(_PREHASH_RemoveInventoryObjects,
+ processRemoveInventoryObjects,
+ NULL);
+ msg->setHandlerFuncFast(_PREHASH_SaveAssetIntoInventory,
+ processSaveAssetIntoInventory,
+ NULL);
+ msg->setHandlerFuncFast(_PREHASH_BulkUpdateInventory,
+ processBulkUpdateInventory,
+ NULL);
+ msg->setHandlerFunc("MoveInventoryItem", processMoveInventoryItem);
}
-// static
+// static
void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, void**)
{
- // do accounting and highlight new items if they arrive
- if (gInventory.messageUpdateCore(msg, true, LLInventoryObserver::UPDATE_CREATE))
- {
- U32 callback_id;
- LLUUID item_id;
- msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id);
- msg->getU32Fast(_PREHASH_InventoryData, _PREHASH_CallbackID, callback_id);
+ // do accounting and highlight new items if they arrive
+ if (gInventory.messageUpdateCore(msg, true, LLInventoryObserver::UPDATE_CREATE))
+ {
+ U32 callback_id;
+ LLUUID item_id;
+ msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id);
+ msg->getU32Fast(_PREHASH_InventoryData, _PREHASH_CallbackID, callback_id);
- gInventoryCallbacks.fire(callback_id, item_id);
+ gInventoryCallbacks.fire(callback_id, item_id);
// Message system at the moment doesn't support Thumbnails and potential
// newer features so just rerequest whole item
@@ -3556,251 +3556,251 @@ void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, vo
// todo: instead of unpacking message fully,
// grab only an item_id, then fetch
LLInventoryModelBackgroundFetch::instance().scheduleItemFetch(item_id, true);
- }
+ }
}
bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, U32 mask)
{
- //make sure our added inventory observer is active
- start_new_inventory_observer();
-
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- if(agent_id != gAgent.getID())
- {
- LL_WARNS(LOG_INV) << "Got a inventory update for the wrong agent: " << agent_id
- << LL_ENDL;
- return false;
- }
- item_array_t items;
- update_map_t update;
- S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
- // Does this loop ever execute more than once?
- for(S32 i = 0; i < count; ++i)
- {
- LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
- titem->unpackMessage(msg, _PREHASH_InventoryData, i);
- LL_DEBUGS(LOG_INV) << "LLInventoryModel::messageUpdateCore() item id: "
- << titem->getUUID() << LL_ENDL;
- items.push_back(titem);
- // examine update for changes.
- LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID());
- if(itemp)
- {
- if(titem->getParentUUID() == itemp->getParentUUID())
- {
- update[titem->getParentUUID()];
- }
- else
- {
- ++update[titem->getParentUUID()];
- --update[itemp->getParentUUID()];
- }
- }
- else
- {
- ++update[titem->getParentUUID()];
- }
- }
- if(account)
- {
- gInventory.accountForUpdate(update);
- }
-
- if (account)
- {
- mask |= LLInventoryObserver::CREATE;
- }
- //as above, this loop never seems to loop more than once per call
- for (item_array_t::iterator it = items.begin(); it != items.end(); ++it)
- {
- gInventory.updateItem(*it, mask);
- }
- gInventory.notifyObservers();
- gViewerWindow->getWindow()->decBusyCount();
-
- return true;
+ //make sure our added inventory observer is active
+ start_new_inventory_observer();
+
+ LLUUID agent_id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+ if(agent_id != gAgent.getID())
+ {
+ LL_WARNS(LOG_INV) << "Got a inventory update for the wrong agent: " << agent_id
+ << LL_ENDL;
+ return false;
+ }
+ item_array_t items;
+ update_map_t update;
+ S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
+ // Does this loop ever execute more than once?
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
+ titem->unpackMessage(msg, _PREHASH_InventoryData, i);
+ LL_DEBUGS(LOG_INV) << "LLInventoryModel::messageUpdateCore() item id: "
+ << titem->getUUID() << LL_ENDL;
+ items.push_back(titem);
+ // examine update for changes.
+ LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID());
+ if(itemp)
+ {
+ if(titem->getParentUUID() == itemp->getParentUUID())
+ {
+ update[titem->getParentUUID()];
+ }
+ else
+ {
+ ++update[titem->getParentUUID()];
+ --update[itemp->getParentUUID()];
+ }
+ }
+ else
+ {
+ ++update[titem->getParentUUID()];
+ }
+ }
+ if(account)
+ {
+ gInventory.accountForUpdate(update);
+ }
+
+ if (account)
+ {
+ mask |= LLInventoryObserver::CREATE;
+ }
+ //as above, this loop never seems to loop more than once per call
+ for (item_array_t::iterator it = items.begin(); it != items.end(); ++it)
+ {
+ gInventory.updateItem(*it, mask);
+ }
+ gInventory.notifyObservers();
+ gViewerWindow->getWindow()->decBusyCount();
+
+ return true;
}
-// static
+// static
void LLInventoryModel::removeInventoryItem(LLUUID agent_id, LLMessageSystem* msg, const char* msg_label)
{
- LLUUID item_id;
- S32 count = msg->getNumberOfBlocksFast(msg_label);
- LL_DEBUGS(LOG_INV) << "Message has " << count << " item blocks" << LL_ENDL;
- uuid_vec_t item_ids;
- update_map_t update;
- for(S32 i = 0; i < count; ++i)
- {
- msg->getUUIDFast(msg_label, _PREHASH_ItemID, item_id, i);
- LL_DEBUGS(LOG_INV) << "Checking for item-to-be-removed " << item_id << LL_ENDL;
- LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
- if(itemp)
- {
- LL_DEBUGS(LOG_INV) << "Item will be removed " << item_id << LL_ENDL;
- // we only bother with the delete and account if we found
- // the item - this is usually a back-up for permissions,
- // so frequently the item will already be gone.
- --update[itemp->getParentUUID()];
- item_ids.push_back(item_id);
- }
- }
- gInventory.accountForUpdate(update);
- for(uuid_vec_t::iterator it = item_ids.begin(); it != item_ids.end(); ++it)
- {
- LL_DEBUGS(LOG_INV) << "Calling deleteObject " << *it << LL_ENDL;
- gInventory.deleteObject(*it);
- }
+ LLUUID item_id;
+ S32 count = msg->getNumberOfBlocksFast(msg_label);
+ LL_DEBUGS(LOG_INV) << "Message has " << count << " item blocks" << LL_ENDL;
+ uuid_vec_t item_ids;
+ update_map_t update;
+ for(S32 i = 0; i < count; ++i)
+ {
+ msg->getUUIDFast(msg_label, _PREHASH_ItemID, item_id, i);
+ LL_DEBUGS(LOG_INV) << "Checking for item-to-be-removed " << item_id << LL_ENDL;
+ LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
+ if(itemp)
+ {
+ LL_DEBUGS(LOG_INV) << "Item will be removed " << item_id << LL_ENDL;
+ // we only bother with the delete and account if we found
+ // the item - this is usually a back-up for permissions,
+ // so frequently the item will already be gone.
+ --update[itemp->getParentUUID()];
+ item_ids.push_back(item_id);
+ }
+ }
+ gInventory.accountForUpdate(update);
+ for(uuid_vec_t::iterator it = item_ids.begin(); it != item_ids.end(); ++it)
+ {
+ LL_DEBUGS(LOG_INV) << "Calling deleteObject " << *it << LL_ENDL;
+ gInventory.deleteObject(*it);
+ }
}
-// static
+// static
void LLInventoryModel::processRemoveInventoryItem(LLMessageSystem* msg, void**)
{
- LL_DEBUGS(LOG_INV) << "LLInventoryModel::processRemoveInventoryItem()" << LL_ENDL;
- LLUUID agent_id, item_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- if(agent_id != gAgent.getID())
- {
- LL_WARNS(LOG_INV) << "Got a RemoveInventoryItem for the wrong agent."
- << LL_ENDL;
- return;
- }
- LLInventoryModel::removeInventoryItem(agent_id, msg, _PREHASH_InventoryData);
- gInventory.notifyObservers();
+ LL_DEBUGS(LOG_INV) << "LLInventoryModel::processRemoveInventoryItem()" << LL_ENDL;
+ LLUUID agent_id, item_id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+ if(agent_id != gAgent.getID())
+ {
+ LL_WARNS(LOG_INV) << "Got a RemoveInventoryItem for the wrong agent."
+ << LL_ENDL;
+ return;
+ }
+ LLInventoryModel::removeInventoryItem(agent_id, msg, _PREHASH_InventoryData);
+ gInventory.notifyObservers();
}
-// static
+// static
void LLInventoryModel::removeInventoryFolder(LLUUID agent_id,
- LLMessageSystem* msg)
+ LLMessageSystem* msg)
{
- LLUUID folder_id;
- uuid_vec_t folder_ids;
- update_map_t update;
- S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
- for(S32 i = 0; i < count; ++i)
- {
- msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, folder_id, i);
- LLViewerInventoryCategory* folderp = gInventory.getCategory(folder_id);
- if(folderp)
- {
- --update[folderp->getParentUUID()];
- folder_ids.push_back(folder_id);
- }
- }
- gInventory.accountForUpdate(update);
- for(uuid_vec_t::iterator it = folder_ids.begin(); it != folder_ids.end(); ++it)
- {
- gInventory.deleteObject(*it);
- }
+ LLUUID folder_id;
+ uuid_vec_t folder_ids;
+ update_map_t update;
+ S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
+ for(S32 i = 0; i < count; ++i)
+ {
+ msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, folder_id, i);
+ LLViewerInventoryCategory* folderp = gInventory.getCategory(folder_id);
+ if(folderp)
+ {
+ --update[folderp->getParentUUID()];
+ folder_ids.push_back(folder_id);
+ }
+ }
+ gInventory.accountForUpdate(update);
+ for(uuid_vec_t::iterator it = folder_ids.begin(); it != folder_ids.end(); ++it)
+ {
+ gInventory.deleteObject(*it);
+ }
}
-// static
+// static
void LLInventoryModel::processRemoveInventoryFolder(LLMessageSystem* msg,
- void**)
+ void**)
{
- LL_DEBUGS() << "LLInventoryModel::processRemoveInventoryFolder()" << LL_ENDL;
- LLUUID agent_id, session_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
- if(agent_id != gAgent.getID())
- {
- LL_WARNS() << "Got a RemoveInventoryFolder for the wrong agent."
- << LL_ENDL;
- return;
- }
- LLInventoryModel::removeInventoryFolder( agent_id, msg );
- gInventory.notifyObservers();
+ LL_DEBUGS() << "LLInventoryModel::processRemoveInventoryFolder()" << LL_ENDL;
+ LLUUID agent_id, session_id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
+ if(agent_id != gAgent.getID())
+ {
+ LL_WARNS() << "Got a RemoveInventoryFolder for the wrong agent."
+ << LL_ENDL;
+ return;
+ }
+ LLInventoryModel::removeInventoryFolder( agent_id, msg );
+ gInventory.notifyObservers();
}
-// static
+// static
void LLInventoryModel::processRemoveInventoryObjects(LLMessageSystem* msg,
- void**)
+ void**)
{
- LL_DEBUGS() << "LLInventoryModel::processRemoveInventoryObjects()" << LL_ENDL;
- LLUUID agent_id, session_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
- if(agent_id != gAgent.getID())
- {
- LL_WARNS() << "Got a RemoveInventoryObjects for the wrong agent."
- << LL_ENDL;
- return;
- }
- LLInventoryModel::removeInventoryFolder( agent_id, msg );
- LLInventoryModel::removeInventoryItem( agent_id, msg, _PREHASH_ItemData );
- gInventory.notifyObservers();
+ LL_DEBUGS() << "LLInventoryModel::processRemoveInventoryObjects()" << LL_ENDL;
+ LLUUID agent_id, session_id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
+ if(agent_id != gAgent.getID())
+ {
+ LL_WARNS() << "Got a RemoveInventoryObjects for the wrong agent."
+ << LL_ENDL;
+ return;
+ }
+ LLInventoryModel::removeInventoryFolder( agent_id, msg );
+ LLInventoryModel::removeInventoryItem( agent_id, msg, _PREHASH_ItemData );
+ gInventory.notifyObservers();
}
-// static
+// static
void LLInventoryModel::processSaveAssetIntoInventory(LLMessageSystem* msg,
- void**)
+ void**)
{
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- if(agent_id != gAgent.getID())
- {
- LL_WARNS() << "Got a SaveAssetIntoInventory message for the wrong agent."
- << LL_ENDL;
- return;
- }
-
- LLUUID item_id;
- msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id);
-
- // The viewer ignores the asset id because this message is only
- // used for attachments/objects, so the asset id is not used in
- // the viewer anyway.
- LL_DEBUGS() << "LLInventoryModel::processSaveAssetIntoInventory itemID="
- << item_id << LL_ENDL;
- LLViewerInventoryItem* item = gInventory.getItem( item_id );
- if( item )
- {
- LLCategoryUpdate up(item->getParentUUID(), 0);
- gInventory.accountForUpdate(up);
- gInventory.addChangedMask( LLInventoryObserver::INTERNAL, item_id);
- gInventory.notifyObservers();
- }
- else
- {
- LL_INFOS() << "LLInventoryModel::processSaveAssetIntoInventory item"
- " not found: " << item_id << LL_ENDL;
- }
- if(gViewerWindow)
- {
- gViewerWindow->getWindow()->decBusyCount();
- }
+ LLUUID agent_id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+ if(agent_id != gAgent.getID())
+ {
+ LL_WARNS() << "Got a SaveAssetIntoInventory message for the wrong agent."
+ << LL_ENDL;
+ return;
+ }
+
+ LLUUID item_id;
+ msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id);
+
+ // The viewer ignores the asset id because this message is only
+ // used for attachments/objects, so the asset id is not used in
+ // the viewer anyway.
+ LL_DEBUGS() << "LLInventoryModel::processSaveAssetIntoInventory itemID="
+ << item_id << LL_ENDL;
+ LLViewerInventoryItem* item = gInventory.getItem( item_id );
+ if( item )
+ {
+ LLCategoryUpdate up(item->getParentUUID(), 0);
+ gInventory.accountForUpdate(up);
+ gInventory.addChangedMask( LLInventoryObserver::INTERNAL, item_id);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LL_INFOS() << "LLInventoryModel::processSaveAssetIntoInventory item"
+ " not found: " << item_id << LL_ENDL;
+ }
+ if(gViewerWindow)
+ {
+ gViewerWindow->getWindow()->decBusyCount();
+ }
}
// static
void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
{
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- if(agent_id != gAgent.getID())
- {
- LL_WARNS() << "Got a BulkUpdateInventory for the wrong agent." << LL_ENDL;
- return;
- }
- LLUUID tid;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, tid);
+ LLUUID agent_id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+ if(agent_id != gAgent.getID())
+ {
+ LL_WARNS() << "Got a BulkUpdateInventory for the wrong agent." << LL_ENDL;
+ return;
+ }
+ LLUUID tid;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, tid);
#ifndef LL_RELEASE_FOR_DOWNLOAD
- LL_DEBUGS("Inventory") << "Bulk inventory: " << tid << LL_ENDL;
+ LL_DEBUGS("Inventory") << "Bulk inventory: " << tid << LL_ENDL;
#endif
- update_map_t update;
- cat_array_t folders;
- S32 count;
- S32 i;
- count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
- for(i = 0; i < count; ++i)
- {
- LLPointer<LLViewerInventoryCategory> tfolder = new LLViewerInventoryCategory(gAgent.getID());
- tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
- LL_DEBUGS("Inventory") << "unpacked folder '" << tfolder->getName() << "' ("
- << tfolder->getUUID() << ") in " << tfolder->getParentUUID()
- << LL_ENDL;
-
+ update_map_t update;
+ cat_array_t folders;
+ S32 count;
+ S32 i;
+ count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
+ for(i = 0; i < count; ++i)
+ {
+ LLPointer<LLViewerInventoryCategory> tfolder = new LLViewerInventoryCategory(gAgent.getID());
+ tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
+ LL_DEBUGS("Inventory") << "unpacked folder '" << tfolder->getName() << "' ("
+ << tfolder->getUUID() << ") in " << tfolder->getParentUUID()
+ << LL_ENDL;
+
// If the folder is a listing or a version folder, all we need to do is update the SLM data
int depth_folder = depth_nesting_in_marketplace(tfolder->getUUID());
if ((depth_folder == 1) || (depth_folder == 2))
@@ -3811,12 +3811,12 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
LLMarketplaceData::instance().getListing(listing_id);
// In that case, there is no item to update so no callback -> we skip the rest of the update
}
- else if(tfolder->getUUID().notNull())
- {
- folders.push_back(tfolder);
- LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID());
- if(folderp)
- {
+ else if(tfolder->getUUID().notNull())
+ {
+ folders.push_back(tfolder);
+ LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID());
+ if(folderp)
+ {
if (folderp->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
{
if (tfolder->getParentUUID() == folderp->getParentUUID())
@@ -3833,15 +3833,15 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
{
folderp->fetch();
}
- }
- else
- {
- // we could not find the folder, so it is probably
- // new. However, we only want to attempt accounting
- // for the parent if we can find the parent.
- folderp = gInventory.getCategory(tfolder->getParentUUID());
- if(folderp)
- {
+ }
+ else
+ {
+ // we could not find the folder, so it is probably
+ // new. However, we only want to attempt accounting
+ // for the parent if we can find the parent.
+ folderp = gInventory.getCategory(tfolder->getParentUUID());
+ if(folderp)
+ {
if (folderp->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
{
++update[tfolder->getParentUUID()];
@@ -3850,51 +3850,51 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
{
folderp->fetch();
}
- }
- }
- }
- }
-
-
- count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
- uuid_vec_t wearable_ids;
- item_array_t items;
- std::list<InventoryCallbackInfo> cblist;
- for(i = 0; i < count; ++i)
- {
- LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
- titem->unpackMessage(msg, _PREHASH_ItemData, i);
- LL_DEBUGS("Inventory") << "unpacked item '" << titem->getName() << "' in "
- << titem->getParentUUID() << LL_ENDL;
- U32 callback_id;
- msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);
- if(titem->getUUID().notNull() ) // && callback_id.notNull() )
- {
- items.push_back(titem);
- cblist.push_back(InventoryCallbackInfo(callback_id, titem->getUUID()));
- if (titem->getInventoryType() == LLInventoryType::IT_WEARABLE)
- {
- wearable_ids.push_back(titem->getUUID());
- }
- // examine update for changes.
- LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID());
- if(itemp)
- {
- if(titem->getParentUUID() == itemp->getParentUUID())
- {
- update[titem->getParentUUID()];
- }
- else
- {
- ++update[titem->getParentUUID()];
- --update[itemp->getParentUUID()];
- }
- }
- else
- {
- LLViewerInventoryCategory* folderp = gInventory.getCategory(titem->getParentUUID());
- if(folderp)
- {
+ }
+ }
+ }
+ }
+
+
+ count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
+ uuid_vec_t wearable_ids;
+ item_array_t items;
+ std::list<InventoryCallbackInfo> cblist;
+ for(i = 0; i < count; ++i)
+ {
+ LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
+ titem->unpackMessage(msg, _PREHASH_ItemData, i);
+ LL_DEBUGS("Inventory") << "unpacked item '" << titem->getName() << "' in "
+ << titem->getParentUUID() << LL_ENDL;
+ U32 callback_id;
+ msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);
+ if(titem->getUUID().notNull() ) // && callback_id.notNull() )
+ {
+ items.push_back(titem);
+ cblist.push_back(InventoryCallbackInfo(callback_id, titem->getUUID()));
+ if (titem->getInventoryType() == LLInventoryType::IT_WEARABLE)
+ {
+ wearable_ids.push_back(titem->getUUID());
+ }
+ // examine update for changes.
+ LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID());
+ if(itemp)
+ {
+ if(titem->getParentUUID() == itemp->getParentUUID())
+ {
+ update[titem->getParentUUID()];
+ }
+ else
+ {
+ ++update[titem->getParentUUID()];
+ --update[itemp->getParentUUID()];
+ }
+ }
+ else
+ {
+ LLViewerInventoryCategory* folderp = gInventory.getCategory(titem->getParentUUID());
+ if(folderp)
+ {
if (folderp->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
{
++update[titem->getParentUUID()];
@@ -3903,18 +3903,18 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
{
folderp->fetch();
}
- }
- }
- }
- else
- {
- cblist.push_back(InventoryCallbackInfo(callback_id, LLUUID::null));
- }
- }
- gInventory.accountForUpdate(update);
-
- for (cat_array_t::iterator cit = folders.begin(); cit != folders.end(); ++cit)
- {
+ }
+ }
+ }
+ else
+ {
+ cblist.push_back(InventoryCallbackInfo(callback_id, LLUUID::null));
+ }
+ }
+ gInventory.accountForUpdate(update);
+
+ for (cat_array_t::iterator cit = folders.begin(); cit != folders.end(); ++cit)
+ {
gInventory.updateCategory(*cit);
if ((*cit)->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
{
@@ -3924,100 +3924,100 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
LLInventoryModelBackgroundFetch::instance().scheduleFolderFetch((*cit)->getUUID(), true /*force, since it has changes*/);
}
// else already called fetch() above
- }
- for (item_array_t::iterator iit = items.begin(); iit != items.end(); ++iit)
- {
- gInventory.updateItem(*iit);
+ }
+ for (item_array_t::iterator iit = items.begin(); iit != items.end(); ++iit)
+ {
+ gInventory.updateItem(*iit);
// Temporary workaround: just fetch the item using AIS to get missing fields.
// If this works fine we might want to extract 'ids only' from the message
// then use AIS as a primary fetcher
LLInventoryModelBackgroundFetch::instance().scheduleItemFetch((*iit)->getUUID(), true);
- }
- gInventory.notifyObservers();
-
- // The incoming inventory could span more than one BulkInventoryUpdate packet,
- // so record the transaction ID for this purchase, then wear all clothing
- // that comes in as part of that transaction ID. JC
- if (LLInventoryState::sWearNewClothing)
- {
- LLInventoryState::sWearNewClothingTransactionID = tid;
- LLInventoryState::sWearNewClothing = FALSE;
- }
-
- if (tid.notNull() && tid == LLInventoryState::sWearNewClothingTransactionID)
- {
- count = wearable_ids.size();
- for (i = 0; i < count; ++i)
- {
- LLViewerInventoryItem* wearable_item;
- wearable_item = gInventory.getItem(wearable_ids[i]);
- LLAppearanceMgr::instance().wearItemOnAvatar(wearable_item->getUUID(), true, true);
- }
- }
-
- std::list<InventoryCallbackInfo>::iterator inv_it;
- for (inv_it = cblist.begin(); inv_it != cblist.end(); ++inv_it)
- {
- InventoryCallbackInfo cbinfo = (*inv_it);
- gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID);
- }
+ }
+ gInventory.notifyObservers();
+
+ // The incoming inventory could span more than one BulkInventoryUpdate packet,
+ // so record the transaction ID for this purchase, then wear all clothing
+ // that comes in as part of that transaction ID. JC
+ if (LLInventoryState::sWearNewClothing)
+ {
+ LLInventoryState::sWearNewClothingTransactionID = tid;
+ LLInventoryState::sWearNewClothing = FALSE;
+ }
+
+ if (tid.notNull() && tid == LLInventoryState::sWearNewClothingTransactionID)
+ {
+ count = wearable_ids.size();
+ for (i = 0; i < count; ++i)
+ {
+ LLViewerInventoryItem* wearable_item;
+ wearable_item = gInventory.getItem(wearable_ids[i]);
+ LLAppearanceMgr::instance().wearItemOnAvatar(wearable_item->getUUID(), true, true);
+ }
+ }
+
+ std::list<InventoryCallbackInfo>::iterator inv_it;
+ for (inv_it = cblist.begin(); inv_it != cblist.end(); ++inv_it)
+ {
+ InventoryCallbackInfo cbinfo = (*inv_it);
+ gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID);
+ }
}
// static
void LLInventoryModel::processMoveInventoryItem(LLMessageSystem* msg, void**)
{
- LL_DEBUGS() << "LLInventoryModel::processMoveInventoryItem()" << LL_ENDL;
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- if(agent_id != gAgent.getID())
- {
- LL_WARNS() << "Got a MoveInventoryItem message for the wrong agent."
- << LL_ENDL;
- return;
- }
-
- LLUUID item_id;
- LLUUID folder_id;
- std::string new_name;
- bool anything_changed = false;
- S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
- for(S32 i = 0; i < count; ++i)
- {
- msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id, i);
- LLViewerInventoryItem* item = gInventory.getItem(item_id);
- if(item)
- {
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_FolderID, folder_id, i);
- msg->getString("InventoryData", "NewName", new_name, i);
-
- LL_DEBUGS() << "moving item " << item_id << " to folder "
- << folder_id << LL_ENDL;
- update_list_t update;
- LLCategoryUpdate old_folder(item->getParentUUID(), -1);
- update.push_back(old_folder);
- LLCategoryUpdate new_folder(folder_id, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
-
- new_item->setParent(folder_id);
- if (new_name.length() > 0)
- {
- new_item->rename(new_name);
- }
- gInventory.updateItem(new_item);
- anything_changed = true;
- }
- else
- {
- LL_INFOS() << "LLInventoryModel::processMoveInventoryItem item not found: " << item_id << LL_ENDL;
- }
- }
- if(anything_changed)
- {
- gInventory.notifyObservers();
- }
+ LL_DEBUGS() << "LLInventoryModel::processMoveInventoryItem()" << LL_ENDL;
+ LLUUID agent_id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+ if(agent_id != gAgent.getID())
+ {
+ LL_WARNS() << "Got a MoveInventoryItem message for the wrong agent."
+ << LL_ENDL;
+ return;
+ }
+
+ LLUUID item_id;
+ LLUUID folder_id;
+ std::string new_name;
+ bool anything_changed = false;
+ S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
+ for(S32 i = 0; i < count; ++i)
+ {
+ msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id, i);
+ LLViewerInventoryItem* item = gInventory.getItem(item_id);
+ if(item)
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_FolderID, folder_id, i);
+ msg->getString("InventoryData", "NewName", new_name, i);
+
+ LL_DEBUGS() << "moving item " << item_id << " to folder "
+ << folder_id << LL_ENDL;
+ update_list_t update;
+ LLCategoryUpdate old_folder(item->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLCategoryUpdate new_folder(folder_id, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ new_item->setParent(folder_id);
+ if (new_name.length() > 0)
+ {
+ new_item->rename(new_name);
+ }
+ gInventory.updateItem(new_item);
+ anything_changed = true;
+ }
+ else
+ {
+ LL_INFOS() << "LLInventoryModel::processMoveInventoryItem item not found: " << item_id << LL_ENDL;
+ }
+ }
+ if(anything_changed)
+ {
+ gInventory.notifyObservers();
+ }
}
//----------------------------------------------------------------------------
@@ -4026,274 +4026,274 @@ void LLInventoryModel::processMoveInventoryItem(LLMessageSystem* msg, void**)
bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLFolderType::EType preferred_type)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option == 0) // YES
- {
- const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
- purge_descendents_of(folder_id, NULL);
- }
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0) // YES
+ {
+ const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
+ purge_descendents_of(folder_id, NULL);
+ }
+ return false;
}
void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderType::EType preferred_type)
{
- if (!notification.empty())
- {
- LLSD args;
- if(LLFolderType::FT_TRASH == preferred_type)
- {
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- const LLUUID trash_id = findCategoryUUIDForType(preferred_type);
- gInventory.collectDescendents(trash_id, cats, items, LLInventoryModel::INCLUDE_TRASH); //All descendants
- S32 item_count = items.size() + cats.size();
- args["COUNT"] = item_count;
- }
- LLNotificationsUtil::add(notification, args, LLSD(),
- boost::bind(&LLInventoryModel::callbackEmptyFolderType, this, _1, _2, preferred_type));
- }
- else
- {
- const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
- purge_descendents_of(folder_id, NULL);
- }
+ if (!notification.empty())
+ {
+ LLSD args;
+ if(LLFolderType::FT_TRASH == preferred_type)
+ {
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ const LLUUID trash_id = findCategoryUUIDForType(preferred_type);
+ gInventory.collectDescendents(trash_id, cats, items, LLInventoryModel::INCLUDE_TRASH); //All descendants
+ S32 item_count = items.size() + cats.size();
+ args["COUNT"] = item_count;
+ }
+ LLNotificationsUtil::add(notification, args, LLSD(),
+ boost::bind(&LLInventoryModel::callbackEmptyFolderType, this, _1, _2, preferred_type));
+ }
+ else
+ {
+ const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
+ purge_descendents_of(folder_id, NULL);
+ }
}
//----------------------------------------------------------------------------
void LLInventoryModel::removeItem(const LLUUID& item_id)
{
- LLViewerInventoryItem* item = getItem(item_id);
- if (! item)
- {
- LL_WARNS("Inventory") << "couldn't find inventory item " << item_id << LL_ENDL;
- }
- else
- {
- const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH);
- if (new_parent.notNull())
- {
- LL_INFOS("Inventory") << "Moving to Trash (" << new_parent << "):" << LL_ENDL;
- changeItemParent(item, new_parent, TRUE);
- }
- }
+ LLViewerInventoryItem* item = getItem(item_id);
+ if (! item)
+ {
+ LL_WARNS("Inventory") << "couldn't find inventory item " << item_id << LL_ENDL;
+ }
+ else
+ {
+ const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if (new_parent.notNull())
+ {
+ LL_INFOS("Inventory") << "Moving to Trash (" << new_parent << "):" << LL_ENDL;
+ changeItemParent(item, new_parent, TRUE);
+ }
+ }
}
void LLInventoryModel::removeCategory(const LLUUID& category_id)
{
- if (! get_is_category_removable(this, category_id))
- {
- return;
- }
-
- // Look for any gestures and deactivate them
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- collectDescendents(category_id, descendent_categories, descendent_items, FALSE);
-
- for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin();
- iter != descendent_items.end();
- ++iter)
- {
- const LLViewerInventoryItem* item = (*iter);
- const LLUUID& item_id = item->getUUID();
- if (item->getType() == LLAssetType::AT_GESTURE
- && LLGestureMgr::instance().isGestureActive(item_id))
- {
- LLGestureMgr::instance().deactivateGesture(item_id);
- }
- }
-
- LLViewerInventoryCategory* cat = getCategory(category_id);
- if (cat)
- {
- const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
- if (trash_id.notNull())
- {
- changeCategoryParent(cat, trash_id, TRUE);
- }
- }
-
- checkTrashOverflow();
+ if (! get_is_category_removable(this, category_id))
+ {
+ return;
+ }
+
+ // Look for any gestures and deactivate them
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ collectDescendents(category_id, descendent_categories, descendent_items, FALSE);
+
+ for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin();
+ iter != descendent_items.end();
+ ++iter)
+ {
+ const LLViewerInventoryItem* item = (*iter);
+ const LLUUID& item_id = item->getUUID();
+ if (item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureMgr::instance().isGestureActive(item_id))
+ {
+ LLGestureMgr::instance().deactivateGesture(item_id);
+ }
+ }
+
+ LLViewerInventoryCategory* cat = getCategory(category_id);
+ if (cat)
+ {
+ const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if (trash_id.notNull())
+ {
+ changeCategoryParent(cat, trash_id, TRUE);
+ }
+ }
+
+ checkTrashOverflow();
}
void LLInventoryModel::removeObject(const LLUUID& object_id)
{
- if(object_id.isNull())
- {
- return;
- }
-
- LLInventoryObject* obj = getObject(object_id);
- if (dynamic_cast<LLViewerInventoryItem*>(obj))
- {
- removeItem(object_id);
- }
- else if (dynamic_cast<LLViewerInventoryCategory*>(obj))
- {
- removeCategory(object_id);
- }
- else if (obj)
- {
- LL_WARNS("Inventory") << "object ID " << object_id
- << " is an object of unrecognized class "
- << typeid(*obj).name() << LL_ENDL;
- }
- else
- {
- LL_WARNS("Inventory") << "object ID " << object_id << " not found" << LL_ENDL;
- }
+ if(object_id.isNull())
+ {
+ return;
+ }
+
+ LLInventoryObject* obj = getObject(object_id);
+ if (dynamic_cast<LLViewerInventoryItem*>(obj))
+ {
+ removeItem(object_id);
+ }
+ else if (dynamic_cast<LLViewerInventoryCategory*>(obj))
+ {
+ removeCategory(object_id);
+ }
+ else if (obj)
+ {
+ LL_WARNS("Inventory") << "object ID " << object_id
+ << " is an object of unrecognized class "
+ << typeid(*obj).name() << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("Inventory") << "object ID " << object_id << " not found" << LL_ENDL;
+ }
}
bool callback_preview_trash_folder(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option == 0) // YES
- {
- LLFloaterPreviewTrash::show();
- }
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0) // YES
+ {
+ LLFloaterPreviewTrash::show();
+ }
+ return false;
}
void LLInventoryModel::checkTrashOverflow()
{
- static LLCachedControl<U32> trash_max_capacity(gSavedSettings, "InventoryTrashMaxCapacity");
-
- // Collect all descendants including those in subfolders.
- //
- // Note: Do we really need content of subfolders?
- // This was made to prevent download of trash folder timeouting
- // viewer and sub-folders are supposed to download independently.
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
- gInventory.collectDescendents(trash_id, cats, items, LLInventoryModel::INCLUDE_TRASH);
- S32 item_count = items.size() + cats.size();
-
- if (item_count >= trash_max_capacity)
- {
- if (LLFloaterPreviewTrash::isVisible())
- {
- // bring to front
- LLFloaterPreviewTrash::show();
- }
- else
- {
- LLNotificationsUtil::add("TrashIsFull", LLSD(), LLSD(),
- boost::bind(callback_preview_trash_folder, _1, _2));
- }
- }
+ static LLCachedControl<U32> trash_max_capacity(gSavedSettings, "InventoryTrashMaxCapacity");
+
+ // Collect all descendants including those in subfolders.
+ //
+ // Note: Do we really need content of subfolders?
+ // This was made to prevent download of trash folder timeouting
+ // viewer and sub-folders are supposed to download independently.
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ gInventory.collectDescendents(trash_id, cats, items, LLInventoryModel::INCLUDE_TRASH);
+ S32 item_count = items.size() + cats.size();
+
+ if (item_count >= trash_max_capacity)
+ {
+ if (LLFloaterPreviewTrash::isVisible())
+ {
+ // bring to front
+ LLFloaterPreviewTrash::show();
+ }
+ else
+ {
+ LLNotificationsUtil::add("TrashIsFull", LLSD(), LLSD(),
+ boost::bind(callback_preview_trash_folder, _1, _2));
+ }
+ }
}
const LLUUID &LLInventoryModel::getRootFolderID() const
{
- return mRootFolderID;
+ return mRootFolderID;
}
void LLInventoryModel::setRootFolderID(const LLUUID& val)
{
- mRootFolderID = val;
+ mRootFolderID = val;
}
const LLUUID &LLInventoryModel::getLibraryRootFolderID() const
{
- return mLibraryRootFolderID;
+ return mLibraryRootFolderID;
}
void LLInventoryModel::setLibraryRootFolderID(const LLUUID& val)
{
- mLibraryRootFolderID = val;
+ mLibraryRootFolderID = val;
}
const LLUUID &LLInventoryModel::getLibraryOwnerID() const
{
- return mLibraryOwnerID;
+ return mLibraryOwnerID;
}
void LLInventoryModel::setLibraryOwnerID(const LLUUID& val)
{
- mLibraryOwnerID = val;
+ mLibraryOwnerID = val;
}
// static
BOOL LLInventoryModel::getIsFirstTimeInViewer2()
{
- // Do not call this before parentchild map is built.
- if (!gInventory.mIsAgentInvUsable)
- {
- LL_WARNS() << "Parent Child Map not yet built; guessing as first time in viewer2." << LL_ENDL;
- return TRUE;
- }
-
- return sFirstTimeInViewer2;
+ // Do not call this before parentchild map is built.
+ if (!gInventory.mIsAgentInvUsable)
+ {
+ LL_WARNS() << "Parent Child Map not yet built; guessing as first time in viewer2." << LL_ENDL;
+ return TRUE;
+ }
+
+ return sFirstTimeInViewer2;
}
LLInventoryModel::item_array_t::iterator LLInventoryModel::findItemIterByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
{
- LLInventoryModel::item_array_t::iterator curr_item = items.begin();
-
- while (curr_item != items.end())
- {
- if ((*curr_item)->getUUID() == id)
- {
- break;
- }
- ++curr_item;
- }
-
- return curr_item;
+ LLInventoryModel::item_array_t::iterator curr_item = items.begin();
+
+ while (curr_item != items.end())
+ {
+ if ((*curr_item)->getUUID() == id)
+ {
+ break;
+ }
+ ++curr_item;
+ }
+
+ return curr_item;
}
// static
// * @param[in, out] items - vector with items to be updated. It should be sorted in a right way
// * before calling this method.
// * @param src_item_id - LLUUID of inventory item to be moved in new position
-// * @param dest_item_id - LLUUID of inventory item before (or after) which source item should
+// * @param dest_item_id - LLUUID of inventory item before (or after) which source item should
// * be placed.
-// * @param insert_before - bool indicating if src_item_id should be placed before or after
+// * @param insert_before - bool indicating if src_item_id should be placed before or after
// * dest_item_id. Default is true.
void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& src_item_id, const LLUUID& dest_item_id, bool insert_before)
{
- LLInventoryModel::item_array_t::iterator it_src = findItemIterByUUID(items, src_item_id);
- LLInventoryModel::item_array_t::iterator it_dest = findItemIterByUUID(items, dest_item_id);
-
- // If one of the passed UUID is not in the item list, bail out
- if ((it_src == items.end()) || (it_dest == items.end()))
- return;
-
- // Erase the source element from the list, keep a copy before erasing.
- LLViewerInventoryItem* src_item = *it_src;
- items.erase(it_src);
-
- // Note: Target iterator is not valid anymore because the container was changed, so update it.
- it_dest = findItemIterByUUID(items, dest_item_id);
-
- // Go to the next element if one wishes to insert after the dest element
- if (!insert_before)
- {
- ++it_dest;
- }
-
- // Reinsert the source item in the right place
- if (it_dest != items.end())
- {
- items.insert(it_dest, src_item);
- }
- else
- {
- // Append to the list if it_dest reached the end
- items.push_back(src_item);
- }
+ LLInventoryModel::item_array_t::iterator it_src = findItemIterByUUID(items, src_item_id);
+ LLInventoryModel::item_array_t::iterator it_dest = findItemIterByUUID(items, dest_item_id);
+
+ // If one of the passed UUID is not in the item list, bail out
+ if ((it_src == items.end()) || (it_dest == items.end()))
+ return;
+
+ // Erase the source element from the list, keep a copy before erasing.
+ LLViewerInventoryItem* src_item = *it_src;
+ items.erase(it_src);
+
+ // Note: Target iterator is not valid anymore because the container was changed, so update it.
+ it_dest = findItemIterByUUID(items, dest_item_id);
+
+ // Go to the next element if one wishes to insert after the dest element
+ if (!insert_before)
+ {
+ ++it_dest;
+ }
+
+ // Reinsert the source item in the right place
+ if (it_dest != items.end())
+ {
+ items.insert(it_dest, src_item);
+ }
+ else
+ {
+ // Append to the list if it_dest reached the end
+ items.push_back(src_item);
+ }
}
// See also LLInventorySort where landmarks in the Favorites folder are sorted.
class LLViewerInventoryItemSort
{
public:
- bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b)
- {
- return a->getSortField() < b->getSortField();
- }
+ bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b)
+ {
+ return a->getSortField() < b->getSortField();
+ }
};
//----------------------------------------------------------------------------
@@ -4301,95 +4301,95 @@ public:
// *NOTE: DEBUG functionality
void LLInventoryModel::dumpInventory() const
{
- LL_INFOS() << "\nBegin Inventory Dump\n**********************:" << LL_ENDL;
- LL_INFOS() << "mCategory[] contains " << mCategoryMap.size() << " items." << LL_ENDL;
- for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
- {
- const LLViewerInventoryCategory* cat = cit->second;
- if(cat)
- {
- LL_INFOS() << " " << cat->getUUID() << " '" << cat->getName() << "' "
- << cat->getVersion() << " " << cat->getDescendentCount()
- << LL_ENDL;
- }
- else
- {
- LL_INFOS() << " NULL!" << LL_ENDL;
- }
- }
- LL_INFOS() << "mItemMap[] contains " << mItemMap.size() << " items." << LL_ENDL;
- for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
- {
- const LLViewerInventoryItem* item = iit->second;
- if(item)
- {
- LL_INFOS() << " " << item->getUUID() << " "
- << item->getName() << LL_ENDL;
- }
- else
- {
- LL_INFOS() << " NULL!" << LL_ENDL;
- }
- }
- LL_INFOS() << "\n**********************\nEnd Inventory Dump" << LL_ENDL;
+ LL_INFOS() << "\nBegin Inventory Dump\n**********************:" << LL_ENDL;
+ LL_INFOS() << "mCategory[] contains " << mCategoryMap.size() << " items." << LL_ENDL;
+ for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
+ {
+ const LLViewerInventoryCategory* cat = cit->second;
+ if(cat)
+ {
+ LL_INFOS() << " " << cat->getUUID() << " '" << cat->getName() << "' "
+ << cat->getVersion() << " " << cat->getDescendentCount()
+ << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << " NULL!" << LL_ENDL;
+ }
+ }
+ LL_INFOS() << "mItemMap[] contains " << mItemMap.size() << " items." << LL_ENDL;
+ for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
+ {
+ const LLViewerInventoryItem* item = iit->second;
+ if(item)
+ {
+ LL_INFOS() << " " << item->getUUID() << " "
+ << item->getName() << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << " NULL!" << LL_ENDL;
+ }
+ }
+ LL_INFOS() << "\n**********************\nEnd Inventory Dump" << LL_ENDL;
}
// Do various integrity checks on model, logging issues found and
-// returning an overall good/bad flag.
+// returning an overall good/bad flag.
LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
- LLPointer<LLInventoryValidationInfo> validation_info = new LLInventoryValidationInfo;
- S32 fatal_errs = 0;
- S32 warning_count= 0;
+ LLPointer<LLInventoryValidationInfo> validation_info = new LLInventoryValidationInfo;
+ S32 fatal_errs = 0;
+ S32 warning_count= 0;
S32 loop_count = 0;
S32 orphaned_count = 0;
- if (getRootFolderID().isNull())
- {
- LL_WARNS("Inventory") << "Fatal inventory corruption: no root folder id" << LL_ENDL;
- validation_info->mFatalNoRootFolder = true;
+ if (getRootFolderID().isNull())
+ {
+ LL_WARNS("Inventory") << "Fatal inventory corruption: no root folder id" << LL_ENDL;
+ validation_info->mFatalNoRootFolder = true;
fatal_errs++;
- }
- if (getLibraryRootFolderID().isNull())
- {
- // Probably shouldn't be a fatality, inventory can function without a library
- LL_WARNS("Inventory") << "Fatal inventory corruption: no library root folder id" << LL_ENDL;
- validation_info->mFatalNoLibraryRootFolder = true;
+ }
+ if (getLibraryRootFolderID().isNull())
+ {
+ // Probably shouldn't be a fatality, inventory can function without a library
+ LL_WARNS("Inventory") << "Fatal inventory corruption: no library root folder id" << LL_ENDL;
+ validation_info->mFatalNoLibraryRootFolder = true;
fatal_errs++;
- }
-
- if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())
- {
- // ParentChild should be one larger because of the special entry for null uuid.
- LL_INFOS("Inventory") << "unexpected sizes: cat map size " << mCategoryMap.size()
- << " parent/child " << mParentChildCategoryTree.size() << LL_ENDL;
-
- validation_info->mWarnings["category_map_size"]++;
- warning_count++;
- }
- S32 cat_lock = 0;
- S32 item_lock = 0;
- S32 desc_unknown_count = 0;
- S32 version_unknown_count = 0;
-
- typedef std::map<LLFolderType::EType, S32> ft_count_map;
- ft_count_map ft_counts_under_root;
- ft_count_map ft_counts_elsewhere;
-
- // Loop over all categories and check.
- for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
- {
- const LLUUID& cat_id = cit->first;
- const LLViewerInventoryCategory *cat = cit->second;
- if (!cat)
- {
- LL_WARNS("Inventory") << "null cat" << LL_ENDL;
- validation_info->mWarnings["null_cat"]++;
- warning_count++;
- continue;
- }
- LLUUID topmost_ancestor_id;
- // Will leave as null uuid on failure
+ }
+
+ if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())
+ {
+ // ParentChild should be one larger because of the special entry for null uuid.
+ LL_INFOS("Inventory") << "unexpected sizes: cat map size " << mCategoryMap.size()
+ << " parent/child " << mParentChildCategoryTree.size() << LL_ENDL;
+
+ validation_info->mWarnings["category_map_size"]++;
+ warning_count++;
+ }
+ S32 cat_lock = 0;
+ S32 item_lock = 0;
+ S32 desc_unknown_count = 0;
+ S32 version_unknown_count = 0;
+
+ typedef std::map<LLFolderType::EType, S32> ft_count_map;
+ ft_count_map ft_counts_under_root;
+ ft_count_map ft_counts_elsewhere;
+
+ // Loop over all categories and check.
+ for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
+ {
+ const LLUUID& cat_id = cit->first;
+ const LLViewerInventoryCategory *cat = cit->second;
+ if (!cat)
+ {
+ LL_WARNS("Inventory") << "null cat" << LL_ENDL;
+ validation_info->mWarnings["null_cat"]++;
+ warning_count++;
+ continue;
+ }
+ LLUUID topmost_ancestor_id;
+ // Will leave as null uuid on failure
EAncestorResult res = getObjectTopmostAncestor(cat_id, topmost_ancestor_id);
switch (res)
{
@@ -4403,361 +4403,361 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
break;
default:
LL_WARNS("Inventory") << "Unknown ancestor error for " << cat_id << LL_ENDL;
- validation_info->mWarnings["unknown_ancestor_status"]++;
+ validation_info->mWarnings["unknown_ancestor_status"]++;
warning_count++;
break;
}
- if (cat_id != cat->getUUID())
- {
- LL_WARNS("Inventory") << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
- validation_info->mWarnings["cat_id_index_mismatch"]++;
- warning_count++;
- }
-
- if (cat->getParentUUID().isNull())
- {
- if (cat_id != getRootFolderID() && cat_id != getLibraryRootFolderID())
- {
- LL_WARNS("Inventory") << "cat " << cat_id << " has no parent, but is not root ("
- << getRootFolderID() << ") or library root ("
- << getLibraryRootFolderID() << ")" << LL_ENDL;
- validation_info->mWarnings["null_parent"]++;
- warning_count++;
- }
- }
- cat_array_t* cats;
- item_array_t* items;
- getDirectDescendentsOf(cat_id,cats,items);
- if (!cats || !items)
- {
- LL_WARNS("Inventory") << "invalid direct descendents for " << cat_id << LL_ENDL;
- validation_info->mWarnings["direct_descendents"]++;
- warning_count++;
- continue;
- }
- if (cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
- {
- desc_unknown_count++;
- }
- else if (cats->size() + items->size() != cat->getDescendentCount())
- {
- // In the case of library this is not unexpected, since
- // different user accounts may be getting the library
- // contents from different inventory hosts.
- if (topmost_ancestor_id.isNull() || topmost_ancestor_id != getLibraryRootFolderID())
- {
- LL_WARNS("Inventory") << "invalid desc count for " << cat_id << " [" << getFullPath(cat) << "]"
- << " cached " << cat->getDescendentCount()
- << " expected " << cats->size() << "+" << items->size()
- << "=" << cats->size() +items->size() << LL_ENDL;
- validation_info->mWarnings["invalid_descendent_count"]++;
- warning_count++;
- }
- }
- if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
- {
- version_unknown_count++;
- }
- auto cat_lock_it = mCategoryLock.find(cat_id);
- if (cat_lock_it != mCategoryLock.end() && cat_lock_it->second)
- {
- cat_lock++;
- }
- auto item_lock_it = mItemLock.find(cat_id);
- if (item_lock_it != mItemLock.end() && item_lock_it->second)
- {
- item_lock++;
- }
- for (S32 i = 0; i<items->size(); i++)
- {
- LLViewerInventoryItem *item = items->at(i);
-
- if (!item)
- {
- LL_WARNS("Inventory") << "null item at index " << i << " for cat " << cat_id << LL_ENDL;
- validation_info->mWarnings["null_item_at_index"]++;
- warning_count++;
- continue;
- }
-
- const LLUUID& item_id = item->getUUID();
-
- if (item->getParentUUID() != cat_id)
- {
- LL_WARNS("Inventory") << "wrong parent for " << item_id << " found "
- << item->getParentUUID() << " expected " << cat_id
- << LL_ENDL;
- validation_info->mWarnings["wrong_parent_for_item"]++;
- warning_count++;
- }
-
-
- // Entries in items and mItemMap should correspond.
- item_map_t::const_iterator it = mItemMap.find(item_id);
- if (it == mItemMap.end())
- {
- LL_WARNS("Inventory") << "item " << item_id << " found as child of "
- << cat_id << " but not in top level mItemMap" << LL_ENDL;
- validation_info->mWarnings["item_not_in_top_map"]++;
- warning_count++;
- }
- else
- {
- LLViewerInventoryItem *top_item = it->second;
- if (top_item != item)
- {
- LL_WARNS("Inventory") << "item mismatch, item_id " << item_id
- << " top level entry is different, uuid " << top_item->getUUID() << LL_ENDL;
- }
- }
-
- // Topmost ancestor should be root or library.
- LLUUID topmost_ancestor_id;
+ if (cat_id != cat->getUUID())
+ {
+ LL_WARNS("Inventory") << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
+ validation_info->mWarnings["cat_id_index_mismatch"]++;
+ warning_count++;
+ }
+
+ if (cat->getParentUUID().isNull())
+ {
+ if (cat_id != getRootFolderID() && cat_id != getLibraryRootFolderID())
+ {
+ LL_WARNS("Inventory") << "cat " << cat_id << " has no parent, but is not root ("
+ << getRootFolderID() << ") or library root ("
+ << getLibraryRootFolderID() << ")" << LL_ENDL;
+ validation_info->mWarnings["null_parent"]++;
+ warning_count++;
+ }
+ }
+ cat_array_t* cats;
+ item_array_t* items;
+ getDirectDescendentsOf(cat_id,cats,items);
+ if (!cats || !items)
+ {
+ LL_WARNS("Inventory") << "invalid direct descendents for " << cat_id << LL_ENDL;
+ validation_info->mWarnings["direct_descendents"]++;
+ warning_count++;
+ continue;
+ }
+ if (cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
+ {
+ desc_unknown_count++;
+ }
+ else if (cats->size() + items->size() != cat->getDescendentCount())
+ {
+ // In the case of library this is not unexpected, since
+ // different user accounts may be getting the library
+ // contents from different inventory hosts.
+ if (topmost_ancestor_id.isNull() || topmost_ancestor_id != getLibraryRootFolderID())
+ {
+ LL_WARNS("Inventory") << "invalid desc count for " << cat_id << " [" << getFullPath(cat) << "]"
+ << " cached " << cat->getDescendentCount()
+ << " expected " << cats->size() << "+" << items->size()
+ << "=" << cats->size() +items->size() << LL_ENDL;
+ validation_info->mWarnings["invalid_descendent_count"]++;
+ warning_count++;
+ }
+ }
+ if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
+ {
+ version_unknown_count++;
+ }
+ auto cat_lock_it = mCategoryLock.find(cat_id);
+ if (cat_lock_it != mCategoryLock.end() && cat_lock_it->second)
+ {
+ cat_lock++;
+ }
+ auto item_lock_it = mItemLock.find(cat_id);
+ if (item_lock_it != mItemLock.end() && item_lock_it->second)
+ {
+ item_lock++;
+ }
+ for (S32 i = 0; i<items->size(); i++)
+ {
+ LLViewerInventoryItem *item = items->at(i);
+
+ if (!item)
+ {
+ LL_WARNS("Inventory") << "null item at index " << i << " for cat " << cat_id << LL_ENDL;
+ validation_info->mWarnings["null_item_at_index"]++;
+ warning_count++;
+ continue;
+ }
+
+ const LLUUID& item_id = item->getUUID();
+
+ if (item->getParentUUID() != cat_id)
+ {
+ LL_WARNS("Inventory") << "wrong parent for " << item_id << " found "
+ << item->getParentUUID() << " expected " << cat_id
+ << LL_ENDL;
+ validation_info->mWarnings["wrong_parent_for_item"]++;
+ warning_count++;
+ }
+
+
+ // Entries in items and mItemMap should correspond.
+ item_map_t::const_iterator it = mItemMap.find(item_id);
+ if (it == mItemMap.end())
+ {
+ LL_WARNS("Inventory") << "item " << item_id << " found as child of "
+ << cat_id << " but not in top level mItemMap" << LL_ENDL;
+ validation_info->mWarnings["item_not_in_top_map"]++;
+ warning_count++;
+ }
+ else
+ {
+ LLViewerInventoryItem *top_item = it->second;
+ if (top_item != item)
+ {
+ LL_WARNS("Inventory") << "item mismatch, item_id " << item_id
+ << " top level entry is different, uuid " << top_item->getUUID() << LL_ENDL;
+ }
+ }
+
+ // Topmost ancestor should be root or library.
+ LLUUID topmost_ancestor_id;
EAncestorResult found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
- if (found != ANCESTOR_OK)
- {
- LL_WARNS("Inventory") << "unable to find topmost ancestor for " << item_id << LL_ENDL;
- validation_info->mWarnings["topmost_ancestor_not_found"]++;
- warning_count++;
- }
- else
- {
- if (topmost_ancestor_id != getRootFolderID() &&
- topmost_ancestor_id != getLibraryRootFolderID())
- {
- LL_WARNS("Inventory") << "unrecognized top level ancestor for " << item_id
- << " got " << topmost_ancestor_id
- << " expected " << getRootFolderID()
- << " or " << getLibraryRootFolderID() << LL_ENDL;
- validation_info->mWarnings["topmost_ancestor_not_recognized"]++;
- warning_count++;
- }
- }
- }
-
- // Does this category appear as a child of its supposed parent?
- const LLUUID& parent_id = cat->getParentUUID();
- if (!parent_id.isNull())
- {
- cat_array_t* cats;
- item_array_t* items;
- getDirectDescendentsOf(parent_id,cats,items);
- if (!cats)
- {
- LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
- << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL;
+ if (found != ANCESTOR_OK)
+ {
+ LL_WARNS("Inventory") << "unable to find topmost ancestor for " << item_id << LL_ENDL;
+ validation_info->mWarnings["topmost_ancestor_not_found"]++;
+ warning_count++;
+ }
+ else
+ {
+ if (topmost_ancestor_id != getRootFolderID() &&
+ topmost_ancestor_id != getLibraryRootFolderID())
+ {
+ LL_WARNS("Inventory") << "unrecognized top level ancestor for " << item_id
+ << " got " << topmost_ancestor_id
+ << " expected " << getRootFolderID()
+ << " or " << getLibraryRootFolderID() << LL_ENDL;
+ validation_info->mWarnings["topmost_ancestor_not_recognized"]++;
+ warning_count++;
+ }
+ }
+ }
+
+ // Does this category appear as a child of its supposed parent?
+ const LLUUID& parent_id = cat->getParentUUID();
+ if (!parent_id.isNull())
+ {
+ cat_array_t* cats;
+ item_array_t* items;
+ getDirectDescendentsOf(parent_id,cats,items);
+ if (!cats)
+ {
+ LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
+ << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL;
orphaned_count++;
- }
- else
- {
- bool found = false;
- for (S32 i = 0; i<cats->size(); i++)
- {
- LLViewerInventoryCategory *kid_cat = cats->at(i);
- if (kid_cat == cat)
- {
- found = true;
- break;
- }
- }
- if (!found)
- {
- LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
- << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL;
+ }
+ else
+ {
+ bool found = false;
+ for (S32 i = 0; i<cats->size(); i++)
+ {
+ LLViewerInventoryCategory *kid_cat = cats->at(i);
+ if (kid_cat == cat)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
+ << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL;
orphaned_count++;
- }
- }
- }
-
- // Update count of preferred types
- LLFolderType::EType folder_type = cat->getPreferredType();
- bool cat_is_in_library = false;
- LLUUID topmost_id;
- if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANCESTOR_OK && topmost_id == getLibraryRootFolderID())
- {
- cat_is_in_library = true;
- }
- if (!cat_is_in_library)
- {
- if (getRootFolderID().notNull() && (cat->getUUID()==getRootFolderID() || cat->getParentUUID()==getRootFolderID()))
- {
- ft_counts_under_root[folder_type]++;
- if (folder_type != LLFolderType::FT_NONE)
- {
- LL_DEBUGS("Inventory") << "Under root cat: " << getFullPath(cat) << " folder_type " << folder_type << LL_ENDL;
- }
- }
- else
- {
- ft_counts_elsewhere[folder_type]++;
- if (folder_type != LLFolderType::FT_NONE)
- {
- LL_DEBUGS("Inventory") << "Elsewhere cat: " << getFullPath(cat) << " folder_type " << folder_type << LL_ENDL;
- }
- }
- }
- }
-
- // Loop over all items and check
- for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
- {
- const LLUUID& item_id = iit->first;
- LLViewerInventoryItem *item = iit->second;
- if (item->getUUID() != item_id)
- {
- LL_WARNS("Inventory") << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL;
- validation_info->mWarnings["item_id_mismatch"]++;
- warning_count++;
- }
-
- const LLUUID& parent_id = item->getParentUUID();
- if (parent_id.isNull())
- {
- LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;
+ }
+ }
+ }
+
+ // Update count of preferred types
+ LLFolderType::EType folder_type = cat->getPreferredType();
+ bool cat_is_in_library = false;
+ LLUUID topmost_id;
+ if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANCESTOR_OK && topmost_id == getLibraryRootFolderID())
+ {
+ cat_is_in_library = true;
+ }
+ if (!cat_is_in_library)
+ {
+ if (getRootFolderID().notNull() && (cat->getUUID()==getRootFolderID() || cat->getParentUUID()==getRootFolderID()))
+ {
+ ft_counts_under_root[folder_type]++;
+ if (folder_type != LLFolderType::FT_NONE)
+ {
+ LL_DEBUGS("Inventory") << "Under root cat: " << getFullPath(cat) << " folder_type " << folder_type << LL_ENDL;
+ }
+ }
+ else
+ {
+ ft_counts_elsewhere[folder_type]++;
+ if (folder_type != LLFolderType::FT_NONE)
+ {
+ LL_DEBUGS("Inventory") << "Elsewhere cat: " << getFullPath(cat) << " folder_type " << folder_type << LL_ENDL;
+ }
+ }
+ }
+ }
+
+ // Loop over all items and check
+ for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
+ {
+ const LLUUID& item_id = iit->first;
+ LLViewerInventoryItem *item = iit->second;
+ if (item->getUUID() != item_id)
+ {
+ LL_WARNS("Inventory") << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL;
+ validation_info->mWarnings["item_id_mismatch"]++;
+ warning_count++;
+ }
+
+ const LLUUID& parent_id = item->getParentUUID();
+ if (parent_id.isNull())
+ {
+ LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;
orphaned_count++;
- }
- else
- {
- cat_array_t* cats;
- item_array_t* items;
- getDirectDescendentsOf(parent_id,cats,items);
- if (!items)
- {
- LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
- << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;
+ }
+ else
+ {
+ cat_array_t* cats;
+ item_array_t* items;
+ getDirectDescendentsOf(parent_id,cats,items);
+ if (!items)
+ {
+ LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
+ << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;
orphaned_count++;
- }
- else
- {
- bool found = false;
- for (S32 i=0; i<items->size(); ++i)
- {
- if (items->at(i) == item)
- {
- found = true;
- break;
- }
- }
- if (!found)
- {
- LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
- << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;
+ }
+ else
+ {
+ bool found = false;
+ for (S32 i=0; i<items->size(); ++i)
+ {
+ if (items->at(i) == item)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
+ << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;
orphaned_count++;
- }
- }
-
- }
- // Link checking
- if (item->getIsLinkType())
- {
- const LLUUID& link_id = item->getUUID();
- const LLUUID& target_id = item->getLinkedUUID();
- LLViewerInventoryItem *target_item = getItem(target_id);
- LLViewerInventoryCategory *target_cat = getCategory(target_id);
- // Linked-to UUID should have back reference to this link.
- if (!hasBacklinkInfo(link_id, target_id))
- {
- LL_WARNS("Inventory") << "link " << item->getUUID() << " type " << item->getActualType()
- << " missing backlink info at target_id " << target_id
- << LL_ENDL;
+ }
+ }
+
+ }
+ // Link checking
+ if (item->getIsLinkType())
+ {
+ const LLUUID& link_id = item->getUUID();
+ const LLUUID& target_id = item->getLinkedUUID();
+ LLViewerInventoryItem *target_item = getItem(target_id);
+ LLViewerInventoryCategory *target_cat = getCategory(target_id);
+ // Linked-to UUID should have back reference to this link.
+ if (!hasBacklinkInfo(link_id, target_id))
+ {
+ LL_WARNS("Inventory") << "link " << item->getUUID() << " type " << item->getActualType()
+ << " missing backlink info at target_id " << target_id
+ << LL_ENDL;
orphaned_count++;
- }
- // Links should have referents.
- if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
- {
- LL_WARNS("Inventory") << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+ }
+ // Links should have referents.
+ if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
+ {
+ LL_WARNS("Inventory") << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
orphaned_count++;
- }
- else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
- {
- LL_WARNS("Inventory") << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+ }
+ else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
+ {
+ LL_WARNS("Inventory") << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
orphaned_count++;
- }
- if (target_item && target_item->getIsLinkType())
- {
- LL_WARNS("Inventory") << "link " << item->getName() << " references a link item "
- << target_item->getName() << " " << target_item->getUUID() << LL_ENDL;
- }
-
- // Links should not have backlinks.
- std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(link_id);
- if (range.first != range.second)
- {
- LL_WARNS("Inventory") << "Link item " << item->getName() << " has backlinks!" << LL_ENDL;
- }
- }
- else
- {
- // Check the backlinks of a non-link item.
- const LLUUID& target_id = item->getUUID();
- std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(target_id);
- for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
- {
- const LLUUID& link_id = it->second;
- LLViewerInventoryItem *link_item = getItem(link_id);
- if (!link_item || !link_item->getIsLinkType())
- {
- LL_WARNS("Inventory") << "invalid backlink from target " << item->getName() << " to " << link_id << LL_ENDL;
- }
- }
- }
- }
-
- // Check system folders
- for (auto fit=ft_counts_under_root.begin(); fit != ft_counts_under_root.end(); ++fit)
- {
- LL_DEBUGS("Inventory") << "Folder type " << fit->first << " count " << fit->second << " under root" << LL_ENDL;
- }
- for (auto fit=ft_counts_elsewhere.begin(); fit != ft_counts_elsewhere.end(); ++fit)
- {
- LL_DEBUGS("Inventory") << "Folder type " << fit->first << " count " << fit->second << " elsewhere" << LL_ENDL;
- }
-
- static LLCachedControl<bool> fake_system_folder_issues(gSavedSettings, "QAModeFakeSystemFolderIssues", false);
- static std::default_random_engine e{};
+ }
+ if (target_item && target_item->getIsLinkType())
+ {
+ LL_WARNS("Inventory") << "link " << item->getName() << " references a link item "
+ << target_item->getName() << " " << target_item->getUUID() << LL_ENDL;
+ }
+
+ // Links should not have backlinks.
+ std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(link_id);
+ if (range.first != range.second)
+ {
+ LL_WARNS("Inventory") << "Link item " << item->getName() << " has backlinks!" << LL_ENDL;
+ }
+ }
+ else
+ {
+ // Check the backlinks of a non-link item.
+ const LLUUID& target_id = item->getUUID();
+ std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(target_id);
+ for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
+ {
+ const LLUUID& link_id = it->second;
+ LLViewerInventoryItem *link_item = getItem(link_id);
+ if (!link_item || !link_item->getIsLinkType())
+ {
+ LL_WARNS("Inventory") << "invalid backlink from target " << item->getName() << " to " << link_id << LL_ENDL;
+ }
+ }
+ }
+ }
+
+ // Check system folders
+ for (auto fit=ft_counts_under_root.begin(); fit != ft_counts_under_root.end(); ++fit)
+ {
+ LL_DEBUGS("Inventory") << "Folder type " << fit->first << " count " << fit->second << " under root" << LL_ENDL;
+ }
+ for (auto fit=ft_counts_elsewhere.begin(); fit != ft_counts_elsewhere.end(); ++fit)
+ {
+ LL_DEBUGS("Inventory") << "Folder type " << fit->first << " count " << fit->second << " elsewhere" << LL_ENDL;
+ }
+
+ static LLCachedControl<bool> fake_system_folder_issues(gSavedSettings, "QAModeFakeSystemFolderIssues", false);
+ static std::default_random_engine e{};
static std::uniform_int_distribution<> distrib(0, 1);
- for (S32 ft=LLFolderType::FT_TEXTURE; ft<LLFolderType::FT_COUNT; ft++)
- {
- LLFolderType::EType folder_type = static_cast<LLFolderType::EType>(ft);
- if (LLFolderType::lookup(folder_type)==LLFolderType::badLookup())
- {
- continue;
- }
- bool is_automatic = LLFolderType::lookupIsAutomaticType(folder_type);
- bool is_singleton = LLFolderType::lookupIsSingletonType(folder_type);
- S32 count_under_root = ft_counts_under_root[folder_type];
- S32 count_elsewhere = ft_counts_elsewhere[folder_type];
- if (fake_system_folder_issues)
- {
- // Force all counts to be either 0 or 2, thus flagged as an error.
- count_under_root = 2*distrib(e);
- count_elsewhere = 2*distrib(e);
- validation_info->mFatalQADebugMode = true;
- }
- if (is_singleton)
- {
- if (count_under_root==0)
- {
- LL_WARNS("Inventory") << "Expected system folder type " << ft << " was not found under root" << LL_ENDL;
- // Need to create, if allowed.
- if (is_automatic)
- {
- LL_WARNS("Inventory") << "Fatal inventory corruption: cannot create system folder of type " << ft << LL_ENDL;
- validation_info->mMissingRequiredSystemFolders.insert(folder_type);
+ for (S32 ft=LLFolderType::FT_TEXTURE; ft<LLFolderType::FT_COUNT; ft++)
+ {
+ LLFolderType::EType folder_type = static_cast<LLFolderType::EType>(ft);
+ if (LLFolderType::lookup(folder_type)==LLFolderType::badLookup())
+ {
+ continue;
+ }
+ bool is_automatic = LLFolderType::lookupIsAutomaticType(folder_type);
+ bool is_singleton = LLFolderType::lookupIsSingletonType(folder_type);
+ S32 count_under_root = ft_counts_under_root[folder_type];
+ S32 count_elsewhere = ft_counts_elsewhere[folder_type];
+ if (fake_system_folder_issues)
+ {
+ // Force all counts to be either 0 or 2, thus flagged as an error.
+ count_under_root = 2*distrib(e);
+ count_elsewhere = 2*distrib(e);
+ validation_info->mFatalQADebugMode = true;
+ }
+ if (is_singleton)
+ {
+ if (count_under_root==0)
+ {
+ LL_WARNS("Inventory") << "Expected system folder type " << ft << " was not found under root" << LL_ENDL;
+ // Need to create, if allowed.
+ if (is_automatic)
+ {
+ LL_WARNS("Inventory") << "Fatal inventory corruption: cannot create system folder of type " << ft << LL_ENDL;
+ validation_info->mMissingRequiredSystemFolders.insert(folder_type);
fatal_errs++;
- }
- else
- {
- // Can create, and will when needed.
- // (Not sure this is really a warning, but worth logging)
- validation_info->mWarnings["missing_system_folder_can_create"]++;
- warning_count++;
- }
- }
- else if (count_under_root > 1)
- {
- validation_info->mDuplicateRequiredSystemFolders.insert(folder_type);
+ }
+ else
+ {
+ // Can create, and will when needed.
+ // (Not sure this is really a warning, but worth logging)
+ validation_info->mWarnings["missing_system_folder_can_create"]++;
+ warning_count++;
+ }
+ }
+ else if (count_under_root > 1)
+ {
+ validation_info->mDuplicateRequiredSystemFolders.insert(folder_type);
if (!is_automatic
&& folder_type != LLFolderType::FT_SETTINGS
// FT_MATERIAL might need to be automatic like the rest of upload folders
@@ -4766,7 +4766,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
// It is a fatal problem or can lead to fatal problems for COF,
// outfits, trash and other non-automatic folders.
- validation_info->mFatalSystemDuplicate++;
+ validation_info->mFatalSystemDuplicate++;
fatal_errs++;
LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL;
}
@@ -4775,65 +4775,76 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
// For automatic folders it's not a fatal issue and shouldn't
// break inventory or other functionality further
// Exception: FT_SETTINGS is not automatic, but only deserves a warning.
- validation_info->mWarnings["non_fatal_system_duplicate_under_root"]++;
+ validation_info->mWarnings["non_fatal_system_duplicate_under_root"]++;
warning_count++;
LL_WARNS("Inventory") << "System folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL;
}
- }
- if (count_elsewhere > 0)
- {
- LL_WARNS("Inventory") << "Found " << count_elsewhere << " extra folders of type " << ft << " outside of root" << LL_ENDL;
- validation_info->mWarnings["non_fatal_system_duplicate_elsewhere"]++;
- warning_count++;
- }
- }
- }
-
-
- if (cat_lock > 0 || item_lock > 0)
- {
- LL_INFOS("Inventory") << "Found locks on some categories: sub-cat arrays "
- << cat_lock << ", item arrays " << item_lock << LL_ENDL;
- }
- if (desc_unknown_count != 0)
- {
- LL_DEBUGS() << "Found " << desc_unknown_count << " cats with unknown descendent count" << LL_ENDL;
- }
- if (version_unknown_count != 0)
- {
- LL_DEBUGS("Inventory") << "Found " << version_unknown_count << " cats with unknown version" << LL_ENDL;
- }
-
- // FIXME need to fail login and tell user to retry, contact support if problem persists.
- bool valid = (fatal_errs == 0);
- LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warning_count << ", valid: " << valid << LL_ENDL;
-
- validation_info->mFatalErrorCount = fatal_errs;
- validation_info->mWarningCount = warning_count;
+ }
+ if (count_elsewhere > 0)
+ {
+ LL_WARNS("Inventory") << "Found " << count_elsewhere << " extra folders of type " << ft << " outside of root" << LL_ENDL;
+ validation_info->mWarnings["non_fatal_system_duplicate_elsewhere"]++;
+ warning_count++;
+ }
+ }
+ }
+
+
+ if (cat_lock > 0 || item_lock > 0)
+ {
+ LL_INFOS("Inventory") << "Found locks on some categories: sub-cat arrays "
+ << cat_lock << ", item arrays " << item_lock << LL_ENDL;
+ }
+ if (desc_unknown_count != 0)
+ {
+ LL_DEBUGS() << "Found " << desc_unknown_count << " cats with unknown descendent count" << LL_ENDL;
+ }
+ if (version_unknown_count != 0)
+ {
+ LL_DEBUGS("Inventory") << "Found " << version_unknown_count << " cats with unknown version" << LL_ENDL;
+ }
+
+ // FIXME need to fail login and tell user to retry, contact support if problem persists.
+ bool valid = (fatal_errs == 0);
+ LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warning_count << ", valid: " << valid << LL_ENDL;
+
+ validation_info->mFatalErrorCount = fatal_errs;
+ validation_info->mWarningCount = warning_count;
validation_info->mLoopCount = loop_count;
validation_info->mOrphanedCount = orphaned_count;
- return validation_info;
+ return validation_info;
}
// Provides a unix-style path from root, like "/My Inventory/Clothing/.../myshirt"
std::string LLInventoryModel::getFullPath(const LLInventoryObject *obj) const
{
- std::vector<std::string> path_elts;
- std::map<LLUUID,bool> visited;
- while (obj != NULL && !visited[obj->getUUID()])
- {
- path_elts.push_back(obj->getName());
- // avoid infinite loop in the unlikely event of a cycle
- visited[obj->getUUID()] = true;
- obj = getObject(obj->getParentUUID());
- }
- std::stringstream s;
- std::string delim("/");
- std::reverse(path_elts.begin(), path_elts.end());
- std::string result = "/" + boost::algorithm::join(path_elts, delim);
- return result;
+ std::vector<std::string> path_elts;
+ std::map<LLUUID,bool> visited;
+ while (obj != NULL && !visited[obj->getUUID()])
+ {
+ path_elts.push_back(obj->getName());
+ // avoid infinite loop in the unlikely event of a cycle
+ visited[obj->getUUID()] = true;
+ obj = getObject(obj->getParentUUID());
+ }
+ std::stringstream s;
+ std::string delim("/");
+ std::reverse(path_elts.begin(), path_elts.end());
+ std::string result = "/" + boost::algorithm::join(path_elts, delim);
+ return result;
+}
+
+/*
+const LLInventoryObject* LLInventoryModel::findByFullPath(const std::string& path)
+{
+ vector<std::string> path_elts;
+ boost::algorithm::split(path_elts, path, boost::is_any_of("/"));
+ for(path_elts, auto e)
+ {
+ }
}
+*/
///----------------------------------------------------------------------------
/// Local function definitions
@@ -4843,41 +4854,41 @@ std::string LLInventoryModel::getFullPath(const LLInventoryObject *obj) const
#if 0
BOOL decompress_file(const char* src_filename, const char* dst_filename)
{
- BOOL rv = FALSE;
- gzFile src = NULL;
- U8* buffer = NULL;
- LLFILE* dst = NULL;
- S32 bytes = 0;
- const S32 DECOMPRESS_BUFFER_SIZE = 32000;
-
- // open the files
- src = gzopen(src_filename, "rb");
- if(!src) goto err_decompress;
- dst = LLFile::fopen(dst_filename, "wb");
- if(!dst) goto err_decompress;
-
- // decompress.
- buffer = new U8[DECOMPRESS_BUFFER_SIZE + 1];
-
- do
- {
- bytes = gzread(src, buffer, DECOMPRESS_BUFFER_SIZE);
- if (bytes < 0)
- {
- goto err_decompress;
- }
-
- fwrite(buffer, bytes, 1, dst);
- } while(gzeof(src) == 0);
-
- // success
- rv = TRUE;
+ BOOL rv = FALSE;
+ gzFile src = NULL;
+ U8* buffer = NULL;
+ LLFILE* dst = NULL;
+ S32 bytes = 0;
+ const S32 DECOMPRESS_BUFFER_SIZE = 32000;
+
+ // open the files
+ src = gzopen(src_filename, "rb");
+ if(!src) goto err_decompress;
+ dst = LLFile::fopen(dst_filename, "wb");
+ if(!dst) goto err_decompress;
+
+ // decompress.
+ buffer = new U8[DECOMPRESS_BUFFER_SIZE + 1];
+
+ do
+ {
+ bytes = gzread(src, buffer, DECOMPRESS_BUFFER_SIZE);
+ if (bytes < 0)
+ {
+ goto err_decompress;
+ }
+
+ fwrite(buffer, bytes, 1, dst);
+ } while(gzeof(src) == 0);
+
+ // success
+ rv = TRUE;
err_decompress:
- if(src != NULL) gzclose(src);
- if(buffer != NULL) delete[] buffer;
- if(dst != NULL) fclose(dst);
- return rv;
+ if(src != NULL) gzclose(src);
+ if(buffer != NULL) delete[] buffer;
+ if(dst != NULL) fclose(dst);
+ return rv;
}
#endif
@@ -4887,163 +4898,163 @@ BOOL decompress_file(const char* src_filename, const char* dst_filename)
///----------------------------------------------------------------------------
LLInventoryModel::FetchItemHttpHandler::FetchItemHttpHandler(const LLSD & request_sd)
- : LLCore::HttpHandler(),
- mRequestSD(request_sd)
+ : LLCore::HttpHandler(),
+ mRequestSD(request_sd)
{}
LLInventoryModel::FetchItemHttpHandler::~FetchItemHttpHandler()
{}
void LLInventoryModel::FetchItemHttpHandler::onCompleted(LLCore::HttpHandle handle,
- LLCore::HttpResponse * response)
+ LLCore::HttpResponse * response)
{
- do // Single-pass do-while used for common exit handling
- {
- LLCore::HttpStatus status(response->getStatus());
- // status = LLCore::HttpStatus(404); // Dev tool to force error handling
- if (! status)
- {
- processFailure(status, response);
- break; // Goto common exit
- }
-
- LLCore::BufferArray * body(response->getBody());
- // body = NULL; // Dev tool to force error handling
- if (! body || ! body->size())
- {
- LL_WARNS(LOG_INV) << "Missing data in inventory item query." << LL_ENDL;
- processFailure("HTTP response for inventory item query missing body", response);
- break; // Goto common exit
- }
-
- // body->write(0, "Garbage Response", 16); // Dev tool to force error handling
- LLSD body_llsd;
- if (! LLCoreHttpUtil::responseToLLSD(response, true, body_llsd))
- {
- // INFOS-level logging will occur on the parsed failure
- processFailure("HTTP response for inventory item query has malformed LLSD", response);
- break; // Goto common exit
- }
-
- // Expect top-level structure to be a map
- // body_llsd = LLSD::emptyArray(); // Dev tool to force error handling
- if (! body_llsd.isMap())
- {
- processFailure("LLSD response for inventory item not a map", response);
- break; // Goto common exit
- }
-
- // Check for 200-with-error failures
- //
- // Original Responder-based serivce model didn't check for these errors.
- // It may be more robust to ignore this condition. With aggregated requests,
- // an error in one inventory item might take down the entire request.
- // So if this instead broke up the aggregated items into single requests,
- // maybe that would make progress. Or perhaps there's structured information
- // that can tell us what went wrong. Need to dig into this and firm up
- // the API.
- //
- // body_llsd["error"] = LLSD::emptyMap(); // Dev tool to force error handling
- // body_llsd["error"]["identifier"] = "Development";
- // body_llsd["error"]["message"] = "You left development code in the viewer";
- if (body_llsd.has("error"))
- {
- processFailure("Inventory application error (200-with-error)", response);
- break; // Goto common exit
- }
-
- // Okay, process data if possible
- processData(body_llsd, response);
- }
- while (false);
+ do // Single-pass do-while used for common exit handling
+ {
+ LLCore::HttpStatus status(response->getStatus());
+ // status = LLCore::HttpStatus(404); // Dev tool to force error handling
+ if (! status)
+ {
+ processFailure(status, response);
+ break; // Goto common exit
+ }
+
+ LLCore::BufferArray * body(response->getBody());
+ // body = NULL; // Dev tool to force error handling
+ if (! body || ! body->size())
+ {
+ LL_WARNS(LOG_INV) << "Missing data in inventory item query." << LL_ENDL;
+ processFailure("HTTP response for inventory item query missing body", response);
+ break; // Goto common exit
+ }
+
+ // body->write(0, "Garbage Response", 16); // Dev tool to force error handling
+ LLSD body_llsd;
+ if (! LLCoreHttpUtil::responseToLLSD(response, true, body_llsd))
+ {
+ // INFOS-level logging will occur on the parsed failure
+ processFailure("HTTP response for inventory item query has malformed LLSD", response);
+ break; // Goto common exit
+ }
+
+ // Expect top-level structure to be a map
+ // body_llsd = LLSD::emptyArray(); // Dev tool to force error handling
+ if (! body_llsd.isMap())
+ {
+ processFailure("LLSD response for inventory item not a map", response);
+ break; // Goto common exit
+ }
+
+ // Check for 200-with-error failures
+ //
+ // Original Responder-based serivce model didn't check for these errors.
+ // It may be more robust to ignore this condition. With aggregated requests,
+ // an error in one inventory item might take down the entire request.
+ // So if this instead broke up the aggregated items into single requests,
+ // maybe that would make progress. Or perhaps there's structured information
+ // that can tell us what went wrong. Need to dig into this and firm up
+ // the API.
+ //
+ // body_llsd["error"] = LLSD::emptyMap(); // Dev tool to force error handling
+ // body_llsd["error"]["identifier"] = "Development";
+ // body_llsd["error"]["message"] = "You left development code in the viewer";
+ if (body_llsd.has("error"))
+ {
+ processFailure("Inventory application error (200-with-error)", response);
+ break; // Goto common exit
+ }
+
+ // Okay, process data if possible
+ processData(body_llsd, response);
+ }
+ while (false);
}
void LLInventoryModel::FetchItemHttpHandler::processData(LLSD & content, LLCore::HttpResponse * response)
{
- start_new_inventory_observer();
+ start_new_inventory_observer();
#if 0
- LLUUID agent_id;
- agent_id = content["agent_id"].asUUID();
- if (agent_id != gAgent.getID())
- {
- LL_WARNS(LOG_INV) << "Got a inventory update for the wrong agent: " << agent_id
- << LL_ENDL;
- return;
- }
+ LLUUID agent_id;
+ agent_id = content["agent_id"].asUUID();
+ if (agent_id != gAgent.getID())
+ {
+ LL_WARNS(LOG_INV) << "Got a inventory update for the wrong agent: " << agent_id
+ << LL_ENDL;
+ return;
+ }
#endif
-
- LLInventoryModel::item_array_t items;
- LLInventoryModel::update_map_t update;
- LLUUID folder_id;
- LLSD content_items(content["items"]);
- const S32 count(content_items.size());
-
- // Does this loop ever execute more than once?
- for (S32 i(0); i < count; ++i)
- {
- LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
- titem->unpackMessage(content_items[i]);
-
- LL_DEBUGS(LOG_INV) << "ItemHttpHandler::httpSuccess item id: "
- << titem->getUUID() << LL_ENDL;
- items.push_back(titem);
-
- // examine update for changes.
- LLViewerInventoryItem * itemp(gInventory.getItem(titem->getUUID()));
-
- if (itemp)
- {
- if (titem->getParentUUID() == itemp->getParentUUID())
- {
- update[titem->getParentUUID()];
- }
- else
- {
- ++update[titem->getParentUUID()];
- --update[itemp->getParentUUID()];
- }
- }
- else
- {
- ++update[titem->getParentUUID()];
- }
-
- if (folder_id.isNull())
- {
- folder_id = titem->getParentUUID();
- }
- }
-
- // as above, this loop never seems to loop more than once per call
- for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it)
- {
- gInventory.updateItem(*it);
- }
- gInventory.notifyObservers();
- gViewerWindow->getWindow()->decBusyCount();
+
+ LLInventoryModel::item_array_t items;
+ LLInventoryModel::update_map_t update;
+ LLUUID folder_id;
+ LLSD content_items(content["items"]);
+ const S32 count(content_items.size());
+
+ // Does this loop ever execute more than once?
+ for (S32 i(0); i < count; ++i)
+ {
+ LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
+ titem->unpackMessage(content_items[i]);
+
+ LL_DEBUGS(LOG_INV) << "ItemHttpHandler::httpSuccess item id: "
+ << titem->getUUID() << LL_ENDL;
+ items.push_back(titem);
+
+ // examine update for changes.
+ LLViewerInventoryItem * itemp(gInventory.getItem(titem->getUUID()));
+
+ if (itemp)
+ {
+ if (titem->getParentUUID() == itemp->getParentUUID())
+ {
+ update[titem->getParentUUID()];
+ }
+ else
+ {
+ ++update[titem->getParentUUID()];
+ --update[itemp->getParentUUID()];
+ }
+ }
+ else
+ {
+ ++update[titem->getParentUUID()];
+ }
+
+ if (folder_id.isNull())
+ {
+ folder_id = titem->getParentUUID();
+ }
+ }
+
+ // as above, this loop never seems to loop more than once per call
+ for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it)
+ {
+ gInventory.updateItem(*it);
+ }
+ gInventory.notifyObservers();
+ gViewerWindow->getWindow()->decBusyCount();
}
void LLInventoryModel::FetchItemHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::HttpResponse * response)
{
- const std::string & ct(response->getContentType());
- LL_WARNS(LOG_INV) << "Inventory item fetch failure\n"
- << "[Status: " << status.toTerseString() << "]\n"
- << "[Reason: " << status.toString() << "]\n"
- << "[Content-type: " << ct << "]\n"
- << "[Content (abridged): "
- << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL;
- gInventory.notifyObservers();
+ const std::string & ct(response->getContentType());
+ LL_WARNS(LOG_INV) << "Inventory item fetch failure\n"
+ << "[Status: " << status.toTerseString() << "]\n"
+ << "[Reason: " << status.toString() << "]\n"
+ << "[Content-type: " << ct << "]\n"
+ << "[Content (abridged): "
+ << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL;
+ gInventory.notifyObservers();
}
void LLInventoryModel::FetchItemHttpHandler::processFailure(const char * const reason, LLCore::HttpResponse * response)
{
- LL_WARNS(LOG_INV) << "Inventory item fetch failure\n"
- << "[Status: internal error]\n"
- << "[Reason: " << reason << "]\n"
- << "[Content (abridged): "
- << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL;
- gInventory.notifyObservers();
+ LL_WARNS(LOG_INV) << "Inventory item fetch failure\n"
+ << "[Status: internal error]\n"
+ << "[Reason: " << reason << "]\n"
+ << "[Content (abridged): "
+ << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL;
+ gInventory.notifyObservers();
}
diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp
new file mode 100644
index 0000000000..97779a12ad
--- /dev/null
+++ b/indra/newview/llluamanager.cpp
@@ -0,0 +1,509 @@
+/**
+ * @file llluamanager.cpp
+ * @brief classes and functions for interfacing with LUA.
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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 "llluamanager.h"
+
+#include "fsyspath.h"
+#include "llcoros.h"
+#include "llerror.h"
+#include "lleventcoro.h"
+#include "llviewercontrol.h"
+#include "lua_function.h"
+#include "lualistener.h"
+#include "stringize.h"
+
+#include <boost/algorithm/string/replace.hpp>
+
+#include "luau/luacode.h"
+#include "luau/lua.h"
+#include "luau/luaconf.h"
+#include "luau/lualib.h"
+
+#include <sstream>
+#include <string_view>
+#include <vector>
+
+std::map<std::string, std::string> LLLUAmanager::sScriptNames;
+
+lua_function(sleep, "sleep(seconds): pause the running coroutine")
+{
+ F32 seconds = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ llcoro::suspendUntilTimeout(seconds);
+ lluau::set_interrupts_counter(L, 0);
+ return 0;
+};
+
+// This function consumes ALL Lua stack arguments and returns concatenated
+// message string
+std::string lua_print_msg(lua_State* L, const std::string_view& level)
+{
+ // On top of existing Lua arguments, we're going to push tostring() and
+ // duplicate each existing stack entry so we can stringize each one.
+ luaL_checkstack(L, 2, nullptr);
+ luaL_where(L, 1);
+ // start with the 'where' info at the top of the stack
+ std::ostringstream out;
+ out << lua_tostring(L, -1);
+ lua_pop(L, 1);
+ const char* sep = ""; // 'where' info ends with ": "
+ // now iterate over arbitrary args, calling Lua tostring() on each and
+ // concatenating with separators
+ for (int p = 1, top = lua_gettop(L); p <= top; ++p)
+ {
+ out << sep;
+ sep = " ";
+ // push Lua tostring() function -- note, semantically different from
+ // lua_tostring()!
+ lua_getglobal(L, "tostring");
+ // Now the stack is arguments 1 .. N, plus tostring().
+ // Push a copy of the argument at index p.
+ lua_pushvalue(L, p);
+ // pop tostring() and arg-p, pushing tostring(arg-p)
+ // (ignore potential error code from lua_pcall() because, if there was
+ // an error, we expect the stack top to be an error message -- which
+ // we'll print)
+ lua_pcall(L, 1, 1, 0);
+ out << lua_tostring(L, -1);
+ lua_pop(L, 1);
+ }
+ // pop everything
+ lua_settop(L, 0);
+ // capture message string
+ std::string msg{ out.str() };
+ // put message out there for any interested party (*koff* LLFloaterLUADebug *koff*)
+ LLEventPumps::instance().obtain("lua output").post(stringize(level, ": ", msg));
+
+ llcoro::suspend();
+ return msg;
+}
+
+lua_function(print_debug, "print_debug(args...): DEBUG level logging")
+{
+ LL_DEBUGS("Lua") << lua_print_msg(L, "DEBUG") << LL_ENDL;
+ return 0;
+}
+
+// also used for print(); see LuaState constructor
+lua_function(print_info, "print_info(args...): INFO level logging")
+{
+ LL_INFOS("Lua") << lua_print_msg(L, "INFO") << LL_ENDL;
+ return 0;
+}
+
+lua_function(print_warning, "print_warning(args...): WARNING level logging")
+{
+ LL_WARNS("Lua") << lua_print_msg(L, "WARN") << LL_ENDL;
+ return 0;
+}
+
+lua_function(post_on, "post_on(pumpname, data): post specified data to specified LLEventPump")
+{
+ std::string pumpname{ lua_tostdstring(L, 1) };
+ LLSD data{ lua_tollsd(L, 2) };
+ lua_pop(L, 2);
+ LL_DEBUGS("Lua") << "post_on('" << pumpname << "', " << data << ")" << LL_ENDL;
+ LLEventPumps::instance().obtain(pumpname).post(data);
+ return 0;
+}
+
+lua_function(get_event_pumps,
+ "get_event_pumps():\n"
+ "Returns replypump, commandpump: names of LLEventPumps specific to this chunk.\n"
+ "Events posted to replypump are queued for get_event_next().\n"
+ "post_on(commandpump, ...) to engage LLEventAPI operations (see helpleap()).")
+{
+ luaL_checkstack(L, 2, nullptr);
+ auto listener{ LuaState::obtainListener(L) };
+ // return the reply pump name and the command pump name on caller's lua_State
+ lua_pushstdstring(L, listener->getReplyName());
+ lua_pushstdstring(L, listener->getCommandName());
+ return 2;
+}
+
+lua_function(get_event_next,
+ "get_event_next():\n"
+ "Returns the next (pumpname, data) pair from the replypump whose name\n"
+ "is returned by get_event_pumps(). Blocks the calling chunk until an\n"
+ "event becomes available.")
+{
+ luaL_checkstack(L, 2, nullptr);
+ auto listener{ LuaState::obtainListener(L) };
+ const auto& [pump, data]{ listener->getNext() };
+ lua_pushstdstring(L, pump);
+ lua_pushllsd(L, data);
+ lluau::set_interrupts_counter(L, 0);
+ return 2;
+}
+
+LLCoros::Future<std::pair<int, LLSD>>
+LLLUAmanager::startScriptFile(const std::string& filename)
+{
+ // Despite returning from startScriptFile(), we need this Promise to
+ // remain alive until the callback has fired.
+ auto promise{ std::make_shared<LLCoros::Promise<std::pair<int, LLSD>>>() };
+ runScriptFile(filename,
+ [promise](int count, LLSD result)
+ { promise->set_value({ count, result }); });
+ return LLCoros::getFuture(*promise);
+}
+
+std::pair<int, LLSD> LLLUAmanager::waitScriptFile(const std::string& filename)
+{
+ return startScriptFile(filename).get();
+}
+
+void LLLUAmanager::runScriptFile(const std::string &filename, script_result_fn result_cb, script_finished_fn finished_cb)
+{
+ // A script_result_fn will be called when LuaState::expr() completes.
+ LLCoros::instance().launch(filename, [filename, result_cb, finished_cb]()
+ {
+ ScriptObserver observer(LLCoros::getName(), filename);
+ llifstream in_file;
+ in_file.open(filename.c_str());
+
+ if (in_file.is_open())
+ {
+ // A script_finished_fn is used to initialize the LuaState.
+ // It will be called when the LuaState is destroyed.
+ LuaState L(finished_cb);
+ std::string text{std::istreambuf_iterator<char>(in_file), {}};
+ auto [count, result] = L.expr(filename, text);
+ if (result_cb)
+ {
+ result_cb(count, result);
+ }
+ }
+ else
+ {
+ auto msg{ stringize("unable to open script file '", filename, "'") };
+ LL_WARNS("Lua") << msg << LL_ENDL;
+ if (result_cb)
+ {
+ result_cb(-1, msg);
+ }
+ }
+ });
+}
+
+void LLLUAmanager::runScriptLine(const std::string& chunk, script_finished_fn cb)
+{
+ // A script_finished_fn is used to initialize the LuaState.
+ // It will be called when the LuaState is destroyed.
+ LuaState L(cb);
+ runScriptLine(L, chunk);
+}
+
+void LLLUAmanager::runScriptLine(const std::string& chunk, script_result_fn cb)
+{
+ LuaState L;
+ // A script_result_fn will be called when LuaState::expr() completes.
+ runScriptLine(L, chunk, cb);
+}
+
+LLCoros::Future<std::pair<int, LLSD>>
+LLLUAmanager::startScriptLine(LuaState& L, const std::string& chunk)
+{
+ // Despite returning from startScriptLine(), we need this Promise to
+ // remain alive until the callback has fired.
+ auto promise{ std::make_shared<LLCoros::Promise<std::pair<int, LLSD>>>() };
+ runScriptLine(L, chunk,
+ [promise](int count, LLSD result)
+ { promise->set_value({ count, result }); });
+ return LLCoros::getFuture(*promise);
+}
+
+std::pair<int, LLSD> LLLUAmanager::waitScriptLine(LuaState& L, const std::string& chunk)
+{
+ return startScriptLine(L, chunk).get();
+}
+
+void LLLUAmanager::runScriptLine(LuaState& L, const std::string& chunk, script_result_fn cb)
+{
+ // find a suitable abbreviation for the chunk string
+ std::string shortchunk{ chunk };
+ const size_t shortlen = 40;
+ std::string::size_type eol = shortchunk.find_first_of("\r\n");
+ if (eol != std::string::npos)
+ shortchunk = shortchunk.substr(0, eol);
+ if (shortchunk.length() > shortlen)
+ shortchunk = stringize(shortchunk.substr(0, shortlen), "...");
+
+ std::string desc{ stringize("lua: ", shortchunk) };
+ LLCoros::instance().launch(desc, [&L, desc, chunk, cb]()
+ {
+ auto [count, result] = L.expr(desc, chunk);
+ if (cb)
+ {
+ cb(count, result);
+ }
+ });
+}
+
+void LLLUAmanager::runScriptOnLogin()
+{
+#ifndef LL_TEST
+ std::string filename = gSavedSettings.getString("AutorunLuaScriptName");
+ if (filename.empty())
+ {
+ LL_INFOS() << "Script name wasn't set." << LL_ENDL;
+ return;
+ }
+
+ filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename);
+ if (!gDirUtilp->fileExists(filename))
+ {
+ LL_INFOS() << filename << " was not found." << LL_ENDL;
+ return;
+ }
+
+ runScriptFile(filename);
+#endif // ! LL_TEST
+}
+
+std::string read_file(const std::string &name)
+{
+ llifstream in_file;
+ in_file.open(name.c_str());
+
+ if (in_file.is_open())
+ {
+ return std::string{std::istreambuf_iterator<char>(in_file), {}};
+ }
+
+ return {};
+}
+
+lua_function(require, "require(module_name) : load module_name.lua from known places")
+{
+ std::string name = lua_tostdstring(L, 1);
+ lua_pop(L, 1);
+
+ // resolveRequire() does not return in case of error.
+ LLRequireResolver::resolveRequire(L, name);
+
+ // resolveRequire() returned the newly-loaded module on the stack top.
+ // Return it.
+ return 1;
+}
+
+// push loaded module or throw Lua error
+void LLRequireResolver::resolveRequire(lua_State *L, std::string path)
+{
+ LLRequireResolver resolver(L, std::move(path));
+ // findModule() pushes the loaded module or throws a Lua error.
+ resolver.findModule();
+}
+
+LLRequireResolver::LLRequireResolver(lua_State *L, const std::string& path) :
+ mPathToResolve(fsyspath(path).lexically_normal()),
+ L(L)
+{
+ mSourceDir = lluau::source_path(L).parent_path();
+
+ if (mPathToResolve.is_absolute())
+ luaL_argerrorL(L, 1, "cannot require a full path");
+}
+
+/**
+ * Remove a particular stack index on exit from enclosing scope.
+ * If you pass a negative index (meaning relative to the current stack top),
+ * converts to an absolute index. The point of LuaRemover is to remove the
+ * entry at the specified index regardless of subsequent pushes to the stack.
+ */
+class LuaRemover
+{
+public:
+ LuaRemover(lua_State* L, int index):
+ mState(L),
+ mIndex(lua_absindex(L, index))
+ {}
+ LuaRemover(const LuaRemover&) = delete;
+ LuaRemover& operator=(const LuaRemover&) = delete;
+ ~LuaRemover()
+ {
+ lua_remove(mState, mIndex);
+ }
+
+private:
+ lua_State* mState;
+ int mIndex;
+};
+
+// push the loaded module or throw a Lua error
+void LLRequireResolver::findModule()
+{
+ // If mPathToResolve is absolute, this replaces mSourceDir.
+ auto absolutePath = (mSourceDir / mPathToResolve).u8string();
+
+ // Push _MODULES table on stack for checking and saving to the cache
+ luaL_findtable(L, LUA_REGISTRYINDEX, "_MODULES", 1);
+ // Remove that stack entry no matter how we exit
+ LuaRemover rm_MODULES(L, -1);
+
+ // Check if the module is already in _MODULES table, read from file
+ // otherwise.
+ // findModuleImpl() pushes module if found, nothing if not, may throw Lua
+ // error.
+ if (findModuleImpl(absolutePath))
+ return;
+
+ // not already cached - prep error message just in case
+ auto fail{
+ [L=L, path=mPathToResolve.u8string()]()
+ { luaL_error(L, "could not find require('%s')", path.data()); }};
+
+ if (mPathToResolve.is_absolute())
+ {
+ // no point searching known directories for an absolute path
+ fail();
+ }
+
+ std::vector<fsyspath> lib_paths
+ {
+ gDirUtilp->getExpandedFilename(LL_PATH_SCRIPTS, "lua"),
+#ifdef LL_TEST
+ // Build-time tests don't have the app bundle - use source tree.
+ fsyspath(__FILE__).parent_path() / "scripts" / "lua",
+#endif
+ };
+
+ for (const auto& path : lib_paths)
+ {
+ std::string absolutePathOpt = (path / mPathToResolve).u8string();
+
+ if (absolutePathOpt.empty())
+ luaL_error(L, "error requiring module '%s'", mPathToResolve.u8string().data());
+
+ if (findModuleImpl(absolutePathOpt))
+ return;
+ }
+
+ // not found
+ fail();
+}
+
+// expects _MODULES table on stack top (and leaves it there)
+// - if found, pushes loaded module and returns true
+// - not found, pushes nothing and returns false
+// - may throw Lua error
+bool LLRequireResolver::findModuleImpl(const std::string& absolutePath)
+{
+ std::string possibleSuffixedPaths[] = {absolutePath + ".luau", absolutePath + ".lua"};
+
+ for (const auto& suffixedPath : possibleSuffixedPaths)
+ {
+ // Check _MODULES cache for module
+ lua_getfield(L, -1, suffixedPath.data());
+ if (!lua_isnil(L, -1))
+ {
+ return true;
+ }
+ lua_pop(L, 1);
+
+ // Try to read the matching file
+ std::string source = read_file(suffixedPath);
+ if (!source.empty())
+ {
+ // Try to run the loaded source. This will leave either a string
+ // error message or the module contents on the stack top.
+ runModule(suffixedPath, source);
+
+ // If the stack top is an error message string, raise it.
+ if (lua_isstring(L, -1))
+ lua_error(L);
+
+ // duplicate the new module: _MODULES newmodule newmodule
+ lua_pushvalue(L, -1);
+ // store _MODULES[found path] = newmodule
+ lua_setfield(L, -3, suffixedPath.data());
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// push string error message or new module
+void LLRequireResolver::runModule(const std::string& desc, const std::string& code)
+{
+ // Here we just loaded a new module 'code', need to run it and get its result.
+ // Module needs to run in a new thread, isolated from the rest.
+ // Note: we create ML on main thread so that it doesn't inherit environment of L.
+ lua_State *GL = lua_mainthread(L);
+// lua_State *ML = lua_newthread(GL);
+ // Try loading modules on Lua's main thread instead.
+ lua_State *ML = GL;
+ // lua_newthread() pushed the new thread object on GL's stack. Move to L's.
+// lua_xmove(GL, L, 1);
+
+ // new thread needs to have the globals sandboxed
+// luaL_sandboxthread(ML);
+
+ {
+ // If loadstring() returns (! LUA_OK) then there's an error message on
+ // the stack. If it returns LUA_OK then the newly-loaded module code
+ // is on the stack.
+ if (lluau::loadstring(ML, desc, code) == LUA_OK)
+ {
+ // luau uses Lua 5.3's version of lua_resume():
+ // run the coroutine on ML, "from" L, passing no arguments.
+// int status = lua_resume(ML, L, 0);
+ // we expect one return value
+ int status = lua_pcall(ML, 0, 1, 0);
+
+ if (status == LUA_OK)
+ {
+ if (lua_gettop(ML) == 0)
+ lua_pushfstring(ML, "module %s must return a value", desc.data());
+ else if (!lua_istable(ML, -1) && !lua_isfunction(ML, -1))
+ lua_pushfstring(ML, "module %s must return a table or function, not %s",
+ desc.data(), lua_typename(ML, lua_type(ML, -1)));
+ }
+ else if (status == LUA_YIELD)
+ {
+ lua_pushfstring(ML, "module %s can not yield", desc.data());
+ }
+ else if (!lua_isstring(ML, -1))
+ {
+ lua_pushfstring(ML, "unknown error while running module %s", desc.data());
+ }
+ }
+ }
+ // There's now a return value (string error message or module) on top of ML.
+ // Move return value to L's stack.
+ if (ML != L)
+ {
+ lua_xmove(ML, L, 1);
+ }
+ // remove ML from L's stack
+// lua_remove(L, -2);
+// // DON'T call lua_close(ML)! Since ML is only a thread of L, corrupts L too!
+// lua_close(ML);
+}
diff --git a/indra/newview/llluamanager.h b/indra/newview/llluamanager.h
new file mode 100644
index 0000000000..af9dcf70c2
--- /dev/null
+++ b/indra/newview/llluamanager.h
@@ -0,0 +1,124 @@
+/**
+ * @file llluamanager.h
+ * @brief classes and functions for interfacing with LUA.
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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_LLLUAMANAGER_H
+#define LL_LLLUAMANAGER_H
+
+#include "fsyspath.h"
+#include "llcoros.h"
+#include "llsd.h"
+#include <functional>
+#include <string>
+#include <utility> // std::pair
+
+#include "luau/lua.h"
+#include "luau/lualib.h"
+
+class LuaState;
+
+class LLLUAmanager
+{
+ friend class ScriptObserver;
+
+public:
+ // Pass a callback with this signature to obtain the error message, if
+ // any, from running a script or source string. Empty msg means success.
+ typedef std::function<void(std::string msg)> script_finished_fn;
+ // Pass a callback with this signature to obtain the result, if any, of
+ // running a script or source string.
+ // count < 0 means error, and result.asString() is the error message.
+ // count == 0 with result.isUndefined() means the script returned no results.
+ // count == 1 means the script returned one result.
+ // count > 1 with result.isArray() means the script returned multiple
+ // results, represented as the entries of the result array.
+ typedef std::function<void(int count, const LLSD& result)> script_result_fn;
+
+ static void runScriptFile(const std::string &filename, script_result_fn result_cb = {}, script_finished_fn finished_cb = {});
+ // Start running a Lua script file, returning an LLCoros::Future whose
+ // get() method will pause the calling coroutine until it can deliver the
+ // (count, result) pair described above. Between startScriptFile() and
+ // Future::get(), the caller and the Lua script coroutine will run
+ // concurrently.
+ static LLCoros::Future<std::pair<int, LLSD>>
+ startScriptFile(const std::string& filename);
+ // Run a Lua script file, and pause the calling coroutine until it completes.
+ // The return value is the (count, result) pair described above.
+ static std::pair<int, LLSD> waitScriptFile(const std::string& filename);
+
+ static void runScriptLine(const std::string &chunk, script_finished_fn cb = {});
+ static void runScriptLine(const std::string &chunk, script_result_fn cb);
+ static void runScriptLine(LuaState& L, const std::string &chunk, script_result_fn cb = {});
+ // Start running a Lua chunk, returning an LLCoros::Future whose
+ // get() method will pause the calling coroutine until it can deliver the
+ // (count, result) pair described above. Between startScriptLine() and
+ // Future::get(), the caller and the Lua script coroutine will run
+ // concurrently.
+ static LLCoros::Future<std::pair<int, LLSD>>
+ startScriptLine(LuaState& L, const std::string& chunk);
+ // Run a Lua chunk, and pause the calling coroutine until it completes.
+ // The return value is the (count, result) pair described above.
+ static std::pair<int, LLSD> waitScriptLine(LuaState& L, const std::string& chunk);
+
+ static void runScriptOnLogin();
+
+ static const std::map<std::string, std::string> getScriptNames() { return sScriptNames; }
+
+ private:
+ static std::map<std::string, std::string> sScriptNames;
+};
+
+class LLRequireResolver
+{
+ public:
+ static void resolveRequire(lua_State *L, std::string path);
+
+ private:
+ fsyspath mPathToResolve;
+ fsyspath mSourceDir;
+
+ LLRequireResolver(lua_State *L, const std::string& path);
+
+ void findModule();
+ lua_State *L;
+
+ bool findModuleImpl(const std::string& absolutePath);
+ void runModule(const std::string& desc, const std::string& code);
+};
+
+// RAII class to guarantee that a script entry is erased even when coro is terminated
+class ScriptObserver
+{
+ public:
+ ScriptObserver(const std::string &coro_name, const std::string &filename) : mCoroName(coro_name)
+ {
+ LLLUAmanager::sScriptNames[mCoroName] = filename;
+ }
+ ~ScriptObserver() { LLLUAmanager::sScriptNames.erase(mCoroName); }
+
+ private:
+ std::string mCoroName;
+};
+#endif
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 4ad0228bd0..a8ba75ab5f 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstartup.cpp
* @brief startup routines.
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -31,9 +31,9 @@
#include "llcallstack.h"
#if LL_WINDOWS
-# include <process.h> // _spawnl()
+# include <process.h> // _spawnl()
#else
-# include <sys/stat.h> // mkdir()
+# include <sys/stat.h> // mkdir()
#endif
#include <memory> // std::unique_ptr
@@ -84,7 +84,7 @@
#include "llversioninfo.h"
#include "llviewercontrol.h"
#include "llviewerhelp.h"
-#include "llxorcipher.h" // saved password, MAC address
+#include "llxorcipher.h" // saved password, MAC address
#include "llwindow.h"
#include "message.h"
#include "v3math.h"
@@ -121,7 +121,7 @@
#include "llinventorymodel.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llkeyboard.h"
-#include "llloginhandler.h" // gLoginHandler, SLURL support
+#include "llloginhandler.h" // gLoginHandler, SLURL support
#include "lllogininstance.h" // Host the login module.
#include "llpanellogin.h"
#include "llmutelist.h"
@@ -138,7 +138,7 @@
#include "llselectmgr.h"
#include "llsky.h"
#include "llstatview.h"
-#include "llstatusbar.h" // sendMoneyBalanceRequest(), owns L$ balance
+#include "llstatusbar.h" // sendMoneyBalanceRequest(), owns L$ balance
#include "llsurface.h"
#include "lltexturecache.h"
#include "lltexturefetch.h"
@@ -208,6 +208,7 @@
#include "llstacktrace.h"
#include "threadpool.h"
+#include "llluamanager.h"
#include "llperfstats.h"
@@ -236,7 +237,7 @@ extern S32 gStartImageHeight;
//
static bool gGotUseCircuitCodeAck = false;
static std::string sInitialOutfit;
-static std::string sInitialOutfitGender; // "male" or "female"
+static std::string sInitialOutfitGender; // "male" or "female"
static bool gUseCircuitCallbackCalled = false;
@@ -290,12 +291,12 @@ void transition_back_to_login_panel(const std::string& emsg);
void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is_group)
{
- LLNameBox::refreshAll(id, full_name, is_group);
- LLNameEditor::refreshAll(id, full_name, is_group);
-
- // TODO: Actually be intelligent about the refresh.
- // For now, just brute force refresh the dialogs.
- dialog_refresh_all();
+ LLNameBox::refreshAll(id, full_name, is_group);
+ LLNameEditor::refreshAll(id, full_name, is_group);
+
+ // TODO: Actually be intelligent about the refresh.
+ // For now, just brute force refresh the dialogs.
+ dialog_refresh_all();
}
//
@@ -320,10 +321,10 @@ void pump_idle_startup_network(void)
//
void update_texture_fetch()
{
- LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
- LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
- LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
- gTextureList.updateImages(0.10f);
+ LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
+ LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
+ LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
+ gTextureList.updateImages(0.10f);
if (LLImageGLThread::sEnabledTextures)
{
@@ -334,8 +335,8 @@ void update_texture_fetch()
void set_flags_and_update_appearance()
{
- LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
- LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op);
+ LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
+ LLAppearanceMgr::instance().updateAppearanceFromCOF(true, true, no_op);
LLInventoryModelBackgroundFetch::instance().start();
}
@@ -344,310 +345,310 @@ void set_flags_and_update_appearance()
// true when all initialization done.
bool idle_startup()
{
- if (gViewerWindow == NULL)
- {
- // We expect window to be initialized
- LL_WARNS_ONCE() << "gViewerWindow is not initialized" << LL_ENDL;
- return false; // No world yet
- }
-
- const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay");
- static LLTimer timeout;
-
- static LLTimer login_time;
-
- // until this is encapsulated, this little hack for the
- // auth/transform loop will do.
- static F32 progress = 0.10f;
-
- static std::string auth_desc;
- static std::string auth_message;
-
- static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server
-
- // last location by default
- static S32 agent_location_id = START_LOCATION_ID_LAST;
-
- static bool show_connect_box = true;
-
- //static bool stipend_since_login = false;
-
- // HACK: These are things from the main loop that usually aren't done
- // until initialization is complete, but need to be done here for things
- // to work.
- gIdleCallbacks.callFunctions();
- gViewerWindow->updateUI();
-
- LLMortician::updateClass();
-
- const std::string delims (" ");
- std::string system;
- int begIdx, endIdx;
- std::string osString = LLOSInfo::instance().getOSStringSimple();
-
- begIdx = osString.find_first_not_of (delims);
- endIdx = osString.find_first_of (delims, begIdx);
- system = osString.substr (begIdx, endIdx - begIdx);
- system += "Locale";
-
- LLStringUtil::setLocale (LLTrans::getString(system));
-
- //note: Removing this line will cause incorrect button size in the login screen. -- bao.
- gTextureList.updateImages(0.01f) ;
-
- if ( STATE_FIRST == LLStartUp::getStartupState() )
- {
- static bool first_call = true;
- if (first_call)
- {
- // Other phases get handled when startup state changes,
- // need to capture the initial state as well.
- LLStartUp::getPhases().startPhase(LLStartUp::getStartupStateString());
- first_call = false;
- }
-
- gViewerWindow->showCursor();
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
-
- /////////////////////////////////////////////////
- //
- // Initialize stuff that doesn't need data from simulators
- //
- std::string lastGPU = gSavedSettings.getString("LastGPUString");
- std::string thisGPU = LLFeatureManager::getInstance()->getGPUString();
-
- if (LLFeatureManager::getInstance()->isSafe())
- {
- LLNotificationsUtil::add("DisplaySetToSafe");
- }
- else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) &&
- (gSavedSettings.getS32("LastFeatureVersion") != 0))
- {
- LLNotificationsUtil::add("DisplaySetToRecommendedFeatureChange");
- }
- else if ( ! lastGPU.empty() && (lastGPU != thisGPU))
- {
- LLSD subs;
- subs["LAST_GPU"] = lastGPU;
- subs["THIS_GPU"] = thisGPU;
- LLNotificationsUtil::add("DisplaySetToRecommendedGPUChange", subs);
- }
- else if (!gViewerWindow->getInitAlert().empty())
- {
- LLNotificationsUtil::add(gViewerWindow->getInitAlert());
- }
-
- //-------------------------------------------------
- // Init the SOCKS 5 proxy if the user has configured
- // one. We need to do this early in case the user
- // is using SOCKS for HTTP so we get the login
- // screen and HTTP tables via SOCKS.
- //-------------------------------------------------
- LLStartUp::startLLProxy();
-
- gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion());
- gSavedSettings.setString("LastGPUString", thisGPU);
-
-
- std::string xml_file = LLUI::locateSkin("xui_version.xml");
- LLXMLNodePtr root;
- bool xml_ok = false;
- if (LLXMLNode::parseFile(xml_file, root, NULL))
- {
- if( (root->hasName("xui_version") ) )
- {
- std::string value = root->getValue();
- F32 version = 0.0f;
- LLStringUtil::convertToF32(value, version);
- if (version >= 1.0f)
- {
- xml_ok = true;
- }
- }
- }
- if (!xml_ok)
- {
- // If XML is bad, there's a good possibility that notifications.xml is ALSO bad.
- // If that's so, then we'll get a fatal error on attempting to load it,
- // which will display a nontranslatable error message that says so.
- // Otherwise, we'll display a reasonable error message that IS translatable.
- LLAppViewer::instance()->earlyExit("BadInstallation");
- }
- //
- // Statistics stuff
- //
-
- // Load autopilot and stats stuff
- gAgentPilot.load();
-
- //gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps"));
-
- // Load the throttle settings
- gViewerThrottle.load();
-
- //
- // Initialize messaging system
- //
- LL_DEBUGS("AppInit") << "Initializing messaging system..." << LL_ENDL;
-
- std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg");
-
- LLFILE* found_template = NULL;
- found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */
-
- #if LL_WINDOWS
- // On the windows dev builds, unpackaged, the message_template.msg
- // file will be located in:
- // build-vc**/newview/<config>/app_settings
- if (!found_template)
- {
- message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg");
- found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */
- }
- #elif LL_DARWIN
- // On Mac dev builds, message_template.msg lives in:
- // indra/build-*/newview/<config>/Second Life/Contents/Resources/app_settings
- if (!found_template)
- {
- message_template_path =
- gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
- "message_template.msg");
- found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */
- }
- #endif
-
- if (found_template)
- {
- fclose(found_template);
-
- U32 port = gSavedSettings.getU32("UserConnectionPort");
-
- if ((NET_USE_OS_ASSIGNED_PORT == port) && // if nothing specified on command line (-port)
- (gSavedSettings.getBOOL("ConnectionPortEnabled")))
- {
- port = gSavedSettings.getU32("ConnectionPort");
- }
-
- // TODO parameterize
- const F32 circuit_heartbeat_interval = 5;
- const F32 circuit_timeout = 100;
-
- const LLUseCircuitCodeResponder* responder = NULL;
- bool failure_is_fatal = true;
-
- if(!start_messaging_system(
- message_template_path,
- port,
- LLVersionInfo::instance().getMajor(),
- LLVersionInfo::instance().getMinor(),
- LLVersionInfo::instance().getPatch(),
- FALSE,
- std::string(),
- responder,
- failure_is_fatal,
- circuit_heartbeat_interval,
- circuit_timeout))
- {
- std::string diagnostic = llformat(" Error: %d", gMessageSystem->getErrorCode());
- LL_WARNS("AppInit") << diagnostic << LL_ENDL;
- LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic));
- }
-
- #if LL_WINDOWS
- // On the windows dev builds, unpackaged, the message.xml file will
- // be located in indra/build-vc**/newview/<config>/app_settings.
- std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml");
-
- if (!LLFile::isfile(message_path.c_str()))
- {
- LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", ""));
- }
- else
- {
- LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
- }
- #else
- LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
- #endif
-
- }
- else
- {
- LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().with("PATH", message_template_path));
- }
-
- if(gMessageSystem && gMessageSystem->isOK())
- {
- // Initialize all of the callbacks in case of bad message
- // system data
- LLMessageSystem* msg = gMessageSystem;
- msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE,
- invalid_message_callback,
- NULL);
- msg->setExceptionFunc(MX_PACKET_TOO_SHORT,
- invalid_message_callback,
- NULL);
-
- // running off end of a packet is now valid in the case
- // when a reader has a newer message template than
- // the sender
- /*msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET,
- invalid_message_callback,
- NULL);*/
- msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE,
- invalid_message_callback,
- NULL);
-
- if (gSavedSettings.getBOOL("LogMessages"))
- {
- LL_DEBUGS("AppInit") << "Message logging activated!" << LL_ENDL;
- msg->startLogging();
- }
-
- // start the xfer system. by default, choke the downloads
- // a lot...
- const S32 VIEWER_MAX_XFER = 3;
- start_xfer_manager();
- gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER);
- F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle");
- if (xfer_throttle_bps > 1.f)
- {
- gXferManager->setUseAckThrottling(TRUE);
- gXferManager->setAckThrottleBPS(xfer_throttle_bps);
- }
- gAssetStorage = new LLViewerAssetStorage(msg, gXferManager);
-
-
- F32 dropPercent = gSavedSettings.getF32("PacketDropPercentage");
- msg->mPacketRing.setDropPercentage(dropPercent);
-
- F32 inBandwidth = gSavedSettings.getF32("InBandwidth");
- F32 outBandwidth = gSavedSettings.getF32("OutBandwidth");
- if (inBandwidth != 0.f)
- {
- LL_DEBUGS("AppInit") << "Setting packetring incoming bandwidth to " << inBandwidth << LL_ENDL;
- msg->mPacketRing.setUseInThrottle(TRUE);
- msg->mPacketRing.setInBandwidth(inBandwidth);
- }
- if (outBandwidth != 0.f)
- {
- LL_DEBUGS("AppInit") << "Setting packetring outgoing bandwidth to " << outBandwidth << LL_ENDL;
- msg->mPacketRing.setUseOutThrottle(TRUE);
- msg->mPacketRing.setOutBandwidth(outBandwidth);
- }
- }
-
- LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL;
-
- //-------------------------------------------------
- // Init audio, which may be needed for prefs dialog
- // or audio cues in connection UI.
- //-------------------------------------------------
-
- if (FALSE == gSavedSettings.getBOOL("NoAudio"))
- {
- delete gAudiop;
- gAudiop = NULL;
+ if (gViewerWindow == NULL)
+ {
+ // We expect window to be initialized
+ LL_WARNS_ONCE() << "gViewerWindow is not initialized" << LL_ENDL;
+ return false; // No world yet
+ }
+
+ const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay");
+ static LLTimer timeout;
+
+ static LLTimer login_time;
+
+ // until this is encapsulated, this little hack for the
+ // auth/transform loop will do.
+ static F32 progress = 0.10f;
+
+ static std::string auth_desc;
+ static std::string auth_message;
+
+ static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server
+
+ // last location by default
+ static S32 agent_location_id = START_LOCATION_ID_LAST;
+
+ static bool show_connect_box = true;
+
+ //static bool stipend_since_login = false;
+
+ // HACK: These are things from the main loop that usually aren't done
+ // until initialization is complete, but need to be done here for things
+ // to work.
+ gIdleCallbacks.callFunctions();
+ gViewerWindow->updateUI();
+
+ LLMortician::updateClass();
+
+ const std::string delims (" ");
+ std::string system;
+ int begIdx, endIdx;
+ std::string osString = LLOSInfo::instance().getOSStringSimple();
+
+ begIdx = osString.find_first_not_of (delims);
+ endIdx = osString.find_first_of (delims, begIdx);
+ system = osString.substr (begIdx, endIdx - begIdx);
+ system += "Locale";
+
+ LLStringUtil::setLocale (LLTrans::getString(system));
+
+ //note: Removing this line will cause incorrect button size in the login screen. -- bao.
+ gTextureList.updateImages(0.01f) ;
+
+ if ( STATE_FIRST == LLStartUp::getStartupState() )
+ {
+ static bool first_call = true;
+ if (first_call)
+ {
+ // Other phases get handled when startup state changes,
+ // need to capture the initial state as well.
+ LLStartUp::getPhases().startPhase(LLStartUp::getStartupStateString());
+ first_call = false;
+ }
+
+ gViewerWindow->showCursor();
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
+
+ /////////////////////////////////////////////////
+ //
+ // Initialize stuff that doesn't need data from simulators
+ //
+ std::string lastGPU = gSavedSettings.getString("LastGPUString");
+ std::string thisGPU = LLFeatureManager::getInstance()->getGPUString();
+
+ if (LLFeatureManager::getInstance()->isSafe())
+ {
+ LLNotificationsUtil::add("DisplaySetToSafe");
+ }
+ else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) &&
+ (gSavedSettings.getS32("LastFeatureVersion") != 0))
+ {
+ LLNotificationsUtil::add("DisplaySetToRecommendedFeatureChange");
+ }
+ else if ( ! lastGPU.empty() && (lastGPU != thisGPU))
+ {
+ LLSD subs;
+ subs["LAST_GPU"] = lastGPU;
+ subs["THIS_GPU"] = thisGPU;
+ LLNotificationsUtil::add("DisplaySetToRecommendedGPUChange", subs);
+ }
+ else if (!gViewerWindow->getInitAlert().empty())
+ {
+ LLNotificationsUtil::add(gViewerWindow->getInitAlert());
+ }
+
+ //-------------------------------------------------
+ // Init the SOCKS 5 proxy if the user has configured
+ // one. We need to do this early in case the user
+ // is using SOCKS for HTTP so we get the login
+ // screen and HTTP tables via SOCKS.
+ //-------------------------------------------------
+ LLStartUp::startLLProxy();
+
+ gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion());
+ gSavedSettings.setString("LastGPUString", thisGPU);
+
+
+ std::string xml_file = LLUI::locateSkin("xui_version.xml");
+ LLXMLNodePtr root;
+ bool xml_ok = false;
+ if (LLXMLNode::parseFile(xml_file, root, NULL))
+ {
+ if( (root->hasName("xui_version") ) )
+ {
+ std::string value = root->getValue();
+ F32 version = 0.0f;
+ LLStringUtil::convertToF32(value, version);
+ if (version >= 1.0f)
+ {
+ xml_ok = true;
+ }
+ }
+ }
+ if (!xml_ok)
+ {
+ // If XML is bad, there's a good possibility that notifications.xml is ALSO bad.
+ // If that's so, then we'll get a fatal error on attempting to load it,
+ // which will display a nontranslatable error message that says so.
+ // Otherwise, we'll display a reasonable error message that IS translatable.
+ LLAppViewer::instance()->earlyExit("BadInstallation");
+ }
+ //
+ // Statistics stuff
+ //
+
+ // Load autopilot and stats stuff
+ gAgentPilot.load();
+
+ //gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps"));
+
+ // Load the throttle settings
+ gViewerThrottle.load();
+
+ //
+ // Initialize messaging system
+ //
+ LL_DEBUGS("AppInit") << "Initializing messaging system..." << LL_ENDL;
+
+ std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg");
+
+ LLFILE* found_template = NULL;
+ found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */
+
+ #if LL_WINDOWS
+ // On the windows dev builds, unpackaged, the message_template.msg
+ // file will be located in:
+ // build-vc**/newview/<config>/app_settings
+ if (!found_template)
+ {
+ message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg");
+ found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */
+ }
+ #elif LL_DARWIN
+ // On Mac dev builds, message_template.msg lives in:
+ // indra/build-*/newview/<config>/Second Life/Contents/Resources/app_settings
+ if (!found_template)
+ {
+ message_template_path =
+ gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
+ "message_template.msg");
+ found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */
+ }
+ #endif
+
+ if (found_template)
+ {
+ fclose(found_template);
+
+ U32 port = gSavedSettings.getU32("UserConnectionPort");
+
+ if ((NET_USE_OS_ASSIGNED_PORT == port) && // if nothing specified on command line (-port)
+ (gSavedSettings.getBOOL("ConnectionPortEnabled")))
+ {
+ port = gSavedSettings.getU32("ConnectionPort");
+ }
+
+ // TODO parameterize
+ const F32 circuit_heartbeat_interval = 5;
+ const F32 circuit_timeout = 100;
+
+ const LLUseCircuitCodeResponder* responder = NULL;
+ bool failure_is_fatal = true;
+
+ if(!start_messaging_system(
+ message_template_path,
+ port,
+ LLVersionInfo::instance().getMajor(),
+ LLVersionInfo::instance().getMinor(),
+ LLVersionInfo::instance().getPatch(),
+ FALSE,
+ std::string(),
+ responder,
+ failure_is_fatal,
+ circuit_heartbeat_interval,
+ circuit_timeout))
+ {
+ std::string diagnostic = llformat(" Error: %d", gMessageSystem->getErrorCode());
+ LL_WARNS("AppInit") << diagnostic << LL_ENDL;
+ LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic));
+ }
+
+ #if LL_WINDOWS
+ // On the windows dev builds, unpackaged, the message.xml file will
+ // be located in indra/build-vc**/newview/<config>/app_settings.
+ std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml");
+
+ if (!LLFile::isfile(message_path.c_str()))
+ {
+ LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", ""));
+ }
+ else
+ {
+ LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+ }
+ #else
+ LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+ #endif
+
+ }
+ else
+ {
+ LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().with("PATH", message_template_path));
+ }
+
+ if(gMessageSystem && gMessageSystem->isOK())
+ {
+ // Initialize all of the callbacks in case of bad message
+ // system data
+ LLMessageSystem* msg = gMessageSystem;
+ msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE,
+ invalid_message_callback,
+ NULL);
+ msg->setExceptionFunc(MX_PACKET_TOO_SHORT,
+ invalid_message_callback,
+ NULL);
+
+ // running off end of a packet is now valid in the case
+ // when a reader has a newer message template than
+ // the sender
+ /*msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET,
+ invalid_message_callback,
+ NULL);*/
+ msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE,
+ invalid_message_callback,
+ NULL);
+
+ if (gSavedSettings.getBOOL("LogMessages"))
+ {
+ LL_DEBUGS("AppInit") << "Message logging activated!" << LL_ENDL;
+ msg->startLogging();
+ }
+
+ // start the xfer system. by default, choke the downloads
+ // a lot...
+ const S32 VIEWER_MAX_XFER = 3;
+ start_xfer_manager();
+ gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER);
+ F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle");
+ if (xfer_throttle_bps > 1.f)
+ {
+ gXferManager->setUseAckThrottling(TRUE);
+ gXferManager->setAckThrottleBPS(xfer_throttle_bps);
+ }
+ gAssetStorage = new LLViewerAssetStorage(msg, gXferManager);
+
+
+ F32 dropPercent = gSavedSettings.getF32("PacketDropPercentage");
+ msg->mPacketRing.setDropPercentage(dropPercent);
+
+ F32 inBandwidth = gSavedSettings.getF32("InBandwidth");
+ F32 outBandwidth = gSavedSettings.getF32("OutBandwidth");
+ if (inBandwidth != 0.f)
+ {
+ LL_DEBUGS("AppInit") << "Setting packetring incoming bandwidth to " << inBandwidth << LL_ENDL;
+ msg->mPacketRing.setUseInThrottle(TRUE);
+ msg->mPacketRing.setInBandwidth(inBandwidth);
+ }
+ if (outBandwidth != 0.f)
+ {
+ LL_DEBUGS("AppInit") << "Setting packetring outgoing bandwidth to " << outBandwidth << LL_ENDL;
+ msg->mPacketRing.setUseOutThrottle(TRUE);
+ msg->mPacketRing.setOutBandwidth(outBandwidth);
+ }
+ }
+
+ LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL;
+
+ //-------------------------------------------------
+ // Init audio, which may be needed for prefs dialog
+ // or audio cues in connection UI.
+ //-------------------------------------------------
+
+ if (FALSE == gSavedSettings.getBOOL("NoAudio"))
+ {
+ delete gAudiop;
+ gAudiop = NULL;
#ifdef LL_FMODSTUDIO
#if !LL_WINDOWS
@@ -660,262 +661,262 @@ bool idle_startup()
#ifdef LL_OPENAL
#if !LL_WINDOWS
- if (NULL == getenv("LL_BAD_OPENAL_DRIVER"))
+ if (NULL == getenv("LL_BAD_OPENAL_DRIVER"))
#endif // !LL_WINDOWS
- {
- gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL();
- }
+ {
+ gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL();
+ }
#endif
-
- if (gAudiop)
- {
+
+ if (gAudiop)
+ {
#if LL_WINDOWS
- // FMOD Ex on Windows needs the window handle to stop playing audio
- // when window is minimized. JC
- void* window_handle = (HWND)gViewerWindow->getPlatformWindow();
+ // FMOD Ex on Windows needs the window handle to stop playing audio
+ // when window is minimized. JC
+ void* window_handle = (HWND)gViewerWindow->getPlatformWindow();
#else
- void* window_handle = NULL;
+ void* window_handle = NULL;
#endif
- if (gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle()))
- {
- if (FALSE == gSavedSettings.getBOOL("UseMediaPluginsForStreamingAudio"))
- {
- LL_INFOS("AppInit") << "Using default impl to render streaming audio" << LL_ENDL;
- gAudiop->setStreamingAudioImpl(gAudiop->createDefaultStreamingAudioImpl());
- }
-
- // if the audio engine hasn't set up its own preferred handler for streaming audio
- // then set up the generic streaming audio implementation which uses media plugins
- if (NULL == gAudiop->getStreamingAudioImpl())
- {
- LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL;
- gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins());
- }
-
- gAudiop->setMuted(TRUE);
- }
- else
- {
- LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL;
- delete gAudiop;
- gAudiop = NULL;
- }
- }
- }
-
- LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL;
-
- if (LLTimer::knownBadTimer())
- {
- LL_WARNS("AppInit") << "Unreliable timers detected (may be bad PCI chipset)!!" << LL_ENDL;
- }
-
- //
- // Log on to system
- //
- if (gUserCredential.isNull())
- {
- gUserCredential = gLoginHandler.initializeLoginInfo();
- }
- // Previous initializeLoginInfo may have generated user credentials. Re-check them.
- if (gUserCredential.isNull())
- {
- show_connect_box = TRUE;
- }
- else if (gSavedSettings.getBOOL("AutoLogin"))
- {
- // Log into last account
- gRememberPassword = true;
- gRememberUser = true;
- gSavedSettings.setBOOL("RememberPassword", TRUE);
- gSavedSettings.setBOOL("RememberUser", TRUE);
- show_connect_box = false;
- }
- else if (gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
- {
- // Console provided login&password
- gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
- gRememberUser = gSavedSettings.getBOOL("RememberUser");
- show_connect_box = false;
- }
- else
- {
- gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
- gRememberUser = gSavedSettings.getBOOL("RememberUser");
- show_connect_box = TRUE;
- }
-
- //setup map of datetime strings to codes and slt & local time offset from utc
- // *TODO: Does this need to be here?
- LLStringOps::setupDatetimeInfo(false);
-
- // Go to the next startup state
- LLStartUp::setStartupState( STATE_BROWSER_INIT );
- return FALSE;
- }
-
-
- if (STATE_BROWSER_INIT == LLStartUp::getStartupState())
- {
- LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL;
- std::string msg = LLTrans::getString("LoginInitializingBrowser");
- set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str());
- display_startup();
- // LLViewerMedia::initBrowser();
- LLStartUp::setStartupState( STATE_LOGIN_SHOW );
- return FALSE;
- }
-
-
- if (STATE_LOGIN_SHOW == LLStartUp::getStartupState())
- {
- LL_DEBUGS("AppInit") << "Initializing Window, show_connect_box = "
- << show_connect_box << LL_ENDL;
-
- // if we've gone backwards in the login state machine, to this state where we show the UI
- // AND the debug setting to exit in this case is true, then go ahead and bail quickly
- if ( mLoginStatePastUI && gSavedSettings.getBOOL("QuitOnLoginActivated") )
- {
- LL_DEBUGS("AppInit") << "taking QuitOnLoginActivated exit" << LL_ENDL;
- // no requirement for notification here - just exit
- LLAppViewer::instance()->earlyExitNoNotify();
- }
-
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
-
- // Login screen needs menus for preferences, but we can enter
- // this startup phase more than once.
- if (gLoginMenuBarView == NULL)
- {
- LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL;
- initialize_spellcheck_menu();
- init_menus();
- }
- show_release_notes_if_required();
-
- if (show_connect_box)
- {
- LL_DEBUGS("AppInit") << "show_connect_box on" << LL_ENDL;
- // Load all the name information out of the login view
- // NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't
- // show the login view until login_show() is called below.
- if (gUserCredential.isNull())
- {
- LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL;
- gUserCredential = gLoginHandler.initializeLoginInfo();
- }
- // Make sure the process dialog doesn't hide things
- gViewerWindow->setShowProgress(FALSE);
- // Show the login dialog
- login_show();
- // connect dialog is already shown, so fill in the names
- LLPanelLogin::populateFields( gUserCredential, gRememberUser, gRememberPassword);
- LLPanelLogin::giveFocus();
-
- // MAINT-3231 Show first run dialog only for Desura viewer
- if (gSavedSettings.getString("sourceid") == "1208_desura")
- {
- if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
- {
- LL_INFOS("AppInit") << "FirstLoginThisInstall, calling show_first_run_dialog()" << LL_ENDL;
- show_first_run_dialog();
- }
- else
- {
- LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL;
- }
- }
- display_startup();
- LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input
- }
- else
- {
- LL_DEBUGS("AppInit") << "show_connect_box off, skipping to STATE_LOGIN_CLEANUP" << LL_ENDL;
- // skip directly to message template verification
- LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
- }
-
- gViewerWindow->setNormalControlsVisible( FALSE );
- gLoginMenuBarView->setVisible( TRUE );
- gLoginMenuBarView->setEnabled( TRUE );
- show_debug_menus();
-
- // Hide the splash screen
- LL_DEBUGS("AppInit") << "Hide the splash screen and show window" << LL_ENDL;
- LLSplashScreen::hide();
- // Push our window frontmost
- gViewerWindow->getWindow()->show();
-
- // DEV-16927. The following code removes errant keystrokes that happen while the window is being
- // first made visible.
+ if (gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle()))
+ {
+ if (FALSE == gSavedSettings.getBOOL("UseMediaPluginsForStreamingAudio"))
+ {
+ LL_INFOS("AppInit") << "Using default impl to render streaming audio" << LL_ENDL;
+ gAudiop->setStreamingAudioImpl(gAudiop->createDefaultStreamingAudioImpl());
+ }
+
+ // if the audio engine hasn't set up its own preferred handler for streaming audio
+ // then set up the generic streaming audio implementation which uses media plugins
+ if (NULL == gAudiop->getStreamingAudioImpl())
+ {
+ LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL;
+ gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins());
+ }
+
+ gAudiop->setMuted(TRUE);
+ }
+ else
+ {
+ LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL;
+ delete gAudiop;
+ gAudiop = NULL;
+ }
+ }
+ }
+
+ LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL;
+
+ if (LLTimer::knownBadTimer())
+ {
+ LL_WARNS("AppInit") << "Unreliable timers detected (may be bad PCI chipset)!!" << LL_ENDL;
+ }
+
+ //
+ // Log on to system
+ //
+ if (gUserCredential.isNull())
+ {
+ gUserCredential = gLoginHandler.initializeLoginInfo();
+ }
+ // Previous initializeLoginInfo may have generated user credentials. Re-check them.
+ if (gUserCredential.isNull())
+ {
+ show_connect_box = TRUE;
+ }
+ else if (gSavedSettings.getBOOL("AutoLogin"))
+ {
+ // Log into last account
+ gRememberPassword = true;
+ gRememberUser = true;
+ gSavedSettings.setBOOL("RememberPassword", TRUE);
+ gSavedSettings.setBOOL("RememberUser", TRUE);
+ show_connect_box = false;
+ }
+ else if (gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
+ {
+ // Console provided login&password
+ gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
+ gRememberUser = gSavedSettings.getBOOL("RememberUser");
+ show_connect_box = false;
+ }
+ else
+ {
+ gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
+ gRememberUser = gSavedSettings.getBOOL("RememberUser");
+ show_connect_box = TRUE;
+ }
+
+ //setup map of datetime strings to codes and slt & local time offset from utc
+ // *TODO: Does this need to be here?
+ LLStringOps::setupDatetimeInfo(false);
+
+ // Go to the next startup state
+ LLStartUp::setStartupState( STATE_BROWSER_INIT );
+ return FALSE;
+ }
+
+
+ if (STATE_BROWSER_INIT == LLStartUp::getStartupState())
+ {
+ LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL;
+ std::string msg = LLTrans::getString("LoginInitializingBrowser");
+ set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str());
+ display_startup();
+ // LLViewerMedia::initBrowser();
+ LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+ return FALSE;
+ }
+
+
+ if (STATE_LOGIN_SHOW == LLStartUp::getStartupState())
+ {
+ LL_DEBUGS("AppInit") << "Initializing Window, show_connect_box = "
+ << show_connect_box << LL_ENDL;
+
+ // if we've gone backwards in the login state machine, to this state where we show the UI
+ // AND the debug setting to exit in this case is true, then go ahead and bail quickly
+ if ( mLoginStatePastUI && gSavedSettings.getBOOL("QuitOnLoginActivated") )
+ {
+ LL_DEBUGS("AppInit") << "taking QuitOnLoginActivated exit" << LL_ENDL;
+ // no requirement for notification here - just exit
+ LLAppViewer::instance()->earlyExitNoNotify();
+ }
+
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+
+ // Login screen needs menus for preferences, but we can enter
+ // this startup phase more than once.
+ if (gLoginMenuBarView == NULL)
+ {
+ LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL;
+ initialize_spellcheck_menu();
+ init_menus();
+ }
+ show_release_notes_if_required();
+
+ if (show_connect_box)
+ {
+ LL_DEBUGS("AppInit") << "show_connect_box on" << LL_ENDL;
+ // Load all the name information out of the login view
+ // NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't
+ // show the login view until login_show() is called below.
+ if (gUserCredential.isNull())
+ {
+ LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL;
+ gUserCredential = gLoginHandler.initializeLoginInfo();
+ }
+ // Make sure the process dialog doesn't hide things
+ gViewerWindow->setShowProgress(FALSE);
+ // Show the login dialog
+ login_show();
+ // connect dialog is already shown, so fill in the names
+ LLPanelLogin::populateFields( gUserCredential, gRememberUser, gRememberPassword);
+ LLPanelLogin::giveFocus();
+
+ // MAINT-3231 Show first run dialog only for Desura viewer
+ if (gSavedSettings.getString("sourceid") == "1208_desura")
+ {
+ if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
+ {
+ LL_INFOS("AppInit") << "FirstLoginThisInstall, calling show_first_run_dialog()" << LL_ENDL;
+ show_first_run_dialog();
+ }
+ else
+ {
+ LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL;
+ }
+ }
+ display_startup();
+ LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input
+ }
+ else
+ {
+ LL_DEBUGS("AppInit") << "show_connect_box off, skipping to STATE_LOGIN_CLEANUP" << LL_ENDL;
+ // skip directly to message template verification
+ LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
+ }
+
+ gViewerWindow->setNormalControlsVisible( FALSE );
+ gLoginMenuBarView->setVisible( TRUE );
+ gLoginMenuBarView->setEnabled( TRUE );
+ show_debug_menus();
+
+ // Hide the splash screen
+ LL_DEBUGS("AppInit") << "Hide the splash screen and show window" << LL_ENDL;
+ LLSplashScreen::hide();
+ // Push our window frontmost
+ gViewerWindow->getWindow()->show();
+
+ // DEV-16927. The following code removes errant keystrokes that happen while the window is being
+ // first made visible.
#ifdef _WIN32
LL_DEBUGS("AppInit") << "Processing PeekMessage" << LL_ENDL;
- MSG msg;
- while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) )
+ MSG msg;
+ while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) )
{
}
LL_DEBUGS("AppInit") << "PeekMessage processed" << LL_ENDL;
#endif
display_startup();
timeout.reset();
- return FALSE;
- }
-
- if (STATE_LOGIN_WAIT == LLStartUp::getStartupState())
- {
- // when we get to this state, we've already been past the login UI
- // (possiblely automatically) - flag this so we can test in the
- // STATE_LOGIN_SHOW state if we've gone backwards
- mLoginStatePastUI = true;
-
- // Don't do anything. Wait for the login view to call the login_callback,
- // which will push us to the next state.
-
- // display() function will be the one to run display_startup()
- // Sleep so we don't spin the CPU
- ms_sleep(1);
- return FALSE;
- }
-
- if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState())
- {
- // Post login screen, we should see if any settings have changed that may
- // require us to either start/stop or change the socks proxy. As various communications
- // past this point may require the proxy to be up.
- if (!LLStartUp::startLLProxy())
- {
- // Proxy start up failed, we should now bail the state machine
- // startLLProxy() will have reported an error to the user
- // already, so we just go back to the login screen. The user
- // could then change the preferences to fix the issue.
-
- LLStartUp::setStartupState(STATE_LOGIN_SHOW);
- return FALSE;
- }
-
- // reset the values that could have come in from a slurl
- // DEV-42215: Make sure they're not empty -- gUserCredential
- // might already have been set from gSavedSettings, and it's too bad
- // to overwrite valid values with empty strings.
-
- if (show_connect_box)
- {
- // TODO if not use viewer auth
- // Load all the name information out of the login view
- LLPanelLogin::getFields(gUserCredential, gRememberUser, gRememberPassword);
- // end TODO
-
- // HACK: Try to make not jump on login
- gKeyboard->resetKeys();
- }
-
- // when we get to this state, we've already been past the login UI
- // (possiblely automatically) - flag this so we can test in the
- // STATE_LOGIN_SHOW state if we've gone backwards
- mLoginStatePastUI = true;
-
- // save the credentials
- std::string userid = "unknown";
+ return FALSE;
+ }
+
+ if (STATE_LOGIN_WAIT == LLStartUp::getStartupState())
+ {
+ // when we get to this state, we've already been past the login UI
+ // (possiblely automatically) - flag this so we can test in the
+ // STATE_LOGIN_SHOW state if we've gone backwards
+ mLoginStatePastUI = true;
+
+ // Don't do anything. Wait for the login view to call the login_callback,
+ // which will push us to the next state.
+
+ // display() function will be the one to run display_startup()
+ // Sleep so we don't spin the CPU
+ ms_sleep(1);
+ return FALSE;
+ }
+
+ if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState())
+ {
+ // Post login screen, we should see if any settings have changed that may
+ // require us to either start/stop or change the socks proxy. As various communications
+ // past this point may require the proxy to be up.
+ if (!LLStartUp::startLLProxy())
+ {
+ // Proxy start up failed, we should now bail the state machine
+ // startLLProxy() will have reported an error to the user
+ // already, so we just go back to the login screen. The user
+ // could then change the preferences to fix the issue.
+
+ LLStartUp::setStartupState(STATE_LOGIN_SHOW);
+ return FALSE;
+ }
+
+ // reset the values that could have come in from a slurl
+ // DEV-42215: Make sure they're not empty -- gUserCredential
+ // might already have been set from gSavedSettings, and it's too bad
+ // to overwrite valid values with empty strings.
+
+ if (show_connect_box)
+ {
+ // TODO if not use viewer auth
+ // Load all the name information out of the login view
+ LLPanelLogin::getFields(gUserCredential, gRememberUser, gRememberPassword);
+ // end TODO
+
+ // HACK: Try to make not jump on login
+ gKeyboard->resetKeys();
+ }
+
+ // when we get to this state, we've already been past the login UI
+ // (possiblely automatically) - flag this so we can test in the
+ // STATE_LOGIN_SHOW state if we've gone backwards
+ mLoginStatePastUI = true;
+
+ // save the credentials
+ std::string userid = "unknown";
if (gUserCredential.notNull())
{
userid = gUserCredential->userID();
@@ -927,24 +928,24 @@ bool idle_startup()
gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);
}
}
- gSavedSettings.setBOOL("RememberPassword", gRememberPassword);
- gSavedSettings.setBOOL("RememberUser", gRememberUser);
- LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL;
- gDebugInfo["LoginName"] = userid;
-
- // create necessary directories
- // *FIX: these mkdir's should error check
- gDirUtilp->setLindenUserDir(userid);
- LLFile::mkdir(gDirUtilp->getLindenUserDir());
-
- // As soon as directories are ready initialize notification storages
- if (!LLPersistentNotificationStorage::instanceExists())
- {
- // check existance since this part of code can be reached
- // twice due to login failures
- LLPersistentNotificationStorage::initParamSingleton();
- LLDoNotDisturbNotificationStorage::initParamSingleton();
- }
+ gSavedSettings.setBOOL("RememberPassword", gRememberPassword);
+ gSavedSettings.setBOOL("RememberUser", gRememberUser);
+ LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL;
+ gDebugInfo["LoginName"] = userid;
+
+ // create necessary directories
+ // *FIX: these mkdir's should error check
+ gDirUtilp->setLindenUserDir(userid);
+ LLFile::mkdir(gDirUtilp->getLindenUserDir());
+
+ // As soon as directories are ready initialize notification storages
+ if (!LLPersistentNotificationStorage::instanceExists())
+ {
+ // check existance since this part of code can be reached
+ // twice due to login failures
+ LLPersistentNotificationStorage::initParamSingleton();
+ LLDoNotDisturbNotificationStorage::initParamSingleton();
+ }
else
{
// reinitialize paths in case user switched grids or accounts
@@ -952,152 +953,152 @@ bool idle_startup()
LLDoNotDisturbNotificationStorage::getInstance()->reset();
}
- // Set PerAccountSettingsFile to the default value.
- std::string settings_per_account = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount"));
- gSavedSettings.setString("PerAccountSettingsFile", settings_per_account);
- gDebugInfo["PerAccountSettingsFilename"] = settings_per_account;
-
- // Note: can't store warnings files per account because some come up before login
-
- // Overwrite default user settings with user settings
- LLAppViewer::instance()->loadSettingsFromDirectory("Account");
-
- // Convert 'LogInstantMessages' into 'KeepConversationLogTranscripts' for backward compatibility (CHUI-743).
- LLControlVariablePtr logInstantMessagesControl = gSavedPerAccountSettings.getControl("LogInstantMessages");
- if (logInstantMessagesControl.notNull())
- {
- gSavedPerAccountSettings.setS32("KeepConversationLogTranscripts", logInstantMessagesControl->getValue() ? 2 : 1);
- }
-
- // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation
- // and startup time is close enough if we don't have a real value.
- if (gSavedPerAccountSettings.getU32("LastLogoff") == 0)
- {
- gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
- }
-
- //Default the path if one isn't set.
- // *NOTE: unable to check variable differ from "InstantMessageLogPath" because it was
- // provided in pre 2.0 viewer. See EXT-6661
- if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty())
- {
- gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir());
- gSavedPerAccountSettings.setString("InstantMessageLogPath", gDirUtilp->getChatLogsDir());
- }
- else
- {
- gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));
- }
- gDirUtilp->setPerAccountChatLogsDir(userid);
-
- LLFile::mkdir(gDirUtilp->getChatLogsDir());
- LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir());
-
- if (show_connect_box)
- {
- LLSLURL slurl;
- //LLPanelLogin::closePanel();
- }
-
-
- // Load URL History File
- LLURLHistory::loadFile("url_history.xml");
- // Load location history
- LLLocationHistory::getInstance()->load();
-
- // Load Avatars icons cache
- LLAvatarIconIDCache::getInstance()->load();
-
- LLRenderMuteList::getInstance()->loadFromFile();
-
- //-------------------------------------------------
- // Handle startup progress screen
- //-------------------------------------------------
-
- // on startup the user can request to go to their home,
- // their last location, or some URL "-url //sim/x/y[/z]"
- // All accounts have both a home and a last location, and we don't support
- // more locations than that. Choose the appropriate one. JC
- switch (LLStartUp::getStartSLURL().getType())
- {
- case LLSLURL::LOCATION:
- agent_location_id = START_LOCATION_ID_URL;
- break;
- case LLSLURL::LAST_LOCATION:
- agent_location_id = START_LOCATION_ID_LAST;
- break;
- default:
- agent_location_id = START_LOCATION_ID_HOME;
- break;
- }
-
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
-
- // Display the startup progress bar.
- gViewerWindow->initTextures(agent_location_id);
- gViewerWindow->setShowProgress(TRUE);
- gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit"));
-
- gViewerWindow->revealIntroPanel();
-
- LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
-
- return FALSE;
- }
-
- if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState())
- {
- gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId();
-
- // Update progress status and the display loop.
- auth_desc = LLTrans::getString("LoginInProgress");
- set_startup_status(progress, auth_desc, auth_message);
- progress += 0.02f;
- display_startup();
-
- // Setting initial values...
- LLLoginInstance* login = LLLoginInstance::getInstance();
- login->setNotificationsInterface(LLNotifications::getInstance());
-
- login->setSerialNumber(LLAppViewer::instance()->getSerialNumber());
- login->setLastExecEvent(gLastExecEvent);
- login->setLastExecDuration(gLastExecDuration);
-
- // This call to LLLoginInstance::connect() starts the
- // authentication process.
- login->connect(gUserCredential);
-
- LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK );
- return FALSE;
- }
-
- if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState())
- {
- // If we get here we have gotten past the potential stall
- // in curl, so take "may appear frozen" out of progress bar. JC
- auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
- set_startup_status(progress, auth_desc, auth_message);
-
- LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );
- return FALSE;
- }
-
- if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState())
- {
- // Generic failure message
- std::ostringstream emsg;
- emsg << LLTrans::getString("LoginFailedHeader") << "\n";
- if(LLLoginInstance::getInstance()->authFailure())
- {
- LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): "
- << LLLoginInstance::getInstance()->getResponse() << LL_ENDL;
- LLSD response = LLLoginInstance::getInstance()->getResponse();
- // Still have error conditions that may need some
- // sort of handling - dig up specific message
- std::string reason_response = response["reason"];
- std::string message_response = response["message"];
- std::string message_id = response["message_id"];
- std::string message; // actual string to show the user
+ // Set PerAccountSettingsFile to the default value.
+ std::string settings_per_account = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount"));
+ gSavedSettings.setString("PerAccountSettingsFile", settings_per_account);
+ gDebugInfo["PerAccountSettingsFilename"] = settings_per_account;
+
+ // Note: can't store warnings files per account because some come up before login
+
+ // Overwrite default user settings with user settings
+ LLAppViewer::instance()->loadSettingsFromDirectory("Account");
+
+ // Convert 'LogInstantMessages' into 'KeepConversationLogTranscripts' for backward compatibility (CHUI-743).
+ LLControlVariablePtr logInstantMessagesControl = gSavedPerAccountSettings.getControl("LogInstantMessages");
+ if (logInstantMessagesControl.notNull())
+ {
+ gSavedPerAccountSettings.setS32("KeepConversationLogTranscripts", logInstantMessagesControl->getValue() ? 2 : 1);
+ }
+
+ // Need to set the LastLogoff time here if we don't have one. LastLogoff is used for "Recent Items" calculation
+ // and startup time is close enough if we don't have a real value.
+ if (gSavedPerAccountSettings.getU32("LastLogoff") == 0)
+ {
+ gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
+ }
+
+ //Default the path if one isn't set.
+ // *NOTE: unable to check variable differ from "InstantMessageLogPath" because it was
+ // provided in pre 2.0 viewer. See EXT-6661
+ if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty())
+ {
+ gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir());
+ gSavedPerAccountSettings.setString("InstantMessageLogPath", gDirUtilp->getChatLogsDir());
+ }
+ else
+ {
+ gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));
+ }
+ gDirUtilp->setPerAccountChatLogsDir(userid);
+
+ LLFile::mkdir(gDirUtilp->getChatLogsDir());
+ LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir());
+
+ if (show_connect_box)
+ {
+ LLSLURL slurl;
+ //LLPanelLogin::closePanel();
+ }
+
+
+ // Load URL History File
+ LLURLHistory::loadFile("url_history.xml");
+ // Load location history
+ LLLocationHistory::getInstance()->load();
+
+ // Load Avatars icons cache
+ LLAvatarIconIDCache::getInstance()->load();
+
+ LLRenderMuteList::getInstance()->loadFromFile();
+
+ //-------------------------------------------------
+ // Handle startup progress screen
+ //-------------------------------------------------
+
+ // on startup the user can request to go to their home,
+ // their last location, or some URL "-url //sim/x/y[/z]"
+ // All accounts have both a home and a last location, and we don't support
+ // more locations than that. Choose the appropriate one. JC
+ switch (LLStartUp::getStartSLURL().getType())
+ {
+ case LLSLURL::LOCATION:
+ agent_location_id = START_LOCATION_ID_URL;
+ break;
+ case LLSLURL::LAST_LOCATION:
+ agent_location_id = START_LOCATION_ID_LAST;
+ break;
+ default:
+ agent_location_id = START_LOCATION_ID_HOME;
+ break;
+ }
+
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
+
+ // Display the startup progress bar.
+ gViewerWindow->initTextures(agent_location_id);
+ gViewerWindow->setShowProgress(TRUE);
+ gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit"));
+
+ gViewerWindow->revealIntroPanel();
+
+ LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
+
+ return FALSE;
+ }
+
+ if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState())
+ {
+ gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId();
+
+ // Update progress status and the display loop.
+ auth_desc = LLTrans::getString("LoginInProgress");
+ set_startup_status(progress, auth_desc, auth_message);
+ progress += 0.02f;
+ display_startup();
+
+ // Setting initial values...
+ LLLoginInstance* login = LLLoginInstance::getInstance();
+ login->setNotificationsInterface(LLNotifications::getInstance());
+
+ login->setSerialNumber(LLAppViewer::instance()->getSerialNumber());
+ login->setLastExecEvent(gLastExecEvent);
+ login->setLastExecDuration(gLastExecDuration);
+
+ // This call to LLLoginInstance::connect() starts the
+ // authentication process.
+ login->connect(gUserCredential);
+
+ LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK );
+ return FALSE;
+ }
+
+ if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState())
+ {
+ // If we get here we have gotten past the potential stall
+ // in curl, so take "may appear frozen" out of progress bar. JC
+ auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
+ set_startup_status(progress, auth_desc, auth_message);
+
+ LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );
+ return FALSE;
+ }
+
+ if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState())
+ {
+ // Generic failure message
+ std::ostringstream emsg;
+ emsg << LLTrans::getString("LoginFailedHeader") << "\n";
+ if(LLLoginInstance::getInstance()->authFailure())
+ {
+ LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): "
+ << LLLoginInstance::getInstance()->getResponse() << LL_ENDL;
+ LLSD response = LLLoginInstance::getInstance()->getResponse();
+ // Still have error conditions that may need some
+ // sort of handling - dig up specific message
+ std::string reason_response = response["reason"];
+ std::string message_response = response["message"];
+ std::string message_id = response["message_id"];
+ std::string message; // actual string to show the user
bool localized_by_id = false;
if(!message_id.empty())
@@ -1130,58 +1131,58 @@ bool idle_startup()
}
if(!localized_by_id && !message_response.empty())
- {
- // *HACK: "no_inventory_host" sent as the message itself.
- // Remove this clause when server is sending message_id as well.
- message = LLAgent::sTeleportErrorMessages[ message_response ];
- }
-
- if (message.empty())
- {
- // Fallback to server-supplied string; necessary since server
- // may add strings that this viewer is not yet aware of
- message = message_response;
- }
-
- emsg << message;
-
-
- if(reason_response == "key")
- {
- // Couldn't login because user/password is wrong
- // Clear the credential
- gUserCredential->clearAuthenticator();
- }
-
- if(reason_response == "update"
- || reason_response == "optional")
- {
- // In the case of a needed update, quit.
- // Its either downloading or declined.
- // If optional was skipped this case shouldn't
- // be reached.
-
- LL_INFOS("LLStartup") << "Forcing a quit due to update." << LL_ENDL;
- LLLoginInstance::getInstance()->disconnect();
- LLAppViewer::instance()->forceQuit();
- }
- else
- {
- if (reason_response != "tos" && reason_response != "mfa_challenge")
- {
- // Don't pop up a notification in the TOS or MFA cases because
- // the specialized floater has already scolded the user.
- std::string error_code;
- if(response.has("errorcode"))
- {
- error_code = response["errorcode"].asString();
- }
- if ((reason_response == "CURLError") &&
- (error_code == "SSL_CACERT" || error_code == "SSL_PEER_CERTIFICATE") &&
- response.has("certificate"))
- {
- // This was a certificate error, so grab the certificate
- // and throw up the appropriate dialog.
+ {
+ // *HACK: "no_inventory_host" sent as the message itself.
+ // Remove this clause when server is sending message_id as well.
+ message = LLAgent::sTeleportErrorMessages[ message_response ];
+ }
+
+ if (message.empty())
+ {
+ // Fallback to server-supplied string; necessary since server
+ // may add strings that this viewer is not yet aware of
+ message = message_response;
+ }
+
+ emsg << message;
+
+
+ if(reason_response == "key")
+ {
+ // Couldn't login because user/password is wrong
+ // Clear the credential
+ gUserCredential->clearAuthenticator();
+ }
+
+ if(reason_response == "update"
+ || reason_response == "optional")
+ {
+ // In the case of a needed update, quit.
+ // Its either downloading or declined.
+ // If optional was skipped this case shouldn't
+ // be reached.
+
+ LL_INFOS("LLStartup") << "Forcing a quit due to update." << LL_ENDL;
+ LLLoginInstance::getInstance()->disconnect();
+ LLAppViewer::instance()->forceQuit();
+ }
+ else
+ {
+ if (reason_response != "tos" && reason_response != "mfa_challenge")
+ {
+ // Don't pop up a notification in the TOS or MFA cases because
+ // the specialized floater has already scolded the user.
+ std::string error_code;
+ if(response.has("errorcode"))
+ {
+ error_code = response["errorcode"].asString();
+ }
+ if ((reason_response == "CURLError") &&
+ (error_code == "SSL_CACERT" || error_code == "SSL_PEER_CERTIFICATE") &&
+ response.has("certificate"))
+ {
+ // This was a certificate error, so grab the certificate
+ // and throw up the appropriate dialog.
LLPointer<LLCertificate> certificate;
try
{
@@ -1200,215 +1201,215 @@ bool idle_startup()
gSavedSettings.setBOOL("AutoLogin", FALSE);
show_connect_box = true;
}
- if(certificate)
- {
- LLSD args = transform_cert_args(certificate);
-
- if(error_code == "SSL_CACERT")
- {
- // if we are handling an untrusted CA, throw up the dialog
- // with the 'trust this CA' button.
- LLNotificationsUtil::add("TrustCertificateError", args, response,
- trust_cert_done);
-
- show_connect_box = true;
- }
- else
- {
- // the certificate exception returns a unique string for each type of exception.
- // we grab this string via the LLUserAuth object, and use that to grab the localized
- // string.
- args["REASON"] = LLTrans::getString(message_response);
-
- LLNotificationsUtil::add("GeneralCertificateError", args, response,
- general_cert_done);
-
- reset_login();
- gSavedSettings.setBOOL("AutoLogin", FALSE);
- show_connect_box = true;
-
- }
-
- }
- }
+ if(certificate)
+ {
+ LLSD args = transform_cert_args(certificate);
+
+ if(error_code == "SSL_CACERT")
+ {
+ // if we are handling an untrusted CA, throw up the dialog
+ // with the 'trust this CA' button.
+ LLNotificationsUtil::add("TrustCertificateError", args, response,
+ trust_cert_done);
+
+ show_connect_box = true;
+ }
+ else
+ {
+ // the certificate exception returns a unique string for each type of exception.
+ // we grab this string via the LLUserAuth object, and use that to grab the localized
+ // string.
+ args["REASON"] = LLTrans::getString(message_response);
+
+ LLNotificationsUtil::add("GeneralCertificateError", args, response,
+ general_cert_done);
+
+ reset_login();
+ gSavedSettings.setBOOL("AutoLogin", FALSE);
+ show_connect_box = true;
+
+ }
+
+ }
+ }
else if (reason_response == "BadType")
{
LLNotificationsUtil::add("LoginFailedToParse", LLSD(), LLSD(), login_alert_done);
}
- else if (!message.empty())
- {
- // This wasn't a certificate error, so throw up the normal
- // notificatioin message.
- LLSD args;
- args["ERROR_MESSAGE"] = emsg.str();
- LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
- LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
- }
- }
- transition_back_to_login_panel(emsg.str());
- show_connect_box = true;
- }
- }
- else if(LLLoginInstance::getInstance()->authSuccess())
- {
- if(process_login_success_response())
- {
- // Pass the user information to the voice chat server interface.
- LLVoiceClient::getInstance()->userAuthorized(gUserCredential->userID(), gAgentID);
- // create the default proximal channel
- LLVoiceChannel::initClass();
- LLStartUp::setStartupState( STATE_WORLD_INIT);
- LLTrace::get_frame_recording().reset();
- }
- else
- {
- LLSD args;
- args["ERROR_MESSAGE"] = emsg.str();
- LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
- LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
- transition_back_to_login_panel(emsg.str());
- show_connect_box = true;
- return FALSE;
- }
- }
- return FALSE;
- }
-
- //---------------------------------------------------------------------
- // World Init
- //---------------------------------------------------------------------
- if (STATE_WORLD_INIT == LLStartUp::getStartupState())
- {
- set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD);
- display_startup();
- // We should have an agent id by this point.
- llassert(!(gAgentID == LLUUID::null));
-
- // Finish agent initialization. (Requires gSavedSettings, builds camera)
- gAgent.init();
- display_startup();
- gAgentCamera.init();
- display_startup();
- display_startup();
-
- // Since we connected, save off the settings so the user doesn't have to
- // type the name/password again if we crash.
- gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
- LLUIColorTable::instance().saveUserSettings();
-
- display_startup();
-
- //
- // Initialize classes w/graphics stuff.
- //
- LLViewerStatsRecorder::instance(); // Since textures work in threads
- LLSurface::initClasses();
- display_startup();
-
- display_startup();
-
- LLDrawable::initClass();
- display_startup();
-
- // init the shader managers
- LLPostProcess::initClass();
- display_startup();
+ else if (!message.empty())
+ {
+ // This wasn't a certificate error, so throw up the normal
+ // notificatioin message.
+ LLSD args;
+ args["ERROR_MESSAGE"] = emsg.str();
+ LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
+ LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
+ }
+ }
+ transition_back_to_login_panel(emsg.str());
+ show_connect_box = true;
+ }
+ }
+ else if(LLLoginInstance::getInstance()->authSuccess())
+ {
+ if(process_login_success_response())
+ {
+ // Pass the user information to the voice chat server interface.
+ LLVoiceClient::getInstance()->userAuthorized(gUserCredential->userID(), gAgentID);
+ // create the default proximal channel
+ LLVoiceChannel::initClass();
+ LLStartUp::setStartupState( STATE_WORLD_INIT);
+ LLTrace::get_frame_recording().reset();
+ }
+ else
+ {
+ LLSD args;
+ args["ERROR_MESSAGE"] = emsg.str();
+ LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
+ LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
+ transition_back_to_login_panel(emsg.str());
+ show_connect_box = true;
+ return FALSE;
+ }
+ }
+ return FALSE;
+ }
+
+ //---------------------------------------------------------------------
+ // World Init
+ //---------------------------------------------------------------------
+ if (STATE_WORLD_INIT == LLStartUp::getStartupState())
+ {
+ set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD);
+ display_startup();
+ // We should have an agent id by this point.
+ llassert(!(gAgentID == LLUUID::null));
+
+ // Finish agent initialization. (Requires gSavedSettings, builds camera)
+ gAgent.init();
+ display_startup();
+ gAgentCamera.init();
+ display_startup();
+ display_startup();
+
+ // Since we connected, save off the settings so the user doesn't have to
+ // type the name/password again if we crash.
+ gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
+ LLUIColorTable::instance().saveUserSettings();
+
+ display_startup();
+
+ //
+ // Initialize classes w/graphics stuff.
+ //
+ LLViewerStatsRecorder::instance(); // Since textures work in threads
+ LLSurface::initClasses();
+ display_startup();
+
+ display_startup();
+
+ LLDrawable::initClass();
+ display_startup();
+
+ // init the shader managers
+ LLPostProcess::initClass();
+ display_startup();
LLAvatarAppearance::initClass("avatar_lad.xml","avatar_skeleton.xml");
- display_startup();
-
- LLViewerObject::initVOClasses();
- display_startup();
-
- // Initialize all our tools. Must be done after saved settings loaded.
- // NOTE: This also is where gToolMgr used to be instantiated before being turned into a singleton.
- LLToolMgr::getInstance()->initTools();
- display_startup();
-
- // Pre-load floaters, like the world map, that are slow to spawn
- // due to XML complexity.
- gViewerWindow->initWorldUI();
-
- display_startup();
-
- // This is where we used to initialize gWorldp. Original comment said:
- // World initialization must be done after above window init
-
- // User might have overridden far clip
- LLWorld::getInstance()->setLandFarClip(gAgentCamera.mDrawDistance);
- display_startup();
- // Before we create the first region, we need to set the agent's mOriginGlobal
- // This is necessary because creating objects before this is set will result in a
- // bad mPositionAgent cache.
-
- gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle));
- display_startup();
-
- LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim);
- display_startup();
-
- LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle);
- LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL;
-
- LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from init_idle(). Seed cap == "
- << gFirstSimSeedCap << LL_ENDL;
- regionp->setSeedCapability(gFirstSimSeedCap);
- LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL;
- display_startup();
- // Set agent's initial region to be the one we just created.
- gAgent.setRegion(regionp);
- display_startup();
- // Set agent's initial position, which will be read by LLVOAvatar when the avatar
- // object is created. I think this must be done after setting the region. JC
- gAgent.setPositionAgent(agent_start_position_region);
-
- display_startup();
- LLStartUp::initExperiences();
-
- display_startup();
-
- // If logging should be enebled, turns it on and loads history from disk
- // Note: does not happen on init of singleton because preferences can use
- // this instance without logging in
- LLConversationLog::getInstance()->initLoggingState();
-
- LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT );
-
- return FALSE;
- }
-
-
- //---------------------------------------------------------------------
- // Load QuickTime/GStreamer and other multimedia engines, can be slow.
- // Do it while we're waiting on the network for our seed capability. JC
- //---------------------------------------------------------------------
- if (STATE_MULTIMEDIA_INIT == LLStartUp::getStartupState())
- {
- LLStartUp::multimediaInit();
- LLStartUp::setStartupState( STATE_FONT_INIT );
- display_startup();
- return FALSE;
- }
-
- // Loading fonts takes several seconds
- if (STATE_FONT_INIT == LLStartUp::getStartupState())
- {
- LLStartUp::fontInit();
- LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT );
- display_startup();
- return FALSE;
- }
-
- //---------------------------------------------------------------------
- // Wait for Seed Cap Grant
- //---------------------------------------------------------------------
- if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
- {
- LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle);
- if (regionp->capabilitiesReceived())
- {
- LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
- }
+ display_startup();
+
+ LLViewerObject::initVOClasses();
+ display_startup();
+
+ // Initialize all our tools. Must be done after saved settings loaded.
+ // NOTE: This also is where gToolMgr used to be instantiated before being turned into a singleton.
+ LLToolMgr::getInstance()->initTools();
+ display_startup();
+
+ // Pre-load floaters, like the world map, that are slow to spawn
+ // due to XML complexity.
+ gViewerWindow->initWorldUI();
+
+ display_startup();
+
+ // This is where we used to initialize gWorldp. Original comment said:
+ // World initialization must be done after above window init
+
+ // User might have overridden far clip
+ LLWorld::getInstance()->setLandFarClip(gAgentCamera.mDrawDistance);
+ display_startup();
+ // Before we create the first region, we need to set the agent's mOriginGlobal
+ // This is necessary because creating objects before this is set will result in a
+ // bad mPositionAgent cache.
+
+ gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle));
+ display_startup();
+
+ LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim);
+ display_startup();
+
+ LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle);
+ LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL;
+
+ LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from init_idle(). Seed cap == "
+ << gFirstSimSeedCap << LL_ENDL;
+ regionp->setSeedCapability(gFirstSimSeedCap);
+ LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL;
+ display_startup();
+ // Set agent's initial region to be the one we just created.
+ gAgent.setRegion(regionp);
+ display_startup();
+ // Set agent's initial position, which will be read by LLVOAvatar when the avatar
+ // object is created. I think this must be done after setting the region. JC
+ gAgent.setPositionAgent(agent_start_position_region);
+
+ display_startup();
+ LLStartUp::initExperiences();
+
+ display_startup();
+
+ // If logging should be enebled, turns it on and loads history from disk
+ // Note: does not happen on init of singleton because preferences can use
+ // this instance without logging in
+ LLConversationLog::getInstance()->initLoggingState();
+
+ LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT );
+
+ return FALSE;
+ }
+
+
+ //---------------------------------------------------------------------
+ // Load QuickTime/GStreamer and other multimedia engines, can be slow.
+ // Do it while we're waiting on the network for our seed capability. JC
+ //---------------------------------------------------------------------
+ if (STATE_MULTIMEDIA_INIT == LLStartUp::getStartupState())
+ {
+ LLStartUp::multimediaInit();
+ LLStartUp::setStartupState( STATE_FONT_INIT );
+ display_startup();
+ return FALSE;
+ }
+
+ // Loading fonts takes several seconds
+ if (STATE_FONT_INIT == LLStartUp::getStartupState())
+ {
+ LLStartUp::fontInit();
+ LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT );
+ display_startup();
+ return FALSE;
+ }
+
+ //---------------------------------------------------------------------
+ // Wait for Seed Cap Grant
+ //---------------------------------------------------------------------
+ if(STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
+ {
+ LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle);
+ if (regionp->capabilitiesReceived())
+ {
+ LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
+ }
else if (regionp->capabilitiesError())
{
LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL;
@@ -1422,9 +1423,9 @@ bool idle_startup()
}
reset_login();
}
- else
- {
- U32 num_retries = regionp->getNumSeedCapRetries();
+ else
+ {
+ U32 num_retries = regionp->getNumSeedCapRetries();
if (num_retries > MAX_SEED_CAP_ATTEMPTS_BEFORE_ABORT)
{
LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL;
@@ -1438,29 +1439,29 @@ bool idle_startup()
}
reset_login();
}
- else if (num_retries > 0)
- {
- LLStringUtil::format_map_t args;
- args["[NUMBER]"] = llformat("%d", num_retries + 1);
- set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD.c_str());
- }
- else
- {
- set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD.c_str());
- }
- }
- display_startup();
- return FALSE;
- }
-
-
- //---------------------------------------------------------------------
- // Seed Capability Granted
- // no newMessage calls should happen before this point
- //---------------------------------------------------------------------
- if (STATE_SEED_CAP_GRANTED == LLStartUp::getStartupState())
- {
- display_startup();
+ else if (num_retries > 0)
+ {
+ LLStringUtil::format_map_t args;
+ args["[NUMBER]"] = llformat("%d", num_retries + 1);
+ set_startup_status(0.4f, LLTrans::getString("LoginRetrySeedCapGrant", args), gAgent.mMOTD.c_str());
+ }
+ else
+ {
+ set_startup_status(0.4f, LLTrans::getString("LoginRequestSeedCapGrant"), gAgent.mMOTD.c_str());
+ }
+ }
+ display_startup();
+ return FALSE;
+ }
+
+
+ //---------------------------------------------------------------------
+ // Seed Capability Granted
+ // no newMessage calls should happen before this point
+ //---------------------------------------------------------------------
+ if (STATE_SEED_CAP_GRANTED == LLStartUp::getStartupState())
+ {
+ display_startup();
// These textures are not warrantied to be cached, so needs
// to hapen with caps granted
@@ -1470,291 +1471,291 @@ bool idle_startup()
LLEnvironment::getInstance()->initSingleton();
display_startup();
- update_texture_fetch();
- display_startup();
-
- if ( gViewerWindow != NULL)
- { // This isn't the first logon attempt, so show the UI
- gViewerWindow->setNormalControlsVisible( TRUE );
- }
- gLoginMenuBarView->setVisible( FALSE );
- gLoginMenuBarView->setEnabled( FALSE );
- display_startup();
-
- // direct logging to the debug console's line buffer
- LLError::logToFixedBuffer(gDebugView->mDebugConsolep);
- display_startup();
-
- // set initial visibility of debug console
- gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole"));
- display_startup();
-
- //
- // Set message handlers
- //
- LL_INFOS("AppInit") << "Initializing communications..." << LL_ENDL;
-
- // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted
- register_viewer_callbacks(gMessageSystem);
- display_startup();
-
- // Debugging info parameters
- gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms
- display_startup();
-
- #ifndef LL_RELEASE_FOR_DOWNLOAD
- gMessageSystem->setTimeDecodes( TRUE ); // Time the decode of each msg
- gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode
- #endif
- display_startup();
-
- gXferManager->registerCallbacks(gMessageSystem);
- display_startup();
-
- LLStartUp::initNameCache();
- display_startup();
-
- // update the voice settings *after* gCacheName initialization
- // so that we can construct voice UI that relies on the name cache
- if (LLVoiceClient::instanceExists())
- {
- LLVoiceClient::getInstance()->updateSettings();
- }
- display_startup();
-
- // create a container's instance for start a controlling conversation windows
- // by the voice's events
- LLFloaterIMContainer::getInstance();
- if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 2)
- {
- LLViewerParcelAskPlay::getInstance()->loadSettings();
- }
-
- gAgent.addRegionChangedCallback(boost::bind(&LLPerfStats::StatsRecorder::clearStats));
-
- // *Note: this is where gWorldMap used to be initialized.
-
- // register null callbacks for audio until the audio system is initialized
- gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL);
- display_startup();
-
- //reset statistics
- LLViewerStats::instance().resetStats();
-
- display_startup();
- //
- // Set up region and surface defaults
- //
-
-
- // Sets up the parameters for the first simulator
-
- LL_DEBUGS("AppInit") << "Initializing camera..." << LL_ENDL;
- gFrameTime = totalTime();
- F32Seconds last_time = gFrameTimeSeconds;
- gFrameTimeSeconds = (gFrameTime - gStartTime);
-
- gFrameIntervalSeconds = gFrameTimeSeconds - last_time;
- if (gFrameIntervalSeconds < 0.f)
- {
- gFrameIntervalSeconds = 0.f;
- }
-
- // Make sure agent knows correct aspect ratio
- // FOV limits depend upon aspect ratio so this needs to happen before initializing the FOV below
- LLViewerCamera::getInstance()->setViewHeightInPixels(gViewerWindow->getWorldViewHeightRaw());
- LLViewerCamera::getInstance()->setAspect(gViewerWindow->getWorldViewAspectRatio());
- // Initialize FOV
- LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("CameraAngle"));
- display_startup();
-
- // Move agent to starting location. The position handed to us by
- // the space server is in global coordinates, but the agent frame
- // is in region local coordinates. Therefore, we need to adjust
- // the coordinates handed to us to fit in the local region.
-
- gAgent.setPositionAgent(agent_start_position_region);
- gAgent.resetAxes(gAgentStartLookAt);
- gAgentCamera.stopCameraAnimation();
- gAgentCamera.resetCamera();
- display_startup();
-
- // Initialize global class data needed for surfaces (i.e. textures)
- LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL;
- // Initialize all of the viewer object classes for the first time (doing things like texture fetches.
- LLGLState::checkStates();
-
- gSky.init();
-
- LLGLState::checkStates();
-
- display_startup();
-
- LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL;
- // For all images pre-loaded into viewer cache, init
+ update_texture_fetch();
+ display_startup();
+
+ if ( gViewerWindow != NULL)
+ { // This isn't the first logon attempt, so show the UI
+ gViewerWindow->setNormalControlsVisible( TRUE );
+ }
+ gLoginMenuBarView->setVisible( FALSE );
+ gLoginMenuBarView->setEnabled( FALSE );
+ display_startup();
+
+ // direct logging to the debug console's line buffer
+ LLError::logToFixedBuffer(gDebugView->mDebugConsolep);
+ display_startup();
+
+ // set initial visibility of debug console
+ gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole"));
+ display_startup();
+
+ //
+ // Set message handlers
+ //
+ LL_INFOS("AppInit") << "Initializing communications..." << LL_ENDL;
+
+ // register callbacks for messages. . . do this after initial handshake to make sure that we don't catch any unwanted
+ register_viewer_callbacks(gMessageSystem);
+ display_startup();
+
+ // Debugging info parameters
+ gMessageSystem->setMaxMessageTime( 0.5f ); // Spam if decoding all msgs takes more than 500 ms
+ display_startup();
+
+ #ifndef LL_RELEASE_FOR_DOWNLOAD
+ gMessageSystem->setTimeDecodes( TRUE ); // Time the decode of each msg
+ gMessageSystem->setTimeDecodesSpamThreshold( 0.05f ); // Spam if a single msg takes over 50ms to decode
+ #endif
+ display_startup();
+
+ gXferManager->registerCallbacks(gMessageSystem);
+ display_startup();
+
+ LLStartUp::initNameCache();
+ display_startup();
+
+ // update the voice settings *after* gCacheName initialization
+ // so that we can construct voice UI that relies on the name cache
+ if (LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->updateSettings();
+ }
+ display_startup();
+
+ // create a container's instance for start a controlling conversation windows
+ // by the voice's events
+ LLFloaterIMContainer::getInstance();
+ if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 2)
+ {
+ LLViewerParcelAskPlay::getInstance()->loadSettings();
+ }
+
+ gAgent.addRegionChangedCallback(boost::bind(&LLPerfStats::StatsRecorder::clearStats));
+
+ // *Note: this is where gWorldMap used to be initialized.
+
+ // register null callbacks for audio until the audio system is initialized
+ gMessageSystem->setHandlerFuncFast(_PREHASH_SoundTrigger, null_message_callback, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_AttachedSound, null_message_callback, NULL);
+ display_startup();
+
+ //reset statistics
+ LLViewerStats::instance().resetStats();
+
+ display_startup();
+ //
+ // Set up region and surface defaults
+ //
+
+
+ // Sets up the parameters for the first simulator
+
+ LL_DEBUGS("AppInit") << "Initializing camera..." << LL_ENDL;
+ gFrameTime = totalTime();
+ F32Seconds last_time = gFrameTimeSeconds;
+ gFrameTimeSeconds = (gFrameTime - gStartTime);
+
+ gFrameIntervalSeconds = gFrameTimeSeconds - last_time;
+ if (gFrameIntervalSeconds < 0.f)
+ {
+ gFrameIntervalSeconds = 0.f;
+ }
+
+ // Make sure agent knows correct aspect ratio
+ // FOV limits depend upon aspect ratio so this needs to happen before initializing the FOV below
+ LLViewerCamera::getInstance()->setViewHeightInPixels(gViewerWindow->getWorldViewHeightRaw());
+ LLViewerCamera::getInstance()->setAspect(gViewerWindow->getWorldViewAspectRatio());
+ // Initialize FOV
+ LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("CameraAngle"));
+ display_startup();
+
+ // Move agent to starting location. The position handed to us by
+ // the space server is in global coordinates, but the agent frame
+ // is in region local coordinates. Therefore, we need to adjust
+ // the coordinates handed to us to fit in the local region.
+
+ gAgent.setPositionAgent(agent_start_position_region);
+ gAgent.resetAxes(gAgentStartLookAt);
+ gAgentCamera.stopCameraAnimation();
+ gAgentCamera.resetCamera();
+ display_startup();
+
+ // Initialize global class data needed for surfaces (i.e. textures)
+ LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL;
+ // Initialize all of the viewer object classes for the first time (doing things like texture fetches.
+ LLGLState::checkStates();
+
+ gSky.init();
+
+ LLGLState::checkStates();
+
+ display_startup();
+
+ LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL;
+ // For all images pre-loaded into viewer cache, init
// priorities and fetching using decodeAllImages.
// Most of the fetching and decoding likely to be done
// by update_texture_fetch() later, while viewer waits.
//
- // Need to do this AFTER we init the sky
- const S32 DECODE_TIME_SEC = 2;
- for (int i = 0; i < DECODE_TIME_SEC; i++)
- {
- F32 frac = (F32)i / (F32)DECODE_TIME_SEC;
- set_startup_status(0.45f + frac*0.1f, LLTrans::getString("LoginDecodingImages"), gAgent.mMOTD);
- display_startup();
- gTextureList.decodeAllImages(1.f);
- }
- LLStartUp::setStartupState( STATE_WORLD_WAIT );
-
- display_startup();
-
- // JC - Do this as late as possible to increase likelihood Purify
- // will run.
- LLMessageSystem* msg = gMessageSystem;
- if (!msg->mOurCircuitCode)
- {
- LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL;
- }
-
- gUseCircuitCallbackCalled = false;
-
- msg->enableCircuit(gFirstSim, TRUE);
- // now, use the circuit info to tell simulator about us!
- LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL;
- msg->newMessageFast(_PREHASH_UseCircuitCode);
- msg->nextBlockFast(_PREHASH_CircuitCode);
- msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode);
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
- msg->sendReliable(
- gFirstSim,
- gSavedSettings.getS32("UseCircuitCodeMaxRetries"),
- FALSE,
- (F32Seconds)gSavedSettings.getF32("UseCircuitCodeTimeout"),
- use_circuit_callback,
- NULL);
-
- timeout.reset();
- display_startup();
-
- return FALSE;
- }
-
- //---------------------------------------------------------------------
- // World Wait
- //---------------------------------------------------------------------
- if(STATE_WORLD_WAIT == LLStartUp::getStartupState())
- {
- LL_DEBUGS("AppInit") << "Waiting for simulator ack...." << LL_ENDL;
- set_startup_status(0.59f, LLTrans::getString("LoginWaitingForRegionHandshake"), gAgent.mMOTD);
- if(gGotUseCircuitCodeAck)
- {
- LLStartUp::setStartupState( STATE_AGENT_SEND );
- }
- pump_idle_startup_network();
- return FALSE;
- }
-
- //---------------------------------------------------------------------
- // Agent Send
- //---------------------------------------------------------------------
- if (STATE_AGENT_SEND == LLStartUp::getStartupState())
- {
- LL_DEBUGS("AppInit") << "Connecting to region..." << LL_ENDL;
- set_startup_status(0.60f, LLTrans::getString("LoginConnectingToRegion"), gAgent.mMOTD);
- display_startup();
- // register with the message system so it knows we're
- // expecting this message
- LLMessageSystem* msg = gMessageSystem;
- msg->setHandlerFuncFast(
- _PREHASH_AgentMovementComplete,
- process_agent_movement_complete);
- LLViewerRegion* regionp = gAgent.getRegion();
- if(regionp)
- {
- send_complete_agent_movement(regionp->getHost());
- gAssetStorage->setUpstream(regionp->getHost());
- gCacheName->setUpstream(regionp->getHost());
- }
- display_startup();
-
- // Create login effect
- // But not on first login, because you can't see your avatar then
- if (!gAgent.isFirstLogin())
- {
- LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
- effectp->setPositionGlobal(gAgent.getPositionGlobal());
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- LLHUDManager::getInstance()->sendEffects();
- }
-
- LLStartUp::setStartupState( STATE_AGENT_WAIT ); // Go to STATE_AGENT_WAIT
-
- timeout.reset();
- display_startup();
- return FALSE;
- }
-
- //---------------------------------------------------------------------
- // Agent Wait
- //---------------------------------------------------------------------
- if (STATE_AGENT_WAIT == LLStartUp::getStartupState())
- {
- {
- LockMessageChecker lmc(gMessageSystem);
- while (lmc.checkAllMessages(gFrameCount, gServicePump))
- {
- if (gAgentMovementCompleted)
- {
- // Sometimes we have more than one message in the
- // queue. break out of this loop and continue
- // processing. If we don't, then this could skip one
- // or more login steps.
- break;
- }
- else
- {
- LL_DEBUGS("AppInit") << "Awaiting AvatarInitComplete, got "
- << gMessageSystem->getMessageName() << LL_ENDL;
- }
- display_startup();
- }
- lmc.processAcks();
- }
-
- display_startup();
-
- if (gAgentMovementCompleted)
- {
- LLStartUp::setStartupState( STATE_INVENTORY_SEND );
- }
- display_startup();
-
- if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT)
- {
- LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
- if (gRememberPassword)
- {
- LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
- }
- else
- {
- LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
- }
- reset_login();
- }
- return FALSE;
- }
-
- //---------------------------------------------------------------------
- // Inventory Send
- //---------------------------------------------------------------------
- if (STATE_INVENTORY_SEND == LLStartUp::getStartupState())
- {
- LL_PROFILE_ZONE_NAMED("State inventory send")
- display_startup();
+ // Need to do this AFTER we init the sky
+ const S32 DECODE_TIME_SEC = 2;
+ for (int i = 0; i < DECODE_TIME_SEC; i++)
+ {
+ F32 frac = (F32)i / (F32)DECODE_TIME_SEC;
+ set_startup_status(0.45f + frac*0.1f, LLTrans::getString("LoginDecodingImages"), gAgent.mMOTD);
+ display_startup();
+ gTextureList.decodeAllImages(1.f);
+ }
+ LLStartUp::setStartupState( STATE_WORLD_WAIT );
+
+ display_startup();
+
+ // JC - Do this as late as possible to increase likelihood Purify
+ // will run.
+ LLMessageSystem* msg = gMessageSystem;
+ if (!msg->mOurCircuitCode)
+ {
+ LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL;
+ }
+
+ gUseCircuitCallbackCalled = false;
+
+ msg->enableCircuit(gFirstSim, TRUE);
+ // now, use the circuit info to tell simulator about us!
+ LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL;
+ msg->newMessageFast(_PREHASH_UseCircuitCode);
+ msg->nextBlockFast(_PREHASH_CircuitCode);
+ msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode);
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
+ msg->sendReliable(
+ gFirstSim,
+ gSavedSettings.getS32("UseCircuitCodeMaxRetries"),
+ FALSE,
+ (F32Seconds)gSavedSettings.getF32("UseCircuitCodeTimeout"),
+ use_circuit_callback,
+ NULL);
+
+ timeout.reset();
+ display_startup();
+
+ return FALSE;
+ }
+
+ //---------------------------------------------------------------------
+ // World Wait
+ //---------------------------------------------------------------------
+ if(STATE_WORLD_WAIT == LLStartUp::getStartupState())
+ {
+ LL_DEBUGS("AppInit") << "Waiting for simulator ack...." << LL_ENDL;
+ set_startup_status(0.59f, LLTrans::getString("LoginWaitingForRegionHandshake"), gAgent.mMOTD);
+ if(gGotUseCircuitCodeAck)
+ {
+ LLStartUp::setStartupState( STATE_AGENT_SEND );
+ }
+ pump_idle_startup_network();
+ return FALSE;
+ }
+
+ //---------------------------------------------------------------------
+ // Agent Send
+ //---------------------------------------------------------------------
+ if (STATE_AGENT_SEND == LLStartUp::getStartupState())
+ {
+ LL_DEBUGS("AppInit") << "Connecting to region..." << LL_ENDL;
+ set_startup_status(0.60f, LLTrans::getString("LoginConnectingToRegion"), gAgent.mMOTD);
+ display_startup();
+ // register with the message system so it knows we're
+ // expecting this message
+ LLMessageSystem* msg = gMessageSystem;
+ msg->setHandlerFuncFast(
+ _PREHASH_AgentMovementComplete,
+ process_agent_movement_complete);
+ LLViewerRegion* regionp = gAgent.getRegion();
+ if(regionp)
+ {
+ send_complete_agent_movement(regionp->getHost());
+ gAssetStorage->setUpstream(regionp->getHost());
+ gCacheName->setUpstream(regionp->getHost());
+ }
+ display_startup();
+
+ // Create login effect
+ // But not on first login, because you can't see your avatar then
+ if (!gAgent.isFirstLogin())
+ {
+ LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
+ effectp->setPositionGlobal(gAgent.getPositionGlobal());
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+ LLHUDManager::getInstance()->sendEffects();
+ }
+
+ LLStartUp::setStartupState( STATE_AGENT_WAIT ); // Go to STATE_AGENT_WAIT
+
+ timeout.reset();
+ display_startup();
+ return FALSE;
+ }
+
+ //---------------------------------------------------------------------
+ // Agent Wait
+ //---------------------------------------------------------------------
+ if (STATE_AGENT_WAIT == LLStartUp::getStartupState())
+ {
+ {
+ LockMessageChecker lmc(gMessageSystem);
+ while (lmc.checkAllMessages(gFrameCount, gServicePump))
+ {
+ if (gAgentMovementCompleted)
+ {
+ // Sometimes we have more than one message in the
+ // queue. break out of this loop and continue
+ // processing. If we don't, then this could skip one
+ // or more login steps.
+ break;
+ }
+ else
+ {
+ LL_DEBUGS("AppInit") << "Awaiting AvatarInitComplete, got "
+ << gMessageSystem->getMessageName() << LL_ENDL;
+ }
+ display_startup();
+ }
+ lmc.processAcks();
+ }
+
+ display_startup();
+
+ if (gAgentMovementCompleted)
+ {
+ LLStartUp::setStartupState( STATE_INVENTORY_SEND );
+ }
+ display_startup();
+
+ if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT)
+ {
+ LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
+ if (gRememberPassword)
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ }
+ else
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
+ }
+ reset_login();
+ }
+ return FALSE;
+ }
+
+ //---------------------------------------------------------------------
+ // Inventory Send
+ //---------------------------------------------------------------------
+ if (STATE_INVENTORY_SEND == LLStartUp::getStartupState())
+ {
+ LL_PROFILE_ZONE_NAMED("State inventory send")
+ display_startup();
// request mute list
LL_INFOS() << "Requesting Mute List" << LL_ENDL;
@@ -1766,47 +1767,47 @@ bool idle_startup()
display_startup();
- // Inform simulator of our language preference
- LLAgentLanguage::update();
-
- display_startup();
- // unpack thin inventory
- LLSD response = LLLoginInstance::getInstance()->getResponse();
- //bool dump_buffer = false;
-
- LLSD inv_lib_root = response["inventory-lib-root"];
- if(inv_lib_root.isDefined())
- {
- // should only be one
- LLSD id = inv_lib_root[0]["folder_id"];
- if(id.isDefined())
- {
- gInventory.setLibraryRootFolderID(id.asUUID());
- }
- }
- display_startup();
-
- LLSD inv_lib_owner = response["inventory-lib-owner"];
- if(inv_lib_owner.isDefined())
- {
- // should only be one
- LLSD id = inv_lib_owner[0]["agent_id"];
- if(id.isDefined())
- {
- gInventory.setLibraryOwnerID(LLUUID(id.asUUID()));
- }
- }
- display_startup();
- LLStartUp::setStartupState(STATE_INVENTORY_SKEL);
- display_startup();
- return FALSE;
- }
+ // Inform simulator of our language preference
+ LLAgentLanguage::update();
+
+ display_startup();
+ // unpack thin inventory
+ LLSD response = LLLoginInstance::getInstance()->getResponse();
+ //bool dump_buffer = false;
+
+ LLSD inv_lib_root = response["inventory-lib-root"];
+ if(inv_lib_root.isDefined())
+ {
+ // should only be one
+ LLSD id = inv_lib_root[0]["folder_id"];
+ if(id.isDefined())
+ {
+ gInventory.setLibraryRootFolderID(id.asUUID());
+ }
+ }
+ display_startup();
+
+ LLSD inv_lib_owner = response["inventory-lib-owner"];
+ if(inv_lib_owner.isDefined())
+ {
+ // should only be one
+ LLSD id = inv_lib_owner[0]["agent_id"];
+ if(id.isDefined())
+ {
+ gInventory.setLibraryOwnerID(LLUUID(id.asUUID()));
+ }
+ }
+ display_startup();
+ LLStartUp::setStartupState(STATE_INVENTORY_SKEL);
+ display_startup();
+ return FALSE;
+ }
if (STATE_INVENTORY_SKEL == LLStartUp::getStartupState())
{
LL_PROFILE_ZONE_NAMED("State inventory load skeleton")
- LLSD response = LLLoginInstance::getInstance()->getResponse();
+ LLSD response = LLLoginInstance::getInstance()->getResponse();
LLSD inv_skel_lib = response["inventory-skel-lib"];
if (inv_skel_lib.isDefined() && gInventory.getLibraryOwnerID().notNull())
@@ -1838,113 +1839,113 @@ bool idle_startup()
{
LL_PROFILE_ZONE_NAMED("State inventory send2")
- LLSD response = LLLoginInstance::getInstance()->getResponse();
-
- LLSD inv_basic = response["inventory-basic"];
- if(inv_basic.isDefined())
- {
- LL_INFOS() << "Basic inventory root folder id is " << inv_basic["folder_id"] << LL_ENDL;
- }
-
- LLSD buddy_list = response["buddy-list"];
- if(buddy_list.isDefined())
- {
- LLAvatarTracker::buddy_map_t list;
- LLUUID agent_id;
- S32 has_rights = 0, given_rights = 0;
- for(LLSD::array_const_iterator it = buddy_list.beginArray(),
- end = buddy_list.endArray(); it != end; ++it)
- {
- LLSD buddy_id = (*it)["buddy_id"];
- if(buddy_id.isDefined())
- {
- agent_id = buddy_id.asUUID();
- }
-
- LLSD buddy_rights_has = (*it)["buddy_rights_has"];
- if(buddy_rights_has.isDefined())
- {
- has_rights = buddy_rights_has.asInteger();
- }
-
- LLSD buddy_rights_given = (*it)["buddy_rights_given"];
- if(buddy_rights_given.isDefined())
- {
- given_rights = buddy_rights_given.asInteger();
- }
-
- list[agent_id] = new LLRelationship(given_rights, has_rights, false);
- }
- LLAvatarTracker::instance().addBuddyList(list);
- display_startup();
- }
-
- bool show_hud = false;
- LLSD tutorial_setting = response["tutorial_setting"];
- if(tutorial_setting.isDefined())
- {
- for(LLSD::array_const_iterator it = tutorial_setting.beginArray(),
- end = tutorial_setting.endArray(); it != end; ++it)
- {
- LLSD tutorial_url = (*it)["tutorial_url"];
- if(tutorial_url.isDefined())
- {
- // Tutorial floater will append language code
- gSavedSettings.setString("TutorialURL", tutorial_url.asString());
- }
-
- // For Viewer 2.0 we are not using the web-based tutorial
- // If we reverse that decision, put this code back and use
- // login.cgi to send a different URL with content that matches
- // the Viewer 2.0 UI.
- //LLSD use_tutorial = (*it)["use_tutorial"];
- //if(use_tutorial.asString() == "true")
- //{
- // show_hud = true;
- //}
- }
- }
- display_startup();
-
- // Either we want to show tutorial because this is the first login
- // to a Linden Help Island or the user quit with the tutorial
- // visible. JC
- if (show_hud || gSavedSettings.getBOOL("ShowTutorial"))
- {
- LLFloaterReg::showInstance("hud", LLSD(), FALSE);
- }
- display_startup();
-
- LLSD event_notifications = response["event_notifications"];
- if(event_notifications.isDefined())
- {
- gEventNotifier.load(event_notifications);
- }
- display_startup();
-
- LLSD classified_categories = response["classified_categories"];
- if(classified_categories.isDefined())
- {
- LLClassifiedInfo::loadCategories(classified_categories);
- }
- display_startup();
-
- // This method MUST be called before gInventory.findCategoryUUIDForType because of
- // gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.
- gInventory.buildParentChildMap();
-
- // If buildParentChildMap succeeded, inventory will now be in
- // a usable state and gInventory.isInventoryUsable() will be
- // true.
-
- // if inventory is unusable, show warning.
- if (!gInventory.isInventoryUsable())
- {
- LLNotificationsUtil::add("InventoryUnusable");
- }
-
+ LLSD response = LLLoginInstance::getInstance()->getResponse();
+
+ LLSD inv_basic = response["inventory-basic"];
+ if(inv_basic.isDefined())
+ {
+ LL_INFOS() << "Basic inventory root folder id is " << inv_basic["folder_id"] << LL_ENDL;
+ }
+
+ LLSD buddy_list = response["buddy-list"];
+ if(buddy_list.isDefined())
+ {
+ LLAvatarTracker::buddy_map_t list;
+ LLUUID agent_id;
+ S32 has_rights = 0, given_rights = 0;
+ for(LLSD::array_const_iterator it = buddy_list.beginArray(),
+ end = buddy_list.endArray(); it != end; ++it)
+ {
+ LLSD buddy_id = (*it)["buddy_id"];
+ if(buddy_id.isDefined())
+ {
+ agent_id = buddy_id.asUUID();
+ }
+
+ LLSD buddy_rights_has = (*it)["buddy_rights_has"];
+ if(buddy_rights_has.isDefined())
+ {
+ has_rights = buddy_rights_has.asInteger();
+ }
+
+ LLSD buddy_rights_given = (*it)["buddy_rights_given"];
+ if(buddy_rights_given.isDefined())
+ {
+ given_rights = buddy_rights_given.asInteger();
+ }
+
+ list[agent_id] = new LLRelationship(given_rights, has_rights, false);
+ }
+ LLAvatarTracker::instance().addBuddyList(list);
+ display_startup();
+ }
+
+ bool show_hud = false;
+ LLSD tutorial_setting = response["tutorial_setting"];
+ if(tutorial_setting.isDefined())
+ {
+ for(LLSD::array_const_iterator it = tutorial_setting.beginArray(),
+ end = tutorial_setting.endArray(); it != end; ++it)
+ {
+ LLSD tutorial_url = (*it)["tutorial_url"];
+ if(tutorial_url.isDefined())
+ {
+ // Tutorial floater will append language code
+ gSavedSettings.setString("TutorialURL", tutorial_url.asString());
+ }
+
+ // For Viewer 2.0 we are not using the web-based tutorial
+ // If we reverse that decision, put this code back and use
+ // login.cgi to send a different URL with content that matches
+ // the Viewer 2.0 UI.
+ //LLSD use_tutorial = (*it)["use_tutorial"];
+ //if(use_tutorial.asString() == "true")
+ //{
+ // show_hud = true;
+ //}
+ }
+ }
+ display_startup();
+
+ // Either we want to show tutorial because this is the first login
+ // to a Linden Help Island or the user quit with the tutorial
+ // visible. JC
+ if (show_hud || gSavedSettings.getBOOL("ShowTutorial"))
+ {
+ LLFloaterReg::showInstance("hud", LLSD(), FALSE);
+ }
+ display_startup();
+
+ LLSD event_notifications = response["event_notifications"];
+ if(event_notifications.isDefined())
+ {
+ gEventNotifier.load(event_notifications);
+ }
+ display_startup();
+
+ LLSD classified_categories = response["classified_categories"];
+ if(classified_categories.isDefined())
+ {
+ LLClassifiedInfo::loadCategories(classified_categories);
+ }
+ display_startup();
+
+ // This method MUST be called before gInventory.findCategoryUUIDForType because of
+ // gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.
+ gInventory.buildParentChildMap();
+
+ // If buildParentChildMap succeeded, inventory will now be in
+ // a usable state and gInventory.isInventoryUsable() will be
+ // true.
+
+ // if inventory is unusable, show warning.
+ if (!gInventory.isInventoryUsable())
+ {
+ LLNotificationsUtil::add("InventoryUnusable");
+ }
+
LLInventoryModelBackgroundFetch::instance().start();
- gInventory.createCommonSystemCategories();
+ gInventory.createCommonSystemCategories();
LLStartUp::setStartupState(STATE_INVENTORY_CALLBACKS );
display_startup();
@@ -1952,7 +1953,7 @@ bool idle_startup()
}
//---------------------------------------------------------------------
- // STATE_INVENTORY_CALLBACKS
+ // STATE_INVENTORY_CALLBACKS
//---------------------------------------------------------------------
if (STATE_INVENTORY_CALLBACKS == LLStartUp::getStartupState())
{
@@ -1974,86 +1975,86 @@ bool idle_startup()
}
- // It's debatable whether this flag is a good idea - sets all
- // bits, and in general it isn't true that inventory
- // initialization generates all types of changes. Maybe add an
- // INITIALIZE mask bit instead?
- gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
- gInventory.notifyObservers();
-
- display_startup();
-
- // set up callbacks
- LL_INFOS() << "Registering Callbacks" << LL_ENDL;
- LLMessageSystem* msg = gMessageSystem;
- LL_INFOS() << " Inventory" << LL_ENDL;
- LLInventoryModel::registerCallbacks(msg);
- LL_INFOS() << " AvatarTracker" << LL_ENDL;
- LLAvatarTracker::instance().registerCallbacks(msg);
- LL_INFOS() << " Landmark" << LL_ENDL;
- LLLandmark::registerCallbacks(msg);
- display_startup();
-
- // request all group information
- LL_INFOS() << "Requesting Agent Data" << LL_ENDL;
- gAgent.sendAgentDataUpdateRequest();
- display_startup();
- // Create the inventory views
- LL_INFOS() << "Creating Inventory Views" << LL_ENDL;
- LLFloaterReg::getInstance("inventory");
- display_startup();
- LLStartUp::setStartupState( STATE_MISC );
- display_startup();
-
- return FALSE;
- }
-
-
- //---------------------------------------------------------------------
- // Misc
- //---------------------------------------------------------------------
- if (STATE_MISC == LLStartUp::getStartupState())
- {
- // We have a region, and just did a big inventory download.
- // We can estimate the user's connection speed, and set their
- // max bandwidth accordingly. JC
- if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
- {
- // This is actually a pessimistic computation, because TCP may not have enough
- // time to ramp up on the (small) default inventory file to truly measure max
- // bandwidth. JC
- F64 rate_bps = LLLoginInstance::getInstance()->getLastTransferRateBPS();
- const F32 FAST_RATE_BPS = 600.f * 1024.f;
- const F32 FASTER_RATE_BPS = 750.f * 1024.f;
- F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
- if (rate_bps > FASTER_RATE_BPS
- && rate_bps > max_bandwidth)
- {
- LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to "
- << FASTER_RATE_BPS/1024.f
- << " kbps" << LL_ENDL;
- gViewerThrottle.setMaxBandwidth(FASTER_RATE_BPS / 1024.f);
- }
- else if (rate_bps > FAST_RATE_BPS
- && rate_bps > max_bandwidth)
- {
- LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to "
- << FAST_RATE_BPS/1024.f
- << " kbps" << LL_ENDL;
- gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f);
- }
-
- if (gSavedSettings.getBOOL("ShowHelpOnFirstLogin"))
- {
- gSavedSettings.setBOOL("HelpFloaterOpen", TRUE);
- }
-
- // Set the show start location to true, now that the user has logged
- // on with this install.
- gSavedSettings.setBOOL("ShowStartLocation", TRUE);
- }
-
- display_startup();
+ // It's debatable whether this flag is a good idea - sets all
+ // bits, and in general it isn't true that inventory
+ // initialization generates all types of changes. Maybe add an
+ // INITIALIZE mask bit instead?
+ gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
+ gInventory.notifyObservers();
+
+ display_startup();
+
+ // set up callbacks
+ LL_INFOS() << "Registering Callbacks" << LL_ENDL;
+ LLMessageSystem* msg = gMessageSystem;
+ LL_INFOS() << " Inventory" << LL_ENDL;
+ LLInventoryModel::registerCallbacks(msg);
+ LL_INFOS() << " AvatarTracker" << LL_ENDL;
+ LLAvatarTracker::instance().registerCallbacks(msg);
+ LL_INFOS() << " Landmark" << LL_ENDL;
+ LLLandmark::registerCallbacks(msg);
+ display_startup();
+
+ // request all group information
+ LL_INFOS() << "Requesting Agent Data" << LL_ENDL;
+ gAgent.sendAgentDataUpdateRequest();
+ display_startup();
+ // Create the inventory views
+ LL_INFOS() << "Creating Inventory Views" << LL_ENDL;
+ LLFloaterReg::getInstance("inventory");
+ display_startup();
+ LLStartUp::setStartupState( STATE_MISC );
+ display_startup();
+
+ return FALSE;
+ }
+
+
+ //---------------------------------------------------------------------
+ // Misc
+ //---------------------------------------------------------------------
+ if (STATE_MISC == LLStartUp::getStartupState())
+ {
+ // We have a region, and just did a big inventory download.
+ // We can estimate the user's connection speed, and set their
+ // max bandwidth accordingly. JC
+ if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
+ {
+ // This is actually a pessimistic computation, because TCP may not have enough
+ // time to ramp up on the (small) default inventory file to truly measure max
+ // bandwidth. JC
+ F64 rate_bps = LLLoginInstance::getInstance()->getLastTransferRateBPS();
+ const F32 FAST_RATE_BPS = 600.f * 1024.f;
+ const F32 FASTER_RATE_BPS = 750.f * 1024.f;
+ F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
+ if (rate_bps > FASTER_RATE_BPS
+ && rate_bps > max_bandwidth)
+ {
+ LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to "
+ << FASTER_RATE_BPS/1024.f
+ << " kbps" << LL_ENDL;
+ gViewerThrottle.setMaxBandwidth(FASTER_RATE_BPS / 1024.f);
+ }
+ else if (rate_bps > FAST_RATE_BPS
+ && rate_bps > max_bandwidth)
+ {
+ LL_DEBUGS("AppInit") << "Fast network connection, increasing max bandwidth to "
+ << FAST_RATE_BPS/1024.f
+ << " kbps" << LL_ENDL;
+ gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f);
+ }
+
+ if (gSavedSettings.getBOOL("ShowHelpOnFirstLogin"))
+ {
+ gSavedSettings.setBOOL("HelpFloaterOpen", TRUE);
+ }
+
+ // Set the show start location to true, now that the user has logged
+ // on with this install.
+ gSavedSettings.setBOOL("ShowStartLocation", TRUE);
+ }
+
+ display_startup();
// Load stored local environment if needed.
LLEnvironment::instance().loadFromSettings();
@@ -2061,368 +2062,370 @@ bool idle_startup()
// *TODO : Uncomment that line once the whole grid migrated to SLM and suppress it from LLAgent::handleTeleportFinished() (llagent.cpp)
//check_merchant_status();
- display_startup();
-
- if (gSavedSettings.getBOOL("HelpFloaterOpen"))
- {
- // show default topic
- LLViewerHelp::instance().showTopic("");
- }
-
- display_startup();
-
- // We're successfully logged in.
- gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE);
-
- LLFloaterReg::showInitialVisibleInstances();
-
- LLFloaterGridStatus::getInstance()->startGridStatusTimer();
-
- display_startup();
-
- display_startup();
- // JC: Initializing audio requests many sounds for download.
- init_audio();
- display_startup();
-
- // JC: Initialize "active" gestures. This may also trigger
- // many gesture downloads, if this is the user's first
- // time on this machine or -purge has been run.
- LLSD gesture_options
- = LLLoginInstance::getInstance()->getResponse("gestures");
- if (gesture_options.isDefined())
- {
- LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size()
- << LL_ENDL;
- uuid_vec_t item_ids;
- for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(),
- end = gesture_options.endArray(); resp_it != end; ++resp_it)
- {
- // If the id is not specifed in the LLSD,
- // the LLSD operator[]() will return a null LLUUID.
- LLUUID item_id = (*resp_it)["item_id"];
- LLUUID asset_id = (*resp_it)["asset_id"];
-
- if (item_id.notNull() && asset_id.notNull())
- {
- // Could schedule and delay these for later.
- const BOOL no_inform_server = FALSE;
- const BOOL no_deactivate_similar = FALSE;
- LLGestureMgr::instance().activateGestureWithAsset(item_id, asset_id,
- no_inform_server,
- no_deactivate_similar);
- // We need to fetch the inventory items for these gestures
- // so we have the names to populate the UI.
- item_ids.push_back(item_id);
- }
- }
- // no need to add gesture to inventory observer, it's already made in constructor
- LLGestureMgr::instance().setFetchIDs(item_ids);
- LLGestureMgr::instance().startFetch();
- }
- gDisplaySwapBuffers = TRUE;
- display_startup();
-
- LLMessageSystem* msg = gMessageSystem;
- msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger);
- msg->setHandlerFuncFast(_PREHASH_PreloadSound, process_preload_sound);
- msg->setHandlerFuncFast(_PREHASH_AttachedSound, process_attached_sound);
- msg->setHandlerFuncFast(_PREHASH_AttachedSoundGainChange, process_attached_sound_gain_change);
-
- LL_DEBUGS("AppInit") << "Initialization complete" << LL_ENDL;
-
- LL_DEBUGS("SceneLoadTiming", "Start") << "Scene Load Started " << LL_ENDL;
- gRenderStartTime.reset();
- gForegroundTime.reset();
-
- // HACK: Inform simulator of window size.
- // Do this here so it's less likely to race with RegisterNewAgent.
- // TODO: Put this into RegisterNewAgent
- // JC - 7/20/2002
- gViewerWindow->sendShapeToSim();
-
- LLPresetsManager::getInstance()->createMissingDefault(PRESETS_CAMERA);
-
- // The reason we show the alert is because we want to
- // reduce confusion for when you log in and your provided
- // location is not your expected location. So, if this is
- // your first login, then you do not have an expectation,
- // thus, do not show this alert.
- if (!gAgent.isFirstLogin())
- {
- LL_INFOS() << "gAgentStartLocation : " << gAgentStartLocation << LL_ENDL;
- LLSLURL start_slurl = LLStartUp::getStartSLURL();
- LL_DEBUGS("AppInit") << "start slurl "<<start_slurl.asString()<<LL_ENDL;
-
- if (((start_slurl.getType() == LLSLURL::LOCATION) && (gAgentStartLocation == "url")) ||
- ((start_slurl.getType() == LLSLURL::LAST_LOCATION) && (gAgentStartLocation == "last")) ||
- ((start_slurl.getType() == LLSLURL::HOME_LOCATION) && (gAgentStartLocation == "home")))
- {
- if (start_slurl.getType() == LLSLURL::LAST_LOCATION
- && gAgentStartLocation == "last"
- && gSavedSettings.getBOOL("RestoreCameraPosOnLogin"))
- {
- // restore old camera pos
- gAgentCamera.setFocusOnAvatar(FALSE, FALSE);
- gAgentCamera.setCameraPosAndFocusGlobal(gSavedSettings.getVector3d("CameraPosOnLogout"), gSavedSettings.getVector3d("FocusPosOnLogout"), LLUUID::null);
- BOOL limit_hit = FALSE;
- gAgentCamera.calcCameraPositionTargetGlobal(&limit_hit);
- if (limit_hit)
- {
- gAgentCamera.setFocusOnAvatar(TRUE, FALSE);
- }
- gAgentCamera.stopCameraAnimation();
- }
- }
- else
- {
- std::string msg;
- switch(start_slurl.getType())
- {
- case LLSLURL::LOCATION:
- {
-
- msg = "AvatarMovedDesired";
- break;
- }
- case LLSLURL::HOME_LOCATION:
- {
- msg = "AvatarMovedHome";
- break;
- }
- default:
- {
- msg = "AvatarMovedLast";
- }
- }
- LLNotificationsUtil::add(msg);
- }
- }
-
- display_startup();
+ display_startup();
+
+ if (gSavedSettings.getBOOL("HelpFloaterOpen"))
+ {
+ // show default topic
+ LLViewerHelp::instance().showTopic("");
+ }
+
+ display_startup();
+
+ // We're successfully logged in.
+ gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE);
+
+ LLFloaterReg::showInitialVisibleInstances();
+
+ LLFloaterGridStatus::getInstance()->startGridStatusTimer();
+
+ display_startup();
+
+ display_startup();
+ // JC: Initializing audio requests many sounds for download.
+ init_audio();
+ display_startup();
+
+ // JC: Initialize "active" gestures. This may also trigger
+ // many gesture downloads, if this is the user's first
+ // time on this machine or -purge has been run.
+ LLSD gesture_options
+ = LLLoginInstance::getInstance()->getResponse("gestures");
+ if (gesture_options.isDefined())
+ {
+ LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size()
+ << LL_ENDL;
+ uuid_vec_t item_ids;
+ for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(),
+ end = gesture_options.endArray(); resp_it != end; ++resp_it)
+ {
+ // If the id is not specifed in the LLSD,
+ // the LLSD operator[]() will return a null LLUUID.
+ LLUUID item_id = (*resp_it)["item_id"];
+ LLUUID asset_id = (*resp_it)["asset_id"];
+
+ if (item_id.notNull() && asset_id.notNull())
+ {
+ // Could schedule and delay these for later.
+ const BOOL no_inform_server = FALSE;
+ const BOOL no_deactivate_similar = FALSE;
+ LLGestureMgr::instance().activateGestureWithAsset(item_id, asset_id,
+ no_inform_server,
+ no_deactivate_similar);
+ // We need to fetch the inventory items for these gestures
+ // so we have the names to populate the UI.
+ item_ids.push_back(item_id);
+ }
+ }
+ // no need to add gesture to inventory observer, it's already made in constructor
+ LLGestureMgr::instance().setFetchIDs(item_ids);
+ LLGestureMgr::instance().startFetch();
+ }
+ gDisplaySwapBuffers = TRUE;
+ display_startup();
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->setHandlerFuncFast(_PREHASH_SoundTrigger, process_sound_trigger);
+ msg->setHandlerFuncFast(_PREHASH_PreloadSound, process_preload_sound);
+ msg->setHandlerFuncFast(_PREHASH_AttachedSound, process_attached_sound);
+ msg->setHandlerFuncFast(_PREHASH_AttachedSoundGainChange, process_attached_sound_gain_change);
+
+ LL_DEBUGS("AppInit") << "Initialization complete" << LL_ENDL;
+
+ LL_DEBUGS("SceneLoadTiming", "Start") << "Scene Load Started " << LL_ENDL;
+ gRenderStartTime.reset();
+ gForegroundTime.reset();
+
+ // HACK: Inform simulator of window size.
+ // Do this here so it's less likely to race with RegisterNewAgent.
+ // TODO: Put this into RegisterNewAgent
+ // JC - 7/20/2002
+ gViewerWindow->sendShapeToSim();
+
+ LLPresetsManager::getInstance()->createMissingDefault(PRESETS_CAMERA);
+
+ // The reason we show the alert is because we want to
+ // reduce confusion for when you log in and your provided
+ // location is not your expected location. So, if this is
+ // your first login, then you do not have an expectation,
+ // thus, do not show this alert.
+ if (!gAgent.isFirstLogin())
+ {
+ LL_INFOS() << "gAgentStartLocation : " << gAgentStartLocation << LL_ENDL;
+ LLSLURL start_slurl = LLStartUp::getStartSLURL();
+ LL_DEBUGS("AppInit") << "start slurl "<<start_slurl.asString()<<LL_ENDL;
+
+ if (((start_slurl.getType() == LLSLURL::LOCATION) && (gAgentStartLocation == "url")) ||
+ ((start_slurl.getType() == LLSLURL::LAST_LOCATION) && (gAgentStartLocation == "last")) ||
+ ((start_slurl.getType() == LLSLURL::HOME_LOCATION) && (gAgentStartLocation == "home")))
+ {
+ if (start_slurl.getType() == LLSLURL::LAST_LOCATION
+ && gAgentStartLocation == "last"
+ && gSavedSettings.getBOOL("RestoreCameraPosOnLogin"))
+ {
+ // restore old camera pos
+ gAgentCamera.setFocusOnAvatar(FALSE, FALSE);
+ gAgentCamera.setCameraPosAndFocusGlobal(gSavedSettings.getVector3d("CameraPosOnLogout"), gSavedSettings.getVector3d("FocusPosOnLogout"), LLUUID::null);
+ BOOL limit_hit = FALSE;
+ gAgentCamera.calcCameraPositionTargetGlobal(&limit_hit);
+ if (limit_hit)
+ {
+ gAgentCamera.setFocusOnAvatar(TRUE, FALSE);
+ }
+ gAgentCamera.stopCameraAnimation();
+ }
+ }
+ else
+ {
+ std::string msg;
+ switch(start_slurl.getType())
+ {
+ case LLSLURL::LOCATION:
+ {
+
+ msg = "AvatarMovedDesired";
+ break;
+ }
+ case LLSLURL::HOME_LOCATION:
+ {
+ msg = "AvatarMovedHome";
+ break;
+ }
+ default:
+ {
+ msg = "AvatarMovedLast";
+ }
+ }
+ LLNotificationsUtil::add(msg);
+ }
+ }
+
+ display_startup();
//DEV-17797. get null folder. Any items found here moved to Lost and Found
LLInventoryModelBackgroundFetch::instance().findLostItems();
- display_startup();
-
- LLStartUp::setStartupState( STATE_PRECACHE );
- timeout.reset();
- return FALSE;
- }
-
- if (STATE_PRECACHE == LLStartUp::getStartupState())
- {
- display_startup();
- F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY;
-
- // We now have an inventory skeleton, so if this is a user's first
- // login, we can start setting up their clothing and avatar
- // appearance. This helps to avoid the generic "Ruth" avatar in
- // the orientation island tutorial experience. JC
- if (gAgent.isFirstLogin()
- && !sInitialOutfit.empty() // registration set up an outfit
- && !sInitialOutfitGender.empty() // and a gender
- && isAgentAvatarValid() // can't wear clothes without object
- && !gAgent.isOutfitChosen()) // nothing already loading
- {
- // Start loading the wearables, textures, gestures
- LLStartUp::loadInitialOutfit( sInitialOutfit, sInitialOutfitGender );
- }
- // If not first login, we need to fetch COF contents and
- // compute appearance from that.
- if (isAgentAvatarValid() && !gAgent.isFirstLogin() && !gAgent.isOutfitChosen())
- {
- gAgentWearables.notifyLoadingStarted();
- gAgent.setOutfitChosen(TRUE);
- gAgentWearables.sendDummyAgentWearablesUpdate();
+ display_startup();
+
+ LLStartUp::setStartupState( STATE_PRECACHE );
+ timeout.reset();
+ return FALSE;
+ }
+
+ if (STATE_PRECACHE == LLStartUp::getStartupState())
+ {
+ display_startup();
+ F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY;
+
+ // We now have an inventory skeleton, so if this is a user's first
+ // login, we can start setting up their clothing and avatar
+ // appearance. This helps to avoid the generic "Ruth" avatar in
+ // the orientation island tutorial experience. JC
+ if (gAgent.isFirstLogin()
+ && !sInitialOutfit.empty() // registration set up an outfit
+ && !sInitialOutfitGender.empty() // and a gender
+ && isAgentAvatarValid() // can't wear clothes without object
+ && !gAgent.isOutfitChosen()) // nothing already loading
+ {
+ // Start loading the wearables, textures, gestures
+ LLStartUp::loadInitialOutfit( sInitialOutfit, sInitialOutfitGender );
+ }
+ // If not first login, we need to fetch COF contents and
+ // compute appearance from that.
+ if (isAgentAvatarValid() && !gAgent.isFirstLogin() && !gAgent.isOutfitChosen())
+ {
+ gAgentWearables.notifyLoadingStarted();
+ gAgent.setOutfitChosen(TRUE);
+ gAgentWearables.sendDummyAgentWearablesUpdate();
callAfterCOFFetch(set_flags_and_update_appearance);
- }
-
- display_startup();
-
- // wait precache-delay and for agent's avatar or a lot longer.
- if ((timeout_frac > 1.f) && isAgentAvatarValid())
- {
- LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
- }
- else if (timeout_frac > 10.f)
- {
- // If we exceed the wait above while isAgentAvatarValid is
- // not true yet, we will change startup state and
- // eventually (once avatar does get created) wind up at
- // the gender chooser. This should occur only in very
- // unusual circumstances, so set the timeout fairly high
- // to minimize mistaken hits here.
- LL_WARNS() << "Wait for valid avatar state exceeded "
- << timeout.getElapsedTimeF32() << " will invoke gender chooser" << LL_ENDL;
- LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
- }
- else
- {
- update_texture_fetch();
- set_startup_status(0.60f + 0.30f * timeout_frac,
- LLTrans::getString("LoginPrecaching"),
- gAgent.mMOTD.c_str());
- display_startup();
- }
-
- return TRUE;
- }
-
- if (STATE_WEARABLES_WAIT == LLStartUp::getStartupState())
- {
- static LLFrameTimer wearables_timer;
-
- const F32 wearables_time = wearables_timer.getElapsedTimeF32();
- static LLCachedControl<F32> max_wearables_time(gSavedSettings, "ClothingLoadingDelay");
-
- if (!gAgent.isOutfitChosen() && isAgentAvatarValid())
- {
- // No point in waiting for clothing, we don't even know
- // what outfit we want. Pop up a gender chooser dialog to
- // ask and proceed to draw the world. JC
- //
- // *NOTE: We might hit this case even if we have an
- // initial outfit, but if the load hasn't started
- // already then something is wrong so fall back
- // to generic outfits. JC
- LLNotificationsUtil::add("WelcomeChooseSex", LLSD(), LLSD(),
- callback_choose_gender);
- LLStartUp::setStartupState( STATE_CLEANUP );
- }
-
- display_startup();
-
- if (gAgent.isOutfitChosen() && (wearables_time > max_wearables_time))
- {
- if (gInventory.isInventoryUsable())
- {
- LLNotificationsUtil::add("ClothingLoading");
- }
- record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time);
- LLStartUp::setStartupState( STATE_CLEANUP );
- }
- else if (gAgent.isFirstLogin()
- && isAgentAvatarValid()
- && gAgentAvatarp->isFullyLoaded())
- {
- // wait for avatar to be completely loaded
- if (isAgentAvatarValid()
- && gAgentAvatarp->isFullyLoaded())
- {
- LL_DEBUGS("Avatar") << "avatar fully loaded" << LL_ENDL;
- LLStartUp::setStartupState( STATE_CLEANUP );
- return TRUE;
- }
- }
- else
- {
- // OK to just get the wearables
- if ( gAgentWearables.areWearablesLoaded() )
- {
- // We have our clothing, proceed.
- LL_DEBUGS("Avatar") << "wearables loaded" << LL_ENDL;
- LLStartUp::setStartupState( STATE_CLEANUP );
- return TRUE;
- }
- }
- //fall through this frame to STATE_CLEANUP
- }
-
- if (STATE_CLEANUP == LLStartUp::getStartupState())
- {
- set_startup_status(1.0, "", "");
- display_startup();
-
- if (!mBenefitsSuccessfullyInit)
- {
- LLNotificationsUtil::add("FailedToGetBenefits", LLSD(), LLSD(), boost::bind(on_benefits_failed_callback, _1, _2));
- }
-
- // Let the map know about the inventory.
- LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
- if(floater_world_map)
- {
- floater_world_map->observeInventory(&gInventory);
- floater_world_map->observeFriends();
- }
- gViewerWindow->showCursor();
- gViewerWindow->getWindow()->resetBusyCount();
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
- LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL;
- //gViewerWindow->revealIntroPanel();
- gViewerWindow->setStartupComplete();
- gViewerWindow->setProgressCancelButtonVisible(FALSE);
- display_startup();
-
- // We're not away from keyboard, even though login might have taken
- // a while. JC
- gAgent.clearAFK();
-
- // Have the agent start watching the friends list so we can update proxies
- gAgent.observeFriends();
-
- // Start automatic replay if the flag is set.
- if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession())
- {
- LL_DEBUGS("AppInit") << "Starting automatic playback" << LL_ENDL;
- gAgentPilot.startPlayback();
- }
-
- show_debug_menus(); // Debug menu visiblity and First Use trigger
-
- // If we've got a startup URL, dispatch it
- //LLStartUp::dispatchURL();
-
- // Retrieve information about the land data
- // (just accessing this the first time will fetch it,
- // then the data is cached for the viewer's lifetime)
- LLProductInfoRequestManager::instance();
-
- // *FIX:Mani - What do I do here?
- // Need we really clear the Auth response data?
- // Clean up the userauth stuff.
- // LLUserAuth::getInstance()->reset();
-
- LLStartUp::setStartupState( STATE_STARTED );
- display_startup();
-
- // Unmute audio if desired and setup volumes.
- // This is a not-uncommon crash site, so surround it with
- // LL_INFOS() output to aid diagnosis.
- LL_INFOS("AppInit") << "Doing first audio_update_volume..." << LL_ENDL;
- audio_update_volume();
- LL_INFOS("AppInit") << "Done first audio_update_volume." << LL_ENDL;
-
- // reset keyboard focus to sane state of pointing at world
- gFocusMgr.setKeyboardFocus(NULL);
-
- LLAppViewer::instance()->handleLoginComplete();
-
- LLAgentPicksInfo::getInstance()->requestNumberOfPicks();
-
- display_startup();
-
- llassert(LLPathfindingManager::getInstance() != NULL);
- LLPathfindingManager::getInstance()->initSystem();
-
- gAgentAvatarp->sendHoverHeight();
-
- // look for parcels we own
- send_places_query(LLUUID::null,
- LLUUID::null,
- "",
- DFQ_AGENT_OWNED,
- LLParcel::C_ANY,
- "");
-
- LLUIUsage::instance().clear();
+ }
+
+ display_startup();
+
+ // wait precache-delay and for agent's avatar or a lot longer.
+ if ((timeout_frac > 1.f) && isAgentAvatarValid())
+ {
+ LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
+ }
+ else if (timeout_frac > 10.f)
+ {
+ // If we exceed the wait above while isAgentAvatarValid is
+ // not true yet, we will change startup state and
+ // eventually (once avatar does get created) wind up at
+ // the gender chooser. This should occur only in very
+ // unusual circumstances, so set the timeout fairly high
+ // to minimize mistaken hits here.
+ LL_WARNS() << "Wait for valid avatar state exceeded "
+ << timeout.getElapsedTimeF32() << " will invoke gender chooser" << LL_ENDL;
+ LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
+ }
+ else
+ {
+ update_texture_fetch();
+ set_startup_status(0.60f + 0.30f * timeout_frac,
+ LLTrans::getString("LoginPrecaching"),
+ gAgent.mMOTD.c_str());
+ display_startup();
+ }
+
+ return TRUE;
+ }
+
+ if (STATE_WEARABLES_WAIT == LLStartUp::getStartupState())
+ {
+ static LLFrameTimer wearables_timer;
+
+ const F32 wearables_time = wearables_timer.getElapsedTimeF32();
+ static LLCachedControl<F32> max_wearables_time(gSavedSettings, "ClothingLoadingDelay");
+
+ if (!gAgent.isOutfitChosen() && isAgentAvatarValid())
+ {
+ // No point in waiting for clothing, we don't even know
+ // what outfit we want. Pop up a gender chooser dialog to
+ // ask and proceed to draw the world. JC
+ //
+ // *NOTE: We might hit this case even if we have an
+ // initial outfit, but if the load hasn't started
+ // already then something is wrong so fall back
+ // to generic outfits. JC
+ LLNotificationsUtil::add("WelcomeChooseSex", LLSD(), LLSD(),
+ callback_choose_gender);
+ LLStartUp::setStartupState( STATE_CLEANUP );
+ }
+
+ display_startup();
+
+ if (gAgent.isOutfitChosen() && (wearables_time > max_wearables_time))
+ {
+ if (gInventory.isInventoryUsable())
+ {
+ LLNotificationsUtil::add("ClothingLoading");
+ }
+ record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time);
+ LLStartUp::setStartupState( STATE_CLEANUP );
+ }
+ else if (gAgent.isFirstLogin()
+ && isAgentAvatarValid()
+ && gAgentAvatarp->isFullyLoaded())
+ {
+ // wait for avatar to be completely loaded
+ if (isAgentAvatarValid()
+ && gAgentAvatarp->isFullyLoaded())
+ {
+ LL_DEBUGS("Avatar") << "avatar fully loaded" << LL_ENDL;
+ LLStartUp::setStartupState( STATE_CLEANUP );
+ return TRUE;
+ }
+ }
+ else
+ {
+ // OK to just get the wearables
+ if ( gAgentWearables.areWearablesLoaded() )
+ {
+ // We have our clothing, proceed.
+ LL_DEBUGS("Avatar") << "wearables loaded" << LL_ENDL;
+ LLStartUp::setStartupState( STATE_CLEANUP );
+ return TRUE;
+ }
+ }
+ //fall through this frame to STATE_CLEANUP
+ }
+
+ if (STATE_CLEANUP == LLStartUp::getStartupState())
+ {
+ set_startup_status(1.0, "", "");
+ display_startup();
+
+ if (!mBenefitsSuccessfullyInit)
+ {
+ LLNotificationsUtil::add("FailedToGetBenefits", LLSD(), LLSD(), boost::bind(on_benefits_failed_callback, _1, _2));
+ }
+
+ // Let the map know about the inventory.
+ LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
+ if(floater_world_map)
+ {
+ floater_world_map->observeInventory(&gInventory);
+ floater_world_map->observeFriends();
+ }
+ gViewerWindow->showCursor();
+ gViewerWindow->getWindow()->resetBusyCount();
+ gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL;
+ //gViewerWindow->revealIntroPanel();
+ gViewerWindow->setStartupComplete();
+ gViewerWindow->setProgressCancelButtonVisible(FALSE);
+ display_startup();
+
+ // We're not away from keyboard, even though login might have taken
+ // a while. JC
+ gAgent.clearAFK();
+
+ // Have the agent start watching the friends list so we can update proxies
+ gAgent.observeFriends();
+
+ // Start automatic replay if the flag is set.
+ if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession())
+ {
+ LL_DEBUGS("AppInit") << "Starting automatic playback" << LL_ENDL;
+ gAgentPilot.startPlayback();
+ }
+
+ show_debug_menus(); // Debug menu visiblity and First Use trigger
+
+ // If we've got a startup URL, dispatch it
+ //LLStartUp::dispatchURL();
+
+ // Retrieve information about the land data
+ // (just accessing this the first time will fetch it,
+ // then the data is cached for the viewer's lifetime)
+ LLProductInfoRequestManager::instance();
+
+ // *FIX:Mani - What do I do here?
+ // Need we really clear the Auth response data?
+ // Clean up the userauth stuff.
+ // LLUserAuth::getInstance()->reset();
+
+ LLStartUp::setStartupState( STATE_STARTED );
+ display_startup();
+
+ // Unmute audio if desired and setup volumes.
+ // This is a not-uncommon crash site, so surround it with
+ // LL_INFOS() output to aid diagnosis.
+ LL_INFOS("AppInit") << "Doing first audio_update_volume..." << LL_ENDL;
+ audio_update_volume();
+ LL_INFOS("AppInit") << "Done first audio_update_volume." << LL_ENDL;
+
+ // reset keyboard focus to sane state of pointing at world
+ gFocusMgr.setKeyboardFocus(NULL);
+
+ LLAppViewer::instance()->handleLoginComplete();
+
+ LLAgentPicksInfo::getInstance()->requestNumberOfPicks();
+
+ display_startup();
+
+ llassert(LLPathfindingManager::getInstance() != NULL);
+ LLPathfindingManager::getInstance()->initSystem();
+
+ gAgentAvatarp->sendHoverHeight();
+
+ // look for parcels we own
+ send_places_query(LLUUID::null,
+ LLUUID::null,
+ "",
+ DFQ_AGENT_OWNED,
+ LLParcel::C_ANY,
+ "");
+
+ LLUIUsage::instance().clear();
LLPerfStats::StatsRecorder::setAutotuneInit();
- return TRUE;
- }
+ LLLUAmanager::runScriptOnLogin();
- return TRUE;
+ return TRUE;
+ }
+
+ return TRUE;
}
//
@@ -2431,50 +2434,50 @@ bool idle_startup()
void login_show()
{
- LL_INFOS("AppInit") << "Initializing Login Screen" << LL_ENDL;
-
- // Hide the toolbars: may happen to come back here if login fails after login agent but before login in region
- if (gToolBarView)
- {
- gToolBarView->setVisible(FALSE);
- }
-
- LLPanelLogin::show( gViewerWindow->getWindowRectScaled(), login_callback, NULL );
+ LL_INFOS("AppInit") << "Initializing Login Screen" << LL_ENDL;
+
+ // Hide the toolbars: may happen to come back here if login fails after login agent but before login in region
+ if (gToolBarView)
+ {
+ gToolBarView->setVisible(FALSE);
+ }
+
+ LLPanelLogin::show( gViewerWindow->getWindowRectScaled(), login_callback, NULL );
}
// Callback for when login screen is closed. Option 0 = connect, option 1 = quit.
void login_callback(S32 option, void *userdata)
{
- const S32 CONNECT_OPTION = 0;
- const S32 QUIT_OPTION = 1;
-
- if (CONNECT_OPTION == option)
- {
- LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
- return;
- }
- else if (QUIT_OPTION == option) // *TODO: THIS CODE SEEMS TO BE UNREACHABLE!!!!! login_callback is never called with option equal to QUIT_OPTION
- {
- if (!gSavedSettings.getBOOL("RememberPassword"))
- {
- // turn off the setting and write out to disk
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile") , TRUE );
- LLUIColorTable::instance().saveUserSettings();
- }
-
- // Next iteration through main loop should shut down the app cleanly.
- LLAppViewer::instance()->userQuit();
-
- if (LLAppViewer::instance()->quitRequested())
- {
- LLPanelLogin::closePanel();
- }
- return;
- }
- else
- {
- LL_WARNS("AppInit") << "Unknown login button clicked" << LL_ENDL;
- }
+ const S32 CONNECT_OPTION = 0;
+ const S32 QUIT_OPTION = 1;
+
+ if (CONNECT_OPTION == option)
+ {
+ LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
+ return;
+ }
+ else if (QUIT_OPTION == option) // *TODO: THIS CODE SEEMS TO BE UNREACHABLE!!!!! login_callback is never called with option equal to QUIT_OPTION
+ {
+ if (!gSavedSettings.getBOOL("RememberPassword"))
+ {
+ // turn off the setting and write out to disk
+ gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile") , TRUE );
+ LLUIColorTable::instance().saveUserSettings();
+ }
+
+ // Next iteration through main loop should shut down the app cleanly.
+ LLAppViewer::instance()->userQuit();
+
+ if (LLAppViewer::instance()->quitRequested())
+ {
+ LLPanelLogin::closePanel();
+ }
+ return;
+ }
+ else
+ {
+ LL_WARNS("AppInit") << "Unknown login button clicked" << LL_ENDL;
+ }
}
void release_notes_coro(const std::string url)
@@ -2556,35 +2559,35 @@ void show_release_notes_if_required()
void show_first_run_dialog()
{
- LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback);
+ LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback);
}
bool first_run_dialog_callback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (0 == option)
- {
- LL_DEBUGS("AppInit") << "First run dialog cancelling" << LL_ENDL;
- LLWeb::loadURLExternal(LLTrans::getString("create_account_url") );
- }
-
- LLPanelLogin::giveFocus();
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ LL_DEBUGS("AppInit") << "First run dialog cancelling" << LL_ENDL;
+ LLWeb::loadURLExternal(LLTrans::getString("create_account_url") );
+ }
+
+ LLPanelLogin::giveFocus();
+ return false;
}
void set_startup_status(const F32 frac, const std::string& string, const std::string& msg)
{
- gViewerWindow->setProgressPercent(frac*100);
- gViewerWindow->setProgressString(string);
+ gViewerWindow->setProgressPercent(frac*100);
+ gViewerWindow->setProgressString(string);
- gViewerWindow->setProgressMessage(msg);
+ gViewerWindow->setProgressMessage(msg);
}
bool login_alert_status(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// Buttons
switch( option )
{
@@ -2595,222 +2598,222 @@ bool login_alert_status(const LLSD& notification, const LLSD& response)
// break;
case 2: // Teleport
// Restart the login process, starting at our home locaton
- LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME));
+ LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME));
LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
break;
default:
LL_WARNS("AppInit") << "Missing case in login_alert_status switch" << LL_ENDL;
}
- LLPanelLogin::giveFocus();
- return false;
+ LLPanelLogin::giveFocus();
+ return false;
}
void use_circuit_callback(void**, S32 result)
{
- // bail if we're quitting.
- if(LLApp::isExiting()) return;
- if( !gUseCircuitCallbackCalled )
- {
- gUseCircuitCallbackCalled = true;
- if (result)
- {
- // Make sure user knows something bad happened. JC
- LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
- if (gRememberPassword)
- {
- LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
- }
- else
- {
- LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
- }
- reset_login();
- }
- else
- {
- gGotUseCircuitCodeAck = true;
- }
- }
+ // bail if we're quitting.
+ if(LLApp::isExiting()) return;
+ if( !gUseCircuitCallbackCalled )
+ {
+ gUseCircuitCallbackCalled = true;
+ if (result)
+ {
+ // Make sure user knows something bad happened. JC
+ LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
+ if (gRememberPassword)
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ }
+ else
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
+ }
+ reset_login();
+ }
+ else
+ {
+ gGotUseCircuitCodeAck = true;
+ }
+ }
}
void register_viewer_callbacks(LLMessageSystem* msg)
{
- msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data );
- msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update );
- msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update );
- msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update );
- msg->setHandlerFuncFast(_PREHASH_ImprovedTerseObjectUpdate, process_terse_object_update_improved );
- msg->setHandlerFunc("SimStats", process_sim_stats);
- msg->setHandlerFuncFast(_PREHASH_HealthMessage, process_health_message );
- msg->setHandlerFuncFast(_PREHASH_EconomyData, process_economy_data);
- msg->setHandlerFunc("RegionInfo", LLViewerRegion::processRegionInfo);
-
- msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator);
- msg->setHandlerFuncFast(_PREHASH_KillObject, process_kill_object, NULL);
- msg->setHandlerFuncFast(_PREHASH_SimulatorViewerTimeMessage, process_time_synch, NULL);
- msg->setHandlerFuncFast(_PREHASH_EnableSimulator, process_enable_simulator);
- msg->setHandlerFuncFast(_PREHASH_DisableSimulator, process_disable_simulator);
- msg->setHandlerFuncFast(_PREHASH_KickUser, process_kick_user, NULL);
-
- msg->setHandlerFunc("CrossedRegion", process_crossed_region);
- msg->setHandlerFuncFast(_PREHASH_TeleportFinish, process_teleport_finish);
-
- msg->setHandlerFuncFast(_PREHASH_AlertMessage, process_alert_message);
- msg->setHandlerFunc("AgentAlertMessage", process_agent_alert_message);
- msg->setHandlerFuncFast(_PREHASH_MeanCollisionAlert, process_mean_collision_alert_message, NULL);
- msg->setHandlerFunc("ViewerFrozenMessage", process_frozen_message);
-
- msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value);
- msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value);
- msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation);
- msg->setHandlerFuncFast(_PREHASH_ObjectAnimation, process_object_animation);
- msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance);
- msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint);
- msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response);
- msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties);
- msg->setHandlerFunc("ClearFollowCamProperties", process_clear_follow_cam_properties);
-
- msg->setHandlerFuncFast(_PREHASH_ImprovedInstantMessage, process_improved_im);
- msg->setHandlerFuncFast(_PREHASH_ScriptQuestion, process_script_question);
- msg->setHandlerFuncFast(_PREHASH_ObjectProperties, LLSelectMgr::processObjectProperties, NULL);
- msg->setHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, LLSelectMgr::processObjectPropertiesFamily, NULL);
- msg->setHandlerFunc("ForceObjectSelect", LLSelectMgr::processForceObjectSelect);
-
- msg->setHandlerFuncFast(_PREHASH_MoneyBalanceReply, process_money_balance_reply, NULL);
- msg->setHandlerFuncFast(_PREHASH_CoarseLocationUpdate, LLWorld::processCoarseUpdate, NULL);
- msg->setHandlerFuncFast(_PREHASH_ReplyTaskInventory, LLViewerObject::processTaskInv, NULL);
- msg->setHandlerFuncFast(_PREHASH_DerezContainer, process_derez_container, NULL);
- msg->setHandlerFuncFast(_PREHASH_ScriptRunningReply,
- &LLLiveLSLEditor::processScriptRunningReply);
-
- msg->setHandlerFuncFast(_PREHASH_DeRezAck, process_derez_ack);
-
- msg->setHandlerFunc("LogoutReply", process_logout_reply);
-
- //msg->setHandlerFuncFast(_PREHASH_AddModifyAbility,
- // &LLAgent::processAddModifyAbility);
- //msg->setHandlerFuncFast(_PREHASH_RemoveModifyAbility,
- // &LLAgent::processRemoveModifyAbility);
- msg->setHandlerFuncFast(_PREHASH_AgentDataUpdate,
- &LLAgent::processAgentDataUpdate);
- msg->setHandlerFuncFast(_PREHASH_AgentGroupDataUpdate,
- &LLAgent::processAgentGroupDataUpdate);
- msg->setHandlerFunc("AgentDropGroup",
- &LLAgent::processAgentDropGroup);
- // land ownership messages
- msg->setHandlerFuncFast(_PREHASH_ParcelOverlay,
- LLViewerParcelMgr::processParcelOverlay);
- msg->setHandlerFuncFast(_PREHASH_ParcelProperties,
- LLViewerParcelMgr::processParcelProperties);
- msg->setHandlerFunc("ParcelAccessListReply",
- LLViewerParcelMgr::processParcelAccessListReply);
- msg->setHandlerFunc("ParcelDwellReply",
- LLViewerParcelMgr::processParcelDwellReply);
-
- msg->setHandlerFunc("AvatarPropertiesReply",
- &LLAvatarPropertiesProcessor::processAvatarPropertiesReply);
- msg->setHandlerFunc("AvatarInterestsReply",
- &LLAvatarPropertiesProcessor::processAvatarInterestsReply);
- msg->setHandlerFunc("AvatarGroupsReply",
- &LLAvatarPropertiesProcessor::processAvatarGroupsReply);
- // ratings deprecated
- //msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply,
- // LLPanelAvatar::processAvatarStatisticsReply);
- msg->setHandlerFunc("AvatarNotesReply",
- &LLAvatarPropertiesProcessor::processAvatarNotesReply);
- msg->setHandlerFunc("AvatarPicksReply",
- &LLAvatarPropertiesProcessor::processAvatarPicksReply);
- msg->setHandlerFunc("AvatarClassifiedReply",
- &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply);
-
- msg->setHandlerFuncFast(_PREHASH_CreateGroupReply,
- LLGroupMgr::processCreateGroupReply);
- msg->setHandlerFuncFast(_PREHASH_JoinGroupReply,
- LLGroupMgr::processJoinGroupReply);
- msg->setHandlerFuncFast(_PREHASH_EjectGroupMemberReply,
- LLGroupMgr::processEjectGroupMemberReply);
- msg->setHandlerFuncFast(_PREHASH_LeaveGroupReply,
- LLGroupMgr::processLeaveGroupReply);
- msg->setHandlerFuncFast(_PREHASH_GroupProfileReply,
- LLGroupMgr::processGroupPropertiesReply);
-
- // ratings deprecated
- // msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply,
- // LLFloaterRate::processReputationIndividualReply);
-
- msg->setHandlerFunc("ScriptControlChange",
- LLAgent::processScriptControlChange );
-
- msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect);
-
- msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers);
-
- msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply,
- LLPanelGroupLandMoney::processGroupAccountSummaryReply);
- msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply,
- LLPanelGroupLandMoney::processGroupAccountDetailsReply);
- msg->setHandlerFuncFast(_PREHASH_GroupAccountTransactionsReply,
- LLPanelGroupLandMoney::processGroupAccountTransactionsReply);
-
- msg->setHandlerFuncFast(_PREHASH_UserInfoReply,
- process_user_info_reply);
-
- msg->setHandlerFunc("RegionHandshake", process_region_handshake, NULL);
-
- msg->setHandlerFunc("TeleportStart", process_teleport_start );
- msg->setHandlerFunc("TeleportProgress", process_teleport_progress);
- msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL);
- msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL);
-
- msg->setHandlerFunc("ImageNotInDatabase", LLViewerTextureList::processImageNotInDatabase, NULL);
-
- msg->setHandlerFuncFast(_PREHASH_GroupMembersReply,
- LLGroupMgr::processGroupMembersReply);
- msg->setHandlerFunc("GroupRoleDataReply",
- LLGroupMgr::processGroupRoleDataReply);
- msg->setHandlerFunc("GroupRoleMembersReply",
- LLGroupMgr::processGroupRoleMembersReply);
- msg->setHandlerFunc("GroupTitlesReply",
- LLGroupMgr::processGroupTitlesReply);
- // Special handler as this message is sometimes used for group land.
- msg->setHandlerFunc("PlacesReply", process_places_reply);
- msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply);
-
- msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply);
-
- msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply);
- msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply);
- msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply);
-
- msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply);
- msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply);
- msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply);
- msg->setHandlerFunc("ScriptDialog", process_script_dialog);
- msg->setHandlerFunc("LoadURL", process_load_url);
- msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request);
- msg->setHandlerFunc("EstateCovenantReply", process_covenant_reply);
-
- // calling cards
- msg->setHandlerFunc("OfferCallingCard", process_offer_callingcard);
- msg->setHandlerFunc("AcceptCallingCard", process_accept_callingcard);
- msg->setHandlerFunc("DeclineCallingCard", process_decline_callingcard);
-
- msg->setHandlerFunc("ParcelObjectOwnersReply", LLPanelLandObjects::processParcelObjectOwnersReply);
-
- msg->setHandlerFunc("InitiateDownload", process_initiate_download);
- msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply);
+ msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data );
+ msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update );
+ msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update );
+ msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update );
+ msg->setHandlerFuncFast(_PREHASH_ImprovedTerseObjectUpdate, process_terse_object_update_improved );
+ msg->setHandlerFunc("SimStats", process_sim_stats);
+ msg->setHandlerFuncFast(_PREHASH_HealthMessage, process_health_message );
+ msg->setHandlerFuncFast(_PREHASH_EconomyData, process_economy_data);
+ msg->setHandlerFunc("RegionInfo", LLViewerRegion::processRegionInfo);
+
+ msg->setHandlerFuncFast(_PREHASH_ChatFromSimulator, process_chat_from_simulator);
+ msg->setHandlerFuncFast(_PREHASH_KillObject, process_kill_object, NULL);
+ msg->setHandlerFuncFast(_PREHASH_SimulatorViewerTimeMessage, process_time_synch, NULL);
+ msg->setHandlerFuncFast(_PREHASH_EnableSimulator, process_enable_simulator);
+ msg->setHandlerFuncFast(_PREHASH_DisableSimulator, process_disable_simulator);
+ msg->setHandlerFuncFast(_PREHASH_KickUser, process_kick_user, NULL);
+
+ msg->setHandlerFunc("CrossedRegion", process_crossed_region);
+ msg->setHandlerFuncFast(_PREHASH_TeleportFinish, process_teleport_finish);
+
+ msg->setHandlerFuncFast(_PREHASH_AlertMessage, process_alert_message);
+ msg->setHandlerFunc("AgentAlertMessage", process_agent_alert_message);
+ msg->setHandlerFuncFast(_PREHASH_MeanCollisionAlert, process_mean_collision_alert_message, NULL);
+ msg->setHandlerFunc("ViewerFrozenMessage", process_frozen_message);
+
+ msg->setHandlerFuncFast(_PREHASH_NameValuePair, process_name_value);
+ msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair, process_remove_name_value);
+ msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation);
+ msg->setHandlerFuncFast(_PREHASH_ObjectAnimation, process_object_animation);
+ msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance);
+ msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint);
+ msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response);
+ msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties);
+ msg->setHandlerFunc("ClearFollowCamProperties", process_clear_follow_cam_properties);
+
+ msg->setHandlerFuncFast(_PREHASH_ImprovedInstantMessage, process_improved_im);
+ msg->setHandlerFuncFast(_PREHASH_ScriptQuestion, process_script_question);
+ msg->setHandlerFuncFast(_PREHASH_ObjectProperties, LLSelectMgr::processObjectProperties, NULL);
+ msg->setHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, LLSelectMgr::processObjectPropertiesFamily, NULL);
+ msg->setHandlerFunc("ForceObjectSelect", LLSelectMgr::processForceObjectSelect);
+
+ msg->setHandlerFuncFast(_PREHASH_MoneyBalanceReply, process_money_balance_reply, NULL);
+ msg->setHandlerFuncFast(_PREHASH_CoarseLocationUpdate, LLWorld::processCoarseUpdate, NULL);
+ msg->setHandlerFuncFast(_PREHASH_ReplyTaskInventory, LLViewerObject::processTaskInv, NULL);
+ msg->setHandlerFuncFast(_PREHASH_DerezContainer, process_derez_container, NULL);
+ msg->setHandlerFuncFast(_PREHASH_ScriptRunningReply,
+ &LLLiveLSLEditor::processScriptRunningReply);
+
+ msg->setHandlerFuncFast(_PREHASH_DeRezAck, process_derez_ack);
+
+ msg->setHandlerFunc("LogoutReply", process_logout_reply);
+
+ //msg->setHandlerFuncFast(_PREHASH_AddModifyAbility,
+ // &LLAgent::processAddModifyAbility);
+ //msg->setHandlerFuncFast(_PREHASH_RemoveModifyAbility,
+ // &LLAgent::processRemoveModifyAbility);
+ msg->setHandlerFuncFast(_PREHASH_AgentDataUpdate,
+ &LLAgent::processAgentDataUpdate);
+ msg->setHandlerFuncFast(_PREHASH_AgentGroupDataUpdate,
+ &LLAgent::processAgentGroupDataUpdate);
+ msg->setHandlerFunc("AgentDropGroup",
+ &LLAgent::processAgentDropGroup);
+ // land ownership messages
+ msg->setHandlerFuncFast(_PREHASH_ParcelOverlay,
+ LLViewerParcelMgr::processParcelOverlay);
+ msg->setHandlerFuncFast(_PREHASH_ParcelProperties,
+ LLViewerParcelMgr::processParcelProperties);
+ msg->setHandlerFunc("ParcelAccessListReply",
+ LLViewerParcelMgr::processParcelAccessListReply);
+ msg->setHandlerFunc("ParcelDwellReply",
+ LLViewerParcelMgr::processParcelDwellReply);
+
+ msg->setHandlerFunc("AvatarPropertiesReply",
+ &LLAvatarPropertiesProcessor::processAvatarPropertiesReply);
+ msg->setHandlerFunc("AvatarInterestsReply",
+ &LLAvatarPropertiesProcessor::processAvatarInterestsReply);
+ msg->setHandlerFunc("AvatarGroupsReply",
+ &LLAvatarPropertiesProcessor::processAvatarGroupsReply);
+ // ratings deprecated
+ //msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply,
+ // LLPanelAvatar::processAvatarStatisticsReply);
+ msg->setHandlerFunc("AvatarNotesReply",
+ &LLAvatarPropertiesProcessor::processAvatarNotesReply);
+ msg->setHandlerFunc("AvatarPicksReply",
+ &LLAvatarPropertiesProcessor::processAvatarPicksReply);
+ msg->setHandlerFunc("AvatarClassifiedReply",
+ &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply);
+
+ msg->setHandlerFuncFast(_PREHASH_CreateGroupReply,
+ LLGroupMgr::processCreateGroupReply);
+ msg->setHandlerFuncFast(_PREHASH_JoinGroupReply,
+ LLGroupMgr::processJoinGroupReply);
+ msg->setHandlerFuncFast(_PREHASH_EjectGroupMemberReply,
+ LLGroupMgr::processEjectGroupMemberReply);
+ msg->setHandlerFuncFast(_PREHASH_LeaveGroupReply,
+ LLGroupMgr::processLeaveGroupReply);
+ msg->setHandlerFuncFast(_PREHASH_GroupProfileReply,
+ LLGroupMgr::processGroupPropertiesReply);
+
+ // ratings deprecated
+ // msg->setHandlerFuncFast(_PREHASH_ReputationIndividualReply,
+ // LLFloaterRate::processReputationIndividualReply);
+
+ msg->setHandlerFunc("ScriptControlChange",
+ LLAgent::processScriptControlChange );
+
+ msg->setHandlerFuncFast(_PREHASH_ViewerEffect, LLHUDManager::processViewerEffect);
+
+ msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers);
+
+ msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply,
+ LLPanelGroupLandMoney::processGroupAccountSummaryReply);
+ msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply,
+ LLPanelGroupLandMoney::processGroupAccountDetailsReply);
+ msg->setHandlerFuncFast(_PREHASH_GroupAccountTransactionsReply,
+ LLPanelGroupLandMoney::processGroupAccountTransactionsReply);
+
+ msg->setHandlerFuncFast(_PREHASH_UserInfoReply,
+ process_user_info_reply);
+
+ msg->setHandlerFunc("RegionHandshake", process_region_handshake, NULL);
+
+ msg->setHandlerFunc("TeleportStart", process_teleport_start );
+ msg->setHandlerFunc("TeleportProgress", process_teleport_progress);
+ msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL);
+ msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL);
+
+ msg->setHandlerFunc("ImageNotInDatabase", LLViewerTextureList::processImageNotInDatabase, NULL);
+
+ msg->setHandlerFuncFast(_PREHASH_GroupMembersReply,
+ LLGroupMgr::processGroupMembersReply);
+ msg->setHandlerFunc("GroupRoleDataReply",
+ LLGroupMgr::processGroupRoleDataReply);
+ msg->setHandlerFunc("GroupRoleMembersReply",
+ LLGroupMgr::processGroupRoleMembersReply);
+ msg->setHandlerFunc("GroupTitlesReply",
+ LLGroupMgr::processGroupTitlesReply);
+ // Special handler as this message is sometimes used for group land.
+ msg->setHandlerFunc("PlacesReply", process_places_reply);
+ msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply);
+
+ msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply);
+
+ msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply);
+ msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply);
+ msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply);
+
+ msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply);
+ msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply);
+ msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply);
+ msg->setHandlerFunc("ScriptDialog", process_script_dialog);
+ msg->setHandlerFunc("LoadURL", process_load_url);
+ msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request);
+ msg->setHandlerFunc("EstateCovenantReply", process_covenant_reply);
+
+ // calling cards
+ msg->setHandlerFunc("OfferCallingCard", process_offer_callingcard);
+ msg->setHandlerFunc("AcceptCallingCard", process_accept_callingcard);
+ msg->setHandlerFunc("DeclineCallingCard", process_decline_callingcard);
+
+ msg->setHandlerFunc("ParcelObjectOwnersReply", LLPanelLandObjects::processParcelObjectOwnersReply);
+
+ msg->setHandlerFunc("InitiateDownload", process_initiate_download);
+ msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply);
msg->setHandlerFunc("GenericMessage", process_generic_message);
msg->setHandlerFunc("GenericStreamingMessage", process_generic_streaming_message);
msg->setHandlerFunc("LargeGenericMessage", process_large_generic_message);
- msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message);
+ msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message);
}
void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32)
{
- // nothing
+ // nothing
}
const S32 OPT_CLOSED_WINDOW = -1;
@@ -2818,27 +2821,27 @@ const S32 OPT_MALE = 0;
const S32 OPT_FEMALE = 1;
const S32 OPT_TRUST_CERT = 0;
const S32 OPT_CANCEL_TRUST = 1;
-
+
bool callback_choose_gender(const LLSD& notification, const LLSD& response)
{
-
- // These defaults are returned from the server on login. They are set in login.xml.
- // If no default is returned from the server, they are retrieved from settings.xml.
-
- S32 option = LLNotification::getSelectedOption(notification, response);
- switch(option)
- {
- case OPT_MALE:
- LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultMaleAvatar"), "male" );
- break;
-
+
+ // These defaults are returned from the server on login. They are set in login.xml.
+ // If no default is returned from the server, they are retrieved from settings.xml.
+
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ switch(option)
+ {
+ case OPT_MALE:
+ LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultMaleAvatar"), "male" );
+ break;
+
case OPT_FEMALE:
case OPT_CLOSED_WINDOW:
default:
- LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultFemaleAvatar"), "female" );
- break;
- }
- return false;
+ LLStartUp::loadInitialOutfit( gSavedSettings.getString("DefaultFemaleAvatar"), "female" );
+ break;
+ }
+ return false;
}
std::string get_screen_filename(const std::string& pattern)
@@ -2870,66 +2873,66 @@ std::string LLStartUp::getScreenHomeFilename()
//static
void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
- const std::string& gender_name )
+ const std::string& gender_name )
{
- LL_DEBUGS() << "starting" << LL_ENDL;
-
- // Not going through the processAgentInitialWearables path, so need to set this here.
- LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
- // Initiate creation of COF, since we're also bypassing that.
- gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT);
-
- ESex gender;
- if (gender_name == "male")
- {
- LL_DEBUGS() << "male" << LL_ENDL;
- gender = SEX_MALE;
- }
- else
- {
- LL_DEBUGS() << "female" << LL_ENDL;
- gender = SEX_FEMALE;
- }
-
- if (!isAgentAvatarValid())
- {
- LL_WARNS() << "Trying to load an initial outfit for an invalid agent avatar" << LL_ENDL;
- return;
- }
-
- gAgentAvatarp->setSex(gender);
-
- // try to find the requested outfit or folder
-
- // -- check for existing outfit in My Outfits
- bool do_copy = false;
- LLUUID cat_id = findDescendentCategoryIDByName(
- gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS),
- outfit_folder_name);
-
- // -- check for existing folder in Library
- if (cat_id.isNull())
- {
- cat_id = findDescendentCategoryIDByName(
- gInventory.getLibraryRootFolderID(),
- outfit_folder_name);
- if (!cat_id.isNull())
- {
- do_copy = true;
- }
- }
-
- if (cat_id.isNull())
- {
- // -- final fallback: create standard wearables
- LL_DEBUGS() << "standard wearables" << LL_ENDL;
- gAgentWearables.createStandardWearables();
- }
- else
- {
- bool do_append = false;
- LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
- // Need to fetch cof contents before we can wear.
+ LL_DEBUGS() << "starting" << LL_ENDL;
+
+ // Not going through the processAgentInitialWearables path, so need to set this here.
+ LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true);
+ // Initiate creation of COF, since we're also bypassing that.
+ gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT);
+
+ ESex gender;
+ if (gender_name == "male")
+ {
+ LL_DEBUGS() << "male" << LL_ENDL;
+ gender = SEX_MALE;
+ }
+ else
+ {
+ LL_DEBUGS() << "female" << LL_ENDL;
+ gender = SEX_FEMALE;
+ }
+
+ if (!isAgentAvatarValid())
+ {
+ LL_WARNS() << "Trying to load an initial outfit for an invalid agent avatar" << LL_ENDL;
+ return;
+ }
+
+ gAgentAvatarp->setSex(gender);
+
+ // try to find the requested outfit or folder
+
+ // -- check for existing outfit in My Outfits
+ bool do_copy = false;
+ LLUUID cat_id = findDescendentCategoryIDByName(
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS),
+ outfit_folder_name);
+
+ // -- check for existing folder in Library
+ if (cat_id.isNull())
+ {
+ cat_id = findDescendentCategoryIDByName(
+ gInventory.getLibraryRootFolderID(),
+ outfit_folder_name);
+ if (!cat_id.isNull())
+ {
+ do_copy = true;
+ }
+ }
+
+ if (cat_id.isNull())
+ {
+ // -- final fallback: create standard wearables
+ LL_DEBUGS() << "standard wearables" << LL_ENDL;
+ gAgentWearables.createStandardWearables();
+ }
+ else
+ {
+ bool do_append = false;
+ LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
+ // Need to fetch cof contents before we can wear.
if (do_copy)
{
callAfterCOFFetch(boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append));
@@ -2938,16 +2941,16 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
{
callAfterCategoryLinksFetch(cat_id, boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append));
}
- LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL;
- }
+ LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL;
+ }
- gAgent.setOutfitChosen(TRUE);
- gAgentWearables.sendDummyAgentWearablesUpdate();
+ gAgent.setOutfitChosen(TRUE);
+ gAgentWearables.sendDummyAgentWearablesUpdate();
}
std::string& LLStartUp::getInitialOutfitName()
{
- return sInitialOutfit;
+ return sInitialOutfit;
}
std::string LLStartUp::getUserId()
@@ -2963,8 +2966,8 @@ std::string LLStartUp::getUserId()
// frees the bitmap
void release_start_screen()
{
- LL_DEBUGS("AppInit") << "Releasing bitmap..." << LL_ENDL;
- gStartTexture = NULL;
+ LL_DEBUGS("AppInit") << "Releasing bitmap..." << LL_ENDL;
+ gStartTexture = NULL;
}
@@ -2972,77 +2975,77 @@ void release_start_screen()
std::string LLStartUp::startupStateToString(EStartupState state)
{
#define RTNENUM(E) case E: return #E
- switch(state){
- RTNENUM( STATE_FIRST );
- RTNENUM( STATE_BROWSER_INIT );
- RTNENUM( STATE_LOGIN_SHOW );
- RTNENUM( STATE_LOGIN_WAIT );
- RTNENUM( STATE_LOGIN_CLEANUP );
- RTNENUM( STATE_LOGIN_AUTH_INIT );
- RTNENUM( STATE_LOGIN_CURL_UNSTUCK );
- RTNENUM( STATE_LOGIN_PROCESS_RESPONSE );
- RTNENUM( STATE_WORLD_INIT );
- RTNENUM( STATE_MULTIMEDIA_INIT );
- RTNENUM( STATE_FONT_INIT );
- RTNENUM( STATE_SEED_GRANTED_WAIT );
- RTNENUM( STATE_SEED_CAP_GRANTED );
- RTNENUM( STATE_WORLD_WAIT );
- RTNENUM( STATE_AGENT_SEND );
- RTNENUM( STATE_AGENT_WAIT );
- RTNENUM( STATE_INVENTORY_SEND );
+ switch(state){
+ RTNENUM( STATE_FIRST );
+ RTNENUM( STATE_BROWSER_INIT );
+ RTNENUM( STATE_LOGIN_SHOW );
+ RTNENUM( STATE_LOGIN_WAIT );
+ RTNENUM( STATE_LOGIN_CLEANUP );
+ RTNENUM( STATE_LOGIN_AUTH_INIT );
+ RTNENUM( STATE_LOGIN_CURL_UNSTUCK );
+ RTNENUM( STATE_LOGIN_PROCESS_RESPONSE );
+ RTNENUM( STATE_WORLD_INIT );
+ RTNENUM( STATE_MULTIMEDIA_INIT );
+ RTNENUM( STATE_FONT_INIT );
+ RTNENUM( STATE_SEED_GRANTED_WAIT );
+ RTNENUM( STATE_SEED_CAP_GRANTED );
+ RTNENUM( STATE_WORLD_WAIT );
+ RTNENUM( STATE_AGENT_SEND );
+ RTNENUM( STATE_AGENT_WAIT );
+ RTNENUM( STATE_INVENTORY_SEND );
RTNENUM(STATE_INVENTORY_CALLBACKS );
- RTNENUM( STATE_MISC );
- RTNENUM( STATE_PRECACHE );
- RTNENUM( STATE_WEARABLES_WAIT );
- RTNENUM( STATE_CLEANUP );
- RTNENUM( STATE_STARTED );
- default:
- return llformat("(state #%d)", state);
- }
+ RTNENUM( STATE_MISC );
+ RTNENUM( STATE_PRECACHE );
+ RTNENUM( STATE_WEARABLES_WAIT );
+ RTNENUM( STATE_CLEANUP );
+ RTNENUM( STATE_STARTED );
+ default:
+ return llformat("(state #%d)", state);
+ }
#undef RTNENUM
}
// static
void LLStartUp::setStartupState( EStartupState state )
{
- LL_INFOS("AppInit") << "Startup state changing from " <<
- getStartupStateString() << " to " <<
- startupStateToString(state) << LL_ENDL;
+ LL_INFOS("AppInit") << "Startup state changing from " <<
+ getStartupStateString() << " to " <<
+ startupStateToString(state) << LL_ENDL;
- getPhases().stopPhase(getStartupStateString());
- gStartupState = state;
- getPhases().startPhase(getStartupStateString());
+ getPhases().stopPhase(getStartupStateString());
+ gStartupState = state;
+ getPhases().startPhase(getStartupStateString());
- postStartupState();
+ postStartupState();
}
void LLStartUp::postStartupState()
{
- LLSD stateInfo;
- stateInfo["str"] = getStartupStateString();
- stateInfo["enum"] = gStartupState;
- sStateWatcher->post(stateInfo);
- gDebugInfo["StartupState"] = getStartupStateString();
+ LLSD stateInfo;
+ stateInfo["str"] = getStartupStateString();
+ stateInfo["enum"] = gStartupState;
+ sStateWatcher->post(stateInfo);
+ gDebugInfo["StartupState"] = getStartupStateString();
}
void reset_login()
{
- gAgentWearables.cleanup();
- gAgentCamera.cleanup();
- gAgent.cleanup();
+ gAgentWearables.cleanup();
+ gAgentCamera.cleanup();
+ gAgent.cleanup();
gSky.cleanup(); // mVOSkyp is an inworld object.
- LLWorld::getInstance()->resetClass();
+ LLWorld::getInstance()->resetClass();
- if ( gViewerWindow )
- { // Hide menus and normal buttons
- gViewerWindow->setNormalControlsVisible( FALSE );
- gLoginMenuBarView->setVisible( TRUE );
- gLoginMenuBarView->setEnabled( TRUE );
- }
+ if ( gViewerWindow )
+ { // Hide menus and normal buttons
+ gViewerWindow->setNormalControlsVisible( FALSE );
+ gLoginMenuBarView->setVisible( TRUE );
+ gLoginMenuBarView->setEnabled( TRUE );
+ }
- // Hide any other stuff
- LLFloaterReg::hideVisibleInstances();
+ // Hide any other stuff
+ LLFloaterReg::hideVisibleInstances();
LLStartUp::setStartupState( STATE_BROWSER_INIT );
if (LLVoiceClient::instanceExists())
@@ -3062,117 +3065,117 @@ void reset_login()
// early, before the login screen). JC
void LLStartUp::multimediaInit()
{
- LL_DEBUGS("AppInit") << "Initializing Multimedia...." << LL_ENDL;
- std::string msg = LLTrans::getString("LoginInitializingMultimedia");
- set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str());
- display_startup();
+ LL_DEBUGS("AppInit") << "Initializing Multimedia...." << LL_ENDL;
+ std::string msg = LLTrans::getString("LoginInitializingMultimedia");
+ set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str());
+ display_startup();
}
void LLStartUp::fontInit()
{
- LL_DEBUGS("AppInit") << "Initializing fonts...." << LL_ENDL;
- std::string msg = LLTrans::getString("LoginInitializingFonts");
- set_startup_status(0.45f, msg.c_str(), gAgent.mMOTD.c_str());
- display_startup();
+ LL_DEBUGS("AppInit") << "Initializing fonts...." << LL_ENDL;
+ std::string msg = LLTrans::getString("LoginInitializingFonts");
+ set_startup_status(0.45f, msg.c_str(), gAgent.mMOTD.c_str());
+ display_startup();
- LLFontGL::loadDefaultFonts();
+ LLFontGL::loadDefaultFonts();
}
void LLStartUp::initNameCache()
{
- // Can be called multiple times
- if ( gCacheName ) return;
-
- gCacheName = new LLCacheName(gMessageSystem);
- gCacheName->addObserver(&callback_cache_name);
- gCacheName->localizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting"));
- gCacheName->localizeCacheName("nobody", LLTrans::getString("AvatarNameNobody"));
- gCacheName->localizeCacheName("none", LLTrans::getString("GroupNameNone"));
- // Load stored cache if possible
- LLAppViewer::instance()->loadNameCache();
-
- // Start cache in not-running state until we figure out if we have
- // capabilities for display name lookup
- LLAvatarNameCache* cache_inst = LLAvatarNameCache::getInstance();
- cache_inst->setUsePeopleAPI(gSavedSettings.getBOOL("UsePeopleAPI"));
- cache_inst->setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames"));
- cache_inst->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames"));
+ // Can be called multiple times
+ if ( gCacheName ) return;
+
+ gCacheName = new LLCacheName(gMessageSystem);
+ gCacheName->addObserver(&callback_cache_name);
+ gCacheName->localizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting"));
+ gCacheName->localizeCacheName("nobody", LLTrans::getString("AvatarNameNobody"));
+ gCacheName->localizeCacheName("none", LLTrans::getString("GroupNameNone"));
+ // Load stored cache if possible
+ LLAppViewer::instance()->loadNameCache();
+
+ // Start cache in not-running state until we figure out if we have
+ // capabilities for display name lookup
+ LLAvatarNameCache* cache_inst = LLAvatarNameCache::getInstance();
+ cache_inst->setUsePeopleAPI(gSavedSettings.getBOOL("UsePeopleAPI"));
+ cache_inst->setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames"));
+ cache_inst->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames"));
}
void LLStartUp::initExperiences()
-{
+{
// Should trigger loading the cache.
LLExperienceCache::instance().setCapabilityQuery(
boost::bind(&LLAgent::getRegionCapability, &gAgent, _1));
- LLExperienceLog::instance().initialize();
+ LLExperienceLog::instance().initialize();
}
void LLStartUp::cleanupNameCache()
{
- delete gCacheName;
- gCacheName = NULL;
+ delete gCacheName;
+ gCacheName = NULL;
}
bool LLStartUp::dispatchURL()
{
- // ok, if we've gotten this far and have a startup URL
+ // ok, if we've gotten this far and have a startup URL
if (!getStartSLURL().isValid())
- {
- return false;
- }
+ {
+ return false;
+ }
if(getStartSLURL().getType() != LLSLURL::APP)
- {
-
- // If we started with a location, but we're already
- // at that location, don't pop dialogs open.
- LLVector3 pos = gAgent.getPositionAgent();
- LLVector3 slurlpos = getStartSLURL().getPosition();
- F32 dx = pos.mV[VX] - slurlpos.mV[VX];
- F32 dy = pos.mV[VY] - slurlpos.mV[VY];
- const F32 SLOP = 2.f; // meters
-
- if( getStartSLURL().getRegion() != gAgent.getRegion()->getName()
- || (dx*dx > SLOP*SLOP)
- || (dy*dy > SLOP*SLOP) )
- {
- LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED,
- NULL, false);
- }
- return true;
- }
- return false;
+ {
+
+ // If we started with a location, but we're already
+ // at that location, don't pop dialogs open.
+ LLVector3 pos = gAgent.getPositionAgent();
+ LLVector3 slurlpos = getStartSLURL().getPosition();
+ F32 dx = pos.mV[VX] - slurlpos.mV[VX];
+ F32 dy = pos.mV[VY] - slurlpos.mV[VY];
+ const F32 SLOP = 2.f; // meters
+
+ if( getStartSLURL().getRegion() != gAgent.getRegion()->getName()
+ || (dx*dx > SLOP*SLOP)
+ || (dy*dy > SLOP*SLOP) )
+ {
+ LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED,
+ NULL, false);
+ }
+ return true;
+ }
+ return false;
}
-void LLStartUp::setStartSLURL(const LLSLURL& slurl)
+void LLStartUp::setStartSLURL(const LLSLURL& slurl)
{
- LL_DEBUGS("AppInit")<<slurl.asString()<<LL_ENDL;
-
- if ( slurl.isSpatial() )
- {
- std::string new_start = slurl.getSLURLString();
- LL_DEBUGS("AppInit")<<new_start<<LL_ENDL;
- sStartSLURL = slurl;
- LLPanelLogin::onUpdateStartSLURL(slurl); // updates grid if needed
-
- // remember that this is where we wanted to log in...if the login fails,
- // the next attempt will default to the same place.
- gSavedSettings.setString("NextLoginLocation", new_start);
- // following a successful login, this is cleared
- // and the default reverts to LoginLocation
- }
- else
- {
- LL_WARNS("AppInit")<<"Invalid start SLURL (ignored): "<<slurl.asString()<<LL_ENDL;
- }
+ LL_DEBUGS("AppInit")<<slurl.asString()<<LL_ENDL;
+
+ if ( slurl.isSpatial() )
+ {
+ std::string new_start = slurl.getSLURLString();
+ LL_DEBUGS("AppInit")<<new_start<<LL_ENDL;
+ sStartSLURL = slurl;
+ LLPanelLogin::onUpdateStartSLURL(slurl); // updates grid if needed
+
+ // remember that this is where we wanted to log in...if the login fails,
+ // the next attempt will default to the same place.
+ gSavedSettings.setString("NextLoginLocation", new_start);
+ // following a successful login, this is cleared
+ // and the default reverts to LoginLocation
+ }
+ else
+ {
+ LL_WARNS("AppInit")<<"Invalid start SLURL (ignored): "<<slurl.asString()<<LL_ENDL;
+ }
}
// static
LLSLURL& LLStartUp::getStartSLURL()
{
- return sStartSLURL;
-}
+ return sStartSLURL;
+}
/**
* Read all proxy configuration settings and set up both the HTTP proxy and
@@ -3185,680 +3188,680 @@ LLSLURL& LLStartUp::getStartSLURL()
*/
bool LLStartUp::startLLProxy()
{
- bool proxy_ok = true;
- std::string httpProxyType = gSavedSettings.getString("HttpProxyType");
-
- // Set up SOCKS proxy (if needed)
- if (gSavedSettings.getBOOL("Socks5ProxyEnabled"))
- {
- // Determine and update LLProxy with the saved authentication system
- std::string auth_type = gSavedSettings.getString("Socks5AuthType");
-
- if (auth_type.compare("UserPass") == 0)
- {
- LLPointer<LLCredential> socks_cred = gSecAPIHandler->loadCredential("SOCKS5");
- std::string socks_user = socks_cred->getIdentifier()["username"].asString();
- std::string socks_password = socks_cred->getAuthenticator()["creds"].asString();
-
- bool ok = LLProxy::getInstance()->setAuthPassword(socks_user, socks_password);
-
- if (!ok)
- {
- LLNotificationsUtil::add("SOCKS_BAD_CREDS");
- proxy_ok = false;
- }
- }
- else if (auth_type.compare("None") == 0)
- {
- LLProxy::getInstance()->setAuthNone();
- }
- else
- {
- LL_WARNS("Proxy") << "Invalid SOCKS 5 authentication type."<< LL_ENDL;
-
- // Unknown or missing setting.
- gSavedSettings.setString("Socks5AuthType", "None");
-
- // Clear the SOCKS credentials.
- LLPointer<LLCredential> socks_cred = new LLCredential("SOCKS5");
- gSecAPIHandler->deleteCredential(socks_cred);
-
- LLProxy::getInstance()->setAuthNone();
- }
-
- if (proxy_ok)
- {
- // Start the proxy and check for errors
- // If status != SOCKS_OK, stopSOCKSProxy() will already have been called when startSOCKSProxy() returns.
- LLHost socks_host;
- socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost"));
- socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort"));
- int status = LLProxy::getInstance()->startSOCKSProxy(socks_host);
-
- if (status != SOCKS_OK)
- {
- LLSD subs;
- subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost");
- subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort");
-
- std::string error_string;
-
- switch(status)
- {
- case SOCKS_CONNECT_ERROR: // TCP Fail
- error_string = "SOCKS_CONNECT_ERROR";
- break;
-
- case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection
- error_string = "SOCKS_NOT_PERMITTED";
- break;
-
- case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server
- error_string = "SOCKS_NOT_ACCEPTABLE";
- break;
-
- case SOCKS_AUTH_FAIL: // Authentication failed
- error_string = "SOCKS_AUTH_FAIL";
- break;
-
- case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed
- error_string = "SOCKS_UDP_FWD_NOT_GRANTED";
- break;
-
- case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server
- error_string = "SOCKS_HOST_CONNECT_FAILED";
- break;
-
- case SOCKS_INVALID_HOST: // Improperly formatted host address or port.
- error_string = "SOCKS_INVALID_HOST";
- break;
-
- default:
- error_string = "SOCKS_UNKNOWN_STATUS"; // Something strange happened,
- LL_WARNS("Proxy") << "Unknown return from LLProxy::startProxy(): " << status << LL_ENDL;
- break;
- }
-
- LLNotificationsUtil::add(error_string, subs);
- proxy_ok = false;
- }
- }
- }
- else
- {
- LLProxy::getInstance()->stopSOCKSProxy(); // ensure no UDP proxy is running and it's all cleaned up
- }
-
- if (proxy_ok)
- {
- // Determine the HTTP proxy type (if any)
- if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled"))
- {
- LLHost http_host;
- http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress"));
- http_host.setPort(gSavedSettings.getS32("BrowserProxyPort"));
- if (!LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP))
- {
- LLSD subs;
- subs["HOST"] = http_host.getIPString();
- subs["PORT"] = (S32)http_host.getPort();
- LLNotificationsUtil::add("PROXY_INVALID_HTTP_HOST", subs);
- proxy_ok = false;
- }
- }
- else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled"))
- {
- LLHost socks_host;
- socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost"));
- socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort"));
- if (!LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS))
- {
- LLSD subs;
- subs["HOST"] = socks_host.getIPString();
- subs["PORT"] = (S32)socks_host.getPort();
- LLNotificationsUtil::add("PROXY_INVALID_SOCKS_HOST", subs);
- proxy_ok = false;
- }
- }
- else if (httpProxyType.compare("None") == 0)
- {
- LLProxy::getInstance()->disableHTTPProxy();
- }
- else
- {
- LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration: " << httpProxyType << LL_ENDL;
-
- // Set the missing or wrong configuration back to something valid.
- gSavedSettings.setString("HttpProxyType", "None");
- LLProxy::getInstance()->disableHTTPProxy();
-
- // Leave proxy_ok alone, since this isn't necessarily fatal.
- }
- }
-
- return proxy_ok;
+ bool proxy_ok = true;
+ std::string httpProxyType = gSavedSettings.getString("HttpProxyType");
+
+ // Set up SOCKS proxy (if needed)
+ if (gSavedSettings.getBOOL("Socks5ProxyEnabled"))
+ {
+ // Determine and update LLProxy with the saved authentication system
+ std::string auth_type = gSavedSettings.getString("Socks5AuthType");
+
+ if (auth_type.compare("UserPass") == 0)
+ {
+ LLPointer<LLCredential> socks_cred = gSecAPIHandler->loadCredential("SOCKS5");
+ std::string socks_user = socks_cred->getIdentifier()["username"].asString();
+ std::string socks_password = socks_cred->getAuthenticator()["creds"].asString();
+
+ bool ok = LLProxy::getInstance()->setAuthPassword(socks_user, socks_password);
+
+ if (!ok)
+ {
+ LLNotificationsUtil::add("SOCKS_BAD_CREDS");
+ proxy_ok = false;
+ }
+ }
+ else if (auth_type.compare("None") == 0)
+ {
+ LLProxy::getInstance()->setAuthNone();
+ }
+ else
+ {
+ LL_WARNS("Proxy") << "Invalid SOCKS 5 authentication type."<< LL_ENDL;
+
+ // Unknown or missing setting.
+ gSavedSettings.setString("Socks5AuthType", "None");
+
+ // Clear the SOCKS credentials.
+ LLPointer<LLCredential> socks_cred = new LLCredential("SOCKS5");
+ gSecAPIHandler->deleteCredential(socks_cred);
+
+ LLProxy::getInstance()->setAuthNone();
+ }
+
+ if (proxy_ok)
+ {
+ // Start the proxy and check for errors
+ // If status != SOCKS_OK, stopSOCKSProxy() will already have been called when startSOCKSProxy() returns.
+ LLHost socks_host;
+ socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost"));
+ socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort"));
+ int status = LLProxy::getInstance()->startSOCKSProxy(socks_host);
+
+ if (status != SOCKS_OK)
+ {
+ LLSD subs;
+ subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost");
+ subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort");
+
+ std::string error_string;
+
+ switch(status)
+ {
+ case SOCKS_CONNECT_ERROR: // TCP Fail
+ error_string = "SOCKS_CONNECT_ERROR";
+ break;
+
+ case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection
+ error_string = "SOCKS_NOT_PERMITTED";
+ break;
+
+ case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server
+ error_string = "SOCKS_NOT_ACCEPTABLE";
+ break;
+
+ case SOCKS_AUTH_FAIL: // Authentication failed
+ error_string = "SOCKS_AUTH_FAIL";
+ break;
+
+ case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed
+ error_string = "SOCKS_UDP_FWD_NOT_GRANTED";
+ break;
+
+ case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server
+ error_string = "SOCKS_HOST_CONNECT_FAILED";
+ break;
+
+ case SOCKS_INVALID_HOST: // Improperly formatted host address or port.
+ error_string = "SOCKS_INVALID_HOST";
+ break;
+
+ default:
+ error_string = "SOCKS_UNKNOWN_STATUS"; // Something strange happened,
+ LL_WARNS("Proxy") << "Unknown return from LLProxy::startProxy(): " << status << LL_ENDL;
+ break;
+ }
+
+ LLNotificationsUtil::add(error_string, subs);
+ proxy_ok = false;
+ }
+ }
+ }
+ else
+ {
+ LLProxy::getInstance()->stopSOCKSProxy(); // ensure no UDP proxy is running and it's all cleaned up
+ }
+
+ if (proxy_ok)
+ {
+ // Determine the HTTP proxy type (if any)
+ if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled"))
+ {
+ LLHost http_host;
+ http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress"));
+ http_host.setPort(gSavedSettings.getS32("BrowserProxyPort"));
+ if (!LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP))
+ {
+ LLSD subs;
+ subs["HOST"] = http_host.getIPString();
+ subs["PORT"] = (S32)http_host.getPort();
+ LLNotificationsUtil::add("PROXY_INVALID_HTTP_HOST", subs);
+ proxy_ok = false;
+ }
+ }
+ else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled"))
+ {
+ LLHost socks_host;
+ socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost"));
+ socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort"));
+ if (!LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS))
+ {
+ LLSD subs;
+ subs["HOST"] = socks_host.getIPString();
+ subs["PORT"] = (S32)socks_host.getPort();
+ LLNotificationsUtil::add("PROXY_INVALID_SOCKS_HOST", subs);
+ proxy_ok = false;
+ }
+ }
+ else if (httpProxyType.compare("None") == 0)
+ {
+ LLProxy::getInstance()->disableHTTPProxy();
+ }
+ else
+ {
+ LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration: " << httpProxyType << LL_ENDL;
+
+ // Set the missing or wrong configuration back to something valid.
+ gSavedSettings.setString("HttpProxyType", "None");
+ LLProxy::getInstance()->disableHTTPProxy();
+
+ // Leave proxy_ok alone, since this isn't necessarily fatal.
+ }
+ }
+
+ return proxy_ok;
}
bool login_alert_done(const LLSD& notification, const LLSD& response)
{
- LLPanelLogin::giveFocus();
- return false;
+ LLPanelLogin::giveFocus();
+ return false;
}
-// parse the certificate information into args for the
+// parse the certificate information into args for the
// certificate notifications
LLSD transform_cert_args(LLPointer<LLCertificate> cert)
{
- LLSD args = LLSD::emptyMap();
- std::string value;
- LLSD cert_info;
- cert->getLLSD(cert_info);
- // convert all of the elements in the cert into
- // args for the xml dialog, so we have flexability to
- // display various parts of the cert by only modifying
- // the cert alert dialog xml.
- for(LLSD::map_iterator iter = cert_info.beginMap();
- iter != cert_info.endMap();
- iter++)
- {
- // key usage and extended key usage
- // are actually arrays, and we want to format them as comma separated
- // strings, so special case those.
- LLSDSerialize::toXML(cert_info[iter->first], std::cout);
- if((iter->first == std::string(CERT_KEY_USAGE)) ||
- (iter->first == std::string(CERT_EXTENDED_KEY_USAGE)))
- {
- value = "";
- LLSD usage = cert_info[iter->first];
- for (LLSD::array_iterator usage_iter = usage.beginArray();
- usage_iter != usage.endArray();
- usage_iter++)
- {
-
- if(usage_iter != usage.beginArray())
- {
- value += ", ";
- }
-
- value += (*usage_iter).asString();
- }
-
- }
- else
- {
- value = iter->second.asString();
- }
-
- std::string name = iter->first;
- std::transform(name.begin(), name.end(), name.begin(),
- (int(*)(int))toupper);
- args[name.c_str()] = value;
- }
- return args;
+ LLSD args = LLSD::emptyMap();
+ std::string value;
+ LLSD cert_info;
+ cert->getLLSD(cert_info);
+ // convert all of the elements in the cert into
+ // args for the xml dialog, so we have flexability to
+ // display various parts of the cert by only modifying
+ // the cert alert dialog xml.
+ for(LLSD::map_iterator iter = cert_info.beginMap();
+ iter != cert_info.endMap();
+ iter++)
+ {
+ // key usage and extended key usage
+ // are actually arrays, and we want to format them as comma separated
+ // strings, so special case those.
+ LLSDSerialize::toXML(cert_info[iter->first], std::cout);
+ if((iter->first == std::string(CERT_KEY_USAGE)) ||
+ (iter->first == std::string(CERT_EXTENDED_KEY_USAGE)))
+ {
+ value = "";
+ LLSD usage = cert_info[iter->first];
+ for (LLSD::array_iterator usage_iter = usage.beginArray();
+ usage_iter != usage.endArray();
+ usage_iter++)
+ {
+
+ if(usage_iter != usage.beginArray())
+ {
+ value += ", ";
+ }
+
+ value += (*usage_iter).asString();
+ }
+
+ }
+ else
+ {
+ value = iter->second.asString();
+ }
+
+ std::string name = iter->first;
+ std::transform(name.begin(), name.end(), name.begin(),
+ (int(*)(int))toupper);
+ args[name.c_str()] = value;
+ }
+ return args;
}
// when we handle a cert error, give focus back to the login panel
void general_cert_done(const LLSD& notification, const LLSD& response)
{
- LLStartUp::setStartupState( STATE_LOGIN_SHOW );
- LLPanelLogin::giveFocus();
+ LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+ LLPanelLogin::giveFocus();
}
// check to see if the user wants to trust the cert.
-// if they do, add it to the cert store and
+// if they do, add it to the cert store and
void trust_cert_done(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
- switch(option)
- {
- case OPT_TRUST_CERT:
- {
- LLPointer<LLCertificate> cert = gSecAPIHandler->getCertificate(notification["payload"]["certificate"]);
- LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore(gSavedSettings.getString("CertStore"));
- store->add(cert);
- store->save();
- LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
- break;
- }
- case OPT_CANCEL_TRUST:
- reset_login();
- gSavedSettings.setBOOL("AutoLogin", FALSE);
- LLStartUp::setStartupState( STATE_LOGIN_SHOW );
- default:
- LLPanelLogin::giveFocus();
- break;
- }
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ switch(option)
+ {
+ case OPT_TRUST_CERT:
+ {
+ LLPointer<LLCertificate> cert = gSecAPIHandler->getCertificate(notification["payload"]["certificate"]);
+ LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore(gSavedSettings.getString("CertStore"));
+ store->add(cert);
+ store->save();
+ LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
+ break;
+ }
+ case OPT_CANCEL_TRUST:
+ reset_login();
+ gSavedSettings.setBOOL("AutoLogin", FALSE);
+ LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+ default:
+ LLPanelLogin::giveFocus();
+ break;
+ }
}
void apply_udp_blacklist(const std::string& csv)
{
- std::string::size_type start = 0;
- std::string::size_type comma = 0;
- do
- {
- comma = csv.find(",", start);
- if (comma == std::string::npos)
- {
- comma = csv.length();
- }
- std::string item(csv, start, comma-start);
-
- LL_DEBUGS() << "udp_blacklist " << item << LL_ENDL;
- gMessageSystem->banUdpMessage(item);
-
- start = comma + 1;
-
- }
- while(comma < csv.length());
-
+ std::string::size_type start = 0;
+ std::string::size_type comma = 0;
+ do
+ {
+ comma = csv.find(",", start);
+ if (comma == std::string::npos)
+ {
+ comma = csv.length();
+ }
+ std::string item(csv, start, comma-start);
+
+ LL_DEBUGS() << "udp_blacklist " << item << LL_ENDL;
+ gMessageSystem->banUdpMessage(item);
+
+ start = comma + 1;
+
+ }
+ while(comma < csv.length());
+
}
void on_benefits_failed_callback(const LLSD& notification, const LLSD& response)
{
- LL_WARNS("Benefits") << "Failed to load benefits information" << LL_ENDL;
+ LL_WARNS("Benefits") << "Failed to load benefits information" << LL_ENDL;
}
bool init_benefits(LLSD& response)
{
- bool succ = true;
-
- std::string package_name = response["account_type"].asString();
- const LLSD& benefits_sd = response["account_level_benefits"];
- if (!LLAgentBenefitsMgr::init(package_name, benefits_sd) ||
- !LLAgentBenefitsMgr::initCurrent(package_name, benefits_sd))
- {
- succ = false;
- }
- else
- {
- LL_DEBUGS("Benefits") << "Initialized current benefits, level " << package_name << " from " << benefits_sd << LL_ENDL;
- }
- const LLSD& packages_sd = response["premium_packages"];
- for(LLSD::map_const_iterator package_iter = packages_sd.beginMap();
- package_iter != packages_sd.endMap();
- ++package_iter)
- {
- std::string package_name = package_iter->first;
- const LLSD& benefits_sd = package_iter->second["benefits"];
- if (LLAgentBenefitsMgr::init(package_name, benefits_sd))
- {
- LL_DEBUGS("Benefits") << "Initialized benefits for package " << package_name << " from " << benefits_sd << LL_ENDL;
- }
- else
- {
- LL_WARNS("Benefits") << "Failed init for package " << package_name << " from " << benefits_sd << LL_ENDL;
- succ = false;
- }
- }
-
- if (!LLAgentBenefitsMgr::has("Base"))
- {
- LL_WARNS("Benefits") << "Benefits info did not include required package Base" << LL_ENDL;
- succ = false;
- }
- if (!LLAgentBenefitsMgr::has("Premium"))
- {
- LL_WARNS("Benefits") << "Benefits info did not include required package Premium" << LL_ENDL;
- succ = false;
- }
-
- return succ;
+ bool succ = true;
+
+ std::string package_name = response["account_type"].asString();
+ const LLSD& benefits_sd = response["account_level_benefits"];
+ if (!LLAgentBenefitsMgr::init(package_name, benefits_sd) ||
+ !LLAgentBenefitsMgr::initCurrent(package_name, benefits_sd))
+ {
+ succ = false;
+ }
+ else
+ {
+ LL_DEBUGS("Benefits") << "Initialized current benefits, level " << package_name << " from " << benefits_sd << LL_ENDL;
+ }
+ const LLSD& packages_sd = response["premium_packages"];
+ for(LLSD::map_const_iterator package_iter = packages_sd.beginMap();
+ package_iter != packages_sd.endMap();
+ ++package_iter)
+ {
+ std::string package_name = package_iter->first;
+ const LLSD& benefits_sd = package_iter->second["benefits"];
+ if (LLAgentBenefitsMgr::init(package_name, benefits_sd))
+ {
+ LL_DEBUGS("Benefits") << "Initialized benefits for package " << package_name << " from " << benefits_sd << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("Benefits") << "Failed init for package " << package_name << " from " << benefits_sd << LL_ENDL;
+ succ = false;
+ }
+ }
+
+ if (!LLAgentBenefitsMgr::has("Base"))
+ {
+ LL_WARNS("Benefits") << "Benefits info did not include required package Base" << LL_ENDL;
+ succ = false;
+ }
+ if (!LLAgentBenefitsMgr::has("Premium"))
+ {
+ LL_WARNS("Benefits") << "Benefits info did not include required package Premium" << LL_ENDL;
+ succ = false;
+ }
+
+ return succ;
}
bool process_login_success_response()
{
- LLSD response = LLLoginInstance::getInstance()->getResponse();
-
- mBenefitsSuccessfullyInit = init_benefits(response);
-
- std::string text(response["udp_blacklist"]);
- if(!text.empty())
- {
- apply_udp_blacklist(text);
- }
-
- // unpack login data needed by the application
- text = response["agent_id"].asString();
- if(!text.empty()) gAgentID.set(text);
- gDebugInfo["AgentID"] = text;
-
- LLPerfStats::StatsRecorder::setEnabled(gSavedSettings.getBOOL("PerfStatsCaptureEnabled"));
- LLPerfStats::StatsRecorder::setFocusAv(gAgentID);
-
- // Agent id needed for parcel info request in LLUrlEntryParcel
- // to resolve parcel name.
- LLUrlEntryParcel::setAgentID(gAgentID);
-
- text = response["session_id"].asString();
- if(!text.empty()) gAgentSessionID.set(text);
- gDebugInfo["SessionID"] = text;
-
- // Session id needed for parcel info request in LLUrlEntryParcel
- // to resolve parcel name.
- LLUrlEntryParcel::setSessionID(gAgentSessionID);
-
- text = response["secure_session_id"].asString();
- if(!text.empty()) gAgent.mSecureSessionID.set(text);
-
- // if the response contains a display name, use that,
- // otherwise if the response contains a first and/or last name,
- // use those. Otherwise use the credential identifier
-
- gDisplayName = "";
- if (response.has("display_name"))
- {
- gDisplayName.assign(response["display_name"].asString());
- if(!gDisplayName.empty())
- {
- // Remove quotes from string. Login.cgi sends these to force
- // names that look like numbers into strings.
- LLStringUtil::replaceChar(gDisplayName, '"', ' ');
- LLStringUtil::trim(gDisplayName);
- }
- }
- std::string first_name;
- if(response.has("first_name"))
- {
- first_name = response["first_name"].asString();
- LLStringUtil::replaceChar(first_name, '"', ' ');
- LLStringUtil::trim(first_name);
- gAgentUsername = first_name;
- }
-
- if(response.has("last_name") && !gAgentUsername.empty())
- {
- std::string last_name = response["last_name"].asString();
- if (last_name != "Resident")
- {
- LLStringUtil::replaceChar(last_name, '"', ' ');
- LLStringUtil::trim(last_name);
- gAgentUsername = gAgentUsername + " " + last_name;
- }
- }
-
- if(gDisplayName.empty())
- {
- if(response.has("first_name"))
- {
- gDisplayName.assign(response["first_name"].asString());
- LLStringUtil::replaceChar(gDisplayName, '"', ' ');
- LLStringUtil::trim(gDisplayName);
- }
- if(response.has("last_name"))
- {
- text.assign(response["last_name"].asString());
- LLStringUtil::replaceChar(text, '"', ' ');
- LLStringUtil::trim(text);
- if(!gDisplayName.empty())
- {
- gDisplayName += " ";
- }
- gDisplayName += text;
- }
- }
-
- if(gDisplayName.empty())
- {
- gDisplayName.assign(gUserCredential->asString());
- }
-
- // this is their actual ability to access content
- text = response["agent_access_max"].asString();
- if (!text.empty())
- {
- // agent_access can be 'A', 'M', and 'PG'.
- gAgent.setMaturity(text[0]);
- }
-
- // this is the value of their preference setting for that content
- // which will always be <= agent_access_max
- text = response["agent_region_access"].asString();
- if (!text.empty())
- {
- U32 preferredMaturity = (U32)LLAgent::convertTextToMaturity(text[0]);
-
- gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
- }
-
- text = response["start_location"].asString();
- if(!text.empty())
- {
- gAgentStartLocation.assign(text);
- }
-
- text = response["circuit_code"].asString();
- if(!text.empty())
- {
- gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10);
- }
- std::string sim_ip_str = response["sim_ip"];
- std::string sim_port_str = response["sim_port"];
- if(!sim_ip_str.empty() && !sim_port_str.empty())
- {
- U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10);
- gFirstSim.set(sim_ip_str, sim_port);
- if (gFirstSim.isOk())
- {
- gMessageSystem->enableCircuit(gFirstSim, TRUE);
- }
- }
- std::string region_x_str = response["region_x"];
- std::string region_y_str = response["region_y"];
- if(!region_x_str.empty() && !region_y_str.empty())
- {
- U32 region_x = strtoul(region_x_str.c_str(), NULL, 10);
- U32 region_y = strtoul(region_y_str.c_str(), NULL, 10);
- gFirstSimHandle = to_region_handle(region_x, region_y);
- }
-
- const std::string look_at_str = response["look_at"];
- if (!look_at_str.empty())
- {
- size_t len = look_at_str.size();
- LLMemoryStream mstr((U8*)look_at_str.c_str(), len);
- LLSD sd = LLSDSerialize::fromNotation(mstr, len);
- gAgentStartLookAt = ll_vector3_from_sd(sd);
- }
-
- text = response["seed_capability"].asString();
- if (!text.empty()) gFirstSimSeedCap = text;
-
- text = response["seconds_since_epoch"].asString();
- if(!text.empty())
- {
- U32 server_utc_time = strtoul(text.c_str(), NULL, 10);
- if(server_utc_time)
- {
- time_t now = time(NULL);
- gUTCOffset = (server_utc_time - now);
-
- // Print server timestamp
- LLSD substitution;
- substitution["datetime"] = (S32)server_utc_time;
- std::string timeStr = "[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second, datetime, slt]";
- LLStringUtil::format(timeStr, substitution);
- LL_INFOS("AppInit") << "Server SLT timestamp: " << timeStr << ". Server-viewer time offset before correction: " << gUTCOffset << "s" << LL_ENDL;
- }
- }
-
- // this is the base used to construct help URLs
- text = response["help_url_format"].asString();
- if (!text.empty())
- {
- // replace the default help URL format
- gSavedSettings.setString("HelpURLFormat",text);
- }
-
- std::string home_location = response["home"];
- if(!home_location.empty())
- {
- size_t len = home_location.size();
- LLMemoryStream mstr((U8*)home_location.c_str(), len);
- LLSD sd = LLSDSerialize::fromNotation(mstr, len);
- S32 region_x = sd["region_handle"][0].asInteger();
- S32 region_y = sd["region_handle"][1].asInteger();
- U64 region_handle = to_region_handle(region_x, region_y);
- LLVector3 position = ll_vector3_from_sd(sd["position"]);
- gAgent.setHomePosRegion(region_handle, position);
- }
-
- gAgent.mMOTD.assign(response["message"]);
-
- // Options...
- // Each 'option' is an array of submaps.
- // It appears that we only ever use the first element of the array.
- LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"];
- if(inv_root_folder_id.notNull())
- {
- gInventory.setRootFolderID(inv_root_folder_id);
- //gInventory.mock(gAgent.getInventoryRootID());
- }
-
- LLSD login_flags = response["login-flags"][0];
- if(login_flags.size())
- {
- std::string flag = login_flags["ever_logged_in"];
- if(!flag.empty())
- {
- gAgent.setFirstLogin(flag == "N");
- }
-
- /* Flag is currently ignored by the viewer.
- flag = login_flags["stipend_since_login"];
- if(flag == "Y")
- {
- stipend_since_login = true;
- }
- */
-
- flag = login_flags["gendered"].asString();
- if(flag == "Y")
- {
- // We don't care about this flag anymore; now base whether
- // outfit is chosen on COF contents, initial outfit
- // requested and available, etc.
-
- //gAgent.setGenderChosen(TRUE);
- }
-
- bool pacific_daylight_time = false;
- flag = login_flags["daylight_savings"].asString();
- if(flag == "Y")
- {
- pacific_daylight_time = (flag == "Y");
- }
-
- //setup map of datetime strings to codes and slt & local time offset from utc
- LLStringOps::setupDatetimeInfo(pacific_daylight_time);
- }
-
- // set up the voice configuration. Ultimately, we should pass this up as part of each voice
- // channel if we need to move to multiple voice servers per grid.
- LLSD voice_config_info = response["voice-config"];
- if(voice_config_info.has("VoiceServerType"))
- {
- gSavedSettings.setString("VoiceServerType", voice_config_info["VoiceServerType"].asString());
- }
-
- // Request the map server url
- std::string map_server_url = response["map-server-url"];
- if(!map_server_url.empty())
- {
- // We got an answer from the grid -> use that for map for the current session
- gSavedSettings.setString("CurrentMapServerURL", map_server_url);
- LL_INFOS("LLStartup") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL;
- }
- else
- {
- // No answer from the grid -> use the default setting for current session
- map_server_url = gSavedSettings.getString("MapServerURL");
- gSavedSettings.setString("CurrentMapServerURL", map_server_url);
- LL_INFOS("LLStartup") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL;
- }
-
- // Default male and female avatars allowing the user to choose their avatar on first login.
- // These may be passed up by SLE to allow choice of enterprise avatars instead of the standard
- // "new ruth." Not to be confused with 'initial-outfit' below
- LLSD newuser_config = response["newuser-config"][0];
- if(newuser_config.has("DefaultFemaleAvatar"))
- {
- gSavedSettings.setString("DefaultFemaleAvatar", newuser_config["DefaultFemaleAvatar"].asString());
- }
- if(newuser_config.has("DefaultMaleAvatar"))
- {
- gSavedSettings.setString("DefaultMaleAvatar", newuser_config["DefaultMaleAvatar"].asString());
- }
-
- // Initial outfit for the user.
- LLSD initial_outfit = response["initial-outfit"][0];
- if(initial_outfit.size())
- {
- std::string flag = initial_outfit["folder_name"];
- if(!flag.empty())
- {
- // Initial outfit is a folder in your inventory,
- // must be an exact folder-name match.
- sInitialOutfit = flag;
- }
-
- flag = initial_outfit["gender"].asString();
- if(!flag.empty())
- {
- sInitialOutfitGender = flag;
- }
- }
-
- std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName");
- if (!fake_initial_outfit_name.empty())
- {
- gAgent.setFirstLogin(true);
- sInitialOutfit = fake_initial_outfit_name;
- if (sInitialOutfitGender.empty())
- {
- sInitialOutfitGender = "female"; // just guess, will get overridden when outfit is worn anyway.
- }
-
- LL_WARNS() << "Faking first-time login with initial outfit " << sInitialOutfit << LL_ENDL;
- }
-
- // set the location of the Agent Appearance service, from which we can request
- // avatar baked textures if they are supported by the current region
- std::string agent_appearance_url = response["agent_appearance_service"];
- if (!agent_appearance_url.empty())
- {
- LLAppearanceMgr::instance().setAppearanceServiceURL(agent_appearance_url);
- }
-
- // Set the location of the snapshot sharing config endpoint
- std::string snapshot_config_url = response["snapshot_config_url"];
- if(!snapshot_config_url.empty())
- {
- gSavedSettings.setString("SnapshotConfigURL", snapshot_config_url);
- }
-
- // Start the process of fetching the OpenID session cookie for this user login
- std::string openid_url = response["openid_url"];
- if(!openid_url.empty())
- {
- std::string openid_token = response["openid_token"];
- LLViewerMedia::getInstance()->openIDSetup(openid_url, openid_token);
- }
-
-
- // Only save mfa_hash for future logins if the user wants their info remembered.
- if(response.has("mfa_hash")
+ LLSD response = LLLoginInstance::getInstance()->getResponse();
+
+ mBenefitsSuccessfullyInit = init_benefits(response);
+
+ std::string text(response["udp_blacklist"]);
+ if(!text.empty())
+ {
+ apply_udp_blacklist(text);
+ }
+
+ // unpack login data needed by the application
+ text = response["agent_id"].asString();
+ if(!text.empty()) gAgentID.set(text);
+ gDebugInfo["AgentID"] = text;
+
+ LLPerfStats::StatsRecorder::setEnabled(gSavedSettings.getBOOL("PerfStatsCaptureEnabled"));
+ LLPerfStats::StatsRecorder::setFocusAv(gAgentID);
+
+ // Agent id needed for parcel info request in LLUrlEntryParcel
+ // to resolve parcel name.
+ LLUrlEntryParcel::setAgentID(gAgentID);
+
+ text = response["session_id"].asString();
+ if(!text.empty()) gAgentSessionID.set(text);
+ gDebugInfo["SessionID"] = text;
+
+ // Session id needed for parcel info request in LLUrlEntryParcel
+ // to resolve parcel name.
+ LLUrlEntryParcel::setSessionID(gAgentSessionID);
+
+ text = response["secure_session_id"].asString();
+ if(!text.empty()) gAgent.mSecureSessionID.set(text);
+
+ // if the response contains a display name, use that,
+ // otherwise if the response contains a first and/or last name,
+ // use those. Otherwise use the credential identifier
+
+ gDisplayName = "";
+ if (response.has("display_name"))
+ {
+ gDisplayName.assign(response["display_name"].asString());
+ if(!gDisplayName.empty())
+ {
+ // Remove quotes from string. Login.cgi sends these to force
+ // names that look like numbers into strings.
+ LLStringUtil::replaceChar(gDisplayName, '"', ' ');
+ LLStringUtil::trim(gDisplayName);
+ }
+ }
+ std::string first_name;
+ if(response.has("first_name"))
+ {
+ first_name = response["first_name"].asString();
+ LLStringUtil::replaceChar(first_name, '"', ' ');
+ LLStringUtil::trim(first_name);
+ gAgentUsername = first_name;
+ }
+
+ if(response.has("last_name") && !gAgentUsername.empty())
+ {
+ std::string last_name = response["last_name"].asString();
+ if (last_name != "Resident")
+ {
+ LLStringUtil::replaceChar(last_name, '"', ' ');
+ LLStringUtil::trim(last_name);
+ gAgentUsername = gAgentUsername + " " + last_name;
+ }
+ }
+
+ if(gDisplayName.empty())
+ {
+ if(response.has("first_name"))
+ {
+ gDisplayName.assign(response["first_name"].asString());
+ LLStringUtil::replaceChar(gDisplayName, '"', ' ');
+ LLStringUtil::trim(gDisplayName);
+ }
+ if(response.has("last_name"))
+ {
+ text.assign(response["last_name"].asString());
+ LLStringUtil::replaceChar(text, '"', ' ');
+ LLStringUtil::trim(text);
+ if(!gDisplayName.empty())
+ {
+ gDisplayName += " ";
+ }
+ gDisplayName += text;
+ }
+ }
+
+ if(gDisplayName.empty())
+ {
+ gDisplayName.assign(gUserCredential->asString());
+ }
+
+ // this is their actual ability to access content
+ text = response["agent_access_max"].asString();
+ if (!text.empty())
+ {
+ // agent_access can be 'A', 'M', and 'PG'.
+ gAgent.setMaturity(text[0]);
+ }
+
+ // this is the value of their preference setting for that content
+ // which will always be <= agent_access_max
+ text = response["agent_region_access"].asString();
+ if (!text.empty())
+ {
+ U32 preferredMaturity = (U32)LLAgent::convertTextToMaturity(text[0]);
+
+ gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
+ }
+
+ text = response["start_location"].asString();
+ if(!text.empty())
+ {
+ gAgentStartLocation.assign(text);
+ }
+
+ text = response["circuit_code"].asString();
+ if(!text.empty())
+ {
+ gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10);
+ }
+ std::string sim_ip_str = response["sim_ip"];
+ std::string sim_port_str = response["sim_port"];
+ if(!sim_ip_str.empty() && !sim_port_str.empty())
+ {
+ U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10);
+ gFirstSim.set(sim_ip_str, sim_port);
+ if (gFirstSim.isOk())
+ {
+ gMessageSystem->enableCircuit(gFirstSim, TRUE);
+ }
+ }
+ std::string region_x_str = response["region_x"];
+ std::string region_y_str = response["region_y"];
+ if(!region_x_str.empty() && !region_y_str.empty())
+ {
+ U32 region_x = strtoul(region_x_str.c_str(), NULL, 10);
+ U32 region_y = strtoul(region_y_str.c_str(), NULL, 10);
+ gFirstSimHandle = to_region_handle(region_x, region_y);
+ }
+
+ const std::string look_at_str = response["look_at"];
+ if (!look_at_str.empty())
+ {
+ size_t len = look_at_str.size();
+ LLMemoryStream mstr((U8*)look_at_str.c_str(), len);
+ LLSD sd = LLSDSerialize::fromNotation(mstr, len);
+ gAgentStartLookAt = ll_vector3_from_sd(sd);
+ }
+
+ text = response["seed_capability"].asString();
+ if (!text.empty()) gFirstSimSeedCap = text;
+
+ text = response["seconds_since_epoch"].asString();
+ if(!text.empty())
+ {
+ U32 server_utc_time = strtoul(text.c_str(), NULL, 10);
+ if(server_utc_time)
+ {
+ time_t now = time(NULL);
+ gUTCOffset = (server_utc_time - now);
+
+ // Print server timestamp
+ LLSD substitution;
+ substitution["datetime"] = (S32)server_utc_time;
+ std::string timeStr = "[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second, datetime, slt]";
+ LLStringUtil::format(timeStr, substitution);
+ LL_INFOS("AppInit") << "Server SLT timestamp: " << timeStr << ". Server-viewer time offset before correction: " << gUTCOffset << "s" << LL_ENDL;
+ }
+ }
+
+ // this is the base used to construct help URLs
+ text = response["help_url_format"].asString();
+ if (!text.empty())
+ {
+ // replace the default help URL format
+ gSavedSettings.setString("HelpURLFormat",text);
+ }
+
+ std::string home_location = response["home"];
+ if(!home_location.empty())
+ {
+ size_t len = home_location.size();
+ LLMemoryStream mstr((U8*)home_location.c_str(), len);
+ LLSD sd = LLSDSerialize::fromNotation(mstr, len);
+ S32 region_x = sd["region_handle"][0].asInteger();
+ S32 region_y = sd["region_handle"][1].asInteger();
+ U64 region_handle = to_region_handle(region_x, region_y);
+ LLVector3 position = ll_vector3_from_sd(sd["position"]);
+ gAgent.setHomePosRegion(region_handle, position);
+ }
+
+ gAgent.mMOTD.assign(response["message"]);
+
+ // Options...
+ // Each 'option' is an array of submaps.
+ // It appears that we only ever use the first element of the array.
+ LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"];
+ if(inv_root_folder_id.notNull())
+ {
+ gInventory.setRootFolderID(inv_root_folder_id);
+ //gInventory.mock(gAgent.getInventoryRootID());
+ }
+
+ LLSD login_flags = response["login-flags"][0];
+ if(login_flags.size())
+ {
+ std::string flag = login_flags["ever_logged_in"];
+ if(!flag.empty())
+ {
+ gAgent.setFirstLogin(flag == "N");
+ }
+
+ /* Flag is currently ignored by the viewer.
+ flag = login_flags["stipend_since_login"];
+ if(flag == "Y")
+ {
+ stipend_since_login = true;
+ }
+ */
+
+ flag = login_flags["gendered"].asString();
+ if(flag == "Y")
+ {
+ // We don't care about this flag anymore; now base whether
+ // outfit is chosen on COF contents, initial outfit
+ // requested and available, etc.
+
+ //gAgent.setGenderChosen(TRUE);
+ }
+
+ bool pacific_daylight_time = false;
+ flag = login_flags["daylight_savings"].asString();
+ if(flag == "Y")
+ {
+ pacific_daylight_time = (flag == "Y");
+ }
+
+ //setup map of datetime strings to codes and slt & local time offset from utc
+ LLStringOps::setupDatetimeInfo(pacific_daylight_time);
+ }
+
+ // set up the voice configuration. Ultimately, we should pass this up as part of each voice
+ // channel if we need to move to multiple voice servers per grid.
+ LLSD voice_config_info = response["voice-config"];
+ if(voice_config_info.has("VoiceServerType"))
+ {
+ gSavedSettings.setString("VoiceServerType", voice_config_info["VoiceServerType"].asString());
+ }
+
+ // Request the map server url
+ std::string map_server_url = response["map-server-url"];
+ if(!map_server_url.empty())
+ {
+ // We got an answer from the grid -> use that for map for the current session
+ gSavedSettings.setString("CurrentMapServerURL", map_server_url);
+ LL_INFOS("LLStartup") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL;
+ }
+ else
+ {
+ // No answer from the grid -> use the default setting for current session
+ map_server_url = gSavedSettings.getString("MapServerURL");
+ gSavedSettings.setString("CurrentMapServerURL", map_server_url);
+ LL_INFOS("LLStartup") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL;
+ }
+
+ // Default male and female avatars allowing the user to choose their avatar on first login.
+ // These may be passed up by SLE to allow choice of enterprise avatars instead of the standard
+ // "new ruth." Not to be confused with 'initial-outfit' below
+ LLSD newuser_config = response["newuser-config"][0];
+ if(newuser_config.has("DefaultFemaleAvatar"))
+ {
+ gSavedSettings.setString("DefaultFemaleAvatar", newuser_config["DefaultFemaleAvatar"].asString());
+ }
+ if(newuser_config.has("DefaultMaleAvatar"))
+ {
+ gSavedSettings.setString("DefaultMaleAvatar", newuser_config["DefaultMaleAvatar"].asString());
+ }
+
+ // Initial outfit for the user.
+ LLSD initial_outfit = response["initial-outfit"][0];
+ if(initial_outfit.size())
+ {
+ std::string flag = initial_outfit["folder_name"];
+ if(!flag.empty())
+ {
+ // Initial outfit is a folder in your inventory,
+ // must be an exact folder-name match.
+ sInitialOutfit = flag;
+ }
+
+ flag = initial_outfit["gender"].asString();
+ if(!flag.empty())
+ {
+ sInitialOutfitGender = flag;
+ }
+ }
+
+ std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName");
+ if (!fake_initial_outfit_name.empty())
+ {
+ gAgent.setFirstLogin(true);
+ sInitialOutfit = fake_initial_outfit_name;
+ if (sInitialOutfitGender.empty())
+ {
+ sInitialOutfitGender = "female"; // just guess, will get overridden when outfit is worn anyway.
+ }
+
+ LL_WARNS() << "Faking first-time login with initial outfit " << sInitialOutfit << LL_ENDL;
+ }
+
+ // set the location of the Agent Appearance service, from which we can request
+ // avatar baked textures if they are supported by the current region
+ std::string agent_appearance_url = response["agent_appearance_service"];
+ if (!agent_appearance_url.empty())
+ {
+ LLAppearanceMgr::instance().setAppearanceServiceURL(agent_appearance_url);
+ }
+
+ // Set the location of the snapshot sharing config endpoint
+ std::string snapshot_config_url = response["snapshot_config_url"];
+ if(!snapshot_config_url.empty())
+ {
+ gSavedSettings.setString("SnapshotConfigURL", snapshot_config_url);
+ }
+
+ // Start the process of fetching the OpenID session cookie for this user login
+ std::string openid_url = response["openid_url"];
+ if(!openid_url.empty())
+ {
+ std::string openid_token = response["openid_token"];
+ LLViewerMedia::getInstance()->openIDSetup(openid_url, openid_token);
+ }
+
+
+ // Only save mfa_hash for future logins if the user wants their info remembered.
+ if(response.has("mfa_hash")
&& gSavedSettings.getBOOL("RememberUser")
&& LLLoginInstance::getInstance()->saveMFA())
- {
- std::string grid(LLGridManager::getInstance()->getGridId());
- std::string user_id(gUserCredential->userID());
- gSecAPIHandler->addToProtectedMap("mfa_hash", grid, user_id, response["mfa_hash"]);
- // TODO(brad) - related to SL-17223 consider building a better interface that sync's automatically
- gSecAPIHandler->syncProtectedMap();
- }
+ {
+ std::string grid(LLGridManager::getInstance()->getGridId());
+ std::string user_id(gUserCredential->userID());
+ gSecAPIHandler->addToProtectedMap("mfa_hash", grid, user_id, response["mfa_hash"]);
+ // TODO(brad) - related to SL-17223 consider building a better interface that sync's automatically
+ gSecAPIHandler->syncProtectedMap();
+ }
else if (!LLLoginInstance::getInstance()->saveMFA())
{
std::string grid(LLGridManager::getInstance()->getGridId());
@@ -3867,26 +3870,26 @@ bool process_login_success_response()
gSecAPIHandler->syncProtectedMap();
}
- bool success = false;
- // JC: gesture loading done below, when we have an asset system
- // in place. Don't delete/clear gUserCredentials until then.
- if(gAgentID.notNull()
- && gAgentSessionID.notNull()
- && gMessageSystem->mOurCircuitCode
- && gFirstSim.isOk()
- && gInventory.getRootFolderID().notNull())
- {
- success = true;
- }
+ bool success = false;
+ // JC: gesture loading done below, when we have an asset system
+ // in place. Don't delete/clear gUserCredentials until then.
+ if(gAgentID.notNull()
+ && gAgentSessionID.notNull()
+ && gMessageSystem->mOurCircuitCode
+ && gFirstSim.isOk()
+ && gInventory.getRootFolderID().notNull())
+ {
+ success = true;
+ }
LLAppViewer* pApp = LLAppViewer::instance();
- pApp->writeDebugInfo(); //Write our static data now that we have username, session_id, etc.
- return success;
+ pApp->writeDebugInfo(); //Write our static data now that we have username, session_id, etc.
+ return success;
}
void transition_back_to_login_panel(const std::string& emsg)
{
- // Bounce back to the login screen.
- reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW );
- gSavedSettings.setBOOL("AutoLogin", FALSE);
+ // Bounce back to the login screen.
+ reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+ gSavedSettings.setBOOL("AutoLogin", FALSE);
}
diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp
index 2519c57e86..a4e6d20181 100644
--- a/indra/newview/lltoolplacer.cpp
+++ b/indra/newview/lltoolplacer.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lltoolplacer.cpp
* @brief Tool for placing new objects into the world
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -60,474 +60,480 @@
// linden library headers
#include "llprimitive.h"
-#include "llwindow.h" // incBusyCount()
+#include "llwindow.h" // incBusyCount()
#include "material_codes.h"
#include "lluiusage.h"
const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f);
-//static
-LLPCode LLToolPlacer::sObjectType = LL_PCODE_CUBE;
+//static
+LLPCode LLToolPlacer::sObjectType = LL_PCODE_CUBE;
LLToolPlacer::LLToolPlacer()
-: LLTool( "Create" )
+: LLTool( "Create" )
{
}
-BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj, S32* hit_face,
- BOOL* b_hit_land, LLVector3* ray_start_region, LLVector3* ray_end_region, LLViewerRegion** region )
+BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj, S32* hit_face,
+ BOOL* b_hit_land, LLVector3* ray_start_region, LLVector3* ray_end_region, LLViewerRegion** region )
{
- F32 max_dist_from_camera = gSavedSettings.getF32( "MaxSelectDistance" ) - 1.f;
-
- // Viewer-side pick to find the right sim to create the object on.
- // First find the surface the object will be created on.
- LLPickInfo pick = gViewerWindow->pickImmediate(x, y, FALSE, FALSE);
-
- // Note: use the frontmost non-flora version because (a) plants usually have lots of alpha and (b) pants' Havok
- // representations (if any) are NOT the same as their viewer representation.
- if (pick.mPickType == LLPickInfo::PICK_FLORA)
- {
- *hit_obj = NULL;
- *hit_face = -1;
- }
- else
- {
- *hit_obj = pick.getObject();
- *hit_face = pick.mObjectFace;
- }
- *b_hit_land = !(*hit_obj) && !pick.mPosGlobal.isExactlyZero();
- LLVector3d land_pos_global = pick.mPosGlobal;
-
- // Make sure there's a surface to place the new object on.
- BOOL bypass_sim_raycast = FALSE;
- LLVector3d surface_pos_global;
- if (*b_hit_land)
- {
- surface_pos_global = land_pos_global;
- bypass_sim_raycast = TRUE;
- }
- else
- if (*hit_obj)
- {
- surface_pos_global = (*hit_obj)->getPositionGlobal();
- }
- else
- {
- return FALSE;
- }
-
- // Make sure the surface isn't too far away.
- LLVector3d ray_start_global = gAgentCamera.getCameraPositionGlobal();
- F32 dist_to_surface_sq = (F32)((surface_pos_global - ray_start_global).magVecSquared());
- if( dist_to_surface_sq > (max_dist_from_camera * max_dist_from_camera) )
- {
- return FALSE;
- }
-
- // Find the sim where the surface lives.
- LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(surface_pos_global);
- if (!regionp)
- {
- LL_WARNS() << "Trying to add object outside of all known regions!" << LL_ENDL;
- return FALSE;
- }
-
- // Find the simulator-side ray that will be used to place the object accurately
- LLVector3d mouse_direction;
- mouse_direction.setVec( gViewerWindow->mouseDirectionGlobal( x, y ) );
-
- *region = regionp;
- *ray_start_region = regionp->getPosRegionFromGlobal( ray_start_global );
- F32 near_clip = LLViewerCamera::getInstance()->getNear() + 0.01f; // Include an epsilon to avoid rounding issues.
- *ray_start_region += LLViewerCamera::getInstance()->getAtAxis() * near_clip;
-
- if( bypass_sim_raycast )
- {
- // Hack to work around Havok's inability to ray cast onto height fields
- *ray_end_region = regionp->getPosRegionFromGlobal( surface_pos_global ); // ray end is the viewer's intersection point
- }
- else
- {
- LLVector3d ray_end_global = ray_start_global + (1.f + max_dist_from_camera) * mouse_direction; // add an epsilon to the sim version of the ray to avoid rounding problems.
- *ray_end_region = regionp->getPosRegionFromGlobal( ray_end_global );
- }
-
- return TRUE;
+ F32 max_dist_from_camera = gSavedSettings.getF32( "MaxSelectDistance" ) - 1.f;
+
+ // Viewer-side pick to find the right sim to create the object on.
+ // First find the surface the object will be created on.
+ LLPickInfo pick = gViewerWindow->pickImmediate(x, y, FALSE, FALSE);
+
+ // Note: use the frontmost non-flora version because (a) plants usually have lots of alpha and (b) pants' Havok
+ // representations (if any) are NOT the same as their viewer representation.
+ if (pick.mPickType == LLPickInfo::PICK_FLORA)
+ {
+ *hit_obj = NULL;
+ *hit_face = -1;
+ }
+ else
+ {
+ *hit_obj = pick.getObject();
+ *hit_face = pick.mObjectFace;
+ }
+ *b_hit_land = !(*hit_obj) && !pick.mPosGlobal.isExactlyZero();
+ LLVector3d land_pos_global = pick.mPosGlobal;
+
+ // Make sure there's a surface to place the new object on.
+ BOOL bypass_sim_raycast = FALSE;
+ LLVector3d surface_pos_global;
+ if (*b_hit_land)
+ {
+ surface_pos_global = land_pos_global;
+ bypass_sim_raycast = TRUE;
+ }
+ else
+ if (*hit_obj)
+ {
+ surface_pos_global = (*hit_obj)->getPositionGlobal();
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ // Make sure the surface isn't too far away.
+ LLVector3d ray_start_global = gAgentCamera.getCameraPositionGlobal();
+ F32 dist_to_surface_sq = (F32)((surface_pos_global - ray_start_global).magVecSquared());
+ if( dist_to_surface_sq > (max_dist_from_camera * max_dist_from_camera) )
+ {
+ return FALSE;
+ }
+
+ // Find the sim where the surface lives.
+ LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(surface_pos_global);
+ if (!regionp)
+ {
+ LL_WARNS() << "Trying to add object outside of all known regions!" << LL_ENDL;
+ return FALSE;
+ }
+
+ // Find the simulator-side ray that will be used to place the object accurately
+ LLVector3d mouse_direction;
+ mouse_direction.setVec( gViewerWindow->mouseDirectionGlobal( x, y ) );
+
+ *region = regionp;
+ *ray_start_region = regionp->getPosRegionFromGlobal( ray_start_global );
+ F32 near_clip = LLViewerCamera::getInstance()->getNear() + 0.01f; // Include an epsilon to avoid rounding issues.
+ *ray_start_region += LLViewerCamera::getInstance()->getAtAxis() * near_clip;
+
+ if( bypass_sim_raycast )
+ {
+ // Hack to work around Havok's inability to ray cast onto height fields
+ *ray_end_region = regionp->getPosRegionFromGlobal( surface_pos_global ); // ray end is the viewer's intersection point
+ }
+ else
+ {
+ LLVector3d ray_end_global = ray_start_global + (1.f + max_dist_from_camera) * mouse_direction; // add an epsilon to the sim version of the ray to avoid rounding problems.
+ *ray_end_region = regionp->getPosRegionFromGlobal( ray_end_global );
+ }
+
+ return TRUE;
}
BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics )
{
- LLVector3 ray_start_region;
- LLVector3 ray_end_region;
- LLViewerRegion* regionp = NULL;
- BOOL b_hit_land = FALSE;
- S32 hit_face = -1;
- LLViewerObject* hit_obj = NULL;
+ LLVector3 ray_start_region;
+ LLVector3 ray_end_region;
+ LLViewerRegion* regionp = NULL;
+ BOOL b_hit_land = FALSE;
+ S32 hit_face = -1;
+ LLViewerObject* hit_obj = NULL;
+ BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, &regionp );
+ if( !success )
+ {
+ return FALSE;
+ }
+ return rezNewObject(pcode,hit_obj, hit_face, b_hit_land, ray_start_region, ray_end_region, regionp, use_physics);
+}
+
+BOOL LLToolPlacer::rezNewObject(LLPCode pcode, LLViewerObject * hit_obj, S32 hit_face, BOOL b_hit_land, LLVector3 ray_start_region,
+ LLVector3 ray_end_region, LLViewerRegion* regionp, U8 use_physics)
+{
+ if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
+ {
+ // Can't create objects on avatars or attachments
+ return FALSE;
+ }
+
+ if (NULL == regionp)
+ {
+ LL_WARNS() << "regionp was NULL; aborting function." << LL_ENDL;
+ return FALSE;
+ }
+
+ if (regionp->getRegionFlag(REGION_FLAGS_SANDBOX))
+ {
+ //LLFirstUse::useSandbox();
+ }
+
+ // Set params for new object based on its PCode.
+ LLQuaternion rotation;
+ LLVector3 scale = DEFAULT_OBJECT_SCALE;
+ U8 material = LL_MCODE_WOOD;
+ BOOL create_selected = FALSE;
+ LLVolumeParams volume_params;
+
U8 state = 0;
- BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, &regionp );
- if( !success )
- {
- return FALSE;
- }
-
- if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
- {
- // Can't create objects on avatars or attachments
- return FALSE;
- }
-
- if (NULL == regionp)
- {
- LL_WARNS() << "regionp was NULL; aborting function." << LL_ENDL;
- return FALSE;
- }
-
- if (regionp->getRegionFlag(REGION_FLAGS_SANDBOX))
- {
- //LLFirstUse::useSandbox();
- }
-
- // Set params for new object based on its PCode.
- LLQuaternion rotation;
- LLVector3 scale = DEFAULT_OBJECT_SCALE;
- U8 material = LL_MCODE_WOOD;
- BOOL create_selected = FALSE;
- LLVolumeParams volume_params;
-
- switch (pcode)
- {
- case LL_PCODE_LEGACY_GRASS:
- // Randomize size of grass patch
- scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f), 1.f + ll_frand(2.f));
- state = rand() % LLVOGrass::sMaxGrassSpecies;
- break;
-
-
- case LL_PCODE_LEGACY_TREE:
- case LL_PCODE_TREE_NEW:
- state = rand() % LLVOTree::sMaxTreeSpecies;
- break;
-
- case LL_PCODE_SPHERE:
- case LL_PCODE_CONE:
- case LL_PCODE_CUBE:
- case LL_PCODE_CYLINDER:
- case LL_PCODE_TORUS:
- case LLViewerObject::LL_VO_SQUARE_TORUS:
- case LLViewerObject::LL_VO_TRIANGLE_TORUS:
- default:
- create_selected = TRUE;
- break;
- }
-
- // Play creation sound
- if (gAudiop)
- {
- gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")),
- gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
- }
-
- LLUIUsage::instance().logCommand("Build.ObjectAdd");
- gMessageSystem->newMessageFast(_PREHASH_ObjectAdd);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU8Fast(_PREHASH_Material, material);
-
- U32 flags = 0; // not selected
- if (use_physics)
- {
- flags |= FLAGS_USE_PHYSICS;
- }
- if (create_selected)
- {
- flags |= FLAGS_CREATE_SELECTED;
- }
- gMessageSystem->addU32Fast(_PREHASH_AddFlags, flags );
-
- LLPCode volume_pcode; // ...PCODE_VOLUME, or the original on error
- switch (pcode)
- {
- case LL_PCODE_SPHERE:
- rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
-
- volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1, 1 );
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_TORUS:
- rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
-
- volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1.f, 0.25f ); // "top size"
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LLViewerObject::LL_VO_SQUARE_TORUS:
- rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
-
- volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_CIRCLE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1.f, 0.25f ); // "top size"
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LLViewerObject::LL_VO_TRIANGLE_TORUS:
- rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
-
- volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_CIRCLE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1.f, 0.25f ); // "top size"
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_SPHERE_HEMI:
- volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
- //volume_params.setBeginAndEndS( 0.5f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 0.5f );
- volume_params.setRatio ( 1, 1 );
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_CUBE:
- volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1, 1 );
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_PRISM:
- volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 0, 1 );
- volume_params.setShear ( -0.5f, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_PYRAMID:
- volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 0, 0 );
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_TETRAHEDRON:
- volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 0, 0 );
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_CYLINDER:
- volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1, 1 );
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_CYLINDER_HEMI:
- volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.25f, 0.75f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1, 1 );
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_CONE:
- volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 0, 0 );
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- case LL_PCODE_CONE_HEMI:
- volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.25f, 0.75f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 0, 0 );
- volume_params.setShear ( 0, 0 );
- LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
- volume_pcode = LL_PCODE_VOLUME;
- break;
-
- default:
- LLVolumeMessage::packVolumeParams(0, gMessageSystem);
- volume_pcode = pcode;
- break;
- }
- gMessageSystem->addU8Fast(_PREHASH_PCode, volume_pcode);
-
- gMessageSystem->addVector3Fast(_PREHASH_Scale, scale );
- gMessageSystem->addQuatFast(_PREHASH_Rotation, rotation );
- gMessageSystem->addVector3Fast(_PREHASH_RayStart, ray_start_region );
- gMessageSystem->addVector3Fast(_PREHASH_RayEnd, ray_end_region );
- gMessageSystem->addU8Fast(_PREHASH_BypassRaycast, (U8)b_hit_land );
- gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE );
- gMessageSystem->addU8Fast(_PREHASH_State, state);
-
- // Limit raycast to a single object.
- // Speeds up server raycast + avoid problems with server ray hitting objects
- // that were clipped by the near plane or culled on the viewer.
- LLUUID ray_target_id;
- if( hit_obj )
- {
- ray_target_id = hit_obj->getID();
- }
- else
- {
- ray_target_id.setNull();
- }
- gMessageSystem->addUUIDFast(_PREHASH_RayTargetID, ray_target_id );
-
- // Pack in name value pairs
- gMessageSystem->sendReliable(regionp->getHost());
-
- // Spawns a message, so must be after above send
- if (create_selected)
- {
- LLSelectMgr::getInstance()->deselectAll();
- gViewerWindow->getWindow()->incBusyCount();
- }
-
- // VEFFECT: AddObject
- LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
- effectp->setSourceObject((LLViewerObject*)gAgentAvatarp);
- effectp->setPositionGlobal(regionp->getPosGlobalFromRegion(ray_end_region));
- effectp->setDuration(LL_HUD_DUR_SHORT);
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
-
- add(LLStatViewer::OBJECT_CREATE, 1);
-
- return TRUE;
+
+ switch (pcode)
+ {
+ case LL_PCODE_LEGACY_GRASS:
+ // Randomize size of grass patch
+ scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f), 1.f + ll_frand(2.f));
+ state = rand() % LLVOGrass::sMaxGrassSpecies;
+ break;
+
+
+ case LL_PCODE_LEGACY_TREE:
+ case LL_PCODE_TREE_NEW:
+ state = rand() % LLVOTree::sMaxTreeSpecies;
+ break;
+
+ case LL_PCODE_SPHERE:
+ case LL_PCODE_CONE:
+ case LL_PCODE_CUBE:
+ case LL_PCODE_CYLINDER:
+ case LL_PCODE_TORUS:
+ case LLViewerObject::LL_VO_SQUARE_TORUS:
+ case LLViewerObject::LL_VO_TRIANGLE_TORUS:
+ default:
+ create_selected = TRUE;
+ break;
+ }
+
+ // Play creation sound
+ if (gAudiop)
+ {
+ gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")),
+ gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
+ }
+
+ LLUIUsage::instance().logCommand("Build.ObjectAdd");
+ gMessageSystem->newMessageFast(_PREHASH_ObjectAdd);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addU8Fast(_PREHASH_Material, material);
+
+ U32 flags = 0; // not selected
+ if (use_physics)
+ {
+ flags |= FLAGS_USE_PHYSICS;
+ }
+ if (create_selected)
+ {
+ flags |= FLAGS_CREATE_SELECTED;
+ }
+ gMessageSystem->addU32Fast(_PREHASH_AddFlags, flags );
+
+ LLPCode volume_pcode; // ...PCODE_VOLUME, or the original on error
+ switch (pcode)
+ {
+ case LL_PCODE_SPHERE:
+ rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
+
+ volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 1, 1 );
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_TORUS:
+ rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
+
+ volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 1.f, 0.25f ); // "top size"
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LLViewerObject::LL_VO_SQUARE_TORUS:
+ rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
+
+ volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_CIRCLE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 1.f, 0.25f ); // "top size"
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LLViewerObject::LL_VO_TRIANGLE_TORUS:
+ rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
+
+ volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_CIRCLE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 1.f, 0.25f ); // "top size"
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_SPHERE_HEMI:
+ volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
+ //volume_params.setBeginAndEndS( 0.5f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 0.5f );
+ volume_params.setRatio ( 1, 1 );
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_CUBE:
+ volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 1, 1 );
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_PRISM:
+ volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 0, 1 );
+ volume_params.setShear ( -0.5f, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_PYRAMID:
+ volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 0, 0 );
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_TETRAHEDRON:
+ volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_LINE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 0, 0 );
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_CYLINDER:
+ volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 1, 1 );
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_CYLINDER_HEMI:
+ volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
+ volume_params.setBeginAndEndS( 0.25f, 0.75f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 1, 1 );
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_CONE:
+ volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
+ volume_params.setBeginAndEndS( 0.f, 1.f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 0, 0 );
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ case LL_PCODE_CONE_HEMI:
+ volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
+ volume_params.setBeginAndEndS( 0.25f, 0.75f );
+ volume_params.setBeginAndEndT( 0.f, 1.f );
+ volume_params.setRatio ( 0, 0 );
+ volume_params.setShear ( 0, 0 );
+ LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
+ volume_pcode = LL_PCODE_VOLUME;
+ break;
+
+ default:
+ LLVolumeMessage::packVolumeParams(0, gMessageSystem);
+ volume_pcode = pcode;
+ break;
+ }
+ gMessageSystem->addU8Fast(_PREHASH_PCode, volume_pcode);
+
+ gMessageSystem->addVector3Fast(_PREHASH_Scale, scale );
+ gMessageSystem->addQuatFast(_PREHASH_Rotation, rotation );
+ gMessageSystem->addVector3Fast(_PREHASH_RayStart, ray_start_region );
+ gMessageSystem->addVector3Fast(_PREHASH_RayEnd, ray_end_region );
+ gMessageSystem->addU8Fast(_PREHASH_BypassRaycast, (U8)b_hit_land );
+ gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE );
+ gMessageSystem->addU8Fast(_PREHASH_State, state);
+
+ // Limit raycast to a single object.
+ // Speeds up server raycast + avoid problems with server ray hitting objects
+ // that were clipped by the near plane or culled on the viewer.
+ LLUUID ray_target_id;
+ if( hit_obj )
+ {
+ ray_target_id = hit_obj->getID();
+ }
+ else
+ {
+ ray_target_id.setNull();
+ }
+ gMessageSystem->addUUIDFast(_PREHASH_RayTargetID, ray_target_id );
+
+ // Pack in name value pairs
+ gMessageSystem->sendReliable(regionp->getHost());
+
+ // Spawns a message, so must be after above send
+ if (create_selected)
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ gViewerWindow->getWindow()->incBusyCount();
+ }
+
+ // VEFFECT: AddObject
+ LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
+ effectp->setSourceObject((LLViewerObject*)gAgentAvatarp);
+ effectp->setPositionGlobal(regionp->getPosGlobalFromRegion(ray_end_region));
+ effectp->setDuration(LL_HUD_DUR_SHORT);
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+
+ add(LLStatViewer::OBJECT_CREATE, 1);
+
+ return TRUE;
}
// Used by the placer tool to add copies of the current selection.
// Inspired by add_object(). JC
BOOL LLToolPlacer::addDuplicate(S32 x, S32 y)
{
- LLVector3 ray_start_region;
- LLVector3 ray_end_region;
- LLViewerRegion* regionp = NULL;
- BOOL b_hit_land = FALSE;
- S32 hit_face = -1;
- LLViewerObject* hit_obj = NULL;
- BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, &regionp );
- if( !success )
- {
- make_ui_sound("UISndInvalidOp");
- return FALSE;
- }
- if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
- {
- // Can't create objects on avatars or attachments
- make_ui_sound("UISndInvalidOp");
- return FALSE;
- }
-
-
- // Limit raycast to a single object.
- // Speeds up server raycast + avoid problems with server ray hitting objects
- // that were clipped by the near plane or culled on the viewer.
- LLUUID ray_target_id;
- if( hit_obj )
- {
- ray_target_id = hit_obj->getID();
- }
- else
- {
- ray_target_id.setNull();
- }
-
- LLSelectMgr::getInstance()->selectDuplicateOnRay(ray_start_region,
- ray_end_region,
- b_hit_land, // suppress raycast
- FALSE, // intersection
- ray_target_id,
- gSavedSettings.getBOOL("CreateToolCopyCenters"),
- gSavedSettings.getBOOL("CreateToolCopyRotates"),
- FALSE); // select copy
-
- if (regionp
- && (regionp->getRegionFlag(REGION_FLAGS_SANDBOX)))
- {
- //LLFirstUse::useSandbox();
- }
-
- return TRUE;
+ LLVector3 ray_start_region;
+ LLVector3 ray_end_region;
+ LLViewerRegion* regionp = NULL;
+ BOOL b_hit_land = FALSE;
+ S32 hit_face = -1;
+ LLViewerObject* hit_obj = NULL;
+ BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, &regionp );
+ if( !success )
+ {
+ make_ui_sound("UISndInvalidOp");
+ return FALSE;
+ }
+ if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
+ {
+ // Can't create objects on avatars or attachments
+ make_ui_sound("UISndInvalidOp");
+ return FALSE;
+ }
+
+
+ // Limit raycast to a single object.
+ // Speeds up server raycast + avoid problems with server ray hitting objects
+ // that were clipped by the near plane or culled on the viewer.
+ LLUUID ray_target_id;
+ if( hit_obj )
+ {
+ ray_target_id = hit_obj->getID();
+ }
+ else
+ {
+ ray_target_id.setNull();
+ }
+
+ LLSelectMgr::getInstance()->selectDuplicateOnRay(ray_start_region,
+ ray_end_region,
+ b_hit_land, // suppress raycast
+ FALSE, // intersection
+ ray_target_id,
+ gSavedSettings.getBOOL("CreateToolCopyCenters"),
+ gSavedSettings.getBOOL("CreateToolCopyRotates"),
+ FALSE); // select copy
+
+ if (regionp
+ && (regionp->getRegionFlag(REGION_FLAGS_SANDBOX)))
+ {
+ //LLFirstUse::useSandbox();
+ }
+
+ return TRUE;
}
BOOL LLToolPlacer::placeObject(S32 x, S32 y, MASK mask)
{
- BOOL added = TRUE;
-
- if (gSavedSettings.getBOOL("CreateToolCopySelection"))
- {
- added = addDuplicate(x, y);
- }
- else
- {
- added = addObject( sObjectType, x, y, FALSE );
- }
-
- // ...and go back to the default tool
- if (added && !gSavedSettings.getBOOL("CreateToolKeepSelected"))
- {
- LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompTranslate::getInstance() );
- }
-
- return added;
+ BOOL added = TRUE;
+
+ if (gSavedSettings.getBOOL("CreateToolCopySelection"))
+ {
+ added = addDuplicate(x, y);
+ }
+ else
+ {
+ added = addObject( sObjectType, x, y, FALSE );
+ }
+
+ // ...and go back to the default tool
+ if (added && !gSavedSettings.getBOOL("CreateToolKeepSelected"))
+ {
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompTranslate::getInstance() );
+ }
+
+ return added;
}
BOOL LLToolPlacer::handleHover(S32 x, S32 y, MASK mask)
{
- LL_DEBUGS("UserInput") << "hover handled by LLToolPlacer" << LL_ENDL;
- gViewerWindow->setCursor(UI_CURSOR_TOOLCREATE);
- return TRUE;
+ LL_DEBUGS("UserInput") << "hover handled by LLToolPlacer" << LL_ENDL;
+ gViewerWindow->setCursor(UI_CURSOR_TOOLCREATE);
+ return TRUE;
}
void LLToolPlacer::handleSelect()
{
- gFloaterTools->setStatusText("place");
+ gFloaterTools->setStatusText("place");
}
void LLToolPlacer::handleDeselect()
diff --git a/indra/newview/lltoolplacer.h b/indra/newview/lltoolplacer.h
index d5e4a587d7..d20d682710 100644
--- a/indra/newview/lltoolplacer.h
+++ b/indra/newview/lltoolplacer.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lltoolplacer.h
* @brief Tool for placing new objects into the world
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -37,27 +37,31 @@ class LLViewerRegion;
// LLToolPlacer
class LLToolPlacer
- : public LLTool
+ : public LLTool
{
public:
- LLToolPlacer();
+ LLToolPlacer();
+
+ virtual BOOL placeObject(S32 x, S32 y, MASK mask);
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ virtual void handleSelect(); // do stuff when your tool is selected
+ virtual void handleDeselect(); // clean up when your tool is deselected
- virtual BOOL placeObject(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual void handleSelect(); // do stuff when your tool is selected
- virtual void handleDeselect(); // clean up when your tool is deselected
+ static void setObjectType( LLPCode type ) { sObjectType = type; }
+ static LLPCode getObjectType() { return sObjectType; }
- static void setObjectType( LLPCode type ) { sObjectType = type; }
- static LLPCode getObjectType() { return sObjectType; }
+ static BOOL addObject(LLPCode pcode, S32 x, S32 y, U8 use_physics);
+ static BOOL rezNewObject(LLPCode pcode, LLViewerObject* hit_obj, S32 hit_face, BOOL b_hit_land, LLVector3 ray_start_region,
+ LLVector3 ray_end_region, LLViewerRegion *regionp, U8 use_physics);
protected:
- static LLPCode sObjectType;
+ static LLPCode sObjectType;
private:
- BOOL addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics );
- BOOL raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj, S32* hit_face,
- BOOL* b_hit_land, LLVector3* ray_start_region, LLVector3* ray_end_region, LLViewerRegion** region );
- BOOL addDuplicate(S32 x, S32 y);
+
+ static BOOL raycastForNewObjPos(S32 x, S32 y, LLViewerObject **hit_obj, S32 *hit_face,
+ BOOL* b_hit_land, LLVector3* ray_start_region, LLVector3* ray_end_region, LLViewerRegion** region );
+ BOOL addDuplicate(S32 x, S32 y);
};
#endif
diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp
index beae71e7bf..97a2be6aa3 100644
--- a/indra/newview/lluilistener.cpp
+++ b/indra/newview/lluilistener.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-08-18
* @brief Implementation for lluilistener.
- *
+ *
* $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$
*/
@@ -67,7 +67,7 @@ void LLUIListener::call(const LLSD& event) const
// API: we provide no reply. Therefore, a typo in the script will
// provide no feedback whatsoever to that script. To rub the coder's
// nose in such an error, crump rather than quietly ignoring it.
- LL_ERRS("LLUIListener") << "function '" << event["function"] << "' not found" << LL_ENDL;
+ LL_WARNS("LLUIListener") << "function '" << event["function"] << "' not found" << LL_ENDL;
}
else
{
@@ -88,7 +88,7 @@ void LLUIListener::getValue(const LLSD&event) const
const LLView* view = LLUI::getInstance()->resolvePath(root, event["path"].asString());
const LLUICtrl* ctrl(dynamic_cast<const LLUICtrl*>(view));
- if (ctrl)
+ if (ctrl)
{
reply["value"] = ctrl->getValue();
}
@@ -96,6 +96,6 @@ void LLUIListener::getValue(const LLSD&event) const
{
// *TODO: ??? return something indicating failure to resolve
}
-
+
sendReply(reply, event);
}
diff --git a/indra/newview/lluilistener.h b/indra/newview/lluilistener.h
index 70455c2c68..e53984dae2 100644
--- a/indra/newview/lluilistener.h
+++ b/indra/newview/lluilistener.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-08-18
* @brief Engage named functions as specified by XUI
- *
+ *
* $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$
*/
@@ -39,7 +39,8 @@ class LLUIListener: public LLEventAPI
public:
LLUIListener();
-private:
+// FIXME These fields are intended to be private, changed here to support very hacky code in llluamanager.cpp
+public:
void call(const LLSD& event) const;
void getValue(const LLSD&event) const;
};
diff --git a/indra/newview/llviewercontrollistener.cpp b/indra/newview/llviewercontrollistener.cpp
index 6f77e21fcc..16c4084a77 100644
--- a/indra/newview/llviewercontrollistener.cpp
+++ b/indra/newview/llviewercontrollistener.cpp
@@ -3,25 +3,25 @@
* @author Brad Kittenbrink
* @date 2009-07-09
* @brief Implementation for llviewercontrollistener.
- *
+ *
* $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$
*/
@@ -44,179 +44,182 @@ LLViewerControlListener sSavedSettingsListener;
} // unnamed namespace
LLViewerControlListener::LLViewerControlListener()
- : LLEventAPI("LLViewerControl",
- "LLViewerControl listener: set, toggle or set default for various controls")
+ : LLEventAPI("LLViewerControl",
+ "LLViewerControl listener: set, toggle or set default for various controls")
{
- std::ostringstream groupnames;
- groupnames << "[\"group\"] is one of ";
- const char* delim = "";
- for (const auto& key : LLControlGroup::key_snapshot())
- {
- groupnames << delim << '"' << key << '"';
- delim = ", ";
- }
- groupnames << '\n';
- std::string grouphelp(groupnames.str());
- std::string replyhelp("If [\"reply\"] requested, send new [\"value\"] on specified LLEventPump\n");
-
- add("set",
- std::string("Set [\"group\"] control [\"key\"] to optional value [\"value\"]\n"
- "If [\"value\"] omitted, set to control's defined default value\n") +
- grouphelp + replyhelp,
- &LLViewerControlListener::set,
- LLSDMap("group", LLSD())("key", LLSD()));
- add("toggle",
- std::string("Toggle [\"group\"] control [\"key\"], if boolean\n") + grouphelp + replyhelp,
- &LLViewerControlListener::toggle,
- LLSDMap("group", LLSD())("key", LLSD()));
- add("get",
- std::string("Query [\"group\"] control [\"key\"], replying on LLEventPump [\"reply\"]\n") +
- grouphelp,
- &LLViewerControlListener::get,
- LLSDMap("group", LLSD())("key", LLSD())("reply", LLSD()));
- add("groups",
- "Send on LLEventPump [\"reply\"] an array [\"groups\"] of valid group names",
- &LLViewerControlListener::groups,
- LLSDMap("reply", LLSD()));
- add("vars",
- std::string("For [\"group\"], send on LLEventPump [\"reply\"] an array [\"vars\"],\n"
- "each of whose entries looks like:\n"
- " [\"name\"], [\"type\"], [\"value\"], [\"comment\"]\n") + grouphelp,
- &LLViewerControlListener::vars,
- LLSDMap("group", LLSD())("reply", LLSD()));
+ std::ostringstream groupnames;
+ groupnames << "[\"group\"] is one of ";
+ const char* delim = "";
+ for (const auto& key : LLControlGroup::key_snapshot())
+ {
+ groupnames << delim << '"' << key << '"';
+ delim = ", ";
+ }
+ groupnames << '\n';
+ std::string grouphelp(groupnames.str());
+ std::string replyhelp("If [\"reply\"] requested, send new [\"value\"] on specified LLEventPump\n");
+
+ add("set",
+ std::string("Set [\"group\"] control [\"key\"] to optional value [\"value\"]\n"
+ "If [\"value\"] omitted, set to control's defined default value\n") +
+ grouphelp + replyhelp,
+ &LLViewerControlListener::set,
+ LLSDMap("group", LLSD())("key", LLSD()));
+ add("toggle",
+ std::string("Toggle [\"group\"] control [\"key\"], if boolean\n") + grouphelp + replyhelp,
+ &LLViewerControlListener::toggle,
+ LLSDMap("group", LLSD())("key", LLSD()));
+ add("get",
+ std::string("Query [\"group\"] control [\"key\"], replying on LLEventPump [\"reply\"]\n") +
+ grouphelp,
+ &LLViewerControlListener::get,
+ LLSDMap("group", LLSD())("key", LLSD())("reply", LLSD()));
+ add("groups",
+ "Send on LLEventPump [\"reply\"] an array [\"groups\"] of valid group names",
+ &LLViewerControlListener::groups,
+ LLSDMap("reply", LLSD()));
+ add("vars",
+ std::string("For [\"group\"], send on LLEventPump [\"reply\"] an array [\"vars\"],\n"
+ "each of whose entries looks like:\n"
+ " [\"name\"], [\"type\"], [\"value\"], [\"comment\"]\n") + grouphelp,
+ &LLViewerControlListener::vars,
+ LLSDMap("group", LLSD())("reply", LLSD()));
}
struct Info
{
- Info(const LLSD& request):
- response(LLSD(), request),
- groupname(request["group"]),
- group(LLControlGroup::getInstance(groupname)),
- key(request["key"]),
- control(NULL)
- {
- if (! group)
- {
- response.error(STRINGIZE("Unrecognized group '" << groupname << "'"));
- return;
- }
-
- control = group->getControl(key);
- if (! control)
- {
- response.error(STRINGIZE("In group '" << groupname
- << "', unrecognized control key '" << key << "'"));
- }
- }
-
- ~Info()
- {
- // If in fact the request passed to our constructor names a valid
- // group and key, grab the final value of the indicated control and
- // stuff it in our response. Since this outer destructor runs before
- // the contained Response destructor, this data will go into the
- // response we send.
- if (control)
- {
- response["name"] = control->getName();
- response["type"] = LLControlGroup::typeEnumToString(control->type());
- response["value"] = control->get();
- response["comment"] = control->getComment();
- }
- }
-
- LLEventAPI::Response response;
- std::string groupname;
- LLControlGroup::ptr_t group;
- std::string key;
- LLControlVariable* control;
+ Info(const LLSD& request):
+ response(LLSD(), request),
+ groupname(request["group"]),
+ group(LLControlGroup::getInstance(groupname)),
+ key(request["key"]),
+ control(NULL)
+ {
+ if (! group)
+ {
+ response.error(STRINGIZE("Unrecognized group '" << groupname << "'"));
+ return;
+ }
+
+ control = group->getControl(key);
+ if (! control)
+ {
+ response.error(STRINGIZE("In group '" << groupname
+ << "', unrecognized control key '" << key << "'"));
+ }
+ }
+
+ ~Info()
+ {
+ // If in fact the request passed to our constructor names a valid
+ // group and key, grab the final value of the indicated control and
+ // stuff it in our response. Since this outer destructor runs before
+ // the contained Response destructor, this data will go into the
+ // response we send.
+ if (control)
+ {
+ response["name"] = control->getName();
+ response["type"] = LLControlGroup::typeEnumToString(control->type());
+ response["value"] = control->get();
+ response["comment"] = control->getComment();
+ }
+ }
+
+ LLEventAPI::Response response;
+ std::string groupname;
+ LLControlGroup::ptr_t group;
+ std::string key;
+ LLControlVariable* control;
};
//static
void LLViewerControlListener::set(LLSD const & request)
{
- Info info(request);
- if (! info.control)
- return;
-
- if (request.has("value"))
- {
- info.control->setValue(request["value"]);
- }
- else
- {
- info.control->resetToDefault();
- }
+ Info info(request);
+ if (! info.control)
+ return;
+
+ if (request.has("value"))
+ {
+ LL_WARNS("LLViewerControlListener") << "Changing debug setting " << std::quoted(info.key) << " to " << request["value"] << LL_ENDL;
+ info.control->setValue(request["value"], false);
+ }
+ else
+ {
+ info.control->resetToDefault();
+ }
}
//static
void LLViewerControlListener::toggle(LLSD const & request)
{
- Info info(request);
- if (! info.control)
- return;
-
- if (info.control->isType(TYPE_BOOLEAN))
- {
- info.control->set(! info.control->get().asBoolean());
- }
- else
- {
- info.response.error(STRINGIZE("toggle of non-boolean '" << info.groupname
- << "' control '" << info.key
- << "', type is "
- << LLControlGroup::typeEnumToString(info.control->type())));
- }
+ Info info(request);
+ if (! info.control)
+ return;
+
+ if (info.control->isType(TYPE_BOOLEAN))
+ {
+ bool value = !info.control->get().asBoolean();
+ LL_WARNS("LLViewerControlListener") << "Toggling debug setting " << std::quoted(info.key) << " to " << value << LL_ENDL;
+ info.control->set(value, false);
+ }
+ else
+ {
+ info.response.error(STRINGIZE("toggle of non-boolean '" << info.groupname
+ << "' control '" << info.key
+ << "', type is "
+ << LLControlGroup::typeEnumToString(info.control->type())));
+ }
}
void LLViewerControlListener::get(LLSD const & request)
{
- // The Info constructor and destructor actually do all the work here.
- Info info(request);
+ // The Info constructor and destructor actually do all the work here.
+ Info info(request);
}
void LLViewerControlListener::groups(LLSD const & request)
{
- // No Info, we're not looking up either a group or a control name.
- Response response(LLSD(), request);
- for (const auto& key : LLControlGroup::key_snapshot())
- {
- response["groups"].append(key);
- }
+ // No Info, we're not looking up either a group or a control name.
+ Response response(LLSD(), request);
+ for (const auto& key : LLControlGroup::key_snapshot())
+ {
+ response["groups"].append(key);
+ }
}
struct CollectVars: public LLControlGroup::ApplyFunctor
{
- CollectVars(LLControlGroup::ptr_t g):
- mGroup(g)
- {}
-
- virtual void apply(const std::string& name, LLControlVariable* control)
- {
- vars.append(LLSDMap
- ("name", name)
- ("type", LLControlGroup::typeEnumToString(control->type()))
- ("value", control->get())
- ("comment", control->getComment()));
- }
-
- LLControlGroup::ptr_t mGroup;
- LLSD vars;
+ CollectVars(LLControlGroup::ptr_t g):
+ mGroup(g)
+ {}
+
+ virtual void apply(const std::string& name, LLControlVariable* control)
+ {
+ vars.append(LLSDMap
+ ("name", name)
+ ("type", LLControlGroup::typeEnumToString(control->type()))
+ ("value", control->get())
+ ("comment", control->getComment()));
+ }
+
+ LLControlGroup::ptr_t mGroup;
+ LLSD vars;
};
void LLViewerControlListener::vars(LLSD const & request)
{
- // This method doesn't use Info, because we're not looking up a specific
- // control name.
- Response response(LLSD(), request);
- std::string groupname(request["group"]);
- auto group(LLControlGroup::getInstance(groupname));
- if (! group)
- {
- return response.error(STRINGIZE("Unrecognized group '" << groupname << "'"));
- }
-
- CollectVars collector(group);
- group->applyToAll(&collector);
- response["vars"] = collector.vars;
+ // This method doesn't use Info, because we're not looking up a specific
+ // control name.
+ Response response(LLSD(), request);
+ std::string groupname(request["group"]);
+ auto group(LLControlGroup::getInstance(groupname));
+ if (! group)
+ {
+ return response.error(STRINGIZE("Unrecognized group '" << groupname << "'"));
+ }
+
+ CollectVars collector(group);
+ group->applyToAll(&collector);
+ response["vars"] = collector.vars;
}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index ceda2675d5..60add691c5 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llviewerfloaterreg.cpp
* @brief LLViewerFloaterReg class registers floaters used in the viewer
*
* $LicenseInfo:firstyear=2007&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$
*/
@@ -94,6 +94,8 @@
#include "llfloaterlandholdings.h"
#include "llfloaterlinkreplace.h"
#include "llfloaterloadprefpreset.h"
+#include "llfloaterluadebug.h"
+#include "llfloaterluascripts.h"
#include "llfloatermap.h"
#include "llfloatermarketplacelistings.h"
#include "llfloatermediasettings.h"
@@ -180,8 +182,8 @@ const std::string FLOATER_PROFILE("profile");
class LLFloaterOpenHandler : public LLCommandHandler
{
public:
- // requires trusted browser to trigger or an explicit click
- LLFloaterOpenHandler() : LLCommandHandler("openfloater", UNTRUSTED_THROTTLE) { }
+ // requires trusted browser to trigger or an explicit click
+ LLFloaterOpenHandler() : LLCommandHandler("openfloater", UNTRUSTED_THROTTLE) { }
bool canHandleUntrusted(
const LLSD& params,
@@ -193,7 +195,7 @@ public:
{
return true; // will fail silently
}
-
+
std::string fl_name = params[0].asString();
// External browsers explicitly ask user about opening links
@@ -280,234 +282,237 @@ public:
return true;
}
- bool handle(
+ bool handle(
const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web) override
- {
- if (params.size() != 1)
- {
- return false;
- }
+ {
+ if (params.size() != 1)
+ {
+ return false;
+ }
- const std::string floater_name = LLURI::unescape(params[0].asString());
+ const std::string floater_name = LLURI::unescape(params[0].asString());
LLSD key;
if (floater_name == FLOATER_PROFILE)
{
key["id"] = gAgentID;
}
- LLFloaterReg::showInstance(floater_name, key);
+ LLFloaterReg::showInstance(floater_name, key);
- return true;
- }
+ return true;
+ }
};
LLFloaterOpenHandler gFloaterOpenHandler;
void LLViewerFloaterReg::registerFloaters()
{
- if (gNonInteractive)
- {
- return;
- }
- // *NOTE: Please keep these alphabetized for easier merges
-
- LLFloaterAboutUtil::registerFloater();
- LLFloaterReg::add("360capture", "floater_360capture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater360Capture>);
- LLFloaterReg::add("block_timers", "floater_fast_timers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFastTimerView>);
- LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>);
- LLFloaterReg::add("add_payment_method", "floater_add_payment_method.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAddPaymentMethod>);
- LLFloaterReg::add("appearance", "floater_my_appearance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
- LLFloaterReg::add("associate_listing", "floater_associate_listing.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAssociateListing>);
- LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>);
- LLFloaterReg::add("avatar", "floater_avatar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatar>);
- LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarPicker>);
- LLFloaterReg::add("avatar_render_settings", "floater_avatar_render_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarRenderSettings>);
- LLFloaterReg::add("avatar_textures", "floater_avatar_textures.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarTextures>);
-
- LLFloaterReg::add("ban_duration", "floater_ban_duration.xml", &LLFloaterReg::build<LLFloaterBanDuration>);
- LLFloaterReg::add("beacons", "floater_beacons.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBeacons>);
- LLFloaterReg::add("bulk_perms", "floater_bulk_perms.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBulkPermission>);
- LLFloaterReg::add("buy_currency", "floater_buy_currency.xml", &LLFloaterBuyCurrency::buildFloater);
- LLFloaterReg::add("buy_currency_html", "floater_buy_currency_html.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuyCurrencyHTML>);
- LLFloaterReg::add("buy_land", "floater_buy_land.xml", &LLFloaterBuyLand::buildFloater);
- LLFloaterReg::add("buy_object", "floater_buy_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuy>);
- LLFloaterReg::add("buy_object_contents", "floater_buy_contents.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuyContents>);
- LLFloaterReg::add("build", "floater_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTools>);
- LLFloaterReg::add("build_options", "floater_build_options.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuildOptions>);
- LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>);
-
- LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>);
- LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCameraPresets>);
- LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>);
+ if (gNonInteractive)
+ {
+ return;
+ }
+ // *NOTE: Please keep these alphabetized for easier merges
+
+ LLFloaterAboutUtil::registerFloater();
+ LLFloaterReg::add("360capture", "floater_360capture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater360Capture>);
+ LLFloaterReg::add("block_timers", "floater_fast_timers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFastTimerView>);
+ LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>);
+ LLFloaterReg::add("add_payment_method", "floater_add_payment_method.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAddPaymentMethod>);
+ LLFloaterReg::add("appearance", "floater_my_appearance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
+ LLFloaterReg::add("associate_listing", "floater_associate_listing.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAssociateListing>);
+ LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>);
+ LLFloaterReg::add("avatar", "floater_avatar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatar>);
+ LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarPicker>);
+ LLFloaterReg::add("avatar_render_settings", "floater_avatar_render_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarRenderSettings>);
+ LLFloaterReg::add("avatar_textures", "floater_avatar_textures.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarTextures>);
+
+ LLFloaterReg::add("ban_duration", "floater_ban_duration.xml", &LLFloaterReg::build<LLFloaterBanDuration>);
+ LLFloaterReg::add("beacons", "floater_beacons.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBeacons>);
+ LLFloaterReg::add("bulk_perms", "floater_bulk_perms.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBulkPermission>);
+ LLFloaterReg::add("buy_currency", "floater_buy_currency.xml", &LLFloaterBuyCurrency::buildFloater);
+ LLFloaterReg::add("buy_currency_html", "floater_buy_currency_html.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuyCurrencyHTML>);
+ LLFloaterReg::add("buy_land", "floater_buy_land.xml", &LLFloaterBuyLand::buildFloater);
+ LLFloaterReg::add("buy_object", "floater_buy_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuy>);
+ LLFloaterReg::add("buy_object_contents", "floater_buy_contents.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuyContents>);
+ LLFloaterReg::add("build", "floater_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTools>);
+ LLFloaterReg::add("build_options", "floater_build_options.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuildOptions>);
+ LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>);
+
+ LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>);
+ LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCameraPresets>);
+ LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>);
LLFloaterReg::add("change_item_thumbnail", "floater_change_item_thumbnail.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChangeItemThumbnail>);
- LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater);
- LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterClassified>);
- LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);
- LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>);
- LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCreateLandmark>);
-
- LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeletePrefPreset>);
- LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>);
-
- LLFloaterReg::add("emoji_picker", "floater_emoji_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiPicker>);
- LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiComplete>);
- LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>);
-
- LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>);
- LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentSky>);
-
- LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvironmentAdjust>);
-
- LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditExtDayCycle>);
- LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyEnvironment>);
-
- LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
- LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);
- LLFloaterReg::add("experience_profile", "floater_experienceprofile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperienceProfile>);
- LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiencePicker>);
-
- LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>);
- LLFloaterReg::add("forget_username", "floater_forget_user.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterForgetUser>);
-
- LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGesture>);
- LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>);
- LLFloaterReg::add("grid_status", "floater_grid_status.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGridStatus>);
- LLFloaterReg::add("group_picker", "floater_choose_group.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGroupPicker>);
-
- LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);
- LLFloaterReg::add("edit_hover_height", "floater_edit_hover_height.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHoverHeight>);
- LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);
-
- LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMSession>);
- LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMContainer>);
- LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>);
- LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
- LLFloaterReg::add("inventory", "floater_my_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
- LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>);
+ LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater);
+ LLFloaterReg::add("classified", "floater_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterClassified>);
+ LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);
+ LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>);
+ LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCreateLandmark>);
+
+ LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeletePrefPreset>);
+ LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>);
+
+ LLFloaterReg::add("emoji_picker", "floater_emoji_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiPicker>);
+ LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiComplete>);
+ LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>);
+
+ LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>);
+ LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentSky>);
+
+ LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvironmentAdjust>);
+
+ LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditExtDayCycle>);
+ LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyEnvironment>);
+
+ LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
+ LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);
+ LLFloaterReg::add("experience_profile", "floater_experienceprofile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperienceProfile>);
+ LLFloaterReg::add("experience_search", "floater_experience_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiencePicker>);
+
+ LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>);
+ LLFloaterReg::add("forget_username", "floater_forget_user.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterForgetUser>);
+
+ LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGesture>);
+ LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>);
+ LLFloaterReg::add("grid_status", "floater_grid_status.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGridStatus>);
+ LLFloaterReg::add("group_picker", "floater_choose_group.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGroupPicker>);
+
+ LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);
+ LLFloaterReg::add("edit_hover_height", "floater_edit_hover_height.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHoverHeight>);
+ LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);
+
+ LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMSession>);
+ LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMContainer>);
+ LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>);
+ LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
+ LLFloaterReg::add("inventory", "floater_my_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
+ LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>);
LLFloaterReg::add("inventory_thumbnails_helper", "floater_inventory_thumbnails_helper.xml", (LLFloaterBuildFunc) &LLFloaterReg::build<LLFloaterInventoryThumbnailsHelper>);
- LLFloaterReg::add("item_properties", "floater_item_properties.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterItemProperties>);
+ LLFloaterReg::add("item_properties", "floater_item_properties.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterItemProperties>);
LLFloaterReg::add("task_properties", "floater_task_properties.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterItemProperties>);
LLFloaterReg::add("inventory_settings", "floater_inventory_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInventorySettings>);
- LLInspectAvatarUtil::registerFloater();
- LLInspectGroupUtil::registerFloater();
- LLInspectObjectUtil::registerFloater();
- LLInspectRemoteObjectUtil::registerFloater();
- LLFloaterVoiceVolumeUtil::registerFloater();
- LLNotificationsUI::registerFloater();
- LLFloaterDisplayNameUtil::registerFloater();
-
- LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>);
- LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>);
- LLFloaterReg::add("linkreplace", "floater_linkreplace.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLinkReplace>);
- LLFloaterReg::add("load_pref_preset", "floater_load_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLoadPrefPreset>);
-
- LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>);
-
- LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>);
- LLFloaterReg::add("marketplace_listings", "floater_marketplace_listings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceListings>);
- LLFloaterReg::add("marketplace_validation", "floater_marketplace_validation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceValidation>);
- LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
- LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
- LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>);
- LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);
- LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
+ LLInspectAvatarUtil::registerFloater();
+ LLInspectGroupUtil::registerFloater();
+ LLInspectObjectUtil::registerFloater();
+ LLInspectRemoteObjectUtil::registerFloater();
+ LLFloaterVoiceVolumeUtil::registerFloater();
+ LLNotificationsUI::registerFloater();
+ LLFloaterDisplayNameUtil::registerFloater();
+
+ LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>);
+ LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>);
+ LLFloaterReg::add("linkreplace", "floater_linkreplace.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLinkReplace>);
+ LLFloaterReg::add("load_pref_preset", "floater_load_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLoadPrefPreset>);
+
+ LLFloaterReg::add("lua_debug", "floater_lua_debug.xml", (LLFloaterBuildFunc) &LLFloaterReg::build<LLFloaterLUADebug>);
+ LLFloaterReg::add("lua_scripts", "floater_lua_scripts.xml", (LLFloaterBuildFunc) &LLFloaterReg::build<LLFloaterLUAScripts>);
+
+ LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>);
+
+ LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>);
+ LLFloaterReg::add("marketplace_listings", "floater_marketplace_listings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceListings>);
+ LLFloaterReg::add("marketplace_validation", "floater_marketplace_validation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceValidation>);
+ LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
+ LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
+ LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>);
+ LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);
+ LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
LLFloaterReg::add("new_feature_notification", "floater_new_feature_notification.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNewFeatureNotification>);
- LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
-
- LLFloaterReg::add("notification_well_window", "floater_notifications_tabbed.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationsTabbed>);
-
- LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>);
- LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
- LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>);
- LLFloaterPayUtil::registerFloater();
-
- LLFloaterReg::add("pathfinding_characters", "floater_pathfinding_characters.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingCharacters>);
- LLFloaterReg::add("pathfinding_linksets", "floater_pathfinding_linksets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingLinksets>);
- LLFloaterReg::add("pathfinding_console", "floater_pathfinding_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingConsole>);
- LLFloaterReg::add("people", "floater_people.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
- LLFloaterReg::add("performance", "floater_performance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerformance>);
- LLFloaterReg::add("perms_default", "floater_perms_default.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPermsDefault>);
- LLFloaterReg::add("places", "floater_places.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
- LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
- LLFloaterReg::add("prefs_graphics_advanced", "floater_preferences_graphics_advanced.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceGraphicsAdvanced>);
- LLFloaterReg::add("prefs_view_advanced", "floater_preferences_view_advanced.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceViewAdvanced>);
- LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>);
- LLFloaterReg::add("prefs_spellchecker_import", "floater_spellcheck_import.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerImport>);
- LLFloaterReg::add("prefs_translation", "floater_translation_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTranslationSettings>);
- LLFloaterReg::add("prefs_spellchecker", "floater_spellcheck.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerSettings>);
- LLFloaterReg::add("prefs_autoreplace", "floater_autoreplace.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAutoReplaceSettings>);
- LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>);
- LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewAnim>, "preview");
- LLFloaterReg::add("preview_conversation", "floater_conversation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationPreview>);
- LLFloaterReg::add("preview_gesture", "floater_preview_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewGesture>, "preview");
- LLFloaterReg::add("preview_notecard", "floater_preview_notecard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewNotecard>, "preview");
- LLFloaterReg::add("preview_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewLSL>, "preview");
- LLFloaterReg::add("preview_scriptedit", "floater_live_lsleditor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLLiveLSLEditor>, "preview");
- LLFloaterReg::add("preview_sound", "floater_preview_sound.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewSound>, "preview");
- LLFloaterReg::add("preview_texture", "floater_preview_texture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewTexture>, "preview");
- LLFloaterReg::add("preview_trash", "floater_preview_trash.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreviewTrash>);
- LLFloaterReg::add("publish_classified", "floater_publish_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPublishClassifiedFloater>);
- LLFloaterReg::add("save_pref_preset", "floater_save_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSavePrefPreset>);
- LLFloaterReg::add("save_camera_preset", "floater_save_camera_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSaveCameraPreset>);
- LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptEdPrefs>);
+ LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
+
+ LLFloaterReg::add("notification_well_window", "floater_notifications_tabbed.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationsTabbed>);
+
+ LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>);
+ LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
+ LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>);
+ LLFloaterPayUtil::registerFloater();
+
+ LLFloaterReg::add("pathfinding_characters", "floater_pathfinding_characters.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingCharacters>);
+ LLFloaterReg::add("pathfinding_linksets", "floater_pathfinding_linksets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingLinksets>);
+ LLFloaterReg::add("pathfinding_console", "floater_pathfinding_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingConsole>);
+ LLFloaterReg::add("people", "floater_people.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
+ LLFloaterReg::add("performance", "floater_performance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerformance>);
+ LLFloaterReg::add("perms_default", "floater_perms_default.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPermsDefault>);
+ LLFloaterReg::add("places", "floater_places.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);
+ LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
+ LLFloaterReg::add("prefs_graphics_advanced", "floater_preferences_graphics_advanced.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceGraphicsAdvanced>);
+ LLFloaterReg::add("prefs_view_advanced", "floater_preferences_view_advanced.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceViewAdvanced>);
+ LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>);
+ LLFloaterReg::add("prefs_spellchecker_import", "floater_spellcheck_import.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerImport>);
+ LLFloaterReg::add("prefs_translation", "floater_translation_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTranslationSettings>);
+ LLFloaterReg::add("prefs_spellchecker", "floater_spellcheck.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerSettings>);
+ LLFloaterReg::add("prefs_autoreplace", "floater_autoreplace.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAutoReplaceSettings>);
+ LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>);
+ LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewAnim>, "preview");
+ LLFloaterReg::add("preview_conversation", "floater_conversation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationPreview>);
+ LLFloaterReg::add("preview_gesture", "floater_preview_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewGesture>, "preview");
+ LLFloaterReg::add("preview_notecard", "floater_preview_notecard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewNotecard>, "preview");
+ LLFloaterReg::add("preview_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewLSL>, "preview");
+ LLFloaterReg::add("preview_scriptedit", "floater_live_lsleditor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLLiveLSLEditor>, "preview");
+ LLFloaterReg::add("preview_sound", "floater_preview_sound.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewSound>, "preview");
+ LLFloaterReg::add("preview_texture", "floater_preview_texture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewTexture>, "preview");
+ LLFloaterReg::add("preview_trash", "floater_preview_trash.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreviewTrash>);
+ LLFloaterReg::add("publish_classified", "floater_publish_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPublishClassifiedFloater>);
+ LLFloaterReg::add("save_pref_preset", "floater_save_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSavePrefPreset>);
+ LLFloaterReg::add("save_camera_preset", "floater_save_camera_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSaveCameraPreset>);
+ LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptEdPrefs>);
LLFloaterReg::add("material_editor", "floater_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>);
LLFloaterReg::add("live_material_editor", "floater_live_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>);
-
- LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>);
- LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build<LLFloaterTestInspectors>);
- //LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build<LLFloaterTestListView>);
- LLFloaterReg::add("test_textbox", "floater_test_textbox.xml", &LLFloaterReg::build<LLFloater>);
- LLFloaterReg::add("test_text_editor", "floater_test_text_editor.xml", &LLFloaterReg::build<LLFloater>);
- LLFloaterReg::add("test_widgets", "floater_test_widgets.xml", &LLFloaterReg::build<LLFloater>);
- LLFloaterReg::add("top_objects", "floater_top_objects.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTopObjects>);
- LLFloaterReg::add("toybox", "floater_toybox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterToybox>);
-
- LLFloaterReg::add("reporter", "floater_report_abuse.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterReporter>);
- LLFloaterReg::add("reset_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterResetQueue>);
- LLFloaterReg::add("region_debug_console", "floater_region_debug_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionDebugConsole>);
- LLFloaterReg::add("region_info", "floater_region_info.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionInfo>);
- LLFloaterReg::add("region_restarting", "floater_region_restarting.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionRestarting>);
-
- LLFloaterReg::add("script_debug", "floater_script_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebug>);
- LLFloaterReg::add("script_debug_output", "floater_script_debug_panel.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebugOutput>);
- LLFloaterReg::add("script_floater", "floater_script.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLScriptFloater>);
- LLFloaterReg::add("script_limits", "floater_script_limits.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptLimits>);
- LLFloaterReg::add("my_scripts", "floater_my_scripts.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyScripts>);
- LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
- LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
- LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);
- LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
- LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);
- LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>);
- LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
- LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);
+
+ LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>);
+ LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build<LLFloaterTestInspectors>);
+ //LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build<LLFloaterTestListView>);
+ LLFloaterReg::add("test_textbox", "floater_test_textbox.xml", &LLFloaterReg::build<LLFloater>);
+ LLFloaterReg::add("test_text_editor", "floater_test_text_editor.xml", &LLFloaterReg::build<LLFloater>);
+ LLFloaterReg::add("test_widgets", "floater_test_widgets.xml", &LLFloaterReg::build<LLFloater>);
+ LLFloaterReg::add("top_objects", "floater_top_objects.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTopObjects>);
+ LLFloaterReg::add("toybox", "floater_toybox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterToybox>);
+
+ LLFloaterReg::add("reporter", "floater_report_abuse.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterReporter>);
+ LLFloaterReg::add("reset_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterResetQueue>);
+ LLFloaterReg::add("region_debug_console", "floater_region_debug_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionDebugConsole>);
+ LLFloaterReg::add("region_info", "floater_region_info.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionInfo>);
+ LLFloaterReg::add("region_restarting", "floater_region_restarting.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionRestarting>);
+
+ LLFloaterReg::add("script_debug", "floater_script_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebug>);
+ LLFloaterReg::add("script_debug_output", "floater_script_debug_panel.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebugOutput>);
+ LLFloaterReg::add("script_floater", "floater_script.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLScriptFloater>);
+ LLFloaterReg::add("script_limits", "floater_script_limits.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptLimits>);
+ LLFloaterReg::add("my_scripts", "floater_my_scripts.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyScripts>);
+ LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
+ LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
+ LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);
+ LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
+ LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);
+ LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>);
+ LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
+ LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);
LLFloaterReg::add("simple_snapshot", "floater_simple_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSimpleSnapshot>);
LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>);
- LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
-
- LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>);
-
- LLFloaterUIPreviewUtil::registerFloater();
- LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload");
- LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");
- LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload");
- LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload");
- LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload");
- LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload");
-
- LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>);
-
- LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
- LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>);
- LLFloaterReg::add("window_size", "floater_window_size.xml", &LLFloaterReg::build<LLFloaterWindowSize>);
- LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWorldMap>);
-
- // *NOTE: Please keep these alphabetized for easier merges
-
- LLFloaterReg::registerControlVariables(); // Make sure visibility and rect controls get preserved when saving
+ LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
+
+ LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>);
+
+ LLFloaterUIPreviewUtil::registerFloater();
+ LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload");
+ LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");
+ LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload");
+ LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload");
+ LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload");
+ LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload");
+
+ LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>);
+
+ LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
+ LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>);
+ LLFloaterReg::add("window_size", "floater_window_size.xml", &LLFloaterReg::build<LLFloaterWindowSize>);
+ LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWorldMap>);
+
+ // *NOTE: Please keep these alphabetized for easier merges
+
+ LLFloaterReg::registerControlVariables(); // Make sure visibility and rect controls get preserved when saving
}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 37f23f9cca..52128a09ab 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llviewermenu.cpp
* @brief Builds menus out of items.
*
* $LicenseInfo:firstyear=2002&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$
*/
@@ -30,7 +30,7 @@
#include "vld.h"
#endif
-#include "llviewermenu.h"
+#include "llviewermenu.h"
// linden library includes
#include "llavatarnamecache.h" // IDEVO (I Are Not Men!)
@@ -115,7 +115,7 @@
#include "llviewerdisplay.h" //for gWindowResized
#include "llviewergenericmessage.h"
#include "llviewerhelp.h"
-#include "llviewermenufile.h" // init_menu_file()
+#include "llviewermenufile.h" // init_menu_file()
#include "llviewermessage.h"
#include "llviewernetwork.h"
#include "llviewerobjectlist.h"
@@ -159,7 +159,7 @@ void handle_test_load_url(void*);
//
// Evil hackish imported globals
-//extern BOOL gHideSelectedObjects;
+//extern BOOL gHideSelectedObjects;
//extern BOOL gAllowSelectAvatar;
//extern BOOL gDebugAvatarRotation;
extern BOOL gDebugClicks;
@@ -173,20 +173,22 @@ extern BOOL gShaderProfileFrame;
// Globals
//
-LLMenuBarGL *gMenuBarView = NULL;
-LLViewerMenuHolderGL *gMenuHolder = NULL;
-LLMenuGL *gPopupMenuView = NULL;
-LLMenuGL *gEditMenu = NULL;
-LLMenuBarGL *gLoginMenuBarView = NULL;
+LLUIListener sUIListener;
+
+LLMenuBarGL *gMenuBarView = NULL;
+LLViewerMenuHolderGL *gMenuHolder = NULL;
+LLMenuGL *gPopupMenuView = NULL;
+LLMenuGL *gEditMenu = NULL;
+LLMenuBarGL *gLoginMenuBarView = NULL;
// Pie menus
-LLContextMenu *gMenuAvatarSelf = NULL;
-LLContextMenu *gMenuAvatarOther = NULL;
-LLContextMenu *gMenuObject = NULL;
-LLContextMenu *gMenuAttachmentSelf = NULL;
-LLContextMenu *gMenuAttachmentOther = NULL;
-LLContextMenu *gMenuLand = NULL;
-LLContextMenu *gMenuMuteParticle = NULL;
+LLContextMenu *gMenuAvatarSelf = NULL;
+LLContextMenu *gMenuAvatarOther = NULL;
+LLContextMenu *gMenuObject = NULL;
+LLContextMenu *gMenuAttachmentSelf = NULL;
+LLContextMenu *gMenuAttachmentOther = NULL;
+LLContextMenu *gMenuLand = NULL;
+LLContextMenu *gMenuMuteParticle = NULL;
const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents");
@@ -284,7 +286,7 @@ void handle_force_parcel_owner_to_me(void*);
void handle_force_parcel_to_content(void*);
void handle_claim_public_land(void*);
-void handle_god_request_avatar_geometry(void *); // Hack for easy testing of new avatar geometry
+void handle_god_request_avatar_geometry(void *); // Hack for easy testing of new avatar geometry
void reload_vertex_shader(void *);
void handle_disconnect_viewer(void *);
@@ -344,28 +346,26 @@ void menu_toggle_attached_particles(void* user_data);
class LLMenuParcelObserver : public LLParcelObserver
{
public:
- LLMenuParcelObserver();
- ~LLMenuParcelObserver();
- virtual void changed();
+ LLMenuParcelObserver();
+ ~LLMenuParcelObserver();
+ virtual void changed();
};
static LLMenuParcelObserver* gMenuParcelObserver = NULL;
-static LLUIListener sUIListener;
-
LLMenuParcelObserver::LLMenuParcelObserver()
{
- LLViewerParcelMgr::getInstance()->addObserver(this);
+ LLViewerParcelMgr::getInstance()->addObserver(this);
}
LLMenuParcelObserver::~LLMenuParcelObserver()
{
- LLViewerParcelMgr::getInstance()->removeObserver(this);
+ LLViewerParcelMgr::getInstance()->removeObserver(this);
}
void LLMenuParcelObserver::changed()
{
- LLParcel *parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
+ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
if (gMenuLand && parcel)
{
LLView* child = gMenuLand->findChild<LLView>("Land Buy Pass");
@@ -438,131 +438,131 @@ void check_merchant_status(bool force)
void init_menus()
{
- // Initialize actions
- initialize_menus();
-
- ///
- /// Popup menu
- ///
- /// The popup menu is now populated by the show_context_menu()
- /// method.
-
- LLMenuGL::Params menu_params;
- menu_params.name = "Popup";
- menu_params.visible = false;
- gPopupMenuView = LLUICtrlFactory::create<LLMenuGL>(menu_params);
- gMenuHolder->addChild( gPopupMenuView );
-
- ///
- /// Context menus
- ///
-
- const widget_registry_t& registry =
- LLViewerMenuHolderGL::child_registry_t::instance();
- gEditMenu = LLUICtrlFactory::createFromFile<LLMenuGL>("menu_edit.xml", gMenuHolder, registry);
- gMenuAvatarSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
- "menu_avatar_self.xml", gMenuHolder, registry);
- gMenuAvatarOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
- "menu_avatar_other.xml", gMenuHolder, registry);
-
- gDetachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach HUD", true);
- gDetachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach", true);
-
- gMenuObject = LLUICtrlFactory::createFromFile<LLContextMenu>(
- "menu_object.xml", gMenuHolder, registry);
-
- gAttachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach HUD");
- gAttachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach");
-
- gMenuAttachmentSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
- "menu_attachment_self.xml", gMenuHolder, registry);
- gMenuAttachmentOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
- "menu_attachment_other.xml", gMenuHolder, registry);
-
- gDetachHUDAttSelfMenu = gMenuHolder->getChild<LLContextMenu>("Detach Self HUD", true);
- gDetachAttSelfMenu = gMenuHolder->getChild<LLContextMenu>("Detach Self", true);
-
- gMenuLand = LLUICtrlFactory::createFromFile<LLContextMenu>(
- "menu_land.xml", gMenuHolder, registry);
-
- gMenuMuteParticle = LLUICtrlFactory::createFromFile<LLContextMenu>(
- "menu_mute_particle.xml", gMenuHolder, registry);
-
- ///
- /// set up the colors
- ///
- LLColor4 color;
-
- LLColor4 context_menu_color = LLUIColorTable::instance().getColor("MenuPopupBgColor");
-
- gMenuAvatarSelf->setBackgroundColor( context_menu_color );
- gMenuAvatarOther->setBackgroundColor( context_menu_color );
- gMenuObject->setBackgroundColor( context_menu_color );
- gMenuAttachmentSelf->setBackgroundColor( context_menu_color );
- gMenuAttachmentOther->setBackgroundColor( context_menu_color );
-
- gMenuLand->setBackgroundColor( context_menu_color );
-
- color = LLUIColorTable::instance().getColor( "MenuPopupBgColor" );
- gPopupMenuView->setBackgroundColor( color );
-
- // If we are not in production, use a different color to make it apparent.
- if (LLGridManager::getInstance()->isInProductionGrid())
- {
- color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
- }
- else
- {
- color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
- }
-
- LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder");
-
- gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- gMenuBarView->setRect(LLRect(0, menu_bar_holder->getRect().mTop, 0, menu_bar_holder->getRect().mTop - MENU_BAR_HEIGHT));
- gMenuBarView->setBackgroundColor( color );
-
- menu_bar_holder->addChild(gMenuBarView);
-
- gViewerWindow->setMenuBackgroundColor(false,
+ // Initialize actions
+ initialize_menus();
+
+ ///
+ /// Popup menu
+ ///
+ /// The popup menu is now populated by the show_context_menu()
+ /// method.
+
+ LLMenuGL::Params menu_params;
+ menu_params.name = "Popup";
+ menu_params.visible = false;
+ gPopupMenuView = LLUICtrlFactory::create<LLMenuGL>(menu_params);
+ gMenuHolder->addChild( gPopupMenuView );
+
+ ///
+ /// Context menus
+ ///
+
+ const widget_registry_t& registry =
+ LLViewerMenuHolderGL::child_registry_t::instance();
+ gEditMenu = LLUICtrlFactory::createFromFile<LLMenuGL>("menu_edit.xml", gMenuHolder, registry);
+ gMenuAvatarSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_avatar_self.xml", gMenuHolder, registry);
+ gMenuAvatarOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_avatar_other.xml", gMenuHolder, registry);
+
+ gDetachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach HUD", true);
+ gDetachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach", true);
+
+ gMenuObject = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_object.xml", gMenuHolder, registry);
+
+ gAttachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach HUD");
+ gAttachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach");
+
+ gMenuAttachmentSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_attachment_self.xml", gMenuHolder, registry);
+ gMenuAttachmentOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_attachment_other.xml", gMenuHolder, registry);
+
+ gDetachHUDAttSelfMenu = gMenuHolder->getChild<LLContextMenu>("Detach Self HUD", true);
+ gDetachAttSelfMenu = gMenuHolder->getChild<LLContextMenu>("Detach Self", true);
+
+ gMenuLand = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_land.xml", gMenuHolder, registry);
+
+ gMenuMuteParticle = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_mute_particle.xml", gMenuHolder, registry);
+
+ ///
+ /// set up the colors
+ ///
+ LLColor4 color;
+
+ LLColor4 context_menu_color = LLUIColorTable::instance().getColor("MenuPopupBgColor");
+
+ gMenuAvatarSelf->setBackgroundColor( context_menu_color );
+ gMenuAvatarOther->setBackgroundColor( context_menu_color );
+ gMenuObject->setBackgroundColor( context_menu_color );
+ gMenuAttachmentSelf->setBackgroundColor( context_menu_color );
+ gMenuAttachmentOther->setBackgroundColor( context_menu_color );
+
+ gMenuLand->setBackgroundColor( context_menu_color );
+
+ color = LLUIColorTable::instance().getColor( "MenuPopupBgColor" );
+ gPopupMenuView->setBackgroundColor( color );
+
+ // If we are not in production, use a different color to make it apparent.
+ if (LLGridManager::getInstance()->isInProductionGrid())
+ {
+ color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
+ }
+ else
+ {
+ color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
+ }
+
+ LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder");
+
+ gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ gMenuBarView->setRect(LLRect(0, menu_bar_holder->getRect().mTop, 0, menu_bar_holder->getRect().mTop - MENU_BAR_HEIGHT));
+ gMenuBarView->setBackgroundColor( color );
+
+ menu_bar_holder->addChild(gMenuBarView);
+
+ gViewerWindow->setMenuBackgroundColor(false,
LLGridManager::getInstance()->isInProductionGrid());
- // *TODO:Also fix cost in llfolderview.cpp for Inventory menus
- const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost());
- const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost());
- const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost());
- gMenuHolder->childSetLabelArg("Upload Image", "[COST]", texture_upload_cost_str);
- gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str);
- gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str);
-
- gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE);
- gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE);
-
- gDetachAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach", true);
- gDetachHUDAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach HUD", true);
-
- // Don't display the Memory console menu if the feature is turned off
- LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", TRUE);
- if (memoryMenu)
- {
- memoryMenu->setVisible(FALSE);
- }
-
- gMenuBarView->createJumpKeys();
-
- // Let land based option enable when parcel changes
- gMenuParcelObserver = new LLMenuParcelObserver();
-
- gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- gLoginMenuBarView->arrangeAndClear();
- LLRect menuBarRect = gLoginMenuBarView->getRect();
- menuBarRect.setLeftTopAndSize(0, menu_bar_holder->getRect().getHeight(), menuBarRect.getWidth(), menuBarRect.getHeight());
- gLoginMenuBarView->setRect(menuBarRect);
- gLoginMenuBarView->setBackgroundColor( color );
- menu_bar_holder->addChild(gLoginMenuBarView);
-
- // tooltips are on top of EVERYTHING, including menus
- gViewerWindow->getRootView()->sendChildToFront(gToolTipView);
+ // *TODO:Also fix cost in llfolderview.cpp for Inventory menus
+ const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost());
+ const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost());
+ const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost());
+ gMenuHolder->childSetLabelArg("Upload Image", "[COST]", texture_upload_cost_str);
+ gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str);
+ gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str);
+
+ gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE);
+ gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE);
+
+ gDetachAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach", true);
+ gDetachHUDAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach HUD", true);
+
+ // Don't display the Memory console menu if the feature is turned off
+ LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", TRUE);
+ if (memoryMenu)
+ {
+ memoryMenu->setVisible(FALSE);
+ }
+
+ gMenuBarView->createJumpKeys();
+
+ // Let land based option enable when parcel changes
+ gMenuParcelObserver = new LLMenuParcelObserver();
+
+ gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ gLoginMenuBarView->arrangeAndClear();
+ LLRect menuBarRect = gLoginMenuBarView->getRect();
+ menuBarRect.setLeftTopAndSize(0, menu_bar_holder->getRect().getHeight(), menuBarRect.getWidth(), menuBarRect.getHeight());
+ gLoginMenuBarView->setRect(menuBarRect);
+ gLoginMenuBarView->setBackgroundColor( color );
+ menu_bar_holder->addChild(gLoginMenuBarView);
+
+ // tooltips are on top of EVERYTHING, including menus
+ gViewerWindow->getRootView()->sendChildToFront(gToolTipView);
}
///////////////////
@@ -572,62 +572,62 @@ void init_menus()
class LLAdvancedToggleConsole : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string console_type = userdata.asString();
- if ("texture" == console_type)
- {
- toggle_visibility( (void*)gTextureView );
- }
- else if ("debug" == console_type)
- {
- toggle_visibility( (void*)static_cast<LLUICtrl*>(gDebugView->mDebugConsolep));
- }
- else if ("fast timers" == console_type)
- {
- LLFloaterReg::toggleInstance("block_timers");
- }
- else if ("scene view" == console_type)
- {
- toggle_visibility( (void*)gSceneView);
- }
- else if ("scene monitor" == console_type)
- {
- toggle_visibility( (void*)gSceneMonitorView);
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string console_type = userdata.asString();
+ if ("texture" == console_type)
+ {
+ toggle_visibility( (void*)gTextureView );
+ }
+ else if ("debug" == console_type)
+ {
+ toggle_visibility( (void*)static_cast<LLUICtrl*>(gDebugView->mDebugConsolep));
+ }
+ else if ("fast timers" == console_type)
+ {
+ LLFloaterReg::toggleInstance("block_timers");
+ }
+ else if ("scene view" == console_type)
+ {
+ toggle_visibility( (void*)gSceneView);
+ }
+ else if ("scene monitor" == console_type)
+ {
+ toggle_visibility( (void*)gSceneMonitorView);
+ }
+
+ return true;
+ }
};
class LLAdvancedCheckConsole : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string console_type = userdata.asString();
- bool new_value = false;
- if ("texture" == console_type)
- {
- new_value = get_visibility( (void*)gTextureView );
- }
- else if ("debug" == console_type)
- {
- new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) );
- }
- else if ("fast timers" == console_type)
- {
- new_value = LLFloaterReg::instanceVisible("block_timers");
- }
- else if ("scene view" == console_type)
- {
- new_value = get_visibility( (void*) gSceneView);
- }
- else if ("scene monitor" == console_type)
- {
- new_value = get_visibility( (void*) gSceneMonitorView);
- }
-
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string console_type = userdata.asString();
+ bool new_value = false;
+ if ("texture" == console_type)
+ {
+ new_value = get_visibility( (void*)gTextureView );
+ }
+ else if ("debug" == console_type)
+ {
+ new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) );
+ }
+ else if ("fast timers" == console_type)
+ {
+ new_value = LLFloaterReg::instanceVisible("block_timers");
+ }
+ else if ("scene view" == console_type)
+ {
+ new_value = get_visibility( (void*) gSceneView);
+ }
+ else if ("scene monitor" == console_type)
+ {
+ new_value = get_visibility( (void*) gSceneMonitorView);
+ }
+
+ return new_value;
+ }
};
@@ -638,24 +638,24 @@ class LLAdvancedCheckConsole : public view_listener_t
class LLAdvancedDumpInfoToConsole : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gDebugView->mDebugConsolep->setVisible(TRUE);
- std::string info_type = userdata.asString();
- if ("region" == info_type)
- {
- handle_region_dump_settings(NULL);
- }
- else if ("group" == info_type)
- {
- handle_dump_group_info(NULL);
- }
- else if ("capabilities" == info_type)
- {
- handle_dump_capabilities_info(NULL);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gDebugView->mDebugConsolep->setVisible(TRUE);
+ std::string info_type = userdata.asString();
+ if ("region" == info_type)
+ {
+ handle_region_dump_settings(NULL);
+ }
+ else if ("group" == info_type)
+ {
+ handle_dump_group_info(NULL);
+ }
+ else if ("capabilities" == info_type)
+ {
+ handle_dump_capabilities_info(NULL);
+ }
+ return true;
+ }
};
@@ -666,54 +666,54 @@ class LLAdvancedDumpInfoToConsole : public view_listener_t
class LLAdvancedToggleHUDInfo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string info_type = userdata.asString();
-
- if ("camera" == info_type)
- {
- gDisplayCameraPos = !(gDisplayCameraPos);
- }
- else if ("wind" == info_type)
- {
- gDisplayWindInfo = !(gDisplayWindInfo);
- }
- else if ("fov" == info_type)
- {
- gDisplayFOV = !(gDisplayFOV);
- }
- else if ("badge" == info_type)
- {
- gDisplayBadge = !(gDisplayBadge);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string info_type = userdata.asString();
+
+ if ("camera" == info_type)
+ {
+ gDisplayCameraPos = !(gDisplayCameraPos);
+ }
+ else if ("wind" == info_type)
+ {
+ gDisplayWindInfo = !(gDisplayWindInfo);
+ }
+ else if ("fov" == info_type)
+ {
+ gDisplayFOV = !(gDisplayFOV);
+ }
+ else if ("badge" == info_type)
+ {
+ gDisplayBadge = !(gDisplayBadge);
+ }
+ return true;
+ }
};
class LLAdvancedCheckHUDInfo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string info_type = userdata.asString();
- bool new_value = false;
- if ("camera" == info_type)
- {
- new_value = gDisplayCameraPos;
- }
- else if ("wind" == info_type)
- {
- new_value = gDisplayWindInfo;
- }
- else if ("fov" == info_type)
- {
- new_value = gDisplayFOV;
- }
- else if ("badge" == info_type)
- {
- new_value = gDisplayBadge;
- }
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string info_type = userdata.asString();
+ bool new_value = false;
+ if ("camera" == info_type)
+ {
+ new_value = gDisplayCameraPos;
+ }
+ else if ("wind" == info_type)
+ {
+ new_value = gDisplayWindInfo;
+ }
+ else if ("fov" == info_type)
+ {
+ new_value = gDisplayFOV;
+ }
+ else if ("badge" == info_type)
+ {
+ new_value = gDisplayBadge;
+ }
+ return new_value;
+ }
};
@@ -723,11 +723,11 @@ class LLAdvancedCheckHUDInfo : public view_listener_t
class LLAdvancedClearGroupCache : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLGroupMgr::debugClearAllGroups(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLGroupMgr::debugClearAllGroups(NULL);
+ return true;
+ }
};
@@ -738,97 +738,97 @@ class LLAdvancedClearGroupCache : public view_listener_t
/////////////////
U32 render_type_from_string(std::string render_type)
{
- if ("simple" == render_type)
- {
- return LLPipeline::RENDER_TYPE_SIMPLE;
- }
- else if ("alpha" == render_type)
- {
- return LLPipeline::RENDER_TYPE_ALPHA;
- }
- else if ("tree" == render_type)
- {
- return LLPipeline::RENDER_TYPE_TREE;
- }
- else if ("character" == render_type)
- {
- return LLPipeline::RENDER_TYPE_AVATAR;
- }
- else if ("controlAV" == render_type) // Animesh
- {
- return LLPipeline::RENDER_TYPE_CONTROL_AV;
- }
- else if ("surfacePatch" == render_type)
- {
- return LLPipeline::RENDER_TYPE_TERRAIN;
- }
- else if ("sky" == render_type)
- {
- return LLPipeline::RENDER_TYPE_SKY;
- }
- else if ("water" == render_type)
- {
- return LLPipeline::RENDER_TYPE_WATER;
- }
- else if ("volume" == render_type)
- {
- return LLPipeline::RENDER_TYPE_VOLUME;
- }
- else if ("grass" == render_type)
- {
- return LLPipeline::RENDER_TYPE_GRASS;
- }
- else if ("clouds" == render_type)
- {
- return LLPipeline::RENDER_TYPE_CLOUDS;
- }
- else if ("particles" == render_type)
- {
- return LLPipeline::RENDER_TYPE_PARTICLES;
- }
- else if ("bump" == render_type)
- {
- return LLPipeline::RENDER_TYPE_BUMP;
- }
- else if ("pbr" == render_type)
+ if ("simple" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_SIMPLE;
+ }
+ else if ("alpha" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_ALPHA;
+ }
+ else if ("tree" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_TREE;
+ }
+ else if ("character" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_AVATAR;
+ }
+ else if ("controlAV" == render_type) // Animesh
+ {
+ return LLPipeline::RENDER_TYPE_CONTROL_AV;
+ }
+ else if ("surfacePatch" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_TERRAIN;
+ }
+ else if ("sky" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_SKY;
+ }
+ else if ("water" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_WATER;
+ }
+ else if ("volume" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_VOLUME;
+ }
+ else if ("grass" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_GRASS;
+ }
+ else if ("clouds" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_CLOUDS;
+ }
+ else if ("particles" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_PARTICLES;
+ }
+ else if ("bump" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_BUMP;
+ }
+ else if ("pbr" == render_type)
{
return LLPipeline::RENDER_TYPE_GLTF_PBR;
}
- else
- {
- return 0;
- }
+ else
+ {
+ return 0;
+ }
}
class LLAdvancedToggleRenderType : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- U32 render_type = render_type_from_string( userdata.asString() );
- if ( render_type != 0 )
- {
- LLPipeline::toggleRenderTypeControl( render_type );
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 render_type = render_type_from_string( userdata.asString() );
+ if ( render_type != 0 )
+ {
+ LLPipeline::toggleRenderTypeControl( render_type );
+ }
+ return true;
+ }
};
class LLAdvancedCheckRenderType : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- U32 render_type = render_type_from_string( userdata.asString() );
- bool new_value = false;
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 render_type = render_type_from_string( userdata.asString() );
+ bool new_value = false;
- if ( render_type != 0 )
- {
- new_value = LLPipeline::hasRenderTypeControl( render_type );
- }
+ if ( render_type != 0 )
+ {
+ new_value = LLPipeline::hasRenderTypeControl( render_type );
+ }
- return new_value;
- }
+ return new_value;
+ }
};
@@ -836,140 +836,140 @@ class LLAdvancedCheckRenderType : public view_listener_t
// FEATURE //
/////////////
U32 feature_from_string(std::string feature)
-{
- if ("ui" == feature)
- {
- return LLPipeline::RENDER_DEBUG_FEATURE_UI;
- }
- else if ("selected" == feature)
- {
- return LLPipeline::RENDER_DEBUG_FEATURE_SELECTED;
- }
- else if ("highlighted" == feature)
- {
- return LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED;
- }
- else if ("dynamic textures" == feature)
- {
- return LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES;
- }
- else if ("foot shadows" == feature)
- {
- return LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS;
- }
- else if ("fog" == feature)
- {
- return LLPipeline::RENDER_DEBUG_FEATURE_FOG;
- }
- else if ("fr info" == feature)
- {
- return LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO;
- }
- else if ("flexible" == feature)
- {
- return LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE;
- }
- else
- {
- return 0;
- }
+{
+ if ("ui" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_UI;
+ }
+ else if ("selected" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_SELECTED;
+ }
+ else if ("highlighted" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED;
+ }
+ else if ("dynamic textures" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES;
+ }
+ else if ("foot shadows" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS;
+ }
+ else if ("fog" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_FOG;
+ }
+ else if ("fr info" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO;
+ }
+ else if ("flexible" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE;
+ }
+ else
+ {
+ return 0;
+ }
};
class LLAdvancedToggleFeature : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- U32 feature = feature_from_string( userdata.asString() );
- if ( feature != 0 )
- {
- LLPipeline::toggleRenderDebugFeature( feature );
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 feature = feature_from_string( userdata.asString() );
+ if ( feature != 0 )
+ {
+ LLPipeline::toggleRenderDebugFeature( feature );
+ }
+ return true;
+ }
};
class LLAdvancedCheckFeature : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- U32 feature = feature_from_string( userdata.asString() );
- bool new_value = false;
+ U32 feature = feature_from_string( userdata.asString() );
+ bool new_value = false;
- if ( feature != 0 )
- {
- new_value = LLPipeline::toggleRenderDebugFeatureControl( feature );
- }
+ if ( feature != 0 )
+ {
+ new_value = LLPipeline::toggleRenderDebugFeatureControl( feature );
+ }
- return new_value;
+ return new_value;
}
};
class LLAdvancedCheckDisplayTextureDensity : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string mode = userdata.asString();
- if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
- {
- return mode == "none";
- }
- if (mode == "current")
- {
- return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_CURRENT;
- }
- else if (mode == "desired")
- {
- return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_DESIRED;
- }
- else if (mode == "full")
- {
- return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_FULL;
- }
- return false;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string mode = userdata.asString();
+ if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
+ {
+ return mode == "none";
+ }
+ if (mode == "current")
+ {
+ return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_CURRENT;
+ }
+ else if (mode == "desired")
+ {
+ return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_DESIRED;
+ }
+ else if (mode == "full")
+ {
+ return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_FULL;
+ }
+ return false;
+ }
};
class LLAdvancedSetDisplayTextureDensity : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string mode = userdata.asString();
- if (mode == "none")
- {
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == TRUE)
- {
- gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
- }
- LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF;
- }
- else if (mode == "current")
- {
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE)
- {
- gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
- }
- LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_CURRENT;
- }
- else if (mode == "desired")
- {
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE)
- {
- gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
- }
- gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY, true);
- LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_DESIRED;
- }
- else if (mode == "full")
- {
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE)
- {
- gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
- }
- LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_FULL;
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string mode = userdata.asString();
+ if (mode == "none")
+ {
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == TRUE)
+ {
+ gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
+ }
+ LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF;
+ }
+ else if (mode == "current")
+ {
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE)
+ {
+ gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
+ }
+ LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_CURRENT;
+ }
+ else if (mode == "desired")
+ {
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE)
+ {
+ gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
+ }
+ gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY, true);
+ LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_DESIRED;
+ }
+ else if (mode == "full")
+ {
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE)
+ {
+ gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY);
+ }
+ LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_FULL;
+ }
+ return true;
+ }
};
@@ -978,122 +978,122 @@ class LLAdvancedSetDisplayTextureDensity : public view_listener_t
//////////////////
U64 info_display_from_string(std::string info_display)
{
- if ("verify" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_VERIFY;
- }
- else if ("bboxes" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_BBOXES;
- }
- else if ("normals" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_NORMALS;
- }
- else if ("points" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_POINTS;
- }
- else if ("octree" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_OCTREE;
- }
- else if ("shadow frusta" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA;
- }
- else if ("physics shapes" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES;
- }
- else if ("occlusion" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_OCCLUSION;
- }
- else if ("render batches" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_BATCH_SIZE;
- }
- else if ("update type" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_UPDATE_TYPE;
- }
- else if ("texture anim" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM;
- }
- else if ("texture priority" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY;
- }
- else if ("texture area" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_TEXTURE_AREA;
- }
- else if ("face area" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_FACE_AREA;
- }
- else if ("lod info" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_LOD_INFO;
- }
- else if ("lights" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_LIGHTS;
- }
- else if ("particles" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_PARTICLES;
- }
- else if ("composition" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_COMPOSITION;
- }
- else if ("avatardrawinfo" == info_display)
- {
- return (LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO);
- }
- else if ("glow" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_GLOW;
- }
- else if ("collision skeleton" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_AVATAR_VOLUME;
- }
- else if ("joints" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_AVATAR_JOINTS;
- }
- else if ("raycast" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_RAYCAST;
- }
- else if ("agent target" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_AGENT_TARGET;
- }
- else if ("sculpt" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_SCULPTED;
- }
- else if ("wind vectors" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_WIND_VECTORS;
- }
- else if ("texel density" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_TEXEL_DENSITY;
- }
- else if ("triangle count" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT;
- }
- else if ("impostors" == info_display)
- {
- return LLPipeline::RENDER_DEBUG_IMPOSTORS;
- }
+ if ("verify" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_VERIFY;
+ }
+ else if ("bboxes" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_BBOXES;
+ }
+ else if ("normals" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_NORMALS;
+ }
+ else if ("points" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_POINTS;
+ }
+ else if ("octree" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_OCTREE;
+ }
+ else if ("shadow frusta" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA;
+ }
+ else if ("physics shapes" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES;
+ }
+ else if ("occlusion" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_OCCLUSION;
+ }
+ else if ("render batches" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_BATCH_SIZE;
+ }
+ else if ("update type" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_UPDATE_TYPE;
+ }
+ else if ("texture anim" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM;
+ }
+ else if ("texture priority" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY;
+ }
+ else if ("texture area" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_TEXTURE_AREA;
+ }
+ else if ("face area" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_FACE_AREA;
+ }
+ else if ("lod info" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_LOD_INFO;
+ }
+ else if ("lights" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_LIGHTS;
+ }
+ else if ("particles" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_PARTICLES;
+ }
+ else if ("composition" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_COMPOSITION;
+ }
+ else if ("avatardrawinfo" == info_display)
+ {
+ return (LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO);
+ }
+ else if ("glow" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_GLOW;
+ }
+ else if ("collision skeleton" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_AVATAR_VOLUME;
+ }
+ else if ("joints" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_AVATAR_JOINTS;
+ }
+ else if ("raycast" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_RAYCAST;
+ }
+ else if ("agent target" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_AGENT_TARGET;
+ }
+ else if ("sculpt" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_SCULPTED;
+ }
+ else if ("wind vectors" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_WIND_VECTORS;
+ }
+ else if ("texel density" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_TEXEL_DENSITY;
+ }
+ else if ("triangle count" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT;
+ }
+ else if ("impostors" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_IMPOSTORS;
+ }
else if ("reflection probes" == info_display)
{
return LLPipeline::RENDER_DEBUG_REFLECTION_PROBES;
@@ -1102,45 +1102,45 @@ U64 info_display_from_string(std::string info_display)
{
return LLPipeline::RENDER_DEBUG_PROBE_UPDATES;
}
- else
- {
- LL_WARNS() << "unrecognized feature name '" << info_display << "'" << LL_ENDL;
- return 0;
- }
+ else
+ {
+ LL_WARNS() << "unrecognized feature name '" << info_display << "'" << LL_ENDL;
+ return 0;
+ }
};
class LLAdvancedToggleInfoDisplay : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- U64 info_display = info_display_from_string( userdata.asString() );
-
- LL_INFOS("ViewerMenu") << "toggle " << userdata.asString() << LL_ENDL;
+ bool handleEvent(const LLSD& userdata)
+ {
+ U64 info_display = info_display_from_string( userdata.asString() );
- if ( info_display != 0 )
- {
- LLPipeline::toggleRenderDebug( info_display );
- }
+ LL_INFOS("ViewerMenu") << "toggle " << userdata.asString() << LL_ENDL;
+
+ if ( info_display != 0 )
+ {
+ LLPipeline::toggleRenderDebug( info_display );
+ }
- return true;
- }
+ return true;
+ }
};
class LLAdvancedCheckInfoDisplay : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- U64 info_display = info_display_from_string( userdata.asString() );
- bool new_value = false;
+ bool handleEvent(const LLSD& userdata)
+ {
+ U64 info_display = info_display_from_string( userdata.asString() );
+ bool new_value = false;
- if ( info_display != 0 )
- {
- new_value = LLPipeline::toggleRenderDebugControl( info_display );
- }
+ if ( info_display != 0 )
+ {
+ new_value = LLPipeline::toggleRenderDebugControl( info_display );
+ }
- return new_value;
- }
+ return new_value;
+ }
};
@@ -1151,20 +1151,20 @@ class LLAdvancedCheckInfoDisplay : public view_listener_t
class LLAdvancedToggleRandomizeFramerate : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gRandomizeFramerate = !(gRandomizeFramerate);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gRandomizeFramerate = !(gRandomizeFramerate);
+ return true;
+ }
};
class LLAdvancedCheckRandomizeFramerate : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gRandomizeFramerate;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gRandomizeFramerate;
+ return new_value;
+ }
};
///////////////////////////
@@ -1174,36 +1174,36 @@ class LLAdvancedCheckRandomizeFramerate : public view_listener_t
class LLAdvancedTogglePeriodicSlowFrame : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gPeriodicSlowFrame = !(gPeriodicSlowFrame);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gPeriodicSlowFrame = !(gPeriodicSlowFrame);
+ return true;
+ }
};
class LLAdvancedCheckPeriodicSlowFrame : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gPeriodicSlowFrame;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gPeriodicSlowFrame;
+ return new_value;
+ }
};
///////////////////////////
// SELECTED TEXTURE INFO //
-//
+//
///////////////////////////
class LLAdvancedSelectedTextureInfo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_selected_texture_info(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_selected_texture_info(NULL);
+ return true;
+ }
};
//////////////////////
@@ -1212,33 +1212,33 @@ class LLAdvancedSelectedTextureInfo : public view_listener_t
class LLAdvancedToggleWireframe : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gUseWireframe = !(gUseWireframe);
+ bool handleEvent(const LLSD& userdata)
+ {
+ gUseWireframe = !(gUseWireframe);
- return true;
- }
+ return true;
+ }
};
class LLAdvancedCheckWireframe : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return gUseWireframe;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return gUseWireframe;
+ }
};
-
+
//////////////////////////
// DUMP SCRIPTED CAMERA //
//////////////////////////
-
+
class LLAdvancedDumpScriptedCamera : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_dump_followcam(NULL);
- return true;
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_dump_followcam(NULL);
+ return true;
}
};
@@ -1251,11 +1251,11 @@ class LLAdvancedDumpScriptedCamera : public view_listener_t
class LLAdvancedDumpRegionObjectCache : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_dump_region_object_cache(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_dump_region_object_cache(NULL);
+ return true;
+ }
};
class LLAdvancedToggleInterestList360Mode : public view_listener_t
@@ -1266,22 +1266,22 @@ public:
// Toggle the mode - regions will get updated
if (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360)
{
- gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_DEFAULT);
- }
- else
- {
- gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360);
- }
+ gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_DEFAULT);
+ }
+ else
+ {
+ gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360);
+ }
return true;
}
};
class LLAdvancedCheckInterestList360Mode : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360);
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360);
+ }
};
class LLAdvancedToggleStatsRecorder : public view_listener_t
@@ -1289,13 +1289,13 @@ class LLAdvancedToggleStatsRecorder : public view_listener_t
bool handleEvent(const LLSD &userdata)
{
if (LLViewerStatsRecorder::instance().isEnabled())
- { // Turn off both recording and logging
- LLViewerStatsRecorder::instance().enableObjectStatsRecording(false);
- }
- else
- { // Turn on both recording and logging
- LLViewerStatsRecorder::instance().enableObjectStatsRecording(true, true);
- }
+ { // Turn off both recording and logging
+ LLViewerStatsRecorder::instance().enableObjectStatsRecording(false);
+ }
+ else
+ { // Turn on both recording and logging
+ LLViewerStatsRecorder::instance().enableObjectStatsRecording(true, true);
+ }
return true;
}
};
@@ -1303,7 +1303,7 @@ class LLAdvancedToggleStatsRecorder : public view_listener_t
class LLAdvancedCheckStatsRecorder : public view_listener_t
{
bool handleEvent(const LLSD &userdata)
- { // Use the logging state as the indicator of whether the stats recorder is on
+ { // Use the logging state as the indicator of whether the stats recorder is on
return LLViewerStatsRecorder::instance().isLogging();
}
};
@@ -1311,7 +1311,7 @@ class LLAdvancedCheckStatsRecorder : public view_listener_t
class LLAdvancedResetInterestLists : public view_listener_t
{
bool handleEvent(const LLSD &userdata)
- { // Reset all region interest lists
+ { // Reset all region interest lists
handle_reset_interest_lists(NULL);
return true;
}
@@ -1319,12 +1319,12 @@ class LLAdvancedResetInterestLists : public view_listener_t
class LLAdvancedBuyCurrencyTest : public view_listener_t
- {
- bool handleEvent(const LLSD& userdata)
- {
- handle_buy_currency_test(NULL);
- return true;
- }
+ {
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_buy_currency_test(NULL);
+ return true;
+ }
};
@@ -1335,11 +1335,11 @@ class LLAdvancedBuyCurrencyTest : public view_listener_t
class LLAdvancedDumpSelectMgr : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- dump_select_mgr(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ dump_select_mgr(NULL);
+ return true;
+ }
};
@@ -1351,11 +1351,11 @@ class LLAdvancedDumpSelectMgr : public view_listener_t
class LLAdvancedDumpInventory : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- dump_inventory(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ dump_inventory(NULL);
+ return true;
+ }
};
@@ -1367,11 +1367,11 @@ class LLAdvancedDumpInventory : public view_listener_t
class LLAdvancedPrintSelectedObjectInfo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- print_object_info(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ print_object_info(NULL);
+ return true;
+ }
};
@@ -1383,11 +1383,11 @@ class LLAdvancedPrintSelectedObjectInfo : public view_listener_t
class LLAdvancedPrintAgentInfo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- print_agent_nvpairs(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ print_agent_nvpairs(NULL);
+ return true;
+ }
};
//////////////////
@@ -1397,20 +1397,20 @@ class LLAdvancedPrintAgentInfo : public view_listener_t
class LLAdvancedToggleDebugClicks : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gDebugClicks = !(gDebugClicks);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gDebugClicks = !(gDebugClicks);
+ return true;
+ }
};
class LLAdvancedCheckDebugClicks : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gDebugClicks;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gDebugClicks;
+ return new_value;
+ }
};
@@ -1422,20 +1422,20 @@ class LLAdvancedCheckDebugClicks : public view_listener_t
class LLAdvancedToggleDebugViews : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLView::sDebugRects = !(LLView::sDebugRects);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLView::sDebugRects = !(LLView::sDebugRects);
+ return true;
+ }
};
class LLAdvancedCheckDebugViews : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLView::sDebugRects;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLView::sDebugRects;
+ return new_value;
+ }
};
@@ -1447,19 +1447,19 @@ class LLAdvancedCheckDebugViews : public view_listener_t
class LLAdvancedToggleDebugUnicode : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLView::sDebugUnicode = !(LLView::sDebugUnicode);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLView::sDebugUnicode = !(LLView::sDebugUnicode);
+ return true;
+ }
};
class LLAdvancedCheckDebugUnicode : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return LLView::sDebugUnicode;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return LLView::sDebugUnicode;
+ }
};
@@ -1471,20 +1471,20 @@ class LLAdvancedCheckDebugUnicode : public view_listener_t
class LLAdvancedToggleDebugCamera : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLView::sDebugCamera = !(LLView::sDebugCamera);
- LLFloaterCamera::onDebugCameraToggled();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLView::sDebugCamera = !(LLView::sDebugCamera);
+ LLFloaterCamera::onDebugCameraToggled();
+ return true;
+ }
};
class LLAdvancedCheckDebugCamera : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return LLView::sDebugCamera;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return LLView::sDebugCamera;
+ }
};
@@ -1496,20 +1496,20 @@ class LLAdvancedCheckDebugCamera : public view_listener_t
class LLAdvancedToggleXUINameTooltips : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- toggle_show_xui_names(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ toggle_show_xui_names(NULL);
+ return true;
+ }
};
class LLAdvancedCheckXUINameTooltips : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = check_show_xui_names(NULL);
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = check_show_xui_names(NULL);
+ return new_value;
+ }
};
@@ -1521,20 +1521,20 @@ class LLAdvancedCheckXUINameTooltips : public view_listener_t
class LLAdvancedToggleDebugMouseEvents : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLView::sDebugMouseHandling = !(LLView::sDebugMouseHandling);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLView::sDebugMouseHandling = !(LLView::sDebugMouseHandling);
+ return true;
+ }
};
class LLAdvancedCheckDebugMouseEvents : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLView::sDebugMouseHandling;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLView::sDebugMouseHandling;
+ return new_value;
+ }
};
@@ -1546,22 +1546,22 @@ class LLAdvancedCheckDebugMouseEvents : public view_listener_t
class LLAdvancedToggleDebugKeys : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLView::sDebugKeys = !(LLView::sDebugKeys);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLView::sDebugKeys = !(LLView::sDebugKeys);
+ return true;
+ }
};
-
+
class LLAdvancedCheckDebugKeys : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLView::sDebugKeys;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLView::sDebugKeys;
+ return new_value;
+ }
};
-
+
///////////////////////
@@ -1571,30 +1571,30 @@ class LLAdvancedCheckDebugKeys : public view_listener_t
class LLAdvancedToggleDebugWindowProc : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gDebugWindowProc = !(gDebugWindowProc);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gDebugWindowProc = !(gDebugWindowProc);
+ return true;
+ }
};
class LLAdvancedCheckDebugWindowProc : public view_listener_t
- {
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gDebugWindowProc;
- return new_value;
- }
+ {
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gDebugWindowProc;
+ return new_value;
+ }
};
// ------------------------------XUI MENU ---------------------------
class LLAdvancedSendTestIms : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLIMModel::instance().testMessages();
- return true;
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLIMModel::instance().testMessages();
+ return true;
}
};
@@ -1606,20 +1606,20 @@ class LLAdvancedSendTestIms : public view_listener_t
class LLAdvancedToggleXUINames : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- toggle_show_xui_names(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ toggle_show_xui_names(NULL);
+ return true;
+ }
};
class LLAdvancedCheckXUINames : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = check_show_xui_names(NULL);
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = check_show_xui_names(NULL);
+ return new_value;
+ }
};
@@ -1630,71 +1630,71 @@ class LLAdvancedCheckXUINames : public view_listener_t
class LLAdvancedGrabBakedTexture : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string texture_type = userdata.asString();
- if ("iris" == texture_type)
- {
- handle_grab_baked_texture( (void*)BAKED_EYES );
- }
- else if ("head" == texture_type)
- {
- handle_grab_baked_texture( (void*)BAKED_HEAD );
- }
- else if ("upper" == texture_type)
- {
- handle_grab_baked_texture( (void*)BAKED_UPPER );
- }
- else if ("lower" == texture_type)
- {
- handle_grab_baked_texture( (void*)BAKED_LOWER );
- }
- else if ("skirt" == texture_type)
- {
- handle_grab_baked_texture( (void*)BAKED_SKIRT );
- }
- else if ("hair" == texture_type)
- {
- handle_grab_baked_texture( (void*)BAKED_HAIR );
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string texture_type = userdata.asString();
+ if ("iris" == texture_type)
+ {
+ handle_grab_baked_texture( (void*)BAKED_EYES );
+ }
+ else if ("head" == texture_type)
+ {
+ handle_grab_baked_texture( (void*)BAKED_HEAD );
+ }
+ else if ("upper" == texture_type)
+ {
+ handle_grab_baked_texture( (void*)BAKED_UPPER );
+ }
+ else if ("lower" == texture_type)
+ {
+ handle_grab_baked_texture( (void*)BAKED_LOWER );
+ }
+ else if ("skirt" == texture_type)
+ {
+ handle_grab_baked_texture( (void*)BAKED_SKIRT );
+ }
+ else if ("hair" == texture_type)
+ {
+ handle_grab_baked_texture( (void*)BAKED_HAIR );
+ }
+
+ return true;
+ }
};
class LLAdvancedEnableGrabBakedTexture : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
-{
- std::string texture_type = userdata.asString();
- bool new_value = false;
-
- if ("iris" == texture_type)
- {
- new_value = enable_grab_baked_texture( (void*)BAKED_EYES );
- }
- else if ("head" == texture_type)
- {
- new_value = enable_grab_baked_texture( (void*)BAKED_HEAD );
- }
- else if ("upper" == texture_type)
- {
- new_value = enable_grab_baked_texture( (void*)BAKED_UPPER );
- }
- else if ("lower" == texture_type)
- {
- new_value = enable_grab_baked_texture( (void*)BAKED_LOWER );
- }
- else if ("skirt" == texture_type)
- {
- new_value = enable_grab_baked_texture( (void*)BAKED_SKIRT );
- }
- else if ("hair" == texture_type)
- {
- new_value = enable_grab_baked_texture( (void*)BAKED_HAIR );
- }
-
- return new_value;
+ bool handleEvent(const LLSD& userdata)
+{
+ std::string texture_type = userdata.asString();
+ bool new_value = false;
+
+ if ("iris" == texture_type)
+ {
+ new_value = enable_grab_baked_texture( (void*)BAKED_EYES );
+ }
+ else if ("head" == texture_type)
+ {
+ new_value = enable_grab_baked_texture( (void*)BAKED_HEAD );
+ }
+ else if ("upper" == texture_type)
+ {
+ new_value = enable_grab_baked_texture( (void*)BAKED_UPPER );
+ }
+ else if ("lower" == texture_type)
+ {
+ new_value = enable_grab_baked_texture( (void*)BAKED_LOWER );
+ }
+ else if ("skirt" == texture_type)
+ {
+ new_value = enable_grab_baked_texture( (void*)BAKED_SKIRT );
+ }
+ else if ("hair" == texture_type)
+ {
+ new_value = enable_grab_baked_texture( (void*)BAKED_HAIR );
+ }
+
+ return new_value;
}
};
@@ -1705,8 +1705,8 @@ class LLAdvancedEnableGrabBakedTexture : public view_listener_t
class LLAdvancedEnableAppearanceToXML : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
+ bool handleEvent(const LLSD& userdata)
+ {
LLViewerObject *obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (obj && obj->isAnimatedObject() && obj->getControlAvatar())
{
@@ -1721,18 +1721,18 @@ class LLAdvancedEnableAppearanceToXML : public view_listener_t
// This has to be a non-control avatar, because control avs are invisible and unclickable.
return gSavedSettings.getBOOL("DebugAvatarAppearanceMessage");
}
- else
- {
- return false;
- }
- }
+ else
+ {
+ return false;
+ }
+ }
};
class LLAdvancedAppearanceToXML : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string emptyname;
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string emptyname;
LLViewerObject *obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
LLVOAvatar *avatar = NULL;
if (obj)
@@ -1755,14 +1755,14 @@ class LLAdvancedAppearanceToXML : public view_listener_t
else
{
// If no selection, use the self avatar.
- avatar = gAgentAvatarp;
+ avatar = gAgentAvatarp;
}
if (avatar)
{
avatar->dumpArchetypeXML(emptyname);
}
- return true;
- }
+ return true;
+ }
};
@@ -1774,44 +1774,44 @@ class LLAdvancedAppearanceToXML : public view_listener_t
class LLAdvancedToggleCharacterGeometry : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_god_request_avatar_geometry(NULL);
- return true;
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_god_request_avatar_geometry(NULL);
+ return true;
}
};
- /////////////////////////////
+ /////////////////////////////
// TEST MALE / TEST FEMALE //
/////////////////////////////
class LLAdvancedTestMale : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_test_male(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_test_male(NULL);
+ return true;
+ }
};
class LLAdvancedTestFemale : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_test_female(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_test_female(NULL);
+ return true;
+ }
};
class LLAdvancedForceParamsToDefault : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLAgent::clearVisualParams(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLAgent::clearVisualParams(NULL);
+ return true;
+ }
};
@@ -1820,47 +1820,47 @@ class LLAdvancedForceParamsToDefault : public view_listener_t
//////////////////////////
// Utility function to set all AV time factors to the same global value
-static void set_all_animation_time_factors(F32 time_factor)
+static void set_all_animation_time_factors(F32 time_factor)
{
- LLMotionController::setCurrentTimeFactor(time_factor);
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- (*iter)->setAnimTimeFactor(time_factor);
- }
+ LLMotionController::setCurrentTimeFactor(time_factor);
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
+ {
+ (*iter)->setAnimTimeFactor(time_factor);
+ }
}
class LLAdvancedAnimTenFaster : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- //LL_INFOS() << "LLAdvancedAnimTenFaster" << LL_ENDL;
- F32 time_factor = LLMotionController::getCurrentTimeFactor();
- time_factor = llmin(time_factor + 0.1f, 2.f); // Upper limit is 200% speed
- set_all_animation_time_factors(time_factor);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ //LL_INFOS() << "LLAdvancedAnimTenFaster" << LL_ENDL;
+ F32 time_factor = LLMotionController::getCurrentTimeFactor();
+ time_factor = llmin(time_factor + 0.1f, 2.f); // Upper limit is 200% speed
+ set_all_animation_time_factors(time_factor);
+ return true;
+ }
};
class LLAdvancedAnimTenSlower : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- //LL_INFOS() << "LLAdvancedAnimTenSlower" << LL_ENDL;
- F32 time_factor = LLMotionController::getCurrentTimeFactor();
- time_factor = llmax(time_factor - 0.1f, 0.1f); // Lower limit is at 10% of normal speed
- set_all_animation_time_factors(time_factor);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ //LL_INFOS() << "LLAdvancedAnimTenSlower" << LL_ENDL;
+ F32 time_factor = LLMotionController::getCurrentTimeFactor();
+ time_factor = llmax(time_factor - 0.1f, 0.1f); // Lower limit is at 10% of normal speed
+ set_all_animation_time_factors(time_factor);
+ return true;
+ }
};
class LLAdvancedAnimResetAll : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- set_all_animation_time_factors(1.f);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ set_all_animation_time_factors(1.f);
+ return true;
+ }
};
@@ -1871,11 +1871,11 @@ class LLAdvancedAnimResetAll : public view_listener_t
class LLAdvancedReloadVertexShader : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- reload_vertex_shader(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ reload_vertex_shader(NULL);
+ return true;
+ }
};
@@ -1887,20 +1887,20 @@ class LLAdvancedReloadVertexShader : public view_listener_t
class LLAdvancedToggleAnimationInfo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar::sShowAnimationDebug = !(LLVOAvatar::sShowAnimationDebug);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar::sShowAnimationDebug = !(LLVOAvatar::sShowAnimationDebug);
+ return true;
+ }
};
class LLAdvancedCheckAnimationInfo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLVOAvatar::sShowAnimationDebug;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLVOAvatar::sShowAnimationDebug;
+ return new_value;
+ }
};
@@ -1911,20 +1911,20 @@ class LLAdvancedCheckAnimationInfo : public view_listener_t
class LLAdvancedToggleShowLookAt : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLHUDEffectLookAt::sDebugLookAt = !(LLHUDEffectLookAt::sDebugLookAt);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLHUDEffectLookAt::sDebugLookAt = !(LLHUDEffectLookAt::sDebugLookAt);
+ return true;
+ }
};
class LLAdvancedCheckShowLookAt : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLHUDEffectLookAt::sDebugLookAt;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLHUDEffectLookAt::sDebugLookAt;
+ return new_value;
+ }
};
@@ -1936,20 +1936,20 @@ class LLAdvancedCheckShowLookAt : public view_listener_t
class LLAdvancedToggleShowPointAt : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLHUDEffectPointAt::sDebugPointAt = !(LLHUDEffectPointAt::sDebugPointAt);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLHUDEffectPointAt::sDebugPointAt = !(LLHUDEffectPointAt::sDebugPointAt);
+ return true;
+ }
};
class LLAdvancedCheckShowPointAt : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLHUDEffectPointAt::sDebugPointAt;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLHUDEffectPointAt::sDebugPointAt;
+ return new_value;
+ }
};
@@ -1961,20 +1961,20 @@ class LLAdvancedCheckShowPointAt : public view_listener_t
class LLAdvancedToggleDebugJointUpdates : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar::sJointDebug = !(LLVOAvatar::sJointDebug);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar::sJointDebug = !(LLVOAvatar::sJointDebug);
+ return true;
+ }
};
class LLAdvancedCheckDebugJointUpdates : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLVOAvatar::sJointDebug;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLVOAvatar::sJointDebug;
+ return new_value;
+ }
};
@@ -1986,20 +1986,20 @@ class LLAdvancedCheckDebugJointUpdates : public view_listener_t
class LLAdvancedToggleDisableLOD : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLViewerJoint::sDisableLOD = !(LLViewerJoint::sDisableLOD);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerJoint::sDisableLOD = !(LLViewerJoint::sDisableLOD);
+ return true;
+ }
};
-
+
class LLAdvancedCheckDisableLOD : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLViewerJoint::sDisableLOD;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLViewerJoint::sDisableLOD;
+ return new_value;
+ }
};
@@ -2011,20 +2011,20 @@ class LLAdvancedCheckDisableLOD : public view_listener_t
class LLAdvancedToggleDebugCharacterVis : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar::sDebugInvisible = !(LLVOAvatar::sDebugInvisible);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar::sDebugInvisible = !(LLVOAvatar::sDebugInvisible);
+ return true;
+ }
};
class LLAdvancedCheckDebugCharacterVis : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLVOAvatar::sDebugInvisible;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLVOAvatar::sDebugInvisible;
+ return new_value;
+ }
};
@@ -2032,33 +2032,33 @@ class LLAdvancedCheckDebugCharacterVis : public view_listener_t
// DUMP ATTACHMENTS //
//////////////////////
-
+
class LLAdvancedDumpAttachments : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_dump_attachments(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_dump_attachments(NULL);
+ return true;
+ }
};
-
+
/////////////////////
// REBAKE TEXTURES //
/////////////////////
-
-
+
+
class LLAdvancedRebakeTextures : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_rebake_textures(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_rebake_textures(NULL);
+ return true;
+ }
};
-
-
+
+
#if 1 //ndef LL_RELEASE_FOR_DOWNLOAD
///////////////////////////
// DEBUG AVATAR TEXTURES //
@@ -2067,14 +2067,14 @@ class LLAdvancedRebakeTextures : public view_listener_t
class LLAdvancedDebugAvatarTextures : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (gAgent.isGodlike())
- {
- handle_debug_avatar_textures(NULL);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgent.isGodlike())
+ {
+ handle_debug_avatar_textures(NULL);
+ }
+ return true;
+ }
};
////////////////////////////////
@@ -2084,17 +2084,17 @@ class LLAdvancedDebugAvatarTextures : public view_listener_t
class LLAdvancedDumpAvatarLocalTextures : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
+ bool handleEvent(const LLSD& userdata)
+ {
#ifndef LL_RELEASE_FOR_DOWNLOAD
- handle_dump_avatar_local_textures(NULL);
+ handle_dump_avatar_local_textures(NULL);
#endif
- return true;
- }
+ return true;
+ }
};
#endif
-
+
/////////////////
// MESSAGE LOG //
/////////////////
@@ -2102,20 +2102,20 @@ class LLAdvancedDumpAvatarLocalTextures : public view_listener_t
class LLAdvancedEnableMessageLog : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_viewer_enable_message_log(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_viewer_enable_message_log(NULL);
+ return true;
+ }
};
class LLAdvancedDisableMessageLog : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_viewer_disable_message_log(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_viewer_disable_message_log(NULL);
+ return true;
+ }
};
/////////////////
@@ -2125,11 +2125,11 @@ class LLAdvancedDisableMessageLog : public view_listener_t
class LLAdvancedDropPacket : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gMessageSystem->mPacketRing.dropPackets(1);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gMessageSystem->mPacketRing.dropPackets(1);
+ return true;
+ }
};
//////////////////////
@@ -2139,8 +2139,8 @@ class LLAdvancedDropPacket : public view_listener_t
class LLAdvancedPurgeDiskCache : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
+ bool handleEvent(const LLSD& userdata)
+ {
LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General");
llassert_always(main_queue);
@@ -2154,8 +2154,8 @@ class LLAdvancedPurgeDiskCache : public view_listener_t
},
[](){}); // Callback to main thread is empty as there is nothing left to do
- return true;
- }
+ return true;
+ }
};
@@ -2166,12 +2166,12 @@ class LLAdvancedPurgeDiskCache : public view_listener_t
class LLAdvancedPurgeShaderCache : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLViewerShaderMgr::instance()->clearShaderCache();
- LLViewerShaderMgr::instance()->setShaders();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerShaderMgr::instance()->clearShaderCache();
+ LLViewerShaderMgr::instance()->setShaders();
+ return true;
+ }
};
////////////////////
@@ -2181,32 +2181,32 @@ class LLAdvancedPurgeShaderCache : public view_listener_t
class LLAdvancedViewerEventRecorder : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string command = userdata.asString();
- if ("start playback" == command)
- {
- LL_INFOS() << "Event Playback starting" << LL_ENDL;
- LLViewerEventRecorder::instance().playbackRecording();
- LL_INFOS() << "Event Playback completed" << LL_ENDL;
- }
- else if ("stop playback" == command)
- {
- // Future
- }
- else if ("start recording" == command)
- {
- LLViewerEventRecorder::instance().setEventLoggingOn();
- LL_INFOS() << "Event recording started" << LL_ENDL;
- }
- else if ("stop recording" == command)
- {
- LLViewerEventRecorder::instance().setEventLoggingOff();
- LL_INFOS() << "Event recording stopped" << LL_ENDL;
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string command = userdata.asString();
+ if ("start playback" == command)
+ {
+ LL_INFOS() << "Event Playback starting" << LL_ENDL;
+ LLViewerEventRecorder::instance().playbackRecording();
+ LL_INFOS() << "Event Playback completed" << LL_ENDL;
+ }
+ else if ("stop playback" == command)
+ {
+ // Future
+ }
+ else if ("start recording" == command)
+ {
+ LLViewerEventRecorder::instance().setEventLoggingOn();
+ LL_INFOS() << "Event recording started" << LL_ENDL;
+ }
+ else if ("stop recording" == command)
+ {
+ LLViewerEventRecorder::instance().setEventLoggingOff();
+ LL_INFOS() << "Event recording stopped" << LL_ENDL;
+ }
+
+ return true;
+ }
};
@@ -2219,29 +2219,29 @@ class LLAdvancedViewerEventRecorder : public view_listener_t
class LLAdvancedAgentPilot : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string command = userdata.asString();
- if ("start playback" == command)
- {
- gAgentPilot.setNumRuns(-1);
- gAgentPilot.startPlayback();
- }
- else if ("stop playback" == command)
- {
- gAgentPilot.stopPlayback();
- }
- else if ("start record" == command)
- {
- gAgentPilot.startRecord();
- }
- else if ("stop record" == command)
- {
- gAgentPilot.stopRecord();
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string command = userdata.asString();
+ if ("start playback" == command)
+ {
+ gAgentPilot.setNumRuns(-1);
+ gAgentPilot.startPlayback();
+ }
+ else if ("stop playback" == command)
+ {
+ gAgentPilot.stopPlayback();
+ }
+ else if ("start record" == command)
+ {
+ gAgentPilot.startRecord();
+ }
+ else if ("stop record" == command)
+ {
+ gAgentPilot.stopRecord();
+ }
+
+ return true;
+ }
};
@@ -2253,20 +2253,20 @@ class LLAdvancedAgentPilot : public view_listener_t
class LLAdvancedToggleAgentPilotLoop : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gAgentPilot.setLoop(!gAgentPilot.getLoop());
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gAgentPilot.setLoop(!gAgentPilot.getLoop());
+ return true;
+ }
};
class LLAdvancedCheckAgentPilotLoop : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gAgentPilot.getLoop();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gAgentPilot.getLoop();
+ return new_value;
+ }
};
@@ -2277,20 +2277,20 @@ class LLAdvancedCheckAgentPilotLoop : public view_listener_t
class LLAdvancedToggleShowObjectUpdates : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gShowObjectUpdates = !(gShowObjectUpdates);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gShowObjectUpdates = !(gShowObjectUpdates);
+ return true;
+ }
};
class LLAdvancedCheckShowObjectUpdates : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gShowObjectUpdates;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gShowObjectUpdates;
+ return new_value;
+ }
};
@@ -2302,11 +2302,11 @@ class LLAdvancedCheckShowObjectUpdates : public view_listener_t
class LLAdvancedCompressImage : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_compress_image(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_compress_image(NULL);
+ return true;
+ }
};
@@ -2332,11 +2332,11 @@ class LLAdvancedCompressFileTest : public view_listener_t
class LLAdvancedShowDebugSettings : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterReg::showInstance("settings_debug",userdata);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterReg::showInstance("settings_debug",userdata);
+ return true;
+ }
};
@@ -2347,40 +2347,40 @@ class LLAdvancedShowDebugSettings : public view_listener_t
class LLAdvancedEnableViewAdminOptions : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- // Don't enable in god mode since the admin menu is shown anyway.
- // Only enable if the user has set the appropriate debug setting.
- bool new_value = !gAgent.getAgentAccess().isGodlikeWithoutAdminMenuFakery() && gSavedSettings.getBOOL("AdminMenu");
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ // Don't enable in god mode since the admin menu is shown anyway.
+ // Only enable if the user has set the appropriate debug setting.
+ bool new_value = !gAgent.getAgentAccess().isGodlikeWithoutAdminMenuFakery() && gSavedSettings.getBOOL("AdminMenu");
+ return new_value;
+ }
};
class LLAdvancedToggleViewAdminOptions : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_admin_override_toggle(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_admin_override_toggle(NULL);
+ return true;
+ }
};
class LLAdvancedToggleVisualLeakDetector : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_visual_leak_detector_toggle(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_visual_leak_detector_toggle(NULL);
+ return true;
+ }
};
class LLAdvancedCheckViewAdminOptions : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = check_admin_override(NULL) || gAgent.isGodlike();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = check_admin_override(NULL) || gAgent.isGodlike();
+ return new_value;
+ }
};
//////////////////
@@ -2390,20 +2390,20 @@ class LLAdvancedCheckViewAdminOptions : public view_listener_t
class LLAdvancedRequestAdminStatus : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_god_mode(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_god_mode(NULL);
+ return true;
+ }
};
class LLAdvancedLeaveAdminStatus : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_leave_god_mode(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_leave_god_mode(NULL);
+ return true;
+ }
};
//////////////////////////
@@ -2412,20 +2412,20 @@ class LLAdvancedLeaveAdminStatus : public view_listener_t
class LLAdvancedForceErrorBreakpoint : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- force_error_breakpoint(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_breakpoint(NULL);
+ return true;
+ }
};
class LLAdvancedForceErrorLlerror : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- force_error_llerror(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_llerror(NULL);
+ return true;
+ }
};
class LLAdvancedForceErrorLlerrorMsg: public view_listener_t
@@ -2439,11 +2439,11 @@ class LLAdvancedForceErrorLlerrorMsg: public view_listener_t
class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- force_error_bad_memory_access(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_bad_memory_access(NULL);
+ return true;
+ }
};
class LLAdvancedForceErrorBadMemoryAccessCoro : public view_listener_t
@@ -2464,20 +2464,20 @@ class LLAdvancedForceErrorBadMemoryAccessCoro : public view_listener_t
class LLAdvancedForceErrorInfiniteLoop : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- force_error_infinite_loop(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_infinite_loop(NULL);
+ return true;
+ }
};
class LLAdvancedForceErrorSoftwareException : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- force_error_software_exception(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_software_exception(NULL);
+ return true;
+ }
};
class LLAdvancedForceOSException: public view_listener_t
@@ -2507,11 +2507,11 @@ class LLAdvancedForceErrorSoftwareExceptionCoro : public view_listener_t
class LLAdvancedForceErrorDriverCrash : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- force_error_driver_crash(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_driver_crash(NULL);
+ return true;
+ }
};
class LLAdvancedForceErrorCoroutineCrash : public view_listener_t
@@ -2534,10 +2534,10 @@ class LLAdvancedForceErrorThreadCrash : public view_listener_t
class LLAdvancedForceErrorDisconnectViewer : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_disconnect_viewer(NULL);
- return true;
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_disconnect_viewer(NULL);
+ return true;
}
};
@@ -2546,29 +2546,29 @@ class LLAdvancedForceErrorDisconnectViewer : public view_listener_t
class LLAdvancedHandleToggleHackedGodmode : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_toggle_hacked_godmode(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_toggle_hacked_godmode(NULL);
+ return true;
+ }
};
class LLAdvancedCheckToggleHackedGodmode : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- check_toggle_hacked_godmode(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ check_toggle_hacked_godmode(NULL);
+ return true;
+ }
};
class LLAdvancedEnableToggleHackedGodmode : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = enable_toggle_hacked_godmode(NULL);
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = enable_toggle_hacked_godmode(NULL);
+ return new_value;
+ }
};
#endif
@@ -2585,21 +2585,21 @@ class LLAdvancedEnableToggleHackedGodmode : public view_listener_t
class LLDevelopCheckLoggingLevel : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- U32 level = userdata.asInteger();
- return (static_cast<LLError::ELevel>(level) == LLError::getDefaultLevel());
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 level = userdata.asInteger();
+ return (static_cast<LLError::ELevel>(level) == LLError::getDefaultLevel());
+ }
};
class LLDevelopSetLoggingLevel : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- U32 level = userdata.asInteger();
- LLError::setDefaultLevel(static_cast<LLError::ELevel>(level));
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 level = userdata.asInteger();
+ LLError::setDefaultLevel(static_cast<LLError::ELevel>(level));
+ return true;
+ }
};
//////////////////
@@ -2609,100 +2609,100 @@ class LLDevelopSetLoggingLevel : public view_listener_t
// Admin > Object
class LLAdminForceTakeCopy : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- force_take_copy(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_take_copy(NULL);
+ return true;
+ }
};
class LLAdminHandleObjectOwnerSelf : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_object_owner_self(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_object_owner_self(NULL);
+ return true;
+ }
};
class LLAdminHandleObjectOwnerPermissive : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_object_owner_permissive(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_object_owner_permissive(NULL);
+ return true;
+ }
};
class LLAdminHandleForceDelete : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_force_delete(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_force_delete(NULL);
+ return true;
+ }
};
class LLAdminHandleObjectLock : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_object_lock(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_object_lock(NULL);
+ return true;
+ }
};
class LLAdminHandleObjectAssetIDs: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_object_asset_ids(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_object_asset_ids(NULL);
+ return true;
+ }
};
//Admin >Parcel
class LLAdminHandleForceParcelOwnerToMe: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_force_parcel_owner_to_me(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_force_parcel_owner_to_me(NULL);
+ return true;
+ }
};
class LLAdminHandleForceParcelToContent: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_force_parcel_to_content(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_force_parcel_to_content(NULL);
+ return true;
+ }
};
class LLAdminHandleClaimPublicLand: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_claim_public_land(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_claim_public_land(NULL);
+ return true;
+ }
};
// Admin > Region
class LLAdminHandleRegionDumpTempAssetData: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_region_dump_temp_asset_data(NULL);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_region_dump_temp_asset_data(NULL);
+ return true;
+ }
};
//Admin (Top Level)
class LLAdminOnSaveState: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLPanelRegionTools::onSaveState(NULL);
- return true;
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLPanelRegionTools::onSaveState(NULL);
+ return true;
}
};
@@ -2712,38 +2712,38 @@ class LLAdminOnSaveState: public view_listener_t
//-----------------------------------------------------------------------------
void cleanup_menus()
{
- delete gMenuParcelObserver;
- gMenuParcelObserver = NULL;
+ delete gMenuParcelObserver;
+ gMenuParcelObserver = NULL;
- delete gMenuAvatarSelf;
- gMenuAvatarSelf = NULL;
+ delete gMenuAvatarSelf;
+ gMenuAvatarSelf = NULL;
- delete gMenuAvatarOther;
- gMenuAvatarOther = NULL;
+ delete gMenuAvatarOther;
+ gMenuAvatarOther = NULL;
- delete gMenuObject;
- gMenuObject = NULL;
+ delete gMenuObject;
+ gMenuObject = NULL;
- delete gMenuAttachmentSelf;
- gMenuAttachmentSelf = NULL;
+ delete gMenuAttachmentSelf;
+ gMenuAttachmentSelf = NULL;
- delete gMenuAttachmentOther;
- gMenuAttachmentSelf = NULL;
+ delete gMenuAttachmentOther;
+ gMenuAttachmentSelf = NULL;
- delete gMenuLand;
- gMenuLand = NULL;
+ delete gMenuLand;
+ gMenuLand = NULL;
- delete gMenuMuteParticle;
- gMenuMuteParticle = NULL;
+ delete gMenuMuteParticle;
+ gMenuMuteParticle = NULL;
- delete gMenuBarView;
- gMenuBarView = NULL;
+ delete gMenuBarView;
+ gMenuBarView = NULL;
- delete gPopupMenuView;
- gPopupMenuView = NULL;
+ delete gPopupMenuView;
+ gPopupMenuView = NULL;
- delete gMenuHolder;
- gMenuHolder = NULL;
+ delete gMenuHolder;
+ gMenuHolder = NULL;
}
//-----------------------------------------------------------------------------
@@ -2752,40 +2752,40 @@ void cleanup_menus()
class LLObjectReportAbuse : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (objectp)
- {
- LLFloaterReporter::showFromObject(objectp->getID());
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (objectp)
+ {
+ LLFloaterReporter::showFromObject(objectp->getID());
+ }
+ return true;
+ }
};
// Enabled it you clicked an object
class LLObjectEnableReportAbuse : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0;
+ return new_value;
+ }
};
void handle_object_touch()
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return;
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object) return;
- LLPickInfo pick = LLToolPie::getInstance()->getPick();
+ LLPickInfo pick = LLToolPie::getInstance()->getPick();
- // *NOTE: Hope the packets arrive safely and in order or else
- // there will be some problems.
- // *TODO: Just fix this bad assumption.
- send_ObjectGrab_message(object, pick, LLVector3::zero);
- send_ObjectDeGrab_message(object, pick);
+ // *NOTE: Hope the packets arrive safely and in order or else
+ // there will be some problems.
+ // *TODO: Just fix this bad assumption.
+ send_ObjectGrab_message(object, pick, LLVector3::zero);
+ send_ObjectDeGrab_message(object, pick);
}
void handle_object_show_original()
@@ -2818,75 +2818,75 @@ void handle_object_show_original()
static void init_default_item_label(LLUICtrl* ctrl)
{
- const std::string& item_name = ctrl->getName();
- boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
- if (it == sDefaultItemLabels.end())
- {
- // *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value
- // (doesn't seem to matter much ATM).
- LLStringExplicit default_label = ctrl->getValue().asString();
- if (!default_label.empty())
- {
- sDefaultItemLabels.insert(std::pair<std::string, LLStringExplicit>(item_name, default_label));
- }
- }
+ const std::string& item_name = ctrl->getName();
+ boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
+ if (it == sDefaultItemLabels.end())
+ {
+ // *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value
+ // (doesn't seem to matter much ATM).
+ LLStringExplicit default_label = ctrl->getValue().asString();
+ if (!default_label.empty())
+ {
+ sDefaultItemLabels.insert(std::pair<std::string, LLStringExplicit>(item_name, default_label));
+ }
+ }
}
static LLStringExplicit get_default_item_label(const std::string& item_name)
{
- LLStringExplicit res("");
- boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
- if (it != sDefaultItemLabels.end())
- {
- res = it->second;
- }
+ LLStringExplicit res("");
+ boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
+ if (it != sDefaultItemLabels.end())
+ {
+ res = it->second;
+ }
- return res;
+ return res;
}
bool enable_object_touch(LLUICtrl* ctrl)
{
- bool new_value = false;
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (obj)
- {
- LLViewerObject* parent = (LLViewerObject*)obj->getParent();
- new_value = obj->flagHandleTouch() || (parent && parent->flagHandleTouch());
- }
+ bool new_value = false;
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (obj)
+ {
+ LLViewerObject* parent = (LLViewerObject*)obj->getParent();
+ new_value = obj->flagHandleTouch() || (parent && parent->flagHandleTouch());
+ }
- init_default_item_label(ctrl);
+ init_default_item_label(ctrl);
- // Update label based on the node touch name if available.
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
- if (node && node->mValid && !node->mTouchName.empty())
- {
- ctrl->setValue(node->mTouchName);
- }
- else
- {
- ctrl->setValue(get_default_item_label(ctrl->getName()));
- }
+ // Update label based on the node touch name if available.
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+ if (node && node->mValid && !node->mTouchName.empty())
+ {
+ ctrl->setValue(node->mTouchName);
+ }
+ else
+ {
+ ctrl->setValue(get_default_item_label(ctrl->getName()));
+ }
- return new_value;
+ return new_value;
};
//void label_touch(std::string& label, void*)
//{
-// LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-// if (node && node->mValid && !node->mTouchName.empty())
-// {
-// label.assign(node->mTouchName);
-// }
-// else
-// {
-// label.assign("Touch");
-// }
+// LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+// if (node && node->mValid && !node->mTouchName.empty())
+// {
+// label.assign(node->mTouchName);
+// }
+// else
+// {
+// label.assign("Touch");
+// }
//}
void handle_object_open()
{
- LLFloaterReg::showInstance("openobject");
+ LLFloaterReg::showInstance("openobject");
}
bool enable_object_inspect()
@@ -2941,67 +2941,67 @@ bool enable_object_edit_gltf_material()
bool enable_object_open()
{
- // Look for contents in root object, which is all the LLFloaterOpenObject
- // understands.
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!obj) return false;
+ // Look for contents in root object, which is all the LLFloaterOpenObject
+ // understands.
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!obj) return false;
- LLViewerObject* root = obj->getRootEdit();
- if (!root) return false;
+ LLViewerObject* root = obj->getRootEdit();
+ if (!root) return false;
- return root->allowOpen();
+ return root->allowOpen();
}
class LLViewJoystickFlycam : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_toggle_flycam();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_toggle_flycam();
+ return true;
+ }
};
class LLViewCheckJoystickFlycam : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera();
+ return new_value;
+ }
};
void handle_toggle_flycam()
{
- LLViewerJoystick::getInstance()->toggleFlycam();
+ LLViewerJoystick::getInstance()->toggleFlycam();
}
class LLObjectBuild : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") )
- {
- // zoom in if we're looking at the avatar
- gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
- gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
- gAgentCamera.cameraZoomIn(0.666f);
- gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
- gViewerWindow->moveCursorToCenter();
- }
- else if ( gSavedSettings.getBOOL("EditCameraMovement") )
- {
- gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
- gViewerWindow->moveCursorToCenter();
- }
-
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
-
- // Could be first use
- //LLFirstUse::useBuild();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") )
+ {
+ // zoom in if we're looking at the avatar
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+ gAgentCamera.cameraZoomIn(0.666f);
+ gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
+ gViewerWindow->moveCursorToCenter();
+ }
+ else if ( gSavedSettings.getBOOL("EditCameraMovement") )
+ {
+ gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+ gViewerWindow->moveCursorToCenter();
+ }
+
+ LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
+
+ // Could be first use
+ //LLFirstUse::useBuild();
+ return true;
+ }
};
void update_camera()
@@ -3040,17 +3040,17 @@ void handle_object_edit()
{
update_camera();
- LLFloaterReg::showInstance("build");
-
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() );
-
- LLViewerJoystick::getInstance()->moveObjects(true);
- LLViewerJoystick::getInstance()->setNeedsReset(true);
-
- // Could be first use
- //LLFirstUse::useBuild();
- return;
+ LLFloaterReg::showInstance("build");
+
+ LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+ gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() );
+
+ LLViewerJoystick::getInstance()->moveObjects(true);
+ LLViewerJoystick::getInstance()->setNeedsReset(true);
+
+ // Could be first use
+ //LLFirstUse::useBuild();
+ return;
}
void handle_object_edit_gltf_material()
@@ -3072,68 +3072,68 @@ void handle_object_edit_gltf_material()
void handle_attachment_edit(const LLUUID& inv_item_id)
{
- if (isAgentAvatarValid())
- {
- if (LLViewerObject* attached_obj = gAgentAvatarp->getWornAttachment(inv_item_id))
- {
- LLSelectMgr::getInstance()->deselectAll();
- LLSelectMgr::getInstance()->selectObjectAndFamily(attached_obj);
+ if (isAgentAvatarValid())
+ {
+ if (LLViewerObject* attached_obj = gAgentAvatarp->getWornAttachment(inv_item_id))
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ LLSelectMgr::getInstance()->selectObjectAndFamily(attached_obj);
- handle_object_edit();
- }
- }
+ handle_object_edit();
+ }
+ }
}
void handle_attachment_touch(const LLUUID& inv_item_id)
{
- if ( (isAgentAvatarValid()) && (enable_attachment_touch(inv_item_id)) )
- {
- if (LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id)))
- {
- LLSelectMgr::getInstance()->deselectAll();
-
- LLObjectSelectionHandle sel = LLSelectMgr::getInstance()->selectObjectAndFamily(attach_obj);
- if (!LLToolMgr::getInstance()->inBuildMode())
- {
- struct SetTransient : public LLSelectedNodeFunctor
- {
- bool apply(LLSelectNode* node)
- {
- node->setTransient(TRUE);
- return true;
- }
- } f;
- sel->applyToNodes(&f);
- }
-
- handle_object_touch();
- }
- }
+ if ( (isAgentAvatarValid()) && (enable_attachment_touch(inv_item_id)) )
+ {
+ if (LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id)))
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+
+ LLObjectSelectionHandle sel = LLSelectMgr::getInstance()->selectObjectAndFamily(attach_obj);
+ if (!LLToolMgr::getInstance()->inBuildMode())
+ {
+ struct SetTransient : public LLSelectedNodeFunctor
+ {
+ bool apply(LLSelectNode* node)
+ {
+ node->setTransient(TRUE);
+ return true;
+ }
+ } f;
+ sel->applyToNodes(&f);
+ }
+
+ handle_object_touch();
+ }
+ }
}
bool enable_attachment_touch(const LLUUID& inv_item_id)
{
- if (isAgentAvatarValid())
- {
- const LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id));
- return (attach_obj) && (attach_obj->flagHandleTouch());
- }
- return false;
+ if (isAgentAvatarValid())
+ {
+ const LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id));
+ return (attach_obj) && (attach_obj->flagHandleTouch());
+ }
+ return false;
}
void handle_object_inspect()
{
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- LLViewerObject* selected_objectp = selection->getFirstRootObject();
- if (selected_objectp)
- {
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ LLViewerObject* selected_objectp = selection->getFirstRootObject();
+ if (selected_objectp)
+ {
LLFloaterReg::showInstance("task_properties");
- }
-
- /*
- // Old floater properties
- LLFloaterReg::showInstance("inspect", LLSD());
- */
+ }
+
+ /*
+ // Old floater properties
+ LLFloaterReg::showInstance("inspect", LLSD());
+ */
}
//---------------------------------------------------------------------------
@@ -3141,133 +3141,133 @@ void handle_object_inspect()
//---------------------------------------------------------------------------
class LLLandBuild : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLViewerParcelMgr::getInstance()->deselectLand();
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerParcelMgr::getInstance()->deselectLand();
- if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") )
- {
- // zoom in if we're looking at the avatar
- gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
- gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
- gAgentCamera.cameraZoomIn(0.666f);
- gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
- gViewerWindow->moveCursorToCenter();
- }
- else if ( gSavedSettings.getBOOL("EditCameraMovement") )
- {
- // otherwise just move focus
- gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
- gViewerWindow->moveCursorToCenter();
- }
+ if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") )
+ {
+ // zoom in if we're looking at the avatar
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+ gAgentCamera.cameraZoomIn(0.666f);
+ gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
+ gViewerWindow->moveCursorToCenter();
+ }
+ else if ( gSavedSettings.getBOOL("EditCameraMovement") )
+ {
+ // otherwise just move focus
+ gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+ gViewerWindow->moveCursorToCenter();
+ }
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
+ LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
- // Could be first use
- //LLFirstUse::useBuild();
- return true;
- }
+ // Could be first use
+ //LLFirstUse::useBuild();
+ return true;
+ }
};
class LLLandBuyPass : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLPanelLandGeneral::onClickBuyPass((void *)FALSE);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLPanelLandGeneral::onClickBuyPass((void *)FALSE);
+ return true;
+ }
};
class LLLandEnableBuyPass : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLPanelLandGeneral::enableBuyPass(NULL);
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLPanelLandGeneral::enableBuyPass(NULL);
+ return new_value;
+ }
};
// BUG: Should really check if CLICK POINT is in a parcel where you can build.
BOOL enable_land_build(void*)
{
- if (gAgent.isGodlike()) return TRUE;
- if (gAgent.inPrelude()) return FALSE;
+ if (gAgent.isGodlike()) return TRUE;
+ if (gAgent.inPrelude()) return FALSE;
- BOOL can_build = FALSE;
- LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if (agent_parcel)
- {
- can_build = agent_parcel->getAllowModify();
- }
- return can_build;
+ BOOL can_build = FALSE;
+ LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (agent_parcel)
+ {
+ can_build = agent_parcel->getAllowModify();
+ }
+ return can_build;
}
// BUG: Should really check if OBJECT is in a parcel where you can build.
BOOL enable_object_build(void*)
{
- if (gAgent.isGodlike()) return TRUE;
- if (gAgent.inPrelude()) return FALSE;
+ if (gAgent.isGodlike()) return TRUE;
+ if (gAgent.inPrelude()) return FALSE;
- BOOL can_build = FALSE;
- LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if (agent_parcel)
- {
- can_build = agent_parcel->getAllowModify();
- }
- return can_build;
+ BOOL can_build = FALSE;
+ LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (agent_parcel)
+ {
+ can_build = agent_parcel->getAllowModify();
+ }
+ return can_build;
}
bool enable_object_edit()
{
- if (!isAgentAvatarValid()) return false;
-
- // *HACK: The new "prelude" Help Islands have a build sandbox area,
- // so users need the Edit and Create pie menu options when they are
- // there. Eventually this needs to be replaced with code that only
- // lets you edit objects if you have permission to do so (edit perms,
- // group edit, god). See also lltoolbar.cpp. JC
- bool enable = false;
- if (gAgent.inPrelude())
- {
- enable = LLViewerParcelMgr::getInstance()->allowAgentBuild()
- || LLSelectMgr::getInstance()->getSelection()->isAttachment();
- }
- else if (LLSelectMgr::getInstance()->selectGetAllValidAndObjectsFound())
- {
- enable = true;
- }
-
- return enable;
+ if (!isAgentAvatarValid()) return false;
+
+ // *HACK: The new "prelude" Help Islands have a build sandbox area,
+ // so users need the Edit and Create pie menu options when they are
+ // there. Eventually this needs to be replaced with code that only
+ // lets you edit objects if you have permission to do so (edit perms,
+ // group edit, god). See also lltoolbar.cpp. JC
+ bool enable = false;
+ if (gAgent.inPrelude())
+ {
+ enable = LLViewerParcelMgr::getInstance()->allowAgentBuild()
+ || LLSelectMgr::getInstance()->getSelection()->isAttachment();
+ }
+ else if (LLSelectMgr::getInstance()->selectGetAllValidAndObjectsFound())
+ {
+ enable = true;
+ }
+
+ return enable;
}
bool enable_mute_particle()
{
- const LLPickInfo& pick = LLToolPie::getInstance()->getPick();
+ const LLPickInfo& pick = LLToolPie::getInstance()->getPick();
- return pick.mParticleOwnerID != LLUUID::null && pick.mParticleOwnerID != gAgent.getID();
+ return pick.mParticleOwnerID != LLUUID::null && pick.mParticleOwnerID != gAgent.getID();
}
// mutually exclusive - show either edit option or build in menu
bool enable_object_build()
{
- return !enable_object_edit();
+ return !enable_object_edit();
}
bool enable_object_select_in_pathfinding_linksets()
{
- return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetEditableLinksets();
+ return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetEditableLinksets();
}
bool visible_object_select_in_pathfinding_linksets()
{
- return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion();
+ return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion();
}
bool enable_object_select_in_pathfinding_characters()
{
- return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters();
+ return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters();
}
bool enable_os_exception()
@@ -3281,40 +3281,40 @@ bool enable_os_exception()
class LLSelfRemoveAllAttachments : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLAppearanceMgr::instance().removeAllAttachmentsFromAvatar();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLAppearanceMgr::instance().removeAllAttachmentsFromAvatar();
+ return true;
+ }
};
class LLSelfEnableRemoveAllAttachments : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = false;
- if (isAgentAvatarValid())
- {
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
- iter != gAgentAvatarp->mAttachmentPoints.end(); )
- {
- LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getNumObjects() > 0)
- {
- new_value = true;
- break;
- }
- }
- }
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = false;
+ if (isAgentAvatarValid())
+ {
+ for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
+ iter != gAgentAvatarp->mAttachmentPoints.end(); )
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ if (attachment->getNumObjects() > 0)
+ {
+ new_value = true;
+ break;
+ }
+ }
+ }
+ return new_value;
+ }
};
BOOL enable_has_attachments(void*)
{
- return FALSE;
+ return FALSE;
}
//---------------------------------------------------------------------------
@@ -3322,229 +3322,229 @@ BOOL enable_has_attachments(void*)
//---------------------------------------------------------------------------
//void handle_follow(void *userdata)
//{
-// // follow a given avatar by ID
-// LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-// if (objectp)
-// {
-// gAgent.startFollowPilot(objectp->getID());
-// }
+// // follow a given avatar by ID
+// LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+// if (objectp)
+// {
+// gAgent.startFollowPilot(objectp->getID());
+// }
//}
bool enable_object_mute()
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return false;
-
- LLVOAvatar* avatar = find_avatar_from_object(object);
- if (avatar)
- {
- // It's an avatar
- LLNameValue *lastname = avatar->getNVPair("LastName");
- bool is_linden =
- lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
- bool is_self = avatar->isSelf();
- return !is_linden && !is_self;
- }
- else
- {
- // Just a regular object
- return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) &&
- !LLMuteList::getInstance()->isMuted(object->getID());
- }
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object) return false;
+
+ LLVOAvatar* avatar = find_avatar_from_object(object);
+ if (avatar)
+ {
+ // It's an avatar
+ LLNameValue *lastname = avatar->getNVPair("LastName");
+ bool is_linden =
+ lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
+ bool is_self = avatar->isSelf();
+ return !is_linden && !is_self;
+ }
+ else
+ {
+ // Just a regular object
+ return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) &&
+ !LLMuteList::getInstance()->isMuted(object->getID());
+ }
}
bool enable_object_unmute()
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return false;
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object) return false;
- LLVOAvatar* avatar = find_avatar_from_object(object);
- if (avatar)
- {
- // It's an avatar
- LLNameValue *lastname = avatar->getNVPair("LastName");
- bool is_linden =
- lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
- bool is_self = avatar->isSelf();
- return !is_linden && !is_self;
- }
- else
- {
- // Just a regular object
- return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) &&
- LLMuteList::getInstance()->isMuted(object->getID());;
- }
+ LLVOAvatar* avatar = find_avatar_from_object(object);
+ if (avatar)
+ {
+ // It's an avatar
+ LLNameValue *lastname = avatar->getNVPair("LastName");
+ bool is_linden =
+ lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
+ bool is_self = avatar->isSelf();
+ return !is_linden && !is_self;
+ }
+ else
+ {
+ // Just a regular object
+ return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) &&
+ LLMuteList::getInstance()->isMuted(object->getID());;
+ }
}
// 0 = normal, 1 = always, 2 = never
class LLAvatarCheckImpostorMode : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return false;
-
- LLVOAvatar* avatar = find_avatar_from_object(object);
- if (!avatar) return false;
-
- U32 mode = userdata.asInteger();
- switch (mode)
- {
- case 0:
- return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_RENDER_NORMALLY);
- case 1:
- return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_DO_NOT_RENDER);
- case 2:
- return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER);
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object) return false;
+
+ LLVOAvatar* avatar = find_avatar_from_object(object);
+ if (!avatar) return false;
+
+ U32 mode = userdata.asInteger();
+ switch (mode)
+ {
+ case 0:
+ return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_RENDER_NORMALLY);
+ case 1:
+ return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_DO_NOT_RENDER);
+ case 2:
+ return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER);
case 4:
return (avatar->getVisualMuteSettings() != LLVOAvatar::AV_RENDER_NORMALLY);
- default:
- return false;
- }
- } // handleEvent()
+ default:
+ return false;
+ }
+ } // handleEvent()
};
// 0 = normal, 1 = always, 2 = never
class LLAvatarSetImpostorMode : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return false;
-
- LLVOAvatar* avatar = find_avatar_from_object(object);
- if (!avatar) return false;
-
- U32 mode = userdata.asInteger();
- switch (mode)
- {
- case 0:
- avatar->setVisualMuteSettings(LLVOAvatar::AV_RENDER_NORMALLY);
- break;
- case 1:
- avatar->setVisualMuteSettings(LLVOAvatar::AV_DO_NOT_RENDER);
- break;
- case 2:
- avatar->setVisualMuteSettings(LLVOAvatar::AV_ALWAYS_RENDER);
- break;
- default:
- return false;
- }
-
- LLVOAvatar::cullAvatarsByPixelArea();
- return true;
- } // handleEvent()
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object) return false;
+
+ LLVOAvatar* avatar = find_avatar_from_object(object);
+ if (!avatar) return false;
+
+ U32 mode = userdata.asInteger();
+ switch (mode)
+ {
+ case 0:
+ avatar->setVisualMuteSettings(LLVOAvatar::AV_RENDER_NORMALLY);
+ break;
+ case 1:
+ avatar->setVisualMuteSettings(LLVOAvatar::AV_DO_NOT_RENDER);
+ break;
+ case 2:
+ avatar->setVisualMuteSettings(LLVOAvatar::AV_ALWAYS_RENDER);
+ break;
+ default:
+ return false;
+ }
+
+ LLVOAvatar::cullAvatarsByPixelArea();
+ return true;
+ } // handleEvent()
};
class LLObjectMute : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return true;
-
- LLUUID id;
- std::string name;
- LLMute::EType type;
- LLVOAvatar* avatar = find_avatar_from_object(object);
- if (avatar)
- {
- avatar->mNeedsImpostorUpdate = TRUE;
- avatar->mLastImpostorUpdateReason = 9;
-
- id = avatar->getID();
-
- LLNameValue *firstname = avatar->getNVPair("FirstName");
- LLNameValue *lastname = avatar->getNVPair("LastName");
- if (firstname && lastname)
- {
- name = LLCacheName::buildFullName(
- firstname->getString(), lastname->getString());
- }
-
- type = LLMute::AGENT;
- }
- else
- {
- // it's an object
- id = object->getID();
-
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
- if (node)
- {
- name = node->mName;
- }
-
- type = LLMute::OBJECT;
- }
-
- LLMute mute(id, name, type);
- if (LLMuteList::getInstance()->isMuted(mute.mID))
- {
- LLMuteList::getInstance()->remove(mute);
- }
- else
- {
- LLMuteList::getInstance()->add(mute);
- LLPanelBlockedList::showPanelAndSelect(mute.mID);
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object) return true;
+
+ LLUUID id;
+ std::string name;
+ LLMute::EType type;
+ LLVOAvatar* avatar = find_avatar_from_object(object);
+ if (avatar)
+ {
+ avatar->mNeedsImpostorUpdate = TRUE;
+ avatar->mLastImpostorUpdateReason = 9;
+
+ id = avatar->getID();
+
+ LLNameValue *firstname = avatar->getNVPair("FirstName");
+ LLNameValue *lastname = avatar->getNVPair("LastName");
+ if (firstname && lastname)
+ {
+ name = LLCacheName::buildFullName(
+ firstname->getString(), lastname->getString());
+ }
+
+ type = LLMute::AGENT;
+ }
+ else
+ {
+ // it's an object
+ id = object->getID();
+
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+ if (node)
+ {
+ name = node->mName;
+ }
+
+ type = LLMute::OBJECT;
+ }
+
+ LLMute mute(id, name, type);
+ if (LLMuteList::getInstance()->isMuted(mute.mID))
+ {
+ LLMuteList::getInstance()->remove(mute);
+ }
+ else
+ {
+ LLMuteList::getInstance()->add(mute);
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
+ }
+
+ return true;
+ }
};
bool handle_go_to()
{
- // try simulator autopilot
- std::vector<std::string> strings;
- std::string val;
- LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
- val = llformat("%g", pos.mdV[VX]);
- strings.push_back(val);
- val = llformat("%g", pos.mdV[VY]);
- strings.push_back(val);
- val = llformat("%g", pos.mdV[VZ]);
- strings.push_back(val);
- send_generic_message("autopilot", strings);
-
- LLViewerParcelMgr::getInstance()->deselectLand();
-
- if (isAgentAvatarValid() && !gSavedSettings.getBOOL("AutoPilotLocksCamera"))
- {
- gAgentCamera.setFocusGlobal(gAgentCamera.getFocusTargetGlobal(), gAgentAvatarp->getID());
- }
- else
- {
- // Snap camera back to behind avatar
- gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE);
- }
-
- // Could be first use
- //LLFirstUse::useGoTo();
- return true;
+ // try simulator autopilot
+ std::vector<std::string> strings;
+ std::string val;
+ LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
+ val = llformat("%g", pos.mdV[VX]);
+ strings.push_back(val);
+ val = llformat("%g", pos.mdV[VY]);
+ strings.push_back(val);
+ val = llformat("%g", pos.mdV[VZ]);
+ strings.push_back(val);
+ send_generic_message("autopilot", strings);
+
+ LLViewerParcelMgr::getInstance()->deselectLand();
+
+ if (isAgentAvatarValid() && !gSavedSettings.getBOOL("AutoPilotLocksCamera"))
+ {
+ gAgentCamera.setFocusGlobal(gAgentCamera.getFocusTargetGlobal(), gAgentAvatarp->getID());
+ }
+ else
+ {
+ // Snap camera back to behind avatar
+ gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE);
+ }
+
+ // Could be first use
+ //LLFirstUse::useGoTo();
+ return true;
}
class LLGoToObject : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return handle_go_to();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return handle_go_to();
+ }
};
class LLAvatarReportAbuse : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if(avatar)
- {
- LLFloaterReporter::showFromObject(avatar->getID());
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ LLFloaterReporter::showFromObject(avatar->getID());
+ }
+ return true;
+ }
};
@@ -3553,230 +3553,230 @@ class LLAvatarReportAbuse : public view_listener_t
//---------------------------------------------------------------------------
bool callback_freeze(const LLSD& notification, const LLSD& response)
{
- LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
- if (0 == option || 1 == option)
- {
- U32 flags = 0x0;
- if (1 == option)
- {
- // unfreeze
- flags |= 0x1;
- }
-
- LLMessageSystem* msg = gMessageSystem;
- LLViewerObject* avatar = gObjectList.findObject(avatar_id);
-
- if (avatar)
- {
- msg->newMessage("FreezeUser");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->nextBlock("Data");
- msg->addUUID("TargetID", avatar_id );
- msg->addU32("Flags", flags );
- msg->sendReliable( avatar->getRegion()->getHost() );
- }
- }
- return false;
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ if (0 == option || 1 == option)
+ {
+ U32 flags = 0x0;
+ if (1 == option)
+ {
+ // unfreeze
+ flags |= 0x1;
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+ LLViewerObject* avatar = gObjectList.findObject(avatar_id);
+
+ if (avatar)
+ {
+ msg->newMessage("FreezeUser");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("Data");
+ msg->addUUID("TargetID", avatar_id );
+ msg->addU32("Flags", flags );
+ msg->sendReliable( avatar->getRegion()->getHost() );
+ }
+ }
+ return false;
}
void handle_avatar_freeze(const LLSD& avatar_id)
{
- // Use avatar_id if available, otherwise default to right-click avatar
- LLVOAvatar* avatar = NULL;
- if (avatar_id.asUUID().notNull())
- {
- avatar = find_avatar_from_object(avatar_id.asUUID());
- }
- else
- {
- avatar = find_avatar_from_object(
- LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
- }
-
- if( avatar )
- {
- std::string fullname = avatar->getFullname();
- LLSD payload;
- payload["avatar_id"] = avatar->getID();
-
- if (!fullname.empty())
- {
- LLSD args;
- args["AVATAR_NAME"] = fullname;
- LLNotificationsUtil::add("FreezeAvatarFullname",
- args,
- payload,
- callback_freeze);
- }
- else
- {
- LLNotificationsUtil::add("FreezeAvatar",
- LLSD(),
- payload,
- callback_freeze);
- }
- }
+ // Use avatar_id if available, otherwise default to right-click avatar
+ LLVOAvatar* avatar = NULL;
+ if (avatar_id.asUUID().notNull())
+ {
+ avatar = find_avatar_from_object(avatar_id.asUUID());
+ }
+ else
+ {
+ avatar = find_avatar_from_object(
+ LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ }
+
+ if( avatar )
+ {
+ std::string fullname = avatar->getFullname();
+ LLSD payload;
+ payload["avatar_id"] = avatar->getID();
+
+ if (!fullname.empty())
+ {
+ LLSD args;
+ args["AVATAR_NAME"] = fullname;
+ LLNotificationsUtil::add("FreezeAvatarFullname",
+ args,
+ payload,
+ callback_freeze);
+ }
+ else
+ {
+ LLNotificationsUtil::add("FreezeAvatar",
+ LLSD(),
+ payload,
+ callback_freeze);
+ }
+ }
}
class LLAvatarVisibleDebug : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return gAgent.isGodlike();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return gAgent.isGodlike();
+ }
};
class LLAvatarDebug : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if( avatar )
- {
- if (avatar->isSelf())
- {
- ((LLVOAvatarSelf *)avatar)->dumpLocalTextures();
- }
- LL_INFOS() << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << LL_ENDL;
- std::vector<std::string> strings;
- strings.push_back(avatar->getID().asString());
- LLUUID invoice;
- send_generic_message("dumptempassetdata", strings, invoice);
- LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) );
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if( avatar )
+ {
+ if (avatar->isSelf())
+ {
+ ((LLVOAvatarSelf *)avatar)->dumpLocalTextures();
+ }
+ LL_INFOS() << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << LL_ENDL;
+ std::vector<std::string> strings;
+ strings.push_back(avatar->getID().asString());
+ LLUUID invoice;
+ send_generic_message("dumptempassetdata", strings, invoice);
+ LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) );
+ }
+ return true;
+ }
};
bool callback_eject(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (2 == option)
- {
- // Cancel button.
- return false;
- }
- LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
- bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean();
-
- if (0 == option)
- {
- // Eject button
- LLMessageSystem* msg = gMessageSystem;
- LLViewerObject* avatar = gObjectList.findObject(avatar_id);
-
- if (avatar)
- {
- U32 flags = 0x0;
- msg->newMessage("EjectUser");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID() );
- msg->addUUID("SessionID", gAgent.getSessionID() );
- msg->nextBlock("Data");
- msg->addUUID("TargetID", avatar_id );
- msg->addU32("Flags", flags );
- msg->sendReliable( avatar->getRegion()->getHost() );
- }
- }
- else if (ban_enabled)
- {
- // This is tricky. It is similar to say if it is not an 'Eject' button,
- // and it is also not an 'Cancle' button, and ban_enabled==ture,
- // it should be the 'Eject and Ban' button.
- LLMessageSystem* msg = gMessageSystem;
- LLViewerObject* avatar = gObjectList.findObject(avatar_id);
-
- if (avatar)
- {
- U32 flags = 0x1;
- msg->newMessage("EjectUser");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID() );
- msg->addUUID("SessionID", gAgent.getSessionID() );
- msg->nextBlock("Data");
- msg->addUUID("TargetID", avatar_id );
- msg->addU32("Flags", flags );
- msg->sendReliable( avatar->getRegion()->getHost() );
- }
- }
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (2 == option)
+ {
+ // Cancel button.
+ return false;
+ }
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean();
+
+ if (0 == option)
+ {
+ // Eject button
+ LLMessageSystem* msg = gMessageSystem;
+ LLViewerObject* avatar = gObjectList.findObject(avatar_id);
+
+ if (avatar)
+ {
+ U32 flags = 0x0;
+ msg->newMessage("EjectUser");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID() );
+ msg->addUUID("SessionID", gAgent.getSessionID() );
+ msg->nextBlock("Data");
+ msg->addUUID("TargetID", avatar_id );
+ msg->addU32("Flags", flags );
+ msg->sendReliable( avatar->getRegion()->getHost() );
+ }
+ }
+ else if (ban_enabled)
+ {
+ // This is tricky. It is similar to say if it is not an 'Eject' button,
+ // and it is also not an 'Cancle' button, and ban_enabled==ture,
+ // it should be the 'Eject and Ban' button.
+ LLMessageSystem* msg = gMessageSystem;
+ LLViewerObject* avatar = gObjectList.findObject(avatar_id);
+
+ if (avatar)
+ {
+ U32 flags = 0x1;
+ msg->newMessage("EjectUser");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID() );
+ msg->addUUID("SessionID", gAgent.getSessionID() );
+ msg->nextBlock("Data");
+ msg->addUUID("TargetID", avatar_id );
+ msg->addU32("Flags", flags );
+ msg->sendReliable( avatar->getRegion()->getHost() );
+ }
+ }
+ return false;
}
void handle_avatar_eject(const LLSD& avatar_id)
{
- // Use avatar_id if available, otherwise default to right-click avatar
- LLVOAvatar* avatar = NULL;
- if (avatar_id.asUUID().notNull())
- {
- avatar = find_avatar_from_object(avatar_id.asUUID());
- }
- else
- {
- avatar = find_avatar_from_object(
- LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
- }
-
- if( avatar )
- {
- LLSD payload;
- payload["avatar_id"] = avatar->getID();
- std::string fullname = avatar->getFullname();
-
- const LLVector3d& pos = avatar->getPositionGlobal();
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel();
-
- if (LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED))
- {
+ // Use avatar_id if available, otherwise default to right-click avatar
+ LLVOAvatar* avatar = NULL;
+ if (avatar_id.asUUID().notNull())
+ {
+ avatar = find_avatar_from_object(avatar_id.asUUID());
+ }
+ else
+ {
+ avatar = find_avatar_from_object(
+ LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ }
+
+ if( avatar )
+ {
+ LLSD payload;
+ payload["avatar_id"] = avatar->getID();
+ std::string fullname = avatar->getFullname();
+
+ const LLVector3d& pos = avatar->getPositionGlobal();
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel();
+
+ if (LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED))
+ {
payload["ban_enabled"] = true;
- if (!fullname.empty())
- {
- LLSD args;
- args["AVATAR_NAME"] = fullname;
- LLNotificationsUtil::add("EjectAvatarFullname",
- args,
- payload,
- callback_eject);
- }
- else
- {
- LLNotificationsUtil::add("EjectAvatarFullname",
- LLSD(),
- payload,
- callback_eject);
- }
- }
- else
- {
+ if (!fullname.empty())
+ {
+ LLSD args;
+ args["AVATAR_NAME"] = fullname;
+ LLNotificationsUtil::add("EjectAvatarFullname",
+ args,
+ payload,
+ callback_eject);
+ }
+ else
+ {
+ LLNotificationsUtil::add("EjectAvatarFullname",
+ LLSD(),
+ payload,
+ callback_eject);
+ }
+ }
+ else
+ {
payload["ban_enabled"] = false;
- if (!fullname.empty())
- {
- LLSD args;
- args["AVATAR_NAME"] = fullname;
- LLNotificationsUtil::add("EjectAvatarFullnameNoBan",
- args,
- payload,
- callback_eject);
- }
- else
- {
- LLNotificationsUtil::add("EjectAvatarNoBan",
- LLSD(),
- payload,
- callback_eject);
- }
- }
- }
+ if (!fullname.empty())
+ {
+ LLSD args;
+ args["AVATAR_NAME"] = fullname;
+ LLNotificationsUtil::add("EjectAvatarFullnameNoBan",
+ args,
+ payload,
+ callback_eject);
+ }
+ else
+ {
+ LLNotificationsUtil::add("EjectAvatarNoBan",
+ LLSD(),
+ payload,
+ callback_eject);
+ }
+ }
+ }
}
bool my_profile_visible()
{
- LLFloater* floaterp = LLAvatarActions::getProfileFloater(gAgentID);
- return floaterp && floaterp->isInVisibleChain();
+ LLFloater* floaterp = LLAvatarActions::getProfileFloater(gAgentID);
+ return floaterp && floaterp->isInVisibleChain();
}
bool picks_tab_visible()
@@ -3786,192 +3786,192 @@ bool picks_tab_visible()
bool enable_freeze_eject(const LLSD& avatar_id)
{
- // Use avatar_id if available, otherwise default to right-click avatar
- LLVOAvatar* avatar = NULL;
- if (avatar_id.asUUID().notNull())
- {
- avatar = find_avatar_from_object(avatar_id.asUUID());
- }
- else
- {
- avatar = find_avatar_from_object(
- LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
- }
- if (!avatar) return false;
-
- // Gods can always freeze
- if (gAgent.isGodlike()) return true;
-
- // Estate owners / managers can freeze
- // Parcel owners can also freeze
- const LLVector3& pos = avatar->getPositionRegion();
- const LLVector3d& pos_global = avatar->getPositionGlobal();
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel();
- LLViewerRegion* region = avatar->getRegion();
- if (!region) return false;
-
- bool new_value = region->isOwnedSelf(pos);
- if (!new_value || region->isOwnedGroup(pos))
- {
- new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN);
- }
- return new_value;
+ // Use avatar_id if available, otherwise default to right-click avatar
+ LLVOAvatar* avatar = NULL;
+ if (avatar_id.asUUID().notNull())
+ {
+ avatar = find_avatar_from_object(avatar_id.asUUID());
+ }
+ else
+ {
+ avatar = find_avatar_from_object(
+ LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ }
+ if (!avatar) return false;
+
+ // Gods can always freeze
+ if (gAgent.isGodlike()) return true;
+
+ // Estate owners / managers can freeze
+ // Parcel owners can also freeze
+ const LLVector3& pos = avatar->getPositionRegion();
+ const LLVector3d& pos_global = avatar->getPositionGlobal();
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel();
+ LLViewerRegion* region = avatar->getRegion();
+ if (!region) return false;
+
+ bool new_value = region->isOwnedSelf(pos);
+ if (!new_value || region->isOwnedGroup(pos))
+ {
+ new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN);
+ }
+ return new_value;
}
bool callback_leave_group(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option == 0)
- {
- LLMessageSystem *msg = gMessageSystem;
-
- msg->newMessageFast(_PREHASH_LeaveGroupRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_GroupData);
- msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() );
- gAgent.sendReliableMessage();
- }
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ LLMessageSystem *msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_LeaveGroupRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_GroupData);
+ msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() );
+ gAgent.sendReliableMessage();
+ }
+ return false;
}
void append_aggregate(std::string& string, const LLAggregatePermissions& ag_perm, PermissionBit bit, const char* txt)
{
- LLAggregatePermissions::EValue val = ag_perm.getValue(bit);
- std::string buffer;
- switch(val)
- {
- case LLAggregatePermissions::AP_NONE:
- buffer = llformat( "* %s None\n", txt);
- break;
- case LLAggregatePermissions::AP_SOME:
- buffer = llformat( "* %s Some\n", txt);
- break;
- case LLAggregatePermissions::AP_ALL:
- buffer = llformat( "* %s All\n", txt);
- break;
- case LLAggregatePermissions::AP_EMPTY:
- default:
- break;
- }
- string.append(buffer);
+ LLAggregatePermissions::EValue val = ag_perm.getValue(bit);
+ std::string buffer;
+ switch(val)
+ {
+ case LLAggregatePermissions::AP_NONE:
+ buffer = llformat( "* %s None\n", txt);
+ break;
+ case LLAggregatePermissions::AP_SOME:
+ buffer = llformat( "* %s Some\n", txt);
+ break;
+ case LLAggregatePermissions::AP_ALL:
+ buffer = llformat( "* %s All\n", txt);
+ break;
+ case LLAggregatePermissions::AP_EMPTY:
+ default:
+ break;
+ }
+ string.append(buffer);
}
bool enable_buy_object()
{
// In order to buy, there must only be 1 purchaseable object in
// the selection manager.
- if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false;
+ if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false;
LLViewerObject* obj = NULL;
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
- if(node)
+ if(node)
{
obj = node->getObject();
if(!obj) return false;
- if( for_sale_selection(node) )
- {
- // *NOTE: Is this needed? This checks to see if anyone owns the
- // object, dating back to when we had "public" objects owned by
- // no one. JC
- if(obj->permAnyOwner()) return true;
- }
+ if( for_sale_selection(node) )
+ {
+ // *NOTE: Is this needed? This checks to see if anyone owns the
+ // object, dating back to when we had "public" objects owned by
+ // no one. JC
+ if(obj->permAnyOwner()) return true;
+ }
}
- return false;
+ return false;
}
// Note: This will only work if the selected object's data has been
// received by the viewer and cached in the selection manager.
void handle_buy_object(LLSaleInfo sale_info)
{
- if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
- {
- LLNotificationsUtil::add("UnableToBuyWhileDownloading");
- return;
- }
+ if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
+ {
+ LLNotificationsUtil::add("UnableToBuyWhileDownloading");
+ return;
+ }
- LLUUID owner_id;
- std::string owner_name;
- BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
- if (!owners_identical)
- {
- LLNotificationsUtil::add("CannotBuyObjectsFromDifferentOwners");
- return;
- }
+ LLUUID owner_id;
+ std::string owner_name;
+ BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
+ if (!owners_identical)
+ {
+ LLNotificationsUtil::add("CannotBuyObjectsFromDifferentOwners");
+ return;
+ }
- LLPermissions perm;
- BOOL valid = LLSelectMgr::getInstance()->selectGetPermissions(perm);
- LLAggregatePermissions ag_perm;
- valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm);
- if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID()))
- {
- LLNotificationsUtil::add("ObjectNotForSale");
- return;
- }
+ LLPermissions perm;
+ BOOL valid = LLSelectMgr::getInstance()->selectGetPermissions(perm);
+ LLAggregatePermissions ag_perm;
+ valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm);
+ if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID()))
+ {
+ LLNotificationsUtil::add("ObjectNotForSale");
+ return;
+ }
- LLFloaterBuy::show(sale_info);
+ LLFloaterBuy::show(sale_info);
}
void handle_buy_contents(LLSaleInfo sale_info)
{
- LLFloaterBuyContents::show(sale_info);
+ LLFloaterBuyContents::show(sale_info);
}
void handle_region_dump_temp_asset_data(void*)
{
- LL_INFOS() << "Dumping temporary asset data to simulator logs" << LL_ENDL;
- std::vector<std::string> strings;
- LLUUID invoice;
- send_generic_message("dumptempassetdata", strings, invoice);
+ LL_INFOS() << "Dumping temporary asset data to simulator logs" << LL_ENDL;
+ std::vector<std::string> strings;
+ LLUUID invoice;
+ send_generic_message("dumptempassetdata", strings, invoice);
}
void handle_region_clear_temp_asset_data(void*)
{
- LL_INFOS() << "Clearing temporary asset data" << LL_ENDL;
- std::vector<std::string> strings;
- LLUUID invoice;
- send_generic_message("cleartempassetdata", strings, invoice);
+ LL_INFOS() << "Clearing temporary asset data" << LL_ENDL;
+ std::vector<std::string> strings;
+ LLUUID invoice;
+ send_generic_message("cleartempassetdata", strings, invoice);
}
void handle_region_dump_settings(void*)
{
- LLViewerRegion* regionp = gAgent.getRegion();
- if (regionp)
- {
- LL_INFOS() << "Damage: " << (regionp->getAllowDamage() ? "on" : "off") << LL_ENDL;
- LL_INFOS() << "Landmark: " << (regionp->getAllowLandmark() ? "on" : "off") << LL_ENDL;
- LL_INFOS() << "SetHome: " << (regionp->getAllowSetHome() ? "on" : "off") << LL_ENDL;
- LL_INFOS() << "ResetHome: " << (regionp->getResetHomeOnTeleport() ? "on" : "off") << LL_ENDL;
- LL_INFOS() << "SunFixed: " << (regionp->getSunFixed() ? "on" : "off") << LL_ENDL;
- LL_INFOS() << "BlockFly: " << (regionp->getBlockFly() ? "on" : "off") << LL_ENDL;
- LL_INFOS() << "AllowP2P: " << (regionp->getAllowDirectTeleport() ? "on" : "off") << LL_ENDL;
- LL_INFOS() << "Water: " << (regionp->getWaterHeight()) << LL_ENDL;
- }
+ LLViewerRegion* regionp = gAgent.getRegion();
+ if (regionp)
+ {
+ LL_INFOS() << "Damage: " << (regionp->getAllowDamage() ? "on" : "off") << LL_ENDL;
+ LL_INFOS() << "Landmark: " << (regionp->getAllowLandmark() ? "on" : "off") << LL_ENDL;
+ LL_INFOS() << "SetHome: " << (regionp->getAllowSetHome() ? "on" : "off") << LL_ENDL;
+ LL_INFOS() << "ResetHome: " << (regionp->getResetHomeOnTeleport() ? "on" : "off") << LL_ENDL;
+ LL_INFOS() << "SunFixed: " << (regionp->getSunFixed() ? "on" : "off") << LL_ENDL;
+ LL_INFOS() << "BlockFly: " << (regionp->getBlockFly() ? "on" : "off") << LL_ENDL;
+ LL_INFOS() << "AllowP2P: " << (regionp->getAllowDirectTeleport() ? "on" : "off") << LL_ENDL;
+ LL_INFOS() << "Water: " << (regionp->getWaterHeight()) << LL_ENDL;
+ }
}
void handle_dump_group_info(void *)
{
- gAgent.dumpGroupInfo();
+ gAgent.dumpGroupInfo();
}
void handle_dump_capabilities_info(void *)
{
- LLViewerRegion* regionp = gAgent.getRegion();
- if (regionp)
- {
- regionp->logActiveCapabilities();
- }
+ LLViewerRegion* regionp = gAgent.getRegion();
+ if (regionp)
+ {
+ regionp->logActiveCapabilities();
+ }
}
void handle_dump_region_object_cache(void*)
{
- LLViewerRegion* regionp = gAgent.getRegion();
- if (regionp)
- {
- regionp->dumpCache();
- }
+ LLViewerRegion* regionp = gAgent.getRegion();
+ if (regionp)
+ {
+ regionp->dumpCache();
+ }
}
void handle_reset_interest_lists(void *)
@@ -3992,18 +3992,18 @@ void handle_reset_interest_lists(void *)
void handle_dump_focus()
{
- LLUICtrl *ctrl = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+ LLUICtrl *ctrl = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
- LL_INFOS() << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << LL_ENDL;
+ LL_INFOS() << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << LL_ENDL;
}
class LLSelfStandUp : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gAgent.standUp();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gAgent.standUp();
+ return true;
+ }
};
bool enable_standup_self()
@@ -4024,202 +4024,202 @@ class LLSelfSitDown : public view_listener_t
bool show_sitdown_self()
{
- return isAgentAvatarValid() && !gAgentAvatarp->isSitting();
+ return isAgentAvatarValid() && !gAgentAvatarp->isSitting();
}
bool enable_sitdown_self()
{
- return show_sitdown_self() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying();
+ return show_sitdown_self() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying();
}
class LLSelfToggleSitStand : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (isAgentAvatarValid())
- {
- if (gAgentAvatarp->isSitting())
- {
- gAgent.standUp();
- }
- else
- {
- gAgent.sitDown();
- }
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (isAgentAvatarValid())
+ {
+ if (gAgentAvatarp->isSitting())
+ {
+ gAgent.standUp();
+ }
+ else
+ {
+ gAgent.sitDown();
+ }
+ }
+ return true;
+ }
};
bool enable_sit_stand()
{
- return enable_sitdown_self() || enable_standup_self();
+ return enable_sitdown_self() || enable_standup_self();
}
bool enable_fly_land()
{
- return gAgent.getFlying() || LLAgent::enableFlying();
+ return gAgent.getFlying() || LLAgent::enableFlying();
}
class LLCheckPanelPeopleTab : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string panel_name = userdata.asString();
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string panel_name = userdata.asString();
- LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name);
- if(panel && panel->isInVisibleChain())
- {
- return true;
- }
- return false;
- }
+ LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name);
+ if(panel && panel->isInVisibleChain())
+ {
+ return true;
+ }
+ return false;
+ }
};
// Toggle one of "People" panel tabs in side tray.
class LLTogglePanelPeopleTab : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string panel_name = userdata.asString();
-
- LLSD param;
- param["people_panel_tab_name"] = panel_name;
-
- if ( panel_name == "friends_panel"
- || panel_name == "groups_panel"
- || panel_name == "nearby_panel"
- || panel_name == "blocked_panel")
- {
- return togglePeoplePanel(panel_name, param);
- }
- else
- {
- return false;
- }
- }
-
- static bool togglePeoplePanel(const std::string& panel_name, const LLSD& param)
- {
- LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name);
- if(!panel)
- return false;
-
- if (panel->isInVisibleChain())
- {
- LLFloaterReg::hideInstance("people");
- }
- else
- {
- LLFloaterSidePanelContainer::showPanel("people", "panel_people", param) ;
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string panel_name = userdata.asString();
+
+ LLSD param;
+ param["people_panel_tab_name"] = panel_name;
+
+ if ( panel_name == "friends_panel"
+ || panel_name == "groups_panel"
+ || panel_name == "nearby_panel"
+ || panel_name == "blocked_panel")
+ {
+ return togglePeoplePanel(panel_name, param);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ static bool togglePeoplePanel(const std::string& panel_name, const LLSD& param)
+ {
+ LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name);
+ if(!panel)
+ return false;
+
+ if (panel->isInVisibleChain())
+ {
+ LLFloaterReg::hideInstance("people");
+ }
+ else
+ {
+ LLFloaterSidePanelContainer::showPanel("people", "panel_people", param) ;
+ }
+
+ return true;
+ }
};
BOOL check_admin_override(void*)
{
- return gAgent.getAdminOverride();
+ return gAgent.getAdminOverride();
}
void handle_admin_override_toggle(void*)
{
- gAgent.setAdminOverride(!gAgent.getAdminOverride());
+ gAgent.setAdminOverride(!gAgent.getAdminOverride());
- // The above may have affected which debug menus are visible
- show_debug_menus();
+ // The above may have affected which debug menus are visible
+ show_debug_menus();
}
void handle_visual_leak_detector_toggle(void*)
{
- static bool vld_enabled = false;
+ static bool vld_enabled = false;
- if ( vld_enabled )
- {
+ if ( vld_enabled )
+ {
#ifdef INCLUDE_VLD
- // only works for debug builds (hard coded into vld.h)
+ // only works for debug builds (hard coded into vld.h)
#ifdef _DEBUG
- // start with Visual Leak Detector turned off
- VLDDisable();
+ // start with Visual Leak Detector turned off
+ VLDDisable();
#endif // _DEBUG
#endif // INCLUDE_VLD
- vld_enabled = false;
- }
- else
- {
+ vld_enabled = false;
+ }
+ else
+ {
#ifdef INCLUDE_VLD
- // only works for debug builds (hard coded into vld.h)
- #ifdef _DEBUG
- // start with Visual Leak Detector turned off
- VLDEnable();
- #endif // _DEBUG
+ // only works for debug builds (hard coded into vld.h)
+ #ifdef _DEBUG
+ // start with Visual Leak Detector turned off
+ VLDEnable();
+ #endif // _DEBUG
#endif // INCLUDE_VLD
- vld_enabled = true;
- };
+ vld_enabled = true;
+ };
}
void handle_god_mode(void*)
{
- gAgent.requestEnterGodMode();
+ gAgent.requestEnterGodMode();
}
void handle_leave_god_mode(void*)
{
- gAgent.requestLeaveGodMode();
+ gAgent.requestLeaveGodMode();
}
void set_god_level(U8 god_level)
{
- U8 old_god_level = gAgent.getGodLevel();
- gAgent.setGodLevel( god_level );
- LLViewerParcelMgr::getInstance()->notifyObservers();
+ U8 old_god_level = gAgent.getGodLevel();
+ gAgent.setGodLevel( god_level );
+ LLViewerParcelMgr::getInstance()->notifyObservers();
- // God mode changes region visibility
- LLWorldMap::getInstance()->reloadItems(true);
+ // God mode changes region visibility
+ LLWorldMap::getInstance()->reloadItems(true);
- // inventory in items may change in god mode
- gObjectList.dirtyAllObjectInventory();
+ // inventory in items may change in god mode
+ gObjectList.dirtyAllObjectInventory();
if(gViewerWindow)
{
gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT,
LLGridManager::getInstance()->isInProductionGrid());
}
-
+
LLSD args;
- if(god_level > GOD_NOT)
- {
- args["LEVEL"] = llformat("%d",(S32)god_level);
- LLNotificationsUtil::add("EnteringGodMode", args);
- }
- else
- {
- args["LEVEL"] = llformat("%d",(S32)old_god_level);
- LLNotificationsUtil::add("LeavingGodMode", args);
- }
-
- // changing god-level can affect which menus we see
- show_debug_menus();
-
- // changing god-level can invalidate search results
- LLFloaterSearch *search = dynamic_cast<LLFloaterSearch*>(LLFloaterReg::getInstance("search"));
- if (search)
- {
- search->godLevelChanged(god_level);
- }
+ if(god_level > GOD_NOT)
+ {
+ args["LEVEL"] = llformat("%d",(S32)god_level);
+ LLNotificationsUtil::add("EnteringGodMode", args);
+ }
+ else
+ {
+ args["LEVEL"] = llformat("%d",(S32)old_god_level);
+ LLNotificationsUtil::add("LeavingGodMode", args);
+ }
+
+ // changing god-level can affect which menus we see
+ show_debug_menus();
+
+ // changing god-level can invalidate search results
+ LLFloaterSearch *search = dynamic_cast<LLFloaterSearch*>(LLFloaterReg::getInstance("search"));
+ if (search)
+ {
+ search->godLevelChanged(god_level);
+ }
}
#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
void handle_toggle_hacked_godmode(void*)
{
- gHackGodmode = !gHackGodmode;
- set_god_level(gHackGodmode ? GOD_MAINTENANCE : GOD_NOT);
+ gHackGodmode = !gHackGodmode;
+ set_god_level(gHackGodmode ? GOD_MAINTENANCE : GOD_NOT);
}
BOOL check_toggle_hacked_godmode(void*)
{
- return gHackGodmode;
+ return gHackGodmode;
}
bool enable_toggle_hacked_godmode(void*)
@@ -4230,174 +4230,174 @@ bool enable_toggle_hacked_godmode(void*)
void process_grant_godlike_powers(LLMessageSystem* msg, void**)
{
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- LLUUID session_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
- if((agent_id == gAgent.getID()) && (session_id == gAgent.getSessionID()))
- {
- U8 god_level;
- msg->getU8Fast(_PREHASH_GrantData, _PREHASH_GodLevel, god_level);
- set_god_level(god_level);
- }
- else
- {
- LL_WARNS() << "Grant godlike for wrong agent " << agent_id << LL_ENDL;
- }
+ LLUUID agent_id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+ LLUUID session_id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
+ if((agent_id == gAgent.getID()) && (session_id == gAgent.getSessionID()))
+ {
+ U8 god_level;
+ msg->getU8Fast(_PREHASH_GrantData, _PREHASH_GodLevel, god_level);
+ set_god_level(god_level);
+ }
+ else
+ {
+ LL_WARNS() << "Grant godlike for wrong agent " << agent_id << LL_ENDL;
+ }
}
/*
class LLHaveCallingcard : public LLInventoryCollectFunctor
{
public:
- LLHaveCallingcard(const LLUUID& agent_id);
- virtual ~LLHaveCallingcard() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
- BOOL isThere() const { return mIsThere;}
+ LLHaveCallingcard(const LLUUID& agent_id);
+ virtual ~LLHaveCallingcard() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
+ BOOL isThere() const { return mIsThere;}
protected:
- LLUUID mID;
- BOOL mIsThere;
+ LLUUID mID;
+ BOOL mIsThere;
};
LLHaveCallingcard::LLHaveCallingcard(const LLUUID& agent_id) :
- mID(agent_id),
- mIsThere(FALSE)
+ mID(agent_id),
+ mIsThere(FALSE)
{
}
bool LLHaveCallingcard::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
-{
- if(item)
- {
- if((item->getType() == LLAssetType::AT_CALLINGCARD)
- && (item->getCreatorUUID() == mID))
- {
- mIsThere = TRUE;
- }
- }
- return FALSE;
+ LLInventoryItem* item)
+{
+ if(item)
+ {
+ if((item->getType() == LLAssetType::AT_CALLINGCARD)
+ && (item->getCreatorUUID() == mID))
+ {
+ mIsThere = TRUE;
+ }
+ }
+ return FALSE;
}
*/
BOOL is_agent_mappable(const LLUUID& agent_id)
{
- const LLRelationship* buddy_info = NULL;
- bool is_friend = LLAvatarActions::isFriend(agent_id);
+ const LLRelationship* buddy_info = NULL;
+ bool is_friend = LLAvatarActions::isFriend(agent_id);
- if (is_friend)
- buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id);
+ if (is_friend)
+ buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id);
- return (buddy_info &&
- buddy_info->isOnline() &&
- buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)
- );
+ return (buddy_info &&
+ buddy_info->isOnline() &&
+ buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)
+ );
}
// Enable a menu item when you don't have someone's card.
class LLAvatarEnableAddFriend : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
- bool new_value = avatar && !LLAvatarActions::isFriend(avatar->getID());
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ bool new_value = avatar && !LLAvatarActions::isFriend(avatar->getID());
+ return new_value;
+ }
};
void request_friendship(const LLUUID& dest_id)
{
- LLViewerObject* dest = gObjectList.findObject(dest_id);
- if(dest && dest->isAvatar())
- {
- std::string full_name;
- LLNameValue* nvfirst = dest->getNVPair("FirstName");
- LLNameValue* nvlast = dest->getNVPair("LastName");
- if(nvfirst && nvlast)
- {
- full_name = LLCacheName::buildFullName(
- nvfirst->getString(), nvlast->getString());
- }
- if (!full_name.empty())
- {
- LLAvatarActions::requestFriendshipDialog(dest_id, full_name);
- }
- else
- {
- LLNotificationsUtil::add("CantOfferFriendship");
- }
- }
+ LLViewerObject* dest = gObjectList.findObject(dest_id);
+ if(dest && dest->isAvatar())
+ {
+ std::string full_name;
+ LLNameValue* nvfirst = dest->getNVPair("FirstName");
+ LLNameValue* nvlast = dest->getNVPair("LastName");
+ if(nvfirst && nvlast)
+ {
+ full_name = LLCacheName::buildFullName(
+ nvfirst->getString(), nvlast->getString());
+ }
+ if (!full_name.empty())
+ {
+ LLAvatarActions::requestFriendshipDialog(dest_id, full_name);
+ }
+ else
+ {
+ LLNotificationsUtil::add("CantOfferFriendship");
+ }
+ }
}
class LLEditEnableCustomizeAvatar : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gAgentWearables.areWearablesLoaded();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gAgentWearables.areWearablesLoaded();
+ return new_value;
+ }
};
class LLEnableEditShape : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0);
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0);
+ }
};
class LLEnableHoverHeight : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled();
+ }
};
class LLEnableEditPhysics : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- //return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0);
- return TRUE;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ //return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0);
+ return TRUE;
+ }
};
bool is_object_sittable()
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (object && object->getPCode() == LL_PCODE_VOLUME)
- {
- return true;
- }
- else
- {
- return false;
- }
+ if (object && object->getPCode() == LL_PCODE_VOLUME)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
// only works on pie menu
void handle_object_sit(LLViewerObject *object, const LLVector3 &offset)
{
- // get object selection offset
+ // get object selection offset
- if (object && object->getPCode() == LL_PCODE_VOLUME)
- {
+ if (object && object->getPCode() == LL_PCODE_VOLUME)
+ {
- gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
- gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID);
- gMessageSystem->addVector3Fast(_PREHASH_Offset, offset);
+ gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
+ gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID);
+ gMessageSystem->addVector3Fast(_PREHASH_Offset, offset);
- object->getRegion()->sendReliableMessage();
- }
+ object->getRegion()->sendReliableMessage();
+ }
}
void handle_object_sit_or_stand()
@@ -4432,12 +4432,12 @@ void handle_object_sit(const LLUUID& object_id)
void near_sit_down_point(BOOL success, void *)
{
- if (success)
- {
- gAgent.setFlying(FALSE);
- gAgent.clearControlFlags(AGENT_CONTROL_STAND_UP); // might have been set by autopilot
- gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
- }
+ if (success)
+ {
+ gAgent.setFlying(FALSE);
+ gAgent.clearControlFlags(AGENT_CONTROL_STAND_UP); // might have been set by autopilot
+ gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
+ }
}
class LLLandSit : public view_listener_t
@@ -4484,120 +4484,120 @@ void reset_view_final( BOOL proceed );
void handle_reset_view()
{
- if (gAgentCamera.cameraCustomizeAvatar())
- {
- // switching to outfit selector should automagically save any currently edited wearable
- LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits"));
- }
- gAgentCamera.setFocusOnAvatar(TRUE, FALSE, FALSE);
- reset_view_final( TRUE );
- LLFloaterCamera::resetCameraMode();
+ if (gAgentCamera.cameraCustomizeAvatar())
+ {
+ // switching to outfit selector should automagically save any currently edited wearable
+ LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits"));
+ }
+ gAgentCamera.setFocusOnAvatar(TRUE, FALSE, FALSE);
+ reset_view_final( TRUE );
+ LLFloaterCamera::resetCameraMode();
}
class LLViewResetView : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- handle_reset_view();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_reset_view();
+ return true;
+ }
};
// Note: extra parameters allow this function to be called from dialog.
-void reset_view_final( BOOL proceed )
+void reset_view_final( BOOL proceed )
{
- if( !proceed )
- {
- return;
- }
+ if( !proceed )
+ {
+ return;
+ }
- gAgentCamera.resetView(TRUE, TRUE);
- gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
+ gAgentCamera.resetView(TRUE, TRUE);
+ gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
}
class LLViewLookAtLastChatter : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gAgentCamera.lookAtLastChat();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gAgentCamera.lookAtLastChat();
+ return true;
+ }
};
class LLViewMouselook : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (!gAgentCamera.cameraMouselook())
- {
- gAgentCamera.changeCameraToMouselook();
- }
- else
- {
- gAgentCamera.changeCameraToDefault();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (!gAgentCamera.cameraMouselook())
+ {
+ gAgentCamera.changeCameraToMouselook();
+ }
+ else
+ {
+ gAgentCamera.changeCameraToDefault();
+ }
+ return true;
+ }
};
class LLViewDefaultUISize : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gSavedSettings.setF32("UIScaleFactor", 1.0f);
- gSavedSettings.setBOOL("UIAutoScale", FALSE);
- gViewerWindow->reshape(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gSavedSettings.setF32("UIScaleFactor", 1.0f);
+ gSavedSettings.setBOOL("UIAutoScale", FALSE);
+ gViewerWindow->reshape(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
+ return true;
+ }
};
class LLViewToggleUI : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if(gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK)
- {
- LLNotification::Params params("ConfirmHideUI");
- params.functor.function(boost::bind(&LLViewToggleUI::confirm, this, _1, _2));
- LLSD substitutions;
+ bool handleEvent(const LLSD& userdata)
+ {
+ if(gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK)
+ {
+ LLNotification::Params params("ConfirmHideUI");
+ params.functor.function(boost::bind(&LLViewToggleUI::confirm, this, _1, _2));
+ LLSD substitutions;
#if LL_DARWIN
- substitutions["SHORTCUT"] = "Cmd+Shift+U";
+ substitutions["SHORTCUT"] = "Cmd+Shift+U";
#else
- substitutions["SHORTCUT"] = "Ctrl+Shift+U";
+ substitutions["SHORTCUT"] = "Ctrl+Shift+U";
#endif
- params.substitutions = substitutions;
- if (!gSavedSettings.getBOOL("HideUIControls"))
- {
- // hiding, so show notification
- LLNotifications::instance().add(params);
- }
- else
- {
- LLNotifications::instance().forceResponse(params, 0);
- }
- }
- return true;
- }
-
- void confirm(const LLSD& notification, const LLSD& response)
- {
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
- if (option == 0) // OK
- {
- gViewerWindow->setUIVisibility(gSavedSettings.getBOOL("HideUIControls"));
- LLPanelStandStopFlying::getInstance()->setVisible(gSavedSettings.getBOOL("HideUIControls"));
- gSavedSettings.setBOOL("HideUIControls",!gSavedSettings.getBOOL("HideUIControls"));
- }
- }
+ params.substitutions = substitutions;
+ if (!gSavedSettings.getBOOL("HideUIControls"))
+ {
+ // hiding, so show notification
+ LLNotifications::instance().add(params);
+ }
+ else
+ {
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+ }
+ return true;
+ }
+
+ void confirm(const LLSD& notification, const LLSD& response)
+ {
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ if (option == 0) // OK
+ {
+ gViewerWindow->setUIVisibility(gSavedSettings.getBOOL("HideUIControls"));
+ LLPanelStandStopFlying::getInstance()->setVisible(gSavedSettings.getBOOL("HideUIControls"));
+ gSavedSettings.setBOOL("HideUIControls",!gSavedSettings.getBOOL("HideUIControls"));
+ }
+ }
};
void handle_duplicate_in_place(void*)
{
- LL_INFOS() << "handle_duplicate_in_place" << LL_ENDL;
+ LL_INFOS() << "handle_duplicate_in_place" << LL_ENDL;
- LLVector3 offset(0.f, 0.f, 0.f);
- LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE);
+ LLVector3 offset(0.f, 0.f, 0.f);
+ LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE);
}
@@ -4606,121 +4606,121 @@ void handle_duplicate_in_place(void*)
* No longer able to support viewer side manipulations in this way
*
void god_force_inv_owner_permissive(LLViewerObject* object,
- LLInventoryObject::object_list_t* inventory,
- S32 serial_num,
- void*)
-{
- typedef std::vector<LLPointer<LLViewerInventoryItem> > item_array_t;
- item_array_t items;
-
- LLInventoryObject::object_list_t::const_iterator inv_it = inventory->begin();
- LLInventoryObject::object_list_t::const_iterator inv_end = inventory->end();
- for ( ; inv_it != inv_end; ++inv_it)
- {
- if(((*inv_it)->getType() != LLAssetType::AT_CATEGORY))
- {
- LLInventoryObject* obj = *inv_it;
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem((LLViewerInventoryItem*)obj);
- LLPermissions perm(new_item->getPermissions());
- perm.setMaskBase(PERM_ALL);
- perm.setMaskOwner(PERM_ALL);
- new_item->setPermissions(perm);
- items.push_back(new_item);
- }
- }
- item_array_t::iterator end = items.end();
- item_array_t::iterator it;
- for(it = items.begin(); it != end; ++it)
- {
- // since we have the inventory item in the callback, it should not
- // invalidate iteration through the selection manager.
- object->updateInventory((*it), TASK_INVENTORY_ITEM_KEY, false);
- }
+ LLInventoryObject::object_list_t* inventory,
+ S32 serial_num,
+ void*)
+{
+ typedef std::vector<LLPointer<LLViewerInventoryItem> > item_array_t;
+ item_array_t items;
+
+ LLInventoryObject::object_list_t::const_iterator inv_it = inventory->begin();
+ LLInventoryObject::object_list_t::const_iterator inv_end = inventory->end();
+ for ( ; inv_it != inv_end; ++inv_it)
+ {
+ if(((*inv_it)->getType() != LLAssetType::AT_CATEGORY))
+ {
+ LLInventoryObject* obj = *inv_it;
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem((LLViewerInventoryItem*)obj);
+ LLPermissions perm(new_item->getPermissions());
+ perm.setMaskBase(PERM_ALL);
+ perm.setMaskOwner(PERM_ALL);
+ new_item->setPermissions(perm);
+ items.push_back(new_item);
+ }
+ }
+ item_array_t::iterator end = items.end();
+ item_array_t::iterator it;
+ for(it = items.begin(); it != end; ++it)
+ {
+ // since we have the inventory item in the callback, it should not
+ // invalidate iteration through the selection manager.
+ object->updateInventory((*it), TASK_INVENTORY_ITEM_KEY, false);
+ }
}
*/
void handle_object_owner_permissive(void*)
{
- // only send this if they're a god.
- if(gAgent.isGodlike())
- {
- // do the objects.
- LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE);
- LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE);
- }
+ // only send this if they're a god.
+ if(gAgent.isGodlike())
+ {
+ // do the objects.
+ LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE);
+ LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE);
+ }
}
void handle_object_owner_self(void*)
{
- // only send this if they're a god.
- if(gAgent.isGodlike())
- {
- LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID(), TRUE);
- }
+ // only send this if they're a god.
+ if(gAgent.isGodlike())
+ {
+ LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID(), TRUE);
+ }
}
// Shortcut to set owner permissions to not editable.
void handle_object_lock(void*)
{
- LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY);
+ LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY);
}
void handle_object_asset_ids(void*)
{
- // only send this if they're a god.
- if (gAgent.isGodlike())
- {
- LLSelectMgr::getInstance()->sendGodlikeRequest("objectinfo", "assetids");
- }
+ // only send this if they're a god.
+ if (gAgent.isGodlike())
+ {
+ LLSelectMgr::getInstance()->sendGodlikeRequest("objectinfo", "assetids");
+ }
}
void handle_force_parcel_owner_to_me(void*)
{
- LLViewerParcelMgr::getInstance()->sendParcelGodForceOwner( gAgent.getID() );
+ LLViewerParcelMgr::getInstance()->sendParcelGodForceOwner( gAgent.getID() );
}
void handle_force_parcel_to_content(void*)
{
- LLViewerParcelMgr::getInstance()->sendParcelGodForceToContent();
+ LLViewerParcelMgr::getInstance()->sendParcelGodForceToContent();
}
void handle_claim_public_land(void*)
{
- if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion())
- {
- LLNotificationsUtil::add("ClaimPublicLand");
- return;
- }
-
- LLVector3d west_south_global;
- LLVector3d east_north_global;
- LLViewerParcelMgr::getInstance()->getSelection(west_south_global, east_north_global);
- LLVector3 west_south = gAgent.getPosAgentFromGlobal(west_south_global);
- LLVector3 east_north = gAgent.getPosAgentFromGlobal(east_north_global);
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("GodlikeMessage");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
- msg->nextBlock("MethodData");
- msg->addString("Method", "claimpublicland");
- msg->addUUID("Invoice", LLUUID::null);
- std::string buffer;
- buffer = llformat( "%f", west_south.mV[VX]);
- msg->nextBlock("ParamList");
- msg->addString("Parameter", buffer);
- buffer = llformat( "%f", west_south.mV[VY]);
- msg->nextBlock("ParamList");
- msg->addString("Parameter", buffer);
- buffer = llformat( "%f", east_north.mV[VX]);
- msg->nextBlock("ParamList");
- msg->addString("Parameter", buffer);
- buffer = llformat( "%f", east_north.mV[VY]);
- msg->nextBlock("ParamList");
- msg->addString("Parameter", buffer);
- gAgent.sendReliableMessage();
+ if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion())
+ {
+ LLNotificationsUtil::add("ClaimPublicLand");
+ return;
+ }
+
+ LLVector3d west_south_global;
+ LLVector3d east_north_global;
+ LLViewerParcelMgr::getInstance()->getSelection(west_south_global, east_north_global);
+ LLVector3 west_south = gAgent.getPosAgentFromGlobal(west_south_global);
+ LLVector3 east_north = gAgent.getPosAgentFromGlobal(east_north_global);
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("GodlikeMessage");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
+ msg->nextBlock("MethodData");
+ msg->addString("Method", "claimpublicland");
+ msg->addUUID("Invoice", LLUUID::null);
+ std::string buffer;
+ buffer = llformat( "%f", west_south.mV[VX]);
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", buffer);
+ buffer = llformat( "%f", west_south.mV[VY]);
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", buffer);
+ buffer = llformat( "%f", east_north.mV[VX]);
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", buffer);
+ buffer = llformat( "%f", east_north.mV[VY]);
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", buffer);
+ gAgent.sendReliableMessage();
}
@@ -4728,286 +4728,286 @@ void handle_claim_public_land(void*)
// HACK for easily testing new avatar geometry
void handle_god_request_avatar_geometry(void *)
{
- if (gAgent.isGodlike())
- {
- LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", "");
- }
+ if (gAgent.isGodlike())
+ {
+ LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", "");
+ }
}
static bool get_derezzable_objects(
- EDeRezDestination dest,
- std::string& error,
- LLViewerRegion*& first_region,
- std::vector<LLViewerObjectPtr>* derez_objectsp,
- bool only_check = false)
-{
- bool found = false;
-
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-
- if (derez_objectsp)
- derez_objectsp->reserve(selection->getRootObjectCount());
-
- // Check conditions that we can't deal with, building a list of
- // everything that we'll actually be derezzing.
- for (LLObjectSelection::valid_root_iterator iter = selection->valid_root_begin();
- iter != selection->valid_root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- LLViewerRegion* region = object->getRegion();
- if (!first_region)
- {
- first_region = region;
- }
- else
- {
- if(region != first_region)
- {
- // Derez doesn't work at all if the some of the objects
- // are in regions besides the first object selected.
-
- // ...crosses region boundaries
- error = "AcquireErrorObjectSpan";
- break;
- }
- }
- if (object->isAvatar())
- {
- // ...don't acquire avatars
- continue;
- }
-
- // If AssetContainers are being sent back, they will appear as
- // boxes in the owner's inventory.
- if (object->getNVPair("AssetContainer")
- && dest != DRD_RETURN_TO_OWNER)
- {
- // this object is an asset container, derez its contents, not it
- LL_WARNS() << "Attempt to derez deprecated AssetContainer object type not supported." << LL_ENDL;
- /*
- object->requestInventory(container_inventory_arrived,
- (void *)(BOOL)(DRD_TAKE_INTO_AGENT_INVENTORY == dest));
- */
- continue;
- }
- BOOL can_derez_current = FALSE;
- switch(dest)
- {
- case DRD_TAKE_INTO_AGENT_INVENTORY:
- case DRD_TRASH:
- if (!object->isPermanentEnforced() &&
- ((node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify())
- || (node->allowOperationOnNode(PERM_OWNER, GP_OBJECT_MANIPULATE))))
- {
- can_derez_current = TRUE;
- }
- break;
-
- case DRD_RETURN_TO_OWNER:
- if(!object->isAttachment())
- {
- can_derez_current = TRUE;
- }
- break;
-
- default:
- if((node->mPermissions->allowTransferTo(gAgent.getID())
- && object->permCopy())
- || gAgent.isGodlike())
- {
- can_derez_current = TRUE;
- }
- break;
- }
- if(can_derez_current)
- {
- found = true;
-
- if (only_check)
- // one found, no need to traverse to the end
- break;
-
- if (derez_objectsp)
- derez_objectsp->push_back(object);
-
- }
- }
-
- return found;
+ EDeRezDestination dest,
+ std::string& error,
+ LLViewerRegion*& first_region,
+ std::vector<LLViewerObjectPtr>* derez_objectsp,
+ bool only_check = false)
+{
+ bool found = false;
+
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+
+ if (derez_objectsp)
+ derez_objectsp->reserve(selection->getRootObjectCount());
+
+ // Check conditions that we can't deal with, building a list of
+ // everything that we'll actually be derezzing.
+ for (LLObjectSelection::valid_root_iterator iter = selection->valid_root_begin();
+ iter != selection->valid_root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = node->getObject();
+ LLViewerRegion* region = object->getRegion();
+ if (!first_region)
+ {
+ first_region = region;
+ }
+ else
+ {
+ if(region != first_region)
+ {
+ // Derez doesn't work at all if the some of the objects
+ // are in regions besides the first object selected.
+
+ // ...crosses region boundaries
+ error = "AcquireErrorObjectSpan";
+ break;
+ }
+ }
+ if (object->isAvatar())
+ {
+ // ...don't acquire avatars
+ continue;
+ }
+
+ // If AssetContainers are being sent back, they will appear as
+ // boxes in the owner's inventory.
+ if (object->getNVPair("AssetContainer")
+ && dest != DRD_RETURN_TO_OWNER)
+ {
+ // this object is an asset container, derez its contents, not it
+ LL_WARNS() << "Attempt to derez deprecated AssetContainer object type not supported." << LL_ENDL;
+ /*
+ object->requestInventory(container_inventory_arrived,
+ (void *)(BOOL)(DRD_TAKE_INTO_AGENT_INVENTORY == dest));
+ */
+ continue;
+ }
+ BOOL can_derez_current = FALSE;
+ switch(dest)
+ {
+ case DRD_TAKE_INTO_AGENT_INVENTORY:
+ case DRD_TRASH:
+ if (!object->isPermanentEnforced() &&
+ ((node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify())
+ || (node->allowOperationOnNode(PERM_OWNER, GP_OBJECT_MANIPULATE))))
+ {
+ can_derez_current = TRUE;
+ }
+ break;
+
+ case DRD_RETURN_TO_OWNER:
+ if(!object->isAttachment())
+ {
+ can_derez_current = TRUE;
+ }
+ break;
+
+ default:
+ if((node->mPermissions->allowTransferTo(gAgent.getID())
+ && object->permCopy())
+ || gAgent.isGodlike())
+ {
+ can_derez_current = TRUE;
+ }
+ break;
+ }
+ if(can_derez_current)
+ {
+ found = true;
+
+ if (only_check)
+ // one found, no need to traverse to the end
+ break;
+
+ if (derez_objectsp)
+ derez_objectsp->push_back(object);
+
+ }
+ }
+
+ return found;
}
static bool can_derez(EDeRezDestination dest)
{
- LLViewerRegion* first_region = NULL;
- std::string error;
- return get_derezzable_objects(dest, error, first_region, NULL, true);
+ LLViewerRegion* first_region = NULL;
+ std::string error;
+ return get_derezzable_objects(dest, error, first_region, NULL, true);
}
static void derez_objects(
- EDeRezDestination dest,
- const LLUUID& dest_id,
- LLViewerRegion*& first_region,
- std::string& error,
- std::vector<LLViewerObjectPtr>* objectsp)
-{
- std::vector<LLViewerObjectPtr> derez_objects;
-
- if (!objectsp) // if objects to derez not specified
- {
- // get them from selection
- if (!get_derezzable_objects(dest, error, first_region, &derez_objects, false))
- {
- LL_WARNS() << "No objects to derez" << LL_ENDL;
- return;
- }
-
- objectsp = &derez_objects;
- }
-
-
- if(gAgentCamera.cameraMouselook())
- {
- gAgentCamera.changeCameraToDefault();
- }
-
- // This constant is based on (1200 - HEADER_SIZE) / 4 bytes per
- // root. I lopped off a few (33) to provide a bit
- // pad. HEADER_SIZE is currently 67 bytes, most of which is UUIDs.
- // This gives us a maximum of 63500 root objects - which should
- // satisfy anybody.
- const S32 MAX_ROOTS_PER_PACKET = 250;
- const S32 MAX_PACKET_COUNT = 254;
- F32 packets = ceil((F32)objectsp->size() / (F32)MAX_ROOTS_PER_PACKET);
- if(packets > (F32)MAX_PACKET_COUNT)
- {
- error = "AcquireErrorTooManyObjects";
- }
-
- if(error.empty() && objectsp->size() > 0)
- {
- U8 d = (U8)dest;
- LLUUID tid;
- tid.generate();
- U8 packet_count = (U8)packets;
- S32 object_index = 0;
- S32 objects_in_packet = 0;
- LLMessageSystem* msg = gMessageSystem;
- for(U8 packet_number = 0;
- packet_number < packet_count;
- ++packet_number)
- {
- msg->newMessageFast(_PREHASH_DeRezObject);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_AgentBlock);
- msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
- msg->addU8Fast(_PREHASH_Destination, d);
- msg->addUUIDFast(_PREHASH_DestinationID, dest_id);
- msg->addUUIDFast(_PREHASH_TransactionID, tid);
- msg->addU8Fast(_PREHASH_PacketCount, packet_count);
- msg->addU8Fast(_PREHASH_PacketNumber, packet_number);
- objects_in_packet = 0;
- while((object_index < objectsp->size())
- && (objects_in_packet++ < MAX_ROOTS_PER_PACKET))
-
- {
- LLViewerObject* object = objectsp->at(object_index++);
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID());
- // VEFFECT: DerezObject
- LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
- effectp->setPositionGlobal(object->getPositionGlobal());
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- }
- msg->sendReliable(first_region->getHost());
- }
- make_ui_sound("UISndObjectRezOut");
-
- // Busy count decremented by inventory update, so only increment
- // if will be causing an update.
- if (dest != DRD_RETURN_TO_OWNER)
- {
- gViewerWindow->getWindow()->incBusyCount();
- }
- }
- else if(!error.empty())
- {
- LLNotificationsUtil::add(error);
- }
+ EDeRezDestination dest,
+ const LLUUID& dest_id,
+ LLViewerRegion*& first_region,
+ std::string& error,
+ std::vector<LLViewerObjectPtr>* objectsp)
+{
+ std::vector<LLViewerObjectPtr> derez_objects;
+
+ if (!objectsp) // if objects to derez not specified
+ {
+ // get them from selection
+ if (!get_derezzable_objects(dest, error, first_region, &derez_objects, false))
+ {
+ LL_WARNS() << "No objects to derez" << LL_ENDL;
+ return;
+ }
+
+ objectsp = &derez_objects;
+ }
+
+
+ if(gAgentCamera.cameraMouselook())
+ {
+ gAgentCamera.changeCameraToDefault();
+ }
+
+ // This constant is based on (1200 - HEADER_SIZE) / 4 bytes per
+ // root. I lopped off a few (33) to provide a bit
+ // pad. HEADER_SIZE is currently 67 bytes, most of which is UUIDs.
+ // This gives us a maximum of 63500 root objects - which should
+ // satisfy anybody.
+ const S32 MAX_ROOTS_PER_PACKET = 250;
+ const S32 MAX_PACKET_COUNT = 254;
+ F32 packets = ceil((F32)objectsp->size() / (F32)MAX_ROOTS_PER_PACKET);
+ if(packets > (F32)MAX_PACKET_COUNT)
+ {
+ error = "AcquireErrorTooManyObjects";
+ }
+
+ if(error.empty() && objectsp->size() > 0)
+ {
+ U8 d = (U8)dest;
+ LLUUID tid;
+ tid.generate();
+ U8 packet_count = (U8)packets;
+ S32 object_index = 0;
+ S32 objects_in_packet = 0;
+ LLMessageSystem* msg = gMessageSystem;
+ for(U8 packet_number = 0;
+ packet_number < packet_count;
+ ++packet_number)
+ {
+ msg->newMessageFast(_PREHASH_DeRezObject);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_AgentBlock);
+ msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
+ msg->addU8Fast(_PREHASH_Destination, d);
+ msg->addUUIDFast(_PREHASH_DestinationID, dest_id);
+ msg->addUUIDFast(_PREHASH_TransactionID, tid);
+ msg->addU8Fast(_PREHASH_PacketCount, packet_count);
+ msg->addU8Fast(_PREHASH_PacketNumber, packet_number);
+ objects_in_packet = 0;
+ while((object_index < objectsp->size())
+ && (objects_in_packet++ < MAX_ROOTS_PER_PACKET))
+
+ {
+ LLViewerObject* object = objectsp->at(object_index++);
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID());
+ // VEFFECT: DerezObject
+ LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
+ effectp->setPositionGlobal(object->getPositionGlobal());
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+ }
+ msg->sendReliable(first_region->getHost());
+ }
+ make_ui_sound("UISndObjectRezOut");
+
+ // Busy count decremented by inventory update, so only increment
+ // if will be causing an update.
+ if (dest != DRD_RETURN_TO_OWNER)
+ {
+ gViewerWindow->getWindow()->incBusyCount();
+ }
+ }
+ else if(!error.empty())
+ {
+ LLNotificationsUtil::add(error);
+ }
}
static void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
{
- LLViewerRegion* first_region = NULL;
- std::string error;
- derez_objects(dest, dest_id, first_region, error, NULL);
+ LLViewerRegion* first_region = NULL;
+ std::string error;
+ derez_objects(dest, dest_id, first_region, error, NULL);
}
void handle_take_copy()
{
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
- const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
- derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
+ const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+ derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
}
void handle_link_objects()
{
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- LLFloaterReg::toggleInstanceOrBringToFront("places");
- }
- else
- {
- LLSelectMgr::getInstance()->linkObjects();
- }
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ LLFloaterReg::toggleInstanceOrBringToFront("places");
+ }
+ else
+ {
+ LLSelectMgr::getInstance()->linkObjects();
+ }
}
// You can return an object to its owner if it is on your land.
class LLObjectReturn : public view_listener_t
{
public:
- LLObjectReturn() : mFirstRegion(NULL) {}
+ LLObjectReturn() : mFirstRegion(NULL) {}
private:
- bool handleEvent(const LLSD& userdata)
- {
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
+
+ mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
- mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
+ // Save selected objects, so that we still know what to return after the confirmation dialog resets selection.
+ get_derezzable_objects(DRD_RETURN_TO_OWNER, mError, mFirstRegion, &mReturnableObjects);
- // Save selected objects, so that we still know what to return after the confirmation dialog resets selection.
- get_derezzable_objects(DRD_RETURN_TO_OWNER, mError, mFirstRegion, &mReturnableObjects);
+ LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2));
+ return true;
+ }
- LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2));
- return true;
- }
-
- bool onReturnToOwner(const LLSD& notification, const LLSD& response)
- {
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (0 == option)
- {
- // Ignore category ID for this derez destination.
- derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, mFirstRegion, mError, &mReturnableObjects);
- }
+ bool onReturnToOwner(const LLSD& notification, const LLSD& response)
+ {
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ // Ignore category ID for this derez destination.
+ derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, mFirstRegion, mError, &mReturnableObjects);
+ }
- mReturnableObjects.clear();
- mError.clear();
- mFirstRegion = NULL;
+ mReturnableObjects.clear();
+ mError.clear();
+ mFirstRegion = NULL;
- // drop reference to current selection
- mObjectSelection = NULL;
- return false;
- }
+ // drop reference to current selection
+ mObjectSelection = NULL;
+ return false;
+ }
- LLObjectSelectionHandle mObjectSelection;
+ LLObjectSelectionHandle mObjectSelection;
- std::vector<LLViewerObjectPtr> mReturnableObjects;
- std::string mError;
- LLViewerRegion* mFirstRegion;
+ std::vector<LLViewerObjectPtr> mReturnableObjects;
+ std::string mError;
+ LLViewerRegion* mFirstRegion;
};
@@ -5015,187 +5015,187 @@ private:
// over land you own.
class LLObjectEnableReturn : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- // Do not enable if nothing selected
- return false;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ // Do not enable if nothing selected
+ return false;
+ }
#ifdef HACKED_GODLIKE_VIEWER
- bool new_value = true;
+ bool new_value = true;
#else
- bool new_value = false;
- if (gAgent.isGodlike())
- {
- new_value = true;
- }
- else
- {
- new_value = can_derez(DRD_RETURN_TO_OWNER);
- }
+ bool new_value = false;
+ if (gAgent.isGodlike())
+ {
+ new_value = true;
+ }
+ else
+ {
+ new_value = can_derez(DRD_RETURN_TO_OWNER);
+ }
#endif
- return new_value;
- }
+ return new_value;
+ }
};
void force_take_copy(void*)
{
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
- const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
- derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id);
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
+ const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+ derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id);
}
void handle_take()
{
- // we want to use the folder this was derezzed from if it's
- // available. Otherwise, derez to the normal place.
- if(LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- return;
- }
-
- BOOL you_own_everything = TRUE;
- BOOL locked_but_takeable_object = FALSE;
- LLUUID category_id;
-
- for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- if(object)
- {
- if(!object->permYouOwner())
- {
- you_own_everything = FALSE;
- }
-
- if(!object->permMove())
- {
- locked_but_takeable_object = TRUE;
- }
- }
- if(node->mFolderID.notNull())
- {
- if(category_id.isNull())
- {
- category_id = node->mFolderID;
- }
- else if(category_id != node->mFolderID)
- {
- // we have found two potential destinations. break out
- // now and send to the default location.
- category_id.setNull();
- break;
- }
- }
- }
- if(category_id.notNull())
- {
- // there is an unambiguous destination. See if this agent has
- // such a location and it is not in the trash or library
- if(!gInventory.getCategory(category_id))
- {
- // nope, set to NULL.
- category_id.setNull();
- }
- if(category_id.notNull())
- {
- // check trash
- const LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
- if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash))
- {
- category_id.setNull();
- }
-
- // check library
- if(gInventory.isObjectDescendentOf(category_id, gInventory.getLibraryRootFolderID()))
- {
- category_id.setNull();
- }
-
- // check inbox
- const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX);
- if (category_id == inbox_id || gInventory.isObjectDescendentOf(category_id, inbox_id))
- {
- category_id.setNull();
- }
- }
- }
- if(category_id.isNull())
- {
- category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
- }
- LLSD payload;
- payload["folder_id"] = category_id;
-
- LLNotification::Params params("ConfirmObjectTakeLock");
- params.payload(payload);
- // MAINT-290
- // Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez.
- // Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened
- params.functor.function(boost::bind(confirm_take, _1, _2, LLSelectMgr::instance().getSelection()));
-
- if(locked_but_takeable_object ||
- !you_own_everything)
- {
- if(locked_but_takeable_object && you_own_everything)
- {
- params.name("ConfirmObjectTakeLock");
- }
- else if(!locked_but_takeable_object && !you_own_everything)
- {
- params.name("ConfirmObjectTakeNoOwn");
- }
- else
- {
- params.name("ConfirmObjectTakeLockNoOwn");
- }
-
- LLNotifications::instance().add(params);
- }
- else
- {
- LLNotifications::instance().forceResponse(params, 0);
- }
+ // we want to use the folder this was derezzed from if it's
+ // available. Otherwise, derez to the normal place.
+ if(LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ return;
+ }
+
+ BOOL you_own_everything = TRUE;
+ BOOL locked_but_takeable_object = FALSE;
+ LLUUID category_id;
+
+ for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = node->getObject();
+ if(object)
+ {
+ if(!object->permYouOwner())
+ {
+ you_own_everything = FALSE;
+ }
+
+ if(!object->permMove())
+ {
+ locked_but_takeable_object = TRUE;
+ }
+ }
+ if(node->mFolderID.notNull())
+ {
+ if(category_id.isNull())
+ {
+ category_id = node->mFolderID;
+ }
+ else if(category_id != node->mFolderID)
+ {
+ // we have found two potential destinations. break out
+ // now and send to the default location.
+ category_id.setNull();
+ break;
+ }
+ }
+ }
+ if(category_id.notNull())
+ {
+ // there is an unambiguous destination. See if this agent has
+ // such a location and it is not in the trash or library
+ if(!gInventory.getCategory(category_id))
+ {
+ // nope, set to NULL.
+ category_id.setNull();
+ }
+ if(category_id.notNull())
+ {
+ // check trash
+ const LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash))
+ {
+ category_id.setNull();
+ }
+
+ // check library
+ if(gInventory.isObjectDescendentOf(category_id, gInventory.getLibraryRootFolderID()))
+ {
+ category_id.setNull();
+ }
+
+ // check inbox
+ const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX);
+ if (category_id == inbox_id || gInventory.isObjectDescendentOf(category_id, inbox_id))
+ {
+ category_id.setNull();
+ }
+ }
+ }
+ if(category_id.isNull())
+ {
+ category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+ }
+ LLSD payload;
+ payload["folder_id"] = category_id;
+
+ LLNotification::Params params("ConfirmObjectTakeLock");
+ params.payload(payload);
+ // MAINT-290
+ // Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez.
+ // Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened
+ params.functor.function(boost::bind(confirm_take, _1, _2, LLSelectMgr::instance().getSelection()));
+
+ if(locked_but_takeable_object ||
+ !you_own_everything)
+ {
+ if(locked_but_takeable_object && you_own_everything)
+ {
+ params.name("ConfirmObjectTakeLock");
+ }
+ else if(!locked_but_takeable_object && !you_own_everything)
+ {
+ params.name("ConfirmObjectTakeNoOwn");
+ }
+ else
+ {
+ params.name("ConfirmObjectTakeLockNoOwn");
+ }
+
+ LLNotifications::instance().add(params);
+ }
+ else
+ {
+ LLNotifications::instance().forceResponse(params, 0);
+ }
}
void handle_object_show_inspector()
{
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- LLViewerObject* objectp = selection->getFirstRootObject(TRUE);
- if (!objectp)
- {
- return;
- }
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ LLViewerObject* objectp = selection->getFirstRootObject(TRUE);
+ if (!objectp)
+ {
+ return;
+ }
- LLSD params;
- params["object_id"] = objectp->getID();
- LLFloaterReg::showInstance("inspect_object", params);
+ LLSD params;
+ params["object_id"] = objectp->getID();
+ LLFloaterReg::showInstance("inspect_object", params);
}
void handle_avatar_show_inspector()
{
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if(avatar)
- {
- LLSD params;
- params["avatar_id"] = avatar->getID();
- LLFloaterReg::showInstance("inspect_avatar", params);
- }
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ LLSD params;
+ params["avatar_id"] = avatar->getID();
+ LLFloaterReg::showInstance("inspect_avatar", params);
+ }
}
bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if(enable_take() && (option == 0))
- {
- derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID());
- }
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if(enable_take() && (option == 0))
+ {
+ derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID());
+ }
+ return false;
}
// You can take an item when it is public and transferrable, or when
@@ -5203,101 +5203,101 @@ bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelect
// one item selected can be copied to inventory.
BOOL enable_take()
{
- if (sitting_on_selection())
- {
- return FALSE;
- }
-
- for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- if (object->isAvatar())
- {
- // ...don't acquire avatars
- continue;
- }
+ if (sitting_on_selection())
+ {
+ return FALSE;
+ }
+
+ for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = node->getObject();
+ if (object->isAvatar())
+ {
+ // ...don't acquire avatars
+ continue;
+ }
#ifdef HACKED_GODLIKE_VIEWER
- return TRUE;
+ return TRUE;
#else
# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
- if (!LLGridManager::getInstance()->isInProductionGrid()
+ if (!LLGridManager::getInstance()->isInProductionGrid()
&& gAgent.isGodlike())
- {
- return TRUE;
- }
+ {
+ return TRUE;
+ }
# endif
- if(!object->isPermanentEnforced() &&
- ((node->mPermissions->allowTransferTo(gAgent.getID())
- && object->permModify())
- || (node->mPermissions->getOwner() == gAgent.getID())))
- {
- return !object->isAttachment();
- }
+ if(!object->isPermanentEnforced() &&
+ ((node->mPermissions->allowTransferTo(gAgent.getID())
+ && object->permModify())
+ || (node->mPermissions->getOwner() == gAgent.getID())))
+ {
+ return !object->isAttachment();
+ }
#endif
- }
- return FALSE;
+ }
+ return FALSE;
}
void handle_buy_or_take()
{
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- return;
- }
-
- if (is_selection_buy_not_take())
- {
- S32 total_price = selection_price();
-
- if (total_price <= gStatusBar->getBalance() || total_price == 0)
- {
- handle_buy();
- }
- else
- {
- LLStringUtil::format_map_t args;
- args["AMOUNT"] = llformat("%d", total_price);
- LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "this_object_costs", args ), total_price );
- }
- }
- else
- {
- handle_take();
- }
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ return;
+ }
+
+ if (is_selection_buy_not_take())
+ {
+ S32 total_price = selection_price();
+
+ if (total_price <= gStatusBar->getBalance() || total_price == 0)
+ {
+ handle_buy();
+ }
+ else
+ {
+ LLStringUtil::format_map_t args;
+ args["AMOUNT"] = llformat("%d", total_price);
+ LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "this_object_costs", args ), total_price );
+ }
+ }
+ else
+ {
+ handle_take();
+ }
}
bool visible_buy_object()
{
- return is_selection_buy_not_take() && enable_buy_object();
+ return is_selection_buy_not_take() && enable_buy_object();
}
bool visible_take_object()
{
- return !is_selection_buy_not_take() && enable_take();
+ return !is_selection_buy_not_take() && enable_take();
}
bool tools_visible_buy_object()
{
- return is_selection_buy_not_take();
+ return is_selection_buy_not_take();
}
bool tools_visible_take_object()
{
- return !is_selection_buy_not_take();
+ return !is_selection_buy_not_take();
}
class LLToolsEnableBuyOrTake : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool is_buy = is_selection_buy_not_take();
- bool new_value = is_buy ? enable_buy_object() : enable_take();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool is_buy = is_selection_buy_not_take();
+ bool new_value = is_buy ? enable_buy_object() : enable_take();
+ return new_value;
+ }
};
// This is a small helper function to determine if we have a buy or a
@@ -5318,255 +5318,255 @@ class LLToolsEnableBuyOrTake : public view_listener_t
// FALSE if selection is a 'take'
BOOL is_selection_buy_not_take()
{
- for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* obj = node->getObject();
- if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
- {
- // you do not own the object and it is for sale, thus,
- // it's a buy
- return TRUE;
- }
- }
- return FALSE;
+ for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* obj = node->getObject();
+ if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
+ {
+ // you do not own the object and it is for sale, thus,
+ // it's a buy
+ return TRUE;
+ }
+ }
+ return FALSE;
}
S32 selection_price()
{
- S32 total_price = 0;
- for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* obj = node->getObject();
- if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
- {
- // you do not own the object and it is for sale.
- // Add its price.
- total_price += node->mSaleInfo.getSalePrice();
- }
- }
-
- return total_price;
+ S32 total_price = 0;
+ for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* obj = node->getObject();
+ if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
+ {
+ // you do not own the object and it is for sale.
+ // Add its price.
+ total_price += node->mSaleInfo.getSalePrice();
+ }
+ }
+
+ return total_price;
}
/*
bool callback_show_buy_currency(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (0 == option)
- {
- LL_INFOS() << "Loading page " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL") << LL_ENDL;
- LLWeb::loadURL(LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL"));
- }
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ LL_INFOS() << "Loading page " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL") << LL_ENDL;
+ LLWeb::loadURL(LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL"));
+ }
+ return false;
}
*/
void show_buy_currency(const char* extra)
{
- // Don't show currency web page for branded clients.
+ // Don't show currency web page for branded clients.
/*
- std::ostringstream mesg;
- if (extra != NULL)
- {
- mesg << extra << "\n \n";
- }
- mesg << "Go to " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")<< "\nfor information on purchasing currency?";
+ std::ostringstream mesg;
+ if (extra != NULL)
+ {
+ mesg << extra << "\n \n";
+ }
+ mesg << "Go to " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")<< "\nfor information on purchasing currency?";
*/
- LLSD args;
- if (extra != NULL)
- {
- args["EXTRA"] = extra;
- }
- LLNotificationsUtil::add("PromptGoToCurrencyPage", args);//, LLSD(), callback_show_buy_currency);
+ LLSD args;
+ if (extra != NULL)
+ {
+ args["EXTRA"] = extra;
+ }
+ LLNotificationsUtil::add("PromptGoToCurrencyPage", args);//, LLSD(), callback_show_buy_currency);
}
void handle_buy()
{
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
-
- LLSaleInfo sale_info;
- BOOL valid = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info);
- if (!valid) return;
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
- S32 price = sale_info.getSalePrice();
+ LLSaleInfo sale_info;
+ BOOL valid = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info);
+ if (!valid) return;
- if (price > 0 && price > gStatusBar->getBalance())
- {
- LLStringUtil::format_map_t args;
- args["AMOUNT"] = llformat("%d", price);
- LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("this_object_costs", args), price );
- return;
- }
+ S32 price = sale_info.getSalePrice();
+
+ if (price > 0 && price > gStatusBar->getBalance())
+ {
+ LLStringUtil::format_map_t args;
+ args["AMOUNT"] = llformat("%d", price);
+ LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("this_object_costs", args), price );
+ return;
+ }
- if (sale_info.getSaleType() == LLSaleInfo::FS_CONTENTS)
- {
- handle_buy_contents(sale_info);
- }
- else
- {
- handle_buy_object(sale_info);
- }
+ if (sale_info.getSaleType() == LLSaleInfo::FS_CONTENTS)
+ {
+ handle_buy_contents(sale_info);
+ }
+ else
+ {
+ handle_buy_object(sale_info);
+ }
}
bool anyone_copy_selection(LLSelectNode* nodep)
{
- bool perm_copy = (bool)(nodep->getObject()->permCopy());
- bool all_copy = (bool)(nodep->mPermissions->getMaskEveryone() & PERM_COPY);
- return perm_copy && all_copy;
+ bool perm_copy = (bool)(nodep->getObject()->permCopy());
+ bool all_copy = (bool)(nodep->mPermissions->getMaskEveryone() & PERM_COPY);
+ return perm_copy && all_copy;
}
bool for_sale_selection(LLSelectNode* nodep)
{
- return nodep->mSaleInfo.isForSale()
- && nodep->mPermissions->getMaskOwner() & PERM_TRANSFER
- && (nodep->mPermissions->getMaskOwner() & PERM_COPY
- || nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY);
+ return nodep->mSaleInfo.isForSale()
+ && nodep->mPermissions->getMaskOwner() & PERM_TRANSFER
+ && (nodep->mPermissions->getMaskOwner() & PERM_COPY
+ || nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY);
}
BOOL sitting_on_selection()
{
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
- if (!node)
- {
- return FALSE;
- }
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+ if (!node)
+ {
+ return FALSE;
+ }
- if (!node->mValid)
- {
- return FALSE;
- }
+ if (!node->mValid)
+ {
+ return FALSE;
+ }
- LLViewerObject* root_object = node->getObject();
- if (!root_object)
- {
- return FALSE;
- }
+ LLViewerObject* root_object = node->getObject();
+ if (!root_object)
+ {
+ return FALSE;
+ }
- // Need to determine if avatar is sitting on this object
- if (!isAgentAvatarValid()) return FALSE;
+ // Need to determine if avatar is sitting on this object
+ if (!isAgentAvatarValid()) return FALSE;
- return (gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == root_object);
+ return (gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == root_object);
}
class LLToolsSaveToObjectInventory : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
- if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
- {
- // *TODO: check to see if the fromtaskid object exists.
- derez_objects(DRD_SAVE_INTO_TASK_INVENTORY, node->mFromTaskID);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+ if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
+ {
+ // *TODO: check to see if the fromtaskid object exists.
+ derez_objects(DRD_SAVE_INTO_TASK_INVENTORY, node->mFromTaskID);
+ }
+ return true;
+ }
};
class LLToolsEnablePathfinding : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion();
+ }
};
class LLToolsEnablePathfindingView : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLPathfindingManager::getInstance()->isPathfindingViewEnabled();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLPathfindingManager::getInstance()->isPathfindingViewEnabled();
+ }
};
class LLToolsDoPathfindingRebakeRegion : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool hasPathfinding = (LLPathfindingManager::getInstance() != NULL);
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool hasPathfinding = (LLPathfindingManager::getInstance() != NULL);
- if (hasPathfinding)
- {
- LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh();
- }
+ if (hasPathfinding)
+ {
+ LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh();
+ }
- return hasPathfinding;
- }
+ return hasPathfinding;
+ }
};
class LLToolsEnablePathfindingRebakeRegion : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool returnValue = false;
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool returnValue = false;
if (LLNavigationBar::instanceExists())
{
returnValue = LLNavigationBar::getInstance()->isRebakeNavMeshAvailable();
}
- return returnValue;
- }
+ return returnValue;
+ }
};
// Round the position of all root objects to the grid
class LLToolsSnapObjectXY : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- F64 snap_size = (F64)gSavedSettings.getF32("GridResolution");
-
- for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* obj = node->getObject();
- if (obj->permModify())
- {
- LLVector3d pos_global = obj->getPositionGlobal();
- F64 round_x = fmod(pos_global.mdV[VX], snap_size);
- if (round_x < snap_size * 0.5)
- {
- // closer to round down
- pos_global.mdV[VX] -= round_x;
- }
- else
- {
- // closer to round up
- pos_global.mdV[VX] -= round_x;
- pos_global.mdV[VX] += snap_size;
- }
-
- F64 round_y = fmod(pos_global.mdV[VY], snap_size);
- if (round_y < snap_size * 0.5)
- {
- pos_global.mdV[VY] -= round_y;
- }
- else
- {
- pos_global.mdV[VY] -= round_y;
- pos_global.mdV[VY] += snap_size;
- }
-
- obj->setPositionGlobal(pos_global, FALSE);
- }
- }
- LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ F64 snap_size = (F64)gSavedSettings.getF32("GridResolution");
+
+ for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* obj = node->getObject();
+ if (obj->permModify())
+ {
+ LLVector3d pos_global = obj->getPositionGlobal();
+ F64 round_x = fmod(pos_global.mdV[VX], snap_size);
+ if (round_x < snap_size * 0.5)
+ {
+ // closer to round down
+ pos_global.mdV[VX] -= round_x;
+ }
+ else
+ {
+ // closer to round up
+ pos_global.mdV[VX] -= round_x;
+ pos_global.mdV[VX] += snap_size;
+ }
+
+ F64 round_y = fmod(pos_global.mdV[VY], snap_size);
+ if (round_y < snap_size * 0.5)
+ {
+ pos_global.mdV[VY] -= round_y;
+ }
+ else
+ {
+ pos_global.mdV[VY] -= round_y;
+ pos_global.mdV[VY] += snap_size;
+ }
+
+ obj->setPositionGlobal(pos_global, FALSE);
+ }
+ }
+ LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
+ return true;
+ }
};
// Determine if the option to cycle between linked prims is shown
class LLToolsEnableSelectNextPart : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
+ bool handleEvent(const LLSD& userdata)
+ {
bool new_value = (!LLSelectMgr::getInstance()->getSelection()->isEmpty()
&& (gSavedSettings.getBOOL("EditLinkedParts")
|| LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()));
- return new_value;
- }
+ return new_value;
+ }
};
// Cycle selection through linked children or/and faces in selected object.
@@ -5641,61 +5641,61 @@ class LLToolsSelectNextPartFace : public view_listener_t
}
}
- S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
- if (cycle_linked && object_count && restart_face_on_part)
- {
- LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
- if (selected && selected->getRootEdit())
- {
- LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren();
- children.push_front(selected->getRootEdit()); // need root in the list too
-
- for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter)
- {
- if ((*iter)->isSelected())
- {
- if (object_count > 1 && (fwd || prev)) // multiple selection, find first or last selected if not include
- {
- to_select = *iter;
- if (fwd)
- {
- // stop searching if going forward; repeat to get last hit if backward
- break;
- }
- }
- else if ((object_count == 1) || (ifwd || iprev)) // single selection or include
- {
- if (fwd || ifwd)
- {
- ++iter;
- while (iter != children.end() && ((*iter)->isAvatar() || (ifwd && (*iter)->isSelected())))
- {
- ++iter; // skip sitting avatars and selected if include
- }
- }
- else // backward
- {
- iter = (iter == children.begin() ? children.end() : iter);
- --iter;
- while (iter != children.begin() && ((*iter)->isAvatar() || (iprev && (*iter)->isSelected())))
- {
- --iter; // skip sitting avatars and selected if include
- }
- }
- iter = (iter == children.end() ? children.begin() : iter);
- to_select = *iter;
- break;
- }
- }
- }
- }
- }
+ S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ if (cycle_linked && object_count && restart_face_on_part)
+ {
+ LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ if (selected && selected->getRootEdit())
+ {
+ LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren();
+ children.push_front(selected->getRootEdit()); // need root in the list too
+
+ for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter)
+ {
+ if ((*iter)->isSelected())
+ {
+ if (object_count > 1 && (fwd || prev)) // multiple selection, find first or last selected if not include
+ {
+ to_select = *iter;
+ if (fwd)
+ {
+ // stop searching if going forward; repeat to get last hit if backward
+ break;
+ }
+ }
+ else if ((object_count == 1) || (ifwd || iprev)) // single selection or include
+ {
+ if (fwd || ifwd)
+ {
+ ++iter;
+ while (iter != children.end() && ((*iter)->isAvatar() || (ifwd && (*iter)->isSelected())))
+ {
+ ++iter; // skip sitting avatars and selected if include
+ }
+ }
+ else // backward
+ {
+ iter = (iter == children.begin() ? children.end() : iter);
+ --iter;
+ while (iter != children.begin() && ((*iter)->isAvatar() || (iprev && (*iter)->isSelected())))
+ {
+ --iter; // skip sitting avatars and selected if include
+ }
+ }
+ iter = (iter == children.end() ? children.begin() : iter);
+ to_select = *iter;
+ break;
+ }
+ }
+ }
+ }
+ }
if (to_select)
{
if (gFocusMgr.childHasKeyboardFocus(gFloaterTools))
{
- gFocusMgr.setKeyboardFocus(NULL); // force edit toolbox to commit any changes
+ gFocusMgr.setKeyboardFocus(NULL); // force edit toolbox to commit any changes
}
if (fwd || prev)
{
@@ -5723,455 +5723,455 @@ class LLToolsSelectNextPartFace : public view_listener_t
}
return true;
}
- return true;
- }
+ return true;
+ }
};
class LLToolsStopAllAnimations : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gAgent.stopCurrentAnimations();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gAgent.stopCurrentAnimations();
+ return true;
+ }
};
class LLToolsReleaseKeys : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gAgent.forceReleaseControls();
+ bool handleEvent(const LLSD& userdata)
+ {
+ gAgent.forceReleaseControls();
- return true;
- }
+ return true;
+ }
};
class LLToolsEnableReleaseKeys : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return gAgent.anyControlGrabbed();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return gAgent.anyControlGrabbed();
+ }
};
class LLEditEnableCut : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCut();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCut();
+ return new_value;
+ }
};
class LLEditCut : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if( LLEditMenuHandler::gEditMenuHandler )
- {
- LLEditMenuHandler::gEditMenuHandler->cut();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if( LLEditMenuHandler::gEditMenuHandler )
+ {
+ LLEditMenuHandler::gEditMenuHandler->cut();
+ }
+ return true;
+ }
};
class LLEditEnableCopy : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCopy();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCopy();
+ return new_value;
+ }
};
class LLEditCopy : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if( LLEditMenuHandler::gEditMenuHandler )
- {
- LLEditMenuHandler::gEditMenuHandler->copy();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if( LLEditMenuHandler::gEditMenuHandler )
+ {
+ LLEditMenuHandler::gEditMenuHandler->copy();
+ }
+ return true;
+ }
};
class LLEditEnablePaste : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canPaste();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canPaste();
+ return new_value;
+ }
};
class LLEditPaste : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if( LLEditMenuHandler::gEditMenuHandler )
- {
- LLEditMenuHandler::gEditMenuHandler->paste();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if( LLEditMenuHandler::gEditMenuHandler )
+ {
+ LLEditMenuHandler::gEditMenuHandler->paste();
+ }
+ return true;
+ }
};
class LLEditEnableDelete : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete();
+ return new_value;
+ }
};
class LLEditDelete : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- // If a text field can do a deletion, it gets precedence over deleting
- // an object in the world.
- if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete())
- {
- LLEditMenuHandler::gEditMenuHandler->doDelete();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ // If a text field can do a deletion, it gets precedence over deleting
+ // an object in the world.
+ if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete())
+ {
+ LLEditMenuHandler::gEditMenuHandler->doDelete();
+ }
- // and close any pie/context menus when done
- gMenuHolder->hideMenus();
+ // and close any pie/context menus when done
+ gMenuHolder->hideMenus();
- // When deleting an object we may not actually be done
- // Keep selection so we know what to delete when confirmation is needed about the delete
- gMenuObject->hide();
- return true;
- }
+ // When deleting an object we may not actually be done
+ // Keep selection so we know what to delete when confirmation is needed about the delete
+ gMenuObject->hide();
+ return true;
+ }
};
void handle_spellcheck_replace_with_suggestion(const LLUICtrl* ctrl, const LLSD& param)
{
- const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
- LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
- if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) )
- {
- return;
- }
+ const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
+ LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
+ if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) )
+ {
+ return;
+ }
- U32 index = 0;
- if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) )
- {
- return;
- }
+ U32 index = 0;
+ if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) )
+ {
+ return;
+ }
- spellcheck_handler->replaceWithSuggestion(index);
+ spellcheck_handler->replaceWithSuggestion(index);
}
bool visible_spellcheck_suggestion(LLUICtrl* ctrl, const LLSD& param)
{
- LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(ctrl);
- const LLContextMenu* menu = (item) ? dynamic_cast<const LLContextMenu*>(item->getParent()) : NULL;
- const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
- if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) )
- {
- return false;
- }
+ LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(ctrl);
+ const LLContextMenu* menu = (item) ? dynamic_cast<const LLContextMenu*>(item->getParent()) : NULL;
+ const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
+ if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) )
+ {
+ return false;
+ }
- U32 index = 0;
- if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) )
- {
- return false;
- }
+ U32 index = 0;
+ if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) )
+ {
+ return false;
+ }
- item->setLabel(spellcheck_handler->getSuggestion(index));
- return true;
+ item->setLabel(spellcheck_handler->getSuggestion(index));
+ return true;
}
void handle_spellcheck_add_to_dictionary(const LLUICtrl* ctrl)
{
- const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
- LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
- if ( (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()) )
- {
- spellcheck_handler->addToDictionary();
- }
+ const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
+ LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
+ if ( (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()) )
+ {
+ spellcheck_handler->addToDictionary();
+ }
}
bool enable_spellcheck_add_to_dictionary(const LLUICtrl* ctrl)
{
- const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
- const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
- return (spellcheck_handler) && (spellcheck_handler->canAddToDictionary());
+ const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
+ const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
+ return (spellcheck_handler) && (spellcheck_handler->canAddToDictionary());
}
void handle_spellcheck_add_to_ignore(const LLUICtrl* ctrl)
{
- const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
- LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
- if ( (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()) )
- {
- spellcheck_handler->addToIgnore();
- }
+ const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
+ LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
+ if ( (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()) )
+ {
+ spellcheck_handler->addToIgnore();
+ }
}
bool enable_spellcheck_add_to_ignore(const LLUICtrl* ctrl)
{
- const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
- const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
- return (spellcheck_handler) && (spellcheck_handler->canAddToIgnore());
+ const LLContextMenu* menu = dynamic_cast<const LLContextMenu*>(ctrl->getParent());
+ const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast<const LLSpellCheckMenuHandler*>(menu->getSpawningView()) : NULL;
+ return (spellcheck_handler) && (spellcheck_handler->canAddToIgnore());
}
bool enable_object_return()
{
- return (!LLSelectMgr::getInstance()->getSelection()->isEmpty() &&
- (gAgent.isGodlike() || can_derez(DRD_RETURN_TO_OWNER)));
+ return (!LLSelectMgr::getInstance()->getSelection()->isEmpty() &&
+ (gAgent.isGodlike() || can_derez(DRD_RETURN_TO_OWNER)));
}
bool enable_object_delete()
{
- bool new_value =
+ bool new_value =
#ifdef HACKED_GODLIKE_VIEWER
- TRUE;
+ TRUE;
#else
# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
- (!LLGridManager::getInstance()->isInProductionGrid()
+ (!LLGridManager::getInstance()->isInProductionGrid()
&& gAgent.isGodlike()) ||
# endif
- LLSelectMgr::getInstance()->canDoDelete();
+ LLSelectMgr::getInstance()->canDoDelete();
#endif
- return new_value;
+ return new_value;
}
class LLObjectsReturnPackage
{
public:
- LLObjectsReturnPackage() : mObjectSelection(), mReturnableObjects(), mError(), mFirstRegion(NULL) {};
- ~LLObjectsReturnPackage()
- {
- mObjectSelection.clear();
- mReturnableObjects.clear();
- mError.clear();
- mFirstRegion = NULL;
- };
+ LLObjectsReturnPackage() : mObjectSelection(), mReturnableObjects(), mError(), mFirstRegion(NULL) {};
+ ~LLObjectsReturnPackage()
+ {
+ mObjectSelection.clear();
+ mReturnableObjects.clear();
+ mError.clear();
+ mFirstRegion = NULL;
+ };
- LLObjectSelectionHandle mObjectSelection;
- std::vector<LLViewerObjectPtr> mReturnableObjects;
- std::string mError;
- LLViewerRegion *mFirstRegion;
+ LLObjectSelectionHandle mObjectSelection;
+ std::vector<LLViewerObjectPtr> mReturnableObjects;
+ std::string mError;
+ LLViewerRegion *mFirstRegion;
};
static void return_objects(LLObjectsReturnPackage *objectsReturnPackage, const LLSD& notification, const LLSD& response)
{
- if (LLNotificationsUtil::getSelectedOption(notification, response) == 0)
- {
- // Ignore category ID for this derez destination.
- derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, objectsReturnPackage->mFirstRegion, objectsReturnPackage->mError, &objectsReturnPackage->mReturnableObjects);
- }
+ if (LLNotificationsUtil::getSelectedOption(notification, response) == 0)
+ {
+ // Ignore category ID for this derez destination.
+ derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, objectsReturnPackage->mFirstRegion, objectsReturnPackage->mError, &objectsReturnPackage->mReturnableObjects);
+ }
- delete objectsReturnPackage;
+ delete objectsReturnPackage;
}
void handle_object_return()
{
- if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- LLObjectsReturnPackage *objectsReturnPackage = new LLObjectsReturnPackage();
- objectsReturnPackage->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
+ if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ LLObjectsReturnPackage *objectsReturnPackage = new LLObjectsReturnPackage();
+ objectsReturnPackage->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
- // Save selected objects, so that we still know what to return after the confirmation dialog resets selection.
- get_derezzable_objects(DRD_RETURN_TO_OWNER, objectsReturnPackage->mError, objectsReturnPackage->mFirstRegion, &objectsReturnPackage->mReturnableObjects);
+ // Save selected objects, so that we still know what to return after the confirmation dialog resets selection.
+ get_derezzable_objects(DRD_RETURN_TO_OWNER, objectsReturnPackage->mError, objectsReturnPackage->mFirstRegion, &objectsReturnPackage->mReturnableObjects);
- LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&return_objects, objectsReturnPackage, _1, _2));
- }
+ LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&return_objects, objectsReturnPackage, _1, _2));
+ }
}
void handle_object_delete()
{
- if (LLSelectMgr::getInstance())
- {
- LLSelectMgr::getInstance()->doDelete();
- }
+ if (LLSelectMgr::getInstance())
+ {
+ LLSelectMgr::getInstance()->doDelete();
+ }
- // and close any pie/context menus when done
- gMenuHolder->hideMenus();
+ // and close any pie/context menus when done
+ gMenuHolder->hideMenus();
- // When deleting an object we may not actually be done
- // Keep selection so we know what to delete when confirmation is needed about the delete
- gMenuObject->hide();
- return;
+ // When deleting an object we may not actually be done
+ // Keep selection so we know what to delete when confirmation is needed about the delete
+ gMenuObject->hide();
+ return;
}
void handle_force_delete(void*)
{
- LLSelectMgr::getInstance()->selectForceDelete();
+ LLSelectMgr::getInstance()->selectForceDelete();
}
class LLViewEnableJoystickFlycam : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = (gSavedSettings.getBOOL("JoystickEnabled") && gSavedSettings.getBOOL("JoystickFlycamEnabled"));
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = (gSavedSettings.getBOOL("JoystickEnabled") && gSavedSettings.getBOOL("JoystickFlycamEnabled"));
+ return new_value;
+ }
};
class LLViewEnableLastChatter : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- // *TODO: add check that last chatter is in range
- bool new_value = (gAgentCamera.cameraThirdPerson() && gAgent.getLastChatter().notNull());
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ // *TODO: add check that last chatter is in range
+ bool new_value = (gAgentCamera.cameraThirdPerson() && gAgent.getLastChatter().notNull());
+ return new_value;
+ }
};
class LLEditEnableDeselect : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDeselect();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDeselect();
+ return new_value;
+ }
};
class LLEditDeselect : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if( LLEditMenuHandler::gEditMenuHandler )
- {
- LLEditMenuHandler::gEditMenuHandler->deselect();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if( LLEditMenuHandler::gEditMenuHandler )
+ {
+ LLEditMenuHandler::gEditMenuHandler->deselect();
+ }
+ return true;
+ }
};
class LLEditEnableSelectAll : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canSelectAll();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canSelectAll();
+ return new_value;
+ }
};
class LLEditSelectAll : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if( LLEditMenuHandler::gEditMenuHandler )
- {
- LLEditMenuHandler::gEditMenuHandler->selectAll();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if( LLEditMenuHandler::gEditMenuHandler )
+ {
+ LLEditMenuHandler::gEditMenuHandler->selectAll();
+ }
+ return true;
+ }
};
class LLEditEnableUndo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo();
+ return new_value;
+ }
};
class LLEditUndo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo() )
- {
- LLEditMenuHandler::gEditMenuHandler->undo();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo() )
+ {
+ LLEditMenuHandler::gEditMenuHandler->undo();
+ }
+ return true;
+ }
};
class LLEditEnableRedo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo();
+ return new_value;
+ }
};
class LLEditRedo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo() )
- {
- LLEditMenuHandler::gEditMenuHandler->redo();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo() )
+ {
+ LLEditMenuHandler::gEditMenuHandler->redo();
+ }
+ return true;
+ }
};
void print_object_info(void*)
{
- LLSelectMgr::getInstance()->selectionDump();
+ LLSelectMgr::getInstance()->selectionDump();
}
void print_agent_nvpairs(void*)
{
- LLViewerObject *objectp;
+ LLViewerObject *objectp;
- LL_INFOS() << "Agent Name Value Pairs" << LL_ENDL;
+ LL_INFOS() << "Agent Name Value Pairs" << LL_ENDL;
- objectp = gObjectList.findObject(gAgentID);
- if (objectp)
- {
- objectp->printNameValuePairs();
- }
- else
- {
- LL_INFOS() << "Can't find agent object" << LL_ENDL;
- }
+ objectp = gObjectList.findObject(gAgentID);
+ if (objectp)
+ {
+ objectp->printNameValuePairs();
+ }
+ else
+ {
+ LL_INFOS() << "Can't find agent object" << LL_ENDL;
+ }
- LL_INFOS() << "Camera at " << gAgentCamera.getCameraPositionGlobal() << LL_ENDL;
+ LL_INFOS() << "Camera at " << gAgentCamera.getCameraPositionGlobal() << LL_ENDL;
}
void show_debug_menus()
{
- // this might get called at login screen where there is no menu so only toggle it if one exists
- if ( gMenuBarView )
- {
- BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
- BOOL qamode = gSavedSettings.getBOOL("QAMode");
-
- gMenuBarView->setItemVisible("Advanced", debug);
-// gMenuBarView->setItemEnabled("Advanced", debug); // Don't disable Advanced keyboard shortcuts when hidden
-
- gMenuBarView->setItemVisible("Debug", qamode);
- gMenuBarView->setItemEnabled("Debug", qamode);
-
- gMenuBarView->setItemVisible("Develop", qamode);
- gMenuBarView->setItemEnabled("Develop", qamode);
-
- // Server ('Admin') menu hidden when not in godmode.
- const bool show_server_menu = (gAgent.getGodLevel() > GOD_NOT || (debug && gAgent.getAdminOverride()));
- gMenuBarView->setItemVisible("Admin", show_server_menu);
- gMenuBarView->setItemEnabled("Admin", show_server_menu);
- }
- if (gLoginMenuBarView)
- {
- BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
- gLoginMenuBarView->setItemVisible("Debug", debug);
- gLoginMenuBarView->setItemEnabled("Debug", debug);
- }
+ // this might get called at login screen where there is no menu so only toggle it if one exists
+ if ( gMenuBarView )
+ {
+ BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
+ BOOL qamode = gSavedSettings.getBOOL("QAMode");
+
+ gMenuBarView->setItemVisible("Advanced", debug);
+// gMenuBarView->setItemEnabled("Advanced", debug); // Don't disable Advanced keyboard shortcuts when hidden
+
+ gMenuBarView->setItemVisible("Debug", qamode);
+ gMenuBarView->setItemEnabled("Debug", qamode);
+
+ gMenuBarView->setItemVisible("Develop", qamode);
+ gMenuBarView->setItemEnabled("Develop", qamode);
+
+ // Server ('Admin') menu hidden when not in godmode.
+ const bool show_server_menu = (gAgent.getGodLevel() > GOD_NOT || (debug && gAgent.getAdminOverride()));
+ gMenuBarView->setItemVisible("Admin", show_server_menu);
+ gMenuBarView->setItemEnabled("Admin", show_server_menu);
+ }
+ if (gLoginMenuBarView)
+ {
+ BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
+ gLoginMenuBarView->setItemVisible("Debug", debug);
+ gLoginMenuBarView->setItemEnabled("Debug", debug);
+ }
}
void toggle_debug_menus(void*)
{
- BOOL visible = ! gSavedSettings.getBOOL("UseDebugMenus");
- gSavedSettings.setBOOL("UseDebugMenus", visible);
- show_debug_menus();
+ BOOL visible = ! gSavedSettings.getBOOL("UseDebugMenus");
+ gSavedSettings.setBOOL("UseDebugMenus", visible);
+ show_debug_menus();
}
@@ -6182,292 +6182,292 @@ void toggle_debug_menus(void*)
// void handle_export_selected( void * )
// {
-// LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-// if (selection->isEmpty())
-// {
-// return;
-// }
-// LL_INFOS() << "Exporting selected objects:" << LL_ENDL;
-
-// gExporterRequestID.generate();
-// gExportDirectory = "";
-
-// LLMessageSystem* msg = gMessageSystem;
-// msg->newMessageFast(_PREHASH_ObjectExportSelected);
-// msg->nextBlockFast(_PREHASH_AgentData);
-// msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-// msg->addUUIDFast(_PREHASH_RequestID, gExporterRequestID);
-// msg->addS16Fast(_PREHASH_VolumeDetail, 4);
-
-// for (LLObjectSelection::root_iterator iter = selection->root_begin();
-// iter != selection->root_end(); iter++)
-// {
-// LLSelectNode* node = *iter;
-// LLViewerObject* object = node->getObject();
-// msg->nextBlockFast(_PREHASH_ObjectData);
-// msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
-// LL_INFOS() << "Object: " << object->getID() << LL_ENDL;
-// }
-// msg->sendReliable(gAgent.getRegion()->getHost());
-
-// gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects...");
+// LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+// if (selection->isEmpty())
+// {
+// return;
+// }
+// LL_INFOS() << "Exporting selected objects:" << LL_ENDL;
+
+// gExporterRequestID.generate();
+// gExportDirectory = "";
+
+// LLMessageSystem* msg = gMessageSystem;
+// msg->newMessageFast(_PREHASH_ObjectExportSelected);
+// msg->nextBlockFast(_PREHASH_AgentData);
+// msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+// msg->addUUIDFast(_PREHASH_RequestID, gExporterRequestID);
+// msg->addS16Fast(_PREHASH_VolumeDetail, 4);
+
+// for (LLObjectSelection::root_iterator iter = selection->root_begin();
+// iter != selection->root_end(); iter++)
+// {
+// LLSelectNode* node = *iter;
+// LLViewerObject* object = node->getObject();
+// msg->nextBlockFast(_PREHASH_ObjectData);
+// msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
+// LL_INFOS() << "Object: " << object->getID() << LL_ENDL;
+// }
+// msg->sendReliable(gAgent.getRegion()->getHost());
+
+// gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects...");
// }
//
class LLCommunicateNearbyChat : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterIMContainer* im_box = LLFloaterIMContainer::getInstance();
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterIMContainer* im_box = LLFloaterIMContainer::getInstance();
LLFloaterIMNearbyChat* floater_nearby = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
- if (floater_nearby->isInVisibleChain() && !floater_nearby->isTornOff()
+ if (floater_nearby->isInVisibleChain() && !floater_nearby->isTornOff()
&& im_box->getSelectedSession() == LLUUID() && im_box->getConversationListItemSize() > 1)
- {
- im_box->selectNextorPreviousConversation(false);
- }
- else
- {
- LLFloaterReg::toggleInstanceOrBringToFront("nearby_chat");
- }
- return true;
- }
+ {
+ im_box->selectNextorPreviousConversation(false);
+ }
+ else
+ {
+ LLFloaterReg::toggleInstanceOrBringToFront("nearby_chat");
+ }
+ return true;
+ }
};
class LLWorldSetHomeLocation : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- // we just send the message and let the server check for failure cases
- // server will echo back a "Home position set." alert if it succeeds
- // and the home location screencapture happens when that alert is recieved
- gAgent.setStartPosition(START_LOCATION_ID_HOME);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ // we just send the message and let the server check for failure cases
+ // server will echo back a "Home position set." alert if it succeeds
+ // and the home location screencapture happens when that alert is recieved
+ gAgent.setStartPosition(START_LOCATION_ID_HOME);
+ return true;
+ }
};
class LLWorldLindenHome : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string url = LLFloaterLandHoldings::sHasLindenHome ? LLTrans::getString("lindenhomes_my_home_url") : LLTrans::getString("lindenhomes_get_home_url");
- LLWeb::loadURL(url);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string url = LLFloaterLandHoldings::sHasLindenHome ? LLTrans::getString("lindenhomes_my_home_url") : LLTrans::getString("lindenhomes_get_home_url");
+ LLWeb::loadURL(url);
+ return true;
+ }
};
class LLWorldTeleportHome : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gAgent.teleportHome();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gAgent.teleportHome();
+ return true;
+ }
};
class LLWorldAlwaysRun : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- // as well as altering the default walk-vs-run state,
- // we also change the *current* walk-vs-run state.
- if (gAgent.getAlwaysRun())
- {
- gAgent.clearAlwaysRun();
- gAgent.clearRunning();
- }
- else
- {
- gAgent.setAlwaysRun();
- gAgent.setRunning();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ // as well as altering the default walk-vs-run state,
+ // we also change the *current* walk-vs-run state.
+ if (gAgent.getAlwaysRun())
+ {
+ gAgent.clearAlwaysRun();
+ gAgent.clearRunning();
+ }
+ else
+ {
+ gAgent.setAlwaysRun();
+ gAgent.setRunning();
+ }
- // tell the simulator.
- gAgent.sendWalkRun(gAgent.getAlwaysRun());
+ // tell the simulator.
+ gAgent.sendWalkRun(gAgent.getAlwaysRun());
- // Update Movement Controls according to AlwaysRun mode
- LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun());
+ // Update Movement Controls according to AlwaysRun mode
+ LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun());
- return true;
- }
+ return true;
+ }
};
class LLWorldCheckAlwaysRun : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gAgent.getAlwaysRun();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gAgent.getAlwaysRun();
+ return new_value;
+ }
};
class LLWorldSetAway : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (gAgent.getAFK())
- {
- gAgent.clearAFK();
- }
- else
- {
- gAgent.setAFK();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgent.getAFK())
+ {
+ gAgent.clearAFK();
+ }
+ else
+ {
+ gAgent.setAFK();
+ }
+ return true;
+ }
};
class LLWorldSetDoNotDisturb : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (gAgent.isDoNotDisturb())
- {
- gAgent.setDoNotDisturb(false);
- }
- else
- {
- gAgent.setDoNotDisturb(true);
- LLNotificationsUtil::add("DoNotDisturbModeSet");
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgent.isDoNotDisturb())
+ {
+ gAgent.setDoNotDisturb(false);
+ }
+ else
+ {
+ gAgent.setDoNotDisturb(true);
+ LLNotificationsUtil::add("DoNotDisturbModeSet");
+ }
+ return true;
+ }
};
class LLWorldCreateLandmark : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterReg::showInstance("add_landmark");
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterReg::showInstance("add_landmark");
- return true;
- }
+ return true;
+ }
};
class LLWorldPlaceProfile : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "agent"));
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "agent"));
- return true;
- }
+ return true;
+ }
};
void handle_look_at_selection(const LLSD& param)
{
- const F32 PADDING_FACTOR = 1.75f;
- BOOL zoom = (param.asString() == "zoom");
- if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-
- LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
- F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
- F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
-
- LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent();
- obj_to_cam.normVec();
-
- LLUUID object_id;
- if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())
- {
- object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID;
- }
- if (zoom)
- {
- // Make sure we are not increasing the distance between the camera and object
- LLVector3d orig_distance = gAgentCamera.getCameraPositionGlobal() - LLSelectMgr::getInstance()->getSelectionCenterGlobal();
- distance = llmin(distance, (F32) orig_distance.length());
-
- gAgentCamera.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance),
- LLSelectMgr::getInstance()->getSelectionCenterGlobal(),
- object_id );
-
- }
- else
- {
- gAgentCamera.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id );
- }
- }
+ const F32 PADDING_FACTOR = 1.75f;
+ BOOL zoom = (param.asString() == "zoom");
+ if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+
+ LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
+ F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
+ F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
+
+ LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent();
+ obj_to_cam.normVec();
+
+ LLUUID object_id;
+ if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())
+ {
+ object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID;
+ }
+ if (zoom)
+ {
+ // Make sure we are not increasing the distance between the camera and object
+ LLVector3d orig_distance = gAgentCamera.getCameraPositionGlobal() - LLSelectMgr::getInstance()->getSelectionCenterGlobal();
+ distance = llmin(distance, (F32) orig_distance.length());
+
+ gAgentCamera.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance),
+ LLSelectMgr::getInstance()->getSelectionCenterGlobal(),
+ object_id );
+
+ }
+ else
+ {
+ gAgentCamera.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id );
+ }
+ }
}
void handle_zoom_to_object(LLUUID object_id)
{
- const F32 PADDING_FACTOR = 2.f;
+ const F32 PADDING_FACTOR = 2.f;
- LLViewerObject* object = gObjectList.findObject(object_id);
+ LLViewerObject* object = gObjectList.findObject(object_id);
- if (object)
- {
- gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ if (object)
+ {
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
- LLBBox bbox = object->getBoundingBoxAgent() ;
- F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
- F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
+ LLBBox bbox = object->getBoundingBoxAgent() ;
+ F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
+ F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
- LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent();
- obj_to_cam.normVec();
+ LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent();
+ obj_to_cam.normVec();
- LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
+ LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
- gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance),
- object_center_global,
- object_id );
- }
+ gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance),
+ object_center_global,
+ object_id );
+ }
}
class LLAvatarInviteToGroup : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if(avatar)
- {
- LLAvatarActions::inviteToGroup(avatar->getID());
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ LLAvatarActions::inviteToGroup(avatar->getID());
+ }
+ return true;
+ }
};
class LLAvatarAddFriend : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if(avatar && !LLAvatarActions::isFriend(avatar->getID()))
- {
- request_friendship(avatar->getID());
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar && !LLAvatarActions::isFriend(avatar->getID()))
+ {
+ request_friendship(avatar->getID());
+ }
+ return true;
+ }
};
class LLAvatarToggleMyProfile : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloater* instance = LLAvatarActions::getProfileFloater(gAgent.getID());
- if (LLFloater::isMinimized(instance))
- {
- instance->setMinimized(FALSE);
- instance->setFocus(TRUE);
- }
- else if (!LLFloater::isShown(instance))
- {
- LLAvatarActions::showProfile(gAgent.getID());
- }
- else if (!instance->hasFocus() && !instance->getIsChrome())
- {
- instance->setFocus(TRUE);
- }
- else
- {
- instance->closeFloater();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloater* instance = LLAvatarActions::getProfileFloater(gAgent.getID());
+ if (LLFloater::isMinimized(instance))
+ {
+ instance->setMinimized(FALSE);
+ instance->setFocus(TRUE);
+ }
+ else if (!LLFloater::isShown(instance))
+ {
+ LLAvatarActions::showProfile(gAgent.getID());
+ }
+ else if (!instance->hasFocus() && !instance->getIsChrome())
+ {
+ instance->setFocus(TRUE);
+ }
+ else
+ {
+ instance->closeFloater();
+ }
+ return true;
+ }
};
class LLAvatarTogglePicks : public view_listener_t
@@ -6495,41 +6495,41 @@ class LLAvatarTogglePicks : public view_listener_t
class LLAvatarToggleSearch : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloater* instance = LLFloaterReg::findInstance("search");
- if (LLFloater::isMinimized(instance))
- {
- instance->setMinimized(FALSE);
- instance->setFocus(TRUE);
- }
- else if (!LLFloater::isShown(instance))
- {
- LLFloaterReg::showInstance("search");
- }
- else if (!instance->hasFocus() && !instance->getIsChrome())
- {
- instance->setFocus(TRUE);
- }
- else
- {
- instance->closeFloater();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloater* instance = LLFloaterReg::findInstance("search");
+ if (LLFloater::isMinimized(instance))
+ {
+ instance->setMinimized(FALSE);
+ instance->setFocus(TRUE);
+ }
+ else if (!LLFloater::isShown(instance))
+ {
+ LLFloaterReg::showInstance("search");
+ }
+ else if (!instance->hasFocus() && !instance->getIsChrome())
+ {
+ instance->setFocus(TRUE);
+ }
+ else
+ {
+ instance->closeFloater();
+ }
+ return true;
+ }
};
class LLAvatarResetSkeleton: public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- LLVOAvatar* avatar = NULL;
+ LLVOAvatar* avatar = NULL;
LLViewerObject *obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (obj)
{
avatar = obj->getAvatar();
}
- if(avatar)
+ if(avatar)
{
avatar->resetSkeleton(false);
}
@@ -6553,184 +6553,184 @@ class LLAvatarEnableResetSkeleton: public view_listener_t
class LLAvatarResetSkeletonAndAnimations : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
- if (avatar)
- {
- avatar->resetSkeleton(true);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ if (avatar)
+ {
+ avatar->resetSkeleton(true);
+ }
+ return true;
+ }
};
class LLAvatarResetSelfSkeletonAndAnimations : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
- if (avatar)
- {
- avatar->resetSkeleton(true);
- }
- else
- {
- gAgentAvatarp->resetSkeleton(true);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ if (avatar)
+ {
+ avatar->resetSkeleton(true);
+ }
+ else
+ {
+ gAgentAvatarp->resetSkeleton(true);
+ }
+ return true;
+ }
};
class LLAvatarAddContact : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if(avatar)
- {
- create_inventory_callingcard(avatar->getID());
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ create_inventory_callingcard(avatar->getID());
+ }
+ return true;
+ }
};
bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option == 0)
- {
- gAgent.setDoNotDisturb(false);
- }
-
- LLViewerObject* objectp = selection->getPrimaryObject();
-
- // Show avatar's name if paying attachment
- if (objectp && objectp->isAttachment())
- {
- while (objectp && !objectp->isAvatar())
- {
- objectp = (LLViewerObject*)objectp->getParent();
- }
- }
-
- if (objectp)
- {
- if (objectp->isAvatar())
- {
- const bool is_group = false;
- LLFloaterPayUtil::payDirectly(&give_money,
- objectp->getID(),
- is_group);
- }
- else
- {
- LLFloaterPayUtil::payViaObject(&give_money, selection);
- }
- }
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ gAgent.setDoNotDisturb(false);
+ }
+
+ LLViewerObject* objectp = selection->getPrimaryObject();
+
+ // Show avatar's name if paying attachment
+ if (objectp && objectp->isAttachment())
+ {
+ while (objectp && !objectp->isAvatar())
+ {
+ objectp = (LLViewerObject*)objectp->getParent();
+ }
+ }
+
+ if (objectp)
+ {
+ if (objectp->isAvatar())
+ {
+ const bool is_group = false;
+ LLFloaterPayUtil::payDirectly(&give_money,
+ objectp->getID(),
+ is_group);
+ }
+ else
+ {
+ LLFloaterPayUtil::payViaObject(&give_money, selection);
+ }
+ }
+ return false;
}
void handle_give_money_dialog()
{
- LLNotification::Params params("DoNotDisturbModePay");
- params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection()));
+ LLNotification::Params params("DoNotDisturbModePay");
+ params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection()));
- if (gAgent.isDoNotDisturb())
- {
- // warn users of being in do not disturb mode during a transaction
- LLNotifications::instance().add(params);
- }
- else
- {
- LLNotifications::instance().forceResponse(params, 1);
- }
+ if (gAgent.isDoNotDisturb())
+ {
+ // warn users of being in do not disturb mode during a transaction
+ LLNotifications::instance().add(params);
+ }
+ else
+ {
+ LLNotifications::instance().forceResponse(params, 1);
+ }
}
bool enable_pay_avatar()
{
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- LLVOAvatar* avatar = find_avatar_from_object(obj);
- return (avatar != NULL);
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ LLVOAvatar* avatar = find_avatar_from_object(obj);
+ return (avatar != NULL);
}
bool enable_pay_object()
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if( object )
- {
- LLViewerObject *parent = (LLViewerObject *)object->getParent();
- if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney()))
- {
- return true;
- }
- }
- return false;
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if( object )
+ {
+ LLViewerObject *parent = (LLViewerObject *)object->getParent();
+ if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney()))
+ {
+ return true;
+ }
+ }
+ return false;
}
bool enable_object_stand_up()
{
- // 'Object Stand Up' menu item is enabled when agent is sitting on selection
- return sitting_on_selection();
+ // 'Object Stand Up' menu item is enabled when agent is sitting on selection
+ return sitting_on_selection();
}
bool enable_object_sit(LLUICtrl* ctrl)
{
- // 'Object Sit' menu item is enabled when agent is not sitting on selection
- bool sitting_on_sel = sitting_on_selection();
- if (!sitting_on_sel)
- {
- // init default labels
- init_default_item_label(ctrl);
-
- // Update label
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
- if (node && node->mValid && !node->mSitName.empty())
- {
- ctrl->setValue(node->mSitName);
- }
- else
- {
- ctrl->setValue(get_default_item_label(ctrl->getName()));
- }
- }
- return !sitting_on_sel && is_object_sittable();
+ // 'Object Sit' menu item is enabled when agent is not sitting on selection
+ bool sitting_on_sel = sitting_on_selection();
+ if (!sitting_on_sel)
+ {
+ // init default labels
+ init_default_item_label(ctrl);
+
+ // Update label
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+ if (node && node->mValid && !node->mSitName.empty())
+ {
+ ctrl->setValue(node->mSitName);
+ }
+ else
+ {
+ ctrl->setValue(get_default_item_label(ctrl->getName()));
+ }
+ }
+ return !sitting_on_sel && is_object_sittable();
}
void dump_select_mgr(void*)
{
- LLSelectMgr::getInstance()->dump();
+ LLSelectMgr::getInstance()->dump();
}
void dump_inventory(void*)
{
- gInventory.dumpInventory();
+ gInventory.dumpInventory();
}
void handle_dump_followcam(void*)
{
- LLFollowCamMgr::getInstance()->dump();
+ LLFollowCamMgr::getInstance()->dump();
}
void handle_viewer_enable_message_log(void*)
{
- gMessageSystem->startLogging();
+ gMessageSystem->startLogging();
}
void handle_viewer_disable_message_log(void*)
{
- gMessageSystem->stopLogging();
+ gMessageSystem->stopLogging();
}
void handle_customize_avatar()
{
- LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits"));
+ LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits"));
}
void handle_edit_outfit()
{
- LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit"));
+ LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit"));
}
void handle_now_wearing()
@@ -6747,225 +6747,225 @@ void handle_now_wearing()
void handle_edit_shape()
{
- LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_shape"));
+ LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_shape"));
}
void handle_hover_height()
{
- LLFloaterReg::showInstance("edit_hover_height");
+ LLFloaterReg::showInstance("edit_hover_height");
}
void handle_edit_physics()
{
- LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_physics"));
+ LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_physics"));
}
void handle_report_abuse()
{
- // Prevent menu from appearing in screen shot.
- gMenuHolder->hideMenus();
- LLFloaterReporter::showFromMenu(COMPLAINT_REPORT);
+ // Prevent menu from appearing in screen shot.
+ gMenuHolder->hideMenus();
+ LLFloaterReporter::showFromMenu(COMPLAINT_REPORT);
}
void handle_buy_currency()
{
- LLBuyCurrencyHTML::openCurrencyFloater();
+ LLBuyCurrencyHTML::openCurrencyFloater();
}
class LLFloaterVisible : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string floater_name = userdata.asString();
- bool new_value = false;
- {
- new_value = LLFloaterReg::instanceVisible(floater_name);
- }
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string floater_name = userdata.asString();
+ bool new_value = false;
+ {
+ new_value = LLFloaterReg::instanceVisible(floater_name);
+ }
+ return new_value;
+ }
};
class LLShowHelp : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string help_topic = userdata.asString();
- LLViewerHelp* vhelp = LLViewerHelp::getInstance();
- vhelp->showTopic(help_topic);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string help_topic = userdata.asString();
+ LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+ vhelp->showTopic(help_topic);
+ return true;
+ }
};
class LLToggleHelp : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser"));
- if (help_browser && help_browser->isInVisibleChain())
- {
- help_browser->closeFloater();
- }
- else
- {
- std::string help_topic = userdata.asString();
- LLViewerHelp* vhelp = LLViewerHelp::getInstance();
- vhelp->showTopic(help_topic);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser"));
+ if (help_browser && help_browser->isInVisibleChain())
+ {
+ help_browser->closeFloater();
+ }
+ else
+ {
+ std::string help_topic = userdata.asString();
+ LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+ vhelp->showTopic(help_topic);
+ }
+ return true;
+ }
};
class LLToggleSpeak : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVoiceClient::getInstance()->toggleUserPTTState();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVoiceClient::getInstance()->toggleUserPTTState();
+ return true;
+ }
};
class LLShowSidetrayPanel : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string floater_name = userdata.asString();
-
- LLPanel* panel = LLFloaterSidePanelContainer::getPanel(floater_name);
- if (panel)
- {
- if (panel->isInVisibleChain())
- {
- LLFloaterReg::getInstance(floater_name)->closeFloater();
- }
- else
- {
- LLFloaterReg::getInstance(floater_name)->openFloater();
- }
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string floater_name = userdata.asString();
+
+ LLPanel* panel = LLFloaterSidePanelContainer::getPanel(floater_name);
+ if (panel)
+ {
+ if (panel->isInVisibleChain())
+ {
+ LLFloaterReg::getInstance(floater_name)->closeFloater();
+ }
+ else
+ {
+ LLFloaterReg::getInstance(floater_name)->openFloater();
+ }
+ }
+ return true;
+ }
};
class LLSidetrayPanelVisible : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string floater_name = userdata.asString();
- // Toggle the panel
- if (LLFloaterReg::getInstance(floater_name)->isInVisibleChain())
- {
- return true;
- }
- else
- {
- return false;
- }
-
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string floater_name = userdata.asString();
+ // Toggle the panel
+ if (LLFloaterReg::getInstance(floater_name)->isInVisibleChain())
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+ }
};
bool callback_show_url(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (0 == option)
- {
- LLWeb::loadURL(notification["payload"]["url"].asString());
- }
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ LLWeb::loadURL(notification["payload"]["url"].asString());
+ }
+ return false;
}
class LLPromptShowURL : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string param = userdata.asString();
- std::string::size_type offset = param.find(",");
- if (offset != param.npos)
- {
- std::string alert = param.substr(0, offset);
- std::string url = param.substr(offset+1);
-
- if (LLWeb::useExternalBrowser(url))
- {
- LLSD payload;
- payload["url"] = url;
- LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_url);
- }
- else
- {
- LLWeb::loadURL(url);
- }
- }
- else
- {
- LL_INFOS() << "PromptShowURL invalid parameters! Expecting \"ALERT,URL\"." << LL_ENDL;
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string param = userdata.asString();
+ std::string::size_type offset = param.find(",");
+ if (offset != param.npos)
+ {
+ std::string alert = param.substr(0, offset);
+ std::string url = param.substr(offset+1);
+
+ if (LLWeb::useExternalBrowser(url))
+ {
+ LLSD payload;
+ payload["url"] = url;
+ LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_url);
+ }
+ else
+ {
+ LLWeb::loadURL(url);
+ }
+ }
+ else
+ {
+ LL_INFOS() << "PromptShowURL invalid parameters! Expecting \"ALERT,URL\"." << LL_ENDL;
+ }
+ return true;
+ }
};
bool callback_show_file(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (0 == option)
- {
- LLWeb::loadURL(notification["payload"]["url"]);
- }
- return false;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ LLWeb::loadURL(notification["payload"]["url"]);
+ }
+ return false;
}
class LLPromptShowFile : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string param = userdata.asString();
- std::string::size_type offset = param.find(",");
- if (offset != param.npos)
- {
- std::string alert = param.substr(0, offset);
- std::string file = param.substr(offset+1);
-
- LLSD payload;
- payload["url"] = file;
- LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_file);
- }
- else
- {
- LL_INFOS() << "PromptShowFile invalid parameters! Expecting \"ALERT,FILE\"." << LL_ENDL;
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string param = userdata.asString();
+ std::string::size_type offset = param.find(",");
+ if (offset != param.npos)
+ {
+ std::string alert = param.substr(0, offset);
+ std::string file = param.substr(offset+1);
+
+ LLSD payload;
+ payload["url"] = file;
+ LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_file);
+ }
+ else
+ {
+ LL_INFOS() << "PromptShowFile invalid parameters! Expecting \"ALERT,FILE\"." << LL_ENDL;
+ }
+ return true;
+ }
};
class LLShowAgentProfile : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLUUID agent_id;
- if (userdata.asString() == "agent")
- {
- agent_id = gAgent.getID();
- }
- else if (userdata.asString() == "hit object")
- {
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (objectp)
- {
- agent_id = objectp->getID();
- }
- }
- else
- {
- agent_id = userdata.asUUID();
- }
-
- LLVOAvatar* avatar = find_avatar_from_object(agent_id);
- if (avatar)
- {
- LLAvatarActions::showProfile(avatar->getID());
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLUUID agent_id;
+ if (userdata.asString() == "agent")
+ {
+ agent_id = gAgent.getID();
+ }
+ else if (userdata.asString() == "hit object")
+ {
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (objectp)
+ {
+ agent_id = objectp->getID();
+ }
+ }
+ else
+ {
+ agent_id = userdata.asUUID();
+ }
+
+ LLVOAvatar* avatar = find_avatar_from_object(agent_id);
+ if (avatar)
+ {
+ LLAvatarActions::showProfile(avatar->getID());
+ }
+ return true;
+ }
};
class LLShowAgentProfilePicks : public view_listener_t
@@ -6979,164 +6979,164 @@ class LLShowAgentProfilePicks : public view_listener_t
class LLToggleAgentProfile : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLUUID agent_id;
- if (userdata.asString() == "agent")
- {
- agent_id = gAgent.getID();
- }
- else if (userdata.asString() == "hit object")
- {
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (objectp)
- {
- agent_id = objectp->getID();
- }
- }
- else
- {
- agent_id = userdata.asUUID();
- }
-
- LLVOAvatar* avatar = find_avatar_from_object(agent_id);
- if (avatar)
- {
- if (!LLAvatarActions::profileVisible(avatar->getID()))
- {
- LLAvatarActions::showProfile(avatar->getID());
- }
- else
- {
- LLAvatarActions::hideProfile(avatar->getID());
- }
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLUUID agent_id;
+ if (userdata.asString() == "agent")
+ {
+ agent_id = gAgent.getID();
+ }
+ else if (userdata.asString() == "hit object")
+ {
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (objectp)
+ {
+ agent_id = objectp->getID();
+ }
+ }
+ else
+ {
+ agent_id = userdata.asUUID();
+ }
+
+ LLVOAvatar* avatar = find_avatar_from_object(agent_id);
+ if (avatar)
+ {
+ if (!LLAvatarActions::profileVisible(avatar->getID()))
+ {
+ LLAvatarActions::showProfile(avatar->getID());
+ }
+ else
+ {
+ LLAvatarActions::hideProfile(avatar->getID());
+ }
+ }
+ return true;
+ }
};
class LLLandEdit : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (gAgentCamera.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") )
- {
- // zoom in if we're looking at the avatar
- gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
- gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgentCamera.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") )
+ {
+ // zoom in if we're looking at the avatar
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
- gAgentCamera.cameraOrbitOver( F_PI * 0.25f );
- gViewerWindow->moveCursorToCenter();
- }
- else if ( gSavedSettings.getBOOL("EditCameraMovement") )
- {
- gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
- gViewerWindow->moveCursorToCenter();
- }
+ gAgentCamera.cameraOrbitOver( F_PI * 0.25f );
+ gViewerWindow->moveCursorToCenter();
+ }
+ else if ( gSavedSettings.getBOOL("EditCameraMovement") )
+ {
+ gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+ gViewerWindow->moveCursorToCenter();
+ }
- LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal );
+ LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal );
- LLFloaterReg::showInstance("build");
+ LLFloaterReg::showInstance("build");
- // Switch to land edit toolset
- LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolSelectLand::getInstance() );
- return true;
- }
+ // Switch to land edit toolset
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolSelectLand::getInstance() );
+ return true;
+ }
};
class LLMuteParticle : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLUUID id = LLToolPie::getInstance()->getPick().mParticleOwnerID;
-
- if (id.notNull())
- {
- LLAvatarName av_name;
- LLAvatarNameCache::get(id, &av_name);
-
- LLMute mute(id, av_name.getUserName(), LLMute::AGENT);
- if (LLMuteList::getInstance()->isMuted(mute.mID))
- {
- LLMuteList::getInstance()->remove(mute);
- }
- else
- {
- LLMuteList::getInstance()->add(mute);
- LLPanelBlockedList::showPanelAndSelect(mute.mID);
- }
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLUUID id = LLToolPie::getInstance()->getPick().mParticleOwnerID;
+
+ if (id.notNull())
+ {
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(id, &av_name);
+
+ LLMute mute(id, av_name.getUserName(), LLMute::AGENT);
+ if (LLMuteList::getInstance()->isMuted(mute.mID))
+ {
+ LLMuteList::getInstance()->remove(mute);
+ }
+ else
+ {
+ LLMuteList::getInstance()->add(mute);
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
+ }
+ }
+
+ return true;
+ }
};
class LLWorldEnableBuyLand : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLViewerParcelMgr::getInstance()->canAgentBuyParcel(
- LLViewerParcelMgr::getInstance()->selectionEmpty()
- ? LLViewerParcelMgr::getInstance()->getAgentParcel()
- : LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(),
- false);
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLViewerParcelMgr::getInstance()->canAgentBuyParcel(
+ LLViewerParcelMgr::getInstance()->selectionEmpty()
+ ? LLViewerParcelMgr::getInstance()->getAgentParcel()
+ : LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(),
+ false);
+ return new_value;
+ }
};
BOOL enable_buy_land(void*)
{
- return LLViewerParcelMgr::getInstance()->canAgentBuyParcel(
- LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false);
+ return LLViewerParcelMgr::getInstance()->canAgentBuyParcel(
+ LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false);
}
void handle_buy_land()
{
- LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance();
- if (vpm->selectionEmpty())
- {
- vpm->selectParcelAt(gAgent.getPositionGlobal());
- }
- vpm->startBuyLand();
+ LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance();
+ if (vpm->selectionEmpty())
+ {
+ vpm->selectParcelAt(gAgent.getPositionGlobal());
+ }
+ vpm->startBuyLand();
}
class LLObjectAttachToAvatar : public view_listener_t
{
public:
- LLObjectAttachToAvatar(bool replace) : mReplace(replace) {}
- static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; }
+ LLObjectAttachToAvatar(bool replace) : mReplace(replace) {}
+ static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; }
private:
- bool handleEvent(const LLSD& userdata)
- {
- setObjectSelection(LLSelectMgr::getInstance()->getSelection());
- LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject();
- if (selectedObject)
- {
- S32 index = userdata.asInteger();
- LLViewerJointAttachment* attachment_point = NULL;
- if (index > 0)
- attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL);
- confirmReplaceAttachment(0, attachment_point);
- }
- return true;
- }
-
- static void onNearAttachObject(BOOL success, void *user_data);
- void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point);
- class CallbackData : public LLSelectionCallbackData
- {
- public:
- CallbackData(LLViewerJointAttachment* point, bool replace) : LLSelectionCallbackData(), mAttachmentPoint(point), mReplace(replace) {}
-
- LLViewerJointAttachment* mAttachmentPoint;
- bool mReplace;
- };
+ bool handleEvent(const LLSD& userdata)
+ {
+ setObjectSelection(LLSelectMgr::getInstance()->getSelection());
+ LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject();
+ if (selectedObject)
+ {
+ S32 index = userdata.asInteger();
+ LLViewerJointAttachment* attachment_point = NULL;
+ if (index > 0)
+ attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL);
+ confirmReplaceAttachment(0, attachment_point);
+ }
+ return true;
+ }
+
+ static void onNearAttachObject(BOOL success, void *user_data);
+ void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point);
+ class CallbackData : public LLSelectionCallbackData
+ {
+ public:
+ CallbackData(LLViewerJointAttachment* point, bool replace) : LLSelectionCallbackData(), mAttachmentPoint(point), mReplace(replace) {}
+
+ LLViewerJointAttachment* mAttachmentPoint;
+ bool mReplace;
+ };
protected:
- static LLObjectSelectionHandle sObjectSelection;
- bool mReplace;
+ static LLObjectSelectionHandle sObjectSelection;
+ bool mReplace;
};
LLObjectSelectionHandle LLObjectAttachToAvatar::sObjectSelection;
@@ -7144,238 +7144,238 @@ LLObjectSelectionHandle LLObjectAttachToAvatar::sObjectSelection;
// static
void LLObjectAttachToAvatar::onNearAttachObject(BOOL success, void *user_data)
{
- if (!user_data) return;
- CallbackData* cb_data = static_cast<CallbackData*>(user_data);
-
- if (success)
- {
- const LLViewerJointAttachment *attachment = cb_data->mAttachmentPoint;
-
- U8 attachment_id = 0;
- if (attachment)
- {
- for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
- iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter)
- {
- if (iter->second == attachment)
- {
- attachment_id = iter->first;
- break;
- }
- }
- }
- else
- {
- // interpret 0 as "default location"
- attachment_id = 0;
- }
- LLSelectMgr::getInstance()->sendAttach(cb_data->getSelection(), attachment_id, cb_data->mReplace);
- }
- LLObjectAttachToAvatar::setObjectSelection(NULL);
-
- delete cb_data;
+ if (!user_data) return;
+ CallbackData* cb_data = static_cast<CallbackData*>(user_data);
+
+ if (success)
+ {
+ const LLViewerJointAttachment *attachment = cb_data->mAttachmentPoint;
+
+ U8 attachment_id = 0;
+ if (attachment)
+ {
+ for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
+ iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter)
+ {
+ if (iter->second == attachment)
+ {
+ attachment_id = iter->first;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // interpret 0 as "default location"
+ attachment_id = 0;
+ }
+ LLSelectMgr::getInstance()->sendAttach(cb_data->getSelection(), attachment_id, cb_data->mReplace);
+ }
+ LLObjectAttachToAvatar::setObjectSelection(NULL);
+
+ delete cb_data;
}
// static
void LLObjectAttachToAvatar::confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point)
{
- if (option == 0/*YES*/)
- {
- LLViewerObject* selectedObject = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject();
- if (selectedObject)
- {
- const F32 MIN_STOP_DISTANCE = 1.f; // meters
- const F32 ARM_LENGTH = 0.5f; // meters
- const F32 SCALE_FUDGE = 1.5f;
-
- F32 stop_distance = SCALE_FUDGE * selectedObject->getMaxScale() + ARM_LENGTH;
- if (stop_distance < MIN_STOP_DISTANCE)
- {
- stop_distance = MIN_STOP_DISTANCE;
- }
-
- LLVector3 walkToSpot = selectedObject->getPositionAgent();
-
- // make sure we stop in front of the object
- LLVector3 delta = walkToSpot - gAgent.getPositionAgent();
- delta.normVec();
- delta = delta * 0.5f;
- walkToSpot -= delta;
-
- // The callback will be called even if avatar fails to get close enough to the object, so we won't get a memory leak.
- CallbackData* user_data = new CallbackData(attachment_point, mReplace);
- gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", NULL, onNearAttachObject, user_data, stop_distance);
- gAgentCamera.clearFocusObject();
- }
- }
+ if (option == 0/*YES*/)
+ {
+ LLViewerObject* selectedObject = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject();
+ if (selectedObject)
+ {
+ const F32 MIN_STOP_DISTANCE = 1.f; // meters
+ const F32 ARM_LENGTH = 0.5f; // meters
+ const F32 SCALE_FUDGE = 1.5f;
+
+ F32 stop_distance = SCALE_FUDGE * selectedObject->getMaxScale() + ARM_LENGTH;
+ if (stop_distance < MIN_STOP_DISTANCE)
+ {
+ stop_distance = MIN_STOP_DISTANCE;
+ }
+
+ LLVector3 walkToSpot = selectedObject->getPositionAgent();
+
+ // make sure we stop in front of the object
+ LLVector3 delta = walkToSpot - gAgent.getPositionAgent();
+ delta.normVec();
+ delta = delta * 0.5f;
+ walkToSpot -= delta;
+
+ // The callback will be called even if avatar fails to get close enough to the object, so we won't get a memory leak.
+ CallbackData* user_data = new CallbackData(attachment_point, mReplace);
+ gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", NULL, onNearAttachObject, user_data, stop_distance);
+ gAgentCamera.clearFocusObject();
+ }
+ }
}
void callback_attachment_drop(const LLSD& notification, const LLSD& response)
{
- // Ensure user confirmed the drop
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option != 0) return;
-
- // Called when the user clicked on an object attached to them
- // and selected "Drop".
- LLUUID object_id = notification["payload"]["object_id"].asUUID();
- LLViewerObject *object = gObjectList.findObject(object_id);
-
- if (!object)
- {
- LL_WARNS() << "handle_drop_attachment() - no object to drop" << LL_ENDL;
- return;
- }
-
- LLViewerObject *parent = (LLViewerObject*)object->getParent();
- while (parent)
- {
- if(parent->isAvatar())
- {
- break;
- }
- object = parent;
- parent = (LLViewerObject*)parent->getParent();
- }
-
- if (!object)
- {
- LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL;
- return;
- }
-
- if (object->isAvatar())
- {
- LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL;
- return;
- }
-
- // reselect the object
- LLSelectMgr::getInstance()->selectObjectAndFamily(object);
-
- LLSelectMgr::getInstance()->sendDropAttachment();
-
- return;
+ // Ensure user confirmed the drop
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0) return;
+
+ // Called when the user clicked on an object attached to them
+ // and selected "Drop".
+ LLUUID object_id = notification["payload"]["object_id"].asUUID();
+ LLViewerObject *object = gObjectList.findObject(object_id);
+
+ if (!object)
+ {
+ LL_WARNS() << "handle_drop_attachment() - no object to drop" << LL_ENDL;
+ return;
+ }
+
+ LLViewerObject *parent = (LLViewerObject*)object->getParent();
+ while (parent)
+ {
+ if(parent->isAvatar())
+ {
+ break;
+ }
+ object = parent;
+ parent = (LLViewerObject*)parent->getParent();
+ }
+
+ if (!object)
+ {
+ LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL;
+ return;
+ }
+
+ if (object->isAvatar())
+ {
+ LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL;
+ return;
+ }
+
+ // reselect the object
+ LLSelectMgr::getInstance()->selectObjectAndFamily(object);
+
+ LLSelectMgr::getInstance()->sendDropAttachment();
+
+ return;
}
class LLAttachmentDrop : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLSD payload;
- LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLSD payload;
+ LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (object)
- {
- payload["object_id"] = object->getID();
- }
- else
- {
- LL_WARNS() << "Drop object not found" << LL_ENDL;
- return true;
- }
+ if (object)
+ {
+ payload["object_id"] = object->getID();
+ }
+ else
+ {
+ LL_WARNS() << "Drop object not found" << LL_ENDL;
+ return true;
+ }
- LLNotificationsUtil::add("AttachmentDrop", LLSD(), payload, &callback_attachment_drop);
- return true;
- }
+ LLNotificationsUtil::add("AttachmentDrop", LLSD(), payload, &callback_attachment_drop);
+ return true;
+ }
};
// called from avatar pie menu
class LLAttachmentDetachFromPoint : public view_listener_t
{
- bool handleEvent(const LLSD& user_data)
- {
- uuid_vec_t ids_to_remove;
- const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL);
- if (attachment->getNumObjects() > 0)
- {
- for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin();
- iter != attachment->mAttachedObjects.end();
- iter++)
- {
- LLViewerObject *attached_object = iter->get();
- ids_to_remove.push_back(attached_object->getAttachmentItemID());
- }
- }
- if (!ids_to_remove.empty())
- {
- LLAppearanceMgr::instance().removeItemsFromAvatar(ids_to_remove);
- }
- return true;
- }
+ bool handleEvent(const LLSD& user_data)
+ {
+ uuid_vec_t ids_to_remove;
+ const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL);
+ if (attachment->getNumObjects() > 0)
+ {
+ for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin();
+ iter != attachment->mAttachedObjects.end();
+ iter++)
+ {
+ LLViewerObject *attached_object = iter->get();
+ ids_to_remove.push_back(attached_object->getAttachmentItemID());
+ }
+ }
+ if (!ids_to_remove.empty())
+ {
+ LLAppearanceMgr::instance().removeItemsFromAvatar(ids_to_remove);
+ }
+ return true;
+ }
};
static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)
{
- std::string label;
- LLMenuItemGL* menu = dynamic_cast<LLMenuItemGL*>(ctrl);
- if (menu)
- {
- const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL);
- if (attachment)
- {
- label = data["label"].asString();
- for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- const LLViewerObject* attached_object = attachment_iter->get();
- if (attached_object)
- {
- LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
- if (itemp)
- {
- label += std::string(" (") + itemp->getName() + std::string(")");
- break;
- }
- }
- }
- }
- menu->setLabel(label);
- }
- return true;
+ std::string label;
+ LLMenuItemGL* menu = dynamic_cast<LLMenuItemGL*>(ctrl);
+ if (menu)
+ {
+ const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL);
+ if (attachment)
+ {
+ label = data["label"].asString();
+ for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ const LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object)
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
+ if (itemp)
+ {
+ label += std::string(" (") + itemp->getName() + std::string(")");
+ break;
+ }
+ }
+ }
+ }
+ menu->setLabel(label);
+ }
+ return true;
}
class LLAttachmentDetach : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- // Called when the user clicked on an object attached to them
- // and selected "Detach".
- LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object)
- {
- LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL;
- return true;
- }
-
- LLViewerObject *parent = (LLViewerObject*)object->getParent();
- while (parent)
- {
- if(parent->isAvatar())
- {
- break;
- }
- object = parent;
- parent = (LLViewerObject*)parent->getParent();
- }
-
- if (!object)
- {
- LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL;
- return true;
- }
-
- if (object->isAvatar())
- {
- LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL;
- return true;
- }
-
- LLAppearanceMgr::instance().removeItemFromAvatar(object->getAttachmentItemID());
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ // Called when the user clicked on an object attached to them
+ // and selected "Detach".
+ LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object)
+ {
+ LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL;
+ return true;
+ }
+
+ LLViewerObject *parent = (LLViewerObject*)object->getParent();
+ while (parent)
+ {
+ if(parent->isAvatar())
+ {
+ break;
+ }
+ object = parent;
+ parent = (LLViewerObject*)parent->getParent();
+ }
+
+ if (!object)
+ {
+ LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL;
+ return true;
+ }
+
+ if (object->isAvatar())
+ {
+ LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL;
+ return true;
+ }
+
+ LLAppearanceMgr::instance().removeItemFromAvatar(object->getAttachmentItemID());
+
+ return true;
+ }
};
//Adding an observer for a Jira 2422 and needs to be a fetch observer
@@ -7383,468 +7383,468 @@ class LLAttachmentDetach : public view_listener_t
class LLWornItemFetchedObserver : public LLInventoryFetchItemsObserver
{
public:
- LLWornItemFetchedObserver(const LLUUID& worn_item_id) :
- LLInventoryFetchItemsObserver(worn_item_id)
- {}
- virtual ~LLWornItemFetchedObserver() {}
+ LLWornItemFetchedObserver(const LLUUID& worn_item_id) :
+ LLInventoryFetchItemsObserver(worn_item_id)
+ {}
+ virtual ~LLWornItemFetchedObserver() {}
protected:
- virtual void done()
- {
- gMenuAttachmentSelf->buildDrawLabels();
- gInventory.removeObserver(this);
- delete this;
- }
+ virtual void done()
+ {
+ gMenuAttachmentSelf->buildDrawLabels();
+ gInventory.removeObserver(this);
+ delete this;
+ }
};
// You can only drop items on parcels where you can build.
class LLAttachmentEnableDrop : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild());
-
- //Add an inventory observer to only allow dropping the newly attached item
- //once it exists in your inventory. Look at Jira 2422.
- //-jwolk
-
- // A bug occurs when you wear/drop an item before it actively is added to your inventory
- // if this is the case (you're on a slow sim, etc.) a copy of the object,
- // well, a newly created object with the same properties, is placed
- // in your inventory. Therefore, we disable the drop option until the
- // item is in your inventory
-
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- LLViewerJointAttachment* attachment = NULL;
- LLInventoryItem* item = NULL;
-
- // Do not enable drop if all faces of object are not enabled
- if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
- {
- S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getAttachmentState());
- attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
-
- if (attachment)
- {
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- // make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
- // so check to see if the item is in the inventory already
- item = gInventory.getItem(attachment_iter->get()->getAttachmentItemID());
- if (!item)
- {
- // Item does not exist, make an observer to enable the pie menu
- // when the item finishes fetching worst case scenario
- // if a fetch is already out there (being sent from a slow sim)
- // we refetch and there are 2 fetches
- LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getAttachmentItemID());
- worn_item_fetched->startFetch();
- gInventory.addObserver(worn_item_fetched);
- }
- }
- }
- }
-
- //now check to make sure that the item is actually in the inventory before we enable dropping it
- bool new_value = enable_detach() && can_build && item;
-
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild());
+
+ //Add an inventory observer to only allow dropping the newly attached item
+ //once it exists in your inventory. Look at Jira 2422.
+ //-jwolk
+
+ // A bug occurs when you wear/drop an item before it actively is added to your inventory
+ // if this is the case (you're on a slow sim, etc.) a copy of the object,
+ // well, a newly created object with the same properties, is placed
+ // in your inventory. Therefore, we disable the drop option until the
+ // item is in your inventory
+
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ LLViewerJointAttachment* attachment = NULL;
+ LLInventoryItem* item = NULL;
+
+ // Do not enable drop if all faces of object are not enabled
+ if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
+ {
+ S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getAttachmentState());
+ attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
+
+ if (attachment)
+ {
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ // make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
+ // so check to see if the item is in the inventory already
+ item = gInventory.getItem(attachment_iter->get()->getAttachmentItemID());
+ if (!item)
+ {
+ // Item does not exist, make an observer to enable the pie menu
+ // when the item finishes fetching worst case scenario
+ // if a fetch is already out there (being sent from a slow sim)
+ // we refetch and there are 2 fetches
+ LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getAttachmentItemID());
+ worn_item_fetched->startFetch();
+ gInventory.addObserver(worn_item_fetched);
+ }
+ }
+ }
+ }
+
+ //now check to make sure that the item is actually in the inventory before we enable dropping it
+ bool new_value = enable_detach() && can_build && item;
+
+ return new_value;
+ }
};
BOOL enable_detach(const LLSD&)
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-
- // Only enable detach if all faces of object are selected
- if (!object ||
- !object->isAttachment() ||
- !LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
- {
- return FALSE;
- }
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+
+ // Only enable detach if all faces of object are selected
+ if (!object ||
+ !object->isAttachment() ||
+ !LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
+ {
+ return FALSE;
+ }
- // Find the avatar who owns this attachment
- LLViewerObject* avatar = object;
- while (avatar)
- {
- // ...if it's you, good to detach
- if (avatar->getID() == gAgent.getID())
- {
- return TRUE;
- }
+ // Find the avatar who owns this attachment
+ LLViewerObject* avatar = object;
+ while (avatar)
+ {
+ // ...if it's you, good to detach
+ if (avatar->getID() == gAgent.getID())
+ {
+ return TRUE;
+ }
- avatar = (LLViewerObject*)avatar->getParent();
- }
+ avatar = (LLViewerObject*)avatar->getParent();
+ }
- return FALSE;
+ return FALSE;
}
class LLAttachmentEnableDetach : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = enable_detach();
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = enable_detach();
+ return new_value;
+ }
};
// Used to tell if the selected object can be attached to your avatar.
BOOL object_selected_and_point_valid()
{
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- for (LLObjectSelection::root_iterator iter = selection->root_begin();
- iter != selection->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- LLViewerObject::const_child_list_t& child_list = object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child = *iter;
- if (child->isAvatar())
- {
- return FALSE;
- }
- }
- }
-
- return (selection->getRootObjectCount() == 1) &&
- (selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) &&
- selection->getFirstRootObject()->permYouOwner() &&
- selection->getFirstRootObject()->flagObjectMove() &&
- !selection->getFirstRootObject()->flagObjectPermanent() &&
- !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() &&
- (selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL);
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ for (LLObjectSelection::root_iterator iter = selection->root_begin();
+ iter != selection->root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = node->getObject();
+ LLViewerObject::const_child_list_t& child_list = object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ if (child->isAvatar())
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ return (selection->getRootObjectCount() == 1) &&
+ (selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) &&
+ selection->getFirstRootObject()->permYouOwner() &&
+ selection->getFirstRootObject()->flagObjectMove() &&
+ !selection->getFirstRootObject()->flagObjectPermanent() &&
+ !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() &&
+ (selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL);
}
BOOL object_is_wearable()
{
- if (!isAgentAvatarValid())
- {
- return FALSE;
- }
- if (!object_selected_and_point_valid())
- {
- return FALSE;
- }
- if (sitting_on_selection())
- {
- return FALSE;
- }
+ if (!isAgentAvatarValid())
+ {
+ return FALSE;
+ }
+ if (!object_selected_and_point_valid())
+ {
+ return FALSE;
+ }
+ if (sitting_on_selection())
+ {
+ return FALSE;
+ }
if (!gAgentAvatarp->canAttachMoreObjects())
{
return FALSE;
}
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- if (node->mPermissions->getOwner() == gAgent.getID())
- {
- return TRUE;
- }
- }
- return FALSE;
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ if (node->mPermissions->getOwner() == gAgent.getID())
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
}
class LLAttachmentPointFilled : public view_listener_t
{
- bool handleEvent(const LLSD& user_data)
- {
- bool enable = false;
- LLVOAvatar::attachment_map_t::iterator found_it = gAgentAvatarp->mAttachmentPoints.find(user_data.asInteger());
- if (found_it != gAgentAvatarp->mAttachmentPoints.end())
- {
- enable = found_it->second->getNumObjects() > 0;
- }
- return enable;
- }
+ bool handleEvent(const LLSD& user_data)
+ {
+ bool enable = false;
+ LLVOAvatar::attachment_map_t::iterator found_it = gAgentAvatarp->mAttachmentPoints.find(user_data.asInteger());
+ if (found_it != gAgentAvatarp->mAttachmentPoints.end())
+ {
+ enable = found_it->second->getNumObjects() > 0;
+ }
+ return enable;
+ }
};
class LLAvatarSendIM : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if(avatar)
- {
- LLAvatarActions::startIM(avatar->getID());
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ LLAvatarActions::startIM(avatar->getID());
+ }
+ return true;
+ }
};
class LLAvatarCall : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if(avatar)
- {
- LLAvatarActions::startCall(avatar->getID());
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ LLAvatarActions::startCall(avatar->getID());
+ }
+ return true;
+ }
};
namespace
{
- struct QueueObjects : public LLSelectedNodeFunctor
- {
- BOOL scripted;
- BOOL modifiable;
- LLFloaterScriptQueue* mQueue;
- QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {}
- virtual bool apply(LLSelectNode* node)
- {
- LLViewerObject* obj = node->getObject();
- if (!obj)
- {
- return true;
- }
- scripted = obj->flagScripted();
- modifiable = obj->permModify();
-
- if( scripted && modifiable )
- {
- mQueue->addObject(obj->getID(), node->mName);
- return false;
- }
- else
- {
- return true; // fail: stop applying
- }
- }
- };
+ struct QueueObjects : public LLSelectedNodeFunctor
+ {
+ BOOL scripted;
+ BOOL modifiable;
+ LLFloaterScriptQueue* mQueue;
+ QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {}
+ virtual bool apply(LLSelectNode* node)
+ {
+ LLViewerObject* obj = node->getObject();
+ if (!obj)
+ {
+ return true;
+ }
+ scripted = obj->flagScripted();
+ modifiable = obj->permModify();
+
+ if( scripted && modifiable )
+ {
+ mQueue->addObject(obj->getID(), node->mName);
+ return false;
+ }
+ else
+ {
+ return true; // fail: stop applying
+ }
+ }
+ };
}
bool queue_actions(LLFloaterScriptQueue* q, const std::string& msg)
{
- QueueObjects func(q);
- LLSelectMgr *mgr = LLSelectMgr::getInstance();
- LLObjectSelectionHandle selectHandle = mgr->getSelection();
- bool fail = selectHandle->applyToNodes(&func);
- if(fail)
- {
- if ( !func.scripted )
- {
- std::string noscriptmsg = std::string("Cannot") + msg + "SelectObjectsNoScripts";
- LLNotificationsUtil::add(noscriptmsg);
- }
- else if ( !func.modifiable )
- {
- std::string nomodmsg = std::string("Cannot") + msg + "SelectObjectsNoPermission";
- LLNotificationsUtil::add(nomodmsg);
- }
- else
- {
- LL_ERRS() << "Bad logic." << LL_ENDL;
- }
- q->closeFloater();
- }
- else
- {
- if (!q->start())
- {
- LL_WARNS() << "Unexpected script compile failure." << LL_ENDL;
- }
- }
- return !fail;
+ QueueObjects func(q);
+ LLSelectMgr *mgr = LLSelectMgr::getInstance();
+ LLObjectSelectionHandle selectHandle = mgr->getSelection();
+ bool fail = selectHandle->applyToNodes(&func);
+ if(fail)
+ {
+ if ( !func.scripted )
+ {
+ std::string noscriptmsg = std::string("Cannot") + msg + "SelectObjectsNoScripts";
+ LLNotificationsUtil::add(noscriptmsg);
+ }
+ else if ( !func.modifiable )
+ {
+ std::string nomodmsg = std::string("Cannot") + msg + "SelectObjectsNoPermission";
+ LLNotificationsUtil::add(nomodmsg);
+ }
+ else
+ {
+ LL_ERRS() << "Bad logic." << LL_ENDL;
+ }
+ q->closeFloater();
+ }
+ else
+ {
+ if (!q->start())
+ {
+ LL_WARNS() << "Unexpected script compile failure." << LL_ENDL;
+ }
+ }
+ return !fail;
}
class LLToolsSelectedScriptAction : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string action = userdata.asString();
- bool mono = false;
- std::string msg, name;
- std::string title;
- if (action == "compile mono")
- {
- name = "compile_queue";
- mono = true;
- msg = "Recompile";
- title = LLTrans::getString("CompileQueueTitle");
- }
- if (action == "compile lsl")
- {
- name = "compile_queue";
- msg = "Recompile";
- title = LLTrans::getString("CompileQueueTitle");
- }
- else if (action == "reset")
- {
- name = "reset_queue";
- msg = "Reset";
- title = LLTrans::getString("ResetQueueTitle");
- }
- else if (action == "start")
- {
- name = "start_queue";
- msg = "SetRunning";
- title = LLTrans::getString("RunQueueTitle");
- }
- else if (action == "stop")
- {
- name = "stop_queue";
- msg = "SetRunningNot";
- title = LLTrans::getString("NotRunQueueTitle");
- }
- LLUUID id; id.generate();
-
- LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance<LLFloaterScriptQueue>(name, LLSD(id));
- if (queue)
- {
- queue->setMono(mono);
- if (queue_actions(queue, msg))
- {
- queue->setTitle(title);
- }
- }
- else
- {
- LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL;
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string action = userdata.asString();
+ bool mono = false;
+ std::string msg, name;
+ std::string title;
+ if (action == "compile mono")
+ {
+ name = "compile_queue";
+ mono = true;
+ msg = "Recompile";
+ title = LLTrans::getString("CompileQueueTitle");
+ }
+ if (action == "compile lsl")
+ {
+ name = "compile_queue";
+ msg = "Recompile";
+ title = LLTrans::getString("CompileQueueTitle");
+ }
+ else if (action == "reset")
+ {
+ name = "reset_queue";
+ msg = "Reset";
+ title = LLTrans::getString("ResetQueueTitle");
+ }
+ else if (action == "start")
+ {
+ name = "start_queue";
+ msg = "SetRunning";
+ title = LLTrans::getString("RunQueueTitle");
+ }
+ else if (action == "stop")
+ {
+ name = "stop_queue";
+ msg = "SetRunningNot";
+ title = LLTrans::getString("NotRunQueueTitle");
+ }
+ LLUUID id; id.generate();
+
+ LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance<LLFloaterScriptQueue>(name, LLSD(id));
+ if (queue)
+ {
+ queue->setMono(mono);
+ if (queue_actions(queue, msg))
+ {
+ queue->setTitle(title);
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL;
+ }
+ return true;
+ }
};
void handle_selected_texture_info(void*)
{
- for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
- {
- LLSelectNode* node = *iter;
-
- std::string msg;
- msg.assign("Texture info for: ");
- msg.append(node->mName);
-
- U8 te_count = node->getObject()->getNumTEs();
- // map from texture ID to list of faces using it
- typedef std::map< LLUUID, std::vector<U8> > map_t;
- map_t faces_per_texture;
- for (U8 i = 0; i < te_count; i++)
- {
- if (!node->isTESelected(i)) continue;
-
- LLViewerTexture* img = node->getObject()->getTEImage(i);
- LLUUID image_id = img->getID();
- faces_per_texture[image_id].push_back(i);
- }
- // Per-texture, dump which faces are using it.
- map_t::iterator it;
- for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
- {
- U8 te = it->second[0];
- LLViewerTexture* img = node->getObject()->getTEImage(te);
- S32 height = img->getHeight();
- S32 width = img->getWidth();
- S32 components = img->getComponents();
- msg.append(llformat("\n%dx%d %s on face ",
- width,
- height,
- (components == 4 ? "alpha" : "opaque")));
- for (U8 i = 0; i < it->second.size(); ++i)
- {
- msg.append( llformat("%d ", (S32)(it->second[i])));
- }
- }
- LLSD args;
- args["MESSAGE"] = msg;
- LLNotificationsUtil::add("SystemMessage", args);
- }
+ for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+
+ std::string msg;
+ msg.assign("Texture info for: ");
+ msg.append(node->mName);
+
+ U8 te_count = node->getObject()->getNumTEs();
+ // map from texture ID to list of faces using it
+ typedef std::map< LLUUID, std::vector<U8> > map_t;
+ map_t faces_per_texture;
+ for (U8 i = 0; i < te_count; i++)
+ {
+ if (!node->isTESelected(i)) continue;
+
+ LLViewerTexture* img = node->getObject()->getTEImage(i);
+ LLUUID image_id = img->getID();
+ faces_per_texture[image_id].push_back(i);
+ }
+ // Per-texture, dump which faces are using it.
+ map_t::iterator it;
+ for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
+ {
+ U8 te = it->second[0];
+ LLViewerTexture* img = node->getObject()->getTEImage(te);
+ S32 height = img->getHeight();
+ S32 width = img->getWidth();
+ S32 components = img->getComponents();
+ msg.append(llformat("\n%dx%d %s on face ",
+ width,
+ height,
+ (components == 4 ? "alpha" : "opaque")));
+ for (U8 i = 0; i < it->second.size(); ++i)
+ {
+ msg.append( llformat("%d ", (S32)(it->second[i])));
+ }
+ }
+ LLSD args;
+ args["MESSAGE"] = msg;
+ LLNotificationsUtil::add("SystemMessage", args);
+ }
}
void handle_selected_material_info()
{
- for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
- {
- LLSelectNode* node = *iter;
-
- std::string msg;
- msg.assign("Material info for: \n");
- msg.append(node->mName);
-
- U8 te_count = node->getObject()->getNumTEs();
- // map from material ID to list of faces using it
- typedef std::map<LLMaterialID, std::vector<U8> > map_t;
- map_t faces_per_material;
- for (U8 i = 0; i < te_count; i++)
- {
- if (!node->isTESelected(i)) continue;
-
- const LLMaterialID& material_id = node->getObject()->getTE(i)->getMaterialID();
- faces_per_material[material_id].push_back(i);
- }
- // Per-material, dump which faces are using it.
- map_t::iterator it;
- for (it = faces_per_material.begin(); it != faces_per_material.end(); ++it)
- {
- const LLMaterialID& material_id = it->first;
- msg += llformat("%s on face ", material_id.asString().c_str());
- for (U8 i = 0; i < it->second.size(); ++i)
- {
- msg.append( llformat("%d ", (S32)(it->second[i])));
- }
- msg.append("\n");
- }
-
- LLSD args;
- args["MESSAGE"] = msg;
- LLNotificationsUtil::add("SystemMessage", args);
- }
+ for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+
+ std::string msg;
+ msg.assign("Material info for: \n");
+ msg.append(node->mName);
+
+ U8 te_count = node->getObject()->getNumTEs();
+ // map from material ID to list of faces using it
+ typedef std::map<LLMaterialID, std::vector<U8> > map_t;
+ map_t faces_per_material;
+ for (U8 i = 0; i < te_count; i++)
+ {
+ if (!node->isTESelected(i)) continue;
+
+ const LLMaterialID& material_id = node->getObject()->getTE(i)->getMaterialID();
+ faces_per_material[material_id].push_back(i);
+ }
+ // Per-material, dump which faces are using it.
+ map_t::iterator it;
+ for (it = faces_per_material.begin(); it != faces_per_material.end(); ++it)
+ {
+ const LLMaterialID& material_id = it->first;
+ msg += llformat("%s on face ", material_id.asString().c_str());
+ for (U8 i = 0; i < it->second.size(); ++i)
+ {
+ msg.append( llformat("%d ", (S32)(it->second[i])));
+ }
+ msg.append("\n");
+ }
+
+ LLSD args;
+ args["MESSAGE"] = msg;
+ LLNotificationsUtil::add("SystemMessage", args);
+ }
}
void handle_test_male(void*)
{
- LLAppearanceMgr::instance().wearOutfitByName("Male Shape & Outfit");
- //gGestureList.requestResetFromServer( TRUE );
+ LLAppearanceMgr::instance().wearOutfitByName("Male Shape & Outfit");
+ //gGestureList.requestResetFromServer( TRUE );
}
void handle_test_female(void*)
{
- LLAppearanceMgr::instance().wearOutfitByName("Female Shape & Outfit");
- //gGestureList.requestResetFromServer( FALSE );
+ LLAppearanceMgr::instance().wearOutfitByName("Female Shape & Outfit");
+ //gGestureList.requestResetFromServer( FALSE );
}
void handle_dump_attachments(void*)
{
- if(!isAgentAvatarValid()) return;
-
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
- iter != gAgentAvatarp->mAttachmentPoints.end(); )
- {
- LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- S32 key = curiter->first;
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- LLViewerObject *attached_object = attachment_iter->get();
- BOOL visible = (attached_object != NULL &&
- attached_object->mDrawable.notNull() &&
- !attached_object->mDrawable->isRenderType(0));
- LLVector3 pos;
- if (visible) pos = attached_object->mDrawable->getPosition();
- LL_INFOS() << "ATTACHMENT " << key << ": item_id=" << attached_object->getAttachmentItemID()
- << (attached_object ? " present " : " absent ")
- << (visible ? "visible " : "invisible ")
- << " at " << pos
- << " and " << (visible ? attached_object->getPosition() : LLVector3::zero)
- << LL_ENDL;
- }
- }
+ if(!isAgentAvatarValid()) return;
+
+ for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
+ iter != gAgentAvatarp->mAttachmentPoints.end(); )
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ S32 key = curiter->first;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject *attached_object = attachment_iter->get();
+ BOOL visible = (attached_object != NULL &&
+ attached_object->mDrawable.notNull() &&
+ !attached_object->mDrawable->isRenderType(0));
+ LLVector3 pos;
+ if (visible) pos = attached_object->mDrawable->getPosition();
+ LL_INFOS() << "ATTACHMENT " << key << ": item_id=" << attached_object->getAttachmentItemID()
+ << (attached_object ? " present " : " absent ")
+ << (visible ? "visible " : "invisible ")
+ << " at " << pos
+ << " and " << (visible ? attached_object->getPosition() : LLVector3::zero)
+ << LL_ENDL;
+ }
+ }
}
@@ -7853,369 +7853,369 @@ class LLToggleControl : public view_listener_t
{
protected:
- bool handleEvent(const LLSD& userdata)
- {
- std::string control_name = userdata.asString();
- BOOL checked = gSavedSettings.getBOOL( control_name );
- gSavedSettings.setBOOL( control_name, !checked );
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string control_name = userdata.asString();
+ BOOL checked = gSavedSettings.getBOOL( control_name );
+ gSavedSettings.setBOOL( control_name, !checked );
+ return true;
+ }
};
class LLCheckControl : public view_listener_t
{
- bool handleEvent( const LLSD& userdata)
- {
- std::string callback_data = userdata.asString();
- bool new_value = gSavedSettings.getBOOL(callback_data);
- return new_value;
- }
+ bool handleEvent( const LLSD& userdata)
+ {
+ std::string callback_data = userdata.asString();
+ bool new_value = gSavedSettings.getBOOL(callback_data);
+ return new_value;
+ }
};
// not so generic
class LLAdvancedCheckRenderShadowOption: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string control_name = userdata.asString();
- S32 current_shadow_level = gSavedSettings.getS32(control_name);
- if (current_shadow_level == 0) // is off
- {
- return false;
- }
- else // is on
- {
- return true;
- }
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string control_name = userdata.asString();
+ S32 current_shadow_level = gSavedSettings.getS32(control_name);
+ if (current_shadow_level == 0) // is off
+ {
+ return false;
+ }
+ else // is on
+ {
+ return true;
+ }
+ }
};
class LLAdvancedClickRenderShadowOption: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string control_name = userdata.asString();
- S32 current_shadow_level = gSavedSettings.getS32(control_name);
- if (current_shadow_level == 0) // upgrade to level 2
- {
- gSavedSettings.setS32(control_name, 2);
- }
- else // downgrade to level 0
- {
- gSavedSettings.setS32(control_name, 0);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string control_name = userdata.asString();
+ S32 current_shadow_level = gSavedSettings.getS32(control_name);
+ if (current_shadow_level == 0) // upgrade to level 2
+ {
+ gSavedSettings.setS32(control_name, 2);
+ }
+ else // downgrade to level 0
+ {
+ gSavedSettings.setS32(control_name, 0);
+ }
+ return true;
+ }
};
class LLAdvancedClickRenderProfile: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gShaderProfileFrame = TRUE;
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gShaderProfileFrame = TRUE;
+ return true;
+ }
};
F32 gpu_benchmark();
class LLAdvancedClickRenderBenchmark: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gpu_benchmark();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gpu_benchmark();
+ return true;
+ }
};
// these are used in the gl menus to set control values that require shader recompilation
class LLToggleShaderControl : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
+ bool handleEvent(const LLSD& userdata)
+ {
std::string control_name = userdata.asString();
- BOOL checked = gSavedSettings.getBOOL( control_name );
- gSavedSettings.setBOOL( control_name, !checked );
+ BOOL checked = gSavedSettings.getBOOL( control_name );
+ gSavedSettings.setBOOL( control_name, !checked );
LLPipeline::refreshCachedSettings();
LLViewerShaderMgr::instance()->setShaders();
- return !checked;
- }
+ return !checked;
+ }
};
void menu_toggle_attached_lights(void* user_data)
{
- LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
+ LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
}
void menu_toggle_attached_particles(void* user_data)
{
- LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
+ LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
}
class LLAdvancedHandleAttachedLightParticles: public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string control_name = userdata.asString();
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string control_name = userdata.asString();
- // toggle the control
- gSavedSettings.setBOOL(control_name,
- !gSavedSettings.getBOOL(control_name));
+ // toggle the control
+ gSavedSettings.setBOOL(control_name,
+ !gSavedSettings.getBOOL(control_name));
- // update internal flags
- if (control_name == "RenderAttachedLights")
- {
- menu_toggle_attached_lights(NULL);
- }
- else if (control_name == "RenderAttachedParticles")
- {
- menu_toggle_attached_particles(NULL);
- }
- return true;
- }
+ // update internal flags
+ if (control_name == "RenderAttachedLights")
+ {
+ menu_toggle_attached_lights(NULL);
+ }
+ else if (control_name == "RenderAttachedParticles")
+ {
+ menu_toggle_attached_particles(NULL);
+ }
+ return true;
+ }
};
class LLSomethingSelected : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = !(LLSelectMgr::getInstance()->getSelection()->isEmpty());
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = !(LLSelectMgr::getInstance()->getSelection()->isEmpty());
+ return new_value;
+ }
};
class LLSomethingSelectedNoHUD : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD);
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD);
+ return new_value;
+ }
};
static bool is_editable_selected()
{
- return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL);
+ return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL);
}
class LLEditableSelected : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return is_editable_selected();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return is_editable_selected();
+ }
};
class LLEditableSelectedMono : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = false;
- LLViewerRegion* region = gAgent.getRegion();
- if(region && gMenuHolder)
- {
- bool have_cap = (! region->getCapability("UpdateScriptTask").empty());
- new_value = is_editable_selected() && have_cap;
- }
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = false;
+ LLViewerRegion* region = gAgent.getRegion();
+ if(region && gMenuHolder)
+ {
+ bool have_cap = (! region->getCapability("UpdateScriptTask").empty());
+ new_value = is_editable_selected() && have_cap;
+ }
+ return new_value;
+ }
};
bool enable_object_take_copy()
{
- bool all_valid = false;
- if (LLSelectMgr::getInstance())
- {
- if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 0)
- {
- all_valid = true;
+ bool all_valid = false;
+ if (LLSelectMgr::getInstance())
+ {
+ if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 0)
+ {
+ all_valid = true;
#ifndef HACKED_GODLIKE_VIEWER
# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
- if (LLGridManager::getInstance()->isInProductionGrid()
+ if (LLGridManager::getInstance()->isInProductionGrid()
|| !gAgent.isGodlike())
# endif
- {
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* obj)
- {
- return (!obj->permCopy() || obj->isAttachment());
- }
- } func;
- const bool firstonly = true;
- bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
- all_valid = !any_invalid;
- }
+ {
+ struct f : public LLSelectedObjectFunctor
+ {
+ virtual bool apply(LLViewerObject* obj)
+ {
+ return (!obj->permCopy() || obj->isAttachment());
+ }
+ } func;
+ const bool firstonly = true;
+ bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
+ all_valid = !any_invalid;
+ }
#endif // HACKED_GODLIKE_VIEWER
- }
- }
+ }
+ }
- return all_valid;
+ return all_valid;
}
class LLHasAsset : public LLInventoryCollectFunctor
{
public:
- LLHasAsset(const LLUUID& id) : mAssetID(id), mHasAsset(FALSE) {}
- virtual ~LLHasAsset() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
- BOOL hasAsset() const { return mHasAsset; }
+ LLHasAsset(const LLUUID& id) : mAssetID(id), mHasAsset(FALSE) {}
+ virtual ~LLHasAsset() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
+ BOOL hasAsset() const { return mHasAsset; }
protected:
- LLUUID mAssetID;
- BOOL mHasAsset;
+ LLUUID mAssetID;
+ BOOL mHasAsset;
};
bool LLHasAsset::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
+ LLInventoryItem* item)
{
- if(item && item->getAssetUUID() == mAssetID)
- {
- mHasAsset = TRUE;
- }
- return FALSE;
+ if(item && item->getAssetUUID() == mAssetID)
+ {
+ mHasAsset = TRUE;
+ }
+ return FALSE;
}
BOOL enable_save_into_task_inventory(void*)
{
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
- if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
- {
- // *TODO: check to see if the fromtaskid object exists.
- LLViewerObject* obj = node->getObject();
- if( obj && !obj->isAttachment() )
- {
- return TRUE;
- }
- }
- return FALSE;
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+ if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
+ {
+ // *TODO: check to see if the fromtaskid object exists.
+ LLViewerObject* obj = node->getObject();
+ if( obj && !obj->isAttachment() )
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
}
class LLToolsEnableSaveToObjectInventory : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = enable_save_into_task_inventory(NULL);
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = enable_save_into_task_inventory(NULL);
+ return new_value;
+ }
};
class LLToggleHowTo : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterReg::toggleInstanceOrBringToFront("guidebook");
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterReg::toggleInstanceOrBringToFront("guidebook");
+ return true;
+ }
};
class LLViewEnableMouselook : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- // You can't go directly from customize avatar to mouselook.
- // TODO: write code with appropriate dialogs to handle this transition.
- bool new_value = (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && !gSavedSettings.getBOOL("FreezeTime"));
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ // You can't go directly from customize avatar to mouselook.
+ // TODO: write code with appropriate dialogs to handle this transition.
+ bool new_value = (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && !gSavedSettings.getBOOL("FreezeTime"));
+ return new_value;
+ }
};
class LLToolsEnableToolNotPie : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = ( LLToolMgr::getInstance()->getBaseTool() != LLToolPie::getInstance() );
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = ( LLToolMgr::getInstance()->getBaseTool() != LLToolPie::getInstance() );
+ return new_value;
+ }
};
class LLWorldEnableCreateLandmark : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return !LLLandmarkActions::landmarkAlreadyExists();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return !LLLandmarkActions::landmarkAlreadyExists();
+ }
};
class LLWorldEnableSetHomeLocation : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gAgent.isGodlike() ||
- (gAgent.getRegion() && gAgent.getRegion()->getAllowSetHome());
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gAgent.isGodlike() ||
+ (gAgent.getRegion() && gAgent.getRegion()->getAllowSetHome());
+ return new_value;
+ }
};
class LLWorldEnableTeleportHome : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLViewerRegion* regionp = gAgent.getRegion();
- bool agent_on_prelude = (regionp && regionp->isPrelude());
- bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude;
- return enable_teleport_home;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerRegion* regionp = gAgent.getRegion();
+ bool agent_on_prelude = (regionp && regionp->isPrelude());
+ bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude;
+ return enable_teleport_home;
+ }
};
BOOL enable_god_full(void*)
{
- return gAgent.getGodLevel() >= GOD_FULL;
+ return gAgent.getGodLevel() >= GOD_FULL;
}
BOOL enable_god_liaison(void*)
{
- return gAgent.getGodLevel() >= GOD_LIAISON;
+ return gAgent.getGodLevel() >= GOD_LIAISON;
}
bool is_god_customer_service()
{
- return gAgent.getGodLevel() >= GOD_CUSTOMER_SERVICE;
+ return gAgent.getGodLevel() >= GOD_CUSTOMER_SERVICE;
}
BOOL enable_god_basic(void*)
{
- return gAgent.getGodLevel() > GOD_NOT;
+ return gAgent.getGodLevel() > GOD_NOT;
}
void toggle_show_xui_names(void *)
{
- gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames"));
+ gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames"));
}
BOOL check_show_xui_names(void *)
{
- return gSavedSettings.getBOOL("DebugShowXUINames");
+ return gSavedSettings.getBOOL("DebugShowXUINames");
}
class LLToolsSelectOnlyMyObjects : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- BOOL cur_val = gSavedSettings.getBOOL("SelectOwnedOnly");
+ bool handleEvent(const LLSD& userdata)
+ {
+ BOOL cur_val = gSavedSettings.getBOOL("SelectOwnedOnly");
- gSavedSettings.setBOOL("SelectOwnedOnly", ! cur_val );
+ gSavedSettings.setBOOL("SelectOwnedOnly", ! cur_val );
- return true;
- }
+ return true;
+ }
};
class LLToolsSelectOnlyMovableObjects : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- BOOL cur_val = gSavedSettings.getBOOL("SelectMovableOnly");
+ bool handleEvent(const LLSD& userdata)
+ {
+ BOOL cur_val = gSavedSettings.getBOOL("SelectMovableOnly");
- gSavedSettings.setBOOL("SelectMovableOnly", ! cur_val );
+ gSavedSettings.setBOOL("SelectMovableOnly", ! cur_val );
- return true;
- }
+ return true;
+ }
};
class LLToolsSelectInvisibleObjects : public view_listener_t
@@ -8244,178 +8244,178 @@ class LLToolsSelectReflectionProbes: public view_listener_t
class LLToolsSelectBySurrounding : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLSelectMgr::sRectSelectInclusive = !LLSelectMgr::sRectSelectInclusive;
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLSelectMgr::sRectSelectInclusive = !LLSelectMgr::sRectSelectInclusive;
- gSavedSettings.setBOOL("RectangleSelectInclusive", LLSelectMgr::sRectSelectInclusive);
- return true;
- }
+ gSavedSettings.setBOOL("RectangleSelectInclusive", LLSelectMgr::sRectSelectInclusive);
+ return true;
+ }
};
class LLToolsShowHiddenSelection : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- // TomY TODO Merge these
- LLSelectMgr::sRenderHiddenSelections = !LLSelectMgr::sRenderHiddenSelections;
+ bool handleEvent(const LLSD& userdata)
+ {
+ // TomY TODO Merge these
+ LLSelectMgr::sRenderHiddenSelections = !LLSelectMgr::sRenderHiddenSelections;
- gSavedSettings.setBOOL("RenderHiddenSelections", LLSelectMgr::sRenderHiddenSelections);
- return true;
- }
+ gSavedSettings.setBOOL("RenderHiddenSelections", LLSelectMgr::sRenderHiddenSelections);
+ return true;
+ }
};
class LLToolsShowSelectionLightRadius : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- // TomY TODO merge these
- LLSelectMgr::sRenderLightRadius = !LLSelectMgr::sRenderLightRadius;
+ bool handleEvent(const LLSD& userdata)
+ {
+ // TomY TODO merge these
+ LLSelectMgr::sRenderLightRadius = !LLSelectMgr::sRenderLightRadius;
- gSavedSettings.setBOOL("RenderLightRadius", LLSelectMgr::sRenderLightRadius);
- return true;
- }
+ gSavedSettings.setBOOL("RenderLightRadius", LLSelectMgr::sRenderLightRadius);
+ return true;
+ }
};
class LLToolsEditLinkedParts : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- BOOL select_individuals = !gSavedSettings.getBOOL("EditLinkedParts");
- gSavedSettings.setBOOL( "EditLinkedParts", select_individuals );
- if (select_individuals)
- {
- LLSelectMgr::getInstance()->demoteSelectionToIndividuals();
- }
- else
- {
- LLSelectMgr::getInstance()->promoteSelectionToRoot();
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ BOOL select_individuals = !gSavedSettings.getBOOL("EditLinkedParts");
+ gSavedSettings.setBOOL( "EditLinkedParts", select_individuals );
+ if (select_individuals)
+ {
+ LLSelectMgr::getInstance()->demoteSelectionToIndividuals();
+ }
+ else
+ {
+ LLSelectMgr::getInstance()->promoteSelectionToRoot();
+ }
+ return true;
+ }
};
void reload_vertex_shader(void *)
{
- //THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought - DaveP
+ //THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought - DaveP
}
void handle_dump_avatar_local_textures(void*)
{
- gAgentAvatarp->dumpLocalTextures();
+ gAgentAvatarp->dumpLocalTextures();
}
void handle_dump_timers()
{
- LLTrace::BlockTimer::dumpCurTimes();
+ LLTrace::BlockTimer::dumpCurTimes();
}
void handle_debug_avatar_textures(void*)
{
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (objectp)
- {
- LLFloaterReg::showInstance( "avatar_textures", LLSD(objectp->getID()) );
- }
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (objectp)
+ {
+ LLFloaterReg::showInstance( "avatar_textures", LLSD(objectp->getID()) );
+ }
}
void handle_grab_baked_texture(void* data)
{
- EBakedTextureIndex baked_tex_index = (EBakedTextureIndex)((intptr_t)data);
- if (!isAgentAvatarValid()) return;
-
- const LLUUID& asset_id = gAgentAvatarp->grabBakedTexture(baked_tex_index);
- LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << LL_ENDL;
- LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE;
- LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE;
- const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type));
- if(folder_id.notNull())
- {
- std::string name;
- name = "Baked " + LLAvatarAppearance::getDictionary()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture";
-
- LLUUID item_id;
- item_id.generate();
- LLPermissions perm;
- perm.init(gAgentID,
- gAgentID,
- LLUUID::null,
- LLUUID::null);
- U32 next_owner_perm = PERM_MOVE | PERM_TRANSFER;
- perm.initMasks(PERM_ALL,
- PERM_ALL,
- PERM_NONE,
- PERM_NONE,
- next_owner_perm);
- time_t creation_date_now = time_corrected();
- LLPointer<LLViewerInventoryItem> item
- = new LLViewerInventoryItem(item_id,
- folder_id,
- perm,
- asset_id,
- asset_type,
- inv_type,
- name,
- LLStringUtil::null,
- LLSaleInfo::DEFAULT,
- LLInventoryItemFlags::II_FLAGS_NONE,
- creation_date_now);
-
- item->updateServer(TRUE);
- gInventory.updateItem(item);
- gInventory.notifyObservers();
-
- // Show the preview panel for textures to let
- // user know that the image is now in inventory.
- LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
- if(active_panel)
- {
- LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
-
- active_panel->setSelection(item_id, TAKE_FOCUS_NO);
- active_panel->openSelected();
- //LLFloaterInventory::dumpSelectionInformation((void*)view);
- // restore keyboard focus
- gFocusMgr.setKeyboardFocus(focus_ctrl);
- }
- }
- else
- {
- LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
- }
+ EBakedTextureIndex baked_tex_index = (EBakedTextureIndex)((intptr_t)data);
+ if (!isAgentAvatarValid()) return;
+
+ const LLUUID& asset_id = gAgentAvatarp->grabBakedTexture(baked_tex_index);
+ LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << LL_ENDL;
+ LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE;
+ LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE;
+ const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type));
+ if(folder_id.notNull())
+ {
+ std::string name;
+ name = "Baked " + LLAvatarAppearance::getDictionary()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture";
+
+ LLUUID item_id;
+ item_id.generate();
+ LLPermissions perm;
+ perm.init(gAgentID,
+ gAgentID,
+ LLUUID::null,
+ LLUUID::null);
+ U32 next_owner_perm = PERM_MOVE | PERM_TRANSFER;
+ perm.initMasks(PERM_ALL,
+ PERM_ALL,
+ PERM_NONE,
+ PERM_NONE,
+ next_owner_perm);
+ time_t creation_date_now = time_corrected();
+ LLPointer<LLViewerInventoryItem> item
+ = new LLViewerInventoryItem(item_id,
+ folder_id,
+ perm,
+ asset_id,
+ asset_type,
+ inv_type,
+ name,
+ LLStringUtil::null,
+ LLSaleInfo::DEFAULT,
+ LLInventoryItemFlags::II_FLAGS_NONE,
+ creation_date_now);
+
+ item->updateServer(TRUE);
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+
+ // Show the preview panel for textures to let
+ // user know that the image is now in inventory.
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ if(active_panel)
+ {
+ LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
+
+ active_panel->setSelection(item_id, TAKE_FOCUS_NO);
+ active_panel->openSelected();
+ //LLFloaterInventory::dumpSelectionInformation((void*)view);
+ // restore keyboard focus
+ gFocusMgr.setKeyboardFocus(focus_ctrl);
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
+ }
}
BOOL enable_grab_baked_texture(void* data)
{
- EBakedTextureIndex index = (EBakedTextureIndex)((intptr_t)data);
- if (isAgentAvatarValid())
- {
- return gAgentAvatarp->canGrabBakedTexture(index);
- }
- return FALSE;
+ EBakedTextureIndex index = (EBakedTextureIndex)((intptr_t)data);
+ if (isAgentAvatarValid())
+ {
+ return gAgentAvatarp->canGrabBakedTexture(index);
+ }
+ return FALSE;
}
// Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing.
// Returns NULL on failure.
LLVOAvatar* find_avatar_from_object( LLViewerObject* object )
{
- if (object)
- {
- if( object->isAttachment() )
- {
- do
- {
- object = (LLViewerObject*) object->getParent();
- }
- while( object && !object->isAvatar() );
- }
- else if( !object->isAvatar() )
- {
- object = NULL;
- }
- }
+ if (object)
+ {
+ if( object->isAttachment() )
+ {
+ do
+ {
+ object = (LLViewerObject*) object->getParent();
+ }
+ while( object && !object->isAvatar() );
+ }
+ else if( !object->isAvatar() )
+ {
+ object = NULL;
+ }
+ }
- return (LLVOAvatar*) object;
+ return (LLVOAvatar*) object;
}
@@ -8423,13 +8423,13 @@ LLVOAvatar* find_avatar_from_object( LLViewerObject* object )
// Returns NULL on failure.
LLVOAvatar* find_avatar_from_object( const LLUUID& object_id )
{
- return find_avatar_from_object( gObjectList.findObject(object_id) );
+ return find_avatar_from_object( gObjectList.findObject(object_id) );
}
void handle_disconnect_viewer(void *)
{
- LLAppViewer::instance()->forceDisconnect(LLTrans::getString("TestingDisconnect"));
+ LLAppViewer::instance()->forceDisconnect(LLTrans::getString("TestingDisconnect"));
}
void force_error_breakpoint(void *)
@@ -8484,30 +8484,30 @@ void force_error_thread_crash(void *)
class LLToolsUseSelectionForGrid : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLSelectMgr::getInstance()->clearGridObjects();
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* objectp)
- {
- LLSelectMgr::getInstance()->addGridObject(objectp);
- return true;
- }
- } func;
- LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func);
- LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT);
- LLFloaterTools::setGridMode((S32)GRID_MODE_REF_OBJECT);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLSelectMgr::getInstance()->clearGridObjects();
+ struct f : public LLSelectedObjectFunctor
+ {
+ virtual bool apply(LLViewerObject* objectp)
+ {
+ LLSelectMgr::getInstance()->addGridObject(objectp);
+ return true;
+ }
+ } func;
+ LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func);
+ LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT);
+ LLFloaterTools::setGridMode((S32)GRID_MODE_REF_OBJECT);
+ return true;
+ }
};
void handle_test_load_url(void*)
{
- LLWeb::loadURL("");
- LLWeb::loadURL("hacker://www.google.com/");
- LLWeb::loadURL("http");
- LLWeb::loadURL("http://www.google.com/");
+ LLWeb::loadURL("");
+ LLWeb::loadURL("hacker://www.google.com/");
+ LLWeb::loadURL("http");
+ LLWeb::loadURL("http://www.google.com/");
}
//
@@ -8521,86 +8521,86 @@ LLViewerMenuHolderGL::LLViewerMenuHolderGL(const LLViewerMenuHolderGL::Params& p
BOOL LLViewerMenuHolderGL::hideMenus()
{
- BOOL handled = FALSE;
-
- if (LLMenuHolderGL::hideMenus())
- {
- handled = TRUE;
- }
+ BOOL handled = FALSE;
+
+ if (LLMenuHolderGL::hideMenus())
+ {
+ handled = TRUE;
+ }
- // drop pie menu selection
- mParcelSelection = NULL;
- mObjectSelection = NULL;
+ // drop pie menu selection
+ mParcelSelection = NULL;
+ mObjectSelection = NULL;
- if (gMenuBarView)
- {
- gMenuBarView->clearHoverItem();
- gMenuBarView->resetMenuTrigger();
- }
+ if (gMenuBarView)
+ {
+ gMenuBarView->clearHoverItem();
+ gMenuBarView->resetMenuTrigger();
+ }
- return handled;
+ return handled;
}
-void LLViewerMenuHolderGL::setParcelSelection(LLSafeHandle<LLParcelSelection> selection)
-{
- mParcelSelection = selection;
+void LLViewerMenuHolderGL::setParcelSelection(LLSafeHandle<LLParcelSelection> selection)
+{
+ mParcelSelection = selection;
}
-void LLViewerMenuHolderGL::setObjectSelection(LLSafeHandle<LLObjectSelection> selection)
-{
- mObjectSelection = selection;
+void LLViewerMenuHolderGL::setObjectSelection(LLSafeHandle<LLObjectSelection> selection)
+{
+ mObjectSelection = selection;
}
const LLRect LLViewerMenuHolderGL::getMenuRect() const
{
- return LLRect(0, getRect().getHeight() - MENU_BAR_HEIGHT, getRect().getWidth(), STATUS_BAR_HEIGHT);
+ return LLRect(0, getRect().getHeight() - MENU_BAR_HEIGHT, getRect().getWidth(), STATUS_BAR_HEIGHT);
}
void handle_web_browser_test(const LLSD& param)
{
- std::string url = param.asString();
- if (url.empty())
- {
- url = "about:blank";
- }
- LLWeb::loadURLInternal(url);
+ std::string url = param.asString();
+ if (url.empty())
+ {
+ url = "about:blank";
+ }
+ LLWeb::loadURLInternal(url);
}
bool callback_clear_cache_immediately(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if ( option == 0 ) // YES
- {
- //clear cache
- LLAppViewer::instance()->purgeCacheImmediate();
- }
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if ( option == 0 ) // YES
+ {
+ //clear cache
+ LLAppViewer::instance()->purgeCacheImmediate();
+ }
- return false;
+ return false;
}
void handle_cache_clear_immediately()
{
- LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately);
+ LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately);
}
void handle_web_content_test(const LLSD& param)
{
- std::string url = param.asString();
- LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true);
+ std::string url = param.asString();
+ LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true);
}
void handle_show_url(const LLSD& param)
{
- std::string url = param.asString();
- if (LLWeb::useExternalBrowser(url))
- {
- LLWeb::loadURLExternal(url);
- }
- else
- {
- LLWeb::loadURLInternal(url);
- }
+ std::string url = param.asString();
+ if (LLWeb::useExternalBrowser(url))
+ {
+ LLWeb::loadURLExternal(url);
+ }
+ else
+ {
+ LLWeb::loadURLInternal(url);
+ }
}
@@ -8612,571 +8612,580 @@ void handle_report_bug(const LLSD& param)
void handle_buy_currency_test(void*)
{
- std::string url =
- "http://sarahd-sl-13041.webdev.lindenlab.com/app/lindex/index.php?agent_id=[AGENT_ID]&secure_session_id=[SESSION_ID]&lang=[LANGUAGE]";
+ std::string url =
+ "http://sarahd-sl-13041.webdev.lindenlab.com/app/lindex/index.php?agent_id=[AGENT_ID]&secure_session_id=[SESSION_ID]&lang=[LANGUAGE]";
- LLStringUtil::format_map_t replace;
- replace["[AGENT_ID]"] = gAgent.getID().asString();
- replace["[SESSION_ID]"] = gAgent.getSecureSessionID().asString();
- replace["[LANGUAGE]"] = LLUI::getLanguage();
- LLStringUtil::format(url, replace);
+ LLStringUtil::format_map_t replace;
+ replace["[AGENT_ID]"] = gAgent.getID().asString();
+ replace["[SESSION_ID]"] = gAgent.getSecureSessionID().asString();
+ replace["[LANGUAGE]"] = LLUI::getLanguage();
+ LLStringUtil::format(url, replace);
- LL_INFOS() << "buy currency url " << url << LL_ENDL;
+ LL_INFOS() << "buy currency url " << url << LL_ENDL;
- LLFloaterReg::showInstance("buy_currency_html", LLSD(url));
+ LLFloaterReg::showInstance("buy_currency_html", LLSD(url));
}
// SUNSHINE CLEANUP - is only the request update at the end needed now?
void handle_rebake_textures(void*)
{
- if (!isAgentAvatarValid()) return;
+ if (!isAgentAvatarValid()) return;
- // Slam pending upload count to "unstick" things
- bool slam_for_debug = true;
- gAgentAvatarp->forceBakeAllTextures(slam_for_debug);
- if (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion())
- {
- LLAppearanceMgr::instance().requestServerAppearanceUpdate();
- }
+ // Slam pending upload count to "unstick" things
+ bool slam_for_debug = true;
+ gAgentAvatarp->forceBakeAllTextures(slam_for_debug);
+ if (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion())
+ {
+ LLAppearanceMgr::instance().requestServerAppearanceUpdate();
+ }
}
void toggle_visibility(void* user_data)
{
- LLView* viewp = (LLView*)user_data;
- viewp->setVisible(!viewp->getVisible());
+ LLView* viewp = (LLView*)user_data;
+ viewp->setVisible(!viewp->getVisible());
}
BOOL get_visibility(void* user_data)
{
- LLView* viewp = (LLView*)user_data;
- return viewp->getVisible();
+ LLView* viewp = (LLView*)user_data;
+ return viewp->getVisible();
}
class LLViewShowHoverTips : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips"));
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips"));
+ return true;
+ }
};
class LLViewCheckShowHoverTips : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gSavedSettings.getBOOL("ShowHoverTips");
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gSavedSettings.getBOOL("ShowHoverTips");
+ return new_value;
+ }
};
class LLViewHighlightTransparent : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha;
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha;
// invisible objects skip building their render batches unless sShowDebugAlpha is true, so rebuild batches whenever toggling this flag
- gPipeline.rebuildDrawInfo();
- return true;
- }
+ gPipeline.rebuildDrawInfo();
+ return true;
+ }
};
class LLViewCheckHighlightTransparent : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLDrawPoolAlpha::sShowDebugAlpha;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLDrawPoolAlpha::sShowDebugAlpha;
+ return new_value;
+ }
};
class LLViewBeaconWidth : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string width = userdata.asString();
- if(width == "1")
- {
- gSavedSettings.setS32("DebugBeaconLineWidth", 1);
- }
- else if(width == "4")
- {
- gSavedSettings.setS32("DebugBeaconLineWidth", 4);
- }
- else if(width == "16")
- {
- gSavedSettings.setS32("DebugBeaconLineWidth", 16);
- }
- else if(width == "32")
- {
- gSavedSettings.setS32("DebugBeaconLineWidth", 32);
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string width = userdata.asString();
+ if(width == "1")
+ {
+ gSavedSettings.setS32("DebugBeaconLineWidth", 1);
+ }
+ else if(width == "4")
+ {
+ gSavedSettings.setS32("DebugBeaconLineWidth", 4);
+ }
+ else if(width == "16")
+ {
+ gSavedSettings.setS32("DebugBeaconLineWidth", 16);
+ }
+ else if(width == "32")
+ {
+ gSavedSettings.setS32("DebugBeaconLineWidth", 32);
+ }
+
+ return true;
+ }
};
class LLViewToggleBeacon : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string beacon = userdata.asString();
- if (beacon == "scriptsbeacon")
- {
- LLPipeline::toggleRenderScriptedBeacons();
- gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() );
- // toggle the other one off if it's on
- if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons())
- {
- LLPipeline::toggleRenderScriptedTouchBeacons();
- gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() );
- }
- }
- else if (beacon == "physicalbeacon")
- {
- LLPipeline::toggleRenderPhysicalBeacons();
- gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons() );
- }
- else if (beacon == "moapbeacon")
- {
- LLPipeline::toggleRenderMOAPBeacons();
- gSavedSettings.setBOOL( "moapbeacon", LLPipeline::getRenderMOAPBeacons() );
- }
- else if (beacon == "soundsbeacon")
- {
- LLPipeline::toggleRenderSoundBeacons();
- gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons() );
- }
- else if (beacon == "particlesbeacon")
- {
- LLPipeline::toggleRenderParticleBeacons();
- gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons() );
- }
- else if (beacon == "scripttouchbeacon")
- {
- LLPipeline::toggleRenderScriptedTouchBeacons();
- gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() );
- // toggle the other one off if it's on
- if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons())
- {
- LLPipeline::toggleRenderScriptedBeacons();
- gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() );
- }
- }
- else if (beacon == "sunbeacon")
- {
- gSavedSettings.setBOOL("sunbeacon", !gSavedSettings.getBOOL("sunbeacon"));
- }
- else if (beacon == "moonbeacon")
- {
- gSavedSettings.setBOOL("moonbeacon", !gSavedSettings.getBOOL("moonbeacon"));
- }
- else if (beacon == "renderbeacons")
- {
- LLPipeline::toggleRenderBeacons();
- gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() );
- // toggle the other one on if it's not
- if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights())
- {
- LLPipeline::toggleRenderHighlights();
- gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() );
- }
- }
- else if (beacon == "renderhighlights")
- {
- LLPipeline::toggleRenderHighlights();
- gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() );
- // toggle the other one on if it's not
- if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights())
- {
- LLPipeline::toggleRenderBeacons();
- gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() );
- }
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string beacon = userdata.asString();
+ if (beacon == "scriptsbeacon")
+ {
+ LLPipeline::toggleRenderScriptedBeacons();
+ gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() );
+ // toggle the other one off if it's on
+ if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons())
+ {
+ LLPipeline::toggleRenderScriptedTouchBeacons();
+ gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() );
+ }
+ }
+ else if (beacon == "physicalbeacon")
+ {
+ LLPipeline::toggleRenderPhysicalBeacons();
+ gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons() );
+ }
+ else if (beacon == "moapbeacon")
+ {
+ LLPipeline::toggleRenderMOAPBeacons();
+ gSavedSettings.setBOOL( "moapbeacon", LLPipeline::getRenderMOAPBeacons() );
+ }
+ else if (beacon == "soundsbeacon")
+ {
+ LLPipeline::toggleRenderSoundBeacons();
+ gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons() );
+ }
+ else if (beacon == "particlesbeacon")
+ {
+ LLPipeline::toggleRenderParticleBeacons();
+ gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons() );
+ }
+ else if (beacon == "scripttouchbeacon")
+ {
+ LLPipeline::toggleRenderScriptedTouchBeacons();
+ gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() );
+ // toggle the other one off if it's on
+ if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons())
+ {
+ LLPipeline::toggleRenderScriptedBeacons();
+ gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() );
+ }
+ }
+ else if (beacon == "sunbeacon")
+ {
+ gSavedSettings.setBOOL("sunbeacon", !gSavedSettings.getBOOL("sunbeacon"));
+ }
+ else if (beacon == "moonbeacon")
+ {
+ gSavedSettings.setBOOL("moonbeacon", !gSavedSettings.getBOOL("moonbeacon"));
+ }
+ else if (beacon == "renderbeacons")
+ {
+ LLPipeline::toggleRenderBeacons();
+ gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() );
+ // toggle the other one on if it's not
+ if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights())
+ {
+ LLPipeline::toggleRenderHighlights();
+ gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() );
+ }
+ }
+ else if (beacon == "renderhighlights")
+ {
+ LLPipeline::toggleRenderHighlights();
+ gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() );
+ // toggle the other one on if it's not
+ if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights())
+ {
+ LLPipeline::toggleRenderBeacons();
+ gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() );
+ }
+ }
+
+ return true;
+ }
};
class LLViewCheckBeaconEnabled : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string beacon = userdata.asString();
- bool new_value = false;
- if (beacon == "scriptsbeacon")
- {
- new_value = gSavedSettings.getBOOL( "scriptsbeacon");
- LLPipeline::setRenderScriptedBeacons(new_value);
- }
- else if (beacon == "moapbeacon")
- {
- new_value = gSavedSettings.getBOOL( "moapbeacon");
- LLPipeline::setRenderMOAPBeacons(new_value);
- }
- else if (beacon == "physicalbeacon")
- {
- new_value = gSavedSettings.getBOOL( "physicalbeacon");
- LLPipeline::setRenderPhysicalBeacons(new_value);
- }
- else if (beacon == "soundsbeacon")
- {
- new_value = gSavedSettings.getBOOL( "soundsbeacon");
- LLPipeline::setRenderSoundBeacons(new_value);
- }
- else if (beacon == "particlesbeacon")
- {
- new_value = gSavedSettings.getBOOL( "particlesbeacon");
- LLPipeline::setRenderParticleBeacons(new_value);
- }
- else if (beacon == "scripttouchbeacon")
- {
- new_value = gSavedSettings.getBOOL( "scripttouchbeacon");
- LLPipeline::setRenderScriptedTouchBeacons(new_value);
- }
- else if (beacon == "renderbeacons")
- {
- new_value = gSavedSettings.getBOOL( "renderbeacons");
- LLPipeline::setRenderBeacons(new_value);
- }
- else if (beacon == "renderhighlights")
- {
- new_value = gSavedSettings.getBOOL( "renderhighlights");
- LLPipeline::setRenderHighlights(new_value);
- }
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string beacon = userdata.asString();
+ bool new_value = false;
+ if (beacon == "scriptsbeacon")
+ {
+ new_value = gSavedSettings.getBOOL( "scriptsbeacon");
+ LLPipeline::setRenderScriptedBeacons(new_value);
+ }
+ else if (beacon == "moapbeacon")
+ {
+ new_value = gSavedSettings.getBOOL( "moapbeacon");
+ LLPipeline::setRenderMOAPBeacons(new_value);
+ }
+ else if (beacon == "physicalbeacon")
+ {
+ new_value = gSavedSettings.getBOOL( "physicalbeacon");
+ LLPipeline::setRenderPhysicalBeacons(new_value);
+ }
+ else if (beacon == "soundsbeacon")
+ {
+ new_value = gSavedSettings.getBOOL( "soundsbeacon");
+ LLPipeline::setRenderSoundBeacons(new_value);
+ }
+ else if (beacon == "particlesbeacon")
+ {
+ new_value = gSavedSettings.getBOOL( "particlesbeacon");
+ LLPipeline::setRenderParticleBeacons(new_value);
+ }
+ else if (beacon == "scripttouchbeacon")
+ {
+ new_value = gSavedSettings.getBOOL( "scripttouchbeacon");
+ LLPipeline::setRenderScriptedTouchBeacons(new_value);
+ }
+ else if (beacon == "renderbeacons")
+ {
+ new_value = gSavedSettings.getBOOL( "renderbeacons");
+ LLPipeline::setRenderBeacons(new_value);
+ }
+ else if (beacon == "renderhighlights")
+ {
+ new_value = gSavedSettings.getBOOL( "renderhighlights");
+ LLPipeline::setRenderHighlights(new_value);
+ }
+ return new_value;
+ }
};
class LLViewToggleRenderType : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string type = userdata.asString();
- if (type == "hideparticles")
- {
- LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string type = userdata.asString();
+ if (type == "hideparticles")
+ {
+ LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+ }
+ return true;
+ }
};
class LLViewCheckRenderType : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string type = userdata.asString();
- bool new_value = false;
- if (type == "hideparticles")
- {
- new_value = LLPipeline::toggleRenderTypeControlNegated(LLPipeline::RENDER_TYPE_PARTICLES);
- }
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string type = userdata.asString();
+ bool new_value = false;
+ if (type == "hideparticles")
+ {
+ new_value = LLPipeline::toggleRenderTypeControlNegated(LLPipeline::RENDER_TYPE_PARTICLES);
+ }
+ return new_value;
+ }
};
class LLViewStatusAway : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return (gAgent.isInitialized() && gAgent.getAFK());
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return (gAgent.isInitialized() && gAgent.getAFK());
+ }
};
class LLViewStatusDoNotDisturb : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return (gAgent.isInitialized() && gAgent.isDoNotDisturb());
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return (gAgent.isInitialized() && gAgent.isDoNotDisturb());
+ }
};
class LLViewShowHUDAttachments : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments;
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments;
+ return true;
+ }
};
class LLViewCheckHUDAttachments : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = LLPipeline::sShowHUDAttachments;
- return new_value;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLPipeline::sShowHUDAttachments;
+ return new_value;
+ }
};
class LLEditEnableTakeOff : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string clothing = userdata.asString();
- LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing);
- if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT)
- return LLAgentWearables::selfHasWearable(type);
- return false;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string clothing = userdata.asString();
+ LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing);
+ if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT)
+ return LLAgentWearables::selfHasWearable(type);
+ return false;
+ }
};
class LLEditTakeOff : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string clothing = userdata.asString();
- if (clothing == "all")
- LLAppearanceMgr::instance().removeAllClothesFromAvatar();
- else
- {
- LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing);
- if (type >= LLWearableType::WT_SHAPE
- && type < LLWearableType::WT_COUNT
- && (gAgentWearables.getWearableCount(type) > 0))
- {
- // MULTI-WEARABLES: assuming user wanted to remove top shirt.
- U32 wearable_index = gAgentWearables.getWearableCount(type) - 1;
- LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index);
- LLAppearanceMgr::instance().removeItemFromAvatar(item_id);
- }
-
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string clothing = userdata.asString();
+ if (clothing == "all")
+ LLAppearanceMgr::instance().removeAllClothesFromAvatar();
+ else
+ {
+ LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing);
+ if (type >= LLWearableType::WT_SHAPE
+ && type < LLWearableType::WT_COUNT
+ && (gAgentWearables.getWearableCount(type) > 0))
+ {
+ // MULTI-WEARABLES: assuming user wanted to remove top shirt.
+ U32 wearable_index = gAgentWearables.getWearableCount(type) - 1;
+ LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index);
+ LLAppearanceMgr::instance().removeItemFromAvatar(item_id);
+ }
+
+ }
+ return true;
+ }
};
class LLToolsSelectTool : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string tool_name = userdata.asString();
- if (tool_name == "focus")
- {
- LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(1);
- }
- else if (tool_name == "move")
- {
- LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(2);
- }
- else if (tool_name == "edit")
- {
- LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(3);
- }
- else if (tool_name == "create")
- {
- LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(4);
- }
- else if (tool_name == "land")
- {
- LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(5);
- }
-
- // Note: if floater is not visible LLViewerWindow::updateLayout() will
- // attempt to open it, but it won't bring it to front or de-minimize.
- if (gFloaterTools && (gFloaterTools->isMinimized() || !gFloaterTools->isShown() || !gFloaterTools->isFrontmost()))
- {
- gFloaterTools->setMinimized(FALSE);
- gFloaterTools->openFloater();
- gFloaterTools->setVisibleAndFrontmost(TRUE);
- }
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string tool_name = userdata.asString();
+ if (tool_name == "focus")
+ {
+ LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(1);
+ }
+ else if (tool_name == "move")
+ {
+ LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(2);
+ }
+ else if (tool_name == "edit")
+ {
+ LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(3);
+ }
+ else if (tool_name == "create")
+ {
+ LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(4);
+ }
+ else if (tool_name == "land")
+ {
+ LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(5);
+ }
+
+ // Note: if floater is not visible LLViewerWindow::updateLayout() will
+ // attempt to open it, but it won't bring it to front or de-minimize.
+ if (gFloaterTools && (gFloaterTools->isMinimized() || !gFloaterTools->isShown() || !gFloaterTools->isFrontmost()))
+ {
+ gFloaterTools->setMinimized(FALSE);
+ gFloaterTools->openFloater();
+ gFloaterTools->setVisibleAndFrontmost(TRUE);
+ }
+ return true;
+ }
};
/// WINDLIGHT callbacks
-class LLWorldEnvSettings : public view_listener_t
+void defocusEnvFloaters()
{
- void defocusEnvFloaters()
+ // currently there is only one instance of each floater
+ std::vector<std::string> env_floaters_names = {"env_edit_extdaycycle", "env_fixed_environmentent_water",
+ "env_fixed_environmentent_sky"};
+ for (std::vector<std::string>::const_iterator it = env_floaters_names.begin(); it != env_floaters_names.end(); ++it)
{
- //currently there is only one instance of each floater
- std::vector<std::string> env_floaters_names = { "env_edit_extdaycycle", "env_fixed_environmentent_water", "env_fixed_environmentent_sky" };
- for (std::vector<std::string>::const_iterator it = env_floaters_names.begin(); it != env_floaters_names.end(); ++it)
+ LLFloater *env_floater = LLFloaterReg::findTypedInstance<LLFloater>(*it);
+ if (env_floater)
{
- LLFloater* env_floater = LLFloaterReg::findTypedInstance<LLFloater>(*it);
- if (env_floater)
- {
- env_floater->setFocus(FALSE);
- }
+ env_floater->setFocus(FALSE);
}
}
+}
- bool handleEvent(const LLSD& userdata)
+bool handle_env_setting_event(std::string event_name)
+{
+ if (event_name == "sunrise")
{
- std::string event_name = userdata.asString();
-
- if (event_name == "sunrise")
- {
- LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE, LLEnvironment::TRANSITION_INSTANT);
- LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
- defocusEnvFloaters();
- }
- else if (event_name == "noon")
- {
- LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY, LLEnvironment::TRANSITION_INSTANT);
- LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
- defocusEnvFloaters();
- }
- else if (event_name == "legacy noon")
- {
- LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_LEGACY_MIDDAY, LLEnvironment::TRANSITION_INSTANT);
- LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
- defocusEnvFloaters();
- }
- else if (event_name == "sunset")
- {
- LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET, LLEnvironment::TRANSITION_INSTANT);
- LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
- defocusEnvFloaters();
- }
- else if (event_name == "midnight")
- {
- LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT, LLEnvironment::TRANSITION_INSTANT);
- LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
- defocusEnvFloaters();
- }
- else if (event_name == "region")
- {
- // reset probe data when reverting back to region sky setting
- gPipeline.mReflectionMapManager.reset();
+ LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE,
+ LLEnvironment::TRANSITION_INSTANT);
+ LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
+ defocusEnvFloaters();
+ }
+ else if (event_name == "noon")
+ {
+ LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY,
+ LLEnvironment::TRANSITION_INSTANT);
+ LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
+ defocusEnvFloaters();
+ }
+ else if (event_name == "legacy noon")
+ {
+ LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_LEGACY_MIDDAY, LLEnvironment::TRANSITION_INSTANT);
+ LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
+ defocusEnvFloaters();
+ }
+ else if (event_name == "sunset")
+ {
+ LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET,
+ LLEnvironment::TRANSITION_INSTANT);
+ LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
+ defocusEnvFloaters();
+ }
+ else if (event_name == "midnight")
+ {
+ LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT,
+ LLEnvironment::TRANSITION_INSTANT);
+ LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
+ defocusEnvFloaters();
+ }
+ else if (event_name == "region")
+ {
+ // reset probe data when reverting back to region sky setting
+ gPipeline.mReflectionMapManager.reset();
- LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL);
- LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
- defocusEnvFloaters();
- }
- else if (event_name == "pause_clouds")
- {
- if (LLEnvironment::instance().isCloudScrollPaused())
- LLEnvironment::instance().resumeCloudScroll();
+ LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL);
+ LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
+ defocusEnvFloaters();
+ }
+ else if (event_name == "pause_clouds")
+ {
+ if (LLEnvironment::instance().isCloudScrollPaused())
+ LLEnvironment::instance().resumeCloudScroll();
else
- LLEnvironment::instance().pauseCloudScroll();
- }
- else if (event_name == "adjust_tool")
- {
- LLFloaterReg::showInstance("env_adjust_snapshot");
- }
- else if (event_name == "my_environs")
- {
- LLFloaterReg::showInstance("my_environments");
- }
-
- return true;
+ LLEnvironment::instance().pauseCloudScroll();
+ }
+ else if (event_name == "adjust_tool")
+ {
+ LLFloaterReg::showInstance("env_adjust_snapshot");
+ }
+ else if (event_name == "my_environs")
+ {
+ LLFloaterReg::showInstance("my_environments");
}
+ return true;
+}
+
+class LLWorldEnvSettings : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_env_setting_event(userdata.asString());
+
+ return true;
+ }
};
class LLWorldEnableEnvSettings : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool result = false;
- std::string event_name = userdata.asString();
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool result = false;
+ std::string event_name = userdata.asString();
if (event_name == "pause_clouds")
- {
+ {
return LLEnvironment::instance().isCloudScrollPaused();
- }
+ }
LLSettingsSky::ptr_t sky = LLEnvironment::instance().getEnvironmentFixedSky(LLEnvironment::ENV_LOCAL);
- if (!sky)
- {
- return (event_name == "region");
- }
+ if (!sky)
+ {
+ return (event_name == "region");
+ }
std::string skyname = (sky) ? sky->getName() : "";
LLUUID skyid = (sky) ? sky->getAssetId() : LLUUID::null;
- if (event_name == "sunrise")
- {
+ if (event_name == "sunrise")
+ {
result = (skyid == LLEnvironment::KNOWN_SKY_SUNRISE);
- }
- else if (event_name == "noon")
- {
+ }
+ else if (event_name == "noon")
+ {
result = (skyid == LLEnvironment::KNOWN_SKY_MIDDAY);
- }
+ }
else if (event_name == "legacy noon")
{
result = (skyid == LLEnvironment::KNOWN_SKY_LEGACY_MIDDAY);
}
- else if (event_name == "sunset")
- {
+ else if (event_name == "sunset")
+ {
result = (skyid == LLEnvironment::KNOWN_SKY_SUNSET);
- }
- else if (event_name == "midnight")
- {
+ }
+ else if (event_name == "midnight")
+ {
result = (skyid == LLEnvironment::KNOWN_SKY_MIDNIGHT);
- }
- else if (event_name == "region")
- {
- return false;
- }
- else
- {
- LL_WARNS() << "Unknown time-of-day item: " << event_name << LL_ENDL;
- }
- return result;
- }
+ }
+ else if (event_name == "region")
+ {
+ return false;
+ }
+ else
+ {
+ LL_WARNS() << "Unknown time-of-day item: " << event_name << LL_ENDL;
+ }
+ return result;
+ }
};
class LLWorldEnvPreset : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- std::string item = userdata.asString();
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string item = userdata.asString();
- if (item == "new_water")
- {
+ if (item == "new_water")
+ {
LLFloaterReg::showInstance("env_fixed_environmentent_water", "new");
- }
- else if (item == "edit_water")
- {
+ }
+ else if (item == "edit_water")
+ {
LLFloaterReg::showInstance("env_fixed_environmentent_water", "edit");
- }
- else if (item == "new_sky")
- {
+ }
+ else if (item == "new_sky")
+ {
LLFloaterReg::showInstance("env_fixed_environmentent_sky", "new");
- }
- else if (item == "edit_sky")
- {
+ }
+ else if (item == "edit_sky")
+ {
LLFloaterReg::showInstance("env_fixed_environmentent_sky", "edit");
- }
- else if (item == "new_day_cycle")
- {
+ }
+ else if (item == "new_day_cycle")
+ {
LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory"));
- }
- else if (item == "edit_day_cycle")
- {
- LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory"));
- }
- else
- {
- LL_WARNS() << "Unknown item selected" << LL_ENDL;
- }
+ }
+ else if (item == "edit_day_cycle")
+ {
+ LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory"));
+ }
+ else
+ {
+ LL_WARNS() << "Unknown item selected" << LL_ENDL;
+ }
- return true;
- }
+ return true;
+ }
};
class LLWorldEnableEnvPreset : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
+ bool handleEvent(const LLSD& userdata)
+ {
- return false;
- }
+ return false;
+ }
};
/// Post-Process callbacks
class LLWorldPostProcess : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterReg::showInstance("env_post_process");
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterReg::showInstance("env_post_process");
+ return true;
+ }
};
class LLWorldCheckBanLines : public view_listener_t
@@ -9200,684 +9209,684 @@ class LLWorldShowBanLines : public view_listener_t
void handle_flush_name_caches()
{
- if (gCacheName) gCacheName->clear();
+ if (gCacheName) gCacheName->clear();
}
class LLUploadCostCalculator : public view_listener_t
{
- std::string mCostStr;
-
- bool handleEvent(const LLSD& userdata)
- {
- std::vector<std::string> fields;
- std::string str = userdata.asString();
- boost::split(fields, str, boost::is_any_of(","));
- if (fields.size()<1)
- {
- return false;
- }
- std::string menu_name = fields[0];
- std::string asset_type_str = "texture";
- if (fields.size()>1)
- {
- asset_type_str = fields[1];
- }
- LL_DEBUGS("Benefits") << "userdata " << userdata << " menu_name " << menu_name << " asset_type_str " << asset_type_str << LL_ENDL;
- calculateCost(asset_type_str);
- gMenuHolder->childSetLabelArg(menu_name, "[COST]", mCostStr);
-
- return true;
- }
-
- void calculateCost(const std::string& asset_type_str);
+ std::string mCostStr;
+
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::vector<std::string> fields;
+ std::string str = userdata.asString();
+ boost::split(fields, str, boost::is_any_of(","));
+ if (fields.size()<1)
+ {
+ return false;
+ }
+ std::string menu_name = fields[0];
+ std::string asset_type_str = "texture";
+ if (fields.size()>1)
+ {
+ asset_type_str = fields[1];
+ }
+ LL_DEBUGS("Benefits") << "userdata " << userdata << " menu_name " << menu_name << " asset_type_str " << asset_type_str << LL_ENDL;
+ calculateCost(asset_type_str);
+ gMenuHolder->childSetLabelArg(menu_name, "[COST]", mCostStr);
+
+ return true;
+ }
+
+ void calculateCost(const std::string& asset_type_str);
public:
- LLUploadCostCalculator()
- {
- }
+ LLUploadCostCalculator()
+ {
+ }
};
class LLUpdateMembershipLabel : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- const std::string label_str = LLAgentBenefitsMgr::isCurrent("Base") ? LLTrans::getString("MembershipUpgradeText") : LLTrans::getString("MembershipPremiumText");
- gMenuHolder->childSetLabelArg("Membership", "[Membership]", label_str);
+ bool handleEvent(const LLSD& userdata)
+ {
+ const std::string label_str = LLAgentBenefitsMgr::isCurrent("Base") ? LLTrans::getString("MembershipUpgradeText") : LLTrans::getString("MembershipPremiumText");
+ gMenuHolder->childSetLabelArg("Membership", "[Membership]", label_str);
- return true;
- }
+ return true;
+ }
};
void handle_voice_morphing_subscribe()
{
- LLWeb::loadURL(LLTrans::getString("voice_morphing_url"));
+ LLWeb::loadURL(LLTrans::getString("voice_morphing_url"));
}
void handle_premium_voice_morphing_subscribe()
{
- LLWeb::loadURL(LLTrans::getString("premium_voice_morphing_url"));
+ LLWeb::loadURL(LLTrans::getString("premium_voice_morphing_url"));
}
class LLToggleUIHints : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool ui_hints_enabled = gSavedSettings.getBOOL("EnableUIHints");
- // toggle
- ui_hints_enabled = !ui_hints_enabled;
- gSavedSettings.setBOOL("EnableUIHints", ui_hints_enabled);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool ui_hints_enabled = gSavedSettings.getBOOL("EnableUIHints");
+ // toggle
+ ui_hints_enabled = !ui_hints_enabled;
+ gSavedSettings.setBOOL("EnableUIHints", ui_hints_enabled);
+ return true;
+ }
};
void LLUploadCostCalculator::calculateCost(const std::string& asset_type_str)
{
- S32 upload_cost = -1;
-
- if (asset_type_str == "texture")
- {
- upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
- }
- else if (asset_type_str == "animation")
- {
- upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost();
- }
- else if (asset_type_str == "sound")
- {
- upload_cost = LLAgentBenefitsMgr::current().getSoundUploadCost();
- }
- if (upload_cost < 0)
- {
- LL_WARNS() << "Unable to find upload cost for asset_type_str " << asset_type_str << LL_ENDL;
- }
- mCostStr = std::to_string(upload_cost);
+ S32 upload_cost = -1;
+
+ if (asset_type_str == "texture")
+ {
+ upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
+ }
+ else if (asset_type_str == "animation")
+ {
+ upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost();
+ }
+ else if (asset_type_str == "sound")
+ {
+ upload_cost = LLAgentBenefitsMgr::current().getSoundUploadCost();
+ }
+ if (upload_cost < 0)
+ {
+ LL_WARNS() << "Unable to find upload cost for asset_type_str " << asset_type_str << LL_ENDL;
+ }
+ mCostStr = std::to_string(upload_cost);
}
void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y)
{
- static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml",
- gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- if(gMenuHolder->hasVisibleMenu())
- {
- gMenuHolder->hideMenus();
- }
- show_navbar_context_menu->buildDrawLabels();
- show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer);
- LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y);
+ static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml",
+ gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(gMenuHolder->hasVisibleMenu())
+ {
+ gMenuHolder->hideMenus();
+ }
+ show_navbar_context_menu->buildDrawLabels();
+ show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y);
}
void show_topinfobar_context_menu(LLView* ctrl, S32 x, S32 y)
{
- static LLMenuGL* show_topbarinfo_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_topinfobar.xml",
- gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ static LLMenuGL* show_topbarinfo_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_topinfobar.xml",
+ gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- LLMenuItemGL* landmark_item = show_topbarinfo_context_menu->getChild<LLMenuItemGL>("Landmark");
- if (!LLLandmarkActions::landmarkAlreadyExists())
- {
- landmark_item->setLabel(LLTrans::getString("AddLandmarkNavBarMenu"));
- }
- else
- {
- landmark_item->setLabel(LLTrans::getString("EditLandmarkNavBarMenu"));
- }
+ LLMenuItemGL* landmark_item = show_topbarinfo_context_menu->getChild<LLMenuItemGL>("Landmark");
+ if (!LLLandmarkActions::landmarkAlreadyExists())
+ {
+ landmark_item->setLabel(LLTrans::getString("AddLandmarkNavBarMenu"));
+ }
+ else
+ {
+ landmark_item->setLabel(LLTrans::getString("EditLandmarkNavBarMenu"));
+ }
- if(gMenuHolder->hasVisibleMenu())
- {
- gMenuHolder->hideMenus();
- }
+ if(gMenuHolder->hasVisibleMenu())
+ {
+ gMenuHolder->hideMenus();
+ }
- show_topbarinfo_context_menu->buildDrawLabels();
- show_topbarinfo_context_menu->updateParent(LLMenuGL::sMenuContainer);
- LLMenuGL::showPopup(ctrl, show_topbarinfo_context_menu, x, y);
+ show_topbarinfo_context_menu->buildDrawLabels();
+ show_topbarinfo_context_menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(ctrl, show_topbarinfo_context_menu, x, y);
}
void initialize_edit_menu()
{
- view_listener_t::addMenu(new LLEditUndo(), "Edit.Undo");
- view_listener_t::addMenu(new LLEditRedo(), "Edit.Redo");
- view_listener_t::addMenu(new LLEditCut(), "Edit.Cut");
- view_listener_t::addMenu(new LLEditCopy(), "Edit.Copy");
- view_listener_t::addMenu(new LLEditPaste(), "Edit.Paste");
- view_listener_t::addMenu(new LLEditDelete(), "Edit.Delete");
- view_listener_t::addMenu(new LLEditSelectAll(), "Edit.SelectAll");
- view_listener_t::addMenu(new LLEditDeselect(), "Edit.Deselect");
- view_listener_t::addMenu(new LLEditTakeOff(), "Edit.TakeOff");
- view_listener_t::addMenu(new LLEditEnableUndo(), "Edit.EnableUndo");
- view_listener_t::addMenu(new LLEditEnableRedo(), "Edit.EnableRedo");
- view_listener_t::addMenu(new LLEditEnableCut(), "Edit.EnableCut");
- view_listener_t::addMenu(new LLEditEnableCopy(), "Edit.EnableCopy");
- view_listener_t::addMenu(new LLEditEnablePaste(), "Edit.EnablePaste");
- view_listener_t::addMenu(new LLEditEnableDelete(), "Edit.EnableDelete");
- view_listener_t::addMenu(new LLEditEnableSelectAll(), "Edit.EnableSelectAll");
- view_listener_t::addMenu(new LLEditEnableDeselect(), "Edit.EnableDeselect");
+ view_listener_t::addMenu(new LLEditUndo(), "Edit.Undo");
+ view_listener_t::addMenu(new LLEditRedo(), "Edit.Redo");
+ view_listener_t::addMenu(new LLEditCut(), "Edit.Cut");
+ view_listener_t::addMenu(new LLEditCopy(), "Edit.Copy");
+ view_listener_t::addMenu(new LLEditPaste(), "Edit.Paste");
+ view_listener_t::addMenu(new LLEditDelete(), "Edit.Delete");
+ view_listener_t::addMenu(new LLEditSelectAll(), "Edit.SelectAll");
+ view_listener_t::addMenu(new LLEditDeselect(), "Edit.Deselect");
+ view_listener_t::addMenu(new LLEditTakeOff(), "Edit.TakeOff");
+ view_listener_t::addMenu(new LLEditEnableUndo(), "Edit.EnableUndo");
+ view_listener_t::addMenu(new LLEditEnableRedo(), "Edit.EnableRedo");
+ view_listener_t::addMenu(new LLEditEnableCut(), "Edit.EnableCut");
+ view_listener_t::addMenu(new LLEditEnableCopy(), "Edit.EnableCopy");
+ view_listener_t::addMenu(new LLEditEnablePaste(), "Edit.EnablePaste");
+ view_listener_t::addMenu(new LLEditEnableDelete(), "Edit.EnableDelete");
+ view_listener_t::addMenu(new LLEditEnableSelectAll(), "Edit.EnableSelectAll");
+ view_listener_t::addMenu(new LLEditEnableDeselect(), "Edit.EnableDeselect");
}
void initialize_spellcheck_menu()
{
- LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
- LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar();
+ LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
+ LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar();
- commit.add("SpellCheck.ReplaceWithSuggestion", boost::bind(&handle_spellcheck_replace_with_suggestion, _1, _2));
- enable.add("SpellCheck.VisibleSuggestion", boost::bind(&visible_spellcheck_suggestion, _1, _2));
- commit.add("SpellCheck.AddToDictionary", boost::bind(&handle_spellcheck_add_to_dictionary, _1));
- enable.add("SpellCheck.EnableAddToDictionary", boost::bind(&enable_spellcheck_add_to_dictionary, _1));
- commit.add("SpellCheck.AddToIgnore", boost::bind(&handle_spellcheck_add_to_ignore, _1));
- enable.add("SpellCheck.EnableAddToIgnore", boost::bind(&enable_spellcheck_add_to_ignore, _1));
+ commit.add("SpellCheck.ReplaceWithSuggestion", boost::bind(&handle_spellcheck_replace_with_suggestion, _1, _2));
+ enable.add("SpellCheck.VisibleSuggestion", boost::bind(&visible_spellcheck_suggestion, _1, _2));
+ commit.add("SpellCheck.AddToDictionary", boost::bind(&handle_spellcheck_add_to_dictionary, _1));
+ enable.add("SpellCheck.EnableAddToDictionary", boost::bind(&enable_spellcheck_add_to_dictionary, _1));
+ commit.add("SpellCheck.AddToIgnore", boost::bind(&handle_spellcheck_add_to_ignore, _1));
+ enable.add("SpellCheck.EnableAddToIgnore", boost::bind(&enable_spellcheck_add_to_ignore, _1));
}
void initialize_menus()
{
- // A parameterized event handler used as ctrl-8/9/0 zoom controls below.
- class LLZoomer : public view_listener_t
- {
- public:
- // The "mult" parameter says whether "val" is a multiplier or used to set the value.
- LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {}
- bool handleEvent(const LLSD& userdata)
- {
- F32 new_fov_rad = mMult ? LLViewerCamera::getInstance()->getDefaultFOV() * mVal : mVal;
- LLViewerCamera::getInstance()->setDefaultFOV(new_fov_rad);
- gSavedSettings.setF32("CameraAngle", LLViewerCamera::getInstance()->getView()); // setView may have clamped it.
- return true;
- }
- private:
- F32 mVal;
- bool mMult;
- };
-
- LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar();
- LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
-
- // Generic enable and visible
- // Don't prepend MenuName.Foo because these can be used in any menu.
- enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service));
-
- enable.add("displayViewerEventRecorderMenuItems",boost::bind(&LLViewerEventRecorder::displayViewerEventRecorderMenuItems,&LLViewerEventRecorder::instance()));
-
- view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts");
-
- view_listener_t::addEnable(new LLUpdateMembershipLabel(), "Membership.UpdateLabel");
-
- enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed));
-
- // Agent
- commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying));
- enable.add("Agent.enableFlyLand", boost::bind(&enable_fly_land));
- commit.add("Agent.PressMicrophone", boost::bind(&LLAgent::pressMicrophone, _2));
- commit.add("Agent.ReleaseMicrophone", boost::bind(&LLAgent::releaseMicrophone, _2));
- commit.add("Agent.ToggleMicrophone", boost::bind(&LLAgent::toggleMicrophone, _2));
- enable.add("Agent.IsMicrophoneOn", boost::bind(&LLAgent::isMicrophoneOn, _2));
- enable.add("Agent.IsActionAllowed", boost::bind(&LLAgent::isActionAllowed, _2));
-
- // File menu
- init_menu_file();
-
- view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
- view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
- view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape");
- view_listener_t::addMenu(new LLEnableHoverHeight(), "Edit.EnableHoverHeight");
- view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics");
- commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
+ // A parameterized event handler used as ctrl-8/9/0 zoom controls below.
+ class LLZoomer : public view_listener_t
+ {
+ public:
+ // The "mult" parameter says whether "val" is a multiplier or used to set the value.
+ LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {}
+ bool handleEvent(const LLSD& userdata)
+ {
+ F32 new_fov_rad = mMult ? LLViewerCamera::getInstance()->getDefaultFOV() * mVal : mVal;
+ LLViewerCamera::getInstance()->setDefaultFOV(new_fov_rad);
+ gSavedSettings.setF32("CameraAngle", LLViewerCamera::getInstance()->getView()); // setView may have clamped it.
+ return true;
+ }
+ private:
+ F32 mVal;
+ bool mMult;
+ };
+
+ LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar();
+ LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
+
+ // Generic enable and visible
+ // Don't prepend MenuName.Foo because these can be used in any menu.
+ enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service));
+
+ enable.add("displayViewerEventRecorderMenuItems",boost::bind(&LLViewerEventRecorder::displayViewerEventRecorderMenuItems,&LLViewerEventRecorder::instance()));
+
+ view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts");
+
+ view_listener_t::addEnable(new LLUpdateMembershipLabel(), "Membership.UpdateLabel");
+
+ enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed));
+
+ // Agent
+ commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying));
+ enable.add("Agent.enableFlyLand", boost::bind(&enable_fly_land));
+ commit.add("Agent.PressMicrophone", boost::bind(&LLAgent::pressMicrophone, _2));
+ commit.add("Agent.ReleaseMicrophone", boost::bind(&LLAgent::releaseMicrophone, _2));
+ commit.add("Agent.ToggleMicrophone", boost::bind(&LLAgent::toggleMicrophone, _2));
+ enable.add("Agent.IsMicrophoneOn", boost::bind(&LLAgent::isMicrophoneOn, _2));
+ enable.add("Agent.IsActionAllowed", boost::bind(&LLAgent::isActionAllowed, _2));
+
+ // File menu
+ init_menu_file();
+
+ view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
+ view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
+ view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape");
+ view_listener_t::addMenu(new LLEnableHoverHeight(), "Edit.EnableHoverHeight");
+ view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics");
+ commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
commit.add("NowWearing", boost::bind(&handle_now_wearing));
- commit.add("EditOutfit", boost::bind(&handle_edit_outfit));
- commit.add("EditShape", boost::bind(&handle_edit_shape));
- commit.add("HoverHeight", boost::bind(&handle_hover_height));
- commit.add("EditPhysics", boost::bind(&handle_edit_physics));
-
- // View menu
- view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook");
- view_listener_t::addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam");
- view_listener_t::addMenu(new LLViewResetView(), "View.ResetView");
- view_listener_t::addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter");
- view_listener_t::addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips");
- view_listener_t::addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent");
- view_listener_t::addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType");
- view_listener_t::addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments");
- view_listener_t::addMenu(new LLZoomer(1.2f), "View.ZoomOut");
- view_listener_t::addMenu(new LLZoomer(1/1.2f), "View.ZoomIn");
- view_listener_t::addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault");
- view_listener_t::addMenu(new LLViewDefaultUISize(), "View.DefaultUISize");
- view_listener_t::addMenu(new LLViewToggleUI(), "View.ToggleUI");
-
- view_listener_t::addMenu(new LLViewEnableMouselook(), "View.EnableMouselook");
- view_listener_t::addMenu(new LLViewEnableJoystickFlycam(), "View.EnableJoystickFlycam");
- view_listener_t::addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter");
-
- view_listener_t::addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam");
- view_listener_t::addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips");
- view_listener_t::addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent");
- view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType");
- view_listener_t::addMenu(new LLViewStatusAway(), "View.Status.CheckAway");
- view_listener_t::addMenu(new LLViewStatusDoNotDisturb(), "View.Status.CheckDoNotDisturb");
- view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments");
-
- //Communicate Nearby chat
- view_listener_t::addMenu(new LLCommunicateNearbyChat(), "Communicate.NearbyChat");
-
- // Communicate > Voice morphing > Subscribe...
- commit.add("Communicate.VoiceMorphing.Subscribe", boost::bind(&handle_voice_morphing_subscribe));
- // Communicate > Voice morphing > Premium perk...
- commit.add("Communicate.VoiceMorphing.PremiumPerk", boost::bind(&handle_premium_voice_morphing_subscribe));
- LLVivoxVoiceClient * voice_clientp = LLVivoxVoiceClient::getInstance();
- enable.add("Communicate.VoiceMorphing.NoVoiceMorphing.Check"
- , boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, voice_clientp, "NoVoiceMorphing"));
- commit.add("Communicate.VoiceMorphing.NoVoiceMorphing.Click"
- , boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, voice_clientp, "NoVoiceMorphing"));
-
- // World menu
- view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
- view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark");
- view_listener_t::addMenu(new LLWorldPlaceProfile(), "World.PlaceProfile");
- view_listener_t::addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation");
- view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome");
- view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway");
- view_listener_t::addMenu(new LLWorldSetDoNotDisturb(), "World.SetDoNotDisturb");
- view_listener_t::addMenu(new LLWorldLindenHome(), "World.LindenHome");
-
- view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark");
- view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation");
- view_listener_t::addMenu(new LLWorldEnableTeleportHome(), "World.EnableTeleportHome");
- view_listener_t::addMenu(new LLWorldEnableBuyLand(), "World.EnableBuyLand");
-
- view_listener_t::addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun");
-
- view_listener_t::addMenu(new LLWorldEnvSettings(), "World.EnvSettings");
- view_listener_t::addMenu(new LLWorldEnableEnvSettings(), "World.EnableEnvSettings");
- view_listener_t::addMenu(new LLWorldEnvPreset(), "World.EnvPreset");
- view_listener_t::addMenu(new LLWorldEnableEnvPreset(), "World.EnableEnvPreset");
- view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess");
+ commit.add("EditOutfit", boost::bind(&handle_edit_outfit));
+ commit.add("EditShape", boost::bind(&handle_edit_shape));
+ commit.add("HoverHeight", boost::bind(&handle_hover_height));
+ commit.add("EditPhysics", boost::bind(&handle_edit_physics));
+
+ // View menu
+ view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook");
+ view_listener_t::addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam");
+ view_listener_t::addMenu(new LLViewResetView(), "View.ResetView");
+ view_listener_t::addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter");
+ view_listener_t::addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips");
+ view_listener_t::addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent");
+ view_listener_t::addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType");
+ view_listener_t::addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments");
+ view_listener_t::addMenu(new LLZoomer(1.2f), "View.ZoomOut");
+ view_listener_t::addMenu(new LLZoomer(1/1.2f), "View.ZoomIn");
+ view_listener_t::addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault");
+ view_listener_t::addMenu(new LLViewDefaultUISize(), "View.DefaultUISize");
+ view_listener_t::addMenu(new LLViewToggleUI(), "View.ToggleUI");
+
+ view_listener_t::addMenu(new LLViewEnableMouselook(), "View.EnableMouselook");
+ view_listener_t::addMenu(new LLViewEnableJoystickFlycam(), "View.EnableJoystickFlycam");
+ view_listener_t::addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter");
+
+ view_listener_t::addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam");
+ view_listener_t::addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips");
+ view_listener_t::addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent");
+ view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType");
+ view_listener_t::addMenu(new LLViewStatusAway(), "View.Status.CheckAway");
+ view_listener_t::addMenu(new LLViewStatusDoNotDisturb(), "View.Status.CheckDoNotDisturb");
+ view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments");
+
+ //Communicate Nearby chat
+ view_listener_t::addMenu(new LLCommunicateNearbyChat(), "Communicate.NearbyChat");
+
+ // Communicate > Voice morphing > Subscribe...
+ commit.add("Communicate.VoiceMorphing.Subscribe", boost::bind(&handle_voice_morphing_subscribe));
+ // Communicate > Voice morphing > Premium perk...
+ commit.add("Communicate.VoiceMorphing.PremiumPerk", boost::bind(&handle_premium_voice_morphing_subscribe));
+ LLVivoxVoiceClient * voice_clientp = LLVivoxVoiceClient::getInstance();
+ enable.add("Communicate.VoiceMorphing.NoVoiceMorphing.Check"
+ , boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, voice_clientp, "NoVoiceMorphing"));
+ commit.add("Communicate.VoiceMorphing.NoVoiceMorphing.Click"
+ , boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, voice_clientp, "NoVoiceMorphing"));
+
+ // World menu
+ view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
+ view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark");
+ view_listener_t::addMenu(new LLWorldPlaceProfile(), "World.PlaceProfile");
+ view_listener_t::addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation");
+ view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome");
+ view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway");
+ view_listener_t::addMenu(new LLWorldSetDoNotDisturb(), "World.SetDoNotDisturb");
+ view_listener_t::addMenu(new LLWorldLindenHome(), "World.LindenHome");
+
+ view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark");
+ view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation");
+ view_listener_t::addMenu(new LLWorldEnableTeleportHome(), "World.EnableTeleportHome");
+ view_listener_t::addMenu(new LLWorldEnableBuyLand(), "World.EnableBuyLand");
+
+ view_listener_t::addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun");
+
+ view_listener_t::addMenu(new LLWorldEnvSettings(), "World.EnvSettings");
+ view_listener_t::addMenu(new LLWorldEnableEnvSettings(), "World.EnableEnvSettings");
+ view_listener_t::addMenu(new LLWorldEnvPreset(), "World.EnvPreset");
+ view_listener_t::addMenu(new LLWorldEnableEnvPreset(), "World.EnableEnvPreset");
+ view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess");
view_listener_t::addMenu(new LLWorldCheckBanLines() , "World.CheckBanLines");
view_listener_t::addMenu(new LLWorldShowBanLines() , "World.ShowBanLines");
- // Tools menu
- view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool");
- view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects");
- view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects");
+ // Tools menu
+ view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool");
+ view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects");
+ view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects");
view_listener_t::addMenu(new LLToolsSelectInvisibleObjects(), "Tools.SelectInvisibleObjects");
view_listener_t::addMenu(new LLToolsSelectReflectionProbes(), "Tools.SelectReflectionProbes");
- view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding");
- view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection");
- view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius");
- view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts");
- view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY");
- view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid");
- view_listener_t::addMenu(new LLToolsSelectNextPartFace(), "Tools.SelectNextPart");
- commit.add("Tools.Link", boost::bind(&handle_link_objects));
- commit.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance()));
- view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations");
- view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys");
- view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys");
- commit.add("Tools.LookAtSelection", boost::bind(&handle_look_at_selection, _2));
- commit.add("Tools.BuyOrTake", boost::bind(&handle_buy_or_take));
- commit.add("Tools.TakeCopy", boost::bind(&handle_take_copy));
- view_listener_t::addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory");
- view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction");
-
- view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie");
- view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart");
- enable.add("Tools.EnableLink", boost::bind(&LLSelectMgr::enableLinkObjects, LLSelectMgr::getInstance()));
- enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance()));
- view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
- enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy));
- enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object));
- enable.add("Tools.VisibleTakeObject", boost::bind(&tools_visible_take_object));
- view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory");
-
- view_listener_t::addMenu(new LLToolsEnablePathfinding(), "Tools.EnablePathfinding");
- view_listener_t::addMenu(new LLToolsEnablePathfindingView(), "Tools.EnablePathfindingView");
- view_listener_t::addMenu(new LLToolsDoPathfindingRebakeRegion(), "Tools.DoPathfindingRebakeRegion");
- view_listener_t::addMenu(new LLToolsEnablePathfindingRebakeRegion(), "Tools.EnablePathfindingRebakeRegion");
-
- // Help menu
- // most items use the ShowFloater method
- view_listener_t::addMenu(new LLToggleHowTo(), "Help.ToggleHowTo");
-
- // Advanced menu
- view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole");
- view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole");
- view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole");
-
- // Advanced > HUD Info
- view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo");
- view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo");
-
- // Advanced Other Settings
- view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache");
-
- // Advanced > Render > Types
- view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType");
- view_listener_t::addMenu(new LLAdvancedCheckRenderType(), "Advanced.CheckRenderType");
-
- //// Advanced > Render > Features
- view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature");
- view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature");
-
- view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity");
- view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity");
-
- // Advanced > Render > Info Displays
- view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay");
- view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay");
- view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo");
- commit.add("Advanced.SelectedMaterialInfo", boost::bind(&handle_selected_material_info));
- view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe");
- view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");
- // Develop > Render
- view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate");
- view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");
- view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame");
- view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame");
- view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles");
- view_listener_t::addMenu(new LLAdvancedCheckRenderShadowOption(), "Advanced.CheckRenderShadowOption");
- view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption");
- view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile");
- view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark");
- view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache");
-
- #ifdef TOGGLE_HACKED_GODLIKE_VIEWER
- view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode");
- view_listener_t::addMenu(new LLAdvancedCheckToggleHackedGodmode(), "Advanced.CheckToggleHackedGodmode");
- view_listener_t::addMenu(new LLAdvancedEnableToggleHackedGodmode(), "Advanced.EnableToggleHackedGodmode");
- #endif
-
- // Advanced > World
- view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera");
- view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache");
+ view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding");
+ view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection");
+ view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius");
+ view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts");
+ view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY");
+ view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid");
+ view_listener_t::addMenu(new LLToolsSelectNextPartFace(), "Tools.SelectNextPart");
+ commit.add("Tools.Link", boost::bind(&handle_link_objects));
+ commit.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance()));
+ view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations");
+ view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys");
+ view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys");
+ commit.add("Tools.LookAtSelection", boost::bind(&handle_look_at_selection, _2));
+ commit.add("Tools.BuyOrTake", boost::bind(&handle_buy_or_take));
+ commit.add("Tools.TakeCopy", boost::bind(&handle_take_copy));
+ view_listener_t::addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory");
+ view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction");
+
+ view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie");
+ view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart");
+ enable.add("Tools.EnableLink", boost::bind(&LLSelectMgr::enableLinkObjects, LLSelectMgr::getInstance()));
+ enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance()));
+ view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
+ enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy));
+ enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object));
+ enable.add("Tools.VisibleTakeObject", boost::bind(&tools_visible_take_object));
+ view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory");
+
+ view_listener_t::addMenu(new LLToolsEnablePathfinding(), "Tools.EnablePathfinding");
+ view_listener_t::addMenu(new LLToolsEnablePathfindingView(), "Tools.EnablePathfindingView");
+ view_listener_t::addMenu(new LLToolsDoPathfindingRebakeRegion(), "Tools.DoPathfindingRebakeRegion");
+ view_listener_t::addMenu(new LLToolsEnablePathfindingRebakeRegion(), "Tools.EnablePathfindingRebakeRegion");
+
+ // Help menu
+ // most items use the ShowFloater method
+ view_listener_t::addMenu(new LLToggleHowTo(), "Help.ToggleHowTo");
+
+ // Advanced menu
+ view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole");
+ view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole");
+ view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole");
+
+ // Advanced > HUD Info
+ view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo");
+ view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo");
+
+ // Advanced Other Settings
+ view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache");
+
+ // Advanced > Render > Types
+ view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType");
+ view_listener_t::addMenu(new LLAdvancedCheckRenderType(), "Advanced.CheckRenderType");
+
+ //// Advanced > Render > Features
+ view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature");
+ view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature");
+
+ view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity");
+ view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity");
+
+ // Advanced > Render > Info Displays
+ view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay");
+ view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay");
+ view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo");
+ commit.add("Advanced.SelectedMaterialInfo", boost::bind(&handle_selected_material_info));
+ view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe");
+ view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");
+ // Develop > Render
+ view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate");
+ view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");
+ view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame");
+ view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame");
+ view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles");
+ view_listener_t::addMenu(new LLAdvancedCheckRenderShadowOption(), "Advanced.CheckRenderShadowOption");
+ view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption");
+ view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile");
+ view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark");
+ view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache");
+
+ #ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+ view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode");
+ view_listener_t::addMenu(new LLAdvancedCheckToggleHackedGodmode(), "Advanced.CheckToggleHackedGodmode");
+ view_listener_t::addMenu(new LLAdvancedEnableToggleHackedGodmode(), "Advanced.EnableToggleHackedGodmode");
+ #endif
+
+ // Advanced > World
+ view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera");
+ view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache");
view_listener_t::addMenu(new LLAdvancedToggleStatsRecorder(), "Advanced.ToggleStatsRecorder");
view_listener_t::addMenu(new LLAdvancedCheckStatsRecorder(), "Advanced.CheckStatsRecorder");
view_listener_t::addMenu(new LLAdvancedToggleInterestList360Mode(), "Advanced.ToggleInterestList360Mode");
view_listener_t::addMenu(new LLAdvancedCheckInterestList360Mode(), "Advanced.CheckInterestList360Mode");
view_listener_t::addMenu(new LLAdvancedResetInterestLists(), "Advanced.ResetInterestLists");
- // Advanced > UI
- commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser
- commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater
- commit.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2));
- commit.add("Advanced.ReportBug", boost::bind(&handle_report_bug, _2));
- view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest");
- view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr");
- view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory");
- commit.add("Advanced.DumpTimers", boost::bind(&handle_dump_timers) );
- commit.add("Advanced.DumpFocusHolder", boost::bind(&handle_dump_focus) );
- view_listener_t::addMenu(new LLAdvancedPrintSelectedObjectInfo(), "Advanced.PrintSelectedObjectInfo");
- view_listener_t::addMenu(new LLAdvancedPrintAgentInfo(), "Advanced.PrintAgentInfo");
- view_listener_t::addMenu(new LLAdvancedToggleDebugClicks(), "Advanced.ToggleDebugClicks");
- view_listener_t::addMenu(new LLAdvancedCheckDebugClicks(), "Advanced.CheckDebugClicks");
- view_listener_t::addMenu(new LLAdvancedCheckDebugViews(), "Advanced.CheckDebugViews");
- view_listener_t::addMenu(new LLAdvancedToggleDebugViews(), "Advanced.ToggleDebugViews");
- view_listener_t::addMenu(new LLAdvancedCheckDebugUnicode(), "Advanced.CheckDebugUnicode");
- view_listener_t::addMenu(new LLAdvancedToggleDebugUnicode(), "Advanced.ToggleDebugUnicode");
- view_listener_t::addMenu(new LLAdvancedCheckDebugCamera(), "Advanced.CheckDebugCamera");
- view_listener_t::addMenu(new LLAdvancedToggleDebugCamera(), "Advanced.ToggleDebugCamera");
- view_listener_t::addMenu(new LLAdvancedToggleXUINameTooltips(), "Advanced.ToggleXUINameTooltips");
- view_listener_t::addMenu(new LLAdvancedCheckXUINameTooltips(), "Advanced.CheckXUINameTooltips");
- view_listener_t::addMenu(new LLAdvancedToggleDebugMouseEvents(), "Advanced.ToggleDebugMouseEvents");
- view_listener_t::addMenu(new LLAdvancedCheckDebugMouseEvents(), "Advanced.CheckDebugMouseEvents");
- view_listener_t::addMenu(new LLAdvancedToggleDebugKeys(), "Advanced.ToggleDebugKeys");
- view_listener_t::addMenu(new LLAdvancedCheckDebugKeys(), "Advanced.CheckDebugKeys");
- view_listener_t::addMenu(new LLAdvancedToggleDebugWindowProc(), "Advanced.ToggleDebugWindowProc");
- view_listener_t::addMenu(new LLAdvancedCheckDebugWindowProc(), "Advanced.CheckDebugWindowProc");
-
- // Advanced > XUI
- commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance()));
- view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames");
- view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames");
- view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs");
- commit.add("Advanced.FlushNameCaches", boost::bind(&handle_flush_name_caches));
-
- // Advanced > Character > Grab Baked Texture
- view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture");
- view_listener_t::addMenu(new LLAdvancedEnableGrabBakedTexture(), "Advanced.EnableGrabBakedTexture");
-
- // Advanced > Character > Character Tests
- view_listener_t::addMenu(new LLAdvancedAppearanceToXML(), "Advanced.AppearanceToXML");
- view_listener_t::addMenu(new LLAdvancedEnableAppearanceToXML(), "Advanced.EnableAppearanceToXML");
- view_listener_t::addMenu(new LLAdvancedToggleCharacterGeometry(), "Advanced.ToggleCharacterGeometry");
-
- view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale");
- view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale");
-
- // Advanced > Character > Animation Speed
- view_listener_t::addMenu(new LLAdvancedAnimTenFaster(), "Advanced.AnimTenFaster");
- view_listener_t::addMenu(new LLAdvancedAnimTenSlower(), "Advanced.AnimTenSlower");
- view_listener_t::addMenu(new LLAdvancedAnimResetAll(), "Advanced.AnimResetAll");
-
- // Advanced > Character (toplevel)
- view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault");
- view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader");
- view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo");
- view_listener_t::addMenu(new LLAdvancedCheckAnimationInfo(), "Advanced.CheckAnimationInfo");
- view_listener_t::addMenu(new LLAdvancedToggleShowLookAt(), "Advanced.ToggleShowLookAt");
- view_listener_t::addMenu(new LLAdvancedCheckShowLookAt(), "Advanced.CheckShowLookAt");
- view_listener_t::addMenu(new LLAdvancedToggleShowPointAt(), "Advanced.ToggleShowPointAt");
- view_listener_t::addMenu(new LLAdvancedCheckShowPointAt(), "Advanced.CheckShowPointAt");
- view_listener_t::addMenu(new LLAdvancedToggleDebugJointUpdates(), "Advanced.ToggleDebugJointUpdates");
- view_listener_t::addMenu(new LLAdvancedCheckDebugJointUpdates(), "Advanced.CheckDebugJointUpdates");
- view_listener_t::addMenu(new LLAdvancedToggleDisableLOD(), "Advanced.ToggleDisableLOD");
- view_listener_t::addMenu(new LLAdvancedCheckDisableLOD(), "Advanced.CheckDisableLOD");
- view_listener_t::addMenu(new LLAdvancedToggleDebugCharacterVis(), "Advanced.ToggleDebugCharacterVis");
- view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis");
- view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments");
- view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures");
- view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures");
- view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures");
- // Advanced > Network
- view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog");
- view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog");
- view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket");
+ // Advanced > UI
+ commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser
+ commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater
+ commit.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2));
+ commit.add("Advanced.ReportBug", boost::bind(&handle_report_bug, _2));
+ view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest");
+ view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr");
+ view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory");
+ commit.add("Advanced.DumpTimers", boost::bind(&handle_dump_timers) );
+ commit.add("Advanced.DumpFocusHolder", boost::bind(&handle_dump_focus) );
+ view_listener_t::addMenu(new LLAdvancedPrintSelectedObjectInfo(), "Advanced.PrintSelectedObjectInfo");
+ view_listener_t::addMenu(new LLAdvancedPrintAgentInfo(), "Advanced.PrintAgentInfo");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugClicks(), "Advanced.ToggleDebugClicks");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugClicks(), "Advanced.CheckDebugClicks");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugViews(), "Advanced.CheckDebugViews");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugViews(), "Advanced.ToggleDebugViews");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugUnicode(), "Advanced.CheckDebugUnicode");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugUnicode(), "Advanced.ToggleDebugUnicode");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugCamera(), "Advanced.CheckDebugCamera");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugCamera(), "Advanced.ToggleDebugCamera");
+ view_listener_t::addMenu(new LLAdvancedToggleXUINameTooltips(), "Advanced.ToggleXUINameTooltips");
+ view_listener_t::addMenu(new LLAdvancedCheckXUINameTooltips(), "Advanced.CheckXUINameTooltips");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugMouseEvents(), "Advanced.ToggleDebugMouseEvents");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugMouseEvents(), "Advanced.CheckDebugMouseEvents");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugKeys(), "Advanced.ToggleDebugKeys");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugKeys(), "Advanced.CheckDebugKeys");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugWindowProc(), "Advanced.ToggleDebugWindowProc");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugWindowProc(), "Advanced.CheckDebugWindowProc");
+
+ // Advanced > XUI
+ commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance()));
+ view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames");
+ view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames");
+ view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs");
+ commit.add("Advanced.FlushNameCaches", boost::bind(&handle_flush_name_caches));
+
+ // Advanced > Character > Grab Baked Texture
+ view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture");
+ view_listener_t::addMenu(new LLAdvancedEnableGrabBakedTexture(), "Advanced.EnableGrabBakedTexture");
+
+ // Advanced > Character > Character Tests
+ view_listener_t::addMenu(new LLAdvancedAppearanceToXML(), "Advanced.AppearanceToXML");
+ view_listener_t::addMenu(new LLAdvancedEnableAppearanceToXML(), "Advanced.EnableAppearanceToXML");
+ view_listener_t::addMenu(new LLAdvancedToggleCharacterGeometry(), "Advanced.ToggleCharacterGeometry");
+
+ view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale");
+ view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale");
+
+ // Advanced > Character > Animation Speed
+ view_listener_t::addMenu(new LLAdvancedAnimTenFaster(), "Advanced.AnimTenFaster");
+ view_listener_t::addMenu(new LLAdvancedAnimTenSlower(), "Advanced.AnimTenSlower");
+ view_listener_t::addMenu(new LLAdvancedAnimResetAll(), "Advanced.AnimResetAll");
+
+ // Advanced > Character (toplevel)
+ view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault");
+ view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader");
+ view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo");
+ view_listener_t::addMenu(new LLAdvancedCheckAnimationInfo(), "Advanced.CheckAnimationInfo");
+ view_listener_t::addMenu(new LLAdvancedToggleShowLookAt(), "Advanced.ToggleShowLookAt");
+ view_listener_t::addMenu(new LLAdvancedCheckShowLookAt(), "Advanced.CheckShowLookAt");
+ view_listener_t::addMenu(new LLAdvancedToggleShowPointAt(), "Advanced.ToggleShowPointAt");
+ view_listener_t::addMenu(new LLAdvancedCheckShowPointAt(), "Advanced.CheckShowPointAt");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugJointUpdates(), "Advanced.ToggleDebugJointUpdates");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugJointUpdates(), "Advanced.CheckDebugJointUpdates");
+ view_listener_t::addMenu(new LLAdvancedToggleDisableLOD(), "Advanced.ToggleDisableLOD");
+ view_listener_t::addMenu(new LLAdvancedCheckDisableLOD(), "Advanced.CheckDisableLOD");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugCharacterVis(), "Advanced.ToggleDebugCharacterVis");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis");
+ view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments");
+ view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures");
+ view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures");
+ view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures");
+ // Advanced > Network
+ view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog");
+ view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog");
+ view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket");
// Advanced > Cache
view_listener_t::addMenu(new LLAdvancedPurgeDiskCache(), "Advanced.PurgeDiskCache");
- // Advanced > Recorder
- view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot");
- view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop");
- view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop");
- view_listener_t::addMenu(new LLAdvancedViewerEventRecorder(), "Advanced.EventRecorder");
+ // Advanced > Recorder
+ view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot");
+ view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop");
+ view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop");
+ view_listener_t::addMenu(new LLAdvancedViewerEventRecorder(), "Advanced.EventRecorder");
- // Advanced > Debugging
- view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint");
- view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror");
+ // Advanced > Debugging
+ view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint");
+ view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror");
view_listener_t::addMenu(new LLAdvancedForceErrorLlerrorMsg(), "Advanced.ForceErrorLlerrorMsg");
- view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess");
- view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro");
- view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop");
- view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException");
+ view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess");
+ view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro");
+ view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop");
+ view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException");
view_listener_t::addMenu(new LLAdvancedForceOSException(), "Advanced.ForceErrorOSException");
- view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro");
- view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash");
+ view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro");
+ view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash");
view_listener_t::addMenu(new LLAdvancedForceErrorCoroutineCrash(), "Advanced.ForceErrorCoroutineCrash");
view_listener_t::addMenu(new LLAdvancedForceErrorThreadCrash(), "Advanced.ForceErrorThreadCrash");
- view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer");
+ view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer");
- // Advanced (toplevel)
- view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates");
- view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates");
- view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage");
+ // Advanced (toplevel)
+ view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates");
+ view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates");
+ view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage");
view_listener_t::addMenu(new LLAdvancedCompressFileTest(), "Advanced.CompressFileTest");
- view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings");
- view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions");
- view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions");
- view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions");
- view_listener_t::addMenu(new LLAdvancedToggleVisualLeakDetector(), "Advanced.ToggleVisualLeakDetector");
-
- view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus");
- view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus");
-
- // Develop >Set logging level
- view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel");
- view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel");
-
- //Develop (clear cache immediately)
- commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) );
-
- // Develop (Fonts debugging)
- commit.add("Develop.Fonts.Dump", boost::bind(&LLFontGL::dumpFonts));
- commit.add("Develop.Fonts.DumpTextures", boost::bind(&LLFontGL::dumpFontTextures));
-
- // Admin >Object
- view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
- view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf");
- view_listener_t::addMenu(new LLAdminHandleObjectOwnerPermissive(), "Admin.HandleObjectOwnerPermissive");
- view_listener_t::addMenu(new LLAdminHandleForceDelete(), "Admin.HandleForceDelete");
- view_listener_t::addMenu(new LLAdminHandleObjectLock(), "Admin.HandleObjectLock");
- view_listener_t::addMenu(new LLAdminHandleObjectAssetIDs(), "Admin.HandleObjectAssetIDs");
-
- // Admin >Parcel
- view_listener_t::addMenu(new LLAdminHandleForceParcelOwnerToMe(), "Admin.HandleForceParcelOwnerToMe");
- view_listener_t::addMenu(new LLAdminHandleForceParcelToContent(), "Admin.HandleForceParcelToContent");
- view_listener_t::addMenu(new LLAdminHandleClaimPublicLand(), "Admin.HandleClaimPublicLand");
-
- // Admin >Region
- view_listener_t::addMenu(new LLAdminHandleRegionDumpTempAssetData(), "Admin.HandleRegionDumpTempAssetData");
- // Admin top level
- view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState");
-
- // Self context menu
- view_listener_t::addMenu(new LLSelfToggleSitStand(), "Self.ToggleSitStand");
- enable.add("Self.EnableSitStand", boost::bind(&enable_sit_stand));
- view_listener_t::addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments");
-
- view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments");
-
- // we don't use boost::bind directly to delay side tray construction
- view_listener_t::addMenu( new LLTogglePanelPeopleTab(), "SideTray.PanelPeopleTab");
- view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab");
-
- // Avatar pie menu
- view_listener_t::addMenu(new LLAvatarCheckImpostorMode(), "Avatar.CheckImpostorMode");
- view_listener_t::addMenu(new LLAvatarSetImpostorMode(), "Avatar.SetImpostorMode");
- view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");
- view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");
- view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact");
- commit.add("Avatar.Freeze", boost::bind(&handle_avatar_freeze, LLSD()));
- view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug");
- view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
- view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
- commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
- commit.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector));
- view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
- view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call");
- enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall));
- view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");
- view_listener_t::addMenu(new LLAvatarToggleMyProfile(), "Avatar.ToggleMyProfile");
- view_listener_t::addMenu(new LLAvatarTogglePicks(), "Avatar.TogglePicks");
- view_listener_t::addMenu(new LLAvatarToggleSearch(), "Avatar.ToggleSearch");
- view_listener_t::addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton");
- view_listener_t::addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton");
- view_listener_t::addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations");
- view_listener_t::addMenu(new LLAvatarResetSelfSkeletonAndAnimations(), "Avatar.ResetSelfSkeletonAndAnimations");
- enable.add("Avatar.IsMyProfileOpen", boost::bind(&my_profile_visible));
+ view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings");
+ view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions");
+ view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions");
+ view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions");
+ view_listener_t::addMenu(new LLAdvancedToggleVisualLeakDetector(), "Advanced.ToggleVisualLeakDetector");
+
+ view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus");
+ view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus");
+
+ // Develop >Set logging level
+ view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel");
+ view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel");
+
+ //Develop (clear cache immediately)
+ commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) );
+
+ // Develop (Fonts debugging)
+ commit.add("Develop.Fonts.Dump", boost::bind(&LLFontGL::dumpFonts));
+ commit.add("Develop.Fonts.DumpTextures", boost::bind(&LLFontGL::dumpFontTextures));
+
+ // Admin >Object
+ view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
+ view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf");
+ view_listener_t::addMenu(new LLAdminHandleObjectOwnerPermissive(), "Admin.HandleObjectOwnerPermissive");
+ view_listener_t::addMenu(new LLAdminHandleForceDelete(), "Admin.HandleForceDelete");
+ view_listener_t::addMenu(new LLAdminHandleObjectLock(), "Admin.HandleObjectLock");
+ view_listener_t::addMenu(new LLAdminHandleObjectAssetIDs(), "Admin.HandleObjectAssetIDs");
+
+ // Admin >Parcel
+ view_listener_t::addMenu(new LLAdminHandleForceParcelOwnerToMe(), "Admin.HandleForceParcelOwnerToMe");
+ view_listener_t::addMenu(new LLAdminHandleForceParcelToContent(), "Admin.HandleForceParcelToContent");
+ view_listener_t::addMenu(new LLAdminHandleClaimPublicLand(), "Admin.HandleClaimPublicLand");
+
+ // Admin >Region
+ view_listener_t::addMenu(new LLAdminHandleRegionDumpTempAssetData(), "Admin.HandleRegionDumpTempAssetData");
+ // Admin top level
+ view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState");
+
+ // Self context menu
+ view_listener_t::addMenu(new LLSelfToggleSitStand(), "Self.ToggleSitStand");
+ enable.add("Self.EnableSitStand", boost::bind(&enable_sit_stand));
+ view_listener_t::addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments");
+
+ view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments");
+
+ // we don't use boost::bind directly to delay side tray construction
+ view_listener_t::addMenu( new LLTogglePanelPeopleTab(), "SideTray.PanelPeopleTab");
+ view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab");
+
+ // Avatar pie menu
+ view_listener_t::addMenu(new LLAvatarCheckImpostorMode(), "Avatar.CheckImpostorMode");
+ view_listener_t::addMenu(new LLAvatarSetImpostorMode(), "Avatar.SetImpostorMode");
+ view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");
+ view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");
+ view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact");
+ commit.add("Avatar.Freeze", boost::bind(&handle_avatar_freeze, LLSD()));
+ view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug");
+ view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
+ view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
+ commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
+ commit.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector));
+ view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
+ view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call");
+ enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall));
+ view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");
+ view_listener_t::addMenu(new LLAvatarToggleMyProfile(), "Avatar.ToggleMyProfile");
+ view_listener_t::addMenu(new LLAvatarTogglePicks(), "Avatar.TogglePicks");
+ view_listener_t::addMenu(new LLAvatarToggleSearch(), "Avatar.ToggleSearch");
+ view_listener_t::addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton");
+ view_listener_t::addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton");
+ view_listener_t::addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations");
+ view_listener_t::addMenu(new LLAvatarResetSelfSkeletonAndAnimations(), "Avatar.ResetSelfSkeletonAndAnimations");
+ enable.add("Avatar.IsMyProfileOpen", boost::bind(&my_profile_visible));
enable.add("Avatar.IsPicksTabOpen", boost::bind(&picks_tab_visible));
- commit.add("Avatar.OpenMarketplace", boost::bind(&LLWeb::loadURLExternal, gSavedSettings.getString("MarketplaceURL")));
-
- view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend");
- enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2));
-
- // Object pie menu
- view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");
- commit.add("Object.Touch", boost::bind(&handle_object_touch));
- commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original));
- commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand));
- commit.add("Object.Delete", boost::bind(&handle_object_delete));
- view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar");
- view_listener_t::addMenu(new LLObjectAttachToAvatar(false), "Object.AttachAddToAvatar");
- view_listener_t::addMenu(new LLObjectReturn(), "Object.Return");
- commit.add("Object.Duplicate", boost::bind(&LLSelectMgr::duplicate, LLSelectMgr::getInstance()));
- view_listener_t::addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse");
- view_listener_t::addMenu(new LLObjectMute(), "Object.Mute");
-
- enable.add("Object.VisibleTake", boost::bind(&visible_take_object));
- enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object));
-
- commit.add("Object.Buy", boost::bind(&handle_buy));
- commit.add("Object.Edit", boost::bind(&handle_object_edit));
+ commit.add("Avatar.OpenMarketplace", boost::bind(&LLWeb::loadURLExternal, gSavedSettings.getString("MarketplaceURL")));
+
+ view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend");
+ enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2));
+
+ // Object pie menu
+ view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");
+ commit.add("Object.Touch", boost::bind(&handle_object_touch));
+ commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original));
+ commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand));
+ commit.add("Object.Delete", boost::bind(&handle_object_delete));
+ view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar");
+ view_listener_t::addMenu(new LLObjectAttachToAvatar(false), "Object.AttachAddToAvatar");
+ view_listener_t::addMenu(new LLObjectReturn(), "Object.Return");
+ commit.add("Object.Duplicate", boost::bind(&LLSelectMgr::duplicate, LLSelectMgr::getInstance()));
+ view_listener_t::addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse");
+ view_listener_t::addMenu(new LLObjectMute(), "Object.Mute");
+
+ enable.add("Object.VisibleTake", boost::bind(&visible_take_object));
+ enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object));
+
+ commit.add("Object.Buy", boost::bind(&handle_buy));
+ commit.add("Object.Edit", boost::bind(&handle_object_edit));
commit.add("Object.Edit", boost::bind(&handle_object_edit));
commit.add("Object.EditGLTFMaterial", boost::bind(&handle_object_edit_gltf_material));
- commit.add("Object.Inspect", boost::bind(&handle_object_inspect));
- commit.add("Object.Open", boost::bind(&handle_object_open));
- commit.add("Object.Take", boost::bind(&handle_take));
- commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector));
+ commit.add("Object.Inspect", boost::bind(&handle_object_inspect));
+ commit.add("Object.Open", boost::bind(&handle_object_open));
+ commit.add("Object.Take", boost::bind(&handle_take));
+ commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector));
enable.add("Object.EnableInspect", boost::bind(&enable_object_inspect));
enable.add("Object.EnableEditGLTFMaterial", boost::bind(&enable_object_edit_gltf_material));
- enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
- enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1));
- enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
- enable.add("Object.EnableWear", boost::bind(&object_is_wearable));
-
- enable.add("Object.EnableStandUp", boost::bind(&enable_object_stand_up));
- enable.add("Object.EnableSit", boost::bind(&enable_object_sit, _1));
-
- view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn");
- enable.add("Object.EnableDuplicate", boost::bind(&LLSelectMgr::canDuplicate, LLSelectMgr::getInstance()));
- view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse");
-
- enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute));
- enable.add("Object.EnableMute", boost::bind(&enable_object_mute));
- enable.add("Object.EnableUnmute", boost::bind(&enable_object_unmute));
- enable.add("Object.EnableBuy", boost::bind(&enable_buy_object));
- commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom"));
-
- // Attachment pie menu
- enable.add("Attachment.Label", boost::bind(&onEnableAttachmentLabel, _1, _2));
- view_listener_t::addMenu(new LLAttachmentDrop(), "Attachment.Drop");
- view_listener_t::addMenu(new LLAttachmentDetachFromPoint(), "Attachment.DetachFromPoint");
- view_listener_t::addMenu(new LLAttachmentDetach(), "Attachment.Detach");
- view_listener_t::addMenu(new LLAttachmentPointFilled(), "Attachment.PointFilled");
- view_listener_t::addMenu(new LLAttachmentEnableDrop(), "Attachment.EnableDrop");
- view_listener_t::addMenu(new LLAttachmentEnableDetach(), "Attachment.EnableDetach");
-
- // Land pie menu
- view_listener_t::addMenu(new LLLandBuild(), "Land.Build");
- view_listener_t::addMenu(new LLLandSit(), "Land.Sit");
+ enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
+ enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1));
+ enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
+ enable.add("Object.EnableWear", boost::bind(&object_is_wearable));
+
+ enable.add("Object.EnableStandUp", boost::bind(&enable_object_stand_up));
+ enable.add("Object.EnableSit", boost::bind(&enable_object_sit, _1));
+
+ view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn");
+ enable.add("Object.EnableDuplicate", boost::bind(&LLSelectMgr::canDuplicate, LLSelectMgr::getInstance()));
+ view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse");
+
+ enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute));
+ enable.add("Object.EnableMute", boost::bind(&enable_object_mute));
+ enable.add("Object.EnableUnmute", boost::bind(&enable_object_unmute));
+ enable.add("Object.EnableBuy", boost::bind(&enable_buy_object));
+ commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom"));
+
+ // Attachment pie menu
+ enable.add("Attachment.Label", boost::bind(&onEnableAttachmentLabel, _1, _2));
+ view_listener_t::addMenu(new LLAttachmentDrop(), "Attachment.Drop");
+ view_listener_t::addMenu(new LLAttachmentDetachFromPoint(), "Attachment.DetachFromPoint");
+ view_listener_t::addMenu(new LLAttachmentDetach(), "Attachment.Detach");
+ view_listener_t::addMenu(new LLAttachmentPointFilled(), "Attachment.PointFilled");
+ view_listener_t::addMenu(new LLAttachmentEnableDrop(), "Attachment.EnableDrop");
+ view_listener_t::addMenu(new LLAttachmentEnableDetach(), "Attachment.EnableDetach");
+
+ // Land pie menu
+ view_listener_t::addMenu(new LLLandBuild(), "Land.Build");
+ view_listener_t::addMenu(new LLLandSit(), "Land.Sit");
view_listener_t::addMenu(new LLLandCanSit(), "Land.CanSit");
- view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass");
- view_listener_t::addMenu(new LLLandEdit(), "Land.Edit");
-
- // Particle muting
- view_listener_t::addMenu(new LLMuteParticle(), "Particle.Mute");
-
- view_listener_t::addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass");
- commit.add("Land.Buy", boost::bind(&handle_buy_land));
-
- // Generic actions
- commit.add("ReportAbuse", boost::bind(&handle_report_abuse));
- commit.add("BuyCurrency", boost::bind(&handle_buy_currency));
- view_listener_t::addMenu(new LLShowHelp(), "ShowHelp");
- view_listener_t::addMenu(new LLToggleHelp(), "ToggleHelp");
- view_listener_t::addMenu(new LLToggleSpeak(), "ToggleSpeak");
- view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL");
- view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile");
+ view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass");
+ view_listener_t::addMenu(new LLLandEdit(), "Land.Edit");
+
+ // Particle muting
+ view_listener_t::addMenu(new LLMuteParticle(), "Particle.Mute");
+
+ view_listener_t::addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass");
+ commit.add("Land.Buy", boost::bind(&handle_buy_land));
+
+ // Generic actions
+ commit.add("ReportAbuse", boost::bind(&handle_report_abuse));
+ commit.add("BuyCurrency", boost::bind(&handle_buy_currency));
+ view_listener_t::addMenu(new LLShowHelp(), "ShowHelp");
+ view_listener_t::addMenu(new LLToggleHelp(), "ToggleHelp");
+ view_listener_t::addMenu(new LLToggleSpeak(), "ToggleSpeak");
+ view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL");
+ view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile");
view_listener_t::addMenu(new LLShowAgentProfilePicks(), "ShowAgentProfilePicks");
- view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile");
- view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");
+ view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile");
+ view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");
view_listener_t::addMenu(new LLToggleShaderControl(), "ToggleShaderControl");
- view_listener_t::addMenu(new LLCheckControl(), "CheckControl");
- view_listener_t::addMenu(new LLGoToObject(), "GoToObject");
- commit.add("PayObject", boost::bind(&handle_give_money_dialog));
-
- commit.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow));
-
- enable.add("EnablePayObject", boost::bind(&enable_pay_object));
- enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar));
- enable.add("EnableEdit", boost::bind(&enable_object_edit));
- enable.add("EnableMuteParticle", boost::bind(&enable_mute_particle));
- enable.add("VisibleBuild", boost::bind(&enable_object_build));
- commit.add("Pathfinding.Linksets.Select", boost::bind(&LLFloaterPathfindingLinksets::openLinksetsWithSelectedObjects));
- enable.add("EnableSelectInPathfindingLinksets", boost::bind(&enable_object_select_in_pathfinding_linksets));
- enable.add("VisibleSelectInPathfindingLinksets", boost::bind(&visible_object_select_in_pathfinding_linksets));
- commit.add("Pathfinding.Characters.Select", boost::bind(&LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects));
- enable.add("EnableSelectInPathfindingCharacters", boost::bind(&enable_object_select_in_pathfinding_characters));
+ view_listener_t::addMenu(new LLCheckControl(), "CheckControl");
+ view_listener_t::addMenu(new LLGoToObject(), "GoToObject");
+ commit.add("PayObject", boost::bind(&handle_give_money_dialog));
+
+ commit.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow));
+
+ enable.add("EnablePayObject", boost::bind(&enable_pay_object));
+ enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar));
+ enable.add("EnableEdit", boost::bind(&enable_object_edit));
+ enable.add("EnableMuteParticle", boost::bind(&enable_mute_particle));
+ enable.add("VisibleBuild", boost::bind(&enable_object_build));
+ commit.add("Pathfinding.Linksets.Select", boost::bind(&LLFloaterPathfindingLinksets::openLinksetsWithSelectedObjects));
+ enable.add("EnableSelectInPathfindingLinksets", boost::bind(&enable_object_select_in_pathfinding_linksets));
+ enable.add("VisibleSelectInPathfindingLinksets", boost::bind(&visible_object_select_in_pathfinding_linksets));
+ commit.add("Pathfinding.Characters.Select", boost::bind(&LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects));
+ enable.add("EnableSelectInPathfindingCharacters", boost::bind(&enable_object_select_in_pathfinding_characters));
enable.add("Advanced.EnableErrorOSException", boost::bind(&enable_os_exception));
- view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible");
- view_listener_t::addMenu(new LLShowSidetrayPanel(), "ShowSidetrayPanel");
- view_listener_t::addMenu(new LLSidetrayPanelVisible(), "SidetrayPanelVisible");
- view_listener_t::addMenu(new LLSomethingSelected(), "SomethingSelected");
- view_listener_t::addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD");
- view_listener_t::addMenu(new LLEditableSelected(), "EditableSelected");
- view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono");
- view_listener_t::addMenu(new LLToggleUIHints(), "ToggleUIHints");
+ view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible");
+ view_listener_t::addMenu(new LLShowSidetrayPanel(), "ShowSidetrayPanel");
+ view_listener_t::addMenu(new LLSidetrayPanelVisible(), "SidetrayPanelVisible");
+ view_listener_t::addMenu(new LLSomethingSelected(), "SomethingSelected");
+ view_listener_t::addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD");
+ view_listener_t::addMenu(new LLEditableSelected(), "EditableSelected");
+ view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono");
+ view_listener_t::addMenu(new LLToggleUIHints(), "ToggleUIHints");
}
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index 6683c5f2e6..b43de3fe3f 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llviewermenu.h
* @brief Builds menus out of objects
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -143,6 +143,7 @@ void handle_give_money_dialog();
bool enable_pay_object();
bool enable_buy_object();
bool handle_go_to();
+bool handle_env_setting_event(std::string event_name);
// Export to XML or Collada
void handle_export_selected( void * );
@@ -155,38 +156,38 @@ U64 info_display_from_string(std::string info_display);
class LLViewerMenuHolderGL : public LLMenuHolderGL
{
public:
- struct Params : public LLInitParam::Block<Params, LLMenuHolderGL::Params>
- {};
-
- LLViewerMenuHolderGL(const Params& p);
+ struct Params : public LLInitParam::Block<Params, LLMenuHolderGL::Params>
+ {};
- virtual BOOL hideMenus();
+ LLViewerMenuHolderGL(const Params& p);
- void setParcelSelection(LLSafeHandle<LLParcelSelection> selection);
- void setObjectSelection(LLSafeHandle<LLObjectSelection> selection);
+ virtual BOOL hideMenus();
+
+ void setParcelSelection(LLSafeHandle<LLParcelSelection> selection);
+ void setObjectSelection(LLSafeHandle<LLObjectSelection> selection);
- virtual const LLRect getMenuRect() const;
+ virtual const LLRect getMenuRect() const;
protected:
- LLSafeHandle<LLParcelSelection> mParcelSelection;
- LLSafeHandle<LLObjectSelection> mObjectSelection;
+ LLSafeHandle<LLParcelSelection> mParcelSelection;
+ LLSafeHandle<LLObjectSelection> mObjectSelection;
};
-extern LLMenuBarGL* gMenuBarView;
-//extern LLView* gMenuBarHolder;
-extern LLMenuGL* gEditMenu;
-extern LLMenuGL* gPopupMenuView;
-extern LLViewerMenuHolderGL* gMenuHolder;
-extern LLMenuBarGL* gLoginMenuBarView;
+extern LLMenuBarGL* gMenuBarView;
+//extern LLView* gMenuBarHolder;
+extern LLMenuGL* gEditMenu;
+extern LLMenuGL* gPopupMenuView;
+extern LLViewerMenuHolderGL* gMenuHolder;
+extern LLMenuBarGL* gLoginMenuBarView;
// Context menus in 3D scene
-extern LLContextMenu *gMenuAvatarSelf;
-extern LLContextMenu *gMenuAvatarOther;
-extern LLContextMenu *gMenuObject;
-extern LLContextMenu *gMenuAttachmentSelf;
-extern LLContextMenu *gMenuAttachmentOther;
-extern LLContextMenu *gMenuLand;
-extern LLContextMenu *gMenuMuteParticle;
+extern LLContextMenu *gMenuAvatarSelf;
+extern LLContextMenu *gMenuAvatarOther;
+extern LLContextMenu *gMenuObject;
+extern LLContextMenu *gMenuAttachmentSelf;
+extern LLContextMenu *gMenuAttachmentOther;
+extern LLContextMenu *gMenuLand;
+extern LLContextMenu *gMenuMuteParticle;
// Needed to build menus when attachment site list available
extern LLMenuGL* gAttachSubMenu;
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index b746d167ba..a1dc7119ce 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llviewermenufile.cpp
* @brief "File" menu in the main menu bar.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -47,17 +47,17 @@
#include "llimagej2c.h"
#include "llimagejpeg.h"
#include "llimagetga.h"
-#include "llinventorymodel.h" // gInventory
+#include "llinventorymodel.h" // gInventory
#include "llpluginclassmedia.h"
#include "llresourcedata.h"
#include "llstatusbar.h"
#include "lltinygltfhelper.h"
#include "lltoast.h"
-#include "llviewercontrol.h" // gSavedSettings
+#include "llviewercontrol.h" // gSavedSettings
#include "llviewertexturelist.h"
#include "lluictrlfactory.h"
#include "llviewerinventory.h"
-#include "llviewermenu.h" // gMenuHolder
+#include "llviewermenu.h" // gMenuHolder
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
@@ -83,24 +83,24 @@
class LLFileEnableUpload : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
+ bool handleEvent(const LLSD& userdata)
+ {
return true;
- }
+ }
};
class LLFileEnableUploadModel : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::findInstance("upload_model");
- if (fmp && fmp->isModelLoading())
- {
- return false;
- }
-
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::findInstance("upload_model");
+ if (fmp && fmp->isModelLoading())
+ {
+ return false;
+ }
+
+ return true;
+ }
};
class LLFileEnableUploadMaterial : public view_listener_t
@@ -118,18 +118,18 @@ class LLFileEnableUploadMaterial : public view_listener_t
class LLMeshEnabled : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return gSavedSettings.getBOOL("MeshEnabled");
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return gSavedSettings.getBOOL("MeshEnabled");
+ }
};
class LLMeshUploadVisible : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- return gMeshRepo.meshUploadEnabled();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ return gMeshRepo.meshUploadEnabled();
+ }
};
LLMutex* LLFilePickerThread::sMutex = NULL;
@@ -139,51 +139,51 @@ void LLFilePickerThread::getFile()
{
#if LL_WINDOWS
// Todo: get rid of LLFilePickerThread and make this modeless
- start();
+ start();
#elif LL_DARWIN
runModeless();
#else
- run();
+ run();
#endif
}
-//virtual
+//virtual
void LLFilePickerThread::run()
{
#if LL_WINDOWS
- bool blocking = false;
+ bool blocking = false;
#else
- bool blocking = true; // modal
+ bool blocking = true; // modal
#endif
- LLFilePicker picker;
-
- if (mIsSaveDialog)
- {
- if (picker.getSaveFile(mSaveFilter, mProposedName, blocking))
- {
- mResponses.push_back(picker.getFirstFile());
- }
- }
- else
- {
- bool result = mIsGetMultiple ? picker.getMultipleOpenFiles(mLoadFilter, blocking) : picker.getOpenFile(mLoadFilter, blocking);
- if (result)
- {
- std::string filename = picker.getFirstFile(); // consider copying mFiles directly
- do
- {
- mResponses.push_back(filename);
- filename = picker.getNextFile();
- }
- while (mIsGetMultiple && !filename.empty());
- }
- }
-
- {
- LLMutexLock lock(sMutex);
- sDeadQ.push(this);
- }
+ LLFilePicker picker;
+
+ if (mIsSaveDialog)
+ {
+ if (picker.getSaveFile(mSaveFilter, mProposedName, blocking))
+ {
+ mResponses.push_back(picker.getFirstFile());
+ }
+ }
+ else
+ {
+ bool result = mIsGetMultiple ? picker.getMultipleOpenFiles(mLoadFilter, blocking) : picker.getOpenFile(mLoadFilter, blocking);
+ if (result)
+ {
+ std::string filename = picker.getFirstFile(); // consider copying mFiles directly
+ do
+ {
+ mResponses.push_back(filename);
+ filename = picker.getNextFile();
+ }
+ while (mIsGetMultiple && !filename.empty());
+ }
+ }
+
+ {
+ LLMutexLock lock(sMutex);
+ sDeadQ.push(this);
+ }
}
void LLFilePickerThread::runModeless()
@@ -206,7 +206,7 @@ void LLFilePickerThread::runModeless()
{
result = picker.getOpenFileModeless(mLoadFilter, modelessVectorCallback, this);
}
-
+
if (!result)
{
LLMutexLock lock(sMutex);
@@ -223,7 +223,7 @@ void LLFilePickerThread::modelessStringCallback(bool success,
{
picker->mResponses.push_back(response);
}
-
+
{
LLMutexLock lock(sMutex);
sDeadQ.push(picker);
@@ -255,7 +255,7 @@ void LLFilePickerThread::modelessVectorCallback(bool success,
}
}
}
-
+
{
LLMutexLock lock(sMutex);
sDeadQ.push(picker);
@@ -265,66 +265,66 @@ void LLFilePickerThread::modelessVectorCallback(bool success,
//static
void LLFilePickerThread::initClass()
{
- sMutex = new LLMutex();
+ sMutex = new LLMutex();
}
//static
void LLFilePickerThread::cleanupClass()
{
- clearDead();
-
- delete sMutex;
- sMutex = NULL;
+ clearDead();
+
+ delete sMutex;
+ sMutex = NULL;
}
//static
void LLFilePickerThread::clearDead()
{
- if (!sDeadQ.empty())
- {
- LLMutexLock lock(sMutex);
- while (!sDeadQ.empty())
- {
- LLFilePickerThread* thread = sDeadQ.front();
- thread->notify(thread->mResponses);
- delete thread;
- sDeadQ.pop();
- }
- }
+ if (!sDeadQ.empty())
+ {
+ LLMutexLock lock(sMutex);
+ while (!sDeadQ.empty())
+ {
+ LLFilePickerThread* thread = sDeadQ.front();
+ thread->notify(thread->mResponses);
+ delete thread;
+ sDeadQ.pop();
+ }
+ }
}
LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb)
- : LLFilePickerThread(filter, get_multiple),
- mLoadFilter(filter),
- mSaveFilter(LLFilePicker::FFSAVE_ALL),
- mFilePickedSignal(NULL),
- mFailureSignal(NULL)
+ : LLFilePickerThread(filter, get_multiple),
+ mLoadFilter(filter),
+ mSaveFilter(LLFilePicker::FFSAVE_ALL),
+ mFilePickedSignal(NULL),
+ mFailureSignal(NULL)
{
- mFilePickedSignal = new file_picked_signal_t();
- mFilePickedSignal->connect(cb);
+ mFilePickedSignal = new file_picked_signal_t();
+ mFilePickedSignal->connect(cb);
- mFailureSignal = new file_picked_signal_t();
- mFailureSignal->connect(failure_cb);
+ mFailureSignal = new file_picked_signal_t();
+ mFailureSignal->connect(failure_cb);
}
LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb)
- : LLFilePickerThread(filter, proposed_name),
- mLoadFilter(LLFilePicker::FFLOAD_ALL),
- mSaveFilter(filter),
- mFilePickedSignal(NULL),
- mFailureSignal(NULL)
+ : LLFilePickerThread(filter, proposed_name),
+ mLoadFilter(LLFilePicker::FFLOAD_ALL),
+ mSaveFilter(filter),
+ mFilePickedSignal(NULL),
+ mFailureSignal(NULL)
{
- mFilePickedSignal = new file_picked_signal_t();
- mFilePickedSignal->connect(cb);
+ mFilePickedSignal = new file_picked_signal_t();
+ mFilePickedSignal->connect(cb);
- mFailureSignal = new file_picked_signal_t();
- mFailureSignal->connect(failure_cb);
+ mFailureSignal = new file_picked_signal_t();
+ mFailureSignal->connect(failure_cb);
}
LLFilePickerReplyThread::~LLFilePickerReplyThread()
{
- delete mFilePickedSignal;
- delete mFailureSignal;
+ delete mFilePickedSignal;
+ delete mFailureSignal;
}
void LLFilePickerReplyThread::startPicker(const file_picked_signal_t::slot_type & cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type & failure_cb)
@@ -339,20 +339,20 @@ void LLFilePickerReplyThread::startPicker(const file_picked_signal_t::slot_type
void LLFilePickerReplyThread::notify(const std::vector<std::string>& filenames)
{
- if (filenames.empty())
- {
- if (mFailureSignal)
- {
- (*mFailureSignal)(filenames, mLoadFilter, mSaveFilter);
- }
- }
- else
- {
- if (mFilePickedSignal)
- {
- (*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter);
- }
- }
+ if (filenames.empty())
+ {
+ if (mFailureSignal)
+ {
+ (*mFailureSignal)(filenames, mLoadFilter, mSaveFilter);
+ }
+ }
+ else
+ {
+ if (mFilePickedSignal)
+ {
+ (*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter);
+ }
+ }
}
@@ -389,167 +389,167 @@ static std::string MATERIAL_EXTENSIONS = "gltf glb";
std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
{
- switch(filter)
- {
+ switch(filter)
+ {
#if LL_WINDOWS
- case LLFilePicker::FFLOAD_IMAGE:
- return IMAGE_EXTENSIONS;
- case LLFilePicker::FFLOAD_WAV:
- return SOUND_EXTENSIONS;
- case LLFilePicker::FFLOAD_ANIM:
- return ANIM_EXTENSIONS;
- case LLFilePicker::FFLOAD_SLOBJECT:
- return SLOBJECT_EXTENSIONS;
- case LLFilePicker::FFLOAD_MODEL:
- return MODEL_EXTENSIONS;
+ case LLFilePicker::FFLOAD_IMAGE:
+ return IMAGE_EXTENSIONS;
+ case LLFilePicker::FFLOAD_WAV:
+ return SOUND_EXTENSIONS;
+ case LLFilePicker::FFLOAD_ANIM:
+ return ANIM_EXTENSIONS;
+ case LLFilePicker::FFLOAD_SLOBJECT:
+ return SLOBJECT_EXTENSIONS;
+ case LLFilePicker::FFLOAD_MODEL:
+ return MODEL_EXTENSIONS;
case LLFilePicker::FFLOAD_MATERIAL:
return MATERIAL_EXTENSIONS;
- case LLFilePicker::FFLOAD_XML:
- return XML_EXTENSIONS;
+ case LLFilePicker::FFLOAD_XML:
+ return XML_EXTENSIONS;
case LLFilePicker::FFLOAD_ALL:
case LLFilePicker::FFLOAD_EXE:
- return ALL_FILE_EXTENSIONS;
+ return ALL_FILE_EXTENSIONS;
#endif
default:
- return ALL_FILE_EXTENSIONS;
- }
+ return ALL_FILE_EXTENSIONS;
+ }
}
const bool check_file_extension(const std::string& filename, LLFilePicker::ELoadFilter type)
{
- std::string ext = gDirUtilp->getExtension(filename);
-
- //strincmp doesn't like NULL pointers
- if (ext.empty())
- {
- std::string short_name = gDirUtilp->getBaseFileName(filename);
-
- // No extension
- LLSD args;
- args["FILE"] = short_name;
- LLNotificationsUtil::add("NoFileExtension", args);
- return false;
- }
- else
- {
- //so there is an extension
- //loop over the valid extensions and compare to see
- //if the extension is valid
-
- //now grab the set of valid file extensions
- std::string valid_extensions = build_extensions_string(type);
-
- BOOL ext_valid = FALSE;
-
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep(" ");
- tokenizer tokens(valid_extensions, sep);
- tokenizer::iterator token_iter;
-
- //now loop over all valid file extensions
- //and compare them to the extension of the file
- //to be uploaded
- for (token_iter = tokens.begin();
- token_iter != tokens.end() && ext_valid != TRUE;
- ++token_iter)
- {
- const std::string& cur_token = *token_iter;
-
- if (cur_token == ext || cur_token == "*.*")
- {
- //valid extension
- //or the acceptable extension is any
- ext_valid = TRUE;
- }
- }//end for (loop over all tokens)
-
- if (ext_valid == FALSE)
- {
- //should only get here if the extension exists
- //but is invalid
- LLSD args;
- args["EXTENSION"] = ext;
- args["VALIDS"] = valid_extensions;
- LLNotificationsUtil::add("InvalidFileExtension", args);
- return false;
- }
- }//end else (non-null extension)
- return true;
+ std::string ext = gDirUtilp->getExtension(filename);
+
+ //strincmp doesn't like NULL pointers
+ if (ext.empty())
+ {
+ std::string short_name = gDirUtilp->getBaseFileName(filename);
+
+ // No extension
+ LLSD args;
+ args["FILE"] = short_name;
+ LLNotificationsUtil::add("NoFileExtension", args);
+ return false;
+ }
+ else
+ {
+ //so there is an extension
+ //loop over the valid extensions and compare to see
+ //if the extension is valid
+
+ //now grab the set of valid file extensions
+ std::string valid_extensions = build_extensions_string(type);
+
+ BOOL ext_valid = FALSE;
+
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(" ");
+ tokenizer tokens(valid_extensions, sep);
+ tokenizer::iterator token_iter;
+
+ //now loop over all valid file extensions
+ //and compare them to the extension of the file
+ //to be uploaded
+ for (token_iter = tokens.begin();
+ token_iter != tokens.end() && ext_valid != TRUE;
+ ++token_iter)
+ {
+ const std::string& cur_token = *token_iter;
+
+ if (cur_token == ext || cur_token == "*.*")
+ {
+ //valid extension
+ //or the acceptable extension is any
+ ext_valid = TRUE;
+ }
+ }//end for (loop over all tokens)
+
+ if (ext_valid == FALSE)
+ {
+ //should only get here if the extension exists
+ //but is invalid
+ LLSD args;
+ args["EXTENSION"] = ext;
+ args["VALIDS"] = valid_extensions;
+ LLNotificationsUtil::add("InvalidFileExtension", args);
+ return false;
+ }
+ }//end else (non-null extension)
+ return true;
}
const void upload_single_file(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter type)
{
- std::string filename = filenames[0];
- if (!check_file_extension(filename, type)) return;
-
- if (!filename.empty())
- {
- if (type == LLFilePicker::FFLOAD_WAV)
- {
- // pre-qualify wavs to make sure the format is acceptable
- std::string error_msg;
- if (check_for_invalid_wav_formats(filename, error_msg))
- {
- LL_INFOS() << error_msg << ": " << filename << LL_ENDL;
- LLSD args;
- args["FILE"] = filename;
- LLNotificationsUtil::add(error_msg, args);
- return;
- }
- else
- {
- LLFloaterReg::showInstance("upload_sound", LLSD(filename));
- }
- }
- if (type == LLFilePicker::FFLOAD_IMAGE)
- {
- LLFloaterReg::showInstance("upload_image", LLSD(filename));
- }
- if (type == LLFilePicker::FFLOAD_ANIM)
- {
- std::string filename_lc(filename);
- LLStringUtil::toLower(filename_lc);
- if (filename_lc.rfind(".anim") != std::string::npos)
- {
- LLFloaterReg::showInstance("upload_anim_anim", LLSD(filename));
- }
- else
- {
- LLFloaterReg::showInstance("upload_anim_bvh", LLSD(filename));
- }
- }
- }
- return;
+ std::string filename = filenames[0];
+ if (!check_file_extension(filename, type)) return;
+
+ if (!filename.empty())
+ {
+ if (type == LLFilePicker::FFLOAD_WAV)
+ {
+ // pre-qualify wavs to make sure the format is acceptable
+ std::string error_msg;
+ if (check_for_invalid_wav_formats(filename, error_msg))
+ {
+ LL_INFOS() << error_msg << ": " << filename << LL_ENDL;
+ LLSD args;
+ args["FILE"] = filename;
+ LLNotificationsUtil::add(error_msg, args);
+ return;
+ }
+ else
+ {
+ LLFloaterReg::showInstance("upload_sound", LLSD(filename));
+ }
+ }
+ if (type == LLFilePicker::FFLOAD_IMAGE)
+ {
+ LLFloaterReg::showInstance("upload_image", LLSD(filename));
+ }
+ if (type == LLFilePicker::FFLOAD_ANIM)
+ {
+ std::string filename_lc(filename);
+ LLStringUtil::toLower(filename_lc);
+ if (filename_lc.rfind(".anim") != std::string::npos)
+ {
+ LLFloaterReg::showInstance("upload_anim_anim", LLSD(filename));
+ }
+ else
+ {
+ LLFloaterReg::showInstance("upload_anim_bvh", LLSD(filename));
+ }
+ }
+ }
+ return;
}
void do_bulk_upload(std::vector<std::string> filenames, const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option != 0)
- {
- // Cancel upload
- return;
- }
-
- for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
- {
- std::string filename = (*in_iter);
-
- std::string name = gDirUtilp->getBaseFileName(filename, true);
- std::string asset_name = name;
- LLStringUtil::replaceNonstandardASCII(asset_name, '?');
- LLStringUtil::replaceChar(asset_name, '|', '?');
- LLStringUtil::stripNonprintable(asset_name);
- LLStringUtil::trim(asset_name);
-
- std::string ext = gDirUtilp->getExtension(filename);
- LLAssetType::EType asset_type;
- U32 codec;
- S32 expected_upload_cost;
- if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) &&
- LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost))
- {
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0)
+ {
+ // Cancel upload
+ return;
+ }
+
+ for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
+ {
+ std::string filename = (*in_iter);
+
+ std::string name = gDirUtilp->getBaseFileName(filename, true);
+ std::string asset_name = name;
+ LLStringUtil::replaceNonstandardASCII(asset_name, '?');
+ LLStringUtil::replaceChar(asset_name, '|', '?');
+ LLStringUtil::stripNonprintable(asset_name);
+ LLStringUtil::trim(asset_name);
+
+ std::string ext = gDirUtilp->getExtension(filename);
+ LLAssetType::EType asset_type;
+ U32 codec;
+ S32 expected_upload_cost;
+ if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) &&
+ LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost))
+ {
LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
filename,
asset_name,
@@ -585,34 +585,34 @@ void do_bulk_upload(std::vector<std::string> filenames, const LLSD& notification
bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S32& total_cost, S32& file_count, S32& bvh_count)
{
- total_cost = 0;
- file_count = 0;
- bvh_count = 0;
- for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
- {
- std::string filename = (*in_iter);
- std::string ext = gDirUtilp->getExtension(filename);
-
- if (ext == "bvh")
- {
- bvh_count++;
- }
-
- LLAssetType::EType asset_type;
- U32 codec;
- S32 cost;
-
- if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) &&
- LLAgentBenefitsMgr::current().findUploadCost(asset_type, cost))
- {
- total_cost += cost;
- file_count++;
- }
+ total_cost = 0;
+ file_count = 0;
+ bvh_count = 0;
+ for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
+ {
+ std::string filename = (*in_iter);
+ std::string ext = gDirUtilp->getExtension(filename);
+
+ if (ext == "bvh")
+ {
+ bvh_count++;
+ }
+
+ LLAssetType::EType asset_type;
+ U32 codec;
+ S32 cost;
+
+ if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) &&
+ LLAgentBenefitsMgr::current().findUploadCost(asset_type, cost))
+ {
+ total_cost += cost;
+ file_count++;
+ }
if (ext == "gltf" || ext == "glb")
{
S32 texture_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
-
+
tinygltf::Model model;
if (LLTinyGLTFHelper::loadModel(filename, model))
@@ -652,87 +652,87 @@ bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S3
}
}
}
- }
-
+ }
+
return file_count > 0;
}
const void upload_bulk(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter type)
{
- // TODO:
- // Check user balance for entire cost
- // Charge user entire cost
- // Loop, uploading
- // If an upload fails, refund the user for that one
- //
- // Also fix single upload to charge first, then refund
-
- // FIXME PREMIUM what about known types that can't be bulk uploaded
- // (bvh)? These will fail in the item by item upload but won't be
- // mentioned in the notification.
- std::vector<std::string> filtered_filenames;
- for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
- {
- const std::string& filename = *in_iter;
- if (check_file_extension(filename, type))
- {
- filtered_filenames.push_back(filename);
- }
- }
-
- S32 expected_upload_cost;
- S32 expected_upload_count;
- S32 bvh_count;
- if (get_bulk_upload_expected_cost(filtered_filenames, expected_upload_cost, expected_upload_count, bvh_count))
- {
- LLSD args;
- args["COST"] = expected_upload_cost;
- args["COUNT"] = expected_upload_count;
- LLNotificationsUtil::add("BulkUploadCostConfirmation", args, LLSD(), boost::bind(do_bulk_upload, filtered_filenames, _1, _2));
-
- if (filtered_filenames.size() > expected_upload_count)
- {
- if (bvh_count == filtered_filenames.size() - expected_upload_count)
- {
- LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload");
- }
- else
- {
- LLNotificationsUtil::add("BulkUploadIncompatibleFiles");
- }
- }
- }
- else if (bvh_count == filtered_filenames.size())
- {
- LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload");
- }
- else
- {
- LLNotificationsUtil::add("BulkUploadNoCompatibleFiles");
- }
+ // TODO:
+ // Check user balance for entire cost
+ // Charge user entire cost
+ // Loop, uploading
+ // If an upload fails, refund the user for that one
+ //
+ // Also fix single upload to charge first, then refund
+
+ // FIXME PREMIUM what about known types that can't be bulk uploaded
+ // (bvh)? These will fail in the item by item upload but won't be
+ // mentioned in the notification.
+ std::vector<std::string> filtered_filenames;
+ for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
+ {
+ const std::string& filename = *in_iter;
+ if (check_file_extension(filename, type))
+ {
+ filtered_filenames.push_back(filename);
+ }
+ }
+
+ S32 expected_upload_cost;
+ S32 expected_upload_count;
+ S32 bvh_count;
+ if (get_bulk_upload_expected_cost(filtered_filenames, expected_upload_cost, expected_upload_count, bvh_count))
+ {
+ LLSD args;
+ args["COST"] = expected_upload_cost;
+ args["COUNT"] = expected_upload_count;
+ LLNotificationsUtil::add("BulkUploadCostConfirmation", args, LLSD(), boost::bind(do_bulk_upload, filtered_filenames, _1, _2));
+
+ if (filtered_filenames.size() > expected_upload_count)
+ {
+ if (bvh_count == filtered_filenames.size() - expected_upload_count)
+ {
+ LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload");
+ }
+ else
+ {
+ LLNotificationsUtil::add("BulkUploadIncompatibleFiles");
+ }
+ }
+ }
+ else if (bvh_count == filtered_filenames.size())
+ {
+ LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload");
+ }
+ else
+ {
+ LLNotificationsUtil::add("BulkUploadNoCompatibleFiles");
+ }
}
class LLFileUploadImage : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (gAgentCamera.cameraMouselook())
- {
- gAgentCamera.changeCameraToDefault();
- }
- LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_IMAGE, false);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgentCamera.cameraMouselook())
+ {
+ gAgentCamera.changeCameraToDefault();
+ }
+ LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_IMAGE, false);
+ return true;
+ }
};
class LLFileUploadModel : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
+ bool handleEvent(const LLSD& userdata)
+ {
LLFloaterModelPreview::showModelPreview();
return TRUE;
- }
+ }
};
class LLFileUploadMaterial : public view_listener_t
@@ -746,213 +746,219 @@ class LLFileUploadMaterial : public view_listener_t
class LLFileUploadSound : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (gAgentCamera.cameraMouselook())
- {
- gAgentCamera.changeCameraToDefault();
- }
- LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_WAV, false);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgentCamera.cameraMouselook())
+ {
+ gAgentCamera.changeCameraToDefault();
+ }
+ LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_WAV, false);
+ return true;
+ }
};
class LLFileUploadAnim : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (gAgentCamera.cameraMouselook())
- {
- gAgentCamera.changeCameraToDefault();
- }
- LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_ANIM, false);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgentCamera.cameraMouselook())
+ {
+ gAgentCamera.changeCameraToDefault();
+ }
+ LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_ANIM, false);
+ return true;
+ }
};
class LLFileUploadBulk : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- if (gAgentCamera.cameraMouselook())
- {
- gAgentCamera.changeCameraToDefault();
- }
- LLFilePickerReplyThread::startPicker(boost::bind(&upload_bulk, _1, _2), LLFilePicker::FFLOAD_ALL, true);
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ if (gAgentCamera.cameraMouselook())
+ {
+ gAgentCamera.changeCameraToDefault();
+ }
+ LLFilePickerReplyThread::startPicker(boost::bind(&upload_bulk, _1, _2), LLFilePicker::FFLOAD_ALL, true);
+ return true;
+ }
};
-void upload_error(const std::string& error_message, const std::string& label, const std::string& filename, const LLSD& args)
+void upload_error(const std::string& error_message, const std::string& label, const std::string& filename, const LLSD& args)
{
- LL_WARNS() << error_message << LL_ENDL;
- LLNotificationsUtil::add(label, args);
- if(LLFile::remove(filename) == -1)
- {
- LL_DEBUGS() << "unable to remove temp file" << LL_ENDL;
- }
- LLFilePicker::instance().reset();
+ LL_WARNS() << error_message << LL_ENDL;
+ LLNotificationsUtil::add(label, args);
+ if(LLFile::remove(filename) == -1)
+ {
+ LL_DEBUGS() << "unable to remove temp file" << LL_ENDL;
+ }
+ LLFilePicker::instance().reset();
}
class LLFileEnableCloseWindow : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool frontmost_fl_exists = (NULL != gFloaterView->getFrontmostClosableFloater());
- bool frontmost_snapshot_fl_exists = (NULL != gSnapshotFloaterView->getFrontmostClosableFloater());
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool frontmost_fl_exists = (NULL != gFloaterView->getFrontmostClosableFloater());
+ bool frontmost_snapshot_fl_exists = (NULL != gSnapshotFloaterView->getFrontmostClosableFloater());
- return !LLNotificationsUI::LLToast::isAlertToastShown() && (frontmost_fl_exists || frontmost_snapshot_fl_exists);
- }
+ return !LLNotificationsUI::LLToast::isAlertToastShown() && (frontmost_fl_exists || frontmost_snapshot_fl_exists);
+ }
};
class LLFileCloseWindow : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool frontmost_fl_exists = (NULL != gFloaterView->getFrontmostClosableFloater());
- LLFloater* snapshot_floater = gSnapshotFloaterView->getFrontmostClosableFloater();
-
- if(snapshot_floater && (!frontmost_fl_exists || snapshot_floater->hasFocus()))
- {
- snapshot_floater->closeFloater();
- if (gFocusMgr.getKeyboardFocus() == NULL)
- {
- gFloaterView->focusFrontFloater();
- }
- }
- else
- {
- LLFloater::closeFrontmostFloater();
- }
- if (gMenuHolder) gMenuHolder->hideMenus();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool frontmost_fl_exists = (NULL != gFloaterView->getFrontmostClosableFloater());
+ LLFloater* snapshot_floater = gSnapshotFloaterView->getFrontmostClosableFloater();
+
+ if(snapshot_floater && (!frontmost_fl_exists || snapshot_floater->hasFocus()))
+ {
+ snapshot_floater->closeFloater();
+ if (gFocusMgr.getKeyboardFocus() == NULL)
+ {
+ gFloaterView->focusFrontFloater();
+ }
+ }
+ else
+ {
+ LLFloater::closeFrontmostFloater();
+ }
+ if (gMenuHolder) gMenuHolder->hideMenus();
+ return true;
+ }
};
class LLFileEnableCloseAllWindows : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
- bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain());
- bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened;
- return !open_children && !LLNotificationsUI::LLToast::isAlertToastShown();
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
+ bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain());
+ bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened;
+ return !open_children && !LLNotificationsUI::LLToast::isAlertToastShown();
+ }
};
+void close_all_windows()
+{
+ bool app_quitting = false;
+ gFloaterView->closeAllChildren(app_quitting);
+ LLFloaterSnapshot *floater_snapshot = LLFloaterSnapshot::findInstance();
+ if (floater_snapshot)
+ floater_snapshot->closeFloater(app_quitting);
+ if (gMenuHolder)
+ gMenuHolder->hideMenus();
+}
+
class LLFileCloseAllWindows : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- bool app_quitting = false;
- gFloaterView->closeAllChildren(app_quitting);
- LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance();
- if (floater_snapshot)
- floater_snapshot->closeFloater(app_quitting);
- if (gMenuHolder) gMenuHolder->hideMenus();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ close_all_windows();
+ return true;
+ }
};
class LLFileTakeSnapshotToDisk : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLPointer<LLImageRaw> raw = new LLImageRaw;
-
- S32 width = gViewerWindow->getWindowWidthRaw();
- S32 height = gViewerWindow->getWindowHeightRaw();
-
- BOOL render_ui = gSavedSettings.getBOOL("RenderUIInSnapshot");
- BOOL render_hud = gSavedSettings.getBOOL("RenderHUDInSnapshot");
- BOOL render_no_post = gSavedSettings.getBOOL("RenderSnapshotNoPost");
-
- BOOL high_res = gSavedSettings.getBOOL("HighResSnapshot");
- if (high_res)
- {
- width *= 2;
- height *= 2;
- // not compatible with UI/HUD
- render_ui = false;
- render_hud = false;
- }
-
- if (gViewerWindow->rawSnapshot(raw,
- width,
- height,
- TRUE,
- FALSE,
- render_ui,
- render_hud,
- FALSE,
- render_no_post,
- LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
- high_res ? S32_MAX : MAX_SNAPSHOT_IMAGE_SIZE)) //per side
- {
- LLPointer<LLImageFormatted> formatted;
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLPointer<LLImageRaw> raw = new LLImageRaw;
+
+ S32 width = gViewerWindow->getWindowWidthRaw();
+ S32 height = gViewerWindow->getWindowHeightRaw();
+
+ BOOL render_ui = gSavedSettings.getBOOL("RenderUIInSnapshot");
+ BOOL render_hud = gSavedSettings.getBOOL("RenderHUDInSnapshot");
+ BOOL render_no_post = gSavedSettings.getBOOL("RenderSnapshotNoPost");
+
+ BOOL high_res = gSavedSettings.getBOOL("HighResSnapshot");
+ if (high_res)
+ {
+ width *= 2;
+ height *= 2;
+ // not compatible with UI/HUD
+ render_ui = false;
+ render_hud = false;
+ }
+
+ if (gViewerWindow->rawSnapshot(raw,
+ width,
+ height,
+ TRUE,
+ FALSE,
+ render_ui,
+ render_hud,
+ FALSE,
+ render_no_post,
+ LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
+ high_res ? S32_MAX : MAX_SNAPSHOT_IMAGE_SIZE)) //per side
+ {
+ LLPointer<LLImageFormatted> formatted;
LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
- switch (fmt)
- {
- case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
- formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality"));
- break;
- default:
- LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL;
- case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
- formatted = new LLImagePNG;
- break;
- case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
- formatted = new LLImageBMP;
- break;
- }
- formatted->enableOverSize() ;
- formatted->encode(raw, 0);
- formatted->disableOverSize() ;
- LLSnapshotLivePreview::saveLocal(formatted);
- }
- return true;
- }
+ switch (fmt)
+ {
+ case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG:
+ formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality"));
+ break;
+ default:
+ LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL;
+ case LLSnapshotModel::SNAPSHOT_FORMAT_PNG:
+ formatted = new LLImagePNG;
+ break;
+ case LLSnapshotModel::SNAPSHOT_FORMAT_BMP:
+ formatted = new LLImageBMP;
+ break;
+ }
+ formatted->enableOverSize() ;
+ formatted->encode(raw, 0);
+ formatted->disableOverSize() ;
+ LLSnapshotLivePreview::saveLocal(formatted);
+ }
+ return true;
+ }
};
class LLFileQuit : public view_listener_t
{
- bool handleEvent(const LLSD& userdata)
- {
- LLAppViewer::instance()->userQuit();
- return true;
- }
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLAppViewer::instance()->userQuit();
+ return true;
+ }
};
void handle_compress_image(void*)
{
- LLFilePicker& picker = LLFilePicker::instance();
- if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE))
- {
- std::string infile = picker.getFirstFile();
- while (!infile.empty())
- {
- std::string outfile = infile + ".j2c";
-
- LL_INFOS() << "Input: " << infile << LL_ENDL;
- LL_INFOS() << "Output: " << outfile << LL_ENDL;
-
- BOOL success;
-
- success = LLViewerTextureList::createUploadFile(infile, outfile, IMG_CODEC_TGA);
-
- if (success)
- {
- LL_INFOS() << "Compression complete" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "Compression failed: " << LLImage::getLastError() << LL_ENDL;
- }
-
- infile = picker.getNextFile();
- }
- }
+ LLFilePicker& picker = LLFilePicker::instance();
+ if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE))
+ {
+ std::string infile = picker.getFirstFile();
+ while (!infile.empty())
+ {
+ std::string outfile = infile + ".j2c";
+
+ LL_INFOS() << "Input: " << infile << LL_ENDL;
+ LL_INFOS() << "Output: " << outfile << LL_ENDL;
+
+ BOOL success;
+
+ success = LLViewerTextureList::createUploadFile(infile, outfile, IMG_CODEC_TGA);
+
+ if (success)
+ {
+ LL_INFOS() << "Compression complete" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "Compression failed: " << LLImage::getLastError() << LL_ENDL;
+ }
+
+ infile = picker.getNextFile();
+ }
+ }
}
// No convinient check in LLFile, and correct way would be something
@@ -960,7 +966,7 @@ void handle_compress_image(void*)
// so doing dirty, but OS independent fopen and fseek
size_t get_file_size(std::string &filename)
{
- LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
+ LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
if (!file)
{
LL_WARNS() << "Error opening " << filename << LL_ENDL;
@@ -1045,21 +1051,21 @@ void handle_compress_file_test(void*)
LLUUID upload_new_resource(
- const std::string& src_filename,
- std::string name,
- std::string desc,
- S32 compression_info,
- LLFolderType::EType destination_folder_type,
- LLInventoryType::EType inv_type,
- U32 next_owner_perms,
- U32 group_perms,
- U32 everyone_perms,
- const std::string& display_name,
- LLAssetStorage::LLStoreAssetCallback callback,
- S32 expected_upload_cost,
- void *userdata,
- bool show_inventory)
-{
+ const std::string& src_filename,
+ std::string name,
+ std::string desc,
+ S32 compression_info,
+ LLFolderType::EType destination_folder_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perms,
+ U32 group_perms,
+ U32 everyone_perms,
+ const std::string& display_name,
+ LLAssetStorage::LLStoreAssetCallback callback,
+ S32 expected_upload_cost,
+ void *userdata,
+ bool show_inventory)
+{
LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLNewFileResourceUploadInfo>(
src_filename,
@@ -1073,127 +1079,127 @@ LLUUID upload_new_resource(
}
void upload_done_callback(
- const LLUUID& uuid,
- void* user_data,
- S32 result,
- LLExtStat ext_status) // StoreAssetData callback (fixed)
+ const LLUUID& uuid,
+ void* user_data,
+ S32 result,
+ LLExtStat ext_status) // StoreAssetData callback (fixed)
{
- LLResourceData* data = (LLResourceData*)user_data;
- S32 expected_upload_cost = data ? data->mExpectedUploadCost : 0;
- //LLAssetType::EType pref_loc = data->mPreferredLocation;
- BOOL is_balance_sufficient = TRUE;
-
- if(data)
- {
- if (result >= 0)
- {
- LLFolderType::EType dest_loc = (data->mPreferredLocation == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(data->mAssetInfo.mType) : data->mPreferredLocation;
-
- if (LLAssetType::AT_SOUND == data->mAssetInfo.mType ||
- LLAssetType::AT_TEXTURE == data->mAssetInfo.mType ||
- LLAssetType::AT_ANIMATION == data->mAssetInfo.mType)
- {
- // Charge the user for the upload.
- LLViewerRegion* region = gAgent.getRegion();
-
- if(!(can_afford_transaction(expected_upload_cost)))
- {
- LLBuyCurrencyHTML::openCurrencyFloater( "", expected_upload_cost );
- is_balance_sufficient = FALSE;
- }
- else if(region)
- {
- // Charge user for upload
- gStatusBar->debitBalance(expected_upload_cost);
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_MoneyTransferRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_MoneyData);
- msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_DestID, LLUUID::null);
- msg->addU8("Flags", 0);
- // we tell the sim how much we were expecting to pay so it
- // can respond to any discrepancy
- msg->addS32Fast(_PREHASH_Amount, expected_upload_cost);
- msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY);
- msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY);
- msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE);
- msg->addStringFast(_PREHASH_Description, NULL);
- msg->sendReliable(region->getHost());
- }
- }
-
- if(is_balance_sufficient)
- {
- // Actually add the upload to inventory
- LL_INFOS() << "Adding " << uuid << " to inventory." << LL_ENDL;
- const LLUUID folder_id = gInventory.findCategoryUUIDForType(dest_loc);
- if(folder_id.notNull())
- {
- U32 next_owner_perms = data->mNextOwnerPerm;
- if(PERM_NONE == next_owner_perms)
- {
- next_owner_perms = PERM_MOVE | PERM_TRANSFER;
- }
- create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
- folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(),
- data->mAssetInfo.getDescription(), data->mAssetInfo.mType,
+ LLResourceData* data = (LLResourceData*)user_data;
+ S32 expected_upload_cost = data ? data->mExpectedUploadCost : 0;
+ //LLAssetType::EType pref_loc = data->mPreferredLocation;
+ BOOL is_balance_sufficient = TRUE;
+
+ if(data)
+ {
+ if (result >= 0)
+ {
+ LLFolderType::EType dest_loc = (data->mPreferredLocation == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(data->mAssetInfo.mType) : data->mPreferredLocation;
+
+ if (LLAssetType::AT_SOUND == data->mAssetInfo.mType ||
+ LLAssetType::AT_TEXTURE == data->mAssetInfo.mType ||
+ LLAssetType::AT_ANIMATION == data->mAssetInfo.mType)
+ {
+ // Charge the user for the upload.
+ LLViewerRegion* region = gAgent.getRegion();
+
+ if(!(can_afford_transaction(expected_upload_cost)))
+ {
+ LLBuyCurrencyHTML::openCurrencyFloater( "", expected_upload_cost );
+ is_balance_sufficient = FALSE;
+ }
+ else if(region)
+ {
+ // Charge user for upload
+ gStatusBar->debitBalance(expected_upload_cost);
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_MoneyTransferRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_MoneyData);
+ msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_DestID, LLUUID::null);
+ msg->addU8("Flags", 0);
+ // we tell the sim how much we were expecting to pay so it
+ // can respond to any discrepancy
+ msg->addS32Fast(_PREHASH_Amount, expected_upload_cost);
+ msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY);
+ msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY);
+ msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE);
+ msg->addStringFast(_PREHASH_Description, NULL);
+ msg->sendReliable(region->getHost());
+ }
+ }
+
+ if(is_balance_sufficient)
+ {
+ // Actually add the upload to inventory
+ LL_INFOS() << "Adding " << uuid << " to inventory." << LL_ENDL;
+ const LLUUID folder_id = gInventory.findCategoryUUIDForType(dest_loc);
+ if(folder_id.notNull())
+ {
+ U32 next_owner_perms = data->mNextOwnerPerm;
+ if(PERM_NONE == next_owner_perms)
+ {
+ next_owner_perms = PERM_MOVE | PERM_TRANSFER;
+ }
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(),
+ data->mAssetInfo.getDescription(), data->mAssetInfo.mType,
data->mInventoryType, NO_INV_SUBTYPE, next_owner_perms,
- LLPointer<LLInventoryCallback>(NULL));
- }
- else
- {
- LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
- }
- }
- }
- else // if(result >= 0)
- {
- LLSD args;
- args["FILE"] = LLInventoryType::lookupHumanReadable(data->mInventoryType);
- args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
- LLNotificationsUtil::add("CannotUploadReason", args);
- }
-
- delete data;
- data = NULL;
- }
-
- LLUploadDialog::modalUploadFinished();
-
- // *NOTE: This is a pretty big hack. What this does is check the
- // file picker if there are any more pending uploads. If so,
- // upload that file.
- const std::string& next_file = LLFilePicker::instance().getNextFile();
- if(is_balance_sufficient && !next_file.empty())
- {
- std::string asset_name = gDirUtilp->getBaseFileName(next_file, true);
- LLStringUtil::replaceNonstandardASCII( asset_name, '?' );
- LLStringUtil::replaceChar(asset_name, '|', '?');
- LLStringUtil::stripNonprintable(asset_name);
- LLStringUtil::trim(asset_name);
-
- std::string display_name = LLStringUtil::null;
- LLAssetStorage::LLStoreAssetCallback callback;
- void *userdata = NULL;
- upload_new_resource(
- next_file,
- asset_name,
- asset_name, // file
- 0,
- LLFolderType::FT_NONE,
- LLInventoryType::IT_NONE,
- LLFloaterPerms::getNextOwnerPerms("Uploads"),
- LLFloaterPerms::getGroupPerms("Uploads"),
- LLFloaterPerms::getEveryonePerms("Uploads"),
- display_name,
- callback,
- expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost
- userdata);
- }
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else
+ {
+ LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
+ }
+ }
+ }
+ else // if(result >= 0)
+ {
+ LLSD args;
+ args["FILE"] = LLInventoryType::lookupHumanReadable(data->mInventoryType);
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
+ LLNotificationsUtil::add("CannotUploadReason", args);
+ }
+
+ delete data;
+ data = NULL;
+ }
+
+ LLUploadDialog::modalUploadFinished();
+
+ // *NOTE: This is a pretty big hack. What this does is check the
+ // file picker if there are any more pending uploads. If so,
+ // upload that file.
+ const std::string& next_file = LLFilePicker::instance().getNextFile();
+ if(is_balance_sufficient && !next_file.empty())
+ {
+ std::string asset_name = gDirUtilp->getBaseFileName(next_file, true);
+ LLStringUtil::replaceNonstandardASCII( asset_name, '?' );
+ LLStringUtil::replaceChar(asset_name, '|', '?');
+ LLStringUtil::stripNonprintable(asset_name);
+ LLStringUtil::trim(asset_name);
+
+ std::string display_name = LLStringUtil::null;
+ LLAssetStorage::LLStoreAssetCallback callback;
+ void *userdata = NULL;
+ upload_new_resource(
+ next_file,
+ asset_name,
+ asset_name, // file
+ 0,
+ LLFolderType::FT_NONE,
+ LLInventoryType::IT_NONE,
+ LLFloaterPerms::getNextOwnerPerms("Uploads"),
+ LLFloaterPerms::getGroupPerms("Uploads"),
+ LLFloaterPerms::getEveryonePerms("Uploads"),
+ display_name,
+ callback,
+ expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost
+ userdata);
+ }
}
void upload_new_resource(
@@ -1201,90 +1207,90 @@ void upload_new_resource(
LLAssetStorage::LLStoreAssetCallback callback,
void *userdata)
{
- if(gDisconnected)
- {
- return ;
- }
+ if(gDisconnected)
+ {
+ return ;
+ }
// uploadInfo->setAssetType(assetType);
// uploadInfo->setTransactionId(tid);
- std::string url = gAgent.getRegionCapability("NewFileAgentInventory");
+ std::string url = gAgent.getRegionCapability("NewFileAgentInventory");
- if ( !url.empty() )
- {
+ if ( !url.empty() )
+ {
LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
- }
- else
- {
+ }
+ else
+ {
uploadInfo->prepareUpload();
uploadInfo->logPreparedUpload();
- LL_INFOS() << "NewAgentInventory capability not found, new agent inventory via asset system." << LL_ENDL;
- // check for adequate funds
- // TODO: do this check on the sim
- if (LLAssetType::AT_SOUND == uploadInfo->getAssetType() ||
+ LL_INFOS() << "NewAgentInventory capability not found, new agent inventory via asset system." << LL_ENDL;
+ // check for adequate funds
+ // TODO: do this check on the sim
+ if (LLAssetType::AT_SOUND == uploadInfo->getAssetType() ||
LLAssetType::AT_TEXTURE == uploadInfo->getAssetType() ||
LLAssetType::AT_ANIMATION == uploadInfo->getAssetType())
- {
- S32 balance = gStatusBar->getBalance();
- if (balance < uploadInfo->getExpectedUploadCost())
- {
- // insufficient funds, bail on this upload
+ {
+ S32 balance = gStatusBar->getBalance();
+ if (balance < uploadInfo->getExpectedUploadCost())
+ {
+ // insufficient funds, bail on this upload
LLBuyCurrencyHTML::openCurrencyFloater("", uploadInfo->getExpectedUploadCost());
- return;
- }
- }
+ return;
+ }
+ }
- LLResourceData* data = new LLResourceData;
- data->mAssetInfo.mTransactionID = uploadInfo->getTransactionId();
- data->mAssetInfo.mUuid = uploadInfo->getAssetId();
+ LLResourceData* data = new LLResourceData;
+ data->mAssetInfo.mTransactionID = uploadInfo->getTransactionId();
+ data->mAssetInfo.mUuid = uploadInfo->getAssetId();
data->mAssetInfo.mType = uploadInfo->getAssetType();
- data->mAssetInfo.mCreatorID = gAgentID;
- data->mInventoryType = uploadInfo->getInventoryType();
- data->mNextOwnerPerm = uploadInfo->getNextOwnerPerms();
- data->mExpectedUploadCost = uploadInfo->getExpectedUploadCost();
- data->mUserData = userdata;
- data->mAssetInfo.setName(uploadInfo->getName());
- data->mAssetInfo.setDescription(uploadInfo->getDescription());
- data->mPreferredLocation = uploadInfo->getDestinationFolderType();
-
- LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback;
- if (callback)
- {
- asset_callback = callback;
- }
- gAssetStorage->storeAssetData(
- data->mAssetInfo.mTransactionID,
- data->mAssetInfo.mType,
- asset_callback,
- (void*)data,
- FALSE);
- }
+ data->mAssetInfo.mCreatorID = gAgentID;
+ data->mInventoryType = uploadInfo->getInventoryType();
+ data->mNextOwnerPerm = uploadInfo->getNextOwnerPerms();
+ data->mExpectedUploadCost = uploadInfo->getExpectedUploadCost();
+ data->mUserData = userdata;
+ data->mAssetInfo.setName(uploadInfo->getName());
+ data->mAssetInfo.setDescription(uploadInfo->getDescription());
+ data->mPreferredLocation = uploadInfo->getDestinationFolderType();
+
+ LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback;
+ if (callback)
+ {
+ asset_callback = callback;
+ }
+ gAssetStorage->storeAssetData(
+ data->mAssetInfo.mTransactionID,
+ data->mAssetInfo.mType,
+ asset_callback,
+ (void*)data,
+ FALSE);
+ }
}
void init_menu_file()
{
- view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage");
- view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound");
- view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim");
- view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel");
+ view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage");
+ view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound");
+ view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim");
+ view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel");
view_listener_t::addCommit(new LLFileUploadMaterial(), "File.UploadMaterial");
- view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk");
- view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow");
- view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows");
- view_listener_t::addEnable(new LLFileEnableCloseWindow(), "File.EnableCloseWindow");
- view_listener_t::addEnable(new LLFileEnableCloseAllWindows(), "File.EnableCloseAllWindows");
- view_listener_t::addCommit(new LLFileTakeSnapshotToDisk(), "File.TakeSnapshotToDisk");
- view_listener_t::addCommit(new LLFileQuit(), "File.Quit");
-
- view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload");
- view_listener_t::addEnable(new LLFileEnableUploadModel(), "File.EnableUploadModel");
+ view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk");
+ view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow");
+ view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows");
+ view_listener_t::addEnable(new LLFileEnableCloseWindow(), "File.EnableCloseWindow");
+ view_listener_t::addEnable(new LLFileEnableCloseAllWindows(), "File.EnableCloseAllWindows");
+ view_listener_t::addCommit(new LLFileTakeSnapshotToDisk(), "File.TakeSnapshotToDisk");
+ view_listener_t::addCommit(new LLFileQuit(), "File.Quit");
+
+ view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload");
+ view_listener_t::addEnable(new LLFileEnableUploadModel(), "File.EnableUploadModel");
view_listener_t::addEnable(new LLFileEnableUploadMaterial(), "File.EnableUploadMaterial");
- view_listener_t::addMenu(new LLMeshEnabled(), "File.MeshEnabled");
- view_listener_t::addMenu(new LLMeshUploadVisible(), "File.VisibleUploadModel");
+ view_listener_t::addMenu(new LLMeshEnabled(), "File.MeshEnabled");
+ view_listener_t::addMenu(new LLMeshUploadVisible(), "File.VisibleUploadModel");
- // "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled.
+ // "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled.
}
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index 1acb701d50..d41aa23829 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llviewermenufile.h
* @brief "File" menu in the main menu bar.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -66,50 +66,52 @@ void upload_new_resource(
void assign_defaults_and_show_upload_message(
- LLAssetType::EType asset_type,
- LLInventoryType::EType& inventory_type,
- std::string& name,
- const std::string& display_name,
- std::string& description);
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType& inventory_type,
+ std::string& name,
+ const std::string& display_name,
+ std::string& description);
+
+void close_all_windows();
//consider moving all file pickers below to more suitable place
class LLFilePickerThread : public LLThread
{ //multi-threaded file picker (runs system specific file picker in background and calls "notify" from main thread)
public:
- static std::queue<LLFilePickerThread*> sDeadQ;
- static LLMutex* sMutex;
+ static std::queue<LLFilePickerThread*> sDeadQ;
+ static LLMutex* sMutex;
- static void initClass();
- static void cleanupClass();
- static void clearDead();
+ static void initClass();
+ static void cleanupClass();
+ static void clearDead();
- std::vector<std::string> mResponses;
- std::string mProposedName;
+ std::vector<std::string> mResponses;
+ std::string mProposedName;
- LLFilePicker::ELoadFilter mLoadFilter;
- LLFilePicker::ESaveFilter mSaveFilter;
- bool mIsSaveDialog;
- bool mIsGetMultiple;
+ LLFilePicker::ELoadFilter mLoadFilter;
+ LLFilePicker::ESaveFilter mSaveFilter;
+ bool mIsSaveDialog;
+ bool mIsGetMultiple;
- LLFilePickerThread(LLFilePicker::ELoadFilter filter, bool get_multiple = false)
- : LLThread("file picker"), mLoadFilter(filter), mIsSaveDialog(false), mIsGetMultiple(get_multiple)
- {
- }
+ LLFilePickerThread(LLFilePicker::ELoadFilter filter, bool get_multiple = false)
+ : LLThread("file picker"), mLoadFilter(filter), mIsSaveDialog(false), mIsGetMultiple(get_multiple)
+ {
+ }
- LLFilePickerThread(LLFilePicker::ESaveFilter filter, const std::string &proposed_name)
- : LLThread("file picker"), mSaveFilter(filter), mIsSaveDialog(true), mProposedName(proposed_name)
- {
- }
+ LLFilePickerThread(LLFilePicker::ESaveFilter filter, const std::string &proposed_name)
+ : LLThread("file picker"), mSaveFilter(filter), mIsSaveDialog(true), mProposedName(proposed_name)
+ {
+ }
- void getFile();
+ void getFile();
- virtual void run();
+ virtual void run();
void runModeless();
static void modelessStringCallback(bool success, std::string &response, void *user_data);
static void modelessVectorCallback(bool success, std::vector<std::string> &responses, void *user_data);
- virtual void notify(const std::vector<std::string>& filenames) = 0;
+ virtual void notify(const std::vector<std::string>& filenames) = 0;
};
@@ -117,12 +119,12 @@ class LLFilePickerReplyThread : public LLFilePickerThread
{
public:
- typedef boost::signals2::signal<void(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)> file_picked_signal_t;
+ typedef boost::signals2::signal<void(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)> file_picked_signal_t;
static void startPicker(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());
static void startPicker(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());
- virtual void notify(const std::vector<std::string>& filenames);
+ virtual void notify(const std::vector<std::string>& filenames);
private:
LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t());
@@ -130,10 +132,10 @@ private:
~LLFilePickerReplyThread();
private:
- LLFilePicker::ELoadFilter mLoadFilter;
- LLFilePicker::ESaveFilter mSaveFilter;
- file_picked_signal_t* mFilePickedSignal;
- file_picked_signal_t* mFailureSignal;
+ LLFilePicker::ELoadFilter mLoadFilter;
+ LLFilePicker::ESaveFilter mSaveFilter;
+ file_picked_signal_t* mFilePickedSignal;
+ file_picked_signal_t* mFailureSignal;
};
class LLMediaFilePicker : public LLFilePickerThread
diff --git a/indra/newview/scripts/lua/ErrorQueue.lua b/indra/newview/scripts/lua/ErrorQueue.lua
new file mode 100644
index 0000000000..6ed1c10d5c
--- /dev/null
+++ b/indra/newview/scripts/lua/ErrorQueue.lua
@@ -0,0 +1,34 @@
+-- ErrorQueue isa WaitQueue with the added feature that a producer can push an
+-- error through the queue. Once that error is dequeued, every consumer will
+-- raise that error.
+
+local WaitQueue = require('WaitQueue')
+-- local dbg = require('printf')
+local function dbg(...) end
+
+local ErrorQueue = WaitQueue:new()
+
+function ErrorQueue:Error(message)
+ -- Setting Error() is a marker, like closing the queue. Once we reach the
+ -- error, every subsequent Dequeue() call will raise the same error.
+ dbg('Setting self._closed to %q', message)
+ self._closed = message
+ self:_wake_waiters()
+end
+
+function ErrorQueue:Dequeue()
+ local value = WaitQueue.Dequeue(self)
+ dbg('ErrorQueue:Dequeue: base Dequeue() got %s', value)
+ if value ~= nil then
+ -- queue not yet closed, show caller
+ return value
+ end
+ if self._closed == true then
+ -- WaitQueue:close() sets true: queue has only been closed, tell caller
+ return nil
+ end
+ -- self._closed is a message set by Error()
+ error(self._closed)
+end
+
+return ErrorQueue
diff --git a/indra/newview/scripts/lua/Floater.lua b/indra/newview/scripts/lua/Floater.lua
new file mode 100644
index 0000000000..76efd47c43
--- /dev/null
+++ b/indra/newview/scripts/lua/Floater.lua
@@ -0,0 +1,151 @@
+-- Floater base class
+
+local leap = require 'leap'
+local fiber = require 'fiber'
+
+-- list of all the events that a LLLuaFloater might send
+local event_list = leap.request("LLFloaterReg", {op="getFloaterEvents"}).events
+local event_set = {}
+for _, event in pairs(event_list) do
+ event_set[event] = true
+end
+
+local function _event(event_name)
+ if not event_set[event_name] then
+ error("Incorrect event name: " .. event_name, 3)
+ end
+ return event_name
+end
+
+-- ---------------------------------------------------------------------------
+local Floater = {}
+
+-- Pass:
+-- relative file path to floater's XUI definition file
+-- optional: sign up for additional events for defined control
+-- {<control_name>={action1, action2, ...}}
+function Floater:new(path, extra)
+ local obj = setmetatable({}, self)
+ self.__index = self
+
+ local path_parts = string.split(path, '/')
+ obj.name = 'Floater ' .. path_parts[#path_parts]
+
+ obj._command = {op="showLuaFloater", xml_path=LL.abspath(path)}
+ if extra then
+ -- validate each of the actions for each specified control
+ for control, actions in pairs(extra) do
+ for _, action in pairs(actions) do
+ _event(action)
+ end
+ end
+ obj._command.extra_events = extra
+ end
+
+ return obj
+end
+
+function Floater:show()
+ local event = leap.request('LLFloaterReg', self._command)
+ self._pump = event.command_name
+ -- we use the returned reqid to claim subsequent unsolicited events
+ local reqid = event.reqid
+
+ -- The response to 'showLuaFloater' *is* the 'post_build' event. Check if
+ -- subclass has a post_build() method. Honor the convention that if
+ -- handleEvents() returns false, we're done.
+ if not self:handleEvents(event) then
+ return
+ end
+
+ local waitfor = leap.WaitFor:new(-1, self.name)
+ function waitfor:filter(pump, data)
+ if data.reqid == reqid then
+ return data
+ end
+ end
+
+ fiber.launch(
+ self.name,
+ function ()
+ event = waitfor:wait()
+ while event and self:handleEvents(event) do
+ event = waitfor:wait()
+ end
+ end)
+end
+
+function Floater:post(action)
+ leap.send(self._pump, action)
+end
+
+function Floater:request(action)
+ return leap.request(self._pump, action)
+end
+
+-- local inspect = require 'inspect'
+
+function Floater:handleEvents(event_data)
+ local event = event_data.event
+ if event_set[event] == nil then
+ LL.print_warning(string.format('%s received unknown event %q', self.name, event))
+ end
+
+ -- Before checking for a general (e.g.) commit() method, first look for
+ -- commit_ctrl_name(): in other words, concatenate the event name with the
+ -- ctrl_name, with an underscore between. If there exists such a specific
+ -- method, call that.
+ local handler, ret
+ if event_data.ctrl_name then
+ local specific = event .. '_' .. event_data.ctrl_name
+ handler = self[specific]
+ if handler then
+ ret = handler(self, event_data)
+ -- Avoid 'return ret or true' because we explicitly want to allow
+ -- the handler to return false.
+ if ret ~= nil then
+ return ret
+ else
+ return true
+ end
+ end
+ end
+
+ -- No specific "event_on_ctrl()" method found; try just "event()"
+ handler = self[event]
+ if handler then
+ ret = handler(self, event_data)
+ if ret ~= nil then
+ return ret
+ end
+-- else
+-- print(string.format('%s ignoring event %s', self.name, inspect(event_data)))
+ end
+
+ -- We check for event() method before recognizing floater_close in case
+ -- the consumer needs to react specially to closing the floater. Now that
+ -- we've checked, recognize it ourselves. Returning false terminates the
+ -- anonymous fiber function launched by show().
+ if event == _event('floater_close') then
+ LL.print_warning(self.name .. ' closed')
+ return false
+ end
+ return true
+end
+
+-- onCtrl() permits a different dispatch style in which the general event()
+-- method explicitly calls (e.g.)
+-- self:onCtrl(event_data, {
+-- ctrl_name=function()
+-- self:post(...)
+-- end,
+-- ...
+-- })
+function Floater:onCtrl(event_data, ctrl_map)
+ local handler = ctrl_map[event_data.ctrl_name]
+ if handler then
+ handler()
+ end
+end
+
+return Floater
diff --git a/indra/newview/scripts/lua/LLDebugSettings.lua b/indra/newview/scripts/lua/LLDebugSettings.lua
new file mode 100644
index 0000000000..c1d74fe00a
--- /dev/null
+++ b/indra/newview/scripts/lua/LLDebugSettings.lua
@@ -0,0 +1,24 @@
+leap = require 'leap'
+
+local function check_response(res)
+ if res.error then
+ error(res.error)
+ end
+ return res
+end
+
+local LLDebugSettings = {}
+
+function LLDebugSettings.set(name, value)
+ check_response(leap.request('LLViewerControl', {op='set', group='Global', key=name, value=value}))
+end
+
+function LLDebugSettings.toggle(name)
+ check_response(leap.request('LLViewerControl', {op='toggle', group='Global', key=name}))
+end
+
+function LLDebugSettings.get(name)
+ return check_response(leap.request('LLViewerControl', {op='get', group='Global', key=name}))['value']
+end
+
+return LLDebugSettings
diff --git a/indra/newview/scripts/lua/LLFloaterAbout.lua b/indra/newview/scripts/lua/LLFloaterAbout.lua
new file mode 100644
index 0000000000..44afee2e5c
--- /dev/null
+++ b/indra/newview/scripts/lua/LLFloaterAbout.lua
@@ -0,0 +1,11 @@
+-- Engage the LLFloaterAbout LLEventAPI
+
+leap = require 'leap'
+
+local LLFloaterAbout = {}
+
+function LLFloaterAbout.getInfo()
+ return leap.request('LLFloaterAbout', {op='getInfo'})
+end
+
+return LLFloaterAbout
diff --git a/indra/newview/scripts/lua/LLGesture.lua b/indra/newview/scripts/lua/LLGesture.lua
new file mode 100644
index 0000000000..cb410446d7
--- /dev/null
+++ b/indra/newview/scripts/lua/LLGesture.lua
@@ -0,0 +1,23 @@
+-- Engage the LLGesture LLEventAPI
+
+leap = require 'leap'
+
+local LLGesture = {}
+
+function LLGesture.getActiveGestures()
+ return leap.request('LLGesture', {op='getActiveGestures'})['gestures']
+end
+
+function LLGesture.isGesturePlaying(id)
+ return leap.request('LLGesture', {op='isGesturePlaying', id=id})['playing']
+end
+
+function LLGesture.startGesture(id)
+ leap.send('LLGesture', {op='startGesture', id=id})
+end
+
+function LLGesture.stopGesture(id)
+ leap.send('LLGesture', {op='stopGesture', id=id})
+end
+
+return LLGesture
diff --git a/indra/newview/scripts/lua/Queue.lua b/indra/newview/scripts/lua/Queue.lua
new file mode 100644
index 0000000000..5ab2a8a72c
--- /dev/null
+++ b/indra/newview/scripts/lua/Queue.lua
@@ -0,0 +1,47 @@
+-- from https://create.roblox.com/docs/luau/queues#implementing-queues,
+-- amended per https://www.lua.org/pil/16.1.html
+
+-- While coding some scripting in Lua
+-- I found that I needed a queua
+-- I thought of linked list
+-- But had to resist
+-- For fear it might be too obscua.
+
+local Queue = {}
+
+function Queue:new()
+ local obj = setmetatable({}, self)
+ self.__index = self
+
+ obj._first = 0
+ obj._last = -1
+ obj._queue = {}
+
+ return obj
+end
+
+-- Check if the queue is empty
+function Queue:IsEmpty()
+ return self._first > self._last
+end
+
+-- Add a value to the queue
+function Queue:Enqueue(value)
+ local last = self._last + 1
+ self._last = last
+ self._queue[last] = value
+end
+
+-- Remove a value from the queue
+function Queue:Dequeue()
+ if self:IsEmpty() then
+ return nil
+ end
+ local first = self._first
+ local value = self._queue[first]
+ self._queue[first] = nil
+ self._first = first + 1
+ return value
+end
+
+return Queue
diff --git a/indra/newview/scripts/lua/UI.lua b/indra/newview/scripts/lua/UI.lua
new file mode 100644
index 0000000000..f851632bad
--- /dev/null
+++ b/indra/newview/scripts/lua/UI.lua
@@ -0,0 +1,16 @@
+-- Engage the UI LLEventAPI
+
+leap = require 'leap'
+
+local UI = {}
+
+function UI.call(func, parameter)
+ -- 'call' is fire-and-forget
+ leap.send('UI', {op='call', ['function']=func, parameter=parameter})
+end
+
+function UI.getValue(path)
+ return leap.request('UI', {op='getValue', path=path})['value']
+end
+
+return UI
diff --git a/indra/newview/scripts/lua/WaitQueue.lua b/indra/newview/scripts/lua/WaitQueue.lua
new file mode 100644
index 0000000000..ad4fdecf43
--- /dev/null
+++ b/indra/newview/scripts/lua/WaitQueue.lua
@@ -0,0 +1,85 @@
+-- WaitQueue isa Queue with the added feature that when the queue is empty,
+-- the Dequeue() operation blocks the calling coroutine until some other
+-- coroutine Enqueue()s a new value.
+
+local fiber = require('fiber')
+local Queue = require('Queue')
+
+-- local dbg = require('printf')
+local function dbg(...) end
+
+local WaitQueue = Queue:new()
+
+function WaitQueue:new()
+ local obj = Queue:new()
+ setmetatable(obj, self)
+ self.__index = self
+
+ obj._waiters = {}
+ obj._closed = false
+ return obj
+end
+
+function WaitQueue:Enqueue(value)
+ if self._closed then
+ error("can't Enqueue() on closed Queue")
+ end
+ -- can't simply call Queue:Enqueue(value)! That calls the method on the
+ -- Queue class definition, instead of calling Queue:Enqueue() on self.
+ -- Hand-expand the Queue:Enqueue() syntactic sugar.
+ Queue.Enqueue(self, value)
+ self:_wake_waiters()
+end
+
+function WaitQueue:_wake_waiters()
+ -- WaitQueue is designed to support multi-producer, multi-consumer use
+ -- cases. With multiple consumers, if more than one is trying to
+ -- Dequeue() from an empty WaitQueue, we'll have multiple waiters.
+ -- Unlike OS threads, with cooperative concurrency it doesn't make sense
+ -- to "notify all": we need wake only one of the waiting Dequeue()
+ -- callers.
+ if ((not self:IsEmpty()) or self._closed) and next(self._waiters) then
+ -- Pop the oldest waiting coroutine instead of the most recent, for
+ -- more-or-less round robin fairness. But skip any coroutines that
+ -- have gone dead in the meantime.
+ local waiter = table.remove(self._waiters, 1)
+ while waiter and fiber.status(waiter) == "dead" do
+ waiter = table.remove(self._waiters, 1)
+ end
+ -- do we still have at least one waiting coroutine?
+ if waiter then
+ -- don't pass the head item: let the resumed coroutine retrieve it
+ fiber.wake(waiter)
+ end
+ end
+end
+
+function WaitQueue:Dequeue()
+ while self:IsEmpty() do
+ -- Don't check for closed until the queue is empty: producer can close
+ -- the queue while there are still items left, and we want the
+ -- consumer(s) to retrieve those last few items.
+ if self._closed then
+ dbg('WaitQueue:Dequeue(): closed')
+ return nil
+ end
+ dbg('WaitQueue:Dequeue(): waiting')
+ -- add the running coroutine to the list of waiters
+ dbg('WaitQueue:Dequeue() running %s', tostring(coroutine.running() or 'main'))
+ table.insert(self._waiters, fiber.running())
+ -- then let somebody else run
+ fiber.wait()
+ end
+ -- here we're sure this queue isn't empty
+ dbg('WaitQueue:Dequeue() calling Queue.Dequeue()')
+ return Queue.Dequeue(self)
+end
+
+function WaitQueue:close()
+ self._closed = true
+ -- close() is like Enqueueing an end marker. If there are waiting
+ -- consumers, give them a chance to see we're closed.
+ self:_wake_waiters()
+end
+
+return WaitQueue
diff --git a/indra/newview/scripts/lua/coro.lua b/indra/newview/scripts/lua/coro.lua
new file mode 100644
index 0000000000..616a797e95
--- /dev/null
+++ b/indra/newview/scripts/lua/coro.lua
@@ -0,0 +1,67 @@
+-- Manage Lua coroutines
+
+local coro = {}
+
+coro._coros = {}
+
+-- Launch a Lua coroutine: create and resume.
+-- Returns: new coroutine, values yielded or returned from initial resume()
+-- If initial resume() encountered an error, propagates the error.
+function coro.launch(func, ...)
+ local co = coroutine.create(func)
+ table.insert(coro._coros, co)
+ return co, coro.resume(co, ...)
+end
+
+-- resume() wrapper to propagate errors
+function coro.resume(co, ...)
+ -- if there's an idiom other than table.pack() to assign an arbitrary
+ -- number of return values, I don't yet know it
+ local ok_result = table.pack(coroutine.resume(co, ...))
+ if not ok_result[1] then
+ -- if [1] is false, then [2] is the error message
+ error(ok_result[2])
+ end
+ -- ok is true, whew, just return the rest of the values
+ return table.unpack(ok_result, 2)
+end
+
+-- yield to other coroutines even if you don't know whether you're in a
+-- created coroutine or the main coroutine
+function coro.yield(...)
+ if coroutine.running() then
+ -- this is a real coroutine, yield normally
+ return coroutine.yield(...)
+ else
+ -- This is the main coroutine: coroutine.yield() doesn't work.
+ -- But we can take a spin through previously-launched coroutines.
+ -- Walk a copy of coro._coros in case any of these coroutines launches
+ -- another: next() forbids creating new entries during traversal.
+ for co in coro._live_coros_iter, table.clone(coro._coros) do
+ coro.resume(co)
+ end
+ end
+end
+
+-- Walk coro._coros table, returning running or suspended coroutines.
+-- Once a coroutine becomes dead, remove it from _coros and don't return it.
+function coro._live_coros()
+ return coro._live_coros_iter, coro._coros
+end
+
+-- iterator function for _live_coros()
+function coro._live_coros_iter(t, idx)
+ local k, co = next(t, idx)
+ while k and coroutine.status(co) == 'dead' do
+-- t[k] = nil
+ -- See coro.yield(): sometimes we traverse a copy of _coros, but if we
+ -- discover a dead coroutine in that copy, delete it from _coros
+ -- anyway. Deleting it from a temporary copy does nothing.
+ coro._coros[k] = nil
+ coroutine.close(co)
+ k, co = next(t, k)
+ end
+ return co
+end
+
+return coro
diff --git a/indra/newview/scripts/lua/fiber.lua b/indra/newview/scripts/lua/fiber.lua
new file mode 100644
index 0000000000..9057e6c890
--- /dev/null
+++ b/indra/newview/scripts/lua/fiber.lua
@@ -0,0 +1,338 @@
+-- Organize Lua coroutines into fibers.
+
+-- In this usage, the difference between coroutines and fibers is that fibers
+-- have a scheduler. Yielding a fiber means allowing other fibers, plural, to
+-- run: it's more than just returning control to the specific Lua thread that
+-- resumed the running coroutine.
+
+-- fiber.launch() creates a new fiber ready to run.
+-- fiber.status() reports (augmented) status of the passed fiber: instead of
+-- 'suspended', it returns either 'ready' or 'waiting'
+-- fiber.yield() allows other fibers to run, but leaves the calling fiber
+-- ready to run.
+-- fiber.wait() marks the running fiber not ready, and resumes other fibers.
+-- fiber.wake() marks the designated suspended fiber ready to run, but does
+-- not yet resume it.
+-- fiber.run() runs all current fibers until all have terminated (successfully
+-- or with an error).
+
+local printf = require 'printf'
+-- local dbg = printf
+local function dbg(...) end
+local coro = require 'coro'
+
+local fiber = {}
+
+-- The tables in which we track fibers must have weak keys so dead fibers
+-- can be garbage-collected.
+local weak_values = {__mode='v'}
+local weak_keys = {__mode='k'}
+
+-- Track each current fiber as being either ready to run or not ready
+-- (waiting). wait() moves the running fiber from ready to waiting; wake()
+-- moves the designated fiber from waiting back to ready.
+-- The ready table is used as a list so yield() can go round robin.
+local ready = setmetatable({'main'}, weak_keys)
+-- The waiting table is used as a set because order doesn't matter.
+local waiting = setmetatable({}, weak_keys)
+
+-- Every fiber has a name, for diagnostic purposes. Names must be unique.
+-- A colliding name will be suffixed with an integer.
+-- Predefine 'main' with our marker so nobody else claims that name.
+local names = setmetatable({main='main'}, weak_keys)
+local byname = setmetatable({main='main'}, weak_values)
+-- each colliding name has its own distinct suffix counter
+local suffix = {}
+
+-- Specify a nullary idle() callback to be called whenever there are no ready
+-- fibers but there are waiting fibers. The idle() callback is responsible for
+-- changing zero or more waiting fibers to ready fibers by calling
+-- fiber.wake(), although a given call may leave them all still waiting.
+-- When there are no ready fibers, it's a good idea for the idle() function to
+-- return control to a higher-level execution agent. Simply returning without
+-- changing any fiber's status will spin the CPU.
+-- The idle() callback can return non-nil to exit fiber.run() with that value.
+function fiber._idle()
+ error('fiber.yield(): you must first call set_idle(nullary idle() function)')
+end
+
+function fiber.set_idle(func)
+ fiber._idle = func
+end
+
+-- Launch a new Lua fiber, ready to run.
+function fiber.launch(name, func, ...)
+ local args = table.pack(...)
+ local co = coroutine.create(function() func(table.unpack(args)) end)
+ -- a new fiber is ready to run
+ table.insert(ready, co)
+ local namekey = name
+ while byname[namekey] do
+ if not suffix[name] then
+ suffix[name] = 1
+ end
+ suffix[name] += 1
+ namekey = name .. tostring(suffix[name])
+ end
+ -- found a namekey not yet in byname: set it
+ byname[namekey] = co
+ -- and remember it as this fiber's name
+ names[co] = namekey
+-- dbg('launch(%s)', namekey)
+-- dbg('byname[%s] = %s', namekey, tostring(byname[namekey]))
+-- dbg('names[%s] = %s', tostring(co), names[co])
+-- dbg('ready[-1] = %s', tostring(ready[#ready]))
+end
+
+-- for debugging
+function format_all()
+ output = {}
+ table.insert(output, 'Ready fibers:' .. if next(ready) then '' else ' none')
+ for _, co in pairs(ready) do
+ table.insert(output, string.format(' %s: %s', fiber.get_name(co), fiber.status(co)))
+ end
+ table.insert(output, 'Waiting fibers:' .. if next(waiting) then '' else ' none')
+ for co in pairs(waiting) do
+ table.insert(output, string.format(' %s: %s', fiber.get_name(co), fiber.status(co)))
+ end
+ return table.concat(output, '\n')
+end
+
+function fiber.print_all()
+ print(format_all())
+end
+
+-- return either the running coroutine or, if called from the main thread,
+-- 'main'
+function fiber.running()
+ return coroutine.running() or 'main'
+end
+
+-- Query a fiber's name (nil for the running fiber)
+function fiber.get_name(co)
+ return names[co or fiber.running()] or 'unknown'
+end
+
+-- Query status of the passed fiber
+function fiber.status(co)
+ local running = coroutine.running()
+ if (not co) or co == running then
+ -- silly to ask the status of the running fiber: it's 'running'
+ return 'running'
+ end
+ if co ~= 'main' then
+ -- for any coroutine but main, consult coroutine.status()
+ local status = coroutine.status(co)
+ if status ~= 'suspended' then
+ return status
+ end
+ -- here co is suspended, answer needs further refinement
+ else
+ -- co == 'main'
+ if not running then
+ -- asking about 'main' from the main fiber
+ return 'running'
+ end
+ -- asking about 'main' from some other fiber, so presumably main is suspended
+ end
+ -- here we know co is suspended -- but is it ready to run?
+ if waiting[co] then
+ return 'waiting'
+ end
+ -- not waiting should imply ready: sanity check
+ if table.find(ready, co) then
+ return 'ready'
+ end
+ -- Calls within yield() between popping the next ready fiber and
+ -- re-appending it to the list are in this state. Once we're done
+ -- debugging yield(), we could reinstate either of the below.
+-- error(string.format('fiber.status(%s) is stumped', fiber.get_name(co)))
+-- print(string.format('*** fiber.status(%s) is stumped', fiber.get_name(co)))
+ return '(unknown)'
+end
+
+-- change the running fiber's status to waiting
+local function set_waiting()
+ -- if called from the main fiber, inject a 'main' marker into the list
+ co = fiber.running()
+ -- delete from ready list
+ local i = table.find(ready, co)
+ if i then
+ table.remove(ready, i)
+ end
+ -- add to waiting list
+ waiting[co] = true
+end
+
+-- Suspend the current fiber until some other fiber calls fiber.wake() on it
+function fiber.wait()
+ dbg('Fiber %q waiting', fiber.get_name())
+ set_waiting()
+ -- now yield to other fibers
+ fiber.yield()
+end
+
+-- Mark a suspended fiber as being ready to run
+function fiber.wake(co)
+ if not waiting[co] then
+ error(string.format('fiber.wake(%s) but status=%s, ready=%s, waiting=%s',
+ names[co], fiber.status(co), ready[co], waiting[co]))
+ end
+ -- delete from waiting list
+ waiting[co] = nil
+ -- add to end of ready list
+ table.insert(ready, co)
+ dbg('Fiber %q ready', fiber.get_name(co))
+ -- but don't yet resume it: that happens next time we reach yield()
+end
+
+-- pop and return the next not-dead fiber in the ready list, or nil if none remain
+local function live_ready_iter()
+ -- don't write:
+ -- for co in table.remove, ready, 1
+ -- because it would keep passing a new second parameter!
+ for co in function() return table.remove(ready, 1) end do
+ dbg('%s live_ready_iter() sees %s, status %s',
+ fiber.get_name(), fiber.get_name(co), fiber.status(co))
+ -- keep removing the head entry until we find one that's not dead,
+ -- discarding any dead coroutines along the way
+ if co == 'main' or coroutine.status(co) ~= 'dead' then
+ dbg('%s live_ready_iter() returning %s',
+ fiber.get_name(), fiber.get_name(co))
+ return co
+ end
+ end
+ dbg('%s live_ready_iter() returning nil', fiber.get_name())
+ return nil
+end
+
+-- prune the set of waiting fibers
+local function prune_waiting()
+ for waiter in pairs(waiting) do
+ if waiter ~= 'main' and coroutine.status(waiter) == 'dead' then
+ waiting[waiter] = nil
+ end
+ end
+end
+
+-- Run other ready fibers, leaving this one ready, returning after a cycle.
+-- Returns:
+-- * true, nil if there remain other live fibers, whether ready or waiting,
+-- but it's our turn to run
+-- * false, nil if this is the only remaining fiber
+-- * nil, x if configured idle() callback returns non-nil x
+local function scheduler()
+ dbg('scheduler():\n%s', format_all())
+ -- scheduler() is asymmetric because Lua distinguishes the main thread
+ -- from other coroutines. The main thread can't yield; it can only resume
+ -- other coroutines. So although an arbitrary coroutine could resume still
+ -- other arbitrary coroutines, it could NOT resume the main thread because
+ -- the main thread can't yield. Therefore, scheduler() delegates its real
+ -- processing to the main thread. If called from a coroutine, pass control
+ -- back to the main thread.
+ if coroutine.running() then
+ -- this is a real coroutine, yield normally to main thread
+ coroutine.yield()
+ -- main certainly still exists
+ return true
+ end
+
+ -- This is the main fiber: coroutine.yield() doesn't work.
+ -- Instead, resume each of the ready fibers.
+ -- Prune the set of waiting fibers after every time fiber business logic
+ -- runs (i.e. other fibers might have terminated or hit error), such as
+ -- here on entry.
+ prune_waiting()
+ local others, idle_stop
+ repeat
+ for co in live_ready_iter do
+ -- seize the opportunity to make sure the viewer isn't shutting down
+ LL.check_stop()
+ -- before we re-append co, is it the only remaining entry?
+ others = next(ready)
+ -- co is live, re-append it to the ready list
+ table.insert(ready, co)
+ if co == 'main' then
+ -- Since we know the caller is the main fiber, it's our turn.
+ -- Tell caller if there are other ready or waiting fibers.
+ return others or next(waiting)
+ end
+ -- not main, but some other ready coroutine:
+ -- use coro.resume() so we'll propagate any error encountered
+ coro.resume(co)
+ prune_waiting()
+ end
+ -- Here there are no ready fibers. Are there any waiting fibers?
+ if not next(waiting) then
+ return false
+ end
+ -- there are waiting fibers: call consumer's configured idle() function
+ idle_stop = fiber._idle()
+ if idle_stop ~= nil then
+ return nil, idle_stop
+ end
+ prune_waiting()
+ -- loop "forever", that is, until:
+ -- * main is ready, or
+ -- * there are neither ready fibers nor waiting fibers, or
+ -- * fiber._idle() returned non-nil
+ until false
+end
+
+-- Let other fibers run. This is useful in either of two cases:
+-- * fiber.wait() calls this to run other fibers while this one is waiting.
+-- fiber.yield() (and therefore fiber.wait()) works from the main thread as
+-- well as from explicitly-launched fibers, without the caller having to
+-- care.
+-- * A long-running fiber that doesn't often call fiber.wait() should sprinkle
+-- in fiber.yield() calls to interleave processing on other fibers.
+function fiber.yield()
+ -- The difference between this and fiber.run() is that fiber.yield()
+ -- assumes its caller has work to do. yield() returns to its caller as
+ -- soon as scheduler() pops this fiber from the ready list. fiber.run()
+ -- continues looping until all other fibers have terminated, or the
+ -- set_idle() callback tells it to stop.
+ local others, idle_done = scheduler()
+ -- scheduler() returns either if we're ready, or if idle_done ~= nil.
+ if idle_done ~= nil then
+ -- Returning normally from yield() means the caller can carry on with
+ -- its pending work. But in this case scheduler() returned because the
+ -- configured set_idle() function interrupted it -- not because we're
+ -- actually ready. Don't return normally.
+ error('fiber.set_idle() interrupted yield() with: ' .. tostring(idle_done))
+ end
+ -- We're ready! Just return to caller. In this situation we don't care
+ -- whether there are other ready fibers.
+end
+
+-- Run fibers until all but main have terminated: return nil.
+-- Or until configured idle() callback returns x ~= nil: return x.
+function fiber.run()
+ -- A fiber calling run() is not also doing other useful work. Remove the
+ -- calling fiber from the ready list. Otherwise yield() would keep seeing
+ -- that our caller is ready and return to us, instead of realizing that
+ -- all coroutines are waiting and call idle(). But don't say we're
+ -- waiting, either, because then when all other fibers have terminated
+ -- we'd call idle() forever waiting for something to make us ready again.
+ local i = table.find(ready, fiber.running())
+ if i then
+ table.remove(ready, i)
+ end
+ local others, idle_done
+ repeat
+ dbg('%s calling fiber.run() calling scheduler()', fiber.get_name())
+ others, idle_done = scheduler()
+ dbg("%s fiber.run()'s scheduler() returned %s, %s", fiber.get_name(),
+ tostring(others), tostring(idle_done))
+ until (not others)
+ dbg('%s fiber.run() done', fiber.get_name())
+ -- For whatever it's worth, put our own fiber back in the ready list.
+ table.insert(ready, fiber.running())
+ -- Once there are no more waiting fibers, and the only ready fiber is
+ -- us, return to caller. All previously-launched fibers are done. Possibly
+ -- the chunk is done, or the chunk may decide to launch a new batch of
+ -- fibers.
+ return idle_done
+end
+
+return fiber
diff --git a/indra/newview/scripts/lua/inspect.lua b/indra/newview/scripts/lua/inspect.lua
new file mode 100644
index 0000000000..9900a0b81b
--- /dev/null
+++ b/indra/newview/scripts/lua/inspect.lua
@@ -0,0 +1,371 @@
+local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local math = _tl_compat and _tl_compat.math or math; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table
+local inspect = {Options = {}, }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+inspect._VERSION = 'inspect.lua 3.1.0'
+inspect._URL = 'http://github.com/kikito/inspect.lua'
+inspect._DESCRIPTION = 'human-readable representations of tables'
+inspect._LICENSE = [[
+ MIT LICENSE
+
+ Copyright (c) 2022 Enrique García Cota
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+]]
+inspect.KEY = setmetatable({}, { __tostring = function() return 'inspect.KEY' end })
+inspect.METATABLE = setmetatable({}, { __tostring = function() return 'inspect.METATABLE' end })
+
+local tostring = tostring
+local rep = string.rep
+local match = string.match
+local char = string.char
+local gsub = string.gsub
+local fmt = string.format
+
+local _rawget
+if rawget then
+ _rawget = rawget
+else
+ _rawget = function(t, k) return t[k] end
+end
+
+local function rawpairs(t)
+ return next, t, nil
+end
+
+
+
+local function smartQuote(str)
+ if match(str, '"') and not match(str, "'") then
+ return "'" .. str .. "'"
+ end
+ return '"' .. gsub(str, '"', '\\"') .. '"'
+end
+
+
+local shortControlCharEscapes = {
+ ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
+ ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\127"] = "\\127",
+}
+local longControlCharEscapes = { ["\127"] = "\127" }
+for i = 0, 31 do
+ local ch = char(i)
+ if not shortControlCharEscapes[ch] then
+ shortControlCharEscapes[ch] = "\\" .. i
+ longControlCharEscapes[ch] = fmt("\\%03d", i)
+ end
+end
+
+local function escape(str)
+ return (gsub(gsub(gsub(str, "\\", "\\\\"),
+ "(%c)%f[0-9]", longControlCharEscapes),
+ "%c", shortControlCharEscapes))
+end
+
+local luaKeywords = {
+ ['and'] = true,
+ ['break'] = true,
+ ['do'] = true,
+ ['else'] = true,
+ ['elseif'] = true,
+ ['end'] = true,
+ ['false'] = true,
+ ['for'] = true,
+ ['function'] = true,
+ ['goto'] = true,
+ ['if'] = true,
+ ['in'] = true,
+ ['local'] = true,
+ ['nil'] = true,
+ ['not'] = true,
+ ['or'] = true,
+ ['repeat'] = true,
+ ['return'] = true,
+ ['then'] = true,
+ ['true'] = true,
+ ['until'] = true,
+ ['while'] = true,
+}
+
+local function isIdentifier(str)
+ return type(str) == "string" and
+ not not str:match("^[_%a][_%a%d]*$") and
+ not luaKeywords[str]
+end
+
+local flr = math.floor
+local function isSequenceKey(k, sequenceLength)
+ return type(k) == "number" and
+ flr(k) == k and
+ 1 <= (k) and
+ k <= sequenceLength
+end
+
+local defaultTypeOrders = {
+ ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
+ ['function'] = 5, ['userdata'] = 6, ['thread'] = 7,
+}
+
+local function sortKeys(a, b)
+ local ta, tb = type(a), type(b)
+
+
+ if ta == tb and (ta == 'string' or ta == 'number') then
+ return (a) < (b)
+ end
+
+ local dta = defaultTypeOrders[ta] or 100
+ local dtb = defaultTypeOrders[tb] or 100
+
+
+ return dta == dtb and ta < tb or dta < dtb
+end
+
+local function getKeys(t)
+
+ local seqLen = 1
+ while _rawget(t, seqLen) ~= nil do
+ seqLen = seqLen + 1
+ end
+ seqLen = seqLen - 1
+
+ local keys, keysLen = {}, 0
+ for k in rawpairs(t) do
+ if not isSequenceKey(k, seqLen) then
+ keysLen = keysLen + 1
+ keys[keysLen] = k
+ end
+ end
+ table.sort(keys, sortKeys)
+ return keys, keysLen, seqLen
+end
+
+local function countCycles(x, cycles)
+ if type(x) == "table" then
+ if cycles[x] then
+ cycles[x] = cycles[x] + 1
+ else
+ cycles[x] = 1
+ for k, v in rawpairs(x) do
+ countCycles(k, cycles)
+ countCycles(v, cycles)
+ end
+ countCycles(getmetatable(x), cycles)
+ end
+ end
+end
+
+local function makePath(path, a, b)
+ local newPath = {}
+ local len = #path
+ for i = 1, len do newPath[i] = path[i] end
+
+ newPath[len + 1] = a
+ newPath[len + 2] = b
+
+ return newPath
+end
+
+
+local function processRecursive(process,
+ item,
+ path,
+ visited)
+ if item == nil then return nil end
+ if visited[item] then return visited[item] end
+
+ local processed = process(item, path)
+ if type(processed) == "table" then
+ local processedCopy = {}
+ visited[item] = processedCopy
+ local processedKey
+
+ for k, v in rawpairs(processed) do
+ processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
+ if processedKey ~= nil then
+ processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
+ end
+ end
+
+ local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
+ if type(mt) ~= 'table' then mt = nil end
+ setmetatable(processedCopy, mt)
+ processed = processedCopy
+ end
+ return processed
+end
+
+local function puts(buf, str)
+ buf.n = buf.n + 1
+ buf[buf.n] = str
+end
+
+
+
+local Inspector = {}
+
+
+
+
+
+
+
+
+
+
+local Inspector_mt = { __index = Inspector }
+
+local function tabify(inspector)
+ puts(inspector.buf, inspector.newline .. rep(inspector.indent, inspector.level))
+end
+
+function Inspector:getId(v)
+ local id = self.ids[v]
+ local ids = self.ids
+ if not id then
+ local tv = type(v)
+ id = (ids[tv] or 0) + 1
+ ids[v], ids[tv] = id, id
+ end
+ return tostring(id)
+end
+
+function Inspector:putValue(v)
+ local buf = self.buf
+ local tv = type(v)
+ if tv == 'string' then
+ puts(buf, smartQuote(escape(v)))
+ elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or
+ tv == 'cdata' or tv == 'ctype' then
+ puts(buf, tostring(v))
+ elseif tv == 'table' and not self.ids[v] then
+ local t = v
+
+ if t == inspect.KEY or t == inspect.METATABLE then
+ puts(buf, tostring(t))
+ elseif self.level >= self.depth then
+ puts(buf, '{...}')
+ else
+ if self.cycles[t] > 1 then puts(buf, fmt('<%d>', self:getId(t))) end
+
+ local keys, keysLen, seqLen = getKeys(t)
+
+ puts(buf, '{')
+ self.level = self.level + 1
+
+ for i = 1, seqLen + keysLen do
+ if i > 1 then puts(buf, ',') end
+ if i <= seqLen then
+ puts(buf, ' ')
+ self:putValue(t[i])
+ else
+ local k = keys[i - seqLen]
+ tabify(self)
+ if isIdentifier(k) then
+ puts(buf, k)
+ else
+ puts(buf, "[")
+ self:putValue(k)
+ puts(buf, "]")
+ end
+ puts(buf, ' = ')
+ self:putValue(t[k])
+ end
+ end
+
+ local mt = getmetatable(t)
+ if type(mt) == 'table' then
+ if seqLen + keysLen > 0 then puts(buf, ',') end
+ tabify(self)
+ puts(buf, '<metatable> = ')
+ self:putValue(mt)
+ end
+
+ self.level = self.level - 1
+
+ if keysLen > 0 or type(mt) == 'table' then
+ tabify(self)
+ elseif seqLen > 0 then
+ puts(buf, ' ')
+ end
+
+ puts(buf, '}')
+ end
+
+ else
+ puts(buf, fmt('<%s %d>', tv, self:getId(v)))
+ end
+end
+
+
+
+
+function inspect.inspect(root, options)
+ options = options or {}
+
+ local depth = options.depth or (math.huge)
+ local newline = options.newline or '\n'
+ local indent = options.indent or ' '
+ local process = options.process
+
+ if process then
+ root = processRecursive(process, root, {}, {})
+ end
+
+ local cycles = {}
+ countCycles(root, cycles)
+
+ local inspector = setmetatable({
+ buf = { n = 0 },
+ ids = {},
+ cycles = cycles,
+ depth = depth,
+ level = 0,
+ newline = newline,
+ indent = indent,
+ }, Inspector_mt)
+
+ inspector:putValue(root)
+
+ return table.concat(inspector.buf)
+end
+
+setmetatable(inspect, {
+ __call = function(_, root, options)
+ return inspect.inspect(root, options)
+ end,
+})
+
+return inspect
diff --git a/indra/newview/scripts/lua/leap.lua b/indra/newview/scripts/lua/leap.lua
new file mode 100644
index 0000000000..ade91789f0
--- /dev/null
+++ b/indra/newview/scripts/lua/leap.lua
@@ -0,0 +1,446 @@
+-- Lua implementation of LEAP (LLSD Event API Plugin) protocol
+--
+-- This module supports Lua scripts run by the Second Life viewer.
+--
+-- LEAP protocol passes LLSD objects, converted to/from Lua tables, in both
+-- directions. A typical LLSD object is a map containing keys 'pump' and
+-- 'data'.
+--
+-- The viewer's Lua post_to(pump, data) function posts 'data' to the
+-- LLEventPump 'pump'. This is typically used to engage an LLEventAPI method.
+--
+-- Similarly, the viewer gives each Lua script its own LLEventPump with a
+-- unique name. That name is returned by get_event_pumps(). Every event
+-- received on that LLEventPump is queued for retrieval by get_event_next(),
+-- which returns (pump, data): the name of the LLEventPump on which the event
+-- was received and the received event data. When the queue is empty,
+-- get_event_next() blocks the calling Lua script until the next event is
+-- received.
+--
+-- Usage:
+-- 1. Launch some number of Lua coroutines. The code in each coroutine may
+-- call leap.send(), leap.request() or leap.generate(). leap.send() returns
+-- immediately ("fire and forget"). leap.request() blocks the calling
+-- coroutine until it receives and returns the viewer's response to its
+-- request. leap.generate() expects an arbitrary number of responses to the
+-- original request.
+-- 2. To handle events from the viewer other than direct responses to
+-- requests, instantiate a leap.WaitFor object with a filter(pump, data)
+-- override method that returns non-nil for desired events. A coroutine may
+-- call wait() on any such WaitFor.
+-- 3. Once the coroutines have been launched, call leap.process() on the main
+-- coroutine. process() retrieves incoming events from the viewer and
+-- dispatches them to waiting request() or generate() calls, or to
+-- appropriate WaitFor instances. process() returns when either
+-- get_event_next() raises an error or the viewer posts nil to the script's
+-- reply pump to indicate it's done.
+-- 4. Alternatively, a running coroutine may call leap.done() to break out of
+-- leap.process(). process() won't notice until the next event from the
+-- viewer, though.
+
+local fiber = require('fiber')
+local ErrorQueue = require('ErrorQueue')
+local function dbg(...) end
+-- local dbg = require('printf')
+
+local leap = {}
+
+-- reply: string name of reply LLEventPump. Any events the viewer posts to
+-- this pump will be queued for get_event_next(). We usually specify it as the
+-- reply pump for requests to internal viewer services.
+-- command: string name of command LLEventPump. post_to(command, ...)
+-- engages LLLeapListener operations such as listening on a specified other
+-- LLEventPump, etc.
+local reply, command = LL.get_event_pumps()
+-- Dict of features added to the LEAP protocol since baseline implementation.
+-- Before engaging a new feature that might break an older viewer, we can
+-- check for the presence of that feature key. This table is solely about the
+-- LEAP protocol itself, the way we communicate with the viewer. To discover
+-- whether a given listener exists, or supports a particular operation, use
+-- command's "getAPI" operation.
+-- For Lua, command's "getFeatures" operation suffices?
+-- leap._features = {}
+
+-- Each outstanding request() or generate() call has a corresponding
+-- WaitForReqid object (later in this module) to handle the
+-- response(s). If an incoming event contains an echoed ["reqid"] key,
+-- we can look up the appropriate WaitForReqid object more efficiently
+-- in a dict than by tossing such objects into the usual waitfors list.
+-- Note: the ["reqid"] must be unique, otherwise we could end up
+-- replacing an earlier WaitForReqid object in pending with a
+-- later one. That means that no incoming event will ever be given to
+-- the old WaitForReqid object. Any coroutine waiting on the discarded
+-- WaitForReqid object would therefore wait forever.
+-- pending is NOT a weak table because the caller of request() or generate()
+-- never sees the WaitForReqid object. pending holds the only reference, so
+-- it should NOT be garbage-collected.
+pending = {}
+-- Our consumer will instantiate some number of WaitFor subclass objects.
+-- As these are traversed in descending priority order, we must keep
+-- them in a list.
+-- Anyone who instantiates a WaitFor subclass object should retain a reference
+-- to it. Once the consuming script drops the reference, allow Lua to
+-- garbage-collect the WaitFor despite its entry in waitfors.
+local weak_values = {__mode='v'}
+waitfors = setmetatable({}, weak_values)
+-- It has been suggested that we should use UUIDs as ["reqid"] values,
+-- since UUIDs are guaranteed unique. However, as the "namespace" for
+-- ["reqid"] values is our very own reply pump, we can get away with
+-- an integer.
+leap._reqid = 0
+-- break leap.process() loop
+leap._done = false
+
+-- get the name of the reply pump
+function leap.replypump()
+ return reply
+end
+
+-- get the name of the command pump
+function leap.cmdpump()
+ return command
+end
+
+-- Fire and forget. Send the specified request LLSD, expecting no reply.
+-- In fact, should the request produce an eventual reply, it will be
+-- treated as an unsolicited event.
+--
+-- See also request(), generate().
+function leap.send(pump, data, reqid)
+ local data = data
+ if type(data) == 'table' then
+ data = table.clone(data)
+ data['reply'] = reply
+ if reqid ~= nil then
+ data['reqid'] = reqid
+ end
+ end
+ dbg('leap.send(%s, %s) calling post_on()', pump, data)
+ LL.post_on(pump, data)
+end
+
+-- common setup code shared by request() and generate()
+local function requestSetup(pump, data)
+ -- invent a new, unique reqid
+ leap._reqid += 1
+ local reqid = leap._reqid
+ -- Instantiate a new WaitForReqid object. The priority is irrelevant
+ -- because, unlike the WaitFor base class, WaitForReqid does not
+ -- self-register on our waitfors list. Instead, capture the new
+ -- WaitForReqid object in pending so dispatch() can find it.
+ local waitfor = leap.WaitForReqid:new(reqid)
+ pending[reqid] = waitfor
+ -- Pass reqid to send() to stamp it into (a copy of) the request data.
+ dbg('requestSetup(%s, %s)', pump, data)
+ leap.send(pump, data, reqid)
+ return reqid, waitfor
+end
+
+-- Send the specified request LLSD, expecting exactly one reply. Block
+-- the calling coroutine until we receive that reply.
+--
+-- Every request() (or generate()) LLSD block we send will get stamped
+-- with a distinct ["reqid"] value. The requested event API must echo the
+-- same ["reqid"] field in each reply associated with that request. This way
+-- we can correctly dispatch interleaved replies from different requests.
+--
+-- If the desired event API doesn't support the ["reqid"] echo convention,
+-- you should use send() instead -- since request() or generate() would
+-- wait forever for a reply stamped with that ["reqid"] -- and intercept
+-- any replies using WaitFor.
+--
+-- Unless the request data already contains a ["reply"] key, we insert
+-- reply=self.replypump to try to ensure that the expected reply will be
+-- returned over the socket.
+--
+-- See also send(), generate().
+function leap.request(pump, data)
+ local reqid, waitfor = requestSetup(pump, data)
+ dbg('leap.request(%s, %s) about to wait on %s', pump, data, tostring(waitfor))
+ local ok, response = pcall(waitfor.wait, waitfor)
+ dbg('leap.request(%s, %s) got %s: %s', pump, data, ok, response)
+ -- kill off temporary WaitForReqid object, even if error
+ pending[reqid] = nil
+ if ok then
+ return response
+ else
+ error(response)
+ end
+end
+
+-- Send the specified request LLSD, expecting an arbitrary number of replies.
+-- Each one is yielded on receipt. If you omit checklast, this is an infinite
+-- generator; it's up to the caller to recognize when the last reply has been
+-- received, and stop resuming for more.
+--
+-- If you pass checklast=<callable accepting(event)>, each response event is
+-- passed to that callable (after the yield). When the callable returns
+-- True, the generator terminates in the usual way.
+--
+-- See request() remarks about ["reqid"].
+function leap.generate(pump, data, checklast)
+ -- Invent a new, unique reqid. Arrange to handle incoming events
+ -- bearing that reqid. Stamp the outbound request with that reqid, and
+ -- send it.
+ local reqid, waitfor = requestSetup(pump, data)
+ local ok, response, resumed_with
+ repeat
+ ok, response = pcall(waitfor.wait, waitfor)
+ if not ok then
+ break
+ end
+ -- can resume(false) to terminate generate() and clean up
+ resumed_with = coroutine.yield(response)
+ until (checklast and checklast(response)) or (resumed_with == false)
+ -- If we break the above loop, whether or not due to error, clean up.
+ pending[reqid] = nil
+ if not ok then
+ error(response)
+ end
+end
+
+local function cleanup(message)
+ -- we're done: clean up all pending coroutines
+ for i, waitfor in pairs(pending) do
+ waitfor:close()
+ end
+ for i, waitfor in pairs(waitfors) do
+ waitfor:close()
+ end
+end
+
+-- Handle an incoming (pump, data) event with no recognizable ['reqid']
+local function unsolicited(pump, data)
+ -- we maintain waitfors in descending priority order, so the first waitfor
+ -- to claim this event is the one with the highest priority
+ for i, waitfor in pairs(waitfors) do
+ dbg('unsolicited() checking %s', waitfor.name)
+ if waitfor:handle(pump, data) then
+ return
+ end
+ end
+ LL.print_debug(string.format('unsolicited(%s, %s) discarding unclaimed event', pump, data))
+end
+
+-- Route incoming (pump, data) event to the appropriate waiting coroutine.
+local function dispatch(pump, data)
+ local reqid = data['reqid']
+ -- if the response has no 'reqid', it's not from request() or generate()
+ if reqid == nil then
+ return unsolicited(pump, data)
+ end
+ -- have reqid; do we have a WaitForReqid?
+ local waitfor = pending[reqid]
+ if waitfor == nil then
+ return unsolicited(pump, data)
+ end
+ -- found the right WaitForReqid object, let it handle the event
+ waitfor:handle(pump, data)
+end
+
+-- We configure fiber.set_idle() function. fiber.yield() calls the configured
+-- idle callback whenever there are waiting fibers but no ready fibers. In
+-- our case, that means it's time to fetch another incoming viewer event.
+fiber.set_idle(function ()
+ -- If someone has called leap.done(), then tell fiber.yield() to break loop.
+ if leap._done then
+ cleanup('done')
+ return 'done'
+ end
+ dbg('leap.idle() calling get_event_next()')
+ local ok, pump, data = pcall(LL.get_event_next)
+ dbg('leap.idle() got %s: %s, %s', ok, pump, data)
+ -- ok false means get_event_next() raised a Lua error, pump is message
+ if not ok then
+ cleanup(pump)
+ error(pump)
+ end
+ -- data nil means get_event_next() returned (pump, LLSD()) to indicate done
+ if not data then
+ cleanup('end')
+ return 'end'
+ end
+ -- got a real pump, data pair
+ dispatch(pump, data)
+ -- return to fiber.yield(): any incoming message might result in one or
+ -- more fibers becoming ready
+end)
+
+function leap.done()
+ leap._done = true
+end
+
+-- called by WaitFor.enable()
+local function registerWaitFor(waitfor)
+ table.insert(waitfors, waitfor)
+ -- keep waitfors sorted in descending order of specified priority
+ table.sort(waitfors,
+ function (lhs, rhs) return lhs.priority > rhs.priority end)
+end
+
+-- called by WaitFor.disable()
+local function unregisterWaitFor(waitfor)
+ for i, w in pairs(waitfors) do
+ if w == waitfor then
+ waitfors[i] = nil
+ break
+ end
+ end
+end
+
+-- ******************************************************************************
+-- WaitFor and friends
+-- ******************************************************************************
+
+-- An unsolicited event is handled by the highest-priority WaitFor subclass
+-- object willing to accept it. If no such object is found, the unsolicited
+-- event is discarded.
+--
+-- * First, instantiate a WaitFor subclass object to register its interest in
+-- some incoming event(s). WaitFor instances are self-registering; merely
+-- instantiating the object suffices.
+-- * Any coroutine may call a given WaitFor object's wait() method. This blocks
+-- the calling coroutine until a suitable event arrives.
+-- * WaitFor's constructor accepts a float priority. Every incoming event
+-- (other than those claimed by request() or generate()) is passed to each
+-- extant WaitFor.filter() method in descending priority order. The first
+-- such filter() to return nontrivial data claims that event.
+-- * At that point, the blocked wait() call on that WaitFor object returns the
+-- item returned by filter().
+-- * WaitFor contains a queue. Multiple arriving events claimed by that WaitFor
+-- object's filter() method are added to the queue. Naturally, until the
+-- queue is empty, calling wait() immediately returns the front entry.
+--
+-- It's reasonable to instantiate a WaitFor subclass whose filter() method
+-- unconditionally returns the incoming event, and whose priority places it
+-- last in the list. This object will enqueue every unsolicited event left
+-- unclaimed by other WaitFor subclass objects.
+--
+-- It's not strictly necessary to associate a WaitFor object with exactly one
+-- coroutine. You might have multiple "worker" coroutines drawing from the same
+-- WaitFor object, useful if the work being done per event might itself involve
+-- "blocking" operations. Or a given coroutine might sample a number of WaitFor
+-- objects in round-robin fashion... etc. etc. Nonetheless, it's
+-- straightforward to designate one coroutine for each WaitFor object.
+
+-- --------------------------------- WaitFor ---------------------------------
+leap.WaitFor = { _id=0 }
+
+function leap.WaitFor.tostring(self)
+ -- Lua (sub)classes have no name; can't prefix with that
+ return self.name
+end
+
+function leap.WaitFor:new(priority, name)
+ local obj = setmetatable({__tostring=leap.WaitFor.tostring}, self)
+ self.__index = self
+
+ obj.priority = priority
+ if name then
+ obj.name = name
+ else
+ self._id += 1
+ obj.name = 'WaitFor' .. self._id
+ end
+ obj._queue = ErrorQueue:new()
+ obj._registered = false
+ -- if no priority, then don't enable() - remember 0 is truthy
+ if priority then
+ obj:enable()
+ end
+
+ return obj
+end
+
+-- Re-enable a disable()d WaitFor object. New WaitFor objects are
+-- enable()d by default.
+function leap.WaitFor:enable()
+ if not self._registered then
+ registerWaitFor(self)
+ self._registered = true
+ end
+end
+
+-- Disable an enable()d WaitFor object.
+function leap.WaitFor:disable()
+ if self._registered then
+ unregisterWaitFor(self)
+ self._registered = false
+ end
+end
+
+-- Block the calling coroutine until a suitable unsolicited event (one
+-- for which filter() returns the event) arrives.
+function leap.WaitFor:wait()
+ dbg('%s about to wait', self.name)
+ local item = self._queue:Dequeue()
+ dbg('%s got %s', self.name, item)
+ return item
+end
+
+-- Override filter() to examine the incoming event in whatever way
+-- makes sense.
+--
+-- Return nil to ignore this event.
+--
+-- To claim the event, return the item you want placed in the queue.
+-- Typically you'd write:
+-- return data
+-- or perhaps
+-- return {pump=pump, data=data}
+-- or some variation.
+function leap.WaitFor:filter(pump, data)
+ error('You must override the WaitFor.filter() method')
+end
+
+-- called by unsolicited() for each WaitFor in waitfors
+function leap.WaitFor:handle(pump, data)
+ local item = self:filter(pump, data)
+ dbg('%s.filter() returned %s', self.name, item)
+ -- if this item doesn't pass the filter, we're not interested
+ if not item then
+ return false
+ end
+ -- okay, filter() claims this event
+ self:process(item)
+ return true
+end
+
+-- called by WaitFor:handle() for an accepted event
+function leap.WaitFor:process(item)
+ self._queue:Enqueue(item)
+end
+
+-- called by cleanup() at end
+function leap.WaitFor:close()
+ self._queue:close()
+end
+
+-- called by leap.process() when get_event_next() raises an error
+function leap.WaitFor:exception(message)
+ LL.print_warning(self.name .. ' error: ' .. message)
+ self._queue:Error(message)
+end
+
+-- ------------------------------ WaitForReqid -------------------------------
+leap.WaitForReqid = leap.WaitFor:new()
+
+function leap.WaitForReqid:new(reqid)
+ -- priority is meaningless, since this object won't be added to the
+ -- priority-sorted waitfors list. Use the reqid as the debugging name
+ -- string.
+ local obj = leap.WaitFor:new(nil, 'WaitForReqid(' .. reqid .. ')')
+ setmetatable(obj, self)
+ self.__index = self
+
+ return obj
+end
+
+function leap.WaitForReqid:filter(pump, data)
+ -- Because we expect to directly look up the WaitForReqid object of
+ -- interest based on the incoming ["reqid"] value, it's not necessary
+ -- to test the event again. Accept every such event.
+ return data
+end
+
+return leap
diff --git a/indra/newview/scripts/lua/luafloater_demo.xml b/indra/newview/scripts/lua/luafloater_demo.xml
new file mode 100644
index 0000000000..b2273d7718
--- /dev/null
+++ b/indra/newview/scripts/lua/luafloater_demo.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="300"
+ layout="topleft"
+ name="lua_demo"
+ title="LUA"
+ width="320">
+ <check_box
+ height="16"
+ label="Disable button"
+ layout="topleft"
+ top_pad="35"
+ left="5"
+ name="disable_ctrl"
+ width="146" />
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|bottom"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ max_length_bytes="50"
+ name="openfloater_cmd"
+ top_delta="25"
+ width="100" />
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Open floater"
+ layout="topleft"
+ name="open_btn"
+ top_delta="25"
+ width="100" >
+ </button>
+ <text
+ type="string"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ top="30"
+ left_delta="170"
+ name="title_lbl">
+ Select title
+ </text>
+ <combo_box
+ follows="top|left"
+ height="23"
+ name="title_cmb"
+ top_pad="5"
+ width="100">
+ <combo_box.item
+ label="LUA"
+ value="LUA" />
+ <combo_box.item
+ label="LUA floater"
+ value="LUA floater" />
+ <combo_box.item
+ label="LUA-U title"
+ value="LUA-U title" />
+ </combo_box>
+ <text
+ type="string"
+ follows="left|bottom"
+ height="10"
+ layout="topleft"
+ top_delta="50"
+ name="show_time_lbl">
+ Double click me
+ </text>
+ <text
+ type="string"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ top_pad="15"
+ font="SansSerif"
+ text_color="white"
+ left_delta="15"
+ name="time_lbl"/>
+ <text_editor
+ follows="top|left"
+ font="SansSerif"
+ height="140"
+ left="5"
+ enabled="false"
+ name="events_editor"
+ top_pad="15"
+ word_wrap="true"
+ max_length="65536"
+ width="310"/>
+</floater>
diff --git a/indra/newview/scripts/lua/luafloater_gesture_list.xml b/indra/newview/scripts/lua/luafloater_gesture_list.xml
new file mode 100644
index 0000000000..a38a04eed0
--- /dev/null
+++ b/indra/newview/scripts/lua/luafloater_gesture_list.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="150"
+ layout="topleft"
+ name="lua_gestures"
+ title="Gestures"
+ width="320">
+ <scroll_list
+ draw_heading="false"
+ left="5"
+ width="310"
+ height="115"
+ top_pad ="25"
+ follows="all"
+ name="gesture_list">
+ <scroll_list.columns
+ name="gesture_name"
+ label="Name"/>
+ </scroll_list>
+</floater>
diff --git a/indra/newview/scripts/lua/printf.lua b/indra/newview/scripts/lua/printf.lua
new file mode 100644
index 0000000000..584cd4f391
--- /dev/null
+++ b/indra/newview/scripts/lua/printf.lua
@@ -0,0 +1,19 @@
+-- printf(...) is short for print(string.format(...))
+
+local inspect = require 'inspect'
+
+local function printf(...)
+ -- string.format() only handles numbers and strings.
+ -- Convert anything else to string using the inspect module.
+ local args = {}
+ for _, arg in pairs(table.pack(...)) do
+ if type(arg) == 'number' or type(arg) == 'string' then
+ table.insert(args, arg)
+ else
+ table.insert(args, inspect(arg))
+ end
+ end
+ print(string.format(table.unpack(args)))
+end
+
+return printf
diff --git a/indra/newview/scripts/lua/qtest.lua b/indra/newview/scripts/lua/qtest.lua
new file mode 100644
index 0000000000..009446d0c3
--- /dev/null
+++ b/indra/newview/scripts/lua/qtest.lua
@@ -0,0 +1,146 @@
+-- Exercise the Queue, WaitQueue, ErrorQueue family
+
+Queue = require('Queue')
+WaitQueue = require('WaitQueue')
+ErrorQueue = require('ErrorQueue')
+util = require('util')
+
+inspect = require('inspect')
+
+-- resume() wrapper to propagate errors
+function resume(co, ...)
+ -- if there's an idiom other than table.pack() to assign an arbitrary
+ -- number of return values, I don't yet know it
+ local ok_result = table.pack(coroutine.resume(co, ...))
+ if not ok_result[1] then
+ -- if [1] is false, then [2] is the error message
+ error(ok_result[2])
+ end
+ -- ok is true, whew, just return the rest of the values
+ return table.unpack(ok_result, 2)
+end
+
+-- ------------------ Queue variables are instance-specific ------------------
+q1 = Queue:new()
+q2 = Queue:new()
+
+q1:Enqueue(17)
+
+assert(not q1:IsEmpty())
+assert(q2:IsEmpty())
+assert(q1:Dequeue() == 17)
+assert(q1:Dequeue() == nil)
+assert(q2:Dequeue() == nil)
+
+-- ----------------------------- test WaitQueue ------------------------------
+q1 = WaitQueue:new()
+q2 = WaitQueue:new()
+result = {}
+values = { 1, 1, 2, 3, 5, 8, 13, 21 }
+
+for i, value in pairs(values) do
+ q1:Enqueue(value)
+end
+-- close() while not empty tests that queue drains before reporting done
+q1:close()
+
+-- ensure that WaitQueue instance variables are in fact independent
+assert(q2:IsEmpty())
+
+-- consumer() coroutine to pull from the passed q until closed
+function consumer(desc, q)
+ print(string.format('consumer(%s) start', desc))
+ local value = q:Dequeue()
+ while value ~= nil do
+ print(string.format('consumer(%s) got %q', desc, value))
+ table.insert(result, value)
+ value = q:Dequeue()
+ end
+ print(string.format('consumer(%s) done', desc))
+end
+
+-- run two consumers
+coa = coroutine.create(consumer)
+cob = coroutine.create(consumer)
+-- Since consumer() doesn't yield while it can still retrieve values,
+-- consumer(a) will dequeue all values from q1 and return when done.
+resume(coa, 'a', q1)
+-- consumer(b) will wake up to find the queue empty and closed.
+resume(cob, 'b', q1)
+coroutine.close(coa)
+coroutine.close(cob)
+
+print('values:', inspect(values))
+print('result:', inspect(result))
+
+assert(util.equal(values, result))
+
+-- try incrementally enqueueing values
+q3 = WaitQueue:new()
+result = {}
+values = { 'This', 'is', 'a', 'test', 'script' }
+
+coros = {}
+for _, name in {'a', 'b'} do
+ local coro = coroutine.create(consumer)
+ table.insert(coros, coro)
+ -- Resuming both coroutines should leave them both waiting for a queue item.
+ resume(coro, name, q3)
+end
+
+for _, s in pairs(values) do
+ print(string.format('Enqueue(%q)', s))
+ q3:Enqueue(s)
+end
+q3:close()
+
+function joinall(coros)
+ local running
+ local errors = 0
+ repeat
+ running = false
+ for i, coro in pairs(coros) do
+ if coroutine.status(coro) == 'suspended' then
+ running = true
+ -- directly call coroutine.resume() instead of our resume()
+ -- wrapper because we explicitly check for errors here
+ local ok, message = coroutine.resume(coro)
+ if not ok then
+ print('*** ' .. message)
+ errors += 1
+ end
+ if coroutine.status(coro) == 'dead' then
+ coros[i] = nil
+ end
+ end
+ end
+ until not running
+ return errors
+end
+
+joinall(coros)
+
+print(string.format('%q', table.concat(result, ' ')))
+assert(util.equal(values, result))
+
+-- ----------------------------- test ErrorQueue -----------------------------
+q4 = ErrorQueue:new()
+result = {}
+values = { 'This', 'is', 'a', 'test', 'script' }
+
+coros = {}
+for _, name in {'a', 'b'} do
+ local coro = coroutine.create(consumer)
+ table.insert(coros, coro)
+ -- Resuming both coroutines should leave them both waiting for a queue item.
+ resume(coro, name, q4)
+end
+
+for i = 1, 4 do
+ print(string.format('Enqueue(%q)', values[i]))
+ q4:Enqueue(values[i])
+end
+q4:Error('something went wrong')
+
+assert(joinall(coros) == 2)
+
diff --git a/indra/newview/scripts/lua/startup.lua b/indra/newview/scripts/lua/startup.lua
new file mode 100644
index 0000000000..4311bb9a60
--- /dev/null
+++ b/indra/newview/scripts/lua/startup.lua
@@ -0,0 +1,101 @@
+-- query, wait for or mandate a particular viewer startup state
+
+-- During startup, the viewer steps through a sequence of numbered (and named)
+-- states. This can be used to detect when, for instance, the login screen is
+-- displayed, or when the viewer has finished logging in and is fully
+-- in-world.
+
+local fiber = require 'fiber'
+local leap = require 'leap'
+local inspect = require 'inspect'
+local function dbg(...) end
+-- local dbg = require 'printf'
+
+-- ---------------------------------------------------------------------------
+-- Get the list of startup states from the viewer.
+local bynum = leap.request('LLStartUp', {op='getStateTable'})['table']
+
+local byname = setmetatable(
+ {},
+ -- set metatable to throw an error if you look up invalid state name
+ {__index=function(t, k)
+ local v = t[k]
+ if v then
+ return v
+ end
+ error(string.format('startup module passed invalid state %q', k), 2)
+ end})
+
+-- derive byname as a lookup table to find the 0-based index for a given name
+for i, name in pairs(bynum) do
+ -- the viewer's states are 0-based, not 1-based like Lua indexes
+ byname[name] = i - 1
+end
+-- dbg('startup states: %s', inspect(byname))
+
+-- specialize a WaitFor to track the viewer's startup state
+local startup_pump = 'StartupState'
+local waitfor = leap.WaitFor:new(0, startup_pump)
+function waitfor:filter(pump, data)
+ if pump == self.name then
+ return data
+ end
+end
+
+function waitfor:process(data)
+ -- keep updating startup._state for interested parties
+ startup._state = data.str
+ dbg('startup updating state to %q', data.str)
+ -- now pass data along to base-class method to queue
+ leap.WaitFor.process(self, data)
+end
+
+-- listen for StartupState events
+leap.request(leap.cmdpump(),
+ {op='listen', source=startup_pump, listener='startup.lua', tweak=true})
+-- poke LLStartUp to make sure we get an event
+leap.send('LLStartUp', {op='postStartupState'})
+
+-- ---------------------------------------------------------------------------
+startup = {}
+
+-- wait for response from postStartupState
+while not startup._state do
+ dbg('startup.state() waiting for first StartupState event')
+ waitfor:wait()
+end
+
+-- return a list of all known startup states
+function startup.list()
+ return bynum
+end
+
+-- report whether state with string name 'left' is before string name 'right'
+function startup.before(left, right)
+ return byname[left] < byname[right]
+end
+
+-- report the viewer's current startup state
+function startup.state()
+ return startup._state
+end
+
+-- error if script is called before specified state string name
+function startup.ensure(state)
+ if startup.before(startup.state(), state) then
+ -- tell error() to pretend this error was thrown by our caller
+ error('must not be called before startup state ' .. state, 2)
+ end
+end
+
+-- block calling fiber until viewer has reached state with specified string name
+function startup.wait(state)
+ dbg('startup.wait(%q)', state)
+ while startup.before(startup.state(), state) do
+ local item = waitfor:wait()
+ dbg('startup.wait(%q) sees %s', state, item)
+ end
+end
+
+return startup
+
diff --git a/indra/newview/scripts/lua/test_LLFloaterAbout.lua b/indra/newview/scripts/lua/test_LLFloaterAbout.lua
new file mode 100644
index 0000000000..6bbf61982d
--- /dev/null
+++ b/indra/newview/scripts/lua/test_LLFloaterAbout.lua
@@ -0,0 +1,6 @@
+-- test LLFloaterAbout
+
+LLFloaterAbout = require('LLFloaterAbout')
+inspect = require('inspect')
+
+print(inspect(LLFloaterAbout.getInfo()))
diff --git a/indra/newview/scripts/lua/test_LLGesture.lua b/indra/newview/scripts/lua/test_LLGesture.lua
new file mode 100644
index 0000000000..1cce674565
--- /dev/null
+++ b/indra/newview/scripts/lua/test_LLGesture.lua
@@ -0,0 +1,26 @@
+-- exercise LLGesture API
+
+LLGesture = require 'LLGesture'
+inspect = require 'inspect'
+
+
+-- getActiveGestures() returns {<UUID>: {name, playing, trigger}}
+gestures_uuid = LLGesture.getActiveGestures()
+-- convert to {<name>: <uuid>}
+gestures = {}
+for uuid, info in pairs(gestures_uuid) do
+ gestures[info.name] = uuid
+end
+-- now run through the list
+for name, uuid in pairs(gestures) do
+ if name == 'afk' then
+ -- afk has a long timeout, and isn't interesting to look at
+ continue
+ end
+ print(name)
+ LLGesture.startGesture(uuid)
+ repeat
+ LL.sleep(1)
+ until not LLGesture.isGesturePlaying(uuid)
+end
+print('Done.')
diff --git a/indra/newview/scripts/lua/test_luafloater_demo.lua b/indra/newview/scripts/lua/test_luafloater_demo.lua
new file mode 100644
index 0000000000..ab638dcdd1
--- /dev/null
+++ b/indra/newview/scripts/lua/test_luafloater_demo.lua
@@ -0,0 +1,77 @@
+XML_FILE_PATH = LL.abspath("luafloater_demo.xml")
+
+scriptparts = string.split(LL.source_path(), '/')
+scriptname = scriptparts[#scriptparts]
+print('Running ' .. scriptname)
+
+leap = require 'leap'
+fiber = require 'fiber'
+startup = require 'startup'
+
+--event pump for sending actions to the floater
+local COMMAND_PUMP_NAME = ""
+local reqid
+--table of floater UI events
+event_list=leap.request("LLFloaterReg", {op="getFloaterEvents"}).events
+
+local function _event(event_name)
+ if not table.find(event_list, event_name) then
+ LL.print_warning("Incorrect event name: " .. event_name)
+ end
+ return event_name
+end
+
+function post(action)
+ leap.send(COMMAND_PUMP_NAME, action)
+end
+
+function getCurrentTime()
+ local currentTime = os.date("*t")
+ return string.format("%02d:%02d:%02d", currentTime.hour, currentTime.min, currentTime.sec)
+end
+
+function handleEvents(event_data)
+ post({action="add_text", ctrl_name="events_editor", value = event_data})
+ if event_data.event == _event("commit") then
+ if event_data.ctrl_name == "disable_ctrl" then
+ post({action="set_enabled", ctrl_name="open_btn", value = (1 - event_data.value)})
+ elseif event_data.ctrl_name == "title_cmb" then
+ post({action="set_title", value= event_data.value})
+ elseif event_data.ctrl_name == "open_btn" then
+ floater_name = leap.request(COMMAND_PUMP_NAME, {action="get_value", ctrl_name='openfloater_cmd'})['value']
+ leap.send("LLFloaterReg", {name = floater_name, op = "showInstance"})
+ end
+ elseif event_data.event == _event("double_click") then
+ if event_data.ctrl_name == "show_time_lbl" then
+ post({action="set_value", ctrl_name="time_lbl", value= getCurrentTime()})
+ end
+ elseif event_data.event == _event("floater_close") then
+ LL.print_warning("Floater was closed")
+ return false
+ end
+ return true
+end
+
+startup.wait('STATE_LOGIN_WAIT')
+local key = {xml_path = XML_FILE_PATH, op = "showLuaFloater"}
+--sign for additional events for defined control {<control_name>= {action1, action2, ...}}
+key.extra_events={show_time_lbl = {_event("right_mouse_down"), _event("double_click")}}
+local resp = leap.request("LLFloaterReg", key)
+COMMAND_PUMP_NAME = resp.command_name
+reqid = resp.reqid
+
+catch_events = leap.WaitFor:new(-1, "all_events")
+function catch_events:filter(pump, data)
+ if data.reqid == reqid then
+ return data
+ end
+end
+
+function process_events(waitfor)
+ event_data = waitfor:wait()
+ while event_data and handleEvents(event_data) do
+ event_data = waitfor:wait()
+ end
+end
+
+fiber.launch("catch_events", process_events, catch_events)
diff --git a/indra/newview/scripts/lua/test_luafloater_demo2.lua b/indra/newview/scripts/lua/test_luafloater_demo2.lua
new file mode 100644
index 0000000000..9e24237d28
--- /dev/null
+++ b/indra/newview/scripts/lua/test_luafloater_demo2.lua
@@ -0,0 +1,39 @@
+local Floater = require 'Floater'
+local leap = require 'leap'
+local startup = require 'startup'
+
+local flt = Floater:new(
+ 'luafloater_demo.xml',
+ {show_time_lbl = {"right_mouse_down", "double_click"}})
+
+-- override base-class handleEvents() to report the event data in the floater's display field
+function flt:handleEvents(event_data)
+ self:post({action="add_text", ctrl_name="events_editor", value = event_data})
+ -- forward the call to base-class handleEvents()
+ return Floater.handleEvents(self, event_data)
+end
+
+function flt:commit_disable_ctrl(event_data)
+ self:post({action="set_enabled", ctrl_name="open_btn", value = (1 - event_data.value)})
+end
+
+function flt:commit_title_cmb(event_data)
+ self:post({action="set_title", value=event_data.value})
+end
+
+function flt:commit_open_btn(event_data)
+ floater_name = self:request({action="get_value", ctrl_name='openfloater_cmd'}).value
+ leap.send("LLFloaterReg", {name = floater_name, op = "showInstance"})
+end
+
+local function getCurrentTime()
+ local currentTime = os.date("*t")
+ return string.format("%02d:%02d:%02d", currentTime.hour, currentTime.min, currentTime.sec)
+end
+
+function flt:double_click_show_time_lbl(event_data)
+ self:post({action="set_value", ctrl_name="time_lbl", value=getCurrentTime()})
+end
+
+startup.wait('STATE_LOGIN_WAIT')
+flt:show()
diff --git a/indra/newview/scripts/lua/test_luafloater_gesture_list.lua b/indra/newview/scripts/lua/test_luafloater_gesture_list.lua
new file mode 100644
index 0000000000..3d9a9b0ad4
--- /dev/null
+++ b/indra/newview/scripts/lua/test_luafloater_gesture_list.lua
@@ -0,0 +1,75 @@
+XML_FILE_PATH = LL.abspath("luafloater_gesture_list.xml")
+
+scriptparts = string.split(LL.source_path(), '/')
+scriptname = scriptparts[#scriptparts]
+print('Running ' .. scriptname)
+
+leap = require 'leap'
+fiber = require 'fiber'
+LLGesture = require 'LLGesture'
+startup = require 'startup'
+
+--event pump for sending actions to the floater
+local COMMAND_PUMP_NAME = ""
+local reqid
+--table of floater UI events
+event_list=leap.request("LLFloaterReg", {op="getFloaterEvents"}).events
+
+local function _event(event_name)
+ if not table.find(event_list, event_name) then
+ LL.print_warning("Incorrect event name: " .. event_name)
+ end
+ return event_name
+end
+
+function post(action)
+ leap.send(COMMAND_PUMP_NAME, action)
+end
+
+function handleEvents(event_data)
+ if event_data.event == _event("floater_close") then
+ return false
+ end
+
+ if event_data.event == _event("post_build") then
+ COMMAND_PUMP_NAME = event_data.command_name
+ reqid = event_data.reqid
+ gestures_uuid = LLGesture.getActiveGestures()
+ local action_data = {}
+ action_data.action = "add_list_element"
+ action_data.ctrl_name = "gesture_list"
+ gestures = {}
+ for uuid, info in pairs(gestures_uuid) do
+ table.insert(gestures, {value = uuid, columns ={column = "gesture_name", value = info.name}})
+ end
+ action_data.value = gestures
+ post(action_data)
+ elseif event_data.event == _event("double_click") then
+ if event_data.ctrl_name == "gesture_list" then
+ LLGesture.startGesture(event_data.value)
+ end
+ end
+ return true
+end
+
+startup.wait('STATE_STARTED')
+local key = {xml_path = XML_FILE_PATH, op = "showLuaFloater"}
+--receive additional events for defined control {<control_name>= {action1, action2, ...}}
+key.extra_events={gesture_list = {_event("double_click")}}
+handleEvents(leap.request("LLFloaterReg", key))
+
+catch_events = leap.WaitFor:new(-1, "all_events")
+function catch_events:filter(pump, data)
+ if data.reqid == reqid then
+ return data
+ end
+end
+
+function process_events(waitfor)
+ event_data = waitfor:wait()
+ while event_data and handleEvents(event_data) do
+ event_data = waitfor:wait()
+ end
+end
+
+fiber.launch("catch_events", process_events, catch_events)
diff --git a/indra/newview/scripts/lua/test_luafloater_gesture_list2.lua b/indra/newview/scripts/lua/test_luafloater_gesture_list2.lua
new file mode 100644
index 0000000000..d702d09c51
--- /dev/null
+++ b/indra/newview/scripts/lua/test_luafloater_gesture_list2.lua
@@ -0,0 +1,27 @@
+local Floater = require 'Floater'
+local LLGesture = require 'LLGesture'
+local startup = require 'startup'
+
+local flt = Floater:new(
+ "luafloater_gesture_list.xml",
+ {gesture_list = {"double_click"}})
+
+function flt:post_build(event_data)
+ local gestures_uuid = LLGesture.getActiveGestures()
+ local action_data = {}
+ action_data.action = "add_list_element"
+ action_data.ctrl_name = "gesture_list"
+ local gestures = {}
+ for uuid, info in pairs(gestures_uuid) do
+ table.insert(gestures, {value = uuid, columns={column = "gesture_name", value = info.name}})
+ end
+ action_data.value = gestures
+ self:post(action_data)
+end
+
+function flt:double_click_gesture_list(event_data)
+ LLGesture.startGesture(event_data.value)
+end
+
+startup.wait('STATE_STARTED')
+flt:show()
diff --git a/indra/newview/scripts/lua/testmod.lua b/indra/newview/scripts/lua/testmod.lua
new file mode 100644
index 0000000000..60f7f80db1
--- /dev/null
+++ b/indra/newview/scripts/lua/testmod.lua
@@ -0,0 +1,2 @@
+print('loaded scripts/lua/testmod.lua')
+return function () return 'hello from scripts/lua/testmod.lua' end
diff --git a/indra/newview/scripts/lua/util.lua b/indra/newview/scripts/lua/util.lua
new file mode 100644
index 0000000000..a2191288f6
--- /dev/null
+++ b/indra/newview/scripts/lua/util.lua
@@ -0,0 +1,44 @@
+-- utility functions, in alpha order
+
+local util = {}
+
+-- check if array-like table contains certain value
+function util.contains(t, v)
+ return table.find(t, v) ~= nil
+end
+
+-- reliable count of the number of entries in table t
+-- (since #t is unreliable)
+function util.count(t)
+ local count = 0
+ for _ in pairs(t) do
+ count += 1
+ end
+ return count
+end
+
+-- cheap test whether table t is empty
+function util.empty(t)
+ return not next(t)
+end
+
+-- recursive table equality
+function util.equal(t1, t2)
+ if not (type(t1) == 'table' and type(t2) == 'table') then
+ return t1 == t2
+ end
+ -- both t1 and t2 are tables: get modifiable copy of t2
+ local temp = table.clone(t2)
+ for k, v in pairs(t1) do
+ -- if any key in t1 doesn't have same value in t2, not equal
+ if not util.equal(v, temp[k]) then
+ return false
+ end
+ -- temp[k] == t1[k], delete temp[k]
+ temp[k] = nil
+ end
+ -- All keys in t1 have equal values in t2; t2 == t1 if there are no extra keys in t2
+ return util.empty(temp)
+end
+
+return util
diff --git a/indra/newview/skins/default/xui/en/floater_lua_debug.xml b/indra/newview/skins/default/xui/en/floater_lua_debug.xml
new file mode 100644
index 0000000000..012ea6f254
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_lua_debug.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_minimize="false"
+ can_resize="true"
+ can_close="true"
+ bevel_style="in"
+ height="220"
+ layout="topleft"
+ name="LUA debug"
+ save_rect="true"
+ title="LUA DEBUG"
+ single_instance="true"
+ width="535">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="10"
+ left_delta="10"
+ name="editor_path_label"
+ top="10"
+ width="100">
+ LUA string:
+ </text>
+ <check_box
+ follows="right|top"
+ height="15"
+ label="Use clean lua_State"
+ layout="topleft"
+ top="10"
+ right ="-70"
+ name="clean_lua_state"
+ width="70"/>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ max_length_bytes="300"
+ name="lua_cmd"
+ select_on_focus="true"
+ top_delta="30"
+ width="435" />
+ <button
+ follows="right|top"
+ height="25"
+ label="Execute"
+ layout="topleft"
+ left_pad="5"
+ name="execute_btn"
+ top_delta="-2"
+ width="75" />
+
+ <text_editor
+ enabled="false"
+ left="10"
+ height="95"
+ layout="topleft"
+ name="result_text"
+ follows="all"
+ max_length="65536"
+ width="515"
+ top_delta="40"
+ word_wrap="true" />
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="10"
+ name="path_label"
+ top_pad="15"
+ width="100">
+ File Path:
+ </text>
+ <line_editor
+ border_style="line"
+ enabled="false"
+ border_thickness="1"
+ follows="left|bottom|right"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="65"
+ max_length_bytes="300"
+ name="script_path"
+ select_on_focus="true"
+ top_delta="-2"
+ width="320" />
+ <button
+ follows="right|bottom"
+ height="25"
+ label="Browse..."
+ label_selected="Browse..."
+ layout="topleft"
+ left_pad="5"
+ name="browse_btn"
+ top_delta="-2"
+ width="70" />
+ <button
+ follows="right|bottom"
+ height="25"
+ label="Run"
+ label_selected="Run"
+ layout="topleft"
+ left_pad="5"
+ name="run_btn"
+ width="50" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_lua_scripts.xml b/indra/newview/skins/default/xui/en/floater_lua_scripts.xml
new file mode 100644
index 0000000000..6859201650
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_lua_scripts.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_minimize="false"
+ can_resize="true"
+ can_close="true"
+ bevel_style="in"
+ height="220"
+ min_height="220"
+ layout="topleft"
+ name="LUA scripts"
+ save_rect="true"
+ title="LUA Scripts"
+ single_instance="true"
+ width="555"
+ min_width="555">
+ <scroll_list
+ column_padding="0"
+ draw_stripes="true"
+ draw_heading="true"
+ height="200"
+ left="10"
+ follows="all"
+ layout="topleft"
+ sort_column="script_name"
+ name="scripts_list"
+ top_pad="10"
+ width="535">
+ <scroll_list.columns
+ label="Name"
+ name="script_name"
+ width="180" />
+ <scroll_list.columns
+ label="Path"
+ name="script_path"/>
+ </scroll_list>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_settings_debug.xml b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
index a93be6a18d..6fd8f2b255 100644
--- a/indra/newview/skins/default/xui/en/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
@@ -43,6 +43,20 @@
label="Setting"
name="setting" />
</scroll_list>
+ <button
+ follows="right|bottom"
+ layout="topleft"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="Icon_Copy"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ name="copy_btn"
+ tool_tip="Copy to clipboard"
+ top_delta="8"
+ left_pad="10"
+ visible="false"
+ height="20"
+ width="20" />
<text
type="string"
length="1"
@@ -51,8 +65,7 @@
layout="topleft"
name="setting_name_txt"
font="SansSerifSmallBold"
- top_delta="8"
- left_pad="10"
+ left_pad="4"
visible="false"
use_ellipses="true"
text_color="White"
@@ -67,6 +80,7 @@
name="comment_text"
follows="left|top"
width="240"
+ left="320"
top_delta="20"
word_wrap="true" />
<radio_group
diff --git a/indra/newview/skins/default/xui/en/menu_lua_scripts.xml b/indra/newview/skins/default/xui/en/menu_lua_scripts.xml
new file mode 100644
index 0000000000..645fee405d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_lua_scripts.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ name="Scripts">
+ <menu_item_call
+ label="Open Containing Folder"
+ layout="topleft"
+ name="open_folder">
+ <menu_item_call.on_click
+ function="Script.OpenFolder" />
+ </menu_item_call>
+ <menu_item_separator/>
+ <menu_item_call
+ label="Terminate script"
+ layout="topleft"
+ name="terminate">
+ <menu_item_call.on_click
+ function="Script.Terminate" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 53f703e56d..5ae97b729e 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2537,6 +2537,27 @@ function="World.EnvPreset"
parameter="scene monitor" />
</menu_item_check>
<menu_item_separator/>
+ <menu_item_check
+ label="LUA Debug Console"
+ name="LUA Debug Console">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="lua_debug" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="lua_debug" />
+ </menu_item_check>
+ <menu_item_check
+ label="LUA Scripts Info"
+ name="LUA Scripts">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="lua_scripts" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="lua_scripts" />
+ </menu_item_check>
+ <menu_item_separator/>
<menu_item_call
label="Region Info to Debug Console"
diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp
new file mode 100644
index 0000000000..cf1bf25b5c
--- /dev/null
+++ b/indra/newview/tests/llluamanager_test.cpp
@@ -0,0 +1,468 @@
+/**
+ * @file llluamanager_test.cpp
+ * @author Nat Goodspeed
+ * @date 2023-09-28
+ * @brief Test for llluamanager.
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Copyright (c) 2023, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+//#include "llviewerprecompiledheaders.h"
+// associated header
+#include "../newview/llluamanager.h"
+// STL headers
+// std headers
+#include <vector>
+// external library headers
+// other Linden headers
+#include "../llcommon/tests/StringVec.h"
+#include "../test/lltut.h"
+#include "llapp.h"
+#include "lldate.h"
+#include "llevents.h"
+#include "lleventcoro.h"
+#include "llsdutil.h"
+#include "lluri.h"
+#include "lluuid.h"
+#include "lua_function.h"
+#include "lualistener.h"
+#include "stringize.h"
+
+class LLTestApp : public LLApp
+{
+public:
+ bool init() override { return true; }
+ bool cleanup() override { return true; }
+ bool frame() override { return true; }
+};
+
+template <typename CALLABLE>
+auto listener(CALLABLE&& callable)
+{
+ return [callable=std::forward<CALLABLE>(callable)]
+ (const LLSD& data)
+ {
+ callable(data);
+ return false;
+ };
+}
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llluamanager_data
+ {
+ // We need an LLApp instance because LLLUAmanager uses coroutines,
+ // which suspend, and when a coroutine suspends it checks LLApp state,
+ // and if it's not APP_STATUS_RUNNING the coroutine terminates.
+ LLTestApp mApp;
+ };
+ typedef test_group<llluamanager_data> llluamanager_group;
+ typedef llluamanager_group::object object;
+ llluamanager_group llluamanagergrp("llluamanager");
+
+ static struct LuaExpr
+ {
+ std::string desc, expr;
+ LLSD expect;
+ } lua_expressions[] = {
+ { "nil", "nil", LLSD() },
+ { "true", "true", true },
+ { "false", "false", false },
+ { "int", "17", 17 },
+ { "real", "3.14", 3.14 },
+ { "string", "'string'", "string" },
+ // can't synthesize Lua userdata in Lua code: that can only be
+ // constructed by a C function
+ { "empty table", "{}", LLSD() },
+ { "nested empty table", "{ 1, 2, 3, {}, 5 }",
+ llsd::array(1, 2, 3, LLSD(), 5) },
+ { "nested non-empty table", "{ 1, 2, 3, {a=0, b=1}, 5 }",
+ llsd::array(1, 2, 3, llsd::map("a", 0, "b", 1), 5) },
+ };
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("test Lua results");
+ LuaState L;
+ for (auto& luax : lua_expressions)
+ {
+ auto [count, result] =
+ LLLUAmanager::waitScriptLine(L, "return " + luax.expr);
+ auto desc{ stringize("waitScriptLine(", luax.desc, "): ") };
+ // if count < 0, report Lua error message
+ ensure_equals(desc + result.asString(), count, 1);
+ ensure_equals(desc + "result", result, luax.expect);
+ }
+ }
+
+ void from_lua(const std::string& desc, const std::string_view& construct, const LLSD& expect)
+ {
+ LLSD fromlua;
+ LLStreamListener pump("testpump",
+ listener([&fromlua](const LLSD& data){ fromlua = data; }));
+ const std::string lua(stringize(
+ "data = ", construct, "\n"
+ "LL.post_on('testpump', data)\n"
+ ));
+ LuaState L;
+ auto [count, result] = LLLUAmanager::waitScriptLine(L, lua);
+ // We woke up again ourselves because the coroutine running Lua has
+ // finished. But our Lua chunk didn't actually return anything, so we
+ // expect count to be 0 and result to be undefined.
+ ensure_equals(desc + ": " + result.asString(), count, 0);
+ ensure_equals(desc, fromlua, expect);
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ set_test_name("LLSD from post_on()");
+ for (auto& luax : lua_expressions)
+ {
+ from_lua(luax.desc, luax.expr, luax.expect);
+ }
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ set_test_name("test post_on(), get_event_pumps(), get_event_next()");
+ StringVec posts;
+ LLStreamListener pump("testpump",
+ listener([&posts](const LLSD& data)
+ { posts.push_back(data.asString()); }));
+ const std::string lua(
+ "-- test post_on,get_event_pumps,get_event_next\n"
+ "LL.post_on('testpump', 'entry')\n"
+ "LL.post_on('testpump', 'get_event_pumps()')\n"
+ "replypump, cmdpump = LL.get_event_pumps()\n"
+ "LL.post_on('testpump', replypump)\n"
+ "LL.post_on('testpump', 'get_event_next()')\n"
+ "pump, data = LL.get_event_next()\n"
+ "LL.post_on('testpump', data)\n"
+ "LL.post_on('testpump', 'exit')\n"
+ );
+ LuaState L;
+ // It's important to let the startScriptLine() coroutine run
+ // concurrently with ours until we've had a chance to post() our
+ // reply.
+ auto future = LLLUAmanager::startScriptLine(L, lua);
+ StringVec expected{
+ "entry",
+ "get_event_pumps()",
+ "",
+ "get_event_next()",
+ "message",
+ "exit"
+ };
+ expected[2] = posts.at(2);
+ LL_DEBUGS() << "Found pumpname '" << expected[2] << "'" << LL_ENDL;
+ LLEventPump& luapump{ LLEventPumps::instance().obtain(expected[2]) };
+ LL_DEBUGS() << "Found pump '" << luapump.getName() << "', type '"
+ << LLError::Log::classname(luapump)
+ << "': post('" << expected[4] << "')" << LL_ENDL;
+ luapump.post(expected[4]);
+ auto [count, result] = future.get();
+ ensure_equals("post_on(): " + result.asString(), count, 0);
+ ensure_equals("post_on() sequence", posts, expected);
+ }
+
+ void round_trip(const std::string& desc, const LLSD& send, const LLSD& expect)
+ {
+ LLEventMailDrop testpump("testpump");
+ const std::string lua(
+ "-- test LLSD round trip\n"
+ "replypump, cmdpump = LL.get_event_pumps()\n"
+ "LL.post_on('testpump', replypump)\n"
+ "pump, data = LL.get_event_next()\n"
+ "return data\n"
+ );
+ LuaState L;
+ auto future = LLLUAmanager::startScriptLine(L, lua);
+ // We woke up again ourselves because the coroutine running Lua has
+ // reached the get_event_next() call, which suspends the calling C++
+ // coroutine (including the Lua code running on it) until we post
+ // something to that reply pump.
+ auto luapump{ llcoro::suspendUntilEventOn(testpump).asString() };
+ LLEventPumps::instance().post(luapump, send);
+ // The C++ coroutine running the Lua script is now ready to run. Run
+ // it so it will echo the LLSD back to us.
+ auto [count, result] = future.get();
+ ensure_equals(stringize("round_trip(", desc, "): ", result.asString()), count, 1);
+ ensure_equals(desc, result, expect);
+ }
+
+ // Define an RTItem to be used for round-trip LLSD testing: what it is,
+ // what we send to Lua, what we expect to get back. They could be the
+ // same.
+ struct RTItem
+ {
+ RTItem(const std::string& name, const LLSD& send, const LLSD& expect):
+ mName(name),
+ mSend(send),
+ mExpect(expect)
+ {}
+ RTItem(const std::string& name, const LLSD& both):
+ mName(name),
+ mSend(both),
+ mExpect(both)
+ {}
+
+ std::string mName;
+ LLSD mSend, mExpect;
+ };
+
+ template<> template<>
+ void object::test<4>()
+ {
+ set_test_name("LLSD round trip");
+ LLSD::Binary binary{ 3, 1, 4, 1, 5, 9, 2, 6, 5 };
+ const char* uuid{ "01234567-abcd-0123-4567-0123456789ab" };
+ const char* date{ "2023-10-04T21:06:00Z" };
+ const char* uri{ "https://secondlife.com/index.html" };
+ std::vector<RTItem> items{
+ RTItem("undefined", LLSD()),
+ RTItem("true", true),
+ RTItem("false", false),
+ RTItem("int", 17),
+ RTItem("real", 3.14),
+ RTItem("int real", 27.0, 27),
+ RTItem("string", "string"),
+ RTItem("binary", binary),
+ RTItem("empty array", LLSD::emptyArray(), LLSD()),
+ RTItem("empty map", LLSD::emptyMap(), LLSD()),
+ RTItem("UUID", LLUUID(uuid), uuid),
+ RTItem("date", LLDate(date), date),
+ RTItem("uri", LLURI(uri), uri)
+ };
+ // scalars
+ for (const auto& item: items)
+ {
+ round_trip(item.mName, item.mSend, item.mExpect);
+ }
+
+ // array
+ LLSD send_array{ LLSD::emptyArray() }, expect_array{ LLSD::emptyArray() };
+ for (const auto& item: items)
+ {
+ send_array.append(item.mSend);
+ expect_array.append(item.mExpect);
+ }
+ // exercise the array tail trimming below
+ send_array.append(items[0].mSend);
+ expect_array.append(items[0].mExpect);
+ // Lua takes a table value of nil to mean: don't store this key. An
+ // LLSD array containing undefined entries (converted to nil) leaves
+ // "holes" in the Lua table. These will be converted back to undefined
+ // LLSD entries -- except at the end. Trailing undefined entries are
+ // simply omitted from the table -- so the table converts back to a
+ // shorter LLSD array. We've constructed send_array and expect_array
+ // according to 'items' above -- but truncate from expect_array any
+ // trailing entries whose mSend will map to Lua nil.
+ while (expect_array.size() > 0 &&
+ send_array[expect_array.size() - 1].isUndefined())
+ {
+ expect_array.erase(expect_array.size() - 1);
+ }
+ round_trip("array", send_array, expect_array);
+
+ // map
+ LLSD send_map{ LLSD::emptyMap() }, expect_map{ LLSD::emptyMap() };
+ for (const auto& item: items)
+ {
+ send_map[item.mName] = item.mSend;
+ // see comment in the expect_array truncation loop above --
+ // Lua never stores table entries with nil values
+ if (item.mSend.isDefined())
+ {
+ expect_map[item.mName] = item.mExpect;
+ }
+ }
+ round_trip("map", send_map, expect_map);
+
+ // deeply nested map: exceed Lua's default stack space (20),
+ // i.e. verify that we have the right checkstack() calls
+ for (int i = 0; i < 20; ++i)
+ {
+ LLSD new_send_map{ send_map }, new_expect_map{ expect_map };
+ new_send_map["nested map"] = send_map;
+ new_expect_map["nested map"] = expect_map;
+ send_map = new_send_map;
+ expect_map = new_expect_map;
+ }
+ round_trip("nested map", send_map, expect_map);
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ set_test_name("leap.request() from main thread");
+ const std::string lua(
+ "-- leap.request() from main thread\n"
+ "\n"
+ "leap = require 'leap'\n"
+ "\n"
+ "return {\n"
+ " a=leap.request('echo', {data='a'}).data,\n"
+ " b=leap.request('echo', {data='b'}).data\n"
+ "}\n"
+ );
+
+ LLStreamListener pump(
+ "echo",
+ listener([](const LLSD& data)
+ {
+ LL_DEBUGS("Lua") << "echo pump got: " << data << LL_ENDL;
+ sendReply(data, data);
+ }));
+
+ LuaState L;
+ auto [count, result] = LLLUAmanager::waitScriptLine(L, lua);
+ ensure_equals("Lua script didn't return item", count, 1);
+ ensure_equals("echo failed", result, llsd::map("a", "a", "b", "b"));
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ set_test_name("interleave leap.request() responses");
+ const std::string lua(
+ "-- interleave leap.request() responses\n"
+ "\n"
+ "fiber = require('fiber')\n"
+ "leap = require('leap')\n"
+ "-- debug = require('printf')\n"
+ "local function debug(...) end\n"
+ "\n"
+ "-- negative priority ensures catchall is always last\n"
+ "catchall = leap.WaitFor:new(-1, 'catchall')\n"
+ "function catchall:filter(pump, data)\n"
+ " debug('catchall:filter(%s, %s)', pump, data)\n"
+ " return data\n"
+ "end\n"
+ "\n"
+ "-- but first, catch events with 'special' key\n"
+ "catch_special = leap.WaitFor:new(2, 'catch_special')\n"
+ "function catch_special:filter(pump, data)\n"
+ " debug('catch_special:filter(%s, %s)', pump, data)\n"
+ " return if data['special'] ~= nil then data else nil\n"
+ "end\n"
+ "\n"
+ "function drain(waitfor)\n"
+ " debug('%s start', waitfor.name)\n"
+ " -- It seems as though we ought to be able to code this loop\n"
+ " -- over waitfor:wait() as:\n"
+ " -- for item in waitfor.wait, waitfor do\n"
+ " -- However, that seems to stitch a detour through C code into\n"
+ " -- the coroutine call stack, which prohibits coroutine.yield():\n"
+ " -- 'attempt to yield across metamethod/C-call boundary'\n"
+ " -- So we resort to two different calls to waitfor:wait().\n"
+ " local item = waitfor:wait()\n"
+ " while item do\n"
+ " debug('%s caught %s', waitfor.name, item)\n"
+ " item = waitfor:wait()\n"
+ " end\n"
+ " debug('%s done', waitfor.name)\n"
+ "end\n"
+ "\n"
+ "function requester(name)\n"
+ " debug('requester(%s) start', name)\n"
+ " local response = leap.request('testpump', {name=name})\n"
+ " debug('requester(%s) got %s', name, response)\n"
+ " -- verify that the correct response was dispatched to this coroutine\n"
+ " assert(response.name == name)\n"
+ "end\n"
+ "\n"
+ "-- fiber.print_all()\n"
+ "fiber.launch('catchall', drain, catchall)\n"
+ "fiber.launch('catch_special', drain, catch_special)\n"
+ "fiber.launch('requester(a)', requester, 'a')\n"
+ "fiber.launch('requester(b)', requester, 'b')\n"
+ );
+
+ LLSD requests;
+ LLStreamListener pump(
+ "testpump",
+ listener([&requests](const LLSD& data)
+ {
+ LL_DEBUGS("Lua") << "testpump got: " << data << LL_ENDL;
+ requests.append(data);
+ }));
+
+ LuaState L;
+ auto future = LLLUAmanager::startScriptLine(L, lua);
+ auto replyname{ L.obtainListener()->getReplyName() };
+ auto& replypump{ LLEventPumps::instance().obtain(replyname) };
+ // LuaState::expr() periodically interrupts a running chunk to ensure
+ // the rest of our coroutines get cycles. Nonetheless, for this test
+ // we have to wait until both requester() coroutines have posted and
+ // are waiting for a reply.
+ for (unsigned count=0; count < 100; ++count)
+ {
+ if (requests.size() == 2)
+ break;
+ llcoro::suspend();
+ }
+ ensure_equals("didn't get both requests", requests.size(), 2);
+ // moreover, we expect they arrived in the order they were created
+ ensure_equals("a wasn't first", requests[0]["name"].asString(), "a");
+ ensure_equals("b wasn't second", requests[1]["name"].asString(), "b");
+ replypump.post(llsd::map("special", "K"));
+ // respond to requester(b) FIRST
+ replypump.post(requests[1]);
+ replypump.post(llsd::map("name", "not special"));
+ // now respond to requester(a)
+ replypump.post(requests[0]);
+ // tell leap we're done
+ replypump.post(LLSD());
+ auto [count, result] = future.get();
+ ensure_equals("leap.lua: " + result.asString(), count, 0);
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ set_test_name("stop hanging Lua script");
+ const std::string lua(
+ "-- hanging Lua script should terminate\n"
+ "\n"
+ "LL.get_event_next()\n"
+ );
+ LuaState L;
+ auto future = LLLUAmanager::startScriptLine(L, lua);
+ // Poke LLTestApp to send its preliminary shutdown message.
+ mApp.setQuitting();
+ // but now we have to give the startScriptLine() coroutine a chance to run
+ auto [count, result] = future.get();
+ ensure_equals("killed Lua script terminated normally", count, -1);
+ ensure_equals("unexpected killed Lua script error",
+ result.asString(), "viewer is stopping");
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ set_test_name("stop looping Lua script");
+ const std::string desc("looping Lua script should terminate");
+ const std::string lua(
+ "-- " + desc + "\n"
+ "\n"
+ "while true do\n"
+ " x = 1\n"
+ "end\n"
+ );
+ LuaState L;
+ auto [count, result] = LLLUAmanager::waitScriptLine(L, lua);
+ // We expect the above erroneous script has been forcibly terminated
+ // because it ran too long without doing any actual work.
+ ensure_equals(desc + " count: " + result.asString(), count, -1);
+ ensure_contains(desc + " result", result.asString(), "terminated");
+ }
+} // namespace tut
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index f249bf470e..8123827f5a 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -59,7 +59,7 @@ class ViewerManifest(LLManifest):
# files during the build (see copy_w_viewer_manifest
# and copy_l_viewer_manifest targets)
return 'package' in self.args['actions']
-
+
def construct(self):
super(ViewerManifest, self).construct()
self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg")
@@ -87,7 +87,7 @@ class ViewerManifest(LLManifest):
# ... and the entire image filters directory
self.path("filters")
-
+
# ... and the included spell checking dictionaries
pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
with self.prefix(src=pkgdir):
@@ -166,6 +166,10 @@ class ViewerManifest(LLManifest):
self.path("*/*/*/*.js")
self.path("*/*/*.html")
+ with self.prefix(src_dst="scripts/lua"):
+ self.path("*.lua")
+ self.path("*.xml")
+
#build_data.json. Standard with exception handling is fine. If we can't open a new file for writing, we have worse problems
#platform is computed above with other arg parsing
build_data_dict = {"Type":"viewer","Version":'.'.join(self.args['version']),
@@ -260,14 +264,14 @@ class ViewerManifest(LLManifest):
def app_name_oneword(self):
return ''.join(self.app_name().split())
-
+
def icon_path(self):
return "icons/" + self.channel_type()
def extract_names(self,src):
"""Extract contributor names from source file, returns string"""
try:
- with open(src, 'r') as contrib_file:
+ with open(src, 'r') as contrib_file:
lines = contrib_file.readlines()
except IOError:
print("Failed to open '%s'" % src)
@@ -491,7 +495,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
raise Exception("Directories are not supported by test_CRT_and_copy_action()")
else:
print("Doesn't exist:", src)
-
+
def construct(self):
super().construct()
@@ -543,7 +547,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
self.path2basename(os.path.join(os.pardir,
'llplugin', 'slplugin', self.args['configuration']),
"slplugin.exe")
-
+
# Get shared libs from the shared libs staging directory
with self.prefix(src=os.path.join(self.args['build'], os.pardir,
'sharedlibs', self.args['buildtype'])):
@@ -582,7 +586,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
# Vivox libraries
self.path("vivoxsdk_x64.dll")
self.path("ortp_x64.dll")
-
+
# OpenSSL
self.path("libcrypto-1_1-x64.dll")
self.path("libssl-1_1-x64.dll")
@@ -709,7 +713,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
self.path("plugins/")
if not self.is_packaging_viewer():
- self.package_file = "copied_deps"
+ self.package_file = "copied_deps"
def nsi_file_commands(self, install=True):
def INSTDIR(path):
@@ -768,7 +772,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
installer_file = self.installer_base_name() + '_Setup.exe'
substitution_strings['installer_file'] = installer_file
-
+
version_vars = """
!define INSTEXE "SLVersionChecker.exe"
!define VERSION "%(version_short)s"
@@ -777,7 +781,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
!define VERSION_REGISTRY "%(version_registry)s"
!define VIEWER_EXE "%(final_exe)s"
""" % substitution_strings
-
+
if self.channel_type() == 'release':
substitution_strings['caption'] = CHANNEL_VENDOR_BASE
else:
@@ -908,7 +912,7 @@ class Darwin_x86_64_Manifest(ViewerManifest):
# yields a slightly smaller binary but makes crash
# logs mostly useless. This may be desirable for the
# final release. Or not.
- if ("package" in self.args['actions'] or
+ if ("package" in self.args['actions'] or
"unpacked" in self.args['actions']):
self.run_command(
['strip', '-S', executable])
@@ -933,7 +937,7 @@ class Darwin_x86_64_Manifest(ViewerManifest):
with self.prefix(src=relpkgdir, dst=""):
self.path("libndofdev.dylib")
- self.path("libhunspell-*.dylib")
+ self.path("libhunspell-*.dylib")
with self.prefix(src_dst="cursors_mac"):
self.path("*.tif")
diff --git a/indra/test/debug.h b/indra/test/debug.h
index 1579bb9c86..2f6a114761 100644
--- a/indra/test/debug.h
+++ b/indra/test/debug.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-05-28
* @brief Debug output for unit test code
- *
+ *
* $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$
*/
@@ -30,43 +30,56 @@
#define LL_DEBUG_H
#include "print.h"
+#include "stringize.h"
+#include <exception> // std::uncaught_exceptions()
/*****************************************************************************
* Debugging stuff
*****************************************************************************/
/**
- * This class is intended to illuminate entry to a given block, exit from the
- * same block and checkpoints along the way. It also provides a convenient
- * place to turn std::cerr output on and off.
- *
- * If the environment variable LOGTEST is non-empty, each Debug instance will
- * announce its construction and destruction, presumably at entry and exit to
- * the block in which it's declared. Moreover, any arguments passed to its
- * operator()() will be streamed to std::cerr, prefixed by the block
- * description.
+ * Return true if the environment variable LOGTEST is non-empty.
*
* The variable LOGTEST is used because that's the environment variable
* checked by test.cpp, our TUT main() program, to turn on LLError logging. It
* is expected that Debug is solely for use in test programs.
*/
+inline
+bool LOGTEST_enabled()
+{
+ auto LOGTEST{ getenv("LOGTEST") };
+ // debug output enabled when LOGTEST is set AND non-empty
+ return LOGTEST && *LOGTEST;
+}
+
+/**
+ * This class is intended to illuminate entry to a given block, exit from the
+ * same block and checkpoints along the way. It also provides a convenient
+ * place to turn std::cerr output on and off.
+ *
+ * If enabled, each Debug instance will announce its construction and
+ * destruction, presumably at entry and exit to the block in which it's
+ * declared. Moreover, any arguments passed to its operator()() will be
+ * streamed to std::cerr, prefixed by the block description.
+ */
class Debug
{
public:
- Debug(const std::string& block):
- mBlock(block),
- mLOGTEST(getenv("LOGTEST")),
- // debug output enabled when LOGTEST is set AND non-empty
- mEnabled(mLOGTEST && *mLOGTEST)
+ template <typename... ARGS>
+ Debug(ARGS&&... args):
+ mBlock(stringize(std::forward<ARGS>(args)...)),
+ mEnabled(LOGTEST_enabled())
{
(*this)("entry");
}
// non-copyable
Debug(const Debug&) = delete;
+ Debug& operator=(const Debug&) = delete;
~Debug()
{
- (*this)("exit");
+ auto exceptional{ std::uncaught_exceptions()? "exceptional " : "" };
+ (*this)(exceptional, "exit");
}
template <typename... ARGS>
@@ -80,7 +93,6 @@ public:
private:
const std::string mBlock;
- const char* mLOGTEST;
bool mEnabled;
};
@@ -88,20 +100,19 @@ private:
// of the Debug block.
#define DEBUG Debug debug(LL_PRETTY_FUNCTION)
-// These BEGIN/END macros are specifically for debugging output -- please
-// don't assume you must use such for coroutines in general! They only help to
-// make control flow (as well as exception exits) explicit.
-#define BEGIN \
-{ \
- DEBUG; \
- try
+/// If enabled, debug_expr(expression) gives you output concerning an inline
+/// expression such as a class member initializer.
+#define debug_expr(expr) debug_expr_(#expr, [&](){ return expr; })
-#define END \
- catch (...) \
- { \
- debug("*** exceptional "); \
- throw; \
- } \
+template <typename EXPR>
+inline auto debug_expr_(const char* strexpr, EXPR&& lambda)
+{
+ if (! LOGTEST_enabled())
+ return std::forward<EXPR>(lambda)();
+ print("Before: ", strexpr);
+ auto result{ std::forward<EXPR>(lambda)() };
+ print(strexpr, " -> ", result);
+ return result;
}
#endif /* ! defined(LL_DEBUG_H) */
diff --git a/indra/test/io.cpp b/indra/test/io.cpp
index 412f9ca1d2..88c22e7508 100644
--- a/indra/test/io.cpp
+++ b/indra/test/io.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file io.cpp
* @author Phoenix
* @date 2005-10-02
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&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$
*/
@@ -45,1135 +45,1157 @@
#include "llcommon.h"
#include "lluuid.h"
#include "llinstantmessage.h"
+#include "stringize.h"
namespace tut
{
- struct heap_buffer_data
- {
- heap_buffer_data() : mBuffer(NULL) {}
- ~heap_buffer_data() { if(mBuffer) delete mBuffer; }
- LLHeapBuffer* mBuffer;
- };
- typedef test_group<heap_buffer_data> heap_buffer_test;
- typedef heap_buffer_test::object heap_buffer_object;
- tut::heap_buffer_test thb("heap_buffer");
-
- template<> template<>
- void heap_buffer_object::test<1>()
- {
- const S32 BUF_SIZE = 100;
- mBuffer = new LLHeapBuffer(BUF_SIZE);
- ensure_equals("empty buffer capacity", mBuffer->capacity(), BUF_SIZE);
- const S32 SEGMENT_SIZE = 50;
- LLSegment segment;
- mBuffer->createSegment(0, SEGMENT_SIZE, segment);
- ensure_equals("used buffer capacity", mBuffer->capacity(), BUF_SIZE);
- }
-
- template<> template<>
- void heap_buffer_object::test<2>()
- {
- const S32 BUF_SIZE = 10;
- mBuffer = new LLHeapBuffer(BUF_SIZE);
- LLSegment segment;
- mBuffer->createSegment(0, BUF_SIZE, segment);
- ensure("segment is in buffer", mBuffer->containsSegment(segment));
- ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
- bool created;
- created = mBuffer->createSegment(0, 0, segment);
- ensure("Create zero size segment fails", !created);
- created = mBuffer->createSegment(0, BUF_SIZE, segment);
- ensure("Create segment fails", !created);
- }
-
- template<> template<>
- void heap_buffer_object::test<3>()
- {
- const S32 BUF_SIZE = 10;
- mBuffer = new LLHeapBuffer(BUF_SIZE);
- LLSegment segment;
- mBuffer->createSegment(0, BUF_SIZE, segment);
- ensure("segment is in buffer", mBuffer->containsSegment(segment));
- ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
- bool reclaimed = mBuffer->reclaimSegment(segment);
- ensure("buffer reclaimed.", reclaimed);
- ensure_equals("buffer available", mBuffer->bytesLeft(), BUF_SIZE);
- bool created;
- created = mBuffer->createSegment(0, 0, segment);
- ensure("Create zero size segment fails", !created);
- created = mBuffer->createSegment(0, BUF_SIZE, segment);
- ensure("Create another segment succeeds", created);
- }
-
- template<> template<>
- void heap_buffer_object::test<4>()
- {
- const S32 BUF_SIZE = 10;
- const S32 SEGMENT_SIZE = 4;
- mBuffer = new LLHeapBuffer(BUF_SIZE);
- LLSegment seg1;
- mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
- ensure("segment is in buffer", mBuffer->containsSegment(seg1));
- LLSegment seg2;
- mBuffer->createSegment(0, SEGMENT_SIZE, seg2);
- ensure("segment is in buffer", mBuffer->containsSegment(seg2));
- LLSegment seg3;
- mBuffer->createSegment(0, SEGMENT_SIZE, seg3);
- ensure("segment is in buffer", mBuffer->containsSegment(seg3));
- ensure_equals("segment is truncated", seg3.size(), 2);
- LLSegment seg4;
- bool created;
- created = mBuffer->createSegment(0, SEGMENT_SIZE, seg4);
- ensure("Create segment fails", !created);
- bool reclaimed;
- reclaimed = mBuffer->reclaimSegment(seg1);
- ensure("buffer reclaim succeed.", reclaimed);
- ensure_equals("no buffer available", mBuffer->bytesLeft(), 0);
- reclaimed = mBuffer->reclaimSegment(seg2);
- ensure("buffer reclaim succeed.", reclaimed);
- ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), 0);
- reclaimed = mBuffer->reclaimSegment(seg3);
- ensure("buffer reclaim succeed.", reclaimed);
- ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), BUF_SIZE);
- created = mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
- ensure("segment is in buffer", mBuffer->containsSegment(seg1));
- ensure("Create segment succeds", created);
- }
+ struct heap_buffer_data
+ {
+ heap_buffer_data() : mBuffer(NULL) {}
+ ~heap_buffer_data() { if(mBuffer) delete mBuffer; }
+ LLHeapBuffer* mBuffer;
+ };
+ typedef test_group<heap_buffer_data> heap_buffer_test;
+ typedef heap_buffer_test::object heap_buffer_object;
+ tut::heap_buffer_test thb("heap_buffer");
+
+ template<> template<>
+ void heap_buffer_object::test<1>()
+ {
+ const S32 BUF_SIZE = 100;
+ mBuffer = new LLHeapBuffer(BUF_SIZE);
+ ensure_equals("empty buffer capacity", mBuffer->capacity(), BUF_SIZE);
+ const S32 SEGMENT_SIZE = 50;
+ LLSegment segment;
+ mBuffer->createSegment(0, SEGMENT_SIZE, segment);
+ ensure_equals("used buffer capacity", mBuffer->capacity(), BUF_SIZE);
+ }
+
+ template<> template<>
+ void heap_buffer_object::test<2>()
+ {
+ const S32 BUF_SIZE = 10;
+ mBuffer = new LLHeapBuffer(BUF_SIZE);
+ LLSegment segment;
+ mBuffer->createSegment(0, BUF_SIZE, segment);
+ ensure("segment is in buffer", mBuffer->containsSegment(segment));
+ ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
+ bool created;
+ created = mBuffer->createSegment(0, 0, segment);
+ ensure("Create zero size segment fails", !created);
+ created = mBuffer->createSegment(0, BUF_SIZE, segment);
+ ensure("Create segment fails", !created);
+ }
+
+ template<> template<>
+ void heap_buffer_object::test<3>()
+ {
+ const S32 BUF_SIZE = 10;
+ mBuffer = new LLHeapBuffer(BUF_SIZE);
+ LLSegment segment;
+ mBuffer->createSegment(0, BUF_SIZE, segment);
+ ensure("segment is in buffer", mBuffer->containsSegment(segment));
+ ensure_equals("buffer consumed", mBuffer->bytesLeft(), 0);
+ bool reclaimed = mBuffer->reclaimSegment(segment);
+ ensure("buffer reclaimed.", reclaimed);
+ ensure_equals("buffer available", mBuffer->bytesLeft(), BUF_SIZE);
+ bool created;
+ created = mBuffer->createSegment(0, 0, segment);
+ ensure("Create zero size segment fails", !created);
+ created = mBuffer->createSegment(0, BUF_SIZE, segment);
+ ensure("Create another segment succeeds", created);
+ }
+
+ template<> template<>
+ void heap_buffer_object::test<4>()
+ {
+ const S32 BUF_SIZE = 10;
+ const S32 SEGMENT_SIZE = 4;
+ mBuffer = new LLHeapBuffer(BUF_SIZE);
+ LLSegment seg1;
+ mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
+ ensure("segment is in buffer", mBuffer->containsSegment(seg1));
+ LLSegment seg2;
+ mBuffer->createSegment(0, SEGMENT_SIZE, seg2);
+ ensure("segment is in buffer", mBuffer->containsSegment(seg2));
+ LLSegment seg3;
+ mBuffer->createSegment(0, SEGMENT_SIZE, seg3);
+ ensure("segment is in buffer", mBuffer->containsSegment(seg3));
+ ensure_equals("segment is truncated", seg3.size(), 2);
+ LLSegment seg4;
+ bool created;
+ created = mBuffer->createSegment(0, SEGMENT_SIZE, seg4);
+ ensure("Create segment fails", !created);
+ bool reclaimed;
+ reclaimed = mBuffer->reclaimSegment(seg1);
+ ensure("buffer reclaim succeed.", reclaimed);
+ ensure_equals("no buffer available", mBuffer->bytesLeft(), 0);
+ reclaimed = mBuffer->reclaimSegment(seg2);
+ ensure("buffer reclaim succeed.", reclaimed);
+ ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), 0);
+ reclaimed = mBuffer->reclaimSegment(seg3);
+ ensure("buffer reclaim succeed.", reclaimed);
+ ensure_equals("buffer reclaimed", mBuffer->bytesLeft(), BUF_SIZE);
+ created = mBuffer->createSegment(0, SEGMENT_SIZE, seg1);
+ ensure("segment is in buffer", mBuffer->containsSegment(seg1));
+ ensure("Create segment succeds", created);
+ }
}
namespace tut
{
- struct buffer_data
- {
- LLBufferArray mBuffer;
- };
- typedef test_group<buffer_data> buffer_test;
- typedef buffer_test::object buffer_object;
- tut::buffer_test tba("buffer_array");
-
- template<> template<>
- void buffer_object::test<1>()
- {
- const char HELLO_WORLD[] = "hello world";
- const S32 str_len = strlen(HELLO_WORLD);
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
- S32 count = mBuffer.countAfter(ch.in(), NULL);
- ensure_equals("total append size", count, str_len);
- LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
- U8* first = (*it).data();
- count = mBuffer.countAfter(ch.in(), first);
- ensure_equals("offset append size", count, str_len - 1);
- }
-
- template<> template<>
- void buffer_object::test<2>()
- {
- const char HELLO_WORLD[] = "hello world";
- const S32 str_len = strlen(HELLO_WORLD); /* Flawfinder: ignore */
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
- mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
- S32 count = mBuffer.countAfter(ch.in(), NULL);
- ensure_equals("total append size", count, 2 * str_len);
- LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
- U8* first = (*it).data();
- count = mBuffer.countAfter(ch.in(), first);
- ensure_equals("offset append size", count, (2 * str_len) - 1);
- }
-
- template<> template<>
- void buffer_object::test<3>()
- {
- const char ONE[] = "one";
- const char TWO[] = "two";
- std::string expected(ONE);
- expected.append(TWO);
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.in(), (U8*)ONE, 3);
- mBuffer.append(ch.in(), (U8*)TWO, 3);
- char buffer[255]; /* Flawfinder: ignore */
- S32 len = 6;
- mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
- ensure_equals(len, 6);
- buffer[len] = '\0';
- std::string actual(buffer);
- ensure_equals("read", actual, expected);
- }
-
- template<> template<>
- void buffer_object::test<4>()
- {
- const char ONE[] = "one";
- const char TWO[] = "two";
- std::string expected(ONE);
- expected.append(TWO);
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.in(), (U8*)TWO, 3);
- mBuffer.prepend(ch.in(), (U8*)ONE, 3);
- char buffer[255]; /* Flawfinder: ignore */
- S32 len = 6;
- mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
- ensure_equals(len, 6);
- buffer[len] = '\0';
- std::string actual(buffer);
- ensure_equals("read", actual, expected);
- }
-
- template<> template<>
- void buffer_object::test<5>()
- {
- const char ONE[] = "one";
- const char TWO[] = "two";
- std::string expected("netwo");
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.in(), (U8*)TWO, 3);
- mBuffer.prepend(ch.in(), (U8*)ONE, 3);
- char buffer[255]; /* Flawfinder: ignore */
- S32 len = 5;
- LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
- U8* addr = (*it).data();
- mBuffer.readAfter(ch.in(), addr, (U8*)buffer, len);
- ensure_equals(len, 5);
- buffer[len] = '\0';
- std::string actual(buffer);
- ensure_equals("read", actual, expected);
- }
-
- template<> template<>
- void buffer_object::test<6>()
- {
- std::string request("The early bird catches the worm.");
- std::string response("If you're a worm, sleep late.");
- std::ostringstream expected;
- expected << "ContentLength: " << response.length() << "\r\n\r\n"
- << response;
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.in(), (U8*)request.c_str(), request.length());
- mBuffer.append(ch.out(), (U8*)response.c_str(), response.length());
- S32 count = mBuffer.countAfter(ch.out(), NULL);
- std::ostringstream header;
- header << "ContentLength: " << count << "\r\n\r\n";
- std::string head(header.str());
- mBuffer.prepend(ch.out(), (U8*)head.c_str(), head.length());
- char buffer[1024]; /* Flawfinder: ignore */
- S32 len = response.size() + head.length();
- ensure_equals("same length", len, (S32)expected.str().length());
- mBuffer.readAfter(ch.out(), NULL, (U8*)buffer, len);
- buffer[len] = '\0';
- std::string actual(buffer);
- ensure_equals("threaded writes", actual, expected.str());
- }
-
- template<> template<>
- void buffer_object::test<7>()
- {
- const S32 LINE_COUNT = 3;
- std::string lines[LINE_COUNT] =
- {
- std::string("GET /index.htm HTTP/1.0\r\n"),
- std::string("User-Agent: Wget/1.9.1\r\n"),
- std::string("Host: localhost:8008\r\n")
- };
- std::string text;
- S32 i;
- for(i = 0; i < LINE_COUNT; ++i)
- {
- text.append(lines[i]);
- }
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.in(), (U8*)text.c_str(), text.length());
- const S32 BUFFER_LEN = 1024;
- char buf[BUFFER_LEN];
- S32 len;
- U8* last = NULL;
- std::string last_line;
- for(i = 0; i < LINE_COUNT; ++i)
- {
- len = BUFFER_LEN;
- last = mBuffer.readAfter(ch.in(), last, (U8*)buf, len);
- char* newline = strchr((char*)buf, '\n');
- S32 offset = -((len - 1) - (newline - buf));
- ++newline;
- *newline = '\0';
- last_line.assign(buf);
- std::ostringstream message;
- message << "line reads in line[" << i << "]";
- ensure_equals(message.str().c_str(), last_line, lines[i]);
- last = mBuffer.seek(ch.in(), last, offset);
- }
- }
-
- template<> template<>
- void buffer_object::test<8>()
- {
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.in(), (U8*)"1", 1);
- LLBufferArray buffer;
- buffer.append(ch.in(), (U8*)"2", 1);
- mBuffer.takeContents(buffer);
- mBuffer.append(ch.in(), (U8*)"3", 1);
- S32 count = mBuffer.countAfter(ch.in(), NULL);
- ensure_equals("buffer size", count, 3);
- U8* temp = new U8[count];
- mBuffer.readAfter(ch.in(), NULL, temp, count);
- ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
- delete[] temp;
- }
-
- template<> template<>
- void buffer_object::test<9>()
- {
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.in(), (U8*)"1", 1);
- S32 capacity = mBuffer.capacity();
- ensure("has capacity", capacity > 0);
- U8* temp = new U8[capacity - 1];
- mBuffer.append(ch.in(), temp, capacity - 1);
- capacity = mBuffer.capacity();
- ensure("has capacity when full", capacity > 0);
- S32 used = mBuffer.countAfter(ch.in(), NULL);
- ensure_equals("used equals capacity", used, capacity);
-
- LLBufferArray::segment_iterator_t iter = mBuffer.beginSegment();
- while(iter != mBuffer.endSegment())
- {
- mBuffer.eraseSegment(iter++);
- }
-
- used = mBuffer.countAfter(ch.in(), NULL);
- ensure_equals("used is zero", used, 0);
- S32 capacity2 = mBuffer.capacity();
- ensure_equals("capacity the same after erase", capacity2, capacity);
- mBuffer.append(ch.in(), temp, capacity - 1);
- capacity2 = mBuffer.capacity();
- ensure_equals("capacity the same after append", capacity2, capacity);
-
- delete[] temp;
- }
+ struct buffer_data
+ {
+ LLBufferArray mBuffer;
+ };
+ typedef test_group<buffer_data> buffer_test;
+ typedef buffer_test::object buffer_object;
+ tut::buffer_test tba("buffer_array");
+
+ template<> template<>
+ void buffer_object::test<1>()
+ {
+ const char HELLO_WORLD[] = "hello world";
+ const S32 str_len = strlen(HELLO_WORLD);
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("total append size", count, str_len);
+ LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
+ U8* first = (*it).data();
+ count = mBuffer.countAfter(ch.in(), first);
+ ensure_equals("offset append size", count, str_len - 1);
+ }
+
+ template<> template<>
+ void buffer_object::test<2>()
+ {
+ const char HELLO_WORLD[] = "hello world";
+ const S32 str_len = strlen(HELLO_WORLD); /* Flawfinder: ignore */
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
+ mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("total append size", count, 2 * str_len);
+ LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
+ U8* first = (*it).data();
+ count = mBuffer.countAfter(ch.in(), first);
+ ensure_equals("offset append size", count, (2 * str_len) - 1);
+ }
+
+ template<> template<>
+ void buffer_object::test<3>()
+ {
+ const char ONE[] = "one";
+ const char TWO[] = "two";
+ std::string expected(ONE);
+ expected.append(TWO);
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)ONE, 3);
+ mBuffer.append(ch.in(), (U8*)TWO, 3);
+ char buffer[255]; /* Flawfinder: ignore */
+ S32 len = 6;
+ mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
+ ensure_equals(len, 6);
+ buffer[len] = '\0';
+ std::string actual(buffer);
+ ensure_equals("read", actual, expected);
+ }
+
+ template<> template<>
+ void buffer_object::test<4>()
+ {
+ const char ONE[] = "one";
+ const char TWO[] = "two";
+ std::string expected(ONE);
+ expected.append(TWO);
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)TWO, 3);
+ mBuffer.prepend(ch.in(), (U8*)ONE, 3);
+ char buffer[255]; /* Flawfinder: ignore */
+ S32 len = 6;
+ mBuffer.readAfter(ch.in(), NULL, (U8*)buffer, len);
+ ensure_equals(len, 6);
+ buffer[len] = '\0';
+ std::string actual(buffer);
+ ensure_equals("read", actual, expected);
+ }
+
+ template<> template<>
+ void buffer_object::test<5>()
+ {
+ const char ONE[] = "one";
+ const char TWO[] = "two";
+ std::string expected("netwo");
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)TWO, 3);
+ mBuffer.prepend(ch.in(), (U8*)ONE, 3);
+ char buffer[255]; /* Flawfinder: ignore */
+ S32 len = 5;
+ LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
+ U8* addr = (*it).data();
+ mBuffer.readAfter(ch.in(), addr, (U8*)buffer, len);
+ ensure_equals(len, 5);
+ buffer[len] = '\0';
+ std::string actual(buffer);
+ ensure_equals("read", actual, expected);
+ }
+
+ template<> template<>
+ void buffer_object::test<6>()
+ {
+ std::string request("The early bird catches the worm.");
+ std::string response("If you're a worm, sleep late.");
+ std::ostringstream expected;
+ expected << "ContentLength: " << response.length() << "\r\n\r\n"
+ << response;
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)request.c_str(), request.length());
+ mBuffer.append(ch.out(), (U8*)response.c_str(), response.length());
+ S32 count = mBuffer.countAfter(ch.out(), NULL);
+ std::ostringstream header;
+ header << "ContentLength: " << count << "\r\n\r\n";
+ std::string head(header.str());
+ mBuffer.prepend(ch.out(), (U8*)head.c_str(), head.length());
+ char buffer[1024]; /* Flawfinder: ignore */
+ S32 len = response.size() + head.length();
+ ensure_equals("same length", len, (S32)expected.str().length());
+ mBuffer.readAfter(ch.out(), NULL, (U8*)buffer, len);
+ buffer[len] = '\0';
+ std::string actual(buffer);
+ ensure_equals("threaded writes", actual, expected.str());
+ }
+
+ template<> template<>
+ void buffer_object::test<7>()
+ {
+ const S32 LINE_COUNT = 3;
+ std::string lines[LINE_COUNT] =
+ {
+ std::string("GET /index.htm HTTP/1.0\r\n"),
+ std::string("User-Agent: Wget/1.9.1\r\n"),
+ std::string("Host: localhost:8008\r\n")
+ };
+ std::string text;
+ S32 i;
+ for(i = 0; i < LINE_COUNT; ++i)
+ {
+ text.append(lines[i]);
+ }
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)text.c_str(), text.length());
+ const S32 BUFFER_LEN = 1024;
+ char buf[BUFFER_LEN];
+ S32 len;
+ U8* last = NULL;
+ std::string last_line;
+ for(i = 0; i < LINE_COUNT; ++i)
+ {
+ len = BUFFER_LEN;
+ last = mBuffer.readAfter(ch.in(), last, (U8*)buf, len);
+ char* newline = strchr((char*)buf, '\n');
+ S32 offset = -((len - 1) - (newline - buf));
+ ++newline;
+ *newline = '\0';
+ last_line.assign(buf);
+ std::ostringstream message;
+ message << "line reads in line[" << i << "]";
+ ensure_equals(message.str().c_str(), last_line, lines[i]);
+ last = mBuffer.seek(ch.in(), last, offset);
+ }
+ }
+
+ template<> template<>
+ void buffer_object::test<8>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)"1", 1);
+ LLBufferArray buffer;
+ buffer.append(ch.in(), (U8*)"2", 1);
+ mBuffer.takeContents(buffer);
+ mBuffer.append(ch.in(), (U8*)"3", 1);
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("buffer size", count, 3);
+ U8* temp = new U8[count];
+ mBuffer.readAfter(ch.in(), NULL, temp, count);
+ ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
+ delete[] temp;
+ }
+
+ template<> template<>
+ void buffer_object::test<9>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.in(), (U8*)"1", 1);
+ S32 capacity = mBuffer.capacity();
+ ensure("has capacity", capacity > 0);
+ U8* temp = new U8[capacity - 1];
+ mBuffer.append(ch.in(), temp, capacity - 1);
+ capacity = mBuffer.capacity();
+ ensure("has capacity when full", capacity > 0);
+ S32 used = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("used equals capacity", used, capacity);
+
+ LLBufferArray::segment_iterator_t iter = mBuffer.beginSegment();
+ while(iter != mBuffer.endSegment())
+ {
+ mBuffer.eraseSegment(iter++);
+ }
+
+ used = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("used is zero", used, 0);
+ S32 capacity2 = mBuffer.capacity();
+ ensure_equals("capacity the same after erase", capacity2, capacity);
+ mBuffer.append(ch.in(), temp, capacity - 1);
+ capacity2 = mBuffer.capacity();
+ ensure_equals("capacity the same after append", capacity2, capacity);
+
+ delete[] temp;
+ }
#if 0
- template<> template<>
- void buffer_object::test<9>()
- {
- char buffer[1024]; /* Flawfinder: ignore */
- S32 size = sprintf(buffer,
- "%d|%d|%s|%s|%s|%s|%s|%x|%x|%x|%x|%x|%s|%s|%d|%d|%x",
- 7,
- 7,
- "Hang Glider INFO",
- "18e84d1e-04a4-4c0d-8cb6-6c73477f0a9a",
- "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
- "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
- "00000000-0000-0000-0000-000000000000",
- 0x7fffffff,
- 0x7fffffff,
- 0,
- 0,
- 0x7fffffff,
- "69e0d357-2e7c-8990-a2bc-7f61c868e5a3",
- "2004-06-04 16:09:17 note card",
- 0,
- 10,
- 0) + 1;
-
- //const char* expected = "7|7|Hang Glider INFO|18e84d1e-04a4-4c0d-8cb6-6c73477f0a9a|0e346d8b-4433-4d66-a6b0-fd37083abc4c|0e346d8b-4433-4d66-a6b0-fd37083abc4c|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|7fffffff|69e0d357-2e7c-8990-a2bc-7f61c868e5a3|2004-06-04 16:09:17 note card|0|10|0\0";
-
- LLSD* bin_bucket = LLIMInfo::buildSDfrombuffer((U8*)buffer,size);
-
- char post_buffer[1024];
- U32 post_size;
- LLIMInfo::getBinaryBucket(bin_bucket,(U8*)post_buffer,post_size);
- ensure_equals("Buffer sizes",size,(S32)post_size);
- ensure("Buffer content",!strcmp(buffer,post_buffer));
- }
+ template<> template<>
+ void buffer_object::test<9>()
+ {
+ char buffer[1024]; /* Flawfinder: ignore */
+ S32 size = sprintf(buffer,
+ "%d|%d|%s|%s|%s|%s|%s|%x|%x|%x|%x|%x|%s|%s|%d|%d|%x",
+ 7,
+ 7,
+ "Hang Glider INFO",
+ "18e84d1e-04a4-4c0d-8cb6-6c73477f0a9a",
+ "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
+ "0e346d8b-4433-4d66-a6b0-fd37083abc4c",
+ "00000000-0000-0000-0000-000000000000",
+ 0x7fffffff,
+ 0x7fffffff,
+ 0,
+ 0,
+ 0x7fffffff,
+ "69e0d357-2e7c-8990-a2bc-7f61c868e5a3",
+ "2004-06-04 16:09:17 note card",
+ 0,
+ 10,
+ 0) + 1;
+
+ //const char* expected = "7|7|Hang Glider INFO|18e84d1e-04a4-4c0d-8cb6-6c73477f0a9a|0e346d8b-4433-4d66-a6b0-fd37083abc4c|0e346d8b-4433-4d66-a6b0-fd37083abc4c|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|7fffffff|69e0d357-2e7c-8990-a2bc-7f61c868e5a3|2004-06-04 16:09:17 note card|0|10|0\0";
+
+ LLSD* bin_bucket = LLIMInfo::buildSDfrombuffer((U8*)buffer,size);
+
+ char post_buffer[1024];
+ U32 post_size;
+ LLIMInfo::getBinaryBucket(bin_bucket,(U8*)post_buffer,post_size);
+ ensure_equals("Buffer sizes",size,(S32)post_size);
+ ensure("Buffer content",!strcmp(buffer,post_buffer));
+ }
#endif
- /*
- template<> template<>
- void buffer_object::test<>()
- {
- }
- */
+ /*
+ template<> template<>
+ void buffer_object::test<>()
+ {
+ }
+ */
}
namespace tut
{
- struct buffer_and_stream_data
- {
- LLBufferArray mBuffer;
- };
- typedef test_group<buffer_and_stream_data> bas_test;
- typedef bas_test::object bas_object;
- tut::bas_test tbs("buffer_stream");
-
- template<> template<>
- void bas_object::test<1>()
- {
- const char HELLO_WORLD[] = "hello world";
- const S32 str_len = strlen(HELLO_WORLD); /* Flawfinder: ignore */
- LLChannelDescriptors ch = mBuffer.nextChannel();
- LLBufferStream str(ch, &mBuffer);
- mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
- std::string hello;
- std::string world;
- str >> hello >> world;
- ensure_equals("first word", hello, std::string("hello"));
- ensure_equals("second word", world, std::string("world"));
- }
-
- template<> template<>
- void bas_object::test<2>()
- {
- std::string part1("Eat my shor");
- std::string part2("ts ho");
- std::string part3("mer");
- std::string ignore("ignore me");
- LLChannelDescriptors ch = mBuffer.nextChannel();
- LLBufferStream str(ch, &mBuffer);
- mBuffer.append(ch.in(), (U8*)part1.c_str(), part1.length());
- mBuffer.append(ch.in(), (U8*)part2.c_str(), part2.length());
- mBuffer.append(ch.out(), (U8*)ignore.c_str(), ignore.length());
- mBuffer.append(ch.in(), (U8*)part3.c_str(), part3.length());
- std::string eat;
- std::string my;
- std::string shorts;
- std::string homer;
- str >> eat >> my >> shorts >> homer;
- ensure_equals("word1", eat, std::string("Eat"));
- ensure_equals("word2", my, std::string("my"));
- ensure_equals("word3", shorts, std::string("shorts"));
- ensure_equals("word4", homer, std::string("homer"));
- }
-
- template<> template<>
- void bas_object::test<3>()
- {
- std::string part1("junk in ");
- std::string part2("the trunk");
- const S32 CHANNEL = 0;
- mBuffer.append(CHANNEL, (U8*)part1.c_str(), part1.length());
- mBuffer.append(CHANNEL, (U8*)part2.c_str(), part2.length());
- U8* last = 0;
- const S32 BUF_LEN = 128;
- char buf[BUF_LEN];
- S32 len = 11;
- last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
- buf[len] = '\0';
- std::string actual(buf);
- ensure_equals("first read", actual, std::string("junk in the"));
- last = mBuffer.seek(CHANNEL, last, -6);
- len = 12;
- last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
- buf[len] = '\0';
- actual.assign(buf);
- ensure_equals("seek and read", actual, std::string("in the trunk"));
- }
-
- template<> template<>
- void bas_object::test<4>()
- {
- std::string phrase("zippity do da!");
- const S32 CHANNEL = 0;
- mBuffer.append(CHANNEL, (U8*)phrase.c_str(), phrase.length());
- const S32 BUF_LEN = 128;
- char buf[BUF_LEN];
- S32 len = 7;
- U8* last = mBuffer.readAfter(CHANNEL, NULL, (U8*)buf, len);
- mBuffer.splitAfter(last);
- LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
- LLBufferArray::segment_iterator_t end = mBuffer.endSegment();
- std::string first((char*)((*it).data()), (*it).size());
- ensure_equals("first part", first, std::string("zippity"));
- ++it;
- std::string second((char*)((*it).data()), (*it).size());
- ensure_equals("second part", second, std::string(" do da!"));
- ++it;
- ensure("iterators equal", (it == end));
- }
-
- template<> template<>
- void bas_object::test<5>()
- {
- LLChannelDescriptors ch = mBuffer.nextChannel();
- LLBufferStream str(ch, &mBuffer);
- std::string h1("hello");
- std::string h2(", how are you doing?");
- std::string expected(h1);
- expected.append(h2);
- str << h1 << h2;
- str.flush();
- const S32 BUF_LEN = 128;
- char buf[BUF_LEN];
- S32 actual_len = BUF_LEN;
- S32 expected_len = h1.size() + h2.size();
- (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
- ensure_equals("streamed size", actual_len, expected_len);
- buf[actual_len] = '\0';
- std::string actual(buf);
- ensure_equals("streamed to buf", actual, expected);
- }
-
- template<> template<>
- void bas_object::test<6>()
- {
- LLChannelDescriptors ch = mBuffer.nextChannel();
- LLBufferStream bstr(ch, &mBuffer);
- std::ostringstream ostr;
- std::vector<LLUUID> ids;
- LLUUID id;
- for(int i = 0; i < 5; ++i)
- {
- id.generate();
- ids.push_back(id);
- }
- bstr << "SELECT concat(u.username, ' ', l.name) "
- << "FROM user u, user_last_name l "
- << "WHERE u.last_name_id = l.last_name_id"
- << " AND u.agent_id IN ('";
- ostr << "SELECT concat(u.username, ' ', l.name) "
- << "FROM user u, user_last_name l "
- << "WHERE u.last_name_id = l.last_name_id"
- << " AND u.agent_id IN ('";
- std::copy(
- ids.begin(),
- ids.end(),
- std::ostream_iterator<LLUUID>(bstr, "','"));
- std::copy(
- ids.begin(),
- ids.end(),
- std::ostream_iterator<LLUUID>(ostr, "','"));
- bstr.seekp(-2, std::ios::cur);
- ostr.seekp(-2, std::ios::cur);
- bstr << ") ";
- ostr << ") ";
- bstr.flush();
- const S32 BUF_LEN = 512;
- char buf[BUF_LEN]; /* Flawfinder: ignore */
- S32 actual_len = BUF_LEN;
- (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
- buf[actual_len] = '\0';
- std::string actual(buf);
- std::string expected(ostr.str());
- ensure_equals("size of string in seek",actual.size(),expected.size());
- ensure_equals("seek in ostream", actual, expected);
- }
-
- template<> template<>
- void bas_object::test<7>()
- {
- LLChannelDescriptors ch = mBuffer.nextChannel();
- LLBufferStream bstr(ch, &mBuffer);
- bstr << "1";
- bstr.flush();
- S32 count = mBuffer.countAfter(ch.out(), NULL);
- ensure_equals("buffer size 1", count, 1);
- LLBufferArray buffer;
- buffer.append(ch.out(), (U8*)"2", 1);
- mBuffer.takeContents(buffer);
- count = mBuffer.countAfter(ch.out(), NULL);
- ensure_equals("buffer size 2", count, 2);
- bstr << "3";
- bstr.flush();
- count = mBuffer.countAfter(ch.out(), NULL);
- ensure_equals("buffer size 3", count, 3);
- U8* temp = new U8[count];
- mBuffer.readAfter(ch.out(), NULL, temp, count);
- ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
- delete[] temp;
- }
-
- template<> template<>
- void bas_object::test<8>()
- {
- LLChannelDescriptors ch = mBuffer.nextChannel();
- LLBufferStream ostr(ch, &mBuffer);
- typedef std::vector<U8> buf_t;
- typedef std::vector<buf_t> actual_t;
- actual_t actual;
- buf_t source;
- bool need_comma = false;
- ostr << "[";
- S32 total_size = 1;
- for(S32 i = 2000; i < 2003; ++i)
- {
- if(need_comma)
- {
- ostr << ",";
- ++total_size;
- }
- need_comma = true;
- srand(69 + i); /* Flawfinder: ignore */
- S32 size = rand() % 1000 + 1000;
- std::generate_n(
- std::back_insert_iterator<buf_t>(source),
- size,
- rand);
- actual.push_back(source);
- ostr << "b(" << size << ")\"";
- total_size += 8;
- ostr.write((const char*)(&source[0]), size);
- total_size += size;
- source.clear();
- ostr << "\"";
- ++total_size;
- }
- ostr << "]";
- ++total_size;
- ostr.flush();
-
- // now that we have a bunch of data on a stream, parse it all.
- ch = mBuffer.nextChannel();
- S32 count = mBuffer.countAfter(ch.in(), NULL);
- ensure_equals("size of buffer", count, total_size);
- LLBufferStream istr(ch, &mBuffer);
- LLSD data;
- count = LLSDSerialize::fromNotation(data, istr, total_size);
- ensure("sd parsed", data.isDefined());
-
- for(S32 j = 0; j < 3; ++j)
- {
- std::ostringstream name;
- LLSD child(data[j]);
- name << "found buffer " << j;
- ensure(name.str(), child.isDefined());
- source = child.asBinary();
- name.str("");
- name << "buffer " << j << " size";
- ensure_equals(name.str().c_str(), source.size(), actual[j].size());
- name.str("");
- name << "buffer " << j << " contents";
- ensure(
- name.str(),
- (0 == memcmp(&source[0], &actual[j][0], source.size())));
- }
- }
-
- template<> template<>
- void bas_object::test<9>()
- {
- LLChannelDescriptors ch = mBuffer.nextChannel();
- LLBufferStream ostr(ch, &mBuffer);
- typedef std::vector<U8> buf_t;
- buf_t source;
- bool need_comma = false;
- ostr << "{";
- S32 total_size = 1;
- for(S32 i = 1000; i < 3000; ++i)
- {
- if(need_comma)
- {
- ostr << ",";
- ++total_size;
- }
- need_comma = true;
- ostr << "'" << i << "':";
- total_size += 7;
- srand(69 + i); /* Flawfinder: ignore */
- S32 size = rand() % 1000 + 1000;
- std::generate_n(
- std::back_insert_iterator<buf_t>(source),
- size,
- rand);
- ostr << "b(" << size << ")\"";
- total_size += 8;
- ostr.write((const char*)(&source[0]), size);
- total_size += size;
- source.clear();
- ostr << "\"";
- ++total_size;
- }
- ostr << "}";
- ++total_size;
- ostr.flush();
-
- // now that we have a bunch of data on a stream, parse it all.
- ch = mBuffer.nextChannel();
- S32 count = mBuffer.countAfter(ch.in(), NULL);
- ensure_equals("size of buffer", count, total_size);
- LLBufferStream istr(ch, &mBuffer);
- LLSD data;
- count = LLSDSerialize::fromNotation(data, istr, total_size);
- ensure("sd parsed", data.isDefined());
- }
-
- template<> template<>
- void bas_object::test<10>()
- {
+ struct buffer_and_stream_data
+ {
+ LLBufferArray mBuffer;
+ };
+ typedef test_group<buffer_and_stream_data> bas_test;
+ typedef bas_test::object bas_object;
+ tut::bas_test tbs("buffer_stream");
+
+ template<> template<>
+ void bas_object::test<1>()
+ {
+ const char HELLO_WORLD[] = "hello world";
+ const S32 str_len = strlen(HELLO_WORLD); /* Flawfinder: ignore */
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream str(ch, &mBuffer);
+ mBuffer.append(ch.in(), (U8*)HELLO_WORLD, str_len);
+ std::string hello;
+ std::string world;
+ str >> hello >> world;
+ ensure_equals("first word", hello, std::string("hello"));
+ ensure_equals("second word", world, std::string("world"));
+ }
+
+ template<> template<>
+ void bas_object::test<2>()
+ {
+ std::string part1("Eat my shor");
+ std::string part2("ts ho");
+ std::string part3("mer");
+ std::string ignore("ignore me");
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream str(ch, &mBuffer);
+ mBuffer.append(ch.in(), (U8*)part1.c_str(), part1.length());
+ mBuffer.append(ch.in(), (U8*)part2.c_str(), part2.length());
+ mBuffer.append(ch.out(), (U8*)ignore.c_str(), ignore.length());
+ mBuffer.append(ch.in(), (U8*)part3.c_str(), part3.length());
+ std::string eat;
+ std::string my;
+ std::string shorts;
+ std::string homer;
+ str >> eat >> my >> shorts >> homer;
+ ensure_equals("word1", eat, std::string("Eat"));
+ ensure_equals("word2", my, std::string("my"));
+ ensure_equals("word3", shorts, std::string("shorts"));
+ ensure_equals("word4", homer, std::string("homer"));
+ }
+
+ template<> template<>
+ void bas_object::test<3>()
+ {
+ std::string part1("junk in ");
+ std::string part2("the trunk");
+ const S32 CHANNEL = 0;
+ mBuffer.append(CHANNEL, (U8*)part1.c_str(), part1.length());
+ mBuffer.append(CHANNEL, (U8*)part2.c_str(), part2.length());
+ U8* last = 0;
+ const S32 BUF_LEN = 128;
+ char buf[BUF_LEN];
+ S32 len = 11;
+ last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
+ buf[len] = '\0';
+ std::string actual(buf);
+ ensure_equals("first read", actual, std::string("junk in the"));
+ last = mBuffer.seek(CHANNEL, last, -6);
+ len = 12;
+ last = mBuffer.readAfter(CHANNEL, last, (U8*)buf, len);
+ buf[len] = '\0';
+ actual.assign(buf);
+ ensure_equals("seek and read", actual, std::string("in the trunk"));
+ }
+
+ template<> template<>
+ void bas_object::test<4>()
+ {
+ std::string phrase("zippity do da!");
+ const S32 CHANNEL = 0;
+ mBuffer.append(CHANNEL, (U8*)phrase.c_str(), phrase.length());
+ const S32 BUF_LEN = 128;
+ char buf[BUF_LEN];
+ S32 len = 7;
+ U8* last = mBuffer.readAfter(CHANNEL, NULL, (U8*)buf, len);
+ mBuffer.splitAfter(last);
+ LLBufferArray::segment_iterator_t it = mBuffer.beginSegment();
+ LLBufferArray::segment_iterator_t end = mBuffer.endSegment();
+ std::string first((char*)((*it).data()), (*it).size());
+ ensure_equals("first part", first, std::string("zippity"));
+ ++it;
+ std::string second((char*)((*it).data()), (*it).size());
+ ensure_equals("second part", second, std::string(" do da!"));
+ ++it;
+ ensure("iterators equal", (it == end));
+ }
+
+ template<> template<>
+ void bas_object::test<5>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream str(ch, &mBuffer);
+ std::string h1("hello");
+ std::string h2(", how are you doing?");
+ std::string expected(h1);
+ expected.append(h2);
+ str << h1 << h2;
+ str.flush();
+ const S32 BUF_LEN = 128;
+ char buf[BUF_LEN];
+ S32 actual_len = BUF_LEN;
+ S32 expected_len = h1.size() + h2.size();
+ (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
+ ensure_equals("streamed size", actual_len, expected_len);
+ buf[actual_len] = '\0';
+ std::string actual(buf);
+ ensure_equals("streamed to buf", actual, expected);
+ }
+
+ template<> template<>
+ void bas_object::test<6>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream bstr(ch, &mBuffer);
+ std::ostringstream ostr;
+ std::vector<LLUUID> ids;
+ LLUUID id;
+ for(int i = 0; i < 5; ++i)
+ {
+ id.generate();
+ ids.push_back(id);
+ }
+ bstr << "SELECT concat(u.username, ' ', l.name) "
+ << "FROM user u, user_last_name l "
+ << "WHERE u.last_name_id = l.last_name_id"
+ << " AND u.agent_id IN ('";
+ ostr << "SELECT concat(u.username, ' ', l.name) "
+ << "FROM user u, user_last_name l "
+ << "WHERE u.last_name_id = l.last_name_id"
+ << " AND u.agent_id IN ('";
+ std::copy(
+ ids.begin(),
+ ids.end(),
+ std::ostream_iterator<LLUUID>(bstr, "','"));
+ std::copy(
+ ids.begin(),
+ ids.end(),
+ std::ostream_iterator<LLUUID>(ostr, "','"));
+ bstr.seekp(-2, std::ios::cur);
+ ostr.seekp(-2, std::ios::cur);
+ bstr << ") ";
+ ostr << ") ";
+ bstr.flush();
+ const S32 BUF_LEN = 512;
+ char buf[BUF_LEN]; /* Flawfinder: ignore */
+ S32 actual_len = BUF_LEN;
+ (void) mBuffer.readAfter(ch.out(), NULL, (U8*)buf, actual_len);
+ buf[actual_len] = '\0';
+ std::string actual(buf);
+ std::string expected(ostr.str());
+ ensure_equals("size of string in seek",actual.size(),expected.size());
+ ensure_equals("seek in ostream", actual, expected);
+ }
+
+ template<> template<>
+ void bas_object::test<7>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream bstr(ch, &mBuffer);
+ bstr << "1";
+ bstr.flush();
+ S32 count = mBuffer.countAfter(ch.out(), NULL);
+ ensure_equals("buffer size 1", count, 1);
+ LLBufferArray buffer;
+ buffer.append(ch.out(), (U8*)"2", 1);
+ mBuffer.takeContents(buffer);
+ count = mBuffer.countAfter(ch.out(), NULL);
+ ensure_equals("buffer size 2", count, 2);
+ bstr << "3";
+ bstr.flush();
+ count = mBuffer.countAfter(ch.out(), NULL);
+ ensure_equals("buffer size 3", count, 3);
+ U8* temp = new U8[count];
+ mBuffer.readAfter(ch.out(), NULL, temp, count);
+ ensure("buffer content", (0 == memcmp(temp, (void*)"123", 3)));
+ delete[] temp;
+ }
+
+ template<> template<>
+ void bas_object::test<8>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream ostr(ch, &mBuffer);
+ typedef std::vector<U8> buf_t;
+ typedef std::vector<buf_t> actual_t;
+ actual_t actual;
+ buf_t source;
+ bool need_comma = false;
+ ostr << "[";
+ S32 total_size = 1;
+ for(S32 i = 2000; i < 2003; ++i)
+ {
+ if(need_comma)
+ {
+ ostr << ",";
+ ++total_size;
+ }
+ need_comma = true;
+ srand(69 + i); /* Flawfinder: ignore */
+ S32 size = rand() % 1000 + 1000;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(source),
+ size,
+ rand);
+ actual.push_back(source);
+ ostr << "b(" << size << ")\"";
+ total_size += 8;
+ ostr.write((const char*)(&source[0]), size);
+ total_size += size;
+ source.clear();
+ ostr << "\"";
+ ++total_size;
+ }
+ ostr << "]";
+ ++total_size;
+ ostr.flush();
+
+ // now that we have a bunch of data on a stream, parse it all.
+ ch = mBuffer.nextChannel();
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("size of buffer", count, total_size);
+ LLBufferStream istr(ch, &mBuffer);
+ LLSD data;
+ count = LLSDSerialize::fromNotation(data, istr, total_size);
+ ensure("sd parsed", data.isDefined());
+
+ for(S32 j = 0; j < 3; ++j)
+ {
+ std::ostringstream name;
+ LLSD child(data[j]);
+ name << "found buffer " << j;
+ ensure(name.str(), child.isDefined());
+ source = child.asBinary();
+ name.str("");
+ name << "buffer " << j << " size";
+ ensure_equals(name.str().c_str(), source.size(), actual[j].size());
+ name.str("");
+ name << "buffer " << j << " contents";
+ ensure(
+ name.str(),
+ (0 == memcmp(&source[0], &actual[j][0], source.size())));
+ }
+ }
+
+ template<> template<>
+ void bas_object::test<9>()
+ {
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ LLBufferStream ostr(ch, &mBuffer);
+ typedef std::vector<U8> buf_t;
+ buf_t source;
+ bool need_comma = false;
+ ostr << "{";
+ S32 total_size = 1;
+ for(S32 i = 1000; i < 3000; ++i)
+ {
+ if(need_comma)
+ {
+ ostr << ",";
+ ++total_size;
+ }
+ need_comma = true;
+ ostr << "'" << i << "':";
+ total_size += 7;
+ srand(69 + i); /* Flawfinder: ignore */
+ S32 size = rand() % 1000 + 1000;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(source),
+ size,
+ rand);
+ ostr << "b(" << size << ")\"";
+ total_size += 8;
+ ostr.write((const char*)(&source[0]), size);
+ total_size += size;
+ source.clear();
+ ostr << "\"";
+ ++total_size;
+ }
+ ostr << "}";
+ ++total_size;
+ ostr.flush();
+
+ // now that we have a bunch of data on a stream, parse it all.
+ ch = mBuffer.nextChannel();
+ S32 count = mBuffer.countAfter(ch.in(), NULL);
+ ensure_equals("size of buffer", count, total_size);
+ LLBufferStream istr(ch, &mBuffer);
+ LLSD data;
+ count = LLSDSerialize::fromNotation(data, istr, total_size);
+ ensure("sd parsed", data.isDefined());
+ }
+
+ template<> template<>
+ void bas_object::test<10>()
+ {
//#if LL_WINDOWS && _MSC_VER >= 1400
// skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
//#endif
- const char LOGIN_STREAM[] = "{'method':'login', 'parameter': [ {"
- "'uri': 'sl-am:kellys.region.siva.lindenlab.com/location?start=url&px=128&py=128&pz=128&lx=0&ly=0&lz=0'}, "
- "{'version': i1}, {'texture_data': [ '61d724fb-ad79-f637-2186-5cf457560daa', '6e38b9be-b7cc-e77a-8aec-029a42b0b416', "
- "'a9073524-e89b-2924-ca6e-a81944109a1a', '658f18b5-5f1e-e593-f5d5-36c3abc7249a', '0cc799f4-8c99-6b91-bd75-b179b12429e2', "
- "'59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '5748decc-f629-461c-9a36-a35a221fe21f', "
- "'b8fc9be2-26a6-6b47-690b-0e902e983484', 'a13ca0fe-3802-dc97-e79a-70d12171c724', 'dd9643cf-fd5d-0376-ed4a-b1cc646a97d5', "
- "'4ad13ae9-a112-af09-210a-cf9353a7a9e7', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
- "'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
- "'5748decc-f629-461c-9a36-a35a221fe21f', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97'],"
- "'session_id': '324cfa9f-fe5d-4d1c-a317-35f20a86a4d1','position': [ i128, i128, i128],'last_name': 'Linden','group_title': '-> !BLING! <-','group_name': 'test!','agent_access': 'M',"
- "'attachment_data': [ {'asset_id': 'aaede2b1-9955-09d4-5c93-2b557c778cf3','attachment_point': i6,'item_id': 'f3694abc-5122-db33-73d9-e0f4288dc2bf'}],"
- "'buddy_ids': [ '101358d5-469d-4b24-9b85-4dc3c05e635d', '1b00fec7-6265-4875-acac-80d9cfe9295c', '203ad6df-b522-491d-ba48-4e24eb57aeff', "
- "'22d4dcdb-aebb-47fa-b925-a871cc75ee48','27da3df5-1339-4463-80aa-40504ee3b3e5', '299d1720-b61f-4268-8c29-9614aa2d44c2', "
- "'2b048a24-2737-4994-9fa5-becc8e466253', '2cd5dc14-a853-49a4-be3c-a5a7178e37bc', '3de548e1-57be-cfea-2b78-83ae3ad95998', "
- "'3dee98e4-a6a3-4543-91c3-bbd528447ba7', '3e2d81a3-6263-6ffe-ad5c-8ce04bee07e9', '40e70b98-fed7-47f3-9700-1bce93f9350b', "
- "'50a9b68e-b5aa-4d35-9137-3cfebda0a15c', '54295571-9357-43ff-ae74-a83b5138160f', '6191e2d7-5f96-4856-bdab-af0f79f47ae4', "
- "'63e577d8-cd34-4235-a0a3-de0500133364', '79cfb666-4fd0-4af7-95df-fb7d96b4e24d', '8121c2f3-4a88-4c33-9899-8fc1273f47ee', "
- "'909da964-ef23-4f2a-ba13-f2a8cfd454b6','a2e76fcd-9360-4f6d-a924-000000000001', 'aaa6d664-527e-4d83-9cbb-7ef79ccc7cc8', "
- "'b79bfb6c-23be-49eb-b35b-30ff2f501b37', 'ba0d9c79-148c-4a79-8e3c-0665eebe2427', 'bc9bda98-57cd-498f-b993-4ff1ac9dec93', "
- "'c62d16f6-81cb-419d-9cac-e46dc394084d', 'd48f8fa7-2512-4fe5-80c8-c0a923412e07', 'd77e3e24-7e6c-4c3f-96d0-a1746337f8fb', "
- "'da615c63-a84b-4592-a3d6-a90dd3e92e6e', 'df47190a-7eb7-4aff-985f-2d1d3ad6c6e9', 'e3380196-72cd-499c-a2ba-caa180bd5fe4', "
- "'e937863f-f134-4207-803b-d6e686651d6c', 'efcdf98b-5269-45ef-ac7a-0671f09ea9d9'],"
- "'circuit_code': i124,'group_id': '8615c885-9cf0-bf0a-6e40-0c11462aa652','limited_to_estate': i1,'look_at': [ i0, i0, i0],"
- "'agent_id': '0e346d8b-4433-4d66-a6b0-fd37083abc4c','first_name': 'Kelly','start': 'url'}]}";
- LLChannelDescriptors ch = mBuffer.nextChannel();
- mBuffer.append(ch.out(), (U8*)LOGIN_STREAM, strlen(LOGIN_STREAM)); /* Flawfinder: ignore */
- ch = mBuffer.nextChannel();
- LLBufferStream istr(ch, &mBuffer);
- LLSD data;
- S32 count = LLSDSerialize::fromNotation(
- data,
- istr,
- mBuffer.count(ch.in()));
- ensure("parsed something", (count > 0));
- ensure("sd parsed", data.isDefined());
- ensure_equals("sd type", data.type(), LLSD::TypeMap);
- ensure("has method", data.has("method"));
- ensure("has parameter", data.has("parameter"));
- LLSD parameter = data["parameter"];
- ensure_equals("parameter is array", parameter.type(), LLSD::TypeArray);
- LLSD agent_params = parameter[2];
- std::string s_value;
- s_value = agent_params["last_name"].asString();
- ensure_equals("last name", s_value, std::string("Linden"));
- s_value = agent_params["first_name"].asString();
- ensure_equals("first name", s_value, std::string("Kelly"));
- s_value = agent_params["agent_access"].asString();
- ensure_equals("agent access", s_value, std::string("M"));
- s_value = agent_params["group_name"].asString();
- ensure_equals("group name", s_value, std::string("test!"));
- s_value = agent_params["group_title"].asString();
- ensure_equals("group title", s_value, std::string("-> !BLING! <-"));
-
- LLUUID agent_id("0e346d8b-4433-4d66-a6b0-fd37083abc4c");
- LLUUID id = agent_params["agent_id"];
- ensure_equals("agent id", id, agent_id);
- LLUUID session_id("324cfa9f-fe5d-4d1c-a317-35f20a86a4d1");
- id = agent_params["session_id"];
- ensure_equals("session id", id, session_id);
- LLUUID group_id ("8615c885-9cf0-bf0a-6e40-0c11462aa652");
- id = agent_params["group_id"];
- ensure_equals("group id", id, group_id);
-
- S32 i_val = agent_params["limited_to_estate"];
- ensure_equals("limited to estate", i_val, 1);
- i_val = agent_params["circuit_code"];
- ensure_equals("circuit code", i_val, 124);
- }
-
-
- template<> template<>
- void bas_object::test<11>()
- {
- std::string val = "{!'foo'@:#'bar'}";
- std::istringstream istr;
- istr.str(val);
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
- ensure_equals("parser error return value", count, -1);
- ensure("data undefined", sd.isUndefined());
- }
-
- template<> template<>
- void bas_object::test<12>()
- {
+ const char LOGIN_STREAM[] = "{'method':'login', 'parameter': [ {"
+ "'uri': 'sl-am:kellys.region.siva.lindenlab.com/location?start=url&px=128&py=128&pz=128&lx=0&ly=0&lz=0'}, "
+ "{'version': i1}, {'texture_data': [ '61d724fb-ad79-f637-2186-5cf457560daa', '6e38b9be-b7cc-e77a-8aec-029a42b0b416', "
+ "'a9073524-e89b-2924-ca6e-a81944109a1a', '658f18b5-5f1e-e593-f5d5-36c3abc7249a', '0cc799f4-8c99-6b91-bd75-b179b12429e2', "
+ "'59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '59fd9b64-8300-a425-aad8-2ffcbe9a49d2', '5748decc-f629-461c-9a36-a35a221fe21f', "
+ "'b8fc9be2-26a6-6b47-690b-0e902e983484', 'a13ca0fe-3802-dc97-e79a-70d12171c724', 'dd9643cf-fd5d-0376-ed4a-b1cc646a97d5', "
+ "'4ad13ae9-a112-af09-210a-cf9353a7a9e7', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
+ "'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', "
+ "'5748decc-f629-461c-9a36-a35a221fe21f', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97'],"
+ "'session_id': '324cfa9f-fe5d-4d1c-a317-35f20a86a4d1','position': [ i128, i128, i128],'last_name': 'Linden','group_title': '-> !BLING! <-','group_name': 'test!','agent_access': 'M',"
+ "'attachment_data': [ {'asset_id': 'aaede2b1-9955-09d4-5c93-2b557c778cf3','attachment_point': i6,'item_id': 'f3694abc-5122-db33-73d9-e0f4288dc2bf'}],"
+ "'buddy_ids': [ '101358d5-469d-4b24-9b85-4dc3c05e635d', '1b00fec7-6265-4875-acac-80d9cfe9295c', '203ad6df-b522-491d-ba48-4e24eb57aeff', "
+ "'22d4dcdb-aebb-47fa-b925-a871cc75ee48','27da3df5-1339-4463-80aa-40504ee3b3e5', '299d1720-b61f-4268-8c29-9614aa2d44c2', "
+ "'2b048a24-2737-4994-9fa5-becc8e466253', '2cd5dc14-a853-49a4-be3c-a5a7178e37bc', '3de548e1-57be-cfea-2b78-83ae3ad95998', "
+ "'3dee98e4-a6a3-4543-91c3-bbd528447ba7', '3e2d81a3-6263-6ffe-ad5c-8ce04bee07e9', '40e70b98-fed7-47f3-9700-1bce93f9350b', "
+ "'50a9b68e-b5aa-4d35-9137-3cfebda0a15c', '54295571-9357-43ff-ae74-a83b5138160f', '6191e2d7-5f96-4856-bdab-af0f79f47ae4', "
+ "'63e577d8-cd34-4235-a0a3-de0500133364', '79cfb666-4fd0-4af7-95df-fb7d96b4e24d', '8121c2f3-4a88-4c33-9899-8fc1273f47ee', "
+ "'909da964-ef23-4f2a-ba13-f2a8cfd454b6','a2e76fcd-9360-4f6d-a924-000000000001', 'aaa6d664-527e-4d83-9cbb-7ef79ccc7cc8', "
+ "'b79bfb6c-23be-49eb-b35b-30ff2f501b37', 'ba0d9c79-148c-4a79-8e3c-0665eebe2427', 'bc9bda98-57cd-498f-b993-4ff1ac9dec93', "
+ "'c62d16f6-81cb-419d-9cac-e46dc394084d', 'd48f8fa7-2512-4fe5-80c8-c0a923412e07', 'd77e3e24-7e6c-4c3f-96d0-a1746337f8fb', "
+ "'da615c63-a84b-4592-a3d6-a90dd3e92e6e', 'df47190a-7eb7-4aff-985f-2d1d3ad6c6e9', 'e3380196-72cd-499c-a2ba-caa180bd5fe4', "
+ "'e937863f-f134-4207-803b-d6e686651d6c', 'efcdf98b-5269-45ef-ac7a-0671f09ea9d9'],"
+ "'circuit_code': i124,'group_id': '8615c885-9cf0-bf0a-6e40-0c11462aa652','limited_to_estate': i1,'look_at': [ i0, i0, i0],"
+ "'agent_id': '0e346d8b-4433-4d66-a6b0-fd37083abc4c','first_name': 'Kelly','start': 'url'}]}";
+ LLChannelDescriptors ch = mBuffer.nextChannel();
+ mBuffer.append(ch.out(), (U8*)LOGIN_STREAM, strlen(LOGIN_STREAM)); /* Flawfinder: ignore */
+ ch = mBuffer.nextChannel();
+ LLBufferStream istr(ch, &mBuffer);
+ LLSD data;
+ S32 count = LLSDSerialize::fromNotation(
+ data,
+ istr,
+ mBuffer.count(ch.in()));
+ ensure("parsed something", (count > 0));
+ ensure("sd parsed", data.isDefined());
+ ensure_equals("sd type", data.type(), LLSD::TypeMap);
+ ensure("has method", data.has("method"));
+ ensure("has parameter", data.has("parameter"));
+ LLSD parameter = data["parameter"];
+ ensure_equals("parameter is array", parameter.type(), LLSD::TypeArray);
+ LLSD agent_params = parameter[2];
+ std::string s_value;
+ s_value = agent_params["last_name"].asString();
+ ensure_equals("last name", s_value, std::string("Linden"));
+ s_value = agent_params["first_name"].asString();
+ ensure_equals("first name", s_value, std::string("Kelly"));
+ s_value = agent_params["agent_access"].asString();
+ ensure_equals("agent access", s_value, std::string("M"));
+ s_value = agent_params["group_name"].asString();
+ ensure_equals("group name", s_value, std::string("test!"));
+ s_value = agent_params["group_title"].asString();
+ ensure_equals("group title", s_value, std::string("-> !BLING! <-"));
+
+ LLUUID agent_id("0e346d8b-4433-4d66-a6b0-fd37083abc4c");
+ LLUUID id = agent_params["agent_id"];
+ ensure_equals("agent id", id, agent_id);
+ LLUUID session_id("324cfa9f-fe5d-4d1c-a317-35f20a86a4d1");
+ id = agent_params["session_id"];
+ ensure_equals("session id", id, session_id);
+ LLUUID group_id ("8615c885-9cf0-bf0a-6e40-0c11462aa652");
+ id = agent_params["group_id"];
+ ensure_equals("group id", id, group_id);
+
+ S32 i_val = agent_params["limited_to_estate"];
+ ensure_equals("limited to estate", i_val, 1);
+ i_val = agent_params["circuit_code"];
+ ensure_equals("circuit code", i_val, 124);
+ }
+
+
+ template<> template<>
+ void bas_object::test<11>()
+ {
+ std::string val = "{!'foo'@:#'bar'}";
+ std::istringstream istr;
+ istr.str(val);
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
+ ensure_equals("parser error return value", count, -1);
+ ensure("data undefined", sd.isUndefined());
+ }
+
+ template<> template<>
+ void bas_object::test<12>()
+ {
//#if LL_WINDOWS && _MSC_VER >= 1400
// skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
//#endif
- std::string val = "{!'foo':[i1,'hi',{@'bar'#:[$i2%,^'baz'&]*}+]=}";
- std::istringstream istr;
- istr.str(val);
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
- ensure_equals("parser error return value", count, -1);
- ensure("data undefined", sd.isUndefined());
- }
+ std::string val = "{!'foo':[i1,'hi',{@'bar'#:[$i2%,^'baz'&]*}+]=}";
+ std::istringstream istr;
+ istr.str(val);
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
+ ensure_equals("parser error return value", count, -1);
+ ensure("data undefined", sd.isUndefined());
+ }
/*
- template<> template<>
- void bas_object::test<13>()
- {
- }
- template<> template<>
- void bas_object::test<14>()
- {
- }
- template<> template<>
- void bas_object::test<15>()
- {
- }
+ template<> template<>
+ void bas_object::test<13>()
+ {
+ }
+ template<> template<>
+ void bas_object::test<14>()
+ {
+ }
+ template<> template<>
+ void bas_object::test<15>()
+ {
+ }
*/
}
namespace tut
{
- class PumpAndChainTestData
- {
- protected:
- apr_pool_t* mPool;
- LLPumpIO* mPump;
- LLPumpIO::chain_t mChain;
-
- public:
- PumpAndChainTestData()
- {
- apr_pool_create(&mPool, NULL);
- mPump = new LLPumpIO(mPool);
- }
-
- ~PumpAndChainTestData()
- {
- mChain.clear();
- delete mPump;
- apr_pool_destroy(mPool);
- }
- };
- typedef test_group<PumpAndChainTestData> PumpAndChainTestGroup;
- typedef PumpAndChainTestGroup::object PumpAndChainTestObject;
- PumpAndChainTestGroup pumpAndChainTestGroup("pump_and_chain");
-
- template<> template<>
- void PumpAndChainTestObject::test<1>()
- {
- LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
-
- mChain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
- mChain.push_back(LLIOPipe::ptr_t(extractor));
-
- LLTimer timer;
- timer.setTimerExpirySec(100.0f);
-
- mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
- while(!extractor->done() && !timer.hasExpired())
- {
- mPump->pump();
- mPump->callback();
- }
-
- ensure("reading string finished", extractor->done());
- ensure_equals("string was empty", extractor->string(), "");
- }
+ class PumpAndChainTestData
+ {
+ protected:
+ apr_pool_t* mPool;
+ LLPumpIO* mPump;
+ LLPumpIO::chain_t mChain;
+
+ public:
+ PumpAndChainTestData()
+ {
+ apr_pool_create(&mPool, NULL);
+ mPump = new LLPumpIO(mPool);
+ }
+
+ ~PumpAndChainTestData()
+ {
+ mChain.clear();
+ delete mPump;
+ apr_pool_destroy(mPool);
+ }
+ };
+ typedef test_group<PumpAndChainTestData> PumpAndChainTestGroup;
+ typedef PumpAndChainTestGroup::object PumpAndChainTestObject;
+ PumpAndChainTestGroup pumpAndChainTestGroup("pump_and_chain");
+
+ template<> template<>
+ void PumpAndChainTestObject::test<1>()
+ {
+ LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
+
+ mChain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
+ mChain.push_back(LLIOPipe::ptr_t(extractor));
+
+ LLTimer timer;
+ timer.setTimerExpirySec(100.0f);
+
+ mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
+ while(!extractor->done() && !timer.hasExpired())
+ {
+ mPump->pump();
+ mPump->callback();
+ }
+
+ ensure("reading string finished", extractor->done());
+ ensure_equals("string was empty", extractor->string(), "");
+ }
}
/*
namespace tut
{
- struct double_construct
- {
- public:
- double_construct()
- {
- LL_INFOS() << "constructed" << LL_ENDL;
- }
- ~double_construct()
- {
- LL_INFOS() << "destroyed" << LL_ENDL;
- }
- };
- typedef test_group<double_construct> double_construct_test_group;
- typedef double_construct_test_group::object dc_test_object;
- double_construct_test_group dctest("double construct");
- template<> template<>
- void dc_test_object::test<1>()
- {
- ensure("test 1", true);
- }
+ struct double_construct
+ {
+ public:
+ double_construct()
+ {
+ LL_INFOS() << "constructed" << LL_ENDL;
+ }
+ ~double_construct()
+ {
+ LL_INFOS() << "destroyed" << LL_ENDL;
+ }
+ };
+ typedef test_group<double_construct> double_construct_test_group;
+ typedef double_construct_test_group::object dc_test_object;
+ double_construct_test_group dctest("double construct");
+ template<> template<>
+ void dc_test_object::test<1>()
+ {
+ ensure("test 1", true);
+ }
}
*/
namespace tut
{
- /**
- * @brief we want to test the pipes & pumps under bad conditions.
- */
- struct pipe_and_pump_fitness
- {
- public:
- enum
- {
- SERVER_LISTEN_PORT = 13050
- };
-
- pipe_and_pump_fitness()
- {
- LLFrameTimer::updateFrameTime();
- apr_pool_create(&mPool, NULL);
- mPump = new LLPumpIO(mPool);
- mSocket = LLSocket::create(
- mPool,
- LLSocket::STREAM_TCP,
- SERVER_LISTEN_PORT,
- "127.0.0.1");
- }
-
- ~pipe_and_pump_fitness()
- {
- mSocket.reset();
- delete mPump;
- apr_pool_destroy(mPool);
- }
-
- protected:
- apr_pool_t* mPool;
- LLPumpIO* mPump;
- LLSocket::ptr_t mSocket;
- };
- typedef test_group<pipe_and_pump_fitness> fitness_test_group;
- typedef fitness_test_group::object fitness_test_object;
- fitness_test_group fitness("pipe and pump fitness");
-
- template<> template<>
- void fitness_test_object::test<1>()
- {
- LL_DEBUGS() << "fitness_test_object::test<1>()" << LL_ENDL;
-
- // Set up the server
- //LL_DEBUGS() << "fitness_test_object::test<1> - setting up server."
- // << LL_ENDL;
- LLPumpIO::chain_t chain;
- typedef LLCloneIOFactory<LLPipeStringInjector> emitter_t;
- emitter_t* emitter = new emitter_t(
- new LLPipeStringInjector("suckers never play me"));
- std::shared_ptr<LLChainIOFactory> factory(emitter);
- LLIOServerSocket* server = new LLIOServerSocket(
- mPool,
- mSocket,
- factory);
- server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
- chain.push_back(LLIOPipe::ptr_t(server));
- mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
-
- // We need to tickle the pump a little to set up the listen()
- //LL_DEBUGS() << "fitness_test_object::test<1> - initializing server."
- // << LL_ENDL;
- pump_loop(mPump, 0.1f);
-
- // Set up the client
- //LL_DEBUGS() << "fitness_test_object::test<1> - connecting client."
- // << LL_ENDL;
- LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
- LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
- bool connected = client->blockingConnect(server_host);
- ensure("Connected to server", connected);
- LL_DEBUGS() << "connected" << LL_ENDL;
-
- // We have connected, since the socket reader does not block,
- // the first call to read data will return EAGAIN, so we need
- // to write something.
- chain.clear();
- chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
- chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
- chain.push_back(LLIOPipe::ptr_t(new LLIONull));
- mPump->addChain(chain, 1.0f);
-
- // Now, the server should immediately send the data, but we'll
- // never read it. pump for a bit
- F32 elapsed = pump_loop(mPump, 2.0f);
- ensure("Did not take too long", (elapsed < 3.0f));
- }
-
- template<> template<>
- void fitness_test_object::test<2>()
- {
- LL_DEBUGS() << "fitness_test_object::test<2>()" << LL_ENDL;
-
- // Set up the server
- LLPumpIO::chain_t chain;
- typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
- emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
- std::shared_ptr<LLChainIOFactory> factory(emitter);
- LLIOServerSocket* server = new LLIOServerSocket(
- mPool,
- mSocket,
- factory);
- server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
- chain.push_back(LLIOPipe::ptr_t(server));
- mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
-
- // We need to tickle the pump a little to set up the listen()
- pump_loop(mPump, 0.1f);
-
- // Set up the client
- LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
- LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
- bool connected = client->blockingConnect(server_host);
- ensure("Connected to server", connected);
- LL_DEBUGS() << "connected" << LL_ENDL;
-
- // We have connected, since the socket reader does not block,
- // the first call to read data will return EAGAIN, so we need
- // to write something.
- chain.clear();
- chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
- chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
- chain.push_back(LLIOPipe::ptr_t(new LLIONull));
- mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS / 2.0f);
-
- // Now, the server should immediately send the data, but we'll
- // never read it. pump for a bit
- F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
- ensure("Did not take too long", (elapsed < 3.0f));
- }
-
- template<> template<>
- void fitness_test_object::test<3>()
- {
- LL_DEBUGS() << "fitness_test_object::test<3>()" << LL_ENDL;
-
- // Set up the server
- LLPumpIO::chain_t chain;
- typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
- emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
- std::shared_ptr<LLChainIOFactory> factory(emitter);
- LLIOServerSocket* server = new LLIOServerSocket(
- mPool,
- mSocket,
- factory);
- server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
- chain.push_back(LLIOPipe::ptr_t(server));
- mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
-
- // We need to tickle the pump a little to set up the listen()
- pump_loop(mPump, 0.1f);
-
- // Set up the client
- LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
- LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
- bool connected = client->blockingConnect(server_host);
- ensure("Connected to server", connected);
- LL_DEBUGS() << "connected" << LL_ENDL;
-
- // We have connected, since the socket reader does not block,
- // the first call to read data will return EAGAIN, so we need
- // to write something.
- chain.clear();
- chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
- chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
- chain.push_back(LLIOPipe::ptr_t(new LLIONull));
- mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
-
- // Now, the server should immediately send the data, but we'll
- // never read it. pump for a bit
- F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f + 1.0f);
- ensure("Did not take too long", (elapsed < 4.0f));
- }
-
- template<> template<>
- void fitness_test_object::test<4>()
- {
- LL_DEBUGS() << "fitness_test_object::test<4>()" << LL_ENDL;
-
- // Set up the server
- LLPumpIO::chain_t chain;
- typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
- emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
- std::shared_ptr<LLChainIOFactory> factory(emitter);
- LLIOServerSocket* server = new LLIOServerSocket(
- mPool,
- mSocket,
- factory);
- server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS + 1.80f);
- chain.push_back(LLIOPipe::ptr_t(server));
- mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
-
- // We need to tickle the pump a little to set up the listen()
- pump_loop(mPump, 0.1f);
-
- // Set up the client
- LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
- LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
- bool connected = client->blockingConnect(server_host);
- ensure("Connected to server", connected);
- LL_DEBUGS() << "connected" << LL_ENDL;
-
- // We have connected, since the socket reader does not block,
- // the first call to read data will return EAGAIN, so we need
- // to write something.
- chain.clear();
- chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
- chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
- chain.push_back(LLIOPipe::ptr_t(new LLIONull));
- mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
-
- // Now, the server should immediately send the data, but we'll
- // never read it. pump for a bit
- F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS + 3.0f);
- ensure("Did not take too long", (elapsed < DEFAULT_CHAIN_EXPIRY_SECS));
- }
-
- template<> template<>
- void fitness_test_object::test<5>()
- {
- // Set up the server
- LLPumpIO::chain_t chain;
- typedef LLCloneIOFactory<LLIOSleeper> sleeper_t;
- sleeper_t* sleeper = new sleeper_t(new LLIOSleeper);
- std::shared_ptr<LLChainIOFactory> factory(sleeper);
- LLIOServerSocket* server = new LLIOServerSocket(
- mPool,
- mSocket,
- factory);
- server->setResponseTimeout(1.0);
- chain.push_back(LLIOPipe::ptr_t(server));
- mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
- // We need to tickle the pump a little to set up the listen()
- pump_loop(mPump, 0.1f);
- U32 count = mPump->runningChains();
- ensure_equals("server chain onboard", count, 1);
- LL_DEBUGS() << "** Server is up." << LL_ENDL;
-
- // Set up the client
- LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
- LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
- bool connected = client->blockingConnect(server_host);
- ensure("Connected to server", connected);
- LL_DEBUGS() << "connected" << LL_ENDL;
- pump_loop(mPump,0.1f);
- count = mPump->runningChains();
- ensure_equals("server chain onboard", count, 2);
- LL_DEBUGS() << "** Client is connected." << LL_ENDL;
-
- // We have connected, since the socket reader does not block,
- // the first call to read data will return EAGAIN, so we need
- // to write something.
- chain.clear();
- chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
- chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
- chain.push_back(LLIOPipe::ptr_t(new LLIONull));
- mPump->addChain(chain, 0.2f);
- chain.clear();
-
- // pump for a bit and make sure all 3 chains are running
- pump_loop(mPump,0.1f);
- count = mPump->runningChains();
- // ensure_equals("client chain onboard", count, 3); commented out because it fails frequently - appears to be timing sensitive
- LL_DEBUGS() << "** request should have been sent." << LL_ENDL;
-
- // pump for long enough the the client socket closes, and the
- // server socket should not be closed yet.
- pump_loop(mPump,0.2f);
- count = mPump->runningChains();
- ensure_equals("client chain timed out ", count, 2);
- LL_DEBUGS() << "** client chain should be closed." << LL_ENDL;
-
- // At this point, the socket should be closed by the timeout
- pump_loop(mPump,1.0f);
- count = mPump->runningChains();
- ensure_equals("accepted socked close", count, 1);
- LL_DEBUGS() << "** Sleeper should have timed out.." << LL_ENDL;
- }
+ /**
+ * @brief we want to test the pipes & pumps under bad conditions.
+ */
+ struct pipe_and_pump_fitness
+ {
+ public:
+ enum
+ {
+ SERVER_LISTEN_PORT = 13050
+ };
+
+ pipe_and_pump_fitness()
+ {
+ LLFrameTimer::updateFrameTime();
+ apr_pool_create(&mPool, NULL);
+ mPump = new LLPumpIO(mPool);
+ mSocket = LLSocket::create(
+ mPool,
+ LLSocket::STREAM_TCP,
+ SERVER_LISTEN_PORT,
+ "127.0.0.1");
+ }
+
+ ~pipe_and_pump_fitness()
+ {
+ mSocket.reset();
+ delete mPump;
+ apr_pool_destroy(mPool);
+ }
+
+ protected:
+ apr_pool_t* mPool;
+ LLPumpIO* mPump;
+ LLSocket::ptr_t mSocket;
+ };
+ typedef test_group<pipe_and_pump_fitness> fitness_test_group;
+ typedef fitness_test_group::object fitness_test_object;
+ fitness_test_group fitness("pipe and pump fitness");
+
+ template<> template<>
+ void fitness_test_object::test<1>()
+ {
+ LL_DEBUGS() << "fitness_test_object::test<1>()" << LL_ENDL;
+
+ // Set up the server
+ //LL_DEBUGS() << "fitness_test_object::test<1> - setting up server."
+ // << LL_ENDL;
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLPipeStringInjector> emitter_t;
+ emitter_t* emitter = new emitter_t(
+ new LLPipeStringInjector("suckers never play me"));
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // We need to tickle the pump a little to set up the listen()
+ //LL_DEBUGS() << "fitness_test_object::test<1> - initializing server."
+ // << LL_ENDL;
+ pump_loop(mPump, 0.1f);
+
+ // Set up the client
+ //LL_DEBUGS() << "fitness_test_object::test<1> - connecting client."
+ // << LL_ENDL;
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, 1.0f);
+
+ // Now, the server should immediately send the data, but we'll
+ // never read it. pump for a bit
+ F32 elapsed = pump_loop(mPump, 2.0f);
+ ensure("Did not take too long", (elapsed < 3.0f));
+ }
+
+ template<> template<>
+ void fitness_test_object::test<2>()
+ {
+ LL_DEBUGS() << "fitness_test_object::test<2>()" << LL_ENDL;
+
+ // Set up the server
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
+ emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // We need to tickle the pump a little to set up the listen()
+ pump_loop(mPump, 0.1f);
+
+ // Set up the client
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS / 2.0f);
+
+ // Now, the server should immediately send the data, but we'll
+ // never read it. pump for a bit
+ F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
+ ensure("Did not take too long", (elapsed < 3.0f));
+ }
+
+ template<> template<>
+ void fitness_test_object::test<3>()
+ {
+ LL_DEBUGS() << "fitness_test_object::test<3>()" << LL_ENDL;
+
+ // Set up the server
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
+ emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // We need to tickle the pump a little to set up the listen()
+ pump_loop(mPump, 0.1f);
+
+ // Set up the client
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, SHORT_CHAIN_EXPIRY_SECS * 2.0f);
+
+ // Now, the server should immediately send the data, but we'll
+ // never read it. pump for a bit
+ F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS * 2.0f + 1.0f);
+ ensure("Did not take too long", (elapsed < 4.0f));
+ }
+
+ template<> template<>
+ void fitness_test_object::test<4>()
+ {
+ LL_DEBUGS() << "fitness_test_object::test<4>()" << LL_ENDL;
+
+ // Set up the server
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLIOFuzz> emitter_t;
+ emitter_t* emitter = new emitter_t(new LLIOFuzz(1000000));
+ std::shared_ptr<LLChainIOFactory> factory(emitter);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(SHORT_CHAIN_EXPIRY_SECS + 1.80f);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // We need to tickle the pump a little to set up the listen()
+ pump_loop(mPump, 0.1f);
+
+ // Set up the client
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+
+ // Now, the server should immediately send the data, but we'll
+ // never read it. pump for a bit
+ F32 elapsed = pump_loop(mPump, SHORT_CHAIN_EXPIRY_SECS + 3.0f);
+ ensure("Did not take too long", (elapsed < DEFAULT_CHAIN_EXPIRY_SECS));
+ }
+
+ template<> template<>
+ void fitness_test_object::test<5>()
+ {
+ skip("Test is strongly timing dependent, "
+ "and on slow CI machines it fails way too often.");
+ const int retries = 100;
+ // Set up the server
+ LLPumpIO::chain_t chain;
+ typedef LLCloneIOFactory<LLIOSleeper> sleeper_t;
+ sleeper_t* sleeper = new sleeper_t(new LLIOSleeper);
+ std::shared_ptr<LLChainIOFactory> factory(sleeper);
+ LLIOServerSocket* server = new LLIOServerSocket(
+ mPool,
+ mSocket,
+ factory);
+ server->setResponseTimeout(1.0);
+ chain.push_back(LLIOPipe::ptr_t(server));
+ mPump->addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
+ // We need to tickle the pump a little to set up the listen()
+ for (int retry = 0; mPump->runningChains() < 1 && retry < retries; ++retry)
+ {
+ pump_loop(mPump, 0.1f);
+ }
+ U32 count = mPump->runningChains();
+ ensure_equals("server chain 1 onboard", count, 1);
+ LL_DEBUGS() << "** Server is up." << LL_ENDL;
+
+ // Set up the client
+ LLSocket::ptr_t client = LLSocket::create(mPool, LLSocket::STREAM_TCP);
+ LLHost server_host("127.0.0.1", SERVER_LISTEN_PORT);
+ bool connected = client->blockingConnect(server_host);
+ ensure("Connected to server", connected);
+ LL_DEBUGS() << "connected" << LL_ENDL;
+ for (int retry = 0; mPump->runningChains() < 2 && retry < retries; ++retry)
+ {
+ pump_loop(mPump,0.1f);
+ }
+ count = mPump->runningChains();
+ ensure_equals("server chain 2 onboard", count, 2);
+ LL_DEBUGS() << "** Client is connected." << LL_ENDL;
+
+ // We have connected, since the socket reader does not block,
+ // the first call to read data will return EAGAIN, so we need
+ // to write something.
+ chain.clear();
+ chain.push_back(LLIOPipe::ptr_t(new LLPipeStringInjector("hi")));
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(client)));
+ chain.push_back(LLIOPipe::ptr_t(new LLIONull));
+ mPump->addChain(chain, 0.2f);
+ chain.clear();
+
+ // pump for a bit and make sure all 3 chains are running
+ for (int retry = 0; mPump->runningChains() < 3 && retry < retries; ++retry)
+ {
+ pump_loop(mPump, 0.1f);
+ }
+ count = mPump->runningChains();
+ ensure_equals("client chain onboard", count, 3);
+ LL_DEBUGS() << "** request should have been sent." << LL_ENDL;
+
+ // pump for long enough the the client socket closes, and the
+ // server socket should not be closed yet.
+ for (int retry = 0; mPump->runningChains() == 3 && retry < retries; ++retry)
+ {
+ pump_loop(mPump, 0.1f);
+ }
+ // We used to test for count == 2 here, but on a slow test machine it
+ // can happen that not just one but two chains close before we reach
+ // this point.
+ count = mPump->runningChains();
+ ensure(stringize("client chain timed out: count ", count), count < 3);
+ LL_DEBUGS() << "** client chain should be closed." << LL_ENDL;
+
+ // At this point, the socket should be closed by the timeout
+ for (int retry = 0; mPump->runningChains() > 1 && retry < retries; ++retry)
+ {
+ pump_loop(mPump, 0.1f);
+ }
+ count = mPump->runningChains();
+ ensure_equals("accepted socked close", count, 1);
+ LL_DEBUGS() << "** Sleeper should have timed out.." << LL_ENDL;
+ }
}
/*
diff --git a/indra/test/lltut.h b/indra/test/lltut.h
index e56b4e8d1c..4ce450057c 100644
--- a/indra/test/lltut.h
+++ b/indra/test/lltut.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lltut.h
* @author Phoenix
* @date 2005-09-26
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&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$
*/
@@ -31,6 +31,8 @@
#include "is_approx_equal_fraction.h" // instead of llmath.h
#include <cstring>
+#include <string>
+#include <vector>
class LLDate;
class LLSD;
@@ -38,35 +40,35 @@ class LLURI;
namespace tut
{
- void ensure_equals(const std::string& msg,
- const LLDate& actual, const LLDate& expected);
+ void ensure_equals(const std::string& msg,
+ const LLDate& actual, const LLDate& expected);
- void ensure_equals(const std::string& msg,
- const LLURI& actual, const LLURI& expected);
+ void ensure_equals(const std::string& msg,
+ const LLURI& actual, const LLURI& expected);
- // std::vector<U8> is the current definition of LLSD::Binary. Because
- // we're only forward-declaring LLSD in this header file, we can't
- // directly reference that nested type. If the build complains that
- // there's no definition for this declaration, it could be that
- // LLSD::Binary has changed, and that this declaration must be adjusted to
- // match.
- void ensure_equals(const std::string& msg,
- const std::vector<U8>& actual, const std::vector<U8>& expected);
+ // std::vector<U8> is the current definition of LLSD::Binary. Because
+ // we're only forward-declaring LLSD in this header file, we can't
+ // directly reference that nested type. If the build complains that
+ // there's no definition for this declaration, it could be that
+ // LLSD::Binary has changed, and that this declaration must be adjusted to
+ // match.
+ void ensure_equals(const std::string& msg,
+ const std::vector<U8>& actual, const std::vector<U8>& expected);
- void ensure_equals(const std::string& msg,
- const LLSD& actual, const LLSD& expected);
+ void ensure_equals(const std::string& msg,
+ const LLSD& actual, const LLSD& expected);
- void ensure_starts_with(const std::string& msg,
- const std::string& actual, const std::string& expectedStart);
+ void ensure_starts_with(const std::string& msg,
+ const std::string& actual, const std::string& expectedStart);
- void ensure_ends_with(const std::string& msg,
- const std::string& actual, const std::string& expectedEnd);
+ void ensure_ends_with(const std::string& msg,
+ const std::string& actual, const std::string& expectedEnd);
- void ensure_contains(const std::string& msg,
- const std::string& actual, const std::string& expectedSubString);
+ void ensure_contains(const std::string& msg,
+ const std::string& actual, const std::string& expectedSubString);
- void ensure_does_not_contain(const std::string& msg,
- const std::string& actual, const std::string& expectedSubString);
+ void ensure_does_not_contain(const std::string& msg,
+ const std::string& actual, const std::string& expectedSubString);
}
// This is an odd place to #include an important contributor -- but the usual
@@ -87,73 +89,73 @@ namespace tut
// The functions BELOW this point actually consume tut.hpp functionality.
namespace tut
{
- inline void ensure_approximately_equals(const char* msg, F64 actual, F64 expected, U32 frac_bits)
- {
- if(!is_approx_equal_fraction(actual, expected, frac_bits))
- {
- std::stringstream ss;
- ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected;
- throw tut::failure(ss.str().c_str());
- }
- }
-
- inline void ensure_approximately_equals(const char* msg, F32 actual, F32 expected, U32 frac_bits)
- {
- if(!is_approx_equal_fraction(actual, expected, frac_bits))
- {
- std::stringstream ss;
- ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected;
- throw tut::failure(ss.str().c_str());
- }
- }
-
- inline void ensure_approximately_equals(F32 actual, F32 expected, U32 frac_bits)
- {
- ensure_approximately_equals(NULL, actual, expected, frac_bits);
- }
-
- inline void ensure_approximately_equals_range(const char *msg, F32 actual, F32 expected, F32 delta)
- {
- if (fabs(actual-expected)>delta)
- {
- std::stringstream ss;
- ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected << " tolerance: " << delta;
- throw tut::failure(ss.str().c_str());
- }
- }
-
- inline void ensure_memory_matches(const char* msg,const void* actual, U32 actual_len, const void* expected,U32 expected_len)
- {
- if((expected_len != actual_len) ||
- (std::memcmp(actual, expected, actual_len) != 0))
- {
- std::stringstream ss;
- ss << (msg?msg:"") << (msg?": ":"") << "not equal";
- throw tut::failure(ss.str().c_str());
- }
- }
-
- inline void ensure_memory_matches(const void* actual, U32 actual_len, const void* expected,U32 expected_len)
- {
- ensure_memory_matches(NULL, actual, actual_len, expected, expected_len);
- }
-
- template <class T,class Q>
- void ensure_not_equals(const char* msg,const Q& actual,const T& expected)
- {
- if( expected == actual )
- {
- std::stringstream ss;
- ss << (msg?msg:"") << (msg?": ":"") << "both equal " << expected;
- throw tut::failure(ss.str().c_str());
- }
- }
-
- template <class T,class Q>
- void ensure_not_equals(const Q& actual,const T& expected)
- {
- ensure_not_equals(NULL, actual, expected);
- }
+ inline void ensure_approximately_equals(const char* msg, F64 actual, F64 expected, U32 frac_bits)
+ {
+ if(!is_approx_equal_fraction(actual, expected, frac_bits))
+ {
+ std::stringstream ss;
+ ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected;
+ throw tut::failure(ss.str().c_str());
+ }
+ }
+
+ inline void ensure_approximately_equals(const char* msg, F32 actual, F32 expected, U32 frac_bits)
+ {
+ if(!is_approx_equal_fraction(actual, expected, frac_bits))
+ {
+ std::stringstream ss;
+ ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected;
+ throw tut::failure(ss.str().c_str());
+ }
+ }
+
+ inline void ensure_approximately_equals(F32 actual, F32 expected, U32 frac_bits)
+ {
+ ensure_approximately_equals(NULL, actual, expected, frac_bits);
+ }
+
+ inline void ensure_approximately_equals_range(const char *msg, F32 actual, F32 expected, F32 delta)
+ {
+ if (fabs(actual-expected)>delta)
+ {
+ std::stringstream ss;
+ ss << (msg?msg:"") << (msg?": ":"") << "not equal actual: " << actual << " expected: " << expected << " tolerance: " << delta;
+ throw tut::failure(ss.str().c_str());
+ }
+ }
+
+ inline void ensure_memory_matches(const char* msg,const void* actual, U32 actual_len, const void* expected,U32 expected_len)
+ {
+ if((expected_len != actual_len) ||
+ (std::memcmp(actual, expected, actual_len) != 0))
+ {
+ std::stringstream ss;
+ ss << (msg?msg:"") << (msg?": ":"") << "not equal";
+ throw tut::failure(ss.str().c_str());
+ }
+ }
+
+ inline void ensure_memory_matches(const void* actual, U32 actual_len, const void* expected,U32 expected_len)
+ {
+ ensure_memory_matches(NULL, actual, actual_len, expected, expected_len);
+ }
+
+ template <class T,class Q>
+ void ensure_not_equals(const char* msg,const Q& actual,const T& expected)
+ {
+ if( expected == actual )
+ {
+ std::stringstream ss;
+ ss << (msg?msg:"") << (msg?": ":"") << "both equal " << expected;
+ throw tut::failure(ss.str().c_str());
+ }
+ }
+
+ template <class T,class Q>
+ void ensure_not_equals(const Q& actual,const T& expected)
+ {
+ ensure_not_equals(NULL, actual, expected);
+ }
}
#endif // LL_LLTUT_H
diff --git a/indra/test/print.h b/indra/test/print.h
index 7577698cc8..749603907e 100644
--- a/indra/test/print.h
+++ b/indra/test/print.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2020-01-02
* @brief print() function for debugging
- *
+ *
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
* Copyright (c) 2020, Linden Research, Inc.
* $/LicenseInfo$
@@ -23,7 +23,9 @@ struct NONL_t {};
inline
void print()
{
+#ifdef LL_TEST
std::cerr << std::endl;
+#endif
}
// print(NONL) is a no-op
@@ -35,8 +37,10 @@ void print(NONL_t)
template <typename T, typename... ARGS>
void print(T&& first, ARGS&&... rest)
{
+#ifdef LL_TEST
std::cerr << first;
print(std::forward<ARGS>(rest)...);
+#endif
}
#endif /* ! defined(LL_PRINT_H) */