diff options
author | Dmitry Zaporozhan <dzaporozhan@productengine.com> | 2009-11-09 15:59:29 +0200 |
---|---|---|
committer | Dmitry Zaporozhan <dzaporozhan@productengine.com> | 2009-11-09 15:59:29 +0200 |
commit | 1b0732183e4437ce673b13c8092f8122db884587 (patch) | |
tree | dc913dbaab1699bb27854d9f22531aa2a6f86e28 | |
parent | 148a29ea1ec97922180ca8f0f6ced9a4a9e05c07 (diff) | |
parent | 21c51025da7f9128a1b425a5e88331ae0e3fe4d4 (diff) |
Merge
--HG--
branch : product-engine
1081 files changed, 36916 insertions, 24359 deletions
@@ -7,6 +7,8 @@ syntax: glob # Emacs temp files *~ .*.swp +#OSX image cache file +*.DS_Store LICENSES indra/.distcc indra/build-darwin-* @@ -27,7 +29,6 @@ indra/newview/fmod.dll indra/newview/mozilla-theme indra/newview/mozilla-universal-darwin.tgz indra/newview/res-sdl -indra/newview/skins indra/newview/vivox-runtime indra/server-linux-* indra/test/linden_file.dat @@ -48,3 +49,7 @@ tarfile_tmp ^indra/web/dataservice/lib/shared/vault.* ^indra/web/dataservice/vendor.* glob:indra/newview/dbghelp.dll +glob:*.cpp.orig +glob:*.cpp.bak +glob:*.h.bak +glob:*.h.orig diff --git a/doc/contributions.txt b/doc/contributions.txt index 942ba0f0b9..4b36c44a5f 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -139,6 +139,7 @@ Blakar Ogre blino Nakamura VWR-17 Boroondas Gupte + SNOW-278 VWR-233 WEB-262 Bulli Schumann @@ -296,6 +297,7 @@ Jacek Antonelli VWR-2947 VWR-2948 VWR-3605 + VWR-8617 JB Kraft VWR-5283 VWR-7802 @@ -372,6 +374,7 @@ Michelle2 Zenovka VWR-8310 VWR-9499 Mm Alder + VWR-197 VWR-3777 VWR-4794 VWR-13578 diff --git a/indra/cmake/WebKitLibPlugin.cmake b/indra/cmake/WebKitLibPlugin.cmake index 9ec23e80ca..1c572ab27f 100644 --- a/indra/cmake/WebKitLibPlugin.cmake +++ b/indra/cmake/WebKitLibPlugin.cmake @@ -51,6 +51,7 @@ elseif (LINUX) QtGui QtCore + jpeg fontconfig X11 Xrender diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py index 17bce6f434..fff78ecbe3 100644 --- a/indra/cmake/run_build_test.py +++ b/indra/cmake/run_build_test.py @@ -1,111 +1,111 @@ -#!/usr/bin/python
-"""\
-@file run_build_test.py
-@author Nat Goodspeed
-@date 2009-09-03
-@brief Helper script to allow CMake to run some command after setting
- environment variables.
-
-CMake has commands to run an external program. But remember that each CMake
-command must be backed by multiple build-system implementations. Unfortunately
-it seems CMake can't promise that every target build system can set specified
-environment variables before running the external program of interest.
-
-This helper script is a workaround. It simply sets the requested environment
-variables and then executes the program specified on the rest of its command
-line.
-
-Example:
-
-python run_build_test.py -DFOO=bar myprog somearg otherarg
-
-sets environment variable FOO=bar, then runs:
-myprog somearg otherarg
-
-$LicenseInfo:firstyear=2009&license=internal$
-Copyright (c) 2009, Linden Research, Inc.
-$/LicenseInfo$
-"""
-
-import os
-import sys
-import subprocess
-
-def main(command, libpath=[], vars={}):
- """Pass:
- command is a sequence (e.g. a list) of strings. The first item in the list
- must be the command name, the rest are its arguments.
-
- libpath is a sequence of directory pathnames. These will be appended to
- the platform-specific dynamic library search path environment variable.
-
- vars is a dict of arbitrary (var, value) pairs to be added to the
- environment before running 'command'.
-
- This function runs the specified command, waits for it to terminate and
- returns its return code. This will be negative if the command terminated
- with a signal, else it will be the process's specified exit code.
- """
- # Handle platform-dependent libpath first.
- if sys.platform == "win32":
- lpvars = ["PATH"]
- elif sys.platform == "darwin":
- lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"]
- elif sys.platform.startswith("linux"):
- lpvars = ["LD_LIBRARY_PATH"]
- else:
- # No idea what the right pathname might be! But only crump if this
- # feature is requested.
- if libpath:
- raise NotImplemented("run_build_test: unknown platform %s" % sys.platform)
- lpvars = []
- for var in lpvars:
- # Split the existing path. Bear in mind that the variable in question
- # might not exist; instead of KeyError, just use an empty string.
- dirs = os.environ.get(var, "").split(os.pathsep)
- # Append the sequence in libpath
-## print "%s += %r" % (var, libpath)
- dirs.extend(libpath)
- # Now rebuild the path string. This way we use a minimum of separators
- # -- and we avoid adding a pointless separator when libpath is empty.
- os.environ[var] = os.pathsep.join(dirs)
- # Now handle arbitrary environment variables. The tricky part is ensuring
- # that all the keys and values we try to pass are actually strings.
-## if vars:
-## print "Setting:"
-## for key, value in vars.iteritems():
-## print "%s=%s" % (key, value)
- os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()]))
- # Run the child process.
-## print "Running: %s" % " ".join(command)
- return subprocess.call(command)
-
-if __name__ == "__main__":
- from optparse import OptionParser
- parser = OptionParser(usage="usage: %prog [options] command args...")
- # We want optparse support for the options we ourselves handle -- but we
- # DO NOT want it looking at options for the executable we intend to run,
- # rejecting them as invalid because we don't define them. So configure the
- # parser to stop looking for options as soon as it sees the first
- # positional argument (traditional Unix syntax).
- parser.disable_interspersed_args()
- parser.add_option("-D", "--define", dest="vars", default=[], action="append",
- metavar="VAR=value",
- help="Add VAR=value to the env variables defined")
- parser.add_option("-l", "--libpath", dest="libpath", default=[], action="append",
- metavar="DIR",
- help="Add DIR to the platform-dependent DLL search path")
- opts, args = parser.parse_args()
- # What we have in opts.vars is a list of strings of the form "VAR=value"
- # or possibly just "VAR". What we want is a dict. We can build that dict by
- # constructing a list of ["VAR", "value"] pairs -- so split each
- # "VAR=value" string on the '=' sign (but only once, in case we have
- # "VAR=some=user=string"). To handle the case of just "VAR", append "" to
- # the list returned by split(), then slice off anything after the pair we
- # want.
- rc = main(command=args, libpath=opts.libpath,
- vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars]))
- if rc not in (None, 0):
- print >>sys.stderr, "Failure running: %s" % " ".join(args)
- print >>sys.stderr, "Error: %s" % rc
- sys.exit((rc < 0) and 255 or rc)
+#!/usr/bin/python +"""\ +@file run_build_test.py +@author Nat Goodspeed +@date 2009-09-03 +@brief Helper script to allow CMake to run some command after setting + environment variables. + +CMake has commands to run an external program. But remember that each CMake +command must be backed by multiple build-system implementations. Unfortunately +it seems CMake can't promise that every target build system can set specified +environment variables before running the external program of interest. + +This helper script is a workaround. It simply sets the requested environment +variables and then executes the program specified on the rest of its command +line. + +Example: + +python run_build_test.py -DFOO=bar myprog somearg otherarg + +sets environment variable FOO=bar, then runs: +myprog somearg otherarg + +$LicenseInfo:firstyear=2009&license=internal$ +Copyright (c) 2009, Linden Research, Inc. +$/LicenseInfo$ +""" + +import os +import sys +import subprocess + +def main(command, libpath=[], vars={}): + """Pass: + command is a sequence (e.g. a list) of strings. The first item in the list + must be the command name, the rest are its arguments. + + libpath is a sequence of directory pathnames. These will be appended to + the platform-specific dynamic library search path environment variable. + + vars is a dict of arbitrary (var, value) pairs to be added to the + environment before running 'command'. + + This function runs the specified command, waits for it to terminate and + returns its return code. This will be negative if the command terminated + with a signal, else it will be the process's specified exit code. + """ + # Handle platform-dependent libpath first. + if sys.platform == "win32": + lpvars = ["PATH"] + elif sys.platform == "darwin": + lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"] + elif sys.platform.startswith("linux"): + lpvars = ["LD_LIBRARY_PATH"] + else: + # No idea what the right pathname might be! But only crump if this + # feature is requested. + if libpath: + raise NotImplemented("run_build_test: unknown platform %s" % sys.platform) + lpvars = [] + for var in lpvars: + # Split the existing path. Bear in mind that the variable in question + # might not exist; instead of KeyError, just use an empty string. + dirs = os.environ.get(var, "").split(os.pathsep) + # Append the sequence in libpath +## print "%s += %r" % (var, libpath) + dirs.extend(libpath) + # Now rebuild the path string. This way we use a minimum of separators + # -- and we avoid adding a pointless separator when libpath is empty. + os.environ[var] = os.pathsep.join(dirs) + # Now handle arbitrary environment variables. The tricky part is ensuring + # that all the keys and values we try to pass are actually strings. +## if vars: +## print "Setting:" +## for key, value in vars.iteritems(): +## print "%s=%s" % (key, value) + os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()])) + # Run the child process. +## print "Running: %s" % " ".join(command) + return subprocess.call(command) + +if __name__ == "__main__": + from optparse import OptionParser + parser = OptionParser(usage="usage: %prog [options] command args...") + # We want optparse support for the options we ourselves handle -- but we + # DO NOT want it looking at options for the executable we intend to run, + # rejecting them as invalid because we don't define them. So configure the + # parser to stop looking for options as soon as it sees the first + # positional argument (traditional Unix syntax). + parser.disable_interspersed_args() + parser.add_option("-D", "--define", dest="vars", default=[], action="append", + metavar="VAR=value", + help="Add VAR=value to the env variables defined") + parser.add_option("-l", "--libpath", dest="libpath", default=[], action="append", + metavar="DIR", + help="Add DIR to the platform-dependent DLL search path") + opts, args = parser.parse_args() + # What we have in opts.vars is a list of strings of the form "VAR=value" + # or possibly just "VAR". What we want is a dict. We can build that dict by + # constructing a list of ["VAR", "value"] pairs -- so split each + # "VAR=value" string on the '=' sign (but only once, in case we have + # "VAR=some=user=string"). To handle the case of just "VAR", append "" to + # the list returned by split(), then slice off anything after the pair we + # want. + rc = main(command=args, libpath=opts.libpath, + vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars])) + if rc not in (None, 0): + print >>sys.stderr, "Failure running: %s" % " ".join(args) + print >>sys.stderr, "Error: %s" % rc + sys.exit((rc < 0) and 255 or rc) diff --git a/indra/llcharacter/llheadrotmotion.cpp b/indra/llcharacter/llheadrotmotion.cpp index 88cd77f7af..0ee378f3b8 100644 --- a/indra/llcharacter/llheadrotmotion.cpp +++ b/indra/llcharacter/llheadrotmotion.cpp @@ -251,10 +251,13 @@ BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask) mLastHeadRot = head_rot_local; // Set the head rotation. - LLQuaternion torsoRotLocal = mNeckState->getJoint()->getParent()->getWorldRotation() * currentInvRootRotWorld; - head_rot_local = head_rot_local * ~torsoRotLocal; - mNeckState->setRotation( nlerp(NECK_LAG, LLQuaternion::DEFAULT, head_rot_local) ); - mHeadState->setRotation( nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT, head_rot_local)); + if(mNeckState->getJoint() && mNeckState->getJoint()->getParent()) + { + LLQuaternion torsoRotLocal = mNeckState->getJoint()->getParent()->getWorldRotation() * currentInvRootRotWorld; + head_rot_local = head_rot_local * ~torsoRotLocal; + mNeckState->setRotation( nlerp(NECK_LAG, LLQuaternion::DEFAULT, head_rot_local) ); + mHeadState->setRotation( nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT, head_rot_local)); + } return TRUE; } diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index affc49debf..eec56d7844 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -151,7 +151,7 @@ public: virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating && !mIsDummy; } BOOL getAnimating() const { return mIsAnimating; } - void setIsDummy(BOOL is_self) { mIsDummy = is_self; } + void setIsDummy(BOOL is_dummy) { mIsDummy = is_dummy; } protected: F32 mCurWeight; // current weight diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index e7aaf3c984..f785698612 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -50,6 +50,7 @@ set(llcommon_SOURCE_FILES llfile.cpp llfindlocale.cpp llfixedbuffer.cpp + llfoldertype.cpp llformat.cpp llframetimer.cpp llheartbeat.cpp @@ -150,6 +151,7 @@ set(llcommon_HEADER_FILES llfile.h llfindlocale.h llfixedbuffer.h + llfoldertype.h llformat.h llframetimer.h llhash.h diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h index 0d6f18c5d4..50129b4526 100644 --- a/indra/llcommon/llallocator.h +++ b/indra/llcommon/llallocator.h @@ -1,63 +1,63 @@ -/**
- * @file llallocator.h
- * @brief Declaration of the LLAllocator class.
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2009-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLALLOCATOR_H
-#define LL_LLALLOCATOR_H
-
-#include <string>
-
-#include "llmemtype.h"
-#include "llallocator_heap_profile.h"
-
-class LL_COMMON_API LLAllocator {
- friend class LLMemoryView;
- friend class LLMemType;
-
-private:
- static void pushMemType(S32 type);
- static S32 popMemType();
-
-public:
- void setProfilingEnabled(bool should_enable);
-
- static bool isProfiling();
-
- LLAllocatorHeapProfile const & getProfile();
-
-private:
- std::string getRawProfile();
-
-private:
- LLAllocatorHeapProfile mProf;
-};
-
-#endif // LL_LLALLOCATOR_H
+/** + * @file llallocator.h + * @brief Declaration of the LLAllocator class. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLALLOCATOR_H +#define LL_LLALLOCATOR_H + +#include <string> + +#include "llmemtype.h" +#include "llallocator_heap_profile.h" + +class LL_COMMON_API LLAllocator { + friend class LLMemoryView; + friend class LLMemType; + +private: + static void pushMemType(S32 type); + static S32 popMemType(); + +public: + void setProfilingEnabled(bool should_enable); + + static bool isProfiling(); + + LLAllocatorHeapProfile const & getProfile(); + +private: + std::string getRawProfile(); + +private: + LLAllocatorHeapProfile mProf; +}; + +#endif // LL_LLALLOCATOR_H diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 669afc5330..ed70b1d9f2 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -57,7 +57,7 @@ void ll_init_apr() if(!LLAPRFile::sAPRFilePoolp) { - LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool() ; + LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ; } } @@ -99,13 +99,12 @@ void ll_cleanup_apr() // //LLAPRPool // -LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) -{ - mParent = parent ; - mReleasePoolFlag = releasePoolFlag ; - mMaxSize = size ; - mPool = NULL ; - +LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) + : mParent(parent), + mReleasePoolFlag(releasePoolFlag), + mMaxSize(size), + mPool(NULL) +{ createAPRPool() ; } @@ -148,31 +147,65 @@ void LLAPRPool::releaseAPRPool() } } +//virtual apr_pool_t* LLAPRPool::getAPRPool() +{ + return mPool ; +} + +LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) + : LLAPRPool(parent, size, releasePoolFlag), + mNumActiveRef(0), + mNumTotalRef(0), + mMutexPool(NULL), + mMutexp(NULL) { - if(!mPool) + //create mutex + if(!is_local) //not a local apr_pool, that is: shared by multiple threads. { - createAPRPool() ; + apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex + apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool); } - - return mPool ; } -LLVolatileAPRPool::LLVolatileAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) - : LLAPRPool(parent, size, releasePoolFlag) + +LLVolatileAPRPool::~LLVolatileAPRPool() { - mNumActiveRef = 0 ; - mNumTotalRef = 0 ; + //delete mutex + if(mMutexp) + { + apr_thread_mutex_destroy(mMutexp); + apr_pool_destroy(mMutexPool); + } } -apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool() +// +//define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool(). +// +//virtual +apr_pool_t* LLVolatileAPRPool::getAPRPool() { + return LLVolatileAPRPool::getVolatileAPRPool() ; +} + +apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool() +{ + LLScopedLock lock(mMutexp) ; + mNumTotalRef++ ; mNumActiveRef++ ; - return getAPRPool() ; + + if(!mPool) + { + createAPRPool() ; + } + + return mPool ; } void LLVolatileAPRPool::clearVolatileAPRPool() { + LLScopedLock lock(mMutexp) ; + if(mNumActiveRef > 0) { mNumActiveRef--; @@ -251,10 +284,9 @@ void LLScopedLock::unlock() bool ll_apr_warn_status(apr_status_t status) { if(APR_SUCCESS == status) return false; -#ifndef LL_WINDOWS char buf[MAX_STRING]; /* Flawfinder: ignore */ - LL_WARNS_ONCE("APR") << "APR: " << apr_strerror(status, buf, MAX_STRING) << LL_ENDL; -#endif + apr_strerror(status, buf, MAX_STRING); + LL_WARNS("APR") << "APR: " << buf << LL_ENDL; return true; } @@ -268,10 +300,18 @@ void ll_apr_assert_status(apr_status_t status) // LLAPRFile functions // LLAPRFile::LLAPRFile() + : mFile(NULL), + mCurrentFilePoolp(NULL) +{ +} + +LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool) + : mFile(NULL), + mCurrentFilePoolp(NULL) { - mFile = NULL ; - mCurrentFilePoolp = NULL ; + open(filename, flags, pool); } + LLAPRFile::~LLAPRFile() { close() ; @@ -295,11 +335,40 @@ apr_status_t LLAPRFile::close() return ret ; } -apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep) +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep) { apr_status_t s ; - s = open(filename, flags, pool ? pool->getVolatileAPRPool() : NULL, sizep) ; + + //check if already open some file + llassert_always(!mFile) ; + llassert_always(!mCurrentFilePoolp) ; + apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ; + s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool)); + + if (s != APR_SUCCESS || !mFile) + { + mFile = NULL ; + + if (sizep) + { + *sizep = 0; + } + } + else if (sizep) + { + S32 file_size = 0; + apr_off_t offset = 0; + if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS) + { + llassert_always(offset <= 0x7fffffff); + file_size = (S32)offset; + offset = 0; + apr_file_seek(mFile, APR_SET, &offset); + } + *sizep = file_size; + } + if(!mCurrentFilePoolp) { mCurrentFilePoolp = pool ; @@ -312,40 +381,25 @@ apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filenam return s ; } -apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool, S32* sizep) + +//use gAPRPoolp. +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool) { apr_status_t s; //check if already open some file llassert_always(!mFile) ; llassert_always(!mCurrentFilePoolp) ; + llassert_always(use_global_pool) ; //be aware of using gAPRPoolp. - s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(pool)); + s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp); if (s != APR_SUCCESS || !mFile) { mFile = NULL ; close() ; - if (sizep) - { - *sizep = 0; - } return s; } - if (sizep) - { - S32 file_size = 0; - apr_off_t offset = 0; - if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS) - { - llassert_always(offset <= 0x7fffffff); - file_size = (S32)offset; - offset = 0; - apr_file_seek(mFile, APR_SET, &offset); - } - *sizep = file_size; - } - return s; } @@ -369,6 +423,7 @@ S32 LLAPRFile::read(void *buf, S32 nbytes) apr_status_t s = apr_file_read(mFile, buf, &sz); if (s != APR_SUCCESS) { + ll_apr_warn_status(s); return 0; } else @@ -386,6 +441,7 @@ S32 LLAPRFile::write(const void *buf, S32 nbytes) apr_status_t s = apr_file_write(mFile, buf, &sz); if (s != APR_SUCCESS) { + ll_apr_warn_status(s); return 0; } else @@ -434,6 +490,8 @@ apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool()); if (s != APR_SUCCESS || !file_handle) { + ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL; file_handle = NULL ; close(file_handle, pool) ; return NULL; @@ -464,6 +522,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) } if (s != APR_SUCCESS) { + ll_apr_warn_status(s); return -1; } else @@ -501,6 +560,8 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb apr_status_t s = apr_file_read(file_handle, buf, &bytes_read); if (s != APR_SUCCESS) { + LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL; + ll_apr_warn_status(s); bytes_read = 0; } else @@ -549,6 +610,8 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n apr_status_t s = apr_file_write(file_handle, buf, &bytes_written); if (s != APR_SUCCESS) { + LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL; + ll_apr_warn_status(s); bytes_written = 0; } else @@ -575,8 +638,8 @@ bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool) if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "LLAPRFile::remove failed on file: " << filename << LL_ENDL; ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL; return false; } return true; @@ -593,8 +656,8 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname, if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "LLAPRFile::rename failed on file: " << filename << LL_ENDL; ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL; return false; } return true; @@ -667,8 +730,8 @@ bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool) if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "LLAPRFile::makeDir failed on file: " << dirname << LL_ENDL; ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL; return false; } return true; @@ -685,8 +748,8 @@ bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool) if (s != APR_SUCCESS) { - LL_DEBUGS("APR") << "LLAPRFile::removeDir failed on file: " << dirname << LL_ENDL; ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL; return false; } return true; diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 0898aeec47..b08bb617c5 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -1,259 +1,265 @@ -/**
- * @file llapr.h
- * @author Phoenix
- * @date 2004-11-28
- * @brief Helper functions for using the apache portable runtime library.
- *
- * $LicenseInfo:firstyear=2004&license=viewergpl$
- *
- * Copyright (c) 2004-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLAPR_H
-#define LL_LLAPR_H
-
-#if LL_LINUX || LL_SOLARIS
-#include <sys/param.h> // Need PATH_MAX in APR headers...
-#endif
-
-#include <boost/noncopyable.hpp>
-
-#include "apr_thread_proc.h"
-#include "apr_thread_mutex.h"
-#include "apr_getopt.h"
-#include "apr_signal.h"
-#include "apr_atomic.h"
-#include "llstring.h"
-
-extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
-extern apr_thread_mutex_t* gCallStacksLogMutexp;
-
-/**
- * @brief initialize the common apr constructs -- apr itself, the
- * global pool, and a mutex.
- */
-void LL_COMMON_API ll_init_apr();
-
-/**
- * @brief Cleanup those common apr constructs.
- */
-void LL_COMMON_API ll_cleanup_apr();
-
-//
-//LL apr_pool
-//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
-//
-class LL_COMMON_API LLAPRPool
-{
-public:
- LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
- ~LLAPRPool() ;
-
- apr_pool_t* getAPRPool() ;
- apr_status_t getStatus() {return mStatus ; }
-
-protected:
- void releaseAPRPool() ;
- void createAPRPool() ;
-
-protected:
- apr_pool_t* mPool ; //pointing to an apr_pool
- apr_pool_t* mParent ; //parent pool
- apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work.
- apr_status_t mStatus ; //status when creating the pool
- BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
-};
-
-//
-//volatile LL apr_pool
-//which clears memory automatically.
-//so it can not hold static data or data after memory is cleared
-//
-class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool
-{
-public:
- LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
- ~LLVolatileAPRPool(){}
-
- apr_pool_t* getVolatileAPRPool() ;
-
- void clearVolatileAPRPool() ;
-
- BOOL isFull() ;
- BOOL isEmpty() {return !mNumActiveRef ;}
-private:
- S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
- S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
-} ;
-
-/**
- * @class LLScopedLock
- * @brief Small class to help lock and unlock mutexes.
- *
- * This class is used to have a stack level lock once you already have
- * an apr mutex handy. The constructor handles the lock, and the
- * destructor handles the unlock. Instances of this class are
- * <b>not</b> thread safe.
- */
-class LL_COMMON_API LLScopedLock : private boost::noncopyable
-{
-public:
- /**
- * @brief Constructor which accepts a mutex, and locks it.
- *
- * @param mutex An allocated APR mutex. If you pass in NULL,
- * this wrapper will not lock.
- */
- LLScopedLock(apr_thread_mutex_t* mutex);
-
- /**
- * @brief Destructor which unlocks the mutex if still locked.
- */
- ~LLScopedLock();
-
- /**
- * @brief Check lock.
- */
- bool isLocked() const { return mLocked; }
-
- /**
- * @brief This method unlocks the mutex.
- */
- void unlock();
-
-protected:
- bool mLocked;
- apr_thread_mutex_t* mMutex;
-};
-
-template <typename Type> class LLAtomic32
-{
-public:
- LLAtomic32<Type>() {};
- LLAtomic32<Type>(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); };
- ~LLAtomic32<Type>() {};
-
- operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
- Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
- void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
- void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
- Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
- Type operator --(int) { return apr_atomic_dec32(&mData); } // Type--
-
-private:
- apr_uint32_t mData;
-};
-
-typedef LLAtomic32<U32> LLAtomicU32;
-typedef LLAtomic32<S32> LLAtomicS32;
-
-// File IO convenience functions.
-// Returns NULL if the file fails to openm sets *sizep to file size of not NULL
-// abbreviated flags
-#define LL_APR_R (APR_READ) // "r"
-#define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w"
-#define LL_APR_RB (APR_READ|APR_BINARY) // "rb"
-#define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb"
-#define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b"
-#define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b"
-
-//
-//apr_file manager
-//which: 1)only keeps one file open;
-// 2)closes the open file in the destruction function
-// 3)informs the apr_pool to clean the memory when the file is closed.
-//Note: please close an open file at the earliest convenience.
-// especially do not put some time-costly operations between open() and close().
-// otherwise it might lock the APRFilePool.
-//there are two different apr_pools the APRFile can use:
-// 1, a temperary pool passed to an APRFile function, which is used within this function and only once.
-// 2, a global pool.
-//
-class LL_COMMON_API LLAPRFile
-{
-private:
- apr_file_t* mFile ;
- LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool.
-
-public:
- LLAPRFile() ;
- ~LLAPRFile() ;
-
- apr_status_t open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep = NULL);
- apr_status_t open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool = NULL, S32* sizep = NULL);
- apr_status_t close() ;
-
- // Returns actual offset, -1 if seek fails
- S32 seek(apr_seek_where_t where, S32 offset);
- apr_status_t eof() { return apr_file_eof(mFile);}
-
- // Returns bytes read/written, 0 if read/write fails:
- S32 read(void* buf, S32 nbytes);
- S32 write(const void* buf, S32 nbytes);
-
- apr_file_t* getFileHandle() {return mFile;}
-
-private:
- apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
-
-//
-//*******************************************************************************************************************************
-//static components
-//
-public:
- static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
-
-private:
- static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags);
- static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ;
- static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
-public:
- // returns false if failure:
- static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL);
- static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL);
- static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ);
- static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL);
- static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
- static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
-
- // Returns bytes read/written, 0 if read/write fails:
- static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);
- static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);
-//*******************************************************************************************************************************
-};
-
-/**
- * @brief Function which approprately logs error or remains quiet on
- * APR_SUCCESS.
- * @return Returns <code>true</code> if status is an error condition.
- */
-bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
-
-void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
-
-extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
-
-#endif // LL_LLAPR_H
+/** + * @file llapr.h + * @author Phoenix + * @date 2004-11-28 + * @brief Helper functions for using the apache portable runtime library. + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLAPR_H +#define LL_LLAPR_H + +#if LL_LINUX || LL_SOLARIS +#include <sys/param.h> // Need PATH_MAX in APR headers... +#endif + +#include <boost/noncopyable.hpp> + +#include "apr_thread_proc.h" +#include "apr_thread_mutex.h" +#include "apr_getopt.h" +#include "apr_signal.h" +#include "apr_atomic.h" +#include "llstring.h" + +extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp; +extern apr_thread_mutex_t* gCallStacksLogMutexp; + +/** + * @brief initialize the common apr constructs -- apr itself, the + * global pool, and a mutex. + */ +void LL_COMMON_API ll_init_apr(); + +/** + * @brief Cleanup those common apr constructs. + */ +void LL_COMMON_API ll_cleanup_apr(); + +// +//LL apr_pool +//manage apr_pool_t, destroy allocated apr_pool in the destruction function. +// +class LL_COMMON_API LLAPRPool +{ +public: + LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ; + virtual ~LLAPRPool() ; + + virtual apr_pool_t* getAPRPool() ; + apr_status_t getStatus() {return mStatus ; } + +protected: + void releaseAPRPool() ; + void createAPRPool() ; + +protected: + apr_pool_t* mPool ; //pointing to an apr_pool + apr_pool_t* mParent ; //parent pool + apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work. + apr_status_t mStatus ; //status when creating the pool + BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true. +}; + +// +//volatile LL apr_pool +//which clears memory automatically. +//so it can not hold static data or data after memory is cleared +// +class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool +{ +public: + LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE); + virtual ~LLVolatileAPRPool(); + + /*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool(). + apr_pool_t* getVolatileAPRPool() ; + void clearVolatileAPRPool() ; + + BOOL isFull() ; + +private: + S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool. + S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating. + + apr_thread_mutex_t *mMutexp; + apr_pool_t *mMutexPool; +} ; + +/** + * @class LLScopedLock + * @brief Small class to help lock and unlock mutexes. + * + * This class is used to have a stack level lock once you already have + * an apr mutex handy. The constructor handles the lock, and the + * destructor handles the unlock. Instances of this class are + * <b>not</b> thread safe. + */ +class LL_COMMON_API LLScopedLock : private boost::noncopyable +{ +public: + /** + * @brief Constructor which accepts a mutex, and locks it. + * + * @param mutex An allocated APR mutex. If you pass in NULL, + * this wrapper will not lock. + */ + LLScopedLock(apr_thread_mutex_t* mutex); + + /** + * @brief Destructor which unlocks the mutex if still locked. + */ + ~LLScopedLock(); + + /** + * @brief Check lock. + */ + bool isLocked() const { return mLocked; } + + /** + * @brief This method unlocks the mutex. + */ + void unlock(); + +protected: + bool mLocked; + apr_thread_mutex_t* mMutex; +}; + +template <typename Type> class LLAtomic32 +{ +public: + LLAtomic32<Type>() {}; + LLAtomic32<Type>(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); }; + ~LLAtomic32<Type>() {}; + + operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); } + Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); } + void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); } + void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); } + Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++ + Type operator --(int) { return apr_atomic_dec32(&mData); } // Type-- + +private: + apr_uint32_t mData; +}; + +typedef LLAtomic32<U32> LLAtomicU32; +typedef LLAtomic32<S32> LLAtomicS32; + +// File IO convenience functions. +// Returns NULL if the file fails to openm sets *sizep to file size of not NULL +// abbreviated flags +#define LL_APR_R (APR_READ) // "r" +#define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w" +#define LL_APR_RB (APR_READ|APR_BINARY) // "rb" +#define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb" +#define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b" +#define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b" + +// +//apr_file manager +//which: 1)only keeps one file open; +// 2)closes the open file in the destruction function +// 3)informs the apr_pool to clean the memory when the file is closed. +//Note: please close an open file at the earliest convenience. +// especially do not put some time-costly operations between open() and close(). +// otherwise it might lock the APRFilePool. +//there are two different apr_pools the APRFile can use: +// 1, a temperary pool passed to an APRFile function, which is used within this function and only once. +// 2, a global pool. +// + +class LL_COMMON_API LLAPRFile : boost::noncopyable +{ + // make this non copyable since a copy closes the file +private: + apr_file_t* mFile ; + LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. + +public: + LLAPRFile() ; + LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL); + ~LLAPRFile() ; + + apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL); + apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp. + apr_status_t close() ; + + // Returns actual offset, -1 if seek fails + S32 seek(apr_seek_where_t where, S32 offset); + apr_status_t eof() { return apr_file_eof(mFile);} + + // Returns bytes read/written, 0 if read/write fails: + S32 read(void* buf, S32 nbytes); + S32 write(const void* buf, S32 nbytes); + + apr_file_t* getFileHandle() {return mFile;} + +private: + apr_pool_t* getAPRFilePool(apr_pool_t* pool) ; + +// +//******************************************************************************************************************************* +//static components +// +public: + static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist. + +private: + static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags); + static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ; + static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset); +public: + // returns false if failure: + static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL); + static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL); + static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ); + static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL); + static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL); + static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL); + + // Returns bytes read/written, 0 if read/write fails: + static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); + static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); +//******************************************************************************************************************************* +}; + +/** + * @brief Function which approprately logs error or remains quiet on + * APR_SUCCESS. + * @return Returns <code>true</code> if status is an error condition. + */ +bool LL_COMMON_API ll_apr_warn_status(apr_status_t status); + +void LL_COMMON_API ll_apr_assert_status(apr_status_t status); + +extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool + +#endif // LL_LLAPR_H diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index b2a92861cc..6d5b12d840 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -43,30 +43,21 @@ struct AssetEntry : public LLDictionaryEntry { AssetEntry(const char *desc_name, - const char *type_name, // 8 character limit! - const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one - const char *category_name, // used by llinventorymodel when creating new categories - EDragAndDropType dad_type, - bool can_link, // can you create a link to this type? - bool is_protected) // can the viewer change categories of this type? + const char *type_name, // 8 character limit! + const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one + bool can_link) // can you create a link to this type? : LLDictionaryEntry(desc_name), mTypeName(type_name), mHumanName(human_name), - mCategoryName(category_name), - mDadType(dad_type), - mCanLink(can_link), - mIsProtected(is_protected) + mCanLink(can_link) { llassert(strlen(mTypeName) <= 8); } const char *mTypeName; const char *mHumanName; - const char *mCategoryName; - EDragAndDropType mDadType; bool mCanLink; - bool mIsProtected; }; class LLAssetDictionary : public LLSingleton<LLAssetDictionary>, @@ -78,48 +69,32 @@ public: LLAssetDictionary::LLAssetDictionary() { - // DESCRIPTION TYPE NAME HUMAN NAME CATEGORY NAME DRAG&DROP CAN LINK? PROTECTED? - // |--------------------|-----------|-------------------|-------------------|---------------|-----------|-----------| - addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, TRUE, TRUE)); - addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, TRUE, TRUE)); - addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, TRUE, TRUE)); - addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, TRUE, TRUE)); - addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, TRUE, TRUE)); - addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING, TRUE, TRUE)); - addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT, TRUE, TRUE)); - addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, TRUE, TRUE)); - addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY, TRUE, TRUE)); - addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY, TRUE, TRUE)); - addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, TRUE, TRUE)); - addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, TRUE, TRUE)); - addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, TRUE, TRUE)); - addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART, TRUE, TRUE)); - addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE, FALSE, TRUE)); - addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE, FALSE, TRUE)); - addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE, FALSE, TRUE)); - addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, TRUE, TRUE)); - addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, TRUE, TRUE)); - addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, TRUE, TRUE)); - addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, TRUE, TRUE)); - addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, TRUE, TRUE)); - addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE, TRUE)); - addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE, TRUE)); - - addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "Link", DAD_LINK, FALSE, TRUE)); - addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", "New Folder", DAD_LINK, FALSE, TRUE)); - - for (S32 ensemble_num = S32(LLAssetType::AT_FOLDER_ENSEMBLE_START); - ensemble_num <= S32(LLAssetType::AT_FOLDER_ENSEMBLE_END); - ensemble_num++) - { - addEntry(LLAssetType::EType(ensemble_num), new AssetEntry("ENSEMBLE", "ensemble", "ensemble", "New Folder", DAD_CATEGORY, FALSE, FALSE)); - } - - addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("CURRENT", "current", "current outfit", "Current Look", DAD_CATEGORY, FALSE, TRUE)); - addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", "New Look", DAD_CATEGORY, FALSE, FALSE)); - addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", "My Looks", DAD_CATEGORY, FALSE, TRUE)); - - addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE, FALSE, FALSE)); + // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? + // |--------------------|-----------|-------------------|-----------| + addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", FALSE)); + addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", FALSE)); + addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", FALSE)); + addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", FALSE)); + addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", FALSE)); + addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", TRUE)); + addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", TRUE)); + addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", FALSE)); + addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", TRUE)); + addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", FALSE)); + addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", FALSE)); + addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", FALSE)); + addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", TRUE)); + addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", FALSE)); + addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", FALSE)); + addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", FALSE)); + addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", FALSE)); + addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", TRUE)); + addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", FALSE)); + + addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", FALSE)); + addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", FALSE)); + + addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE)); }; // static @@ -140,8 +115,7 @@ const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type) } else { - static const std::string error_string = "BAD TYPE"; - return error_string; + return badLookup(); } } @@ -156,7 +130,7 @@ const char *LLAssetType::lookup(LLAssetType::EType asset_type) } else { - return "-1"; + return badLookup().c_str(); } } @@ -166,6 +140,7 @@ LLAssetType::EType LLAssetType::lookup(const char* name) return lookup(ll_safe_string(name)); } +// static LLAssetType::EType LLAssetType::lookup(const std::string& type_name) { const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); @@ -193,7 +168,7 @@ const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type) } else { - return NULL; + return badLookup().c_str(); } } @@ -203,6 +178,7 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const char* name) return lookupHumanReadable(ll_safe_string(name)); } +// static LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_name) { const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); @@ -220,32 +196,6 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_ } // static -const char *LLAssetType::lookupCategoryName(LLAssetType::EType asset_type) -{ - const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); - const AssetEntry *entry = dict->lookup(asset_type); - if (entry) - { - return entry->mCategoryName; - } - else - { - return "New Folder"; - } -} - -// static -EDragAndDropType LLAssetType::lookupDragAndDropType(EType asset_type) -{ - const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); - const AssetEntry *entry = dict->lookup(asset_type); - if (entry) - return entry->mDadType; - else - return DAD_NONE; -} - -// static bool LLAssetType::lookupCanLink(EType asset_type) { const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); @@ -269,37 +219,9 @@ bool LLAssetType::lookupIsLinkType(EType asset_type) } // static -// Only ensembles and plain folders aren't protected. "Protected" means -// you can't change certain properties such as their type. -bool LLAssetType::lookupIsProtectedCategoryType(EType asset_type) +const std::string &LLAssetType::badLookup() { - const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); - const AssetEntry *entry = dict->lookup(asset_type); - if (entry) - { - return entry->mIsProtected; - } - return true; -} + static const std::string sBadLookup = "llassettype_bad_lookup"; + return sBadLookup; -// static -bool LLAssetType::lookupIsEnsembleCategoryType(EType asset_type) -{ - return (asset_type >= AT_FOLDER_ENSEMBLE_START && - asset_type <= AT_FOLDER_ENSEMBLE_END); -} - - -// static. Generate a good default description -void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type, - std::string& description) -{ - const S32 BUF_SIZE = 30; - char time_str[BUF_SIZE]; /* Flawfinder: ignore */ - time_t now; - time(&now); - memset(time_str, '\0', BUF_SIZE); - strftime(time_str, BUF_SIZE - 1, "%Y-%m-%d %H:%M:%S ", localtime(&now)); - description.assign(time_str); - description.append(LLAssetType::lookupHumanReadable(asset_type)); } diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 33705cd2b1..ec2290d30e 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -1,205 +1,161 @@ -/**
- * @file llassettype.h
- * @brief Declaration of LLAssetType.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLASSETTYPE_H
-#define LL_LLASSETTYPE_H
-
-#include <string>
-
-#include "stdenums.h" // for EDragAndDropType
-
-class LL_COMMON_API LLAssetType
-{
-public:
- enum EType
- {
- AT_TEXTURE = 0,
- // Used for painting the faces of geometry.
- // Stored in typical j2c stream format.
-
- AT_SOUND = 1,
- // Used to fill the aural spectrum.
-
- AT_CALLINGCARD = 2,
- // Links instant message access to the user on the card.
- // : E.G. A card for yourself, for linden support, for
- // : the guy you were talking to in the coliseum.
-
- AT_LANDMARK = 3,
- // Links to places in the world with location and a screen shot or image saved.
- // : E.G. Home, linden headquarters, the coliseum, destinations where
- // : we want to increase traffic.
-
- AT_SCRIPT = 4,
- // Valid scripts that can be attached to an object.
- // : E.G. Open a door, jump into the air.
-
- AT_CLOTHING = 5,
- // A collection of textures and parameters that can be worn by an avatar.
-
- AT_OBJECT = 6,
- // Any combination of textures, sounds, and scripts that are
- // associated with a fixed piece of geometry.
- // : E.G. A hot tub, a house with working door.
-
- AT_NOTECARD = 7,
- // Just text.
-
- AT_CATEGORY = 8,
- // Holds a collection of inventory items.
- // It's treated as an item in the inventory and therefore needs a type.
-
- AT_ROOT_CATEGORY = 9,
- // A user's root inventory category.
- // We decided to expose it visually, so it seems logical to fold
- // it into the asset types.
-
- AT_LSL_TEXT = 10,
- AT_LSL_BYTECODE = 11,
- // The LSL is the scripting language.
- // We've split it into a text and bytecode representation.
-
- AT_TEXTURE_TGA = 12,
- // Uncompressed TGA texture.
-
- AT_BODYPART = 13,
- // A collection of textures and parameters that can be worn by an avatar.
-
- AT_TRASH = 14,
- // Only to be used as a marker for a category preferred type.
- // Using this, we can throw things in the trash before completely deleting.
-
- AT_SNAPSHOT_CATEGORY = 15,
- // A marker for a folder meant for snapshots.
- // No actual assets will be snapshots, though if there were, you
- // could interpret them as textures.
-
- AT_LOST_AND_FOUND = 16,
- // Used to stuff lost&found items into.
-
- AT_SOUND_WAV = 17,
- // Uncompressed sound.
-
- AT_IMAGE_TGA = 18,
- // Uncompressed image, non-square.
- // Not appropriate for use as a texture.
-
- AT_IMAGE_JPEG = 19,
- // Compressed image, non-square.
- // Not appropriate for use as a texture.
-
- AT_ANIMATION = 20,
- // Animation.
-
- AT_GESTURE = 21,
- // Gesture, sequence of animations, sounds, chat, wait steps.
-
- AT_SIMSTATE = 22,
- // Simstate file.
-
- AT_FAVORITE = 23,
- // favorite items
-
- AT_LINK = 24,
- // Inventory symbolic link
-
- AT_LINK_FOLDER = 25,
- // Inventory folder link
-
- AT_FOLDER_ENSEMBLE_START = 26,
- AT_FOLDER_ENSEMBLE_END = 45,
- // This range is reserved for special clothing folder types.
-
- AT_CURRENT_OUTFIT = 46,
- // Current outfit
-
- AT_OUTFIT = 47,
- // Predefined outfit ("look")
-
- AT_MY_OUTFITS = 48,
- // Folder that holds your outfits.
-
-
- AT_COUNT = 49,
-
- // +*********************************************************+
- // | TO ADD AN ELEMENT TO THIS ENUM: |
- // +*********************************************************+
- // | 1. INSERT BEFORE AT_COUNT |
- // | 2. INCREMENT AT_COUNT BY 1 |
- // | 3. ADD TO LLAssetDictionary in LLAssetType.cpp |
- // | 3. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp |
- // +*********************************************************+
-
- AT_NONE = -1
- };
-
- // machine transation between type and strings
- static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
- static EType lookup(const std::string& type_name);
- static const char* lookup(EType asset_type);
-
- // translation from a type to a human readable form.
- static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate
- static EType lookupHumanReadable(const std::string& readable_name);
- static const char* lookupHumanReadable(EType asset_type);
-
- // Generate a good default description. You may want to add a verb
- // or agent name after this depending on your application.
- static void generateDescriptionFor(LLAssetType::EType asset_type,
- std::string& description);
-
- static EType getType(const std::string& desc_name);
- static const std::string& getDesc(EType asset_type);
- static EDragAndDropType lookupDragAndDropType(EType asset_type);
-
- static bool lookupCanLink(EType asset_type);
- static bool lookupIsLinkType(EType asset_type);
-
- static const char* lookupCategoryName(EType asset_type);
- static bool lookupIsProtectedCategoryType(EType asset_type);
- static bool lookupIsEnsembleCategoryType(EType asset_type);
-
- /* TODO: Change return types from "const char *" to "const std::string &".
- This is fairly straightforward, but requires changing some calls to use .c_str().
- e.g.:
- - fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- + fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType).c_str());
- */
-
-private:
- // don't instantiate or derive one of these objects
- LLAssetType( void ) {}
- ~LLAssetType( void ) {}
-};
-
-#endif // LL_LLASSETTYPE_H
+/** + * @file llassettype.h + * @brief Declaration of LLAssetType. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLASSETTYPE_H +#define LL_LLASSETTYPE_H + +#include <string> + +#include "stdenums.h" // for EDragAndDropType + +class LL_COMMON_API LLAssetType +{ +public: + enum EType + { + AT_TEXTURE = 0, + // Used for painting the faces of geometry. + // Stored in typical j2c stream format. + + AT_SOUND = 1, + // Used to fill the aural spectrum. + + AT_CALLINGCARD = 2, + // Links instant message access to the user on the card. + // : E.G. A card for yourself, for linden support, for + // : the guy you were talking to in the coliseum. + + AT_LANDMARK = 3, + // Links to places in the world with location and a screen shot or image saved. + // : E.G. Home, linden headquarters, the coliseum, destinations where + // : we want to increase traffic. + + AT_SCRIPT = 4, + // Valid scripts that can be attached to an object. + // : E.G. Open a door, jump into the air. + + AT_CLOTHING = 5, + // A collection of textures and parameters that can be worn by an avatar. + + AT_OBJECT = 6, + // Any combination of textures, sounds, and scripts that are + // associated with a fixed piece of geometry. + // : E.G. A hot tub, a house with working door. + + AT_NOTECARD = 7, + // Just text. + + AT_CATEGORY = 8, + // Holds a collection of inventory items. + // It's treated as an item in the inventory and therefore needs a type. + + AT_ROOT_CATEGORY = 9, + // A user's root inventory category. + // We decided to expose it visually, so it seems logical to fold + // it into the asset types. + + AT_LSL_TEXT = 10, + AT_LSL_BYTECODE = 11, + // The LSL is the scripting language. + // We've split it into a text and bytecode representation. + + AT_TEXTURE_TGA = 12, + // Uncompressed TGA texture. + + AT_BODYPART = 13, + // A collection of textures and parameters that can be worn by an avatar. + + AT_SOUND_WAV = 17, + // Uncompressed sound. + + AT_IMAGE_TGA = 18, + // Uncompressed image, non-square. + // Not appropriate for use as a texture. + + AT_IMAGE_JPEG = 19, + // Compressed image, non-square. + // Not appropriate for use as a texture. + + AT_ANIMATION = 20, + // Animation. + + AT_GESTURE = 21, + // Gesture, sequence of animations, sounds, chat, wait steps. + + AT_SIMSTATE = 22, + // Simstate file. + + AT_LINK = 24, + // Inventory symbolic link + + AT_LINK_FOLDER = 25, + // Inventory folder link + + AT_COUNT = 26, + + // +*********************************************************+ + // | TO ADD AN ELEMENT TO THIS ENUM: | + // +*********************************************************+ + // | 1. INSERT BEFORE AT_COUNT | + // | 2. INCREMENT AT_COUNT BY 1 | + // | 3. ADD TO LLAssetType.cpp | + // | 4. ADD TO LLViewerAssetType.cpp | + // | 5. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp | + // +*********************************************************+ + + AT_NONE = -1 + }; + + // machine transation between type and strings + static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate + static EType lookup(const std::string& type_name); + static const char* lookup(EType asset_type); + + // translation from a type to a human readable form. + static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate + static EType lookupHumanReadable(const std::string& readable_name); + static const char* lookupHumanReadable(EType asset_type); + + static EType getType(const std::string& desc_name); + static const std::string& getDesc(EType asset_type); + + static bool lookupCanLink(EType asset_type); + static bool lookupIsLinkType(EType asset_type); + + static const std::string& badLookup(); // error string when a lookup fails + +protected: + LLAssetType() {} + ~LLAssetType() {} +}; + +#endif // LL_LLASSETTYPE_H diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 6c5fa5af6d..141b0df43c 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -1,149 +1,149 @@ -/**
- * @file llcoros.h
- * @author Nat Goodspeed
- * @date 2009-06-02
- * @brief Manage running boost::coroutine instances
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLCOROS_H)
-#define LL_LLCOROS_H
-
-#include <boost/coroutine/coroutine.hpp>
-#include "llsingleton.h"
-#include <boost/ptr_container/ptr_map.hpp>
-#include <string>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_binary_params.hpp>
-#include <boost/preprocessor/iteration/local.hpp>
-#include <stdexcept>
-
-/**
- * Registry of named Boost.Coroutine instances
- *
- * The Boost.Coroutine library supports the general case of a coroutine
- * accepting arbitrary parameters and yielding multiple (sets of) results. For
- * such use cases, it's natural for the invoking code to retain the coroutine
- * instance: the consumer repeatedly calls into the coroutine, perhaps passing
- * new parameter values, prompting it to yield its next result.
- *
- * Our typical coroutine usage is different, though. For us, coroutines
- * provide an alternative to the @c Responder pattern. Our typical coroutine
- * has @c void return, invoked in fire-and-forget mode: the handler for some
- * user gesture launches the coroutine and promptly returns to the main loop.
- * The coroutine initiates some action that will take multiple frames (e.g. a
- * capability request), waits for its result, processes it and silently steals
- * away.
- *
- * This usage poses two (related) problems:
- *
- * # Who should own the coroutine instance? If it's simply local to the
- * handler code that launches it, return from the handler will destroy the
- * coroutine object, terminating the coroutine.
- * # Once the coroutine terminates, in whatever way, who's responsible for
- * cleaning up the coroutine object?
- *
- * LLCoros is a Singleton collection of currently-active coroutine instances.
- * Each has a name. You ask LLCoros to launch a new coroutine with a suggested
- * name prefix; from your prefix it generates a distinct name, registers the
- * new coroutine and returns the actual name.
- *
- * The name can be used to kill off the coroutine prematurely, if needed. It
- * can also provide diagnostic info: we can look up the name of the
- * currently-running coroutine.
- *
- * Finally, the next frame ("mainloop" event) after the coroutine terminates,
- * LLCoros will notice its demise and destroy it.
- */
-class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
-{
-public:
- /// Canonical boost::coroutines::coroutine signature we use
- typedef boost::coroutines::coroutine<void()> coro;
- /// Canonical 'self' type
- typedef coro::self self;
-
- /**
- * Create and start running a new coroutine with specified name. The name
- * string you pass is a suggestion; it will be tweaked for uniqueness. The
- * actual name is returned to you.
- *
- * Usage looks like this, for (e.g.) two coroutine parameters:
- * @code
- * class MyClass
- * {
- * public:
- * ...
- * // Do NOT NOT NOT accept reference params other than 'self'!
- * // Pass by value only!
- * void myCoroutineMethod(LLCoros::self& self, std::string, LLSD);
- * ...
- * };
- * ...
- * std::string name = LLCoros::instance().launch(
- * "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1,
- * "somestring", LLSD(17));
- * @endcode
- *
- * Your function/method must accept LLCoros::self& as its first parameter.
- * It can accept any other parameters you want -- but ONLY BY VALUE!
- * Other reference parameters are a BAD IDEA! You Have Been Warned. See
- * DEV-32777 comments for an explanation.
- *
- * Pass a callable that accepts the single LLCoros::self& parameter. It
- * may work to pass a free function whose only parameter is 'self'; for
- * all other cases use boost::bind(). Of course, for a non-static class
- * method, the first parameter must be the class instance. Use the
- * placeholder _1 for the 'self' parameter. Any other parameters should be
- * passed via the bind() expression.
- *
- * launch() tweaks the suggested name so it won't collide with any
- * existing coroutine instance, creates the coroutine instance, registers
- * it with the tweaked name and runs it until its first wait. At that
- * point it returns the tweaked name.
- */
- template <typename CALLABLE>
- std::string launch(const std::string& prefix, const CALLABLE& callable)
- {
- return launchImpl(prefix, new coro(callable));
- }
-
- /**
- * Abort a running coroutine by name. 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);
-
- /**
- * From within a coroutine, pass its @c self object to look up the
- * (tweaked) name string by which this coroutine is registered. Returns
- * the empty string if not found (e.g. if the coroutine was launched by
- * hand rather than using LLCoros::launch()).
- */
- template <typename COROUTINE_SELF>
- std::string getName(const COROUTINE_SELF& self) const
- {
- return getNameByID(self.get_id());
- }
-
- /// getName() by self.get_id()
- std::string getNameByID(const void* self_id) const;
-
-private:
- friend class LLSingleton<LLCoros>;
- LLCoros();
- std::string launchImpl(const std::string& prefix, coro* newCoro);
- std::string generateDistinctName(const std::string& prefix) const;
- bool cleanup(const LLSD&);
-
- typedef boost::ptr_map<std::string, coro> CoroMap;
- CoroMap mCoros;
-};
-
-#endif /* ! defined(LL_LLCOROS_H) */
+/** + * @file llcoros.h + * @author Nat Goodspeed + * @date 2009-06-02 + * @brief Manage running boost::coroutine instances + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLCOROS_H) +#define LL_LLCOROS_H + +#include <boost/coroutine/coroutine.hpp> +#include "llsingleton.h" +#include <boost/ptr_container/ptr_map.hpp> +#include <string> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/iteration/local.hpp> +#include <stdexcept> + +/** + * Registry of named Boost.Coroutine instances + * + * The Boost.Coroutine library supports the general case of a coroutine + * accepting arbitrary parameters and yielding multiple (sets of) results. For + * such use cases, it's natural for the invoking code to retain the coroutine + * instance: the consumer repeatedly calls into the coroutine, perhaps passing + * new parameter values, prompting it to yield its next result. + * + * Our typical coroutine usage is different, though. For us, coroutines + * provide an alternative to the @c Responder pattern. Our typical coroutine + * has @c void return, invoked in fire-and-forget mode: the handler for some + * user gesture launches the coroutine and promptly returns to the main loop. + * The coroutine initiates some action that will take multiple frames (e.g. a + * capability request), waits for its result, processes it and silently steals + * away. + * + * This usage poses two (related) problems: + * + * # Who should own the coroutine instance? If it's simply local to the + * handler code that launches it, return from the handler will destroy the + * coroutine object, terminating the coroutine. + * # Once the coroutine terminates, in whatever way, who's responsible for + * cleaning up the coroutine object? + * + * LLCoros is a Singleton collection of currently-active coroutine instances. + * Each has a name. You ask LLCoros to launch a new coroutine with a suggested + * name prefix; from your prefix it generates a distinct name, registers the + * new coroutine and returns the actual name. + * + * The name can be used to kill off the coroutine prematurely, if needed. It + * can also provide diagnostic info: we can look up the name of the + * currently-running coroutine. + * + * Finally, the next frame ("mainloop" event) after the coroutine terminates, + * LLCoros will notice its demise and destroy it. + */ +class LL_COMMON_API LLCoros: public LLSingleton<LLCoros> +{ +public: + /// Canonical boost::coroutines::coroutine signature we use + typedef boost::coroutines::coroutine<void()> coro; + /// Canonical 'self' type + typedef coro::self self; + + /** + * Create and start running a new coroutine with specified name. The name + * string you pass is a suggestion; it will be tweaked for uniqueness. The + * actual name is returned to you. + * + * Usage looks like this, for (e.g.) two coroutine parameters: + * @code + * class MyClass + * { + * public: + * ... + * // Do NOT NOT NOT accept reference params other than 'self'! + * // Pass by value only! + * void myCoroutineMethod(LLCoros::self& self, std::string, LLSD); + * ... + * }; + * ... + * std::string name = LLCoros::instance().launch( + * "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1, + * "somestring", LLSD(17)); + * @endcode + * + * Your function/method must accept LLCoros::self& as its first parameter. + * It can accept any other parameters you want -- but ONLY BY VALUE! + * Other reference parameters are a BAD IDEA! You Have Been Warned. See + * DEV-32777 comments for an explanation. + * + * Pass a callable that accepts the single LLCoros::self& parameter. It + * may work to pass a free function whose only parameter is 'self'; for + * all other cases use boost::bind(). Of course, for a non-static class + * method, the first parameter must be the class instance. Use the + * placeholder _1 for the 'self' parameter. Any other parameters should be + * passed via the bind() expression. + * + * launch() tweaks the suggested name so it won't collide with any + * existing coroutine instance, creates the coroutine instance, registers + * it with the tweaked name and runs it until its first wait. At that + * point it returns the tweaked name. + */ + template <typename CALLABLE> + std::string launch(const std::string& prefix, const CALLABLE& callable) + { + return launchImpl(prefix, new coro(callable)); + } + + /** + * Abort a running coroutine by name. 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); + + /** + * From within a coroutine, pass its @c self object to look up the + * (tweaked) name string by which this coroutine is registered. Returns + * the empty string if not found (e.g. if the coroutine was launched by + * hand rather than using LLCoros::launch()). + */ + template <typename COROUTINE_SELF> + std::string getName(const COROUTINE_SELF& self) const + { + return getNameByID(self.get_id()); + } + + /// getName() by self.get_id() + std::string getNameByID(const void* self_id) const; + +private: + friend class LLSingleton<LLCoros>; + LLCoros(); + std::string launchImpl(const std::string& prefix, coro* newCoro); + std::string generateDistinctName(const std::string& prefix) const; + bool cleanup(const LLSD&); + + typedef boost::ptr_map<std::string, coro> CoroMap; + CoroMap mCoros; +}; + +#endif /* ! defined(LL_LLCOROS_H) */ diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index 671f2a4d1c..5a86b90bff 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -1,130 +1,130 @@ -/**
- * @file lleventdispatcher.h
- * @author Nat Goodspeed
- * @date 2009-06-18
- * @brief Central mechanism for dispatching events by string name. This is
- * 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=viewergpl$
- * Copyright (c) 2009, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLEVENTDISPATCHER_H)
-#define LL_LLEVENTDISPATCHER_H
-
-#include <string>
-#include <map>
-#include <boost/function.hpp>
-#include <boost/bind.hpp>
-#include <typeinfo>
-#include "llevents.h"
-
-class LLSD;
-
-/**
- * Given an LLSD map, examine a string-valued key and call a corresponding
- * callable. This class is designed to be contained by an LLEventPump
- * listener class that will register some of its own methods, though any
- * callable can be used.
- */
-class LL_COMMON_API LLEventDispatcher
-{
-public:
- LLEventDispatcher(const std::string& desc, const std::string& key);
- virtual ~LLEventDispatcher();
-
- /// Accept any C++ callable, typically a boost::bind() expression
- typedef boost::function<void(const LLSD&)> Callable;
-
- /**
- * Register a @a callable by @a name. The optional @a required parameter
- * is used to validate the structure of each incoming event (see
- * llsd_matches()).
- */
- void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD());
-
- /**
- * Special case: a subclass of this class can pass an unbound member
- * function pointer without explicitly specifying the
- * <tt>boost::bind()</tt> expression.
- */
- template <class CLASS>
- void add(const std::string& name, void (CLASS::*method)(const LLSD&),
- const LLSD& required=LLSD())
- {
- addMethod<CLASS>(name, method, required);
- }
-
- /// Overload for both const and non-const methods
- template <class CLASS>
- void add(const std::string& name, void (CLASS::*method)(const LLSD&) const,
- const LLSD& required=LLSD())
- {
- addMethod<CLASS>(name, method, required);
- }
-
- /// Unregister a callable
- bool remove(const std::string& name);
-
- /// Call a registered callable with an explicitly-specified name. If no
- /// such callable exists, die with LL_ERRS. If the @a event fails to match
- /// the @a required prototype specified at add() time, die with LL_ERRS.
- void operator()(const std::string& name, const LLSD& event) const;
-
- /// Extract the @a key value from the incoming @a event, and call the
- /// callable whose name is specified by that map @a key. If no such
- /// callable exists, die with LL_ERRS. If the @a event fails to match the
- /// @a required prototype specified at add() time, die with LL_ERRS.
- void operator()(const LLSD& event) const;
-
- /// Fetch the Callable for the specified name. If no such name was
- /// registered, return an empty() Callable.
- Callable get(const std::string& name) const;
-
-private:
- template <class CLASS, typename METHOD>
- void addMethod(const std::string& name, const METHOD& method, const LLSD& required)
- {
- CLASS* downcast = dynamic_cast<CLASS*>(this);
- if (! downcast)
- {
- addFail(name, typeid(CLASS).name());
- }
- else
- {
- add(name, boost::bind(method, downcast, _1), required);
- }
- }
- void addFail(const std::string& name, const std::string& classname) const;
- /// try to dispatch, return @c true if success
- bool attemptCall(const std::string& name, const LLSD& event) const;
-
- std::string mDesc, mKey;
- typedef std::map<std::string, std::pair<Callable, LLSD> > DispatchMap;
- DispatchMap mDispatch;
-};
-
-/**
- * Bundle an LLEventPump and a listener with an LLEventDispatcher. A class
- * that contains (or derives from) LLDispatchListener need only specify the
- * LLEventPump name and dispatch key, and add() its methods. Incoming events
- * will automatically be dispatched.
- */
-class LL_COMMON_API LLDispatchListener: public LLEventDispatcher
-{
-public:
- LLDispatchListener(const std::string& pumpname, const std::string& key);
-
- std::string getPumpName() const { return mPump.getName(); }
-
-private:
- bool process(const LLSD& event);
-
- LLEventStream mPump;
- LLTempBoundListener mBoundListener;
-};
-
-#endif /* ! defined(LL_LLEVENTDISPATCHER_H) */
+/** + * @file lleventdispatcher.h + * @author Nat Goodspeed + * @date 2009-06-18 + * @brief Central mechanism for dispatching events by string name. This is + * 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=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLEVENTDISPATCHER_H) +#define LL_LLEVENTDISPATCHER_H + +#include <string> +#include <map> +#include <boost/function.hpp> +#include <boost/bind.hpp> +#include <typeinfo> +#include "llevents.h" + +class LLSD; + +/** + * Given an LLSD map, examine a string-valued key and call a corresponding + * callable. This class is designed to be contained by an LLEventPump + * listener class that will register some of its own methods, though any + * callable can be used. + */ +class LL_COMMON_API LLEventDispatcher +{ +public: + LLEventDispatcher(const std::string& desc, const std::string& key); + virtual ~LLEventDispatcher(); + + /// Accept any C++ callable, typically a boost::bind() expression + typedef boost::function<void(const LLSD&)> Callable; + + /** + * Register a @a callable by @a name. The optional @a required parameter + * is used to validate the structure of each incoming event (see + * llsd_matches()). + */ + void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD()); + + /** + * Special case: a subclass of this class can pass an unbound member + * function pointer without explicitly specifying the + * <tt>boost::bind()</tt> expression. + */ + template <class CLASS> + void add(const std::string& name, void (CLASS::*method)(const LLSD&), + const LLSD& required=LLSD()) + { + addMethod<CLASS>(name, method, required); + } + + /// Overload for both const and non-const methods + template <class CLASS> + void add(const std::string& name, void (CLASS::*method)(const LLSD&) const, + const LLSD& required=LLSD()) + { + addMethod<CLASS>(name, method, required); + } + + /// Unregister a callable + bool remove(const std::string& name); + + /// Call a registered callable with an explicitly-specified name. If no + /// such callable exists, die with LL_ERRS. If the @a event fails to match + /// the @a required prototype specified at add() time, die with LL_ERRS. + void operator()(const std::string& name, const LLSD& event) const; + + /// Extract the @a key value from the incoming @a event, and call the + /// callable whose name is specified by that map @a key. If no such + /// callable exists, die with LL_ERRS. If the @a event fails to match the + /// @a required prototype specified at add() time, die with LL_ERRS. + void operator()(const LLSD& event) const; + + /// Fetch the Callable for the specified name. If no such name was + /// registered, return an empty() Callable. + Callable get(const std::string& name) const; + +private: + template <class CLASS, typename METHOD> + void addMethod(const std::string& name, const METHOD& method, const LLSD& required) + { + CLASS* downcast = dynamic_cast<CLASS*>(this); + if (! downcast) + { + addFail(name, typeid(CLASS).name()); + } + else + { + add(name, boost::bind(method, downcast, _1), required); + } + } + void addFail(const std::string& name, const std::string& classname) const; + /// try to dispatch, return @c true if success + bool attemptCall(const std::string& name, const LLSD& event) const; + + std::string mDesc, mKey; + typedef std::map<std::string, std::pair<Callable, LLSD> > DispatchMap; + DispatchMap mDispatch; +}; + +/** + * Bundle an LLEventPump and a listener with an LLEventDispatcher. A class + * that contains (or derives from) LLDispatchListener need only specify the + * LLEventPump name and dispatch key, and add() its methods. Incoming events + * will automatically be dispatched. + */ +class LL_COMMON_API LLDispatchListener: public LLEventDispatcher +{ +public: + LLDispatchListener(const std::string& pumpname, const std::string& key); + + std::string getPumpName() const { return mPump.getName(); } + +private: + bool process(const LLSD& event); + + LLEventStream mPump; + LLTempBoundListener mBoundListener; +}; + +#endif /* ! defined(LL_LLEVENTDISPATCHER_H) */ diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 64e5cb5da7..192d79b27d 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -1,943 +1,943 @@ -/**
- * @file llevents.h
- * @author Kent Quirk, Nat Goodspeed
- * @date 2008-09-11
- * @brief This is an implementation of the event system described at
- * 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=viewergpl$
- * Copyright (c) 2008, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLEVENTS_H)
-#define LL_LLEVENTS_H
-
-#include <string>
-#include <map>
-#include <set>
-#include <vector>
-#include <deque>
-#include <stdexcept>
-#if LL_WINDOWS
- #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)
-#endif
-
-#include <boost/bind.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/enable_shared_from_this.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/function.hpp>
-#include <boost/static_assert.hpp>
-#include "llsd.h"
-#include "llsingleton.h"
-#include "lldependencies.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
-#endif
-
-/*****************************************************************************
-* Signal and handler declarations
-* Using a single handler signature means that we can have a common handler
-* type, rather than needing a distinct one for each different handler.
-*****************************************************************************/
-
-/**
- * A boost::signals Combiner that stops the first time a handler returns true
- * We need this because we want to have our handlers return bool, so that
- * we have the option to cause a handler to stop further processing. The
- * default handler fails when the signal returns a value but has no slots.
- */
-struct LLStopWhenHandled
-{
- typedef bool result_type;
-
- template<typename InputIterator>
- result_type operator()(InputIterator first, InputIterator last) const
- {
- for (InputIterator si = first; si != last; ++si)
- {
- if (*si)
- {
- return true;
- }
- }
- return false;
- }
-};
-
-/**
- * We want to have a standard signature for all signals; this way,
- * we can easily document a protocol for communicating across
- * dlls and into scripting languages someday.
- *
- * We want to return a bool to indicate whether the signal has been
- * handled and should NOT be passed on to other listeners.
- * Return true to stop further handling of the signal, and false
- * to continue.
- *
- * We take an LLSD because this way the contents of the signal
- * are independent of the API used to communicate it.
- * It is const ref because then there's low cost to pass it;
- * if you only need to inspect it, it's very cheap.
- *
- * @internal
- * The @c float template parameter indicates that we will internally use @c
- * float to indicate relative listener order on a given LLStandardSignal.
- * Don't worry, the @c float values are strictly internal! They are not part
- * of the interface, for the excellent reason that requiring the caller to
- * specify a numeric key to establish order means that the caller must know
- * the universe of possible values. We use LLDependencies for that instead.
- */
-typedef boost::signals2::signal<bool(const LLSD&), LLStopWhenHandled, float> LLStandardSignal;
-/// Methods that forward listeners (e.g. constructed with
-/// <tt>boost::bind()</tt>) should accept (const LLEventListener&)
-typedef LLStandardSignal::slot_type LLEventListener;
-/// Result of registering a listener, supports <tt>connected()</tt>,
-/// <tt>disconnect()</tt> and <tt>blocked()</tt>
-typedef boost::signals2::connection LLBoundListener;
-/// Storing an LLBoundListener in LLTempBoundListener will disconnect the
-/// referenced listener when the LLTempBoundListener instance is destroyed.
-typedef boost::signals2::scoped_connection LLTempBoundListener;
-
-/**
- * A common idiom for event-based code is to accept either a callable --
- * directly called on completion -- or the string name of an LLEventPump on
- * which to post the completion event. Specifying a parameter as <tt>const
- * LLListenerOrPumpName&</tt> allows either.
- *
- * Calling a validly-constructed LLListenerOrPumpName, passing the LLSD
- * 'event' object, either calls the callable or posts the event to the named
- * LLEventPump.
- *
- * A default-constructed LLListenerOrPumpName is 'empty'. (This is useful as
- * the default value of an optional method parameter.) Calling it throws
- * LLListenerOrPumpName::Empty. Test for this condition beforehand using
- * either <tt>if (param)</tt> or <tt>if (! param)</tt>.
- */
-class LL_COMMON_API LLListenerOrPumpName
-{
-public:
- /// passing string name of LLEventPump
- LLListenerOrPumpName(const std::string& pumpname);
- /// passing string literal (overload so compiler isn't forced to infer
- /// double conversion)
- LLListenerOrPumpName(const char* pumpname);
- /// passing listener -- the "anything else" catch-all case. The type of an
- /// object constructed by boost::bind() isn't intended to be written out.
- /// Normally we'd just accept 'const LLEventListener&', but that would
- /// require double implicit conversion: boost::bind() object to
- /// LLEventListener, LLEventListener to LLListenerOrPumpName. So use a
- /// template to forward anything.
- template<typename T>
- LLListenerOrPumpName(const T& listener): mListener(listener) {}
-
- /// for omitted method parameter: uninitialized mListener
- LLListenerOrPumpName() {}
-
- /// test for validity
- operator bool() const { return bool(mListener); }
- bool operator! () const { return ! mListener; }
-
- /// explicit accessor
- const LLEventListener& getListener() const { return *mListener; }
-
- /// implicit conversion to LLEventListener
- operator LLEventListener() const { return *mListener; }
-
- /// allow calling directly
- bool operator()(const LLSD& event) const;
-
- /// exception if you try to call when empty
- struct Empty: public std::runtime_error
- {
- Empty(const std::string& what):
- std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {}
- };
-
-private:
- boost::optional<LLEventListener> mListener;
-};
-
-/*****************************************************************************
-* LLEventPumps
-*****************************************************************************/
-class LLEventPump;
-
-/**
- * LLEventPumps is a Singleton manager through which one typically accesses
- * this subsystem.
- */
-class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
-{
- friend class LLSingleton<LLEventPumps>;
-public:
- /**
- * Find or create an LLEventPump instance with a specific name. We return
- * a reference so there's no question about ownership. obtain() @em finds
- * an instance without conferring @em ownership.
- */
- LLEventPump& obtain(const std::string& name);
- /**
- * Flush all known LLEventPump instances
- */
- void flush();
-
- /**
- * Reset all known LLEventPump instances
- * workaround for DEV-35406 crash on shutdown
- */
- void reset();
-
-private:
- friend class LLEventPump;
- /**
- * Register a new LLEventPump instance (internal)
- */
- std::string registerNew(const LLEventPump&, const std::string& name, bool tweak);
- /**
- * Unregister a doomed LLEventPump instance (internal)
- */
- void unregister(const LLEventPump&);
-
-private:
- LLEventPumps();
- ~LLEventPumps();
-
-testable:
- // Map of all known LLEventPump instances, whether or not we instantiated
- // them. We store a plain old LLEventPump* because this map doesn't claim
- // ownership of the instances. Though the common usage pattern is to
- // request an instance using obtain(), it's fair to instantiate an
- // LLEventPump subclass statically, as a class member, on the stack or on
- // the heap. In such cases, the instantiating party is responsible for its
- // lifespan.
- typedef std::map<std::string, LLEventPump*> PumpMap;
- PumpMap mPumpMap;
- // Set of all LLEventPumps we instantiated. Membership in this set means
- // we claim ownership, and will delete them when this LLEventPumps is
- // destroyed.
- typedef std::set<LLEventPump*> PumpSet;
- PumpSet mOurPumps;
- // LLEventPump names that should be instantiated as LLEventQueue rather
- // than as LLEventStream
- typedef std::set<std::string> PumpNames;
- PumpNames mQueueNames;
-};
-
-/*****************************************************************************
-* details
-*****************************************************************************/
-namespace LLEventDetail
-{
- /// Any callable capable of connecting an LLEventListener to an
- /// LLStandardSignal to produce an LLBoundListener can be mapped to this
- /// signature.
- typedef boost::function<LLBoundListener(const LLEventListener&)> ConnectFunc;
-
- /**
- * Utility template function to use Visitor appropriately
- *
- * @param listener Callable to connect, typically a boost::bind()
- * expression. This will be visited by Visitor using boost::visit_each().
- * @param connect_func Callable that will connect() @a listener to an
- * LLStandardSignal, returning LLBoundListener.
- */
- template <typename LISTENER>
- LLBoundListener visit_and_connect(const LISTENER& listener,
- const ConnectFunc& connect_func);
-} // namespace LLEventDetail
-
-/*****************************************************************************
-* LLEventTrackable
-*****************************************************************************/
-/**
- * LLEventTrackable wraps boost::signals2::trackable, which resembles
- * boost::trackable. Derive your listener class from LLEventTrackable instead,
- * and use something like
- * <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method,
- * instance, _1))</tt>. This will implicitly disconnect when the object
- * referenced by @c instance is destroyed.
- *
- * @note
- * LLEventTrackable doesn't address a couple of cases:
- * * Object destroyed during call
- * - You enter a slot call in thread A.
- * - Thread B destroys the object, which of course disconnects it from any
- * future slot calls.
- * - Thread A's call uses 'this', which now refers to a defunct object.
- * Undefined behavior results.
- * * Call during destruction
- * - @c MySubclass is derived from LLEventTrackable.
- * - @c MySubclass registers one of its own methods using
- * <tt>LLEventPump::listen()</tt>.
- * - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt>
- * runs, destroying state specific to the subclass. (For instance, a
- * <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.)
- * - The listening method will not be disconnected until
- * <tt>~LLEventTrackable()</tt> runs.
- * - Before we get there, another thread posts data to the @c LLEventPump
- * instance, calling the @c MySubclass method.
- * - The method in question relies on valid @c MySubclass state. (For
- * instance, it attempts to dereference the <tt>Foo*</tt> pointer that was
- * <tt>delete</tt>d but not zeroed.)
- * - Undefined behavior results.
- * If you suspect you may encounter any such scenario, you're better off
- * managing the lifespan of your object with <tt>boost::shared_ptr</tt>.
- * Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression
- * involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging
- * thread-safe Boost.Signals2 machinery.
- */
-typedef boost::signals2::trackable LLEventTrackable;
-
-/*****************************************************************************
-* LLEventPump
-*****************************************************************************/
-/**
- * LLEventPump is the base class interface through which we access the
- * concrete subclasses LLEventStream and LLEventQueue.
- *
- * @NOTE
- * LLEventPump derives from LLEventTrackable so that when you "chain"
- * LLEventPump instances together, they will automatically disconnect on
- * destruction. Please see LLEventTrackable documentation for situations in
- * which this may be perilous across threads.
- */
-class LL_COMMON_API LLEventPump: public LLEventTrackable
-{
-public:
- /**
- * Exception thrown by LLEventPump(). You are trying to instantiate an
- * LLEventPump (subclass) using the same name as some other instance, and
- * you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
- * variant.
- */
- struct DupPumpName: public std::runtime_error
- {
- DupPumpName(const std::string& what):
- std::runtime_error(std::string("DupPumpName: ") + what) {}
- };
-
- /**
- * Instantiate an LLEventPump (subclass) with the string name by which it
- * can be found using LLEventPumps::obtain().
- *
- * If you pass (or default) @a tweak to @c false, then a duplicate name
- * will throw DupPumpName. This won't happen if LLEventPumps::obtain()
- * instantiates the LLEventPump, because obtain() uses find-or-create
- * logic. It can only happen if you instantiate an LLEventPump in your own
- * code -- and a collision with the name of some other LLEventPump is
- * likely to cause much more subtle problems!
- *
- * When you hand-instantiate an LLEventPump, consider passing @a tweak as
- * @c true. This directs LLEventPump() to append a suffix to the passed @a
- * name to make it unique. You can retrieve the adjusted name by calling
- * getName() on your new instance.
- */
- LLEventPump(const std::string& name, bool tweak=false);
- virtual ~LLEventPump();
-
- /// group exceptions thrown by listen(). We use exceptions because these
- /// particular errors are likely to be coding errors, found and fixed by
- /// the developer even before preliminary checkin.
- struct ListenError: public std::runtime_error
- {
- ListenError(const std::string& what): std::runtime_error(what) {}
- };
- /**
- * exception thrown by listen(). You are attempting to register a
- * listener on this LLEventPump using the same listener name as an
- * already-registered listener.
- */
- struct DupListenerName: public ListenError
- {
- DupListenerName(const std::string& what):
- ListenError(std::string("DupListenerName: ") + what)
- {}
- };
- /**
- * exception thrown by listen(). The order dependencies specified for your
- * listener are incompatible with existing listeners.
- *
- * Consider listener "a" which specifies before "b" and "b" which
- * specifies before "c". You are now attempting to register "c" before
- * "a". There is no order that can satisfy all constraints.
- */
- struct Cycle: public ListenError
- {
- Cycle(const std::string& what): ListenError(std::string("Cycle: ") + what) {}
- };
- /**
- * exception thrown by listen(). This one means that your new listener
- * would force a change to the order of previously-registered listeners,
- * and we don't have a good way to implement that.
- *
- * Consider listeners "some", "other" and "third". "some" and "other" are
- * registered earlier without specifying relative order, so "other"
- * happens to be first. Now you attempt to register "third" after "some"
- * and before "other". Whoops, that would require swapping "some" and
- * "other", which we can't do. Instead we throw this exception.
- *
- * It may not be possible to change the registration order so we already
- * know "third"s order requirement by the time we register the second of
- * "some" and "other". A solution would be to specify that "some" must
- * come before "other", or equivalently that "other" must come after
- * "some".
- */
- struct OrderChange: public ListenError
- {
- OrderChange(const std::string& what): ListenError(std::string("OrderChange: ") + what) {}
- };
-
- /// used by listen()
- typedef std::vector<std::string> NameList;
- /// convenience placeholder for when you explicitly want to pass an empty
- /// NameList
- const static NameList empty;
-
- /// Get this LLEventPump's name
- std::string getName() const { return mName; }
-
- /**
- * Register a new listener with a unique name. Specify an optional list
- * of other listener names after which this one must be called, likewise
- * an optional list of other listener names before which this one must be
- * called. The other listeners mentioned need not yet be registered
- * themselves. listen() can throw any ListenError; see ListenError
- * subclasses.
- *
- * The listener name must be unique among active listeners for this
- * LLEventPump, else you get DupListenerName. If you don't care to invent
- * a name yourself, use inventName(). (I was tempted to recognize e.g. ""
- * and internally generate a distinct name for that case. But that would
- * handle badly the scenario in which you want to add, remove, re-add,
- * etc. the same listener: each new listen() call would necessarily
- * perform a new dependency sort. Assuming you specify the same
- * after/before lists each time, using inventName() when you first
- * instantiate your listener, then passing the same name on each listen()
- * call, allows us to optimize away the second and subsequent dependency
- * sorts.
- *
- * If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a
- * listener, listen() will inspect the components of that expression. If a
- * bound object matches any of several cases, the connection will
- * automatically be disconnected when that object is destroyed.
- *
- * * You bind a <tt>boost::weak_ptr</tt>.
- * * Binding a <tt>boost::shared_ptr</tt> that way would ensure that the
- * referenced object would @em never be destroyed, since the @c
- * shared_ptr stored in the LLEventPump would remain an outstanding
- * reference. Use the weaken() function to convert your @c shared_ptr to
- * @c weak_ptr. Because this is easy to forget, binding a @c shared_ptr
- * will produce a compile error (@c BOOST_STATIC_ASSERT failure).
- * * You bind a simple pointer or reference to an object derived from
- * <tt>boost::enable_shared_from_this</tt>. (UNDER CONSTRUCTION)
- * * You bind a simple pointer or reference to an object derived from
- * LLEventTrackable. Unlike the cases described above, though, this is
- * vulnerable to a couple of cross-thread race conditions, as described
- * in the LLEventTrackable documentation.
- */
- template <typename LISTENER>
- LLBoundListener listen(const std::string& name, const LISTENER& listener,
- const NameList& after=NameList(),
- const NameList& before=NameList())
- {
- // Examine listener, using our listen_impl() method to make the
- // actual connection.
- // This is why listen() is a template. Conversion from boost::bind()
- // to LLEventListener performs type erasure, so it's important to look
- // at the boost::bind object itself before that happens.
- return LLEventDetail::visit_and_connect(listener,
- boost::bind(&LLEventPump::listen_impl,
- this,
- name,
- _1,
- after,
- before));
- }
-
- /// Get the LLBoundListener associated with the passed name (dummy
- /// LLBoundListener if not found)
- virtual LLBoundListener getListener(const std::string& name) const;
- /**
- * Instantiate one of these to block an existing connection:
- * @code
- * { // in some local scope
- * LLEventPump::Blocker block(someLLBoundListener);
- * // code that needs the connection blocked
- * } // unblock the connection again
- * @endcode
- */
- typedef boost::signals2::shared_connection_block Blocker;
- /// Unregister a listener by name. Prefer this to
- /// <tt>getListener(name).disconnect()</tt> because stopListening() also
- /// forgets this name.
- virtual void stopListening(const std::string& name);
- /// Post an event to all listeners. The @c bool return is only meaningful
- /// if the underlying leaf class is LLEventStream -- beware of relying on
- /// it too much! Truthfully, we return @c bool mostly to permit chaining
- /// one LLEventPump as a listener on another.
- virtual bool post(const LLSD&) = 0;
- /// Enable/disable: while disabled, silently ignore all post() calls
- virtual void enable(bool enabled=true) { mEnabled = enabled; }
- /// query
- virtual bool enabled() const { return mEnabled; }
-
- /// Generate a distinct name for a listener -- see listen()
- static std::string inventName(const std::string& pfx="listener");
-
-private:
- friend class LLEventPumps;
- /// flush queued events
- virtual void flush() {}
-
- virtual void reset();
-
-private:
- virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&,
- const NameList& after,
- const NameList& before);
- std::string mName;
-
-protected:
- /// implement the dispatching
- boost::scoped_ptr<LLStandardSignal> mSignal;
-
- /// valve open?
- bool mEnabled;
- /// Map of named listeners. This tracks the listeners that actually exist
- /// at this moment. When we stopListening(), we discard the entry from
- /// this map.
- typedef std::map<std::string, boost::signals2::connection> ConnectionMap;
- ConnectionMap mConnections;
- typedef LLDependencies<std::string, float> DependencyMap;
- /// Dependencies between listeners. For each listener, track the float
- /// used to establish its place in mSignal's order. This caches all the
- /// listeners that have ever registered; stopListening() does not discard
- /// the entry from this map. This is to avoid a new dependency sort if the
- /// same listener with the same dependencies keeps hopping on and off this
- /// LLEventPump.
- DependencyMap mDeps;
-};
-
-/*****************************************************************************
-* LLEventStream
-*****************************************************************************/
-/**
- * LLEventStream is a thin wrapper around LLStandardSignal. Posting an
- * event immediately calls all registered listeners.
- */
-class LL_COMMON_API LLEventStream: public LLEventPump
-{
-public:
- LLEventStream(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
- virtual ~LLEventStream() {}
-
- /// Post an event to all listeners
- virtual bool post(const LLSD& event);
-};
-
-/*****************************************************************************
-* LLEventQueue
-*****************************************************************************/
-/**
- * LLEventQueue isa LLEventPump whose post() method defers calling registered
- * listeners until flush() is called.
- */
-class LL_COMMON_API LLEventQueue: public LLEventPump
-{
-public:
- LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
- virtual ~LLEventQueue() {}
-
- /// Post an event to all listeners
- virtual bool post(const LLSD& event);
-
-private:
- /// flush queued events
- virtual void flush();
-
-private:
- typedef std::deque<LLSD> EventQueue;
- EventQueue mEventQueue;
-};
-
-/*****************************************************************************
-* LLReqID
-*****************************************************************************/
-/**
- * This class helps the implementer of a given event API to honor the
- * ["reqid"] convention. By this convention, each event API stamps into its
- * response LLSD a ["reqid"] key whose value echoes the ["reqid"] value, if
- * any, from the corresponding request.
- *
- * This supports an (atypical, but occasionally necessary) use case in which
- * two or more asynchronous requests are multiplexed onto the same ["reply"]
- * LLEventPump. Since the response events could arrive in arbitrary order, the
- * caller must be able to demux them. It does so by matching the ["reqid"]
- * value in each response with the ["reqid"] value in the corresponding
- * request.
- *
- * It is the caller's responsibility to ensure distinct ["reqid"] values for
- * that case. Though LLSD::UUID is guaranteed to work, it might be overkill:
- * the "namespace" of unique ["reqid"] values is simply the set of requests
- * specifying the same ["reply"] LLEventPump name.
- *
- * Making a given event API echo the request's ["reqid"] into the response is
- * nearly trivial. This helper is mostly for mnemonic purposes, to serve as a
- * place to put these comments. We hope that each time a coder implements a
- * new event API based on some existing one, s/he will say, "Huh, what's an
- * LLReqID?" and look up this material.
- *
- * The hardest part about the convention is deciding where to store the
- * ["reqid"] value. Ironically, LLReqID can't help with that: you must store
- * an LLReqID instance in whatever storage will persist until the reply is
- * sent. For example, if the request ultimately ends up using a Responder
- * subclass, storing an LLReqID instance in the Responder works.
- *
- * @note
- * The @em implementer of an event API must honor the ["reqid"] convention.
- * However, the @em caller of an event API need only use it if s/he is sharing
- * the same ["reply"] LLEventPump for two or more asynchronous event API
- * requests.
- *
- * In most cases, it's far easier for the caller to instantiate a local
- * LLEventStream and pass its name to the event API in question. Then it's
- * perfectly reasonable not to set a ["reqid"] key in the request, ignoring
- * the @c isUndefined() ["reqid"] value in the response.
- */
-class LL_COMMON_API LLReqID
-{
-public:
- /**
- * If you have the request in hand at the time you instantiate the
- * LLReqID, pass that request to extract its ["reqid"].
- */
- LLReqID(const LLSD& request):
- mReqid(request["reqid"])
- {}
- /// If you don't yet have the request, use setFrom() later.
- LLReqID() {}
-
- /// Extract and store the ["reqid"] value from an incoming request.
- void setFrom(const LLSD& request)
- {
- mReqid = request["reqid"];
- }
-
- /// Set ["reqid"] key into a pending response LLSD object.
- void stamp(LLSD& response) const;
-
- /// Make a whole new response LLSD object with our ["reqid"].
- LLSD makeResponse() const
- {
- LLSD response;
- stamp(response);
- return response;
- }
-
- /// Not really sure of a use case for this accessor...
- LLSD getReqID() const { return mReqid; }
-
-private:
- LLSD mReqid;
-};
-
-/*****************************************************************************
-* Underpinnings
-*****************************************************************************/
-/**
- * We originally provided a suite of overloaded
- * LLEventTrackable::listenTo(LLEventPump&, ...) methods that would call
- * LLEventPump::listen(...) and then pass the returned LLBoundListener to
- * LLEventTrackable::track(). This was workable but error-prone: the coder
- * must remember to call listenTo() rather than the more straightforward
- * listen() method.
- *
- * Now we publish only the single canonical listen() method, so there's a
- * uniform mechanism. Having a single way to do this is good, in that there's
- * no question in the coder's mind which of several alternatives to choose.
- *
- * To support automatic connection management, we use boost::visit_each
- * (http://www.boost.org/doc/libs/1_37_0/doc/html/boost/visit_each.html) to
- * inspect each argument of a boost::bind expression. (Although the visit_each
- * mechanism was first introduced with the original Boost.Signals library, it
- * was only later documented.)
- *
- * Cases:
- * * At least one of the function's arguments is a boost::weak_ptr<T>. Pass
- * the corresponding shared_ptr to slot_type::track(). Ideally that would be
- * the object whose method we want to call, but in fact we do the same for
- * any weak_ptr we might find among the bound arguments. If we're passing
- * our bound method a weak_ptr to some object, wouldn't the destruction of
- * that object invalidate the call? So we disconnect automatically when any
- * such object is destroyed. This is the mechanism preferred by boost::
- * signals2.
- * * One of the functions's arguments is a boost::shared_ptr<T>. This produces
- * a compile error: the bound copy of the shared_ptr stored in the
- * boost_bind object stored in the signal object would make the referenced
- * T object immortal. We provide a weaken() function. Pass
- * weaken(your_shared_ptr) instead. (We can inspect, but not modify, the
- * boost::bind object. Otherwise we'd replace the shared_ptr with weak_ptr
- * implicitly and just proceed.)
- * * One of the function's arguments is a plain pointer/reference to an object
- * derived from boost::enable_shared_from_this. We assume that this object
- * is managed using boost::shared_ptr, so we implicitly extract a shared_ptr
- * and track that. (UNDER CONSTRUCTION)
- * * One of the function's arguments is derived from LLEventTrackable. Pass
- * the LLBoundListener to its LLEventTrackable::track(). This is vulnerable
- * to a couple different race conditions, as described in LLEventTrackable
- * documentation. (NOTE: Now that LLEventTrackable is a typedef for
- * boost::signals2::trackable, the Signals2 library handles this itself, so
- * our visitor needs no special logic for this case.)
- * * Any other argument type is irrelevant to automatic connection management.
- */
-
-namespace LLEventDetail
-{
- template <typename F>
- const F& unwrap(const F& f) { return f; }
-
- template <typename F>
- const F& unwrap(const boost::reference_wrapper<F>& f) { return f.get(); }
-
- // Most of the following is lifted from the Boost.Signals use of
- // visit_each.
- template<bool Cond> struct truth {};
-
- /**
- * boost::visit_each() Visitor, used on a template argument <tt>const F&
- * f</tt> as follows (see visit_and_connect()):
- * @code
- * LLEventListener listener(f);
- * Visitor visitor(listener); // bind listener so it can track() shared_ptrs
- * using boost::visit_each; // allow unqualified visit_each() call for ADL
- * visit_each(visitor, unwrap(f));
- * @endcode
- */
- class Visitor
- {
- public:
- /**
- * Visitor binds a reference to LLEventListener so we can track() any
- * shared_ptrs we find in the argument list.
- */
- Visitor(LLEventListener& listener):
- mListener(listener)
- {
- }
-
- /**
- * boost::visit_each() calls this method for each component of a
- * boost::bind() expression.
- */
- template <typename T>
- void operator()(const T& t) const
- {
- decode(t, 0);
- }
-
- private:
- // decode() decides between a reference wrapper and anything else
- // boost::ref() variant
- template<typename T>
- void decode(const boost::reference_wrapper<T>& t, int) const
- {
-// add_if_trackable(t.get_pointer());
- }
-
- // decode() anything else
- template<typename T>
- void decode(const T& t, long) const
- {
- typedef truth<(boost::is_pointer<T>::value)> is_a_pointer;
- maybe_get_pointer(t, is_a_pointer());
- }
-
- // maybe_get_pointer() decides between a pointer and a non-pointer
- // plain pointer variant
- template<typename T>
- void maybe_get_pointer(const T& t, truth<true>) const
- {
-// add_if_trackable(t);
- }
-
- // shared_ptr variant
- template<typename T>
- void maybe_get_pointer(const boost::shared_ptr<T>& t, truth<false>) const
- {
- // If we have a shared_ptr to this object, it doesn't matter
- // whether the object is derived from LLEventTrackable, so no
- // further analysis of T is needed.
-// mListener.track(t);
-
- // Make this case illegal. Passing a bound shared_ptr to
- // slot_type::track() is useless, since the bound shared_ptr will
- // keep the object alive anyway! Force the coder to cast to weak_ptr.
-
- // Trivial as it is, make the BOOST_STATIC_ASSERT() condition
- // dependent on template param so the macro is only evaluated if
- // this method is in fact instantiated, as described here:
- // http://www.boost.org/doc/libs/1_34_1/doc/html/boost_staticassert.html
-
- // ATTENTION: Don't bind a shared_ptr<anything> using
- // LLEventPump::listen(boost::bind()). Doing so captures a copy of
- // the shared_ptr, making the referenced object effectively
- // immortal. Use the weaken() function, e.g.:
- // somepump.listen(boost::bind(...weaken(my_shared_ptr)...));
- // This lets us automatically disconnect when the referenced
- // object is destroyed.
- BOOST_STATIC_ASSERT(sizeof(T) == 0);
- }
-
- // weak_ptr variant
- template<typename T>
- void maybe_get_pointer(const boost::weak_ptr<T>& t, truth<false>) const
- {
- // If we have a weak_ptr to this object, it doesn't matter
- // whether the object is derived from LLEventTrackable, so no
- // further analysis of T is needed.
- mListener.track(t);
-// std::cout << "Found weak_ptr<" << typeid(T).name() << ">!\n";
- }
-
-#if 0
- // reference to anything derived from boost::enable_shared_from_this
- template <typename T>
- inline void maybe_get_pointer(const boost::enable_shared_from_this<T>& ct,
- truth<false>) const
- {
- // Use the slot_type::track(shared_ptr) mechanism. Cast away
- // const-ness because (in our code base anyway) it's unusual
- // to find shared_ptr<const T>.
- boost::enable_shared_from_this<T>&
- t(const_cast<boost::enable_shared_from_this<T>&>(ct));
- std::cout << "Capturing shared_from_this()" << std::endl;
- boost::shared_ptr<T> sp(t.shared_from_this());
-/*==========================================================================*|
- std::cout << "Capturing weak_ptr" << std::endl;
- boost::weak_ptr<T> wp(sp);
-|*==========================================================================*/
- std::cout << "Tracking shared__ptr" << std::endl;
- mListener.track(sp);
- }
-#endif
-
- // non-pointer variant
- template<typename T>
- void maybe_get_pointer(const T& t, truth<false>) const
- {
- // Take the address of this object, because the object itself may be
- // trackable
-// add_if_trackable(boost::addressof(t));
- }
-
-/*==========================================================================*|
- // add_if_trackable() adds LLEventTrackable objects to mTrackables
- inline void add_if_trackable(const LLEventTrackable* t) const
- {
- if (t)
- {
- }
- }
-
- // pointer to anything not an LLEventTrackable subclass
- inline void add_if_trackable(const void*) const
- {
- }
-
- // pointer to free function
- // The following construct uses the preprocessor to generate
- // add_if_trackable() overloads accepting pointer-to-function taking
- // 0, 1, ..., LLEVENTS_LISTENER_ARITY parameters of arbitrary type.
-#define BOOST_PP_LOCAL_MACRO(n) \
- template <typename R \
- BOOST_PP_COMMA_IF(n) \
- BOOST_PP_ENUM_PARAMS(n, typename T)> \
- inline void \
- add_if_trackable(R (*)(BOOST_PP_ENUM_PARAMS(n, T))) const \
- { \
- }
-#define BOOST_PP_LOCAL_LIMITS (0, LLEVENTS_LISTENER_ARITY)
-#include BOOST_PP_LOCAL_ITERATE()
-#undef BOOST_PP_LOCAL_MACRO
-#undef BOOST_PP_LOCAL_LIMITS
-|*==========================================================================*/
-
- /// Bind a reference to the LLEventListener to call its track() method.
- LLEventListener& mListener;
- };
-
- /**
- * Utility template function to use Visitor appropriately
- *
- * @param raw_listener Callable to connect, typically a boost::bind()
- * expression. This will be visited by Visitor using boost::visit_each().
- * @param connect_funct Callable that will connect() @a raw_listener to an
- * LLStandardSignal, returning LLBoundListener.
- */
- template <typename LISTENER>
- LLBoundListener visit_and_connect(const LISTENER& raw_listener,
- const ConnectFunc& connect_func)
- {
- // Capture the listener
- LLEventListener listener(raw_listener);
- // Define our Visitor, binding the listener so we can call
- // listener.track() if we discover any shared_ptr<Foo>.
- LLEventDetail::Visitor visitor(listener);
- // Allow unqualified visit_each() call for ADL
- using boost::visit_each;
- // Visit each component of a boost::bind() expression. Pass
- // 'raw_listener', our template argument, rather than 'listener' from
- // which type details have been erased. unwrap() comes from
- // Boost.Signals, in case we were passed a boost::ref().
- visit_each(visitor, LLEventDetail::unwrap(raw_listener));
- // Make the connection using passed function. At present, wrapping
- // this functionality into this function is a bit silly: we don't
- // really need a visit_and_connect() function any more, just a visit()
- // function. The definition of this function dates from when, after
- // visit_each(), after establishing the connection, we had to
- // postprocess the new connection with the visitor object. That's no
- // longer necessary.
- return connect_func(listener);
- }
-} // namespace LLEventDetail
-
-// Somewhat to my surprise, passing boost::bind(...boost::weak_ptr<T>...) to
-// listen() fails in Boost code trying to instantiate LLEventListener (i.e.
-// LLStandardSignal::slot_type) because the boost::get_pointer() utility function isn't
-// specialized for boost::weak_ptr. This remedies that omission.
-namespace boost
-{
- template <typename T>
- T* get_pointer(const weak_ptr<T>& ptr) { return shared_ptr<T>(ptr).get(); }
-}
-
-/// Since we forbid use of listen(boost::bind(...shared_ptr<T>...)), provide an
-/// easy way to cast to the corresponding weak_ptr.
-template <typename T>
-boost::weak_ptr<T> weaken(const boost::shared_ptr<T>& ptr)
-{
- return boost::weak_ptr<T>(ptr);
-}
-
-#endif /* ! defined(LL_LLEVENTS_H) */
+/** + * @file llevents.h + * @author Kent Quirk, Nat Goodspeed + * @date 2008-09-11 + * @brief This is an implementation of the event system described at + * 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=viewergpl$ + * Copyright (c) 2008, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLEVENTS_H) +#define LL_LLEVENTS_H + +#include <string> +#include <map> +#include <set> +#include <vector> +#include <deque> +#include <stdexcept> +#if LL_WINDOWS + #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) +#endif + +#include <boost/bind.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.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/function.hpp> +#include <boost/static_assert.hpp> +#include "llsd.h" +#include "llsingleton.h" +#include "lldependencies.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 +#endif + +/***************************************************************************** +* Signal and handler declarations +* Using a single handler signature means that we can have a common handler +* type, rather than needing a distinct one for each different handler. +*****************************************************************************/ + +/** + * A boost::signals Combiner that stops the first time a handler returns true + * We need this because we want to have our handlers return bool, so that + * we have the option to cause a handler to stop further processing. The + * default handler fails when the signal returns a value but has no slots. + */ +struct LLStopWhenHandled +{ + typedef bool result_type; + + template<typename InputIterator> + result_type operator()(InputIterator first, InputIterator last) const + { + for (InputIterator si = first; si != last; ++si) + { + if (*si) + { + return true; + } + } + return false; + } +}; + +/** + * We want to have a standard signature for all signals; this way, + * we can easily document a protocol for communicating across + * dlls and into scripting languages someday. + * + * We want to return a bool to indicate whether the signal has been + * handled and should NOT be passed on to other listeners. + * Return true to stop further handling of the signal, and false + * to continue. + * + * We take an LLSD because this way the contents of the signal + * are independent of the API used to communicate it. + * It is const ref because then there's low cost to pass it; + * if you only need to inspect it, it's very cheap. + * + * @internal + * The @c float template parameter indicates that we will internally use @c + * float to indicate relative listener order on a given LLStandardSignal. + * Don't worry, the @c float values are strictly internal! They are not part + * of the interface, for the excellent reason that requiring the caller to + * specify a numeric key to establish order means that the caller must know + * the universe of possible values. We use LLDependencies for that instead. + */ +typedef boost::signals2::signal<bool(const LLSD&), LLStopWhenHandled, float> LLStandardSignal; +/// Methods that forward listeners (e.g. constructed with +/// <tt>boost::bind()</tt>) should accept (const LLEventListener&) +typedef LLStandardSignal::slot_type LLEventListener; +/// Result of registering a listener, supports <tt>connected()</tt>, +/// <tt>disconnect()</tt> and <tt>blocked()</tt> +typedef boost::signals2::connection LLBoundListener; +/// Storing an LLBoundListener in LLTempBoundListener will disconnect the +/// referenced listener when the LLTempBoundListener instance is destroyed. +typedef boost::signals2::scoped_connection LLTempBoundListener; + +/** + * A common idiom for event-based code is to accept either a callable -- + * directly called on completion -- or the string name of an LLEventPump on + * which to post the completion event. Specifying a parameter as <tt>const + * LLListenerOrPumpName&</tt> allows either. + * + * Calling a validly-constructed LLListenerOrPumpName, passing the LLSD + * 'event' object, either calls the callable or posts the event to the named + * LLEventPump. + * + * A default-constructed LLListenerOrPumpName is 'empty'. (This is useful as + * the default value of an optional method parameter.) Calling it throws + * LLListenerOrPumpName::Empty. Test for this condition beforehand using + * either <tt>if (param)</tt> or <tt>if (! param)</tt>. + */ +class LL_COMMON_API LLListenerOrPumpName +{ +public: + /// passing string name of LLEventPump + LLListenerOrPumpName(const std::string& pumpname); + /// passing string literal (overload so compiler isn't forced to infer + /// double conversion) + LLListenerOrPumpName(const char* pumpname); + /// passing listener -- the "anything else" catch-all case. The type of an + /// object constructed by boost::bind() isn't intended to be written out. + /// Normally we'd just accept 'const LLEventListener&', but that would + /// require double implicit conversion: boost::bind() object to + /// LLEventListener, LLEventListener to LLListenerOrPumpName. So use a + /// template to forward anything. + template<typename T> + LLListenerOrPumpName(const T& listener): mListener(listener) {} + + /// for omitted method parameter: uninitialized mListener + LLListenerOrPumpName() {} + + /// test for validity + operator bool() const { return bool(mListener); } + bool operator! () const { return ! mListener; } + + /// explicit accessor + const LLEventListener& getListener() const { return *mListener; } + + /// implicit conversion to LLEventListener + operator LLEventListener() const { return *mListener; } + + /// allow calling directly + bool operator()(const LLSD& event) const; + + /// exception if you try to call when empty + struct Empty: public std::runtime_error + { + Empty(const std::string& what): + std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {} + }; + +private: + boost::optional<LLEventListener> mListener; +}; + +/***************************************************************************** +* LLEventPumps +*****************************************************************************/ +class LLEventPump; + +/** + * LLEventPumps is a Singleton manager through which one typically accesses + * this subsystem. + */ +class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps> +{ + friend class LLSingleton<LLEventPumps>; +public: + /** + * Find or create an LLEventPump instance with a specific name. We return + * a reference so there's no question about ownership. obtain() @em finds + * an instance without conferring @em ownership. + */ + LLEventPump& obtain(const std::string& name); + /** + * Flush all known LLEventPump instances + */ + void flush(); + + /** + * Reset all known LLEventPump instances + * workaround for DEV-35406 crash on shutdown + */ + void reset(); + +private: + friend class LLEventPump; + /** + * Register a new LLEventPump instance (internal) + */ + std::string registerNew(const LLEventPump&, const std::string& name, bool tweak); + /** + * Unregister a doomed LLEventPump instance (internal) + */ + void unregister(const LLEventPump&); + +private: + LLEventPumps(); + ~LLEventPumps(); + +testable: + // Map of all known LLEventPump instances, whether or not we instantiated + // them. We store a plain old LLEventPump* because this map doesn't claim + // ownership of the instances. Though the common usage pattern is to + // request an instance using obtain(), it's fair to instantiate an + // LLEventPump subclass statically, as a class member, on the stack or on + // the heap. In such cases, the instantiating party is responsible for its + // lifespan. + typedef std::map<std::string, LLEventPump*> PumpMap; + PumpMap mPumpMap; + // Set of all LLEventPumps we instantiated. Membership in this set means + // we claim ownership, and will delete them when this LLEventPumps is + // destroyed. + typedef std::set<LLEventPump*> PumpSet; + PumpSet mOurPumps; + // LLEventPump names that should be instantiated as LLEventQueue rather + // than as LLEventStream + typedef std::set<std::string> PumpNames; + PumpNames mQueueNames; +}; + +/***************************************************************************** +* details +*****************************************************************************/ +namespace LLEventDetail +{ + /// Any callable capable of connecting an LLEventListener to an + /// LLStandardSignal to produce an LLBoundListener can be mapped to this + /// signature. + typedef boost::function<LLBoundListener(const LLEventListener&)> ConnectFunc; + + /** + * Utility template function to use Visitor appropriately + * + * @param listener Callable to connect, typically a boost::bind() + * expression. This will be visited by Visitor using boost::visit_each(). + * @param connect_func Callable that will connect() @a listener to an + * LLStandardSignal, returning LLBoundListener. + */ + template <typename LISTENER> + LLBoundListener visit_and_connect(const LISTENER& listener, + const ConnectFunc& connect_func); +} // namespace LLEventDetail + +/***************************************************************************** +* LLEventTrackable +*****************************************************************************/ +/** + * LLEventTrackable wraps boost::signals2::trackable, which resembles + * boost::trackable. Derive your listener class from LLEventTrackable instead, + * and use something like + * <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method, + * instance, _1))</tt>. This will implicitly disconnect when the object + * referenced by @c instance is destroyed. + * + * @note + * LLEventTrackable doesn't address a couple of cases: + * * Object destroyed during call + * - You enter a slot call in thread A. + * - Thread B destroys the object, which of course disconnects it from any + * future slot calls. + * - Thread A's call uses 'this', which now refers to a defunct object. + * Undefined behavior results. + * * Call during destruction + * - @c MySubclass is derived from LLEventTrackable. + * - @c MySubclass registers one of its own methods using + * <tt>LLEventPump::listen()</tt>. + * - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt> + * runs, destroying state specific to the subclass. (For instance, a + * <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.) + * - The listening method will not be disconnected until + * <tt>~LLEventTrackable()</tt> runs. + * - Before we get there, another thread posts data to the @c LLEventPump + * instance, calling the @c MySubclass method. + * - The method in question relies on valid @c MySubclass state. (For + * instance, it attempts to dereference the <tt>Foo*</tt> pointer that was + * <tt>delete</tt>d but not zeroed.) + * - Undefined behavior results. + * If you suspect you may encounter any such scenario, you're better off + * managing the lifespan of your object with <tt>boost::shared_ptr</tt>. + * Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression + * involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging + * thread-safe Boost.Signals2 machinery. + */ +typedef boost::signals2::trackable LLEventTrackable; + +/***************************************************************************** +* LLEventPump +*****************************************************************************/ +/** + * LLEventPump is the base class interface through which we access the + * concrete subclasses LLEventStream and LLEventQueue. + * + * @NOTE + * LLEventPump derives from LLEventTrackable so that when you "chain" + * LLEventPump instances together, they will automatically disconnect on + * destruction. Please see LLEventTrackable documentation for situations in + * which this may be perilous across threads. + */ +class LL_COMMON_API LLEventPump: public LLEventTrackable +{ +public: + /** + * Exception thrown by LLEventPump(). You are trying to instantiate an + * LLEventPump (subclass) using the same name as some other instance, and + * you didn't pass <tt>tweak=true</tt> to permit it to generate a unique + * variant. + */ + struct DupPumpName: public std::runtime_error + { + DupPumpName(const std::string& what): + std::runtime_error(std::string("DupPumpName: ") + what) {} + }; + + /** + * Instantiate an LLEventPump (subclass) with the string name by which it + * can be found using LLEventPumps::obtain(). + * + * If you pass (or default) @a tweak to @c false, then a duplicate name + * will throw DupPumpName. This won't happen if LLEventPumps::obtain() + * instantiates the LLEventPump, because obtain() uses find-or-create + * logic. It can only happen if you instantiate an LLEventPump in your own + * code -- and a collision with the name of some other LLEventPump is + * likely to cause much more subtle problems! + * + * When you hand-instantiate an LLEventPump, consider passing @a tweak as + * @c true. This directs LLEventPump() to append a suffix to the passed @a + * name to make it unique. You can retrieve the adjusted name by calling + * getName() on your new instance. + */ + LLEventPump(const std::string& name, bool tweak=false); + virtual ~LLEventPump(); + + /// group exceptions thrown by listen(). We use exceptions because these + /// particular errors are likely to be coding errors, found and fixed by + /// the developer even before preliminary checkin. + struct ListenError: public std::runtime_error + { + ListenError(const std::string& what): std::runtime_error(what) {} + }; + /** + * exception thrown by listen(). You are attempting to register a + * listener on this LLEventPump using the same listener name as an + * already-registered listener. + */ + struct DupListenerName: public ListenError + { + DupListenerName(const std::string& what): + ListenError(std::string("DupListenerName: ") + what) + {} + }; + /** + * exception thrown by listen(). The order dependencies specified for your + * listener are incompatible with existing listeners. + * + * Consider listener "a" which specifies before "b" and "b" which + * specifies before "c". You are now attempting to register "c" before + * "a". There is no order that can satisfy all constraints. + */ + struct Cycle: public ListenError + { + Cycle(const std::string& what): ListenError(std::string("Cycle: ") + what) {} + }; + /** + * exception thrown by listen(). This one means that your new listener + * would force a change to the order of previously-registered listeners, + * and we don't have a good way to implement that. + * + * Consider listeners "some", "other" and "third". "some" and "other" are + * registered earlier without specifying relative order, so "other" + * happens to be first. Now you attempt to register "third" after "some" + * and before "other". Whoops, that would require swapping "some" and + * "other", which we can't do. Instead we throw this exception. + * + * It may not be possible to change the registration order so we already + * know "third"s order requirement by the time we register the second of + * "some" and "other". A solution would be to specify that "some" must + * come before "other", or equivalently that "other" must come after + * "some". + */ + struct OrderChange: public ListenError + { + OrderChange(const std::string& what): ListenError(std::string("OrderChange: ") + what) {} + }; + + /// used by listen() + typedef std::vector<std::string> NameList; + /// convenience placeholder for when you explicitly want to pass an empty + /// NameList + const static NameList empty; + + /// Get this LLEventPump's name + std::string getName() const { return mName; } + + /** + * Register a new listener with a unique name. Specify an optional list + * of other listener names after which this one must be called, likewise + * an optional list of other listener names before which this one must be + * called. The other listeners mentioned need not yet be registered + * themselves. listen() can throw any ListenError; see ListenError + * subclasses. + * + * The listener name must be unique among active listeners for this + * LLEventPump, else you get DupListenerName. If you don't care to invent + * a name yourself, use inventName(). (I was tempted to recognize e.g. "" + * and internally generate a distinct name for that case. But that would + * handle badly the scenario in which you want to add, remove, re-add, + * etc. the same listener: each new listen() call would necessarily + * perform a new dependency sort. Assuming you specify the same + * after/before lists each time, using inventName() when you first + * instantiate your listener, then passing the same name on each listen() + * call, allows us to optimize away the second and subsequent dependency + * sorts. + * + * If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a + * listener, listen() will inspect the components of that expression. If a + * bound object matches any of several cases, the connection will + * automatically be disconnected when that object is destroyed. + * + * * You bind a <tt>boost::weak_ptr</tt>. + * * Binding a <tt>boost::shared_ptr</tt> that way would ensure that the + * referenced object would @em never be destroyed, since the @c + * shared_ptr stored in the LLEventPump would remain an outstanding + * reference. Use the weaken() function to convert your @c shared_ptr to + * @c weak_ptr. Because this is easy to forget, binding a @c shared_ptr + * will produce a compile error (@c BOOST_STATIC_ASSERT failure). + * * You bind a simple pointer or reference to an object derived from + * <tt>boost::enable_shared_from_this</tt>. (UNDER CONSTRUCTION) + * * You bind a simple pointer or reference to an object derived from + * LLEventTrackable. Unlike the cases described above, though, this is + * vulnerable to a couple of cross-thread race conditions, as described + * in the LLEventTrackable documentation. + */ + template <typename LISTENER> + LLBoundListener listen(const std::string& name, const LISTENER& listener, + const NameList& after=NameList(), + const NameList& before=NameList()) + { + // Examine listener, using our listen_impl() method to make the + // actual connection. + // This is why listen() is a template. Conversion from boost::bind() + // to LLEventListener performs type erasure, so it's important to look + // at the boost::bind object itself before that happens. + return LLEventDetail::visit_and_connect(listener, + boost::bind(&LLEventPump::listen_impl, + this, + name, + _1, + after, + before)); + } + + /// Get the LLBoundListener associated with the passed name (dummy + /// LLBoundListener if not found) + virtual LLBoundListener getListener(const std::string& name) const; + /** + * Instantiate one of these to block an existing connection: + * @code + * { // in some local scope + * LLEventPump::Blocker block(someLLBoundListener); + * // code that needs the connection blocked + * } // unblock the connection again + * @endcode + */ + typedef boost::signals2::shared_connection_block Blocker; + /// Unregister a listener by name. Prefer this to + /// <tt>getListener(name).disconnect()</tt> because stopListening() also + /// forgets this name. + virtual void stopListening(const std::string& name); + /// Post an event to all listeners. The @c bool return is only meaningful + /// if the underlying leaf class is LLEventStream -- beware of relying on + /// it too much! Truthfully, we return @c bool mostly to permit chaining + /// one LLEventPump as a listener on another. + virtual bool post(const LLSD&) = 0; + /// Enable/disable: while disabled, silently ignore all post() calls + virtual void enable(bool enabled=true) { mEnabled = enabled; } + /// query + virtual bool enabled() const { return mEnabled; } + + /// Generate a distinct name for a listener -- see listen() + static std::string inventName(const std::string& pfx="listener"); + +private: + friend class LLEventPumps; + /// flush queued events + virtual void flush() {} + + virtual void reset(); + +private: + virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&, + const NameList& after, + const NameList& before); + std::string mName; + +protected: + /// implement the dispatching + boost::scoped_ptr<LLStandardSignal> mSignal; + + /// valve open? + bool mEnabled; + /// Map of named listeners. This tracks the listeners that actually exist + /// at this moment. When we stopListening(), we discard the entry from + /// this map. + typedef std::map<std::string, boost::signals2::connection> ConnectionMap; + ConnectionMap mConnections; + typedef LLDependencies<std::string, float> DependencyMap; + /// Dependencies between listeners. For each listener, track the float + /// used to establish its place in mSignal's order. This caches all the + /// listeners that have ever registered; stopListening() does not discard + /// the entry from this map. This is to avoid a new dependency sort if the + /// same listener with the same dependencies keeps hopping on and off this + /// LLEventPump. + DependencyMap mDeps; +}; + +/***************************************************************************** +* LLEventStream +*****************************************************************************/ +/** + * LLEventStream is a thin wrapper around LLStandardSignal. Posting an + * event immediately calls all registered listeners. + */ +class LL_COMMON_API LLEventStream: public LLEventPump +{ +public: + LLEventStream(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {} + virtual ~LLEventStream() {} + + /// Post an event to all listeners + virtual bool post(const LLSD& event); +}; + +/***************************************************************************** +* LLEventQueue +*****************************************************************************/ +/** + * LLEventQueue isa LLEventPump whose post() method defers calling registered + * listeners until flush() is called. + */ +class LL_COMMON_API LLEventQueue: public LLEventPump +{ +public: + LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {} + virtual ~LLEventQueue() {} + + /// Post an event to all listeners + virtual bool post(const LLSD& event); + +private: + /// flush queued events + virtual void flush(); + +private: + typedef std::deque<LLSD> EventQueue; + EventQueue mEventQueue; +}; + +/***************************************************************************** +* LLReqID +*****************************************************************************/ +/** + * This class helps the implementer of a given event API to honor the + * ["reqid"] convention. By this convention, each event API stamps into its + * response LLSD a ["reqid"] key whose value echoes the ["reqid"] value, if + * any, from the corresponding request. + * + * This supports an (atypical, but occasionally necessary) use case in which + * two or more asynchronous requests are multiplexed onto the same ["reply"] + * LLEventPump. Since the response events could arrive in arbitrary order, the + * caller must be able to demux them. It does so by matching the ["reqid"] + * value in each response with the ["reqid"] value in the corresponding + * request. + * + * It is the caller's responsibility to ensure distinct ["reqid"] values for + * that case. Though LLSD::UUID is guaranteed to work, it might be overkill: + * the "namespace" of unique ["reqid"] values is simply the set of requests + * specifying the same ["reply"] LLEventPump name. + * + * Making a given event API echo the request's ["reqid"] into the response is + * nearly trivial. This helper is mostly for mnemonic purposes, to serve as a + * place to put these comments. We hope that each time a coder implements a + * new event API based on some existing one, s/he will say, "Huh, what's an + * LLReqID?" and look up this material. + * + * The hardest part about the convention is deciding where to store the + * ["reqid"] value. Ironically, LLReqID can't help with that: you must store + * an LLReqID instance in whatever storage will persist until the reply is + * sent. For example, if the request ultimately ends up using a Responder + * subclass, storing an LLReqID instance in the Responder works. + * + * @note + * The @em implementer of an event API must honor the ["reqid"] convention. + * However, the @em caller of an event API need only use it if s/he is sharing + * the same ["reply"] LLEventPump for two or more asynchronous event API + * requests. + * + * In most cases, it's far easier for the caller to instantiate a local + * LLEventStream and pass its name to the event API in question. Then it's + * perfectly reasonable not to set a ["reqid"] key in the request, ignoring + * the @c isUndefined() ["reqid"] value in the response. + */ +class LL_COMMON_API LLReqID +{ +public: + /** + * If you have the request in hand at the time you instantiate the + * LLReqID, pass that request to extract its ["reqid"]. + */ + LLReqID(const LLSD& request): + mReqid(request["reqid"]) + {} + /// If you don't yet have the request, use setFrom() later. + LLReqID() {} + + /// Extract and store the ["reqid"] value from an incoming request. + void setFrom(const LLSD& request) + { + mReqid = request["reqid"]; + } + + /// Set ["reqid"] key into a pending response LLSD object. + void stamp(LLSD& response) const; + + /// Make a whole new response LLSD object with our ["reqid"]. + LLSD makeResponse() const + { + LLSD response; + stamp(response); + return response; + } + + /// Not really sure of a use case for this accessor... + LLSD getReqID() const { return mReqid; } + +private: + LLSD mReqid; +}; + +/***************************************************************************** +* Underpinnings +*****************************************************************************/ +/** + * We originally provided a suite of overloaded + * LLEventTrackable::listenTo(LLEventPump&, ...) methods that would call + * LLEventPump::listen(...) and then pass the returned LLBoundListener to + * LLEventTrackable::track(). This was workable but error-prone: the coder + * must remember to call listenTo() rather than the more straightforward + * listen() method. + * + * Now we publish only the single canonical listen() method, so there's a + * uniform mechanism. Having a single way to do this is good, in that there's + * no question in the coder's mind which of several alternatives to choose. + * + * To support automatic connection management, we use boost::visit_each + * (http://www.boost.org/doc/libs/1_37_0/doc/html/boost/visit_each.html) to + * inspect each argument of a boost::bind expression. (Although the visit_each + * mechanism was first introduced with the original Boost.Signals library, it + * was only later documented.) + * + * Cases: + * * At least one of the function's arguments is a boost::weak_ptr<T>. Pass + * the corresponding shared_ptr to slot_type::track(). Ideally that would be + * the object whose method we want to call, but in fact we do the same for + * any weak_ptr we might find among the bound arguments. If we're passing + * our bound method a weak_ptr to some object, wouldn't the destruction of + * that object invalidate the call? So we disconnect automatically when any + * such object is destroyed. This is the mechanism preferred by boost:: + * signals2. + * * One of the functions's arguments is a boost::shared_ptr<T>. This produces + * a compile error: the bound copy of the shared_ptr stored in the + * boost_bind object stored in the signal object would make the referenced + * T object immortal. We provide a weaken() function. Pass + * weaken(your_shared_ptr) instead. (We can inspect, but not modify, the + * boost::bind object. Otherwise we'd replace the shared_ptr with weak_ptr + * implicitly and just proceed.) + * * One of the function's arguments is a plain pointer/reference to an object + * derived from boost::enable_shared_from_this. We assume that this object + * is managed using boost::shared_ptr, so we implicitly extract a shared_ptr + * and track that. (UNDER CONSTRUCTION) + * * One of the function's arguments is derived from LLEventTrackable. Pass + * the LLBoundListener to its LLEventTrackable::track(). This is vulnerable + * to a couple different race conditions, as described in LLEventTrackable + * documentation. (NOTE: Now that LLEventTrackable is a typedef for + * boost::signals2::trackable, the Signals2 library handles this itself, so + * our visitor needs no special logic for this case.) + * * Any other argument type is irrelevant to automatic connection management. + */ + +namespace LLEventDetail +{ + template <typename F> + const F& unwrap(const F& f) { return f; } + + template <typename F> + const F& unwrap(const boost::reference_wrapper<F>& f) { return f.get(); } + + // Most of the following is lifted from the Boost.Signals use of + // visit_each. + template<bool Cond> struct truth {}; + + /** + * boost::visit_each() Visitor, used on a template argument <tt>const F& + * f</tt> as follows (see visit_and_connect()): + * @code + * LLEventListener listener(f); + * Visitor visitor(listener); // bind listener so it can track() shared_ptrs + * using boost::visit_each; // allow unqualified visit_each() call for ADL + * visit_each(visitor, unwrap(f)); + * @endcode + */ + class Visitor + { + public: + /** + * Visitor binds a reference to LLEventListener so we can track() any + * shared_ptrs we find in the argument list. + */ + Visitor(LLEventListener& listener): + mListener(listener) + { + } + + /** + * boost::visit_each() calls this method for each component of a + * boost::bind() expression. + */ + template <typename T> + void operator()(const T& t) const + { + decode(t, 0); + } + + private: + // decode() decides between a reference wrapper and anything else + // boost::ref() variant + template<typename T> + void decode(const boost::reference_wrapper<T>& t, int) const + { +// add_if_trackable(t.get_pointer()); + } + + // decode() anything else + template<typename T> + void decode(const T& t, long) const + { + typedef truth<(boost::is_pointer<T>::value)> is_a_pointer; + maybe_get_pointer(t, is_a_pointer()); + } + + // maybe_get_pointer() decides between a pointer and a non-pointer + // plain pointer variant + template<typename T> + void maybe_get_pointer(const T& t, truth<true>) const + { +// add_if_trackable(t); + } + + // shared_ptr variant + template<typename T> + void maybe_get_pointer(const boost::shared_ptr<T>& t, truth<false>) const + { + // If we have a shared_ptr to this object, it doesn't matter + // whether the object is derived from LLEventTrackable, so no + // further analysis of T is needed. +// mListener.track(t); + + // Make this case illegal. Passing a bound shared_ptr to + // slot_type::track() is useless, since the bound shared_ptr will + // keep the object alive anyway! Force the coder to cast to weak_ptr. + + // Trivial as it is, make the BOOST_STATIC_ASSERT() condition + // dependent on template param so the macro is only evaluated if + // this method is in fact instantiated, as described here: + // http://www.boost.org/doc/libs/1_34_1/doc/html/boost_staticassert.html + + // ATTENTION: Don't bind a shared_ptr<anything> using + // LLEventPump::listen(boost::bind()). Doing so captures a copy of + // the shared_ptr, making the referenced object effectively + // immortal. Use the weaken() function, e.g.: + // somepump.listen(boost::bind(...weaken(my_shared_ptr)...)); + // This lets us automatically disconnect when the referenced + // object is destroyed. + BOOST_STATIC_ASSERT(sizeof(T) == 0); + } + + // weak_ptr variant + template<typename T> + void maybe_get_pointer(const boost::weak_ptr<T>& t, truth<false>) const + { + // If we have a weak_ptr to this object, it doesn't matter + // whether the object is derived from LLEventTrackable, so no + // further analysis of T is needed. + mListener.track(t); +// std::cout << "Found weak_ptr<" << typeid(T).name() << ">!\n"; + } + +#if 0 + // reference to anything derived from boost::enable_shared_from_this + template <typename T> + inline void maybe_get_pointer(const boost::enable_shared_from_this<T>& ct, + truth<false>) const + { + // Use the slot_type::track(shared_ptr) mechanism. Cast away + // const-ness because (in our code base anyway) it's unusual + // to find shared_ptr<const T>. + boost::enable_shared_from_this<T>& + t(const_cast<boost::enable_shared_from_this<T>&>(ct)); + std::cout << "Capturing shared_from_this()" << std::endl; + boost::shared_ptr<T> sp(t.shared_from_this()); +/*==========================================================================*| + std::cout << "Capturing weak_ptr" << std::endl; + boost::weak_ptr<T> wp(sp); +|*==========================================================================*/ + std::cout << "Tracking shared__ptr" << std::endl; + mListener.track(sp); + } +#endif + + // non-pointer variant + template<typename T> + void maybe_get_pointer(const T& t, truth<false>) const + { + // Take the address of this object, because the object itself may be + // trackable +// add_if_trackable(boost::addressof(t)); + } + +/*==========================================================================*| + // add_if_trackable() adds LLEventTrackable objects to mTrackables + inline void add_if_trackable(const LLEventTrackable* t) const + { + if (t) + { + } + } + + // pointer to anything not an LLEventTrackable subclass + inline void add_if_trackable(const void*) const + { + } + + // pointer to free function + // The following construct uses the preprocessor to generate + // add_if_trackable() overloads accepting pointer-to-function taking + // 0, 1, ..., LLEVENTS_LISTENER_ARITY parameters of arbitrary type. +#define BOOST_PP_LOCAL_MACRO(n) \ + template <typename R \ + BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM_PARAMS(n, typename T)> \ + inline void \ + add_if_trackable(R (*)(BOOST_PP_ENUM_PARAMS(n, T))) const \ + { \ + } +#define BOOST_PP_LOCAL_LIMITS (0, LLEVENTS_LISTENER_ARITY) +#include BOOST_PP_LOCAL_ITERATE() +#undef BOOST_PP_LOCAL_MACRO +#undef BOOST_PP_LOCAL_LIMITS +|*==========================================================================*/ + + /// Bind a reference to the LLEventListener to call its track() method. + LLEventListener& mListener; + }; + + /** + * Utility template function to use Visitor appropriately + * + * @param raw_listener Callable to connect, typically a boost::bind() + * expression. This will be visited by Visitor using boost::visit_each(). + * @param connect_funct Callable that will connect() @a raw_listener to an + * LLStandardSignal, returning LLBoundListener. + */ + template <typename LISTENER> + LLBoundListener visit_and_connect(const LISTENER& raw_listener, + const ConnectFunc& connect_func) + { + // Capture the listener + LLEventListener listener(raw_listener); + // Define our Visitor, binding the listener so we can call + // listener.track() if we discover any shared_ptr<Foo>. + LLEventDetail::Visitor visitor(listener); + // Allow unqualified visit_each() call for ADL + using boost::visit_each; + // Visit each component of a boost::bind() expression. Pass + // 'raw_listener', our template argument, rather than 'listener' from + // which type details have been erased. unwrap() comes from + // Boost.Signals, in case we were passed a boost::ref(). + visit_each(visitor, LLEventDetail::unwrap(raw_listener)); + // Make the connection using passed function. At present, wrapping + // this functionality into this function is a bit silly: we don't + // really need a visit_and_connect() function any more, just a visit() + // function. The definition of this function dates from when, after + // visit_each(), after establishing the connection, we had to + // postprocess the new connection with the visitor object. That's no + // longer necessary. + return connect_func(listener); + } +} // namespace LLEventDetail + +// Somewhat to my surprise, passing boost::bind(...boost::weak_ptr<T>...) to +// listen() fails in Boost code trying to instantiate LLEventListener (i.e. +// LLStandardSignal::slot_type) because the boost::get_pointer() utility function isn't +// specialized for boost::weak_ptr. This remedies that omission. +namespace boost +{ + template <typename T> + T* get_pointer(const weak_ptr<T>& ptr) { return shared_ptr<T>(ptr).get(); } +} + +/// Since we forbid use of listen(boost::bind(...shared_ptr<T>...)), provide an +/// easy way to cast to the corresponding weak_ptr. +template <typename T> +boost::weak_ptr<T> weaken(const boost::shared_ptr<T>& ptr) +{ + return boost::weak_ptr<T>(ptr); +} + +#endif /* ! defined(LL_LLEVENTS_H) */ diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 905d736d62..45b84ea3ea 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -1,317 +1,317 @@ -/**
- * @file llfasttimer.h
- * @brief Declaration of a fast timer.
- *
- * $LicenseInfo:firstyear=2004&license=viewergpl$
- *
- * Copyright (c) 2004-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_FASTTIMER_H
-#define LL_FASTTIMER_H
-
-#include "llinstancetracker.h"
-
-#define FAST_TIMER_ON 1
-
-#if LL_WINDOWS
-
-// shift off lower 8 bits for lower resolution but longer term timing
-// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
-inline U32 get_cpu_clock_count_32()
-{
- U32 ret_val;
- __asm
- {
- _emit 0x0f
- _emit 0x31
- shr eax,8
- shl edx,24
- or eax, edx
- mov dword ptr [ret_val], eax
- }
- return ret_val;
-}
-
-// return full timer value, still shifted by 8 bits
-inline U64 get_cpu_clock_count_64()
-{
- U64 ret_val;
- __asm
- {
- _emit 0x0f
- _emit 0x31
- mov eax,eax
- mov edx,edx
- mov dword ptr [ret_val+4], edx
- mov dword ptr [ret_val], eax
- }
- return ret_val >> 8;
-}
-
-#endif // LL_WINDOWS
-
-#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
-inline U32 get_cpu_clock_count_32()
-{
- U64 x;
- __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
- return (U32)x >> 8;
-}
-
-inline U32 get_cpu_clock_count_64()
-{
- U64 x;
- __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
- return x >> 8;
-}
-#endif
-
-#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__))
-//
-// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock
-//
-// Just use gettimeofday implementation for now
-
-inline U32 get_cpu_clock_count_32()
-{
- return (U32)get_clock_count();
-}
-
-inline U32 get_cpu_clock_count_64()
-{
- return get_clock_count();
-}
-#endif
-
-class LLMutex;
-
-#include <queue>
-#include "llsd.h"
-
-
-class LL_COMMON_API LLFastTimer
-{
-public:
- // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
- class LL_COMMON_API NamedTimer
- : public LLInstanceTracker<NamedTimer>
- {
- friend class DeclareTimer;
- public:
- ~NamedTimer();
-
- enum { HISTORY_NUM = 60 };
-
- const std::string& getName() const { return mName; }
- NamedTimer* getParent() const { return mParent; }
- void setParent(NamedTimer* parent);
- S32 getDepth();
- std::string getToolTip(S32 history_index = -1);
-
- typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
- child_const_iter beginChildren();
- child_const_iter endChildren();
- std::vector<NamedTimer*>& getChildren();
-
- void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
- bool getCollapsed() const { return mCollapsed; }
-
- U32 getCountAverage() const { return mCountAverage; }
- U32 getCallAverage() const { return mCallAverage; }
-
- U32 getHistoricalCount(S32 history_index = 0) const;
- U32 getHistoricalCalls(S32 history_index = 0) const;
-
- static NamedTimer& getRootNamedTimer();
-
- struct FrameState
- {
- FrameState(NamedTimer* timerp);
-
- U32 mSelfTimeCounter;
- U32 mCalls;
- FrameState* mParent; // info for caller timer
- FrameState* mLastCaller; // used to bootstrap tree construction
- NamedTimer* mTimer;
- U16 mActiveCount; // number of timers with this ID active on stack
- bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
- };
-
- S32 getFrameStateIndex() const { return mFrameStateIndex; }
-
- FrameState& getFrameState() const;
-
-
- private:
- friend class LLFastTimer;
- friend class NamedTimerFactory;
-
- //
- // methods
- //
- NamedTimer(const std::string& name);
- // recursive call to gather total time from children
- static void accumulateTimings();
-
- // updates cumulative times and hierarchy,
- // can be called multiple times in a frame, at any point
- static void processTimes();
-
- static void buildHierarchy();
- static void resetFrame();
- static void reset();
-
-
- //
- // members
- //
- S32 mFrameStateIndex;
-
- std::string mName;
-
- U32 mTotalTimeCounter;
-
- U32 mCountAverage;
- U32 mCallAverage;
-
- U32* mCountHistory;
- U32* mCallHistory;
-
- // tree structure
- NamedTimer* mParent; // NamedTimer of caller(parent)
- std::vector<NamedTimer*> mChildren;
- bool mCollapsed; // don't show children
- bool mNeedsSorting; // sort children whenever child added
-
- };
-
- // used to statically declare a new named timer
- class LL_COMMON_API DeclareTimer
- : public LLInstanceTracker<DeclareTimer>
- {
- public:
- DeclareTimer(const std::string& name, bool open);
- DeclareTimer(const std::string& name);
-
- static void updateCachedPointers();
-
- // convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer)
- operator NamedTimer::FrameState&() { return *mFrameState; }
- private:
- NamedTimer& mTimer;
- NamedTimer::FrameState* mFrameState;
- };
-
-
-public:
- static LLMutex* sLogLock;
- static std::queue<LLSD> sLogQueue;
- static BOOL sLog;
- static BOOL sMetricLog;
-
- typedef std::vector<NamedTimer::FrameState> info_list_t;
- static info_list_t& getFrameStateList();
-
- enum RootTimerMarker { ROOT };
- LLFastTimer(RootTimerMarker);
-
- LLFastTimer(NamedTimer::FrameState& timer)
- : mFrameState(&timer)
- {
-#if FAST_TIMER_ON
- NamedTimer::FrameState* frame_state = &timer;
- U32 cur_time = get_cpu_clock_count_32();
- mStartSelfTime = cur_time;
- mStartTotalTime = cur_time;
-
- frame_state->mActiveCount++;
- frame_state->mCalls++;
- // keep current parent as long as it is active when we are
- frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
-
- mLastTimer = sCurTimer;
- sCurTimer = this;
-#endif
- }
-
- ~LLFastTimer()
- {
-#if FAST_TIMER_ON
- NamedTimer::FrameState* frame_state = mFrameState;
- U32 cur_time = get_cpu_clock_count_32();
- frame_state->mSelfTimeCounter += cur_time - mStartSelfTime;
-
- frame_state->mActiveCount--;
- LLFastTimer* last_timer = mLastTimer;
- sCurTimer = last_timer;
-
- // store last caller to bootstrap tree creation
- frame_state->mLastCaller = last_timer->mFrameState;
-
- // we are only tracking self time, so subtract our total time delta from parents
- U32 total_time = cur_time - mStartTotalTime;
- last_timer->mStartSelfTime += total_time;
-#endif
- }
-
-
- // call this once a frame to reset timers
- static void nextFrame();
-
- // dumps current cumulative frame stats to log
- // call nextFrame() to reset timers
- static void dumpCurTimes();
-
- // call this to reset timer hierarchy, averages, etc.
- static void reset();
-
- static U64 countsPerSecond();
- static S32 getLastFrameIndex() { return sLastFrameIndex; }
- static S32 getCurFrameIndex() { return sCurFrameIndex; }
-
- static void writeLog(std::ostream& os);
- static const NamedTimer* getTimerByName(const std::string& name);
-
-public:
- static bool sPauseHistory;
- static bool sResetHistory;
-
-private:
- typedef std::vector<LLFastTimer*> timer_stack_t;
- static LLFastTimer* sCurTimer;
- static S32 sCurFrameIndex;
- static S32 sLastFrameIndex;
- static U64 sLastFrameTime;
- static info_list_t* sTimerInfos;
-
- U32 mStartSelfTime; // start time + time of all child timers
- U32 mStartTotalTime; // start time + time of all child timers
- NamedTimer::FrameState* mFrameState;
- LLFastTimer* mLastTimer;
-};
-
-#endif // LL_LLFASTTIMER_H
+/** + * @file llfasttimer.h + * @brief Declaration of a fast timer. + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_FASTTIMER_H +#define LL_FASTTIMER_H + +#include "llinstancetracker.h" + +#define FAST_TIMER_ON 1 + +#if LL_WINDOWS + +// shift off lower 8 bits for lower resolution but longer term timing +// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing +inline U32 get_cpu_clock_count_32() +{ + U32 ret_val; + __asm + { + _emit 0x0f + _emit 0x31 + shr eax,8 + shl edx,24 + or eax, edx + mov dword ptr [ret_val], eax + } + return ret_val; +} + +// return full timer value, still shifted by 8 bits +inline U64 get_cpu_clock_count_64() +{ + U64 ret_val; + __asm + { + _emit 0x0f + _emit 0x31 + mov eax,eax + mov edx,edx + mov dword ptr [ret_val+4], edx + mov dword ptr [ret_val], eax + } + return ret_val >> 8; +} + +#endif // LL_WINDOWS + +#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) +inline U32 get_cpu_clock_count_32() +{ + U64 x; + __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); + return (U32)x >> 8; +} + +inline U32 get_cpu_clock_count_64() +{ + U64 x; + __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); + return x >> 8; +} +#endif + +#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__)) +// +// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock +// +// Just use gettimeofday implementation for now + +inline U32 get_cpu_clock_count_32() +{ + return (U32)get_clock_count(); +} + +inline U32 get_cpu_clock_count_64() +{ + return get_clock_count(); +} +#endif + +class LLMutex; + +#include <queue> +#include "llsd.h" + + +class LL_COMMON_API LLFastTimer +{ +public: + // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances + class LL_COMMON_API NamedTimer + : public LLInstanceTracker<NamedTimer> + { + friend class DeclareTimer; + public: + ~NamedTimer(); + + enum { HISTORY_NUM = 60 }; + + const std::string& getName() const { return mName; } + NamedTimer* getParent() const { return mParent; } + void setParent(NamedTimer* parent); + S32 getDepth(); + std::string getToolTip(S32 history_index = -1); + + typedef std::vector<NamedTimer*>::const_iterator child_const_iter; + child_const_iter beginChildren(); + child_const_iter endChildren(); + std::vector<NamedTimer*>& getChildren(); + + void setCollapsed(bool collapsed) { mCollapsed = collapsed; } + bool getCollapsed() const { return mCollapsed; } + + U32 getCountAverage() const { return mCountAverage; } + U32 getCallAverage() const { return mCallAverage; } + + U32 getHistoricalCount(S32 history_index = 0) const; + U32 getHistoricalCalls(S32 history_index = 0) const; + + static NamedTimer& getRootNamedTimer(); + + struct FrameState + { + FrameState(NamedTimer* timerp); + + U32 mSelfTimeCounter; + U32 mCalls; + FrameState* mParent; // info for caller timer + FrameState* mLastCaller; // used to bootstrap tree construction + NamedTimer* mTimer; + U16 mActiveCount; // number of timers with this ID active on stack + bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame + }; + + S32 getFrameStateIndex() const { return mFrameStateIndex; } + + FrameState& getFrameState() const; + + + private: + friend class LLFastTimer; + friend class NamedTimerFactory; + + // + // methods + // + NamedTimer(const std::string& name); + // recursive call to gather total time from children + static void accumulateTimings(); + + // updates cumulative times and hierarchy, + // can be called multiple times in a frame, at any point + static void processTimes(); + + static void buildHierarchy(); + static void resetFrame(); + static void reset(); + + + // + // members + // + S32 mFrameStateIndex; + + std::string mName; + + U32 mTotalTimeCounter; + + U32 mCountAverage; + U32 mCallAverage; + + U32* mCountHistory; + U32* mCallHistory; + + // tree structure + NamedTimer* mParent; // NamedTimer of caller(parent) + std::vector<NamedTimer*> mChildren; + bool mCollapsed; // don't show children + bool mNeedsSorting; // sort children whenever child added + + }; + + // used to statically declare a new named timer + class LL_COMMON_API DeclareTimer + : public LLInstanceTracker<DeclareTimer> + { + public: + DeclareTimer(const std::string& name, bool open); + DeclareTimer(const std::string& name); + + static void updateCachedPointers(); + + // convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer) + operator NamedTimer::FrameState&() { return *mFrameState; } + private: + NamedTimer& mTimer; + NamedTimer::FrameState* mFrameState; + }; + + +public: + static LLMutex* sLogLock; + static std::queue<LLSD> sLogQueue; + static BOOL sLog; + static BOOL sMetricLog; + + typedef std::vector<NamedTimer::FrameState> info_list_t; + static info_list_t& getFrameStateList(); + + enum RootTimerMarker { ROOT }; + LLFastTimer(RootTimerMarker); + + LLFastTimer(NamedTimer::FrameState& timer) + : mFrameState(&timer) + { +#if FAST_TIMER_ON + NamedTimer::FrameState* frame_state = &timer; + U32 cur_time = get_cpu_clock_count_32(); + mStartSelfTime = cur_time; + mStartTotalTime = cur_time; + + frame_state->mActiveCount++; + frame_state->mCalls++; + // keep current parent as long as it is active when we are + frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); + + mLastTimer = sCurTimer; + sCurTimer = this; +#endif + } + + ~LLFastTimer() + { +#if FAST_TIMER_ON + NamedTimer::FrameState* frame_state = mFrameState; + U32 cur_time = get_cpu_clock_count_32(); + frame_state->mSelfTimeCounter += cur_time - mStartSelfTime; + + frame_state->mActiveCount--; + LLFastTimer* last_timer = mLastTimer; + sCurTimer = last_timer; + + // store last caller to bootstrap tree creation + frame_state->mLastCaller = last_timer->mFrameState; + + // we are only tracking self time, so subtract our total time delta from parents + U32 total_time = cur_time - mStartTotalTime; + last_timer->mStartSelfTime += total_time; +#endif + } + + + // call this once a frame to reset timers + static void nextFrame(); + + // dumps current cumulative frame stats to log + // call nextFrame() to reset timers + static void dumpCurTimes(); + + // call this to reset timer hierarchy, averages, etc. + static void reset(); + + static U64 countsPerSecond(); + static S32 getLastFrameIndex() { return sLastFrameIndex; } + static S32 getCurFrameIndex() { return sCurFrameIndex; } + + static void writeLog(std::ostream& os); + static const NamedTimer* getTimerByName(const std::string& name); + +public: + static bool sPauseHistory; + static bool sResetHistory; + +private: + typedef std::vector<LLFastTimer*> timer_stack_t; + static LLFastTimer* sCurTimer; + static S32 sCurFrameIndex; + static S32 sLastFrameIndex; + static U64 sLastFrameTime; + static info_list_t* sTimerInfos; + + U32 mStartSelfTime; // start time + time of all child timers + U32 mStartTotalTime; // start time + time of all child timers + NamedTimer::FrameState* mFrameState; + LLFastTimer* mLastTimer; +}; + +#endif // LL_LLFASTTIMER_H diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp new file mode 100644 index 0000000000..9107b11597 --- /dev/null +++ b/indra/llcommon/llfoldertype.cpp @@ -0,0 +1,165 @@ +/** + * @file llfoldertype.cpp + * @brief Implementatino of LLFolderType functionality. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfoldertype.h" +#include "lldictionary.h" +#include "llmemory.h" +#include "llsingleton.h" + +///---------------------------------------------------------------------------- +/// Class LLFolderType +///---------------------------------------------------------------------------- +struct FolderEntry : public LLDictionaryEntry +{ + FolderEntry(const std::string &type_name, // 8 character limit! + bool is_protected) // can the viewer change categories of this type? + : + LLDictionaryEntry(type_name), + mIsProtected(is_protected) + { + llassert(type_name.length() <= 8); + } + + const bool mIsProtected; +}; + +class LLFolderDictionary : public LLSingleton<LLFolderDictionary>, + public LLDictionary<LLFolderType::EType, FolderEntry> +{ +public: + LLFolderDictionary(); +}; + +LLFolderDictionary::LLFolderDictionary() +{ + // TYPE NAME PROTECTED + // |-----------|---------| + addEntry(LLFolderType::FT_TEXTURE, new FolderEntry("texture", TRUE)); + addEntry(LLFolderType::FT_SOUND, new FolderEntry("sound", TRUE)); + addEntry(LLFolderType::FT_CALLINGCARD, new FolderEntry("callcard", TRUE)); + addEntry(LLFolderType::FT_LANDMARK, new FolderEntry("landmark", TRUE)); + addEntry(LLFolderType::FT_CLOTHING, new FolderEntry("clothing", TRUE)); + addEntry(LLFolderType::FT_OBJECT, new FolderEntry("object", TRUE)); + addEntry(LLFolderType::FT_NOTECARD, new FolderEntry("notecard", TRUE)); + addEntry(LLFolderType::FT_CATEGORY, new FolderEntry("category", TRUE)); + addEntry(LLFolderType::FT_ROOT_CATEGORY, new FolderEntry("root", TRUE)); + addEntry(LLFolderType::FT_LSL_TEXT, new FolderEntry("lsltext", TRUE)); + addEntry(LLFolderType::FT_BODYPART, new FolderEntry("bodypart", TRUE)); + addEntry(LLFolderType::FT_TRASH, new FolderEntry("trash", TRUE)); + addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new FolderEntry("snapshot", TRUE)); + addEntry(LLFolderType::FT_LOST_AND_FOUND, new FolderEntry("lstndfnd", TRUE)); + addEntry(LLFolderType::FT_ANIMATION, new FolderEntry("animatn", TRUE)); + addEntry(LLFolderType::FT_GESTURE, new FolderEntry("gesture", TRUE)); + addEntry(LLFolderType::FT_FAVORITE, new FolderEntry("favorite", TRUE)); + + for (S32 ensemble_num = S32(LLFolderType::FT_ENSEMBLE_START); ensemble_num <= S32(LLFolderType::FT_ENSEMBLE_END); ensemble_num++) + { + addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", FALSE)); + } + + addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", TRUE)); + addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", FALSE)); + addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", TRUE)); + addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE)); + + addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE)); +}; + +// static +LLFolderType::EType LLFolderType::lookup(const std::string& name) +{ + return LLFolderDictionary::getInstance()->lookup(name); +} + +// static +const std::string &LLFolderType::lookup(LLFolderType::EType folder_type) +{ + const FolderEntry *entry = LLFolderDictionary::getInstance()->lookup(folder_type); + if (entry) + { + return entry->mName; + } + else + { + return badLookup(); + } +} + +// static +// Only ensembles and plain folders aren't protected. "Protected" means +// you can't change certain properties such as their type. +bool LLFolderType::lookupIsProtectedType(EType folder_type) +{ + const LLFolderDictionary *dict = LLFolderDictionary::getInstance(); + const FolderEntry *entry = dict->lookup(folder_type); + if (entry) + { + return entry->mIsProtected; + } + return true; +} + +// static +bool LLFolderType::lookupIsEnsembleType(EType folder_type) +{ + return (folder_type >= FT_ENSEMBLE_START && + folder_type <= FT_ENSEMBLE_END); +} + +// static +LLAssetType::EType LLFolderType::folderTypeToAssetType(LLFolderType::EType folder_type) +{ + if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::badLookup()) + { + llwarns << "Converting to unknown asset type " << folder_type << llendl; + } + return (LLAssetType::EType)folder_type; +} + +// static +LLFolderType::EType LLFolderType::assetTypeToFolderType(LLAssetType::EType asset_type) +{ + if (LLFolderType::lookup(LLFolderType::EType(asset_type)) == LLFolderType::badLookup()) + { + llwarns << "Converting to unknown folder type " << asset_type << llendl; + } + return (LLFolderType::EType)asset_type; +} + +// static +const std::string &LLFolderType::badLookup() +{ + static const std::string sBadLookup = "llfoldertype_bad_lookup"; + return sBadLookup; +} diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h new file mode 100644 index 0000000000..5374ffd829 --- /dev/null +++ b/indra/llcommon/llfoldertype.h @@ -0,0 +1,123 @@ +/** + * @file llfoldertype.h + * @brief Declaration of LLFolderType. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFOLDERTYPE_H +#define LL_LLFOLDERTYPE_H + +#include <string> +#include "llassettype.h" + +// This class handles folder types (similar to assettype, except for folders) +// and operations on those. +class LL_COMMON_API LLFolderType +{ +public: + // ! BACKWARDS COMPATIBILITY ! Folder type enums must match asset type enums. + enum EType + { + FT_TEXTURE = 0, + + FT_SOUND = 1, + + FT_CALLINGCARD = 2, + + FT_LANDMARK = 3, + + // FT_SCRIPT = 4, + + FT_CLOTHING = 5, + + FT_OBJECT = 6, + + FT_NOTECARD = 7, + + FT_CATEGORY = 8, + + FT_ROOT_CATEGORY = 9, + + FT_LSL_TEXT = 10, + + // FT_LSL_BYTECODE = 11, + // FT_TEXTURE_TGA = 12, + + FT_BODYPART = 13, + + FT_TRASH = 14, + + FT_SNAPSHOT_CATEGORY = 15, + + FT_LOST_AND_FOUND = 16, + + // FT_SOUND_WAV = 17, + // FT_IMAGE_TGA = 18, + // FT_IMAGE_JPEG = 19, + + FT_ANIMATION = 20, + + FT_GESTURE = 21, + + // FT_SIMSTATE = 22, + + FT_FAVORITE = 23, + + FT_ENSEMBLE_START = 26, + FT_ENSEMBLE_END = 45, + // This range is reserved for special clothing folder types. + + FT_CURRENT_OUTFIT = 46, + FT_OUTFIT = 47, + FT_MY_OUTFITS = 48, + + FT_INBOX = 49, + + FT_COUNT = 50, + + FT_NONE = -1 + }; + + static EType lookup(const std::string& type_name); + static const std::string& lookup(EType folder_type); + + static bool lookupIsProtectedType(EType folder_type); + static bool lookupIsEnsembleType(EType folder_type); + + static LLAssetType::EType folderTypeToAssetType(LLFolderType::EType folder_type); + static LLFolderType::EType assetTypeToFolderType(LLAssetType::EType asset_type); + + static const std::string& badLookup(); // error string when a lookup fails + +protected: + LLFolderType() {} + ~LLFolderType() {} +}; + +#endif // LL_LLFOLDERTYPE_H diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 09f19532b7..1c6f64dd8b 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -1,65 +1,65 @@ -/**
- * @file llmemory.h
- * @brief Memory allocation/deallocation header-stuff goes here.
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-#ifndef LLMEMORY_H
-#define LLMEMORY_H
-
-
-
-extern S32 gTotalDAlloc;
-extern S32 gTotalDAUse;
-extern S32 gDACount;
-
-extern void* ll_allocate (size_t size);
-extern void ll_release (void *p);
-
-class LL_COMMON_API LLMemory
-{
-public:
- static void initClass();
- static void cleanupClass();
- static void freeReserve();
- // Return the resident set size of the current process, in bytes.
- // Return value is zero if not known.
- static U64 getCurrentRSS();
-private:
- static char* reserveMem;
-};
-
-// LLRefCount moved to llrefcount.h
-
-// LLPointer moved to llpointer.h
-
-// LLSafeHandle moved to llsafehandle.h
-
-// LLSingleton moved to llsingleton.h
-
-#endif
+/** + * @file llmemory.h + * @brief Memory allocation/deallocation header-stuff goes here. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLMEMORY_H +#define LLMEMORY_H + + + +extern S32 gTotalDAlloc; +extern S32 gTotalDAUse; +extern S32 gDACount; + +extern void* ll_allocate (size_t size); +extern void ll_release (void *p); + +class LL_COMMON_API LLMemory +{ +public: + static void initClass(); + static void cleanupClass(); + static void freeReserve(); + // Return the resident set size of the current process, in bytes. + // Return value is zero if not known. + static U64 getCurrentRSS(); +private: + static char* reserveMem; +}; + +// LLRefCount moved to llrefcount.h + +// LLPointer moved to llpointer.h + +// LLSafeHandle moved to llsafehandle.h + +// LLSingleton moved to llsingleton.h + +#endif diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h index 5952a3a7c5..677fad3034 100644 --- a/indra/llcommon/llmemtype.h +++ b/indra/llcommon/llmemtype.h @@ -1,248 +1,248 @@ -/**
- * @file llmemtype.h
- * @brief Runtime memory usage debugging utilities.
- *
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- *
- * Copyright (c) 2005-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_MEMTYPE_H
-#define LL_MEMTYPE_H
-
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-
-#include "linden_common.h"
-//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-// WARNING: Never commit with MEM_TRACK_MEM == 1
-//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-#define MEM_TRACK_MEM (0 && LL_WINDOWS)
-
-#include <vector>
-
-#define MEM_TYPE_NEW(T)
-
-class LL_COMMON_API LLMemType
-{
-public:
-
- // class we'll initialize all instances of as
- // static members of MemType. Then use
- // to construct any new mem type.
- class LL_COMMON_API DeclareMemType
- {
- public:
- DeclareMemType(char const * st);
- ~DeclareMemType();
-
- S32 mID;
- char const * mName;
-
- // array so we can map an index ID to Name
- static std::vector<char const *> mNameList;
- };
-
- LLMemType(DeclareMemType& dt);
- ~LLMemType();
-
- static char const * getNameFromID(S32 id);
-
- static DeclareMemType MTYPE_INIT;
- static DeclareMemType MTYPE_STARTUP;
- static DeclareMemType MTYPE_MAIN;
- static DeclareMemType MTYPE_FRAME;
-
- static DeclareMemType MTYPE_GATHER_INPUT;
- static DeclareMemType MTYPE_JOY_KEY;
-
- static DeclareMemType MTYPE_IDLE;
- static DeclareMemType MTYPE_IDLE_PUMP;
- static DeclareMemType MTYPE_IDLE_NETWORK;
- static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS;
- static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION;
- static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE;
- static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY;
- static DeclareMemType MTYPE_IDLE_AUDIO;
-
- static DeclareMemType MTYPE_CACHE_PROCESS_PENDING;
- static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS;
- static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES;
-
- static DeclareMemType MTYPE_MESSAGE_CHECK_ALL;
- static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS;
-
- static DeclareMemType MTYPE_RENDER;
- static DeclareMemType MTYPE_SLEEP;
-
- static DeclareMemType MTYPE_NETWORK;
- static DeclareMemType MTYPE_PHYSICS;
- static DeclareMemType MTYPE_INTERESTLIST;
-
- static DeclareMemType MTYPE_IMAGEBASE;
- static DeclareMemType MTYPE_IMAGERAW;
- static DeclareMemType MTYPE_IMAGEFORMATTED;
-
- static DeclareMemType MTYPE_APPFMTIMAGE;
- static DeclareMemType MTYPE_APPRAWIMAGE;
- static DeclareMemType MTYPE_APPAUXRAWIMAGE;
-
- static DeclareMemType MTYPE_DRAWABLE;
-
- static DeclareMemType MTYPE_OBJECT;
- static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE;
- static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE;
-
- static DeclareMemType MTYPE_DISPLAY;
- static DeclareMemType MTYPE_DISPLAY_UPDATE;
- static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA;
- static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM;
- static DeclareMemType MTYPE_DISPLAY_SWAP;
- static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD;
- static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION;
- static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE;
- static DeclareMemType MTYPE_DISPLAY_STATE_SORT;
- static DeclareMemType MTYPE_DISPLAY_SKY;
- static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM;
- static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH;
- static DeclareMemType MTYPE_DISPLAY_RENDER_UI;
- static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS;
-
- static DeclareMemType MTYPE_VERTEX_DATA;
- static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR;
- static DeclareMemType MTYPE_VERTEX_DESTRUCTOR;
- static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES;
- static DeclareMemType MTYPE_VERTEX_CREATE_INDICES;
- static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER;
- static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES;
- static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS;
- static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES;
- static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER;
- static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER;
- static DeclareMemType MTYPE_VERTEX_MAP_BUFFER;
- static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES;
- static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES;
- static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER;
- static DeclareMemType MTYPE_VERTEX_SET_STRIDE;
- static DeclareMemType MTYPE_VERTEX_SET_BUFFER;
- static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER;
- static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS;
-
- static DeclareMemType MTYPE_SPACE_PARTITION;
-
- static DeclareMemType MTYPE_PIPELINE;
- static DeclareMemType MTYPE_PIPELINE_INIT;
- static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS;
- static DeclareMemType MTYPE_PIPELINE_RESTORE_GL;
- static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS;
- static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL;
- static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE;
- static DeclareMemType MTYPE_PIPELINE_ADD_POOL;
- static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE;
- static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT;
- static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS;
- static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE;
- static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM;
- static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE;
- static DeclareMemType MTYPE_PIPELINE_MARK_MOVED;
- static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT;
- static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS;
- static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED;
- static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD;
- static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL;
- static DeclareMemType MTYPE_PIPELINE_STATE_SORT;
- static DeclareMemType MTYPE_PIPELINE_POST_SORT;
-
- static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS;
- static DeclareMemType MTYPE_PIPELINE_RENDER_HL;
- static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM;
- static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED;
- static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF;
- static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW;
- static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT;
- static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS;
- static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP;
- static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS;
- static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR;
- static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM;
-
- static DeclareMemType MTYPE_UPKEEP_POOLS;
-
- static DeclareMemType MTYPE_AVATAR;
- static DeclareMemType MTYPE_AVATAR_MESH;
- static DeclareMemType MTYPE_PARTICLES;
- static DeclareMemType MTYPE_REGIONS;
-
- static DeclareMemType MTYPE_INVENTORY;
- static DeclareMemType MTYPE_INVENTORY_DRAW;
- static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS;
- static DeclareMemType MTYPE_INVENTORY_DO_FOLDER;
- static DeclareMemType MTYPE_INVENTORY_POST_BUILD;
- static DeclareMemType MTYPE_INVENTORY_FROM_XML;
- static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM;
- static DeclareMemType MTYPE_INVENTORY_VIEW_INIT;
- static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW;
- static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE;
-
- static DeclareMemType MTYPE_ANIMATION;
- static DeclareMemType MTYPE_VOLUME;
- static DeclareMemType MTYPE_PRIMITIVE;
-
- static DeclareMemType MTYPE_SCRIPT;
- static DeclareMemType MTYPE_SCRIPT_RUN;
- static DeclareMemType MTYPE_SCRIPT_BYTECODE;
-
- static DeclareMemType MTYPE_IO_PUMP;
- static DeclareMemType MTYPE_IO_TCP;
- static DeclareMemType MTYPE_IO_BUFFER;
- static DeclareMemType MTYPE_IO_HTTP_SERVER;
- static DeclareMemType MTYPE_IO_SD_SERVER;
- static DeclareMemType MTYPE_IO_SD_CLIENT;
- static DeclareMemType MTYPE_IO_URL_REQUEST;
-
- static DeclareMemType MTYPE_DIRECTX_INIT;
-
- static DeclareMemType MTYPE_TEMP1;
- static DeclareMemType MTYPE_TEMP2;
- static DeclareMemType MTYPE_TEMP3;
- static DeclareMemType MTYPE_TEMP4;
- static DeclareMemType MTYPE_TEMP5;
- static DeclareMemType MTYPE_TEMP6;
- static DeclareMemType MTYPE_TEMP7;
- static DeclareMemType MTYPE_TEMP8;
- static DeclareMemType MTYPE_TEMP9;
-
- static DeclareMemType MTYPE_OTHER; // Special; used by display code
-
- S32 mTypeIndex;
-};
-
-//----------------------------------------------------------------------------
-
-#endif
-
+/** + * @file llmemtype.h + * @brief Runtime memory usage debugging utilities. + * + * $LicenseInfo:firstyear=2005&license=viewergpl$ + * + * Copyright (c) 2005-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_MEMTYPE_H +#define LL_MEMTYPE_H + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- + +#include "linden_common.h" +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// WARNING: Never commit with MEM_TRACK_MEM == 1 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +#define MEM_TRACK_MEM (0 && LL_WINDOWS) + +#include <vector> + +#define MEM_TYPE_NEW(T) + +class LL_COMMON_API LLMemType +{ +public: + + // class we'll initialize all instances of as + // static members of MemType. Then use + // to construct any new mem type. + class LL_COMMON_API DeclareMemType + { + public: + DeclareMemType(char const * st); + ~DeclareMemType(); + + S32 mID; + char const * mName; + + // array so we can map an index ID to Name + static std::vector<char const *> mNameList; + }; + + LLMemType(DeclareMemType& dt); + ~LLMemType(); + + static char const * getNameFromID(S32 id); + + static DeclareMemType MTYPE_INIT; + static DeclareMemType MTYPE_STARTUP; + static DeclareMemType MTYPE_MAIN; + static DeclareMemType MTYPE_FRAME; + + static DeclareMemType MTYPE_GATHER_INPUT; + static DeclareMemType MTYPE_JOY_KEY; + + static DeclareMemType MTYPE_IDLE; + static DeclareMemType MTYPE_IDLE_PUMP; + static DeclareMemType MTYPE_IDLE_NETWORK; + static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS; + static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION; + static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE; + static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY; + static DeclareMemType MTYPE_IDLE_AUDIO; + + static DeclareMemType MTYPE_CACHE_PROCESS_PENDING; + static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS; + static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES; + + static DeclareMemType MTYPE_MESSAGE_CHECK_ALL; + static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS; + + static DeclareMemType MTYPE_RENDER; + static DeclareMemType MTYPE_SLEEP; + + static DeclareMemType MTYPE_NETWORK; + static DeclareMemType MTYPE_PHYSICS; + static DeclareMemType MTYPE_INTERESTLIST; + + static DeclareMemType MTYPE_IMAGEBASE; + static DeclareMemType MTYPE_IMAGERAW; + static DeclareMemType MTYPE_IMAGEFORMATTED; + + static DeclareMemType MTYPE_APPFMTIMAGE; + static DeclareMemType MTYPE_APPRAWIMAGE; + static DeclareMemType MTYPE_APPAUXRAWIMAGE; + + static DeclareMemType MTYPE_DRAWABLE; + + static DeclareMemType MTYPE_OBJECT; + static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE; + static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE; + + static DeclareMemType MTYPE_DISPLAY; + static DeclareMemType MTYPE_DISPLAY_UPDATE; + static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA; + static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM; + static DeclareMemType MTYPE_DISPLAY_SWAP; + static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD; + static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION; + static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE; + static DeclareMemType MTYPE_DISPLAY_STATE_SORT; + static DeclareMemType MTYPE_DISPLAY_SKY; + static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM; + static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH; + static DeclareMemType MTYPE_DISPLAY_RENDER_UI; + static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS; + + static DeclareMemType MTYPE_VERTEX_DATA; + static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR; + static DeclareMemType MTYPE_VERTEX_DESTRUCTOR; + static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES; + static DeclareMemType MTYPE_VERTEX_CREATE_INDICES; + static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER; + static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES; + static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS; + static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES; + static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER; + static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER; + static DeclareMemType MTYPE_VERTEX_MAP_BUFFER; + static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES; + static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES; + static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER; + static DeclareMemType MTYPE_VERTEX_SET_STRIDE; + static DeclareMemType MTYPE_VERTEX_SET_BUFFER; + static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER; + static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS; + + static DeclareMemType MTYPE_SPACE_PARTITION; + + static DeclareMemType MTYPE_PIPELINE; + static DeclareMemType MTYPE_PIPELINE_INIT; + static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS; + static DeclareMemType MTYPE_PIPELINE_RESTORE_GL; + static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS; + static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL; + static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE; + static DeclareMemType MTYPE_PIPELINE_ADD_POOL; + static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE; + static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT; + static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS; + static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE; + static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM; + static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE; + static DeclareMemType MTYPE_PIPELINE_MARK_MOVED; + static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT; + static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS; + static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED; + static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD; + static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL; + static DeclareMemType MTYPE_PIPELINE_STATE_SORT; + static DeclareMemType MTYPE_PIPELINE_POST_SORT; + + static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS; + static DeclareMemType MTYPE_PIPELINE_RENDER_HL; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW; + static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT; + static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS; + static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP; + static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS; + static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR; + static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM; + + static DeclareMemType MTYPE_UPKEEP_POOLS; + + static DeclareMemType MTYPE_AVATAR; + static DeclareMemType MTYPE_AVATAR_MESH; + static DeclareMemType MTYPE_PARTICLES; + static DeclareMemType MTYPE_REGIONS; + + static DeclareMemType MTYPE_INVENTORY; + static DeclareMemType MTYPE_INVENTORY_DRAW; + static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS; + static DeclareMemType MTYPE_INVENTORY_DO_FOLDER; + static DeclareMemType MTYPE_INVENTORY_POST_BUILD; + static DeclareMemType MTYPE_INVENTORY_FROM_XML; + static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM; + static DeclareMemType MTYPE_INVENTORY_VIEW_INIT; + static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW; + static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE; + + static DeclareMemType MTYPE_ANIMATION; + static DeclareMemType MTYPE_VOLUME; + static DeclareMemType MTYPE_PRIMITIVE; + + static DeclareMemType MTYPE_SCRIPT; + static DeclareMemType MTYPE_SCRIPT_RUN; + static DeclareMemType MTYPE_SCRIPT_BYTECODE; + + static DeclareMemType MTYPE_IO_PUMP; + static DeclareMemType MTYPE_IO_TCP; + static DeclareMemType MTYPE_IO_BUFFER; + static DeclareMemType MTYPE_IO_HTTP_SERVER; + static DeclareMemType MTYPE_IO_SD_SERVER; + static DeclareMemType MTYPE_IO_SD_CLIENT; + static DeclareMemType MTYPE_IO_URL_REQUEST; + + static DeclareMemType MTYPE_DIRECTX_INIT; + + static DeclareMemType MTYPE_TEMP1; + static DeclareMemType MTYPE_TEMP2; + static DeclareMemType MTYPE_TEMP3; + static DeclareMemType MTYPE_TEMP4; + static DeclareMemType MTYPE_TEMP5; + static DeclareMemType MTYPE_TEMP6; + static DeclareMemType MTYPE_TEMP7; + static DeclareMemType MTYPE_TEMP8; + static DeclareMemType MTYPE_TEMP9; + + static DeclareMemType MTYPE_OTHER; // Special; used by display code + + S32 mTypeIndex; +}; + +//---------------------------------------------------------------------------- + +#endif + diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 48baa50edb..48244480b1 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -1,168 +1,168 @@ -/**
- * @file llpreprocessor.h
- * @brief This file should be included in all Linden Lab files and
- * should only contain special preprocessor directives
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LLPREPROCESSOR_H
-#define LLPREPROCESSOR_H
-
-// Figure out endianness of platform
-#ifdef LL_LINUX
-#define __ENABLE_WSTRING
-#include <endian.h>
-#endif // LL_LINUX
-
-#if LL_SOLARIS
-# ifdef __sparc // Since we're talking Solaris 10 and up, only 64 bit is supported.
-# define LL_BIG_ENDIAN 1
-# define LL_SOLARIS_ALIGNED_CPU 1 // used to designate issues where SPARC alignment is addressed
-# define LL_SOLARIS_NON_MESA_GL 1 // The SPARC GL does not provide a MESA-based GL API
-# endif
-# include <sys/isa_defs.h> // ensure we know which end is up
-#endif // LL_SOLARIS
-
-#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(LL_SOLARIS) && defined(__i386)))
-#define LL_LITTLE_ENDIAN 1
-#else
-#define LL_BIG_ENDIAN 1
-#endif
-
-// Per-compiler switches
-#ifdef __GNUC__
-#define LL_FORCE_INLINE inline __attribute__((always_inline))
-#else
-#define LL_FORCE_INLINE __forceinline
-#endif
-
-// Figure out differences between compilers
-#if defined(__GNUC__)
- #define GCC_VERSION (__GNUC__ * 10000 \
- + __GNUC_MINOR__ * 100 \
- + __GNUC_PATCHLEVEL__)
- #ifndef LL_GNUC
- #define LL_GNUC 1
- #endif
-#elif defined(__MSVC_VER__) || defined(_MSC_VER)
- #ifndef LL_MSVC
- #define LL_MSVC 1
- #endif
- #if _MSC_VER < 1400
- #define LL_MSVC7 //Visual C++ 2003 or earlier
- #endif
-#endif
-
-// Deal with minor differences on Unixy OSes.
-#if LL_DARWIN || LL_LINUX
- // Different name, same functionality.
- #define stricmp strcasecmp
- #define strnicmp strncasecmp
-
- // Not sure why this is different, but...
- #ifndef MAX_PATH
- #define MAX_PATH PATH_MAX
- #endif // not MAX_PATH
-
-#endif
-
-
-// Static linking with apr on windows needs to be declared.
-#if LL_WINDOWS && !LL_COMMON_LINK_SHARED
-#ifndef APR_DECLARE_STATIC
-#define APR_DECLARE_STATIC // For APR on Windows
-#endif
-#ifndef APU_DECLARE_STATIC
-#define APU_DECLARE_STATIC // For APR util on Windows
-#endif
-#endif
-
-#if defined(LL_WINDOWS)
-#define BOOST_REGEX_NO_LIB 1
-#define CURL_STATICLIB 1
-#ifndef XML_STATIC
-#define XML_STATIC
-#endif
-#endif // LL_WINDOWS
-
-
-// Deal with VC6 problems
-#if LL_MSVC
-#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4.
-#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4.
-#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4.
-//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4.
-#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function
-#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden"
-#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
-#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden
-#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
-#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
-#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
-#pragma warning( disable : 4996 ) // warning: deprecated
-
-// level 4 warnings that we need to disable:
-#pragma warning (disable : 4100) // unreferenced formal parameter
-#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) )
-#pragma warning (disable : 4244) // possible loss of data on conversions
-#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
-#pragma warning (disable : 4512) // assignment operator could not be generated
-#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) )
-
-#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class
-#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class
-#endif // LL_MSVC
-
-#if LL_WINDOWS
-#define LL_DLLEXPORT __declspec(dllexport)
-#define LL_DLLIMPORT __declspec(dllimport)
-#elif LL_LINUX
-#define LL_DLLEXPORT __attribute__ ((visibility("default")))
-#define LL_DLLIMPORT
-#else
-#define LL_DLLEXPORT
-#define LL_DLLIMPORT
-#endif // LL_WINDOWS
-
-#if LL_COMMON_LINK_SHARED
-// CMake automagically defines llcommon_EXPORTS only when building llcommon
-// sources, and only when llcommon is a shared library (i.e. when
-// LL_COMMON_LINK_SHARED). We must still test LL_COMMON_LINK_SHARED because
-// otherwise we can't distinguish between (non-llcommon source) and (llcommon
-// not shared).
-# if defined(llcommon_EXPORTS)
-# define LL_COMMON_API LL_DLLEXPORT
-# else //llcommon_EXPORTS
-# define LL_COMMON_API LL_DLLIMPORT
-# endif //llcommon_EXPORTS
-#else // LL_COMMON_LINK_SHARED
-# define LL_COMMON_API
-#endif // LL_COMMON_LINK_SHARED
-
-#endif // not LL_LINDEN_PREPROCESSOR_H
+/** + * @file llpreprocessor.h + * @brief This file should be included in all Linden Lab files and + * should only contain special preprocessor directives + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLPREPROCESSOR_H +#define LLPREPROCESSOR_H + +// Figure out endianness of platform +#ifdef LL_LINUX +#define __ENABLE_WSTRING +#include <endian.h> +#endif // LL_LINUX + +#if LL_SOLARIS +# ifdef __sparc // Since we're talking Solaris 10 and up, only 64 bit is supported. +# define LL_BIG_ENDIAN 1 +# define LL_SOLARIS_ALIGNED_CPU 1 // used to designate issues where SPARC alignment is addressed +# define LL_SOLARIS_NON_MESA_GL 1 // The SPARC GL does not provide a MESA-based GL API +# endif +# include <sys/isa_defs.h> // ensure we know which end is up +#endif // LL_SOLARIS + +#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(LL_SOLARIS) && defined(__i386))) +#define LL_LITTLE_ENDIAN 1 +#else +#define LL_BIG_ENDIAN 1 +#endif + +// Per-compiler switches +#ifdef __GNUC__ +#define LL_FORCE_INLINE inline __attribute__((always_inline)) +#else +#define LL_FORCE_INLINE __forceinline +#endif + +// Figure out differences between compilers +#if defined(__GNUC__) + #define GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) + #ifndef LL_GNUC + #define LL_GNUC 1 + #endif +#elif defined(__MSVC_VER__) || defined(_MSC_VER) + #ifndef LL_MSVC + #define LL_MSVC 1 + #endif + #if _MSC_VER < 1400 + #define LL_MSVC7 //Visual C++ 2003 or earlier + #endif +#endif + +// Deal with minor differences on Unixy OSes. +#if LL_DARWIN || LL_LINUX + // Different name, same functionality. + #define stricmp strcasecmp + #define strnicmp strncasecmp + + // Not sure why this is different, but... + #ifndef MAX_PATH + #define MAX_PATH PATH_MAX + #endif // not MAX_PATH + +#endif + + +// Static linking with apr on windows needs to be declared. +#if LL_WINDOWS && !LL_COMMON_LINK_SHARED +#ifndef APR_DECLARE_STATIC +#define APR_DECLARE_STATIC // For APR on Windows +#endif +#ifndef APU_DECLARE_STATIC +#define APU_DECLARE_STATIC // For APR util on Windows +#endif +#endif + +#if defined(LL_WINDOWS) +#define BOOST_REGEX_NO_LIB 1 +#define CURL_STATICLIB 1 +#ifndef XML_STATIC +#define XML_STATIC +#endif +#endif // LL_WINDOWS + + +// Deal with VC6 problems +#if LL_MSVC +#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4. +#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4. +#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4. +//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4. +#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function +#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden" +#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual" +#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden +#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file +#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. +#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) +#pragma warning( disable : 4996 ) // warning: deprecated + +// level 4 warnings that we need to disable: +#pragma warning (disable : 4100) // unreferenced formal parameter +#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) ) +#pragma warning (disable : 4244) // possible loss of data on conversions +#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template +#pragma warning (disable : 4512) // assignment operator could not be generated +#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) ) + +#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class +#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class +#endif // LL_MSVC + +#if LL_WINDOWS +#define LL_DLLEXPORT __declspec(dllexport) +#define LL_DLLIMPORT __declspec(dllimport) +#elif LL_LINUX +#define LL_DLLEXPORT __attribute__ ((visibility("default"))) +#define LL_DLLIMPORT +#else +#define LL_DLLEXPORT +#define LL_DLLIMPORT +#endif // LL_WINDOWS + +#if LL_COMMON_LINK_SHARED +// CMake automagically defines llcommon_EXPORTS only when building llcommon +// sources, and only when llcommon is a shared library (i.e. when +// LL_COMMON_LINK_SHARED). We must still test LL_COMMON_LINK_SHARED because +// otherwise we can't distinguish between (non-llcommon source) and (llcommon +// not shared). +# if defined(llcommon_EXPORTS) +# define LL_COMMON_API LL_DLLEXPORT +# else //llcommon_EXPORTS +# define LL_COMMON_API LL_DLLIMPORT +# endif //llcommon_EXPORTS +#else // LL_COMMON_LINK_SHARED +# define LL_COMMON_API +#endif // LL_COMMON_LINK_SHARED + +#endif // not LL_LINDEN_PREPROCESSOR_H diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 3db5c36545..e7ad571a90 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -42,7 +42,8 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : LLThread(name), mThreaded(threaded), mIdleThread(TRUE), - mNextHandle(0) + mNextHandle(0), + mStarted(FALSE) { if (mThreaded) { @@ -53,6 +54,10 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : // MAIN THREAD LLQueuedThread::~LLQueuedThread() { + if (!mThreaded) + { + endThread(); + } shutdown(); // ~LLThread() will be called here } @@ -106,6 +111,14 @@ void LLQueuedThread::shutdown() // virtual S32 LLQueuedThread::update(U32 max_time_ms) { + if (!mStarted) + { + if (!mThreaded) + { + startThread(); + mStarted = TRUE; + } + } return updateQueue(max_time_ms); } @@ -452,26 +465,12 @@ S32 LLQueuedThread::processNextRequest() } } - S32 res; S32 pending = getPending(); - if (pending == 0) - { - if (isQuitting()) - { - res = -1; // exit thread - } - else - { - res = 0; - } - } - else - { - res = pending; - } - return res; + + return pending; } +// virtual bool LLQueuedThread::runCondition() { // mRunCondition must be locked here @@ -481,35 +480,53 @@ bool LLQueuedThread::runCondition() return true; } +// virtual void LLQueuedThread::run() { + // call checPause() immediately so we don't try to do anything before the class is fully constructed + checkPause(); + startThread(); + mStarted = TRUE; + while (1) { // this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state. checkPause(); - if(isQuitting()) + if (isQuitting()) + { + endThread(); break; - - //llinfos << "QUEUED THREAD RUNNING, queue size = " << mRequestQueue.size() << llendl; + } mIdleThread = FALSE; + + threadedUpdate(); int res = processNextRequest(); if (res == 0) { mIdleThread = TRUE; + ms_sleep(1); } - - if (res < 0) // finished working and want to exit - { - break; - } - //LLThread::yield(); // thread should yield after each request } + llinfos << "LLQueuedThread " << mName << " EXITING." << llendl; +} + +// virtual +void LLQueuedThread::startThread() +{ +} - llinfos << "QUEUED THREAD " << mName << " EXITING." << llendl; +// virtual +void LLQueuedThread::endThread() +{ +} + +// virtual +void LLQueuedThread::threadedUpdate() +{ } //============================================================================ diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index 8bfa5632a1..9a9dbb18cc 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -166,6 +166,9 @@ private: virtual bool runCondition(void); virtual void run(void); + virtual void startThread(void); + virtual void endThread(void); + virtual void threadedUpdate(void); protected: handle_t generateHandle(); @@ -200,6 +203,7 @@ public: protected: BOOL mThreaded; // if false, run on main thread and do updates during update() + BOOL mStarted; // required when mThreaded is false to call startThread() from update() LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle typedef std::set<QueuedRequest*, queued_request_less> request_queue_t; diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp index 3cb074257b..6558df70a4 100644 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp @@ -1,142 +1,142 @@ -/**
- * @file llstacktrace.cpp
- * @brief stack tracing functionality
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llstacktrace.h"
-
-#ifdef LL_WINDOWS
-
-#include <iostream>
-#include <sstream>
-
-#include "windows.h"
-#include "Dbghelp.h"
-
-typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
- IN ULONG frames_to_skip,
- IN ULONG frames_to_capture,
- OUT PVOID *backtrace,
- OUT PULONG backtrace_hash);
-
-static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
- (RtlCaptureStackBackTrace_Function*)
- GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
-
-bool ll_get_stack_trace(std::vector<std::string>& lines)
-{
- const S32 MAX_STACK_DEPTH = 32;
- const S32 STRING_NAME_LENGTH = 200;
- const S32 FRAME_SKIP = 2;
- static BOOL symbolsLoaded = false;
- static BOOL firstCall = true;
-
- HANDLE hProc = GetCurrentProcess();
-
- // load the symbols if they're not loaded
- if(!symbolsLoaded && firstCall)
- {
- symbolsLoaded = SymInitialize(hProc, NULL, true);
- firstCall = false;
- }
-
- // if loaded, get the call stack
- if(symbolsLoaded)
- {
- // create the frames to hold the addresses
- void* frames[MAX_STACK_DEPTH];
- memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
- S32 depth = 0;
-
- // get the addresses
- depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
-
- IMAGEHLP_LINE64 line;
- memset(&line, 0, sizeof(IMAGEHLP_LINE64));
- line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
-
- // create something to hold address info
- PIMAGEHLP_SYMBOL64 pSym;
- pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
- memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
- pSym->MaxNameLength = STRING_NAME_LENGTH;
- pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
-
- // get address info for each address frame
- // and store
- for(S32 i=0; i < depth; i++)
- {
- std::stringstream stack_line;
- BOOL ret;
-
- DWORD64 addr = (DWORD64)frames[i];
- ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
- if(ret)
- {
- stack_line << pSym->Name << " ";
- }
-
- DWORD dummy;
- ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
- if(ret)
- {
- std::string file_name = line.FileName;
- std::string::size_type index = file_name.rfind("\\");
- stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber;
- }
-
- lines.push_back(stack_line.str());
- }
-
- free(pSym);
-
- // TODO: figure out a way to cleanup symbol loading
- // Not hugely necessary, however.
- //SymCleanup(hProc);
- return true;
- }
- else
- {
- lines.push_back("Stack Trace Failed. PDB symbol info not loaded");
- }
-
- return false;
-}
-
-#else
-
-bool ll_get_stack_trace(std::vector<std::string>& lines)
-{
- return false;
-}
-
-#endif
-
+/** + * @file llstacktrace.cpp + * @brief stack tracing functionality + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llstacktrace.h" + +#ifdef LL_WINDOWS + +#include <iostream> +#include <sstream> + +#include "windows.h" +#include "Dbghelp.h" + +typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( + IN ULONG frames_to_skip, + IN ULONG frames_to_capture, + OUT PVOID *backtrace, + OUT PULONG backtrace_hash); + +static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn = + (RtlCaptureStackBackTrace_Function*) + GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace"); + +bool ll_get_stack_trace(std::vector<std::string>& lines) +{ + const S32 MAX_STACK_DEPTH = 32; + const S32 STRING_NAME_LENGTH = 200; + const S32 FRAME_SKIP = 2; + static BOOL symbolsLoaded = false; + static BOOL firstCall = true; + + HANDLE hProc = GetCurrentProcess(); + + // load the symbols if they're not loaded + if(!symbolsLoaded && firstCall) + { + symbolsLoaded = SymInitialize(hProc, NULL, true); + firstCall = false; + } + + // if loaded, get the call stack + if(symbolsLoaded) + { + // create the frames to hold the addresses + void* frames[MAX_STACK_DEPTH]; + memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH); + S32 depth = 0; + + // get the addresses + depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL); + + IMAGEHLP_LINE64 line; + memset(&line, 0, sizeof(IMAGEHLP_LINE64)); + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + // create something to hold address info + PIMAGEHLP_SYMBOL64 pSym; + pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + pSym->MaxNameLength = STRING_NAME_LENGTH; + pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + + // get address info for each address frame + // and store + for(S32 i=0; i < depth; i++) + { + std::stringstream stack_line; + BOOL ret; + + DWORD64 addr = (DWORD64)frames[i]; + ret = SymGetSymFromAddr64(hProc, addr, 0, pSym); + if(ret) + { + stack_line << pSym->Name << " "; + } + + DWORD dummy; + ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line); + if(ret) + { + std::string file_name = line.FileName; + std::string::size_type index = file_name.rfind("\\"); + stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; + } + + lines.push_back(stack_line.str()); + } + + free(pSym); + + // TODO: figure out a way to cleanup symbol loading + // Not hugely necessary, however. + //SymCleanup(hProc); + return true; + } + else + { + lines.push_back("Stack Trace Failed. PDB symbol info not loaded"); + } + + return false; +} + +#else + +bool ll_get_stack_trace(std::vector<std::string>& lines) +{ + return false; +} + +#endif + diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h index b84b1aa6ad..9f857f0fd3 100644 --- a/indra/llcommon/llstacktrace.h +++ b/indra/llcommon/llstacktrace.h @@ -1,44 +1,44 @@ -/**
- * @file llstacktrace.h
- * @brief stack trace functions
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-
-#ifndef LL_LLSTACKTRACE_H
-#define LL_LLSTACKTRACE_H
-
-#include "stdtypes.h"
-#include <vector>
-#include <string>
-
-LL_COMMON_API bool ll_get_stack_trace(std::vector<std::string>& lines);
-
-#endif
-
+/** + * @file llstacktrace.h + * @brief stack trace functions + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#ifndef LL_LLSTACKTRACE_H +#define LL_LLSTACKTRACE_H + +#include "stdtypes.h" +#include <vector> +#include <string> + +LL_COMMON_API bool ll_get_stack_trace(std::vector<std::string>& lines); + +#endif + diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index edbb007f61..31e70e0fe4 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -1,1300 +1,1300 @@ -/**
- * @file llstring.h
- * @brief String utility functions and std::string class.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSTRING_H
-#define LL_LLSTRING_H
-
-#include <string>
-#include <cstdio>
-#include <locale>
-#include <iomanip>
-#include "llsd.h"
-#include "llfasttimer.h"
-
-#if LL_LINUX || LL_SOLARIS
-#include <wctype.h>
-#include <wchar.h>
-#endif
-
-#include <string.h>
-
-#if LL_SOLARIS
-// stricmp and strnicmp do not exist on Solaris:
-#define stricmp strcasecmp
-#define strnicmp strncasecmp
-#endif
-
-const char LL_UNKNOWN_CHAR = '?';
-
-#if LL_DARWIN || LL_LINUX || LL_SOLARIS
-// Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already)
-#include <cstring>
-
-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)
- { return (__c == eof()) ? 0 : __c; }
- };
-};
-#endif
-
-class LL_COMMON_API LLStringOps
-{
-private:
- static long sPacificTimeOffset;
- static long sLocalTimeOffset;
- static bool sPacificDaylightTime;
- static std::map<std::string, std::string> datetimeToCodes;
-
-public:
- 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 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 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 isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
- static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
-
- 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 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);
-};
-
-/**
- * @brief Return a string constructed from in without crashing if the
- * pointer is NULL.
- */
-LL_COMMON_API std::string ll_safe_string(const char* in);
-LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen);
-
-
-// Allowing assignments from non-strings into format_map_t is apparently
-// *really* error-prone, so subclass std::string with just basic c'tors.
-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(); }
-
-private:
- std::string mString;
-};
-
-template <class T>
-class LLStringUtilBase
-{
-private:
- static std::string sLocale;
-
-public:
- typedef typename std::basic_string<T>::size_type size_type;
-
-public:
- /////////////////////////////////////////////////////////////////////////////////////////
- // Static Utility functions that operate on std::strings
-
- static std::basic_string<T> null;
-
- typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
- LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
- LL_COMMON_API static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
- LL_COMMON_API static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
- LL_COMMON_API static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
- LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
- LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
- LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions);
- static void setLocale (std::string inLocale) {sLocale = inLocale;};
- static std::string getLocale (void) {return sLocale;};
-
- static bool isValidIndex(const std::basic_string<T>& string, size_type i)
- {
- return !string.empty() && (0 <= i) && (i <= string.size());
- }
-
- static void trimHead(std::basic_string<T>& string);
- static void trimTail(std::basic_string<T>& string);
- static void trim(std::basic_string<T>& string) { trimHead(string); trimTail(string); }
- static void truncate(std::basic_string<T>& string, size_type count);
-
- static void toUpper(std::basic_string<T>& string);
- static void toLower(std::basic_string<T>& string);
-
- // True if this is the head of s.
- static BOOL isHead( const std::basic_string<T>& 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 std::basic_string<T>& string,
- const std::basic_string<T>& substr);
-
- /**
- * @brief Returns true if string ends in substr
- *
- * If etither string or substr are empty, this method returns false.
- */
- static bool endsWith(
- const std::basic_string<T>& string,
- const std::basic_string<T>& substr);
-
- static void addCRLF(std::basic_string<T>& string);
- static void removeCRLF(std::basic_string<T>& string);
-
- static void replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab );
- static void replaceNonstandardASCII( std::basic_string<T>& string, T replacement );
- static void replaceChar( std::basic_string<T>& string, T target, T replacement );
- static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement );
-
- static BOOL containsNonprintable(const std::basic_string<T>& string);
- static void stripNonprintable(std::basic_string<T>& string);
-
- /**
- * @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(std::basic_string<T>& string);
-
- // Conversion to other data types
- static BOOL convertToBOOL(const std::basic_string<T>& string, BOOL& value);
- static BOOL convertToU8(const std::basic_string<T>& string, U8& value);
- static BOOL convertToS8(const std::basic_string<T>& string, S8& value);
- static BOOL convertToS16(const std::basic_string<T>& string, S16& value);
- static BOOL convertToU16(const std::basic_string<T>& string, U16& value);
- static BOOL convertToU32(const std::basic_string<T>& string, U32& value);
- static BOOL convertToS32(const std::basic_string<T>& string, S32& value);
- static BOOL convertToF32(const std::basic_string<T>& string, F32& value);
- static BOOL convertToF64(const std::basic_string<T>& 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 std::basic_string<T>& lhs, const std::basic_string<T>& 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 std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
-
- // Case sensitive comparison with good handling of numbers. Does not use current locale.
- // a.k.a. strdictcmp()
- static S32 compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b);
-
- // Case *in*sensitive comparison with good handling of numbers. Does not use current locale.
- // a.k.a. strdictcmp()
- static S32 compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b);
-
- // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
- static BOOL precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& 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(std::basic_string<T>& dst, const std::basic_string<T>& 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 std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
-};
-
-template<class T> std::basic_string<T> LLStringUtilBase<T>::null;
-template<class T> std::string LLStringUtilBase<T>::sLocale;
-
-typedef LLStringUtilBase<char> LLStringUtil;
-typedef LLStringUtilBase<llwchar> LLWStringUtil;
-typedef std::basic_string<llwchar> LLWString;
-
-//@ Use this where we want to disallow input in the form of "foo"
-// This is used to catch places where english text is embedded in the code
-// instead of in a translatable XUI file.
-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) {}
-};
-
-struct LLDictionaryLess
-{
-public:
- bool operator()(const std::string& a, const std::string& b)
- {
- return (LLStringUtil::precedesDict(a, b) ? true : false);
- }
-};
-
-
-/**
- * Simple support functions
- */
-
-/**
- * @brief chop off the trailing characters in a string.
- *
- * This function works on bytes rather than glyphs, so this will
- * incorrectly truncate non-single byte strings.
- * Use utf8str_truncate() for utf8 strings
- * @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)
-{
- return std::string(in, 0, in.length() - count);
-}
-
-/**
- * @brief This translates a nybble stored as a hex value from 0-f back
- * to a nybble in the low order bits of the return byte.
- */
-LL_COMMON_API U8 hex_as_nybble(char hex);
-
-/**
- * @brief read the contents of a file into a string.
- *
- * Since this function has no concept of character encoding, most
- * anything you do with this method ill-advised. Please avoid.
- * @param str [out] The string which will have.
- * @param filename The full name of the file to read.
- * @return Returns true on success. If false, str is unmodified.
- */
-LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename);
-LL_COMMON_API bool iswindividual(llwchar elem);
-
-/**
- * Unicode support
- */
-
-// Make the incoming string a utf8 string. Replaces any unknown glyph
-// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
-// of the data may not be recovered.
-LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);
-
-//
-// We should never use UTF16 except when communicating with Win32!
-//
-typedef std::basic_string<U16> llutf16string;
-
-LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
-LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str);
-
-LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
-LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str);
-
-LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
-LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str );
-
-LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
-LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str);
-// Same function, better name. JC
-inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
-
-//
-LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
-
-LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
-LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
-
-LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
-LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
-
-// Length of this UTF32 string in bytes when transformed to UTF8
-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 std::string utf8str_tolower(const std::string& utf8str);
-
-// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
-LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
-
-// Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
-LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
-
-// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.)
-LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
-
-/**
- * @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.
- * @param utf8str A valid utf8 string to truncate.
- * @param max_len The maximum number of bytes in the return value.
- * @return Returns a valid utf8 string with byte count <= max_len.
- */
-LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
-
-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);
-
-/**
- * @brief Replace all occurences of target_char with replace_char
- *
- * @param utf8str A utf8 string to process.
- * @param target_char The wchar to be replaced
- * @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);
-
-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 utf8str_removeCRLF(const std::string& utf8str);
-
-
-#if LL_WINDOWS
-/* @name Windows string helpers
- */
-//@{
-
-/**
- * @brief Implementation the expected snprintf interface.
- *
- * If the size of the passed in buffer is not large enough to hold the string,
- * two bad things happen:
- * 1. resulting formatted string is NOT null terminated
- * 2. Depending on the platform, the return value could be a) the required
- * size of the buffer to copy the entire formatted string or b) -1.
- * On Windows with VS.Net 2003, it returns -1 e.g.
- *
- * safe_snprintf always adds a NULL terminator so that the caller does not
- * need to check for return value or need to add the NULL terminator.
- * It does not, however change the return value - to let the caller know
- * that the passed in buffer size was not large enough to hold the
- * formatted string.
- *
- */
-
-// Deal with the differeneces on Windows
-namespace snprintf_hack
-{
- LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...);
-}
-
-using snprintf_hack::snprintf;
-
-/**
- * @brief Convert a wide string to std::string
- *
- * This replaces the unsafe W2A macro from ATL.
- */
-LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in);
-
-//@}
-#endif // LL_WINDOWS
-
-/**
- * Many of the 'strip' and 'replace' methods of LLStringUtilBase need
- * specialization to work with the signed char type.
- * Sadly, it is not possible (AFAIK) to specialize a single method of
- * a template class.
- * That stuff should go here.
- */
-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);
-}
-
-////////////////////////////////////////////////////////////
-// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp.
-// There is no LLWStringUtil::format implementation currently.
-// Calling thse for anything other than LLStringUtil will produce link errors.
-
-////////////////////////////////////////////////////////////
-
-
-// static
-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;
-}
-
-//static
-template<class T>
-S32 LLStringUtilBase<T>::compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
-{
- return LLStringOps::collate(lhs.c_str(), rhs.c_str());
-}
-
-// static
-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
- {
- std::basic_string<T> lhs_string(lhs);
- std::basic_string<T> 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>
-S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
-{
- std::basic_string<T> lhs_string(lhs);
- std::basic_string<T> 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
-template<class T>
-S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& 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;
-}
-
-// static
-template<class T>
-S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& 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;
-}
-
-// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
-// static
-template<class T>
-BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b )
-{
- 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(std::basic_string<T>& string)
-{
- if( !string.empty() )
- {
- std::transform(
- string.begin(),
- string.end(),
- string.begin(),
- (T(*)(T)) &LLStringOps::toUpper);
- }
-}
-
-//static
-template<class T>
-void LLStringUtilBase<T>::toLower(std::basic_string<T>& string)
-{
- if( !string.empty() )
- {
- std::transform(
- string.begin(),
- string.end(),
- string.begin(),
- (T(*)(T)) &LLStringOps::toLower);
- }
-}
-
-//static
-template<class T>
-void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string)
-{
- if( !string.empty() )
- {
- size_type i = 0;
- while( i < string.length() && LLStringOps::isSpace( string[i] ) )
- {
- i++;
- }
- string.erase(0, i);
- }
-}
-
-//static
-template<class T>
-void LLStringUtilBase<T>::trimTail(std::basic_string<T>& 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 );
- }
-}
-
-
-// Replace line feeds with carriage return-line feed pairs.
-//static
-template<class T>
-void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& 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);
- }
-}
-
-// Remove all carriage returns
-//static
-template<class T>
-void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& 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);
-}
-
-//static
-template<class T>
-void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
-{
- size_type found_pos = 0;
- while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
- {
- string[found_pos] = replacement;
- found_pos++; // avoid infinite defeat if target == replacement
- }
-}
-
-//static
-template<class T>
-void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement )
-{
- size_type found_pos = 0;
- while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
- {
- string.replace( found_pos, target.length(), replacement );
- found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
- }
-}
-
-//static
-template<class T>
-void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& 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;
- }
- }
-}
-
-//static
-template<class T>
-void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab )
-{
- const T TAB = '\t';
- const T SPACE = ' ';
-
- std::basic_string<T> 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>
-BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& 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;
-}
-
-//static
-template<class T>
-void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& 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;
-}
-
-template<class T>
-void LLStringUtilBase<T>::_makeASCII(std::basic_string<T>& 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;
- }
- }
-}
-
-// static
-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';
- }
-}
-
-// static
-template<class T>
-void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& 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
- {
- std::basic_string<T> 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 std::basic_string<T>& 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>
-bool LLStringUtilBase<T>::startsWith(
- const std::basic_string<T>& string,
- const std::basic_string<T>& substr)
-{
- if(string.empty() || (substr.empty())) return false;
- if(0 == string.find(substr)) return true;
- return false;
-}
-
-// static
-template<class T>
-bool LLStringUtilBase<T>::endsWith(
- const std::basic_string<T>& string,
- const std::basic_string<T>& substr)
-{
- if(string.empty() || (substr.empty())) return false;
- std::string::size_type idx = string.rfind(substr);
- if(std::string::npos == idx) return false;
- return (idx == (string.size() - substr.size()));
-}
-
-
-template<class T>
-BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value)
-{
- if( string.empty() )
- {
- return FALSE;
- }
-
- std::basic_string<T> 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 std::basic_string<T>& 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 std::basic_string<T>& 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 std::basic_string<T>& 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 std::basic_string<T>& 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 std::basic_string<T>& string, U32& value)
-{
- if( string.empty() )
- {
- return FALSE;
- }
-
- std::basic_string<T> temp( string );
- trim(temp);
- U32 v;
- std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
- if(i_stream >> v)
- {
- value = v;
- return TRUE;
- }
- return FALSE;
-}
-
-template<class T>
-BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& value)
-{
- if( string.empty() )
- {
- return FALSE;
- }
-
- std::basic_string<T> temp( string );
- trim(temp);
- S32 v;
- std::basic_istringstream<T> i_stream((std::basic_string<T>)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 std::basic_string<T>& 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>::convertToF64(const std::basic_string<T>& string, F64& value)
-{
- if( string.empty() )
- {
- return FALSE;
- }
-
- std::basic_string<T> temp( string );
- trim(temp);
- F64 v;
- std::basic_istringstream<T> i_stream((std::basic_string<T>)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>
-void LLStringUtilBase<T>::truncate(std::basic_string<T>& string, size_type count)
-{
- size_type cur_size = string.size();
- string.resize(count < cur_size ? count : cur_size);
-}
-
-#endif // LL_STRING_H
+/** + * @file llstring.h + * @brief String utility functions and std::string class. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLSTRING_H +#define LL_LLSTRING_H + +#include <string> +#include <cstdio> +#include <locale> +#include <iomanip> +#include "llsd.h" +#include "llfasttimer.h" + +#if LL_LINUX || LL_SOLARIS +#include <wctype.h> +#include <wchar.h> +#endif + +#include <string.h> + +#if LL_SOLARIS +// stricmp and strnicmp do not exist on Solaris: +#define stricmp strcasecmp +#define strnicmp strncasecmp +#endif + +const char LL_UNKNOWN_CHAR = '?'; + +#if LL_DARWIN || LL_LINUX || LL_SOLARIS +// Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already) +#include <cstring> + +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) + { return (__c == eof()) ? 0 : __c; } + }; +}; +#endif + +class LL_COMMON_API LLStringOps +{ +private: + static long sPacificTimeOffset; + static long sLocalTimeOffset; + static bool sPacificDaylightTime; + static std::map<std::string, std::string> datetimeToCodes; + +public: + 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 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 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 isAlnum(char a) { return isalnum((unsigned char)a) != 0; } + static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } + + 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 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); +}; + +/** + * @brief Return a string constructed from in without crashing if the + * pointer is NULL. + */ +LL_COMMON_API std::string ll_safe_string(const char* in); +LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen); + + +// Allowing assignments from non-strings into format_map_t is apparently +// *really* error-prone, so subclass std::string with just basic c'tors. +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(); } + +private: + std::string mString; +}; + +template <class T> +class LLStringUtilBase +{ +private: + static std::string sLocale; + +public: + typedef typename std::basic_string<T>::size_type size_type; + +public: + ///////////////////////////////////////////////////////////////////////////////////////// + // Static Utility functions that operate on std::strings + + static std::basic_string<T> null; + + typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; + LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims); + LL_COMMON_API static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals); + LL_COMMON_API static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch); + LL_COMMON_API static S32 format(std::basic_string<T>& s, const format_map_t& substitutions); + LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions); + LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions); + LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions); + static void setLocale (std::string inLocale) {sLocale = inLocale;}; + static std::string getLocale (void) {return sLocale;}; + + static bool isValidIndex(const std::basic_string<T>& string, size_type i) + { + return !string.empty() && (0 <= i) && (i <= string.size()); + } + + static void trimHead(std::basic_string<T>& string); + static void trimTail(std::basic_string<T>& string); + static void trim(std::basic_string<T>& string) { trimHead(string); trimTail(string); } + static void truncate(std::basic_string<T>& string, size_type count); + + static void toUpper(std::basic_string<T>& string); + static void toLower(std::basic_string<T>& string); + + // True if this is the head of s. + static BOOL isHead( const std::basic_string<T>& 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 std::basic_string<T>& string, + const std::basic_string<T>& substr); + + /** + * @brief Returns true if string ends in substr + * + * If etither string or substr are empty, this method returns false. + */ + static bool endsWith( + const std::basic_string<T>& string, + const std::basic_string<T>& substr); + + static void addCRLF(std::basic_string<T>& string); + static void removeCRLF(std::basic_string<T>& string); + + static void replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab ); + static void replaceNonstandardASCII( std::basic_string<T>& string, T replacement ); + static void replaceChar( std::basic_string<T>& string, T target, T replacement ); + static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement ); + + static BOOL containsNonprintable(const std::basic_string<T>& string); + static void stripNonprintable(std::basic_string<T>& string); + + /** + * @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(std::basic_string<T>& string); + + // Conversion to other data types + static BOOL convertToBOOL(const std::basic_string<T>& string, BOOL& value); + static BOOL convertToU8(const std::basic_string<T>& string, U8& value); + static BOOL convertToS8(const std::basic_string<T>& string, S8& value); + static BOOL convertToS16(const std::basic_string<T>& string, S16& value); + static BOOL convertToU16(const std::basic_string<T>& string, U16& value); + static BOOL convertToU32(const std::basic_string<T>& string, U32& value); + static BOOL convertToS32(const std::basic_string<T>& string, S32& value); + static BOOL convertToF32(const std::basic_string<T>& string, F32& value); + static BOOL convertToF64(const std::basic_string<T>& 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 std::basic_string<T>& lhs, const std::basic_string<T>& 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 std::basic_string<T>& lhs, const std::basic_string<T>& rhs); + + // Case sensitive comparison with good handling of numbers. Does not use current locale. + // a.k.a. strdictcmp() + static S32 compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b); + + // Case *in*sensitive comparison with good handling of numbers. Does not use current locale. + // a.k.a. strdictcmp() + static S32 compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b); + + // Puts compareDict() in a form appropriate for LL container classes to use for sorting. + static BOOL precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& 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(std::basic_string<T>& dst, const std::basic_string<T>& 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 std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens); +}; + +template<class T> std::basic_string<T> LLStringUtilBase<T>::null; +template<class T> std::string LLStringUtilBase<T>::sLocale; + +typedef LLStringUtilBase<char> LLStringUtil; +typedef LLStringUtilBase<llwchar> LLWStringUtil; +typedef std::basic_string<llwchar> LLWString; + +//@ Use this where we want to disallow input in the form of "foo" +// This is used to catch places where english text is embedded in the code +// instead of in a translatable XUI file. +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) {} +}; + +struct LLDictionaryLess +{ +public: + bool operator()(const std::string& a, const std::string& b) + { + return (LLStringUtil::precedesDict(a, b) ? true : false); + } +}; + + +/** + * Simple support functions + */ + +/** + * @brief chop off the trailing characters in a string. + * + * This function works on bytes rather than glyphs, so this will + * incorrectly truncate non-single byte strings. + * Use utf8str_truncate() for utf8 strings + * @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) +{ + return std::string(in, 0, in.length() - count); +} + +/** + * @brief This translates a nybble stored as a hex value from 0-f back + * to a nybble in the low order bits of the return byte. + */ +LL_COMMON_API U8 hex_as_nybble(char hex); + +/** + * @brief read the contents of a file into a string. + * + * Since this function has no concept of character encoding, most + * anything you do with this method ill-advised. Please avoid. + * @param str [out] The string which will have. + * @param filename The full name of the file to read. + * @return Returns true on success. If false, str is unmodified. + */ +LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename); +LL_COMMON_API bool iswindividual(llwchar elem); + +/** + * Unicode support + */ + +// Make the incoming string a utf8 string. Replaces any unknown glyph +// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest +// of the data may not be recovered. +LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw); + +// +// We should never use UTF16 except when communicating with Win32! +// +typedef std::basic_string<U16> llutf16string; + +LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len); +LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str); + +LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len); +LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str); + +LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len); +LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str ); + +LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len); +LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str); +// Same function, better name. JC +inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); } + +// +LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars); + +LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len); +LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str); + +LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len); +LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str); + +// Length of this UTF32 string in bytes when transformed to UTF8 +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 std::string utf8str_tolower(const std::string& utf8str); + +// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string. +LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len); + +// Length in utf16string (UTF-16) of wlen wchars beginning at woffset. +LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen); + +// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.) +LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL); + +/** + * @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. + * @param utf8str A valid utf8 string to truncate. + * @param max_len The maximum number of bytes in the return value. + * @return Returns a valid utf8 string with byte count <= max_len. + */ +LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len); + +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); + +/** + * @brief Replace all occurences of target_char with replace_char + * + * @param utf8str A utf8 string to process. + * @param target_char The wchar to be replaced + * @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); + +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 utf8str_removeCRLF(const std::string& utf8str); + + +#if LL_WINDOWS +/* @name Windows string helpers + */ +//@{ + +/** + * @brief Implementation the expected snprintf interface. + * + * If the size of the passed in buffer is not large enough to hold the string, + * two bad things happen: + * 1. resulting formatted string is NOT null terminated + * 2. Depending on the platform, the return value could be a) the required + * size of the buffer to copy the entire formatted string or b) -1. + * On Windows with VS.Net 2003, it returns -1 e.g. + * + * safe_snprintf always adds a NULL terminator so that the caller does not + * need to check for return value or need to add the NULL terminator. + * It does not, however change the return value - to let the caller know + * that the passed in buffer size was not large enough to hold the + * formatted string. + * + */ + +// Deal with the differeneces on Windows +namespace snprintf_hack +{ + LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...); +} + +using snprintf_hack::snprintf; + +/** + * @brief Convert a wide string to std::string + * + * This replaces the unsafe W2A macro from ATL. + */ +LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in); + +//@} +#endif // LL_WINDOWS + +/** + * Many of the 'strip' and 'replace' methods of LLStringUtilBase need + * specialization to work with the signed char type. + * Sadly, it is not possible (AFAIK) to specialize a single method of + * a template class. + * That stuff should go here. + */ +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); +} + +//////////////////////////////////////////////////////////// +// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp. +// There is no LLWStringUtil::format implementation currently. +// Calling thse for anything other than LLStringUtil will produce link errors. + +//////////////////////////////////////////////////////////// + + +// static +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; +} + +//static +template<class T> +S32 LLStringUtilBase<T>::compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs) +{ + return LLStringOps::collate(lhs.c_str(), rhs.c_str()); +} + +// static +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 + { + std::basic_string<T> lhs_string(lhs); + std::basic_string<T> 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> +S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs) +{ + std::basic_string<T> lhs_string(lhs); + std::basic_string<T> 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 +template<class T> +S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& 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; +} + +// static +template<class T> +S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& 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; +} + +// Puts compareDict() in a form appropriate for LL container classes to use for sorting. +// static +template<class T> +BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b ) +{ + 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(std::basic_string<T>& string) +{ + if( !string.empty() ) + { + std::transform( + string.begin(), + string.end(), + string.begin(), + (T(*)(T)) &LLStringOps::toUpper); + } +} + +//static +template<class T> +void LLStringUtilBase<T>::toLower(std::basic_string<T>& string) +{ + if( !string.empty() ) + { + std::transform( + string.begin(), + string.end(), + string.begin(), + (T(*)(T)) &LLStringOps::toLower); + } +} + +//static +template<class T> +void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string) +{ + if( !string.empty() ) + { + size_type i = 0; + while( i < string.length() && LLStringOps::isSpace( string[i] ) ) + { + i++; + } + string.erase(0, i); + } +} + +//static +template<class T> +void LLStringUtilBase<T>::trimTail(std::basic_string<T>& 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 ); + } +} + + +// Replace line feeds with carriage return-line feed pairs. +//static +template<class T> +void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& 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); + } +} + +// Remove all carriage returns +//static +template<class T> +void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& 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); +} + +//static +template<class T> +void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement ) +{ + size_type found_pos = 0; + while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) + { + string[found_pos] = replacement; + found_pos++; // avoid infinite defeat if target == replacement + } +} + +//static +template<class T> +void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement ) +{ + size_type found_pos = 0; + while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) + { + string.replace( found_pos, target.length(), replacement ); + found_pos += replacement.length(); // avoid infinite defeat if replacement contains target + } +} + +//static +template<class T> +void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& 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; + } + } +} + +//static +template<class T> +void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab ) +{ + const T TAB = '\t'; + const T SPACE = ' '; + + std::basic_string<T> 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> +BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& 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; +} + +//static +template<class T> +void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& 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; +} + +template<class T> +void LLStringUtilBase<T>::_makeASCII(std::basic_string<T>& 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; + } + } +} + +// static +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'; + } +} + +// static +template<class T> +void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& 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 + { + std::basic_string<T> 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 std::basic_string<T>& 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> +bool LLStringUtilBase<T>::startsWith( + const std::basic_string<T>& string, + const std::basic_string<T>& substr) +{ + if(string.empty() || (substr.empty())) return false; + if(0 == string.find(substr)) return true; + return false; +} + +// static +template<class T> +bool LLStringUtilBase<T>::endsWith( + const std::basic_string<T>& string, + const std::basic_string<T>& substr) +{ + if(string.empty() || (substr.empty())) return false; + std::string::size_type idx = string.rfind(substr); + if(std::string::npos == idx) return false; + return (idx == (string.size() - substr.size())); +} + + +template<class T> +BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value) +{ + if( string.empty() ) + { + return FALSE; + } + + std::basic_string<T> 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 std::basic_string<T>& 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 std::basic_string<T>& 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 std::basic_string<T>& 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 std::basic_string<T>& 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 std::basic_string<T>& string, U32& value) +{ + if( string.empty() ) + { + return FALSE; + } + + std::basic_string<T> temp( string ); + trim(temp); + U32 v; + std::basic_istringstream<T> i_stream((std::basic_string<T>)temp); + if(i_stream >> v) + { + value = v; + return TRUE; + } + return FALSE; +} + +template<class T> +BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& value) +{ + if( string.empty() ) + { + return FALSE; + } + + std::basic_string<T> temp( string ); + trim(temp); + S32 v; + std::basic_istringstream<T> i_stream((std::basic_string<T>)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 std::basic_string<T>& 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>::convertToF64(const std::basic_string<T>& string, F64& value) +{ + if( string.empty() ) + { + return FALSE; + } + + std::basic_string<T> temp( string ); + trim(temp); + F64 v; + std::basic_istringstream<T> i_stream((std::basic_string<T>)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> +void LLStringUtilBase<T>::truncate(std::basic_string<T>& string, size_type count) +{ + size_type cur_size = string.size(); + string.resize(count < cur_size ? count : cur_size); +} + +#endif // LL_STRING_H diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index c3d7650bd9..932d96d940 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -33,9 +33,7 @@ #ifndef LL_LLTHREAD_H #define LL_LLTHREAD_H -#include "llapr.h" #include "llapp.h" - #include "apr_thread_cond.h" class LLThread; diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h index 71c6fc0591..0f1e59a18c 100644 --- a/indra/llcommon/llversionserver.h +++ b/indra/llcommon/llversionserver.h @@ -36,7 +36,7 @@ const S32 LL_VERSION_MAJOR = 1; const S32 LL_VERSION_MINOR = 31; const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 3256; +const S32 LL_VERSION_BUILD = 200030; const char * const LL_CHANNEL = "Second Life Server"; diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 082d054ba2..540aea4252 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -36,7 +36,7 @@ const S32 LL_VERSION_MAJOR = 2; const S32 LL_VERSION_MINOR = 0; const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 3256; +const S32 LL_VERSION_BUILD = 200030; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 5dda600755..82c736266d 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -201,6 +201,7 @@ LLWorkerClass::~LLWorkerClass() { llassert_always(!(mWorkFlags & WCF_WORKING)); llassert_always(mWorkFlags & WCF_DELETE_REQUESTED); + llassert_always(!mMutex.isLocked()); if (mRequestHandle != LLWorkerThread::nullHandle()) { LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle); diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index a12bd52a64..a1e85d2ecc 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -52,6 +52,7 @@ class LLWorkerClass; class LL_COMMON_API LLWorkerThread : public LLQueuedThread { + friend class LLWorkerClass; public: class WorkRequest : public LLQueuedThread::QueuedRequest { @@ -92,8 +93,11 @@ public: handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL); - void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug + +private: + void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion + }; //============================================================================ diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index 0635ddd5f5..22be4078a1 100644 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -3,6 +3,7 @@ project(llimage) include(00-Common) +include(LLAddBuildTest) include(LLCommon) include(LLImage) include(LLMath) @@ -59,3 +60,6 @@ target_link_libraries(llimage ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ) + +# Add tests +#ADD_BUILD_TEST(llimageworker llimage) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 9bbc55509d..575ad5363d 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -55,13 +55,9 @@ std::string LLImage::sLastErrorMessage; LLMutex* LLImage::sMutex = NULL; //static -void LLImage::initClass(LLWorkerThread* workerthread) +void LLImage::initClass() { sMutex = new LLMutex(NULL); - if (workerthread) - { - LLImageWorker::initImageWorker(workerthread); - } LLImageJ2C::openDSO(); } @@ -69,7 +65,6 @@ void LLImage::initClass(LLWorkerThread* workerthread) void LLImage::cleanupClass() { LLImageJ2C::closeDSO(); - LLImageWorker::cleanupImageWorker(); delete sMutex; sMutex = NULL; } @@ -316,6 +311,21 @@ void LLImageRaw::deleteData() LLImageBase::deleteData(); } +void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components) +{ + if(data == getData()) + { + return ; + } + + deleteData(); + + LLImageBase::setSize(width, height, components) ; + LLImageBase::setDataAndSize(data, width * height * components) ; + + sGlobalRawMemory += getDataSize(); +} + BOOL LLImageRaw::resize(U16 width, U16 height, S8 components) { if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components)) @@ -816,6 +826,51 @@ void LLImageRaw::copyScaled( LLImageRaw* src ) } } +//scale down image by not blending a pixel with its neighbors. +BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height) +{ + LLMemType mt1(mMemType); + + S8 c = getComponents() ; + llassert((1 == c) || (3 == c) || (4 == c) ); + + S32 old_width = getWidth(); + S32 old_height = getHeight(); + + S32 new_data_size = old_width * new_height * c ; + llassert_always(new_data_size > 0); + + F32 ratio_x = (F32)old_width / new_width ; + F32 ratio_y = (F32)old_height / new_height ; + if( ratio_x < 1.0f || ratio_y < 1.0f ) + { + return TRUE; // Nothing to do. + } + ratio_x -= 1.0f ; + ratio_y -= 1.0f ; + + U8* new_data = new U8[new_data_size] ; + llassert_always(new_data != NULL) ; + + U8* old_data = getData() ; + S32 i, j, k, s, t; + for(i = 0, s = 0, t = 0 ; i < new_height ; i++) + { + for(j = 0 ; j < new_width ; j++) + { + for(k = 0 ; k < c ; k++) + { + new_data[s++] = old_data[t++] ; + } + t += (S32)(ratio_x * c + 0.1f) ; + } + t += (S32)(ratio_y * old_width * c + 0.1f) ; + } + + setDataAndSize(new_data, new_width, new_height, c) ; + + return TRUE ; +} BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) { @@ -1223,25 +1278,28 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip ifs.read ((char*)buffer, length); ifs.close(); - image->updateData(); - - if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C) + BOOL success; + + success = image->updateData(); + if (success) { - S32 width = image->getWidth(); - S32 height = image->getHeight(); - S32 discard_level = 0; - while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL) + if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C) { - width >>= 1; - height >>= 1; - discard_level++; + S32 width = image->getWidth(); + S32 height = image->getHeight(); + S32 discard_level = 0; + while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL) + { + width >>= 1; + height >>= 1; + discard_level++; + } + ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level); } - ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level); + success = image->decode(this, 100000.0f); } - - BOOL success = image->decode(this, 100000.0f); - image = NULL; // deletes image + image = NULL; // deletes image if (!success) { deleteData(); diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 8108553107..686f583886 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -50,7 +50,8 @@ const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE; const S32 MAX_IMAGE_COMPONENTS = 8; const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; -// Note! These CANNOT be changed without invalidating the viewer VFS files, I think? +// Note! These CANNOT be changed without modifying simulator code +// *TODO: change both to 1024 when SIM texture fetching is deprecated const S32 FIRST_PACKET_SIZE = 600; const S32 MAX_IMG_PACKET_SIZE = 1000; @@ -61,7 +62,6 @@ const S32 MAX_IMG_PACKET_SIZE = 1000; class LLImageFormatted; class LLImageRaw; class LLColor4U; -class LLWorkerThread; typedef enum e_image_codec { @@ -82,7 +82,7 @@ typedef enum e_image_codec class LLImage { public: - static void initClass(LLWorkerThread* workerthread); + static void initClass(); static void cleanupClass(); static const std::string& getLastError(); @@ -131,7 +131,7 @@ public: protected: // special accessor to allow direct setting of mData and mDataSize by LLImageFormatted - void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; }; + void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; } public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -192,6 +192,7 @@ public: void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE); void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE); BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE ); + BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ; // Fill the buffer with a constant color void fill( const LLColor4U& color ); @@ -240,6 +241,8 @@ protected: U8 fastFractionalMult(U8 a,U8 b); + void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; + public: static S32 sGlobalRawMemory; static S32 sRawImageCount; @@ -310,7 +313,7 @@ protected: protected: S8 mCodec; S8 mDecoding; - S8 mDecoded; + S8 mDecoded; // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC S8 mDiscardLevel; public: diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp index 1ce4517a0d..0aa6840ff6 100644 --- a/indra/llimage/llimagedxt.cpp +++ b/indra/llimage/llimagedxt.cpp @@ -264,6 +264,8 @@ void LLImageDXT::setFormat() // virtual BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time) { + // *TODO: Test! This has been tweaked since its intial inception, + // but we don't use it any more! llassert_always(raw_image); if (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5) @@ -274,8 +276,17 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time) S32 width = getWidth(), height = getHeight(); S32 ncomponents = getComponents(); + U8* data = NULL; + if (mDiscardLevel >= 0) + { + data = getData() + getMipOffset(mDiscardLevel); + calcDiscardWidthHeight(mDiscardLevel, mFileFormat, width, height); + } + else + { + data = getData() + getMipOffset(0); + } S32 image_size = formatBytes(mFileFormat, width, height); - U8* data = getData() + getMipOffset(0); if ((!getData()) || (data + image_size > getData() + getDataSize())) { @@ -300,10 +311,8 @@ BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard) llerrs << "Request for invalid discard level" << llendl; } U8* data = getData() + getMipOffset(discard); - // I'm not sure these are the correct initial values for height and width, - // but previously they were being used uninitialized. JC - S32 width = raw->getWidth(); - S32 height = raw->getHeight(); + S32 width = 0; + S32 height = 0; calcDiscardWidthHeight(discard, mFileFormat, width, height); raw = new LLImageRaw(data, width, height, getComponents()); return TRUE; diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 2352c8edd7..74f08b2d0b 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -283,6 +283,7 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time) } +// Returns TRUE to mean done, whether successful or not. BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count ) { LLMemType mt1(mMemType); @@ -295,7 +296,7 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir if (!getData() || (getDataSize() < 16)) { setLastError("LLImageJ2C uninitialized"); - res = FALSE; + res = TRUE; // done } else { @@ -348,7 +349,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, //static S32 LLImageJ2C::calcHeaderSizeJ2C() { - return 600; //2048; // ??? hack... just needs to be >= actual header size... + return FIRST_PACKET_SIZE; // Hack. just needs to be >= actual header size... } //static diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp index fa0dd3ff05..79ea79cc07 100644 --- a/indra/llimage/llimagejpeg.cpp +++ b/indra/llimage/llimagejpeg.cpp @@ -188,6 +188,7 @@ void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo) } +// Returns true when done, whether or not decode was successful. BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) { llassert_always(raw_image); @@ -198,7 +199,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) if (!getData() || (0 == getDataSize())) { setLastError("LLImageJPEG trying to decode an image with no data!"); - return FALSE; + return TRUE; // done } S32 row_stride = 0; @@ -226,7 +227,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) if(setjmp(sSetjmpBuffer)) { jpeg_destroy_decompress(&cinfo); - return FALSE; + return TRUE; // done } try { @@ -320,7 +321,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) catch (int) { jpeg_destroy_decompress(&cinfo); - return FALSE; + return TRUE; // done } // Check to see whether any corrupt-data warnings occurred @@ -328,7 +329,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) { // TODO: extract the warning to find out what went wrong. setLastError( "Unable to decode JPEG image."); - return FALSE; + return TRUE; // done } return TRUE; diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index 532e996188..86d41515e7 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -37,152 +37,138 @@ //---------------------------------------------------------------------------- -//static -LLWorkerThread* LLImageWorker::sWorkerThread = NULL; -S32 LLImageWorker::sCount = 0; +// MAIN THREAD +LLImageDecodeThread::LLImageDecodeThread(bool threaded) + : LLQueuedThread("imagedecode", threaded) +{ + mCreationMutex = new LLMutex(getAPRPool()); +} -//static -void LLImageWorker::initImageWorker(LLWorkerThread* workerthread) +// MAIN THREAD +// virtual +S32 LLImageDecodeThread::update(U32 max_time_ms) { - sWorkerThread = workerthread; + LLMutexLock lock(mCreationMutex); + for (creation_list_t::iterator iter = mCreationList.begin(); + iter != mCreationList.end(); ++iter) + { + creation_info& info = *iter; + ImageRequest* req = new ImageRequest(info.handle, info.image, + info.priority, info.discard, info.needs_aux, + info.responder); + addRequest(req); + } + mCreationList.clear(); + S32 res = LLQueuedThread::update(max_time_ms); + return res; } -//static -void LLImageWorker::cleanupImageWorker() +LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image, + U32 priority, S32 discard, BOOL needs_aux, Responder* responder) +{ + LLMutexLock lock(mCreationMutex); + handle_t handle = generateHandle(); + mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); + return handle; +} + +// Used by unit test only +// Returns the size of the mutex guarded list as an indication of sanity +S32 LLImageDecodeThread::tut_size() +{ + LLMutexLock lock(mCreationMutex); + S32 res = mCreationList.size(); + return res; +} + +LLImageDecodeThread::Responder::~Responder() { } //---------------------------------------------------------------------------- -LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority, - S32 discard, - LLPointer<LLResponder> responder) - : LLWorkerClass(sWorkerThread, "Image"), +LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatted* image, + U32 priority, S32 discard, BOOL needs_aux, + LLImageDecodeThread::Responder* responder) + : LLQueuedThread::QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE), mFormattedImage(image), - mDecodedType(-1), mDiscardLevel(discard), - mPriority(priority), + mNeedsAux(needs_aux), + mDecodedRaw(FALSE), + mDecodedAux(FALSE), mResponder(responder) { - ++sCount; } -LLImageWorker::~LLImageWorker() +LLImageDecodeThread::ImageRequest::~ImageRequest() { - mDecodedImage = NULL; + mDecodedImageRaw = NULL; + mDecodedImageAux = NULL; mFormattedImage = NULL; - --sCount; } //---------------------------------------------------------------------------- -//virtual, main thread -void LLImageWorker::startWork(S32 param) -{ - llassert_always(mDecodedImage.isNull()); - mDecodedType = -1; -} -bool LLImageWorker::doWork(S32 param) +// Returns true when done, whether or not decode was successful. +bool LLImageDecodeThread::ImageRequest::processRequest() { - bool decoded = false; - if(mDecodedImage.isNull()) + const F32 decode_time_slice = .1f; + bool done = true; + if (!mDecodedRaw && mFormattedImage.notNull()) { - if (!mFormattedImage->updateData()) - { - mDecodedType = -2; // failed - return true; - } - if (mDiscardLevel >= 0) + // Decode primary channels + if (mDecodedImageRaw.isNull()) { - mFormattedImage->setDiscardLevel(mDiscardLevel); - } - if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents())) - { - decoded = true; // failed - } - else - { - mDecodedImage = new LLImageRaw(); // allow possibly smaller size set during decoding + // parse formatted header + if (!mFormattedImage->updateData()) + { + return true; // done (failed) + } + if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents())) + { + return true; // done (failed) + } + if (mDiscardLevel >= 0) + { + mFormattedImage->setDiscardLevel(mDiscardLevel); + } + mDecodedImageRaw = new LLImageRaw(mFormattedImage->getWidth(), + mFormattedImage->getHeight(), + mFormattedImage->getComponents()); } + done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // 1ms + mDecodedRaw = done; } - if (!decoded) + if (done && mNeedsAux && !mDecodedAux && mFormattedImage.notNull()) { - if (param == 0) - { - // Decode primary channels - decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms - } - else + // Decode aux channel + if (!mDecodedImageAux) { - // Decode aux channel - decoded = mFormattedImage->decodeChannels(mDecodedImage, .1f, param, param); // 1ms + mDecodedImageAux = new LLImageRaw(mFormattedImage->getWidth(), + mFormattedImage->getHeight(), + 1); } + done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); // 1ms + mDecodedAux = done; } - if (decoded) - { - // Call the callback immediately; endWork doesn't get called until ckeckWork - if (mResponder.notNull()) - { - bool success = (!wasAborted() && mDecodedImage.notNull() && mDecodedImage->getDataSize() != 0); - mResponder->completed(success); - } - } - return decoded; -} -void LLImageWorker::endWork(S32 param, bool aborted) -{ - if (mDecodedType != -2) - { - mDecodedType = aborted ? -2 : param; - } + return done; } -//---------------------------------------------------------------------------- - - -BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard) +void LLImageDecodeThread::ImageRequest::finishRequest(bool completed) { - // For most codecs, only mDiscardLevel data is available. - // (see LLImageDXT for exception) - if (discard >= 0 && discard != mFormattedImage->getDiscardLevel()) - { - llerrs << "Request for invalid discard level" << llendl; - } - checkWork(); - if (mDecodedType == -2) + if (mResponder.notNull()) { - return TRUE; // aborted, done - } - if (mDecodedType != channel) - { - if (!haveWork()) - { - addWork(channel, mPriority); - } - return FALSE; - } - else - { - llassert_always(!haveWork()); - llassert_always(mDecodedType == channel); - raw = mDecodedImage; // smart pointer acquires ownership of data - mDecodedImage = NULL; - return TRUE; + bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux); + mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux); } + // Will automatically be deleted } -BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard) +// Used by unit test only +// Checks that a responder exists for this instance so that something can happen when completion is reached +bool LLImageDecodeThread::ImageRequest::tut_isOK() { - if (mFormattedImage->getCodec() == IMG_CODEC_DXT) - { - // special case - LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage); - return imagedxt->getMipData(raw, discard); - } - else - { - return requestDecodedAuxData(raw, 0, discard); - } + return mResponder.notNull(); } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 0d66695d6e..6a5b86a277 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -37,49 +37,72 @@ #include "llpointer.h" #include "llworkerthread.h" -class LLImageWorker : public LLWorkerClass +class LLImageDecodeThread : public LLQueuedThread { public: - static void initImageWorker(LLWorkerThread* workerthread); - static void cleanupImageWorker(); - -public: - static LLWorkerThread* getWorkerThread() { return sWorkerThread; } - - // LLWorkerThread -public: - LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, - LLPointer<LLResponder> responder); - ~LLImageWorker(); - - // called from WORKER THREAD, returns TRUE if done - /*virtual*/ bool doWork(S32 param); - - BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1); - BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard = -1); - void releaseDecodedData(); - void cancelDecode(); + class Responder : public LLThreadSafeRefCount + { + protected: + virtual ~Responder(); + public: + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0; + }; -private: - // called from MAIN THREAD - /*virtual*/ void startWork(S32 param); // called from addWork() - /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork() + class ImageRequest : public LLQueuedThread::QueuedRequest + { + protected: + virtual ~ImageRequest(); // use deleteRequest() + + public: + ImageRequest(handle_t handle, LLImageFormatted* image, + U32 priority, S32 discard, BOOL needs_aux, + LLImageDecodeThread::Responder* responder); -protected: - LLPointer<LLImageFormatted> mFormattedImage; - LLPointer<LLImageRaw> mDecodedImage; - S32 mDecodedType; - S32 mDiscardLevel; + /*virtual*/ bool processRequest(); + /*virtual*/ void finishRequest(bool completed); -private: - U32 mPriority; - LLPointer<LLResponder> mResponder; + // Used by unit tests to check the consitency of the request instance + bool tut_isOK(); + + private: + // input + LLPointer<LLImageFormatted> mFormattedImage; + S32 mDiscardLevel; + BOOL mNeedsAux; + // output + LLPointer<LLImageRaw> mDecodedImageRaw; + LLPointer<LLImageRaw> mDecodedImageAux; + BOOL mDecodedRaw; + BOOL mDecodedAux; + LLPointer<LLImageDecodeThread::Responder> mResponder; + }; -protected: - static LLWorkerThread* sWorkerThread; - public: - static S32 sCount; + LLImageDecodeThread(bool threaded = true); + handle_t decodeImage(LLImageFormatted* image, + U32 priority, S32 discard, BOOL needs_aux, + Responder* responder); + S32 update(U32 max_time_ms); + + // Used by unit tests to check the consistency of the thread instance + S32 tut_size(); + +private: + struct creation_info + { + handle_t handle; + LLPointer<LLImageFormatted> image; + U32 priority; + S32 discard; + BOOL needs_aux; + LLPointer<Responder> responder; + creation_info(handle_t h, LLImageFormatted* i, U32 p, S32 d, BOOL aux, Responder* r) + : handle(h), image(i), priority(p), discard(d), needs_aux(aux), responder(r) + {} + }; + typedef std::list<creation_info> creation_list_t; + creation_list_t mCreationList; + LLMutex* mCreationMutex; }; #endif diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp new file mode 100644 index 0000000000..cc44696a45 --- /dev/null +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -0,0 +1,260 @@ +/** + * @file llimageworker_test.cpp + * @author Merov Linden + * @date 2009-04-28 + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Precompiled header: almost always required for newview cpp files +#include <list> +#include <map> +#include <algorithm> +// Class to test +#include "../llimageworker.h" +// For timer class +#include "../llcommon/lltimer.h" +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// 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() {} +void LLImageBase::dump() { } +void LLImageBase::sanityCheck() { } +void LLImageBase::deleteData() { } +U8* LLImageBase::allocateData(S32 size) { return NULL; } +U8* LLImageBase::reallocateData(S32 size) { return NULL; } + +LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components) { } +LLImageRaw::~LLImageRaw() { } +void LLImageRaw::deleteData() { } +U8* LLImageRaw::allocateData(S32 size) { return NULL; } +U8* LLImageRaw::reallocateData(S32 size) { return NULL; } + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- + +namespace tut +{ + // 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) + { + *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 : image worker + // Note: this class is not meant to be instantiated outside an LLImageDecodeThread instance + // but it's not a bad idea to get its public API a good shake as part of a thorough unit test set. + // Some gotcha with the destructor though (see below). + struct imagerequest_test + { + // Instance to be tested + LLImageDecodeThread::ImageRequest* mRequest; + bool done; + + // Constructor and destructor of the test wrapper + imagerequest_test() + { + done = false; + mRequest = new LLImageDecodeThread::ImageRequest(0, 0, + LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, + new responder_test(&done)); + } + ~imagerequest_test() + { + // We should delete the object *but*, because its destructor is protected, that cannot be + // done from outside an LLImageDecodeThread instance... So we leak memory here... It's fine... + //delete mRequest; + } + }; + + // 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("imagedecodethread"); + + typedef test_group<imagerequest_test> imagerequest_t; + typedef imagerequest_t::object imagerequest_object_t; + tut::imagerequest_t tut_imagerequest("imagerequest"); + + // --------------------------------------------------------------------------------------- + // 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 + // --------------------------------------------------------------------------------------- + // + // Note on Unit Testing Queued Thread Classes + // + // Since methods on such a class are called on a separate loop and that we can't insert tut + // ensure() calls in there, we exercise the class with 2 sets of tests: + // - 1: Test as a single threaded instance: We declare the class but ask for no thread + // to be spawned (easy with LLThreads since there's a boolean argument on the constructor + // just for that). We can then unit test each public method like we do on a normal class. + // - 2: Test as a threaded instance: We let the thread launch and check that its external + // behavior is as expected (i.e. it runs, can accept a work order and processes + // it). Typically though there's no guarantee that this exercises all the methods of the + // class which is why we also need the previous "non threaded" set of unit tests for + // complete coverage. + // + // --------------------------------------------------------------------------------------- + + template<> template<> + void imagedecodethread_object_t::test<1>() + { + // Test a *non threaded* instance of the class + mThread = new LLImageDecodeThread(false); + ensure("LLImageDecodeThread: non threaded constructor failed", mThread != NULL); + // Test that we start with an empty list right at creation + ensure("LLImageDecodeThread: non threaded init state incorrect", mThread->tut_size() == 0); + // Insert something in the queue + bool done = false; + LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done)); + // Verifies we got a valid handle + ensure("LLImageDecodeThread: non threaded decodeImage(), returned handle is null", decodeHandle != 0); + // Verifies that we do now have something in the queued list + ensure("LLImageDecodeThread: non threaded decodeImage() insertion in threaded list failed", mThread->tut_size() == 1); + // Trigger queue handling "manually" (on a threaded instance, this is done on the thread loop) + S32 res = mThread->update(0); + // Verifies that we successfully handled the list + ensure("LLImageDecodeThread: non threaded update() list handling test failed", res == 0); + // Verifies that the list is now empty + ensure("LLImageDecodeThread: non threaded update() list emptying test failed", mThread->tut_size() == 0); + } + + template<> template<> + void imagedecodethread_object_t::test<2>() + { + // Test a *threaded* instance of the class + mThread = new LLImageDecodeThread(true); + ensure("LLImageDecodeThread: threaded constructor failed", mThread != NULL); + // Test that we start with an empty list right at creation + ensure("LLImageDecodeThread: threaded init state incorrect", mThread->tut_size() == 0); + // Insert something in the queue + bool done = false; + LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done)); + // Verifies we get back a valid handle + ensure("LLImageDecodeThread: threaded decodeImage(), returned handle is null", decodeHandle != 0); + // Wait a little so to simulate the main thread doing something on its main loop... + ms_sleep(500); // 500 milliseconds + // Verifies that the responder has *not* been called yet in the meantime + ensure("LLImageDecodeThread: responder creation failed", done == false); + // Ask the thread to update: that means tells the queue to check itself and creates work requests + mThread->update(1); + // 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); + } + + // --------------------------------------------------------------------------------------- + // Test the LLImageDecodeThread::ImageRequest interface + // --------------------------------------------------------------------------------------- + + template<> template<> + void imagerequest_object_t::test<1>() + { + // Test that we start with a correct request at creation + ensure("LLImageDecodeThread::ImageRequest::ImageRequest() constructor test failed", mRequest->tut_isOK()); + bool res = mRequest->processRequest(); + // Verifies that we processed the request successfully + ensure("LLImageDecodeThread::ImageRequest::processRequest() processing request test failed", res == true); + // Check that we can call the finishing call safely + try { + mRequest->finishRequest(false); + } catch (...) { + fail("LLImageDecodeThread::ImageRequest::finishRequest() test failed"); + } + } +} diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index ec6264dcf5..e71429b18d 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -168,7 +168,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod // dereference the array. if(!image || !image->numcomps) { - llwarns << "ERROR -> decodeImpl: failed to decode image!" << llendl; + LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; if (image) { opj_image_destroy(image); @@ -241,7 +241,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod } else // Some rare OpenJPEG versions have this bug. { - llwarns << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl; + LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL; opj_image_destroy(image); return TRUE; // done @@ -375,7 +375,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con if (!bSuccess) { opj_cio_close(cio); - llinfos << "Failed to encode image." << llendl; + LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL; return FALSE; } codestream_length = cio_tell(cio); diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 5d3fbe5128..d665deb605 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -1324,7 +1324,7 @@ BOOL item_date_sort( LLInventoryItem* a, LLInventoryItem* b ) LLInventoryCategory::LLInventoryCategory( const LLUUID& uuid, const LLUUID& parent_uuid, - LLAssetType::EType preferred_type, + LLFolderType::EType preferred_type, const std::string& name) : LLInventoryObject(uuid, parent_uuid, LLAssetType::AT_CATEGORY, name), mPreferredType(preferred_type) @@ -1332,7 +1332,7 @@ LLInventoryCategory::LLInventoryCategory( } LLInventoryCategory::LLInventoryCategory() : - mPreferredType(LLAssetType::AT_NONE) + mPreferredType(LLFolderType::FT_NONE) { mType = LLAssetType::AT_CATEGORY; } @@ -1354,12 +1354,12 @@ void LLInventoryCategory::copyCategory(const LLInventoryCategory* other) mPreferredType = other->mPreferredType; } -LLAssetType::EType LLInventoryCategory::getPreferredType() const +LLFolderType::EType LLInventoryCategory::getPreferredType() const { return mPreferredType; } -void LLInventoryCategory::setPreferredType(LLAssetType::EType type) +void LLInventoryCategory::setPreferredType(LLFolderType::EType type) { mPreferredType = type; } @@ -1405,13 +1405,13 @@ bool LLInventoryCategory::fromLLSD(const LLSD& sd) if (sd.has(w)) { S8 type = (U8)sd[w].asInteger(); - mPreferredType = static_cast<LLAssetType::EType>(type); + mPreferredType = static_cast<LLFolderType::EType>(type); } w = INV_ASSET_TYPE_LABEL_WS; if (sd.has(w)) { S8 type = (U8)sd[w].asInteger(); - mPreferredType = static_cast<LLAssetType::EType>(type); + mPreferredType = static_cast<LLFolderType::EType>(type); } w = INV_NAME_LABEL; @@ -1433,7 +1433,7 @@ void LLInventoryCategory::unpackMessage(LLMessageSystem* msg, msg->getUUIDFast(block, _PREHASH_ParentID, mParentUUID, block_num); S8 type; msg->getS8Fast(block, _PREHASH_Type, type, block_num); - mPreferredType = static_cast<LLAssetType::EType>(type); + mPreferredType = static_cast<LLFolderType::EType>(type); msg->getStringFast(block, _PREHASH_Name, mName, block_num); LLStringUtil::replaceNonstandardASCII(mName, ' '); } @@ -1482,7 +1482,7 @@ BOOL LLInventoryCategory::importFile(LLFILE* fp) } else if(0 == strcmp("pref_type", keyword)) { - mPreferredType = LLAssetType::lookup(valuestr); + mPreferredType = LLFolderType::lookup(valuestr); } else if(0 == strcmp("name", keyword)) { @@ -1514,7 +1514,7 @@ BOOL LLInventoryCategory::exportFile(LLFILE* fp, BOOL) const mParentUUID.toString(uuid_str); fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str()); fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - fprintf(fp, "\t\tpref_type\t%s\n", LLAssetType::lookup(mPreferredType)); + fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str()); fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); fprintf(fp,"\t}\n"); return TRUE; @@ -1561,7 +1561,7 @@ BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream) } else if(0 == strcmp("pref_type", keyword)) { - mPreferredType = LLAssetType::lookup(valuestr); + mPreferredType = LLFolderType::lookup(valuestr); } else if(0 == strcmp("name", keyword)) { @@ -1593,7 +1593,7 @@ BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL) mParentUUID.toString(uuid_str); output_stream << "\t\tparent_id\t" << uuid_str << "\n"; output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n"; - output_stream << "\t\tpref_type\t" << LLAssetType::lookup(mPreferredType) << "\n"; + output_stream << "\t\tpref_type\t" << LLFolderType::lookup(mPreferredType) << "\n"; output_stream << "\t\tname\t" << mName.c_str() << "|\n"; output_stream << "\t}\n"; return TRUE; @@ -1629,38 +1629,6 @@ LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item) return rv; } -/* deprecated, use LLInventoryItem::fromLLSD() instead -LLPointer<LLInventoryItem> ll_create_item_from_sd(const LLSD& sd_item) -{ - LLPointer<LLInventoryItem> rv = new LLInventoryItem; - rv->setUUID(sd_item[INV_ITEM_ID_LABEL].asUUID()); - rv->setParent(sd_item[INV_PARENT_ID_LABEL].asUUID()); - rv->rename(sd_item[INV_NAME_LABEL].asString()); - rv->setType( - LLAssetType::lookup(sd_item[INV_ASSET_TYPE_LABEL].asString())); - if (sd_item.has("shadow_id")) - { - LLUUID asset_id = sd_item["shadow_id"]; - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.decrypt(asset_id.mData, UUID_BYTES); - rv->setAssetUUID(asset_id); - } - if (sd_item.has(INV_ASSET_ID_LABEL)) - { - rv->setAssetUUID(sd_item[INV_ASSET_ID_LABEL].asUUID()); - } - rv->setDescription(sd_item[INV_DESC_LABEL].asString()); - rv->setSaleInfo(ll_sale_info_from_sd(sd_item[INV_SALE_INFO_LABEL])); - rv->setPermissions(ll_permissions_from_sd(sd_item[INV_PERMISSIONS_LABEL])); - rv->setInventoryType( - LLInventoryType::lookup( - sd_item[INV_INVENTORY_TYPE_LABEL].asString())); - rv->setFlags((U32)(sd_item[INV_FLAGS_LABEL].asInteger())); - rv->setCreationDate(sd_item[INV_CREATION_DATE_LABEL].asInteger()); - return rv; -} -*/ - LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat) { LLSD rv; @@ -1675,10 +1643,10 @@ LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat) rv[INV_PARENT_ID_LABEL] = cat->getParentUUID(); rv[INV_NAME_LABEL] = cat->getName(); rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType()); - if(LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())) + if(LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { rv[INV_PREFERRED_TYPE_LABEL] = - LLAssetType::lookup(cat->getPreferredType()); + LLFolderType::lookup(cat->getPreferredType()).c_str(); } return rv; } @@ -1692,7 +1660,7 @@ LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat) rv->setType( LLAssetType::lookup(sd_cat[INV_ASSET_TYPE_LABEL].asString())); rv->setPreferredType( - LLAssetType::lookup( - sd_cat[INV_PREFERRED_TYPE_LABEL].asString())); + LLFolderType::lookup( + sd_cat[INV_PREFERRED_TYPE_LABEL].asString())); return rv; } diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index bd581e860f..3de9d14f54 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -37,6 +37,7 @@ #include "llassetstorage.h" #include "lldarray.h" +#include "llfoldertype.h" #include "llinventorytype.h" #include "llmemtype.h" #include "llpermissions.h" @@ -321,15 +322,15 @@ protected: public: MEM_TYPE_NEW(LLMemType::MTYPE_INVENTORY); LLInventoryCategory(const LLUUID& uuid, const LLUUID& parent_uuid, - LLAssetType::EType preferred_type, + LLFolderType::EType preferred_type, const std::string& name); LLInventoryCategory(); LLInventoryCategory(const LLInventoryCategory* other); void copyCategory(const LLInventoryCategory* other); // LLRefCount requires custom copy // accessors and mutators - LLAssetType::EType getPreferredType() const; - void setPreferredType(LLAssetType::EType type); + LLFolderType::EType getPreferredType() const; + void setPreferredType(LLFolderType::EType type); // For messaging system support virtual void packMessage(LLMessageSystem* msg) const; virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); @@ -345,10 +346,8 @@ public: virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; protected: - // The type of asset that this category was "meant" to hold - // (although it may in fact hold any type). - LLAssetType::EType mPreferredType; - + // May be the type that this category was "meant" to hold (although it may hold any type). + LLFolderType::EType mPreferredType; }; diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index a445466b26..0e71c0d12d 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -79,24 +79,16 @@ LLInventoryDictionary::LLInventoryDictionary() addEntry(LLInventoryType::IT_SOUND, new InventoryEntry("sound", "sound", 1, LLAssetType::AT_SOUND)); addEntry(LLInventoryType::IT_CALLINGCARD, new InventoryEntry("callcard", "calling card", 1, LLAssetType::AT_CALLINGCARD)); addEntry(LLInventoryType::IT_LANDMARK, new InventoryEntry("landmark", "landmark", 1, LLAssetType::AT_LANDMARK)); - //addEntry(LLInventoryType::IT_SCRIPT, new InventoryEntry(NULL,NULL)); - //addEntry(LLInventoryType::IT_CLOTHING, new InventoryEntry(NULL,NULL)); addEntry(LLInventoryType::IT_OBJECT, new InventoryEntry("object", "object", 1, LLAssetType::AT_OBJECT)); addEntry(LLInventoryType::IT_NOTECARD, new InventoryEntry("notecard", "note card", 1, LLAssetType::AT_NOTECARD)); addEntry(LLInventoryType::IT_CATEGORY, new InventoryEntry("category", "folder" )); addEntry(LLInventoryType::IT_ROOT_CATEGORY, new InventoryEntry("root", "root" )); addEntry(LLInventoryType::IT_LSL, new InventoryEntry("script", "script", 2, LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE)); - //addEntry(LLInventoryType::IT_LSL_BYTECODE, new InventoryEntry(NULL,NULL)); - //addEntry(LLInventoryType::IT_TEXTURE_TGA, new InventoryEntry(NULL,NULL)); - //addEntry(LLInventoryType::IT_BODYPART, new InventoryEntry(NULL,NULL)); - //addEntry(LLInventoryType::IT_TRASH, new InventoryEntry(NULL,NULL)); addEntry(LLInventoryType::IT_SNAPSHOT, new InventoryEntry("snapshot", "snapshot", 1, LLAssetType::AT_TEXTURE)); - //addEntry(LLInventoryType::IT_LOST_AND_FOUND, new InventoryEntry(NULL,NULL, )); addEntry(LLInventoryType::IT_ATTACHMENT, new InventoryEntry("attach", "attachment", 1, LLAssetType::AT_OBJECT)); addEntry(LLInventoryType::IT_WEARABLE, new InventoryEntry("wearable", "wearable", 2, LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART)); addEntry(LLInventoryType::IT_ANIMATION, new InventoryEntry("animation", "animation", 1, LLAssetType::AT_ANIMATION)); addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE)); - addEntry(LLInventoryType::IT_FAVORITE, new InventoryEntry("favorite", "favorite", 1, LLAssetType::AT_FAVORITE)); } @@ -128,35 +120,9 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_ANIMATION, // AT_ANIMATION LLInventoryType::IT_GESTURE, // AT_GESTURE LLInventoryType::IT_NONE, // AT_SIMSTATE - LLInventoryType::IT_FAVORITE, // AT_FAVORITE LLInventoryType::IT_NONE, // AT_LINK LLInventoryType::IT_NONE, // AT_LINK_FOLDER - - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE - - LLInventoryType::IT_CATEGORY, // AT_CURRENT_OUTFIT - LLInventoryType::IT_CATEGORY, // AT_OUTFIT - LLInventoryType::IT_CATEGORY, // AT_MY_OUTFITS }; // static diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index 14b28bfe4b..e515b8a304 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -67,8 +67,7 @@ public: IT_WEARABLE = 18, IT_ANIMATION = 19, IT_GESTURE = 20, - IT_FAVORITE = 21, - IT_COUNT = 22, + IT_COUNT = 21, IT_NONE = -1 }; diff --git a/indra/llinventory/tests/inventorymisc_test.cpp b/indra/llinventory/tests/inventorymisc_test.cpp index 770594dc9d..c797a70c50 100644 --- a/indra/llinventory/tests/inventorymisc_test.cpp +++ b/indra/llinventory/tests/inventorymisc_test.cpp @@ -94,7 +94,7 @@ LLPointer<LLInventoryCategory> create_random_inventory_cat() LLPointer<LLInventoryCategory> cat = new LLInventoryCategory( item_id, parent_id, - LLAssetType::AT_NONE, + LLFolderType::FT_NONE, std::string("Sample category")); return cat; } @@ -452,7 +452,7 @@ namespace tut ensure_equals("4.type::getType() failed", dst->getType(), src->getType()); ensure_equals("5.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType()); - src->setPreferredType( LLAssetType::AT_TEXTURE); + src->setPreferredType( LLFolderType::FT_TEXTURE); sd = ll_create_sd_from_inventory_category(src); dst = ll_create_category_from_sd(sd); ensure_equals("6.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType()); diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index b8ef92f9a9..df4c618ac1 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -3582,7 +3582,7 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, if (face == -1) // ALL_SIDES { start_face = 0; - end_face = getNumFaces() - 1; + end_face = getNumVolumeFaces() - 1; } else { diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index b3087bcc3f..0ab1081200 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -64,6 +64,9 @@ const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-0 const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds +LLTempAssetStorage::~LLTempAssetStorage() +{ +} ///---------------------------------------------------------------------------- /// LLAssetInfo diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 56adbd5ccf..83cfdf6110 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -204,7 +204,16 @@ typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t; typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status); -class LLAssetStorage +class LLTempAssetStorage +{ +public: + virtual ~LLTempAssetStorage() =0; + virtual void addTempAssetData(const LLUUID& asset_id, + const LLUUID& agent_id, + const std::string& host_name) = 0; +}; + +class LLAssetStorage : public LLTempAssetStorage { public: // VFS member is public because static child methods need it :( diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 5ff41322b7..dc02367a62 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -229,7 +229,7 @@ public: U32 report(CURLcode); void getTransferInfo(LLCurl::TransferInfo* info); - void prepRequest(const std::string& url, ResponderPtr, bool post = false); + void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false); const char* getErrorBuffer(); @@ -441,7 +441,9 @@ size_t curlHeaderCallback(void* data, size_t size, size_t nmemb, void* user_data return n; } -void LLCurl::Easy::prepRequest(const std::string& url, ResponderPtr responder, bool post) +void LLCurl::Easy::prepRequest(const std::string& url, + const std::vector<std::string>& headers, + ResponderPtr responder, bool post) { resetState(); @@ -474,8 +476,13 @@ void LLCurl::Easy::prepRequest(const std::string& url, ResponderPtr responder, b { slist_append("Connection: keep-alive"); slist_append("Keep-alive: 300"); + // Accept and other headers + for (std::vector<std::string>::const_iterator iter = headers.begin(); + iter != headers.end(); ++iter) + { + slist_append((*iter).c_str()); + } } - // *FIX: should have ACCEPT headers } //////////////////////////////////////////////////////////////////////////// @@ -685,15 +692,18 @@ LLCurlRequest::LLCurlRequest() : mActiveMulti(NULL), mActiveRequestCount(0) { + mThreadID = LLThread::currentID(); } LLCurlRequest::~LLCurlRequest() { + llassert_always(mThreadID == LLThread::currentID()); for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer()); } void LLCurlRequest::addMulti() { + llassert_always(mThreadID == LLThread::currentID()); LLCurl::Multi* multi = new LLCurl::Multi(); mMultiSet.insert(multi); mActiveMulti = multi; @@ -723,17 +733,20 @@ bool LLCurlRequest::addEasy(LLCurl::Easy* easy) void LLCurlRequest::get(const std::string& url, LLCurl::ResponderPtr responder) { - getByteRange(url, 0, -1, responder); + getByteRange(url, headers_t(), 0, -1, responder); } -bool LLCurlRequest::getByteRange(const std::string& url, S32 offset, S32 length, LLCurl::ResponderPtr responder) +bool LLCurlRequest::getByteRange(const std::string& url, + const headers_t& headers, + S32 offset, S32 length, + LLCurl::ResponderPtr responder) { LLCurl::Easy* easy = allocEasy(); if (!easy) { return false; } - easy->prepRequest(url, responder); + easy->prepRequest(url, headers, responder); easy->setopt(CURLOPT_HTTPGET, 1); if (length > 0) { @@ -745,14 +758,17 @@ bool LLCurlRequest::getByteRange(const std::string& url, S32 offset, S32 length, return res; } -bool LLCurlRequest::post(const std::string& url, const LLSD& data, LLCurl::ResponderPtr responder) +bool LLCurlRequest::post(const std::string& url, + const headers_t& headers, + const LLSD& data, + LLCurl::ResponderPtr responder) { LLCurl::Easy* easy = allocEasy(); if (!easy) { return false; } - easy->prepRequest(url, responder); + easy->prepRequest(url, headers, responder); LLSDSerialize::toXML(data, easy->getInput()); S32 bytes = easy->getInput().str().length(); @@ -772,6 +788,7 @@ bool LLCurlRequest::post(const std::string& url, const LLSD& data, LLCurl::Respo // Note: call once per frame S32 LLCurlRequest::process() { + llassert_always(mThreadID == LLThread::currentID()); S32 res = 0; for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ) @@ -791,6 +808,7 @@ S32 LLCurlRequest::process() S32 LLCurlRequest::getQueued() { + llassert_always(mThreadID == LLThread::currentID()); S32 queued = 0; for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ) @@ -1011,7 +1029,7 @@ void LLCurl::initClass() S32 mutex_count = CRYPTO_num_locks(); for (S32 i=0; i<mutex_count; i++) { - sSSLMutex.push_back(new LLMutex(gAPRPoolp)); + sSSLMutex.push_back(new LLMutex(NULL)); } CRYPTO_set_id_callback(&LLCurl::ssl_thread_id); CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback); diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 0b58e7c4a5..1bc1767966 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -194,12 +194,14 @@ namespace boost class LLCurlRequest { public: + typedef std::vector<std::string> headers_t; + LLCurlRequest(); ~LLCurlRequest(); void get(const std::string& url, LLCurl::ResponderPtr responder); - bool getByteRange(const std::string& url, S32 offset, S32 length, LLCurl::ResponderPtr responder); - bool post(const std::string& url, const LLSD& data, LLCurl::ResponderPtr responder); + bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder); + bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder); S32 process(); S32 getQueued(); @@ -213,6 +215,7 @@ private: curlmulti_set_t mMultiSet; LLCurl::Multi* mActiveMulti; S32 mActiveRequestCount; + U32 mThreadID; // debug }; class LLCurlEasyRequest diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index 41f3f3f607..7332f5c954 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -292,7 +292,6 @@ bool is_asset_id_knowable(LLAssetType::EType type) case LLAssetType::AT_BODYPART: case LLAssetType::AT_ANIMATION: case LLAssetType::AT_GESTURE: - case LLAssetType::AT_FAVORITE: case LLAssetType::AT_LINK: case LLAssetType::AT_LINK_FOLDER: rv = true; diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp index e6a5ad9946..ffbe7bd202 100644 --- a/indra/llmessage/tests/llcurl_stub.cpp +++ b/indra/llmessage/tests/llcurl_stub.cpp @@ -20,6 +20,7 @@ */ #include "linden_common.h" +#include "llcurl.h" LLCurl::Responder::Responder() : mReferenceCount(0) diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp index 250fa100b6..7065c9d7e4 100644 --- a/indra/llmessage/tests/llhttpclientadapter_test.cpp +++ b/indra/llmessage/tests/llhttpclientadapter_test.cpp @@ -50,7 +50,7 @@ std::vector<std::string> put_urls; std::vector<LLSD> put_body; std::vector<boost::intrusive_ptr<LLCurl::Responder> > put_responders; -void LLHTTPClient::put(std::string const &url, LLSD const &body, boost::intrusive_ptr<LLCurl::Responder> responder,float) +void LLHTTPClient::put(const std::string& url, const LLSD& body, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout) { put_urls.push_back(url); put_responders.push_back(responder); diff --git a/indra/llprimitive/llmediaentry.cpp b/indra/llprimitive/llmediaentry.cpp index fa04bf80e7..701300163a 100644 --- a/indra/llprimitive/llmediaentry.cpp +++ b/indra/llprimitive/llmediaentry.cpp @@ -164,6 +164,7 @@ void LLMediaEntry::asLLSD(LLSD& sd) const // "security" fields sd[WHITELIST_ENABLE_KEY] = mWhiteListEnable; + sd.erase(WHITELIST_KEY); for (U32 i=0; i<mWhiteList.size(); i++) { sd[WHITELIST_KEY].append(mWhiteList[i]); diff --git a/indra/llprimitive/tests/llmediaentry_test.cpp b/indra/llprimitive/tests/llmediaentry_test.cpp index 9ce6560923..cd9608d56b 100644 --- a/indra/llprimitive/tests/llmediaentry_test.cpp +++ b/indra/llprimitive/tests/llmediaentry_test.cpp @@ -223,8 +223,7 @@ namespace tut { set_test_name("Test LLMediaEntry Instantiation"); LLMediaEntry entry; - ensure_llsd_equals(get_test_name(), defaultMediaEntryLLSD, entry.asLLSD()); - + ensure_llsd_equals(get_test_name() + " failed", defaultMediaEntryLLSD, entry.asLLSD()); } template<> template<> @@ -251,12 +250,27 @@ namespace tut ensure_llsd_equals(get_test_name() + " failed", golden, entry.asLLSD()); } + template<> template<> + void object::test<4>() + { + set_test_name("Test LLMediaEntry::asLLSD()"); + LLMediaEntry entry; + LLSD sd; + // Put some cruft in the LLSD + sd[LLMediaEntry::CURRENT_URL_KEY] = "http://www.example.com"; + LLSD whitelist; + whitelist.append("*.example.com"); + sd[LLMediaEntry::WHITELIST_KEY] = whitelist; + entry.asLLSD(sd); + ensure_llsd_equals(get_test_name() + " failed", defaultMediaEntryLLSD, sd); + } + // limit tests const char *URL_OK = "http://www.example.com"; const char *URL_TOO_BIG = "http://www.example.com.qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"; template<> template<> - void object::test<4>() + void object::test<5>() { set_test_name("Test Limits on setting current URL"); LLMediaEntry entry; @@ -267,7 +281,7 @@ namespace tut } template<> template<> - void object::test<5>() + void object::test<6>() { set_test_name("Test Limits on setting home URL"); LLMediaEntry entry; @@ -278,7 +292,7 @@ namespace tut } template<> template<> - void object::test<6>() + void object::test<7>() { set_test_name("Test Limits on setting whitelist"); @@ -292,7 +306,7 @@ namespace tut } template<> template<> - void object::test<7>() + void object::test<8>() { set_test_name("Test Limits on setting whitelist too big"); @@ -307,7 +321,7 @@ namespace tut } template<> template<> - void object::test<8>() + void object::test<9>() { set_test_name("Test Limits on setting whitelist too many"); @@ -323,7 +337,7 @@ namespace tut } template<> template<> - void object::test<9>() + void object::test<10>() { set_test_name("Test to make sure both setWhiteList() functions behave the same"); @@ -341,7 +355,7 @@ namespace tut } template<> template<> - void object::test<10>() + void object::test<11>() { set_test_name("Test to make sure both setWhiteList() functions behave the same"); @@ -362,7 +376,7 @@ namespace tut } template<> template<> - void object::test<11>() + void object::test<12>() { set_test_name("Test to make sure both setWhiteList() functions behave the same"); @@ -386,99 +400,99 @@ namespace tut // Check the "empty whitelist" case template<> template<> - void object::test<12>() { whitelist_test("", "http://www.example.com", true); } + void object::test<13>() { whitelist_test("", "http://www.example.com", true); } // Check the "missing scheme" case template<> template<> - void object::test<13>() { whitelist_test("www.example.com", "http://www.example.com", true); } + void object::test<14>() { whitelist_test("www.example.com", "http://www.example.com", true); } // Check the "exactly the same" case template<> template<> - void object::test<14>() { whitelist_test("http://example.com", "http://example.com", true); } + void object::test<15>() { whitelist_test("http://example.com", "http://example.com", true); } // Check the enable flag template<> template<> - void object::test<15>() { whitelist_test(false, "www.example.com", "http://www.secondlife.com", true); } + void object::test<16>() { whitelist_test(false, "www.example.com", "http://www.secondlife.com", true); } template<> template<> - void object::test<16>() { whitelist_test(true, "www.example.com", "http://www.secondlife.com", false); } + void object::test<17>() { whitelist_test(true, "www.example.com", "http://www.secondlife.com", false); } // Check permutations of trailing slash: template<> template<> - void object::test<17>() { whitelist_test("http://www.example.com", "http://www.example.com/", true); } + void object::test<18>() { whitelist_test("http://www.example.com", "http://www.example.com/", true); } template<> template<> - void object::test<18>() { whitelist_test("http://www.example.com/", "http://www.example.com/", true); } + void object::test<19>() { whitelist_test("http://www.example.com/", "http://www.example.com/", true); } template<> template<> - void object::test<19>() { whitelist_test("http://www.example.com/", "http://www.example.com", false); } + void object::test<20>() { whitelist_test("http://www.example.com/", "http://www.example.com", false); } template<> template<> - void object::test<20>() { whitelist_test("http://www.example.com", "http://www.example.com/foobar", true); } + void object::test<21>() { whitelist_test("http://www.example.com", "http://www.example.com/foobar", true); } template<> template<> - void object::test<21>() { whitelist_test("http://www.example.com/", "http://www.example.com/foobar", false); } + void object::test<22>() { whitelist_test("http://www.example.com/", "http://www.example.com/foobar", false); } // More cases... template<> template<> - void object::test<22>() { whitelist_test("http://example.com", "http://example.com/wiki", true); } + void object::test<23>() { whitelist_test("http://example.com", "http://example.com/wiki", true); } template<> template<> - void object::test<23>() { whitelist_test("www.example.com", "http://www.example.com/help", true); } + void object::test<24>() { whitelist_test("www.example.com", "http://www.example.com/help", true); } template<> template<> - void object::test<24>() { whitelist_test("http://www.example.com", "http://wwwexample.com", false); } + void object::test<25>() { whitelist_test("http://www.example.com", "http://wwwexample.com", false); } template<> template<> - void object::test<25>() { whitelist_test("http://www.example.com", "http://www.example.com/wiki", true); } + void object::test<26>() { whitelist_test("http://www.example.com", "http://www.example.com/wiki", true); } template<> template<> - void object::test<26>() { whitelist_test("example.com", "http://wwwexample.com", false); } + void object::test<27>() { whitelist_test("example.com", "http://wwwexample.com", false); } template<> template<> - void object::test<27>() { whitelist_test("http://www.example.com/", "http://www.amazon.com/wiki", false); } + void object::test<28>() { whitelist_test("http://www.example.com/", "http://www.amazon.com/wiki", false); } template<> template<> - void object::test<28>() { whitelist_test("www.example.com", "http://www.amazon.com", false); } + void object::test<29>() { whitelist_test("www.example.com", "http://www.amazon.com", false); } // regexp cases template<> template<> - void object::test<29>() { whitelist_test("*.example.com", "http://www.example.com", true); } + void object::test<30>() { whitelist_test("*.example.com", "http://www.example.com", true); } template<> template<> - void object::test<30>() { whitelist_test("*.example.com", "http://www.amazon.com", false); } + void object::test<31>() { whitelist_test("*.example.com", "http://www.amazon.com", false); } template<> template<> - void object::test<31>() { whitelist_test("*.example.com", "http://www.example.com/foo/bar", true); } + void object::test<32>() { whitelist_test("*.example.com", "http://www.example.com/foo/bar", true); } template<> template<> - void object::test<32>() { whitelist_test("*.example.com", "http:/example.com/foo/bar", false); } + void object::test<33>() { whitelist_test("*.example.com", "http:/example.com/foo/bar", false); } template<> template<> - void object::test<33>() { whitelist_test("*example.com", "http://example.com/foo/bar", true); } + void object::test<34>() { whitelist_test("*example.com", "http://example.com/foo/bar", true); } template<> template<> - void object::test<34>() { whitelist_test("*example.com", "http://my.virus.com/foo/bar?example.com", false); } + void object::test<35>() { whitelist_test("*example.com", "http://my.virus.com/foo/bar?example.com", false); } template<> template<> - void object::test<35>() { whitelist_test("example.com", "http://my.virus.com/foo/bar?example.com", false); } + void object::test<36>() { whitelist_test("example.com", "http://my.virus.com/foo/bar?example.com", false); } template<> template<> - void object::test<36>() { whitelist_test("*example.com", "http://my.virus.com/foo/bar?*example.com", false); } + void object::test<37>() { whitelist_test("*example.com", "http://my.virus.com/foo/bar?*example.com", false); } template<> template<> - void object::test<37>() { whitelist_test("http://*example.com", "http://www.example.com", true); } + void object::test<38>() { whitelist_test("http://*example.com", "http://www.example.com", true); } template<> template<> - void object::test<38>() { whitelist_test("http://*.example.com", "http://www.example.com", true); } + void object::test<39>() { whitelist_test("http://*.example.com", "http://www.example.com", true); } template<> template<> - void object::test<39>() { whitelist_test("http://*.e$?^.com", "http://www.e$?^.com", true); } + void object::test<40>() { whitelist_test("http://*.e$?^.com", "http://www.e$?^.com", true); } template<> template<> - void object::test<40>() { whitelist_test("*.example.com/foo/bar", "http://www.example.com/", false); } + void object::test<41>() { whitelist_test("*.example.com/foo/bar", "http://www.example.com/", false); } template<> template<> - void object::test<41>() { whitelist_test("*.example.com/foo/bar", "http://example.com/foo/bar", false); } + void object::test<42>() { whitelist_test("*.example.com/foo/bar", "http://example.com/foo/bar", false); } template<> template<> - void object::test<42>() { whitelist_test("http://*.example.com/foo/bar", "http://www.example.com", false); } + void object::test<43>() { whitelist_test("http://*.example.com/foo/bar", "http://www.example.com", false); } template<> template<> - void object::test<43>() { whitelist_test("http://*.example.com", "https://www.example.com", false); } + void object::test<44>() { whitelist_test("http://*.example.com", "https://www.example.com", false); } template<> template<> - void object::test<44>() { whitelist_test("http*://*.example.com", "rtsp://www.example.com", false); } + void object::test<45>() { whitelist_test("http*://*.example.com", "rtsp://www.example.com", false); } template<> template<> - void object::test<45>() { whitelist_test("http*://*.example.com", "https://www.example.com", true); } + void object::test<46>() { whitelist_test("http*://*.example.com", "https://www.example.com", true); } template<> template<> - void object::test<46>() { whitelist_test("example.com", "http://www.example.com", false); } + void object::test<47>() { whitelist_test("example.com", "http://www.example.com", false); } template<> template<> - void object::test<47>() { whitelist_test("www.example.com", "http://www.example.com:80", false); } + void object::test<48>() { whitelist_test("www.example.com", "http://www.example.com:80", false); } template<> template<> - void object::test<48>() { whitelist_test("www.example.com", "http://www.example.com", true); } + void object::test<49>() { whitelist_test("www.example.com", "http://www.example.com", true); } template<> template<> - void object::test<49>() { whitelist_test("www.example.com/", "http://www.example.com", false); } + void object::test<50>() { whitelist_test("www.example.com/", "http://www.example.com", false); } template<> template<> - void object::test<50>() { whitelist_test("www.example.com/foo/bar/*", "http://www.example.com/foo/bar/baz", true); } + void object::test<51>() { whitelist_test("www.example.com/foo/bar/*", "http://www.example.com/foo/bar/baz", true); } // Path only template<> template<> - void object::test<51>() { whitelist_test("/foo/*/baz", "http://www.example.com/foo/bar/baz", true); } + void object::test<52>() { whitelist_test("/foo/*/baz", "http://www.example.com/foo/bar/baz", true); } template<> template<> - void object::test<52>() { whitelist_test("/foo/*/baz", "http://www.example.com/foo/bar/", false); } + void object::test<53>() { whitelist_test("/foo/*/baz", "http://www.example.com/foo/bar/", false); } } diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index e5fea5b995..f8d7ea00e0 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -43,7 +43,6 @@ #include "llmath.h" #include "llgl.h" #include "llrender.h" - //---------------------------------------------------------------------------- const F32 MIN_TEXTURE_LIFETIME = 10.f; @@ -60,21 +59,34 @@ std::list<U32> LLImageGL::sDeadTextureList; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; +BOOL LLImageGL::sAllowReadBackRaw = FALSE ; LLImageGL* LLImageGL::sDefaultGLTexture = NULL ; + std::set<LLImageGL*> LLImageGL::sImageList; -#if !LL_RELEASE_FOR_DOWNLOAD +//**************************************************************************************************** +//The below for texture auditing use only +//**************************************************************************************************** //----------------------- //debug use +BOOL gAuditTexture = FALSE ; #define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048 std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ; std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; S32 LLImageGL::sCurTexSizeBar = -1 ; S32 LLImageGL::sCurTexPickSize = -1 ; -LLPointer<LLImageGL> LLImageGL::sDefaultTexturep = NULL; +LLPointer<LLImageGL> LLImageGL::sHighlightTexturep = NULL; +S32 LLImageGL::sMaxCatagories = 1 ; + +std::vector<S32> LLImageGL::sTextureMemByCategory; +std::vector<S32> LLImageGL::sTextureMemByCategoryBound ; +std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ; //------------------------ -#endif +//**************************************************************************************************** +//End for texture auditing use only +//**************************************************************************************************** + //************************************************************************************** //below are functions for debug use //do not delete them even though they are not currently being used. @@ -144,6 +156,60 @@ void LLImageGL::checkTexSize() const //************************************************************************************** //---------------------------------------------------------------------------- +BOOL is_little_endian() +{ + S32 a = 0x12345678; + U8 *c = (U8*)(&a); + + return (*c == 0x78) ; +} +//static +void LLImageGL::initClass(S32 num_catagories) +{ + sMaxCatagories = num_catagories ; + + sTextureMemByCategory.resize(sMaxCatagories); + sTextureMemByCategoryBound.resize(sMaxCatagories) ; + sTextureCurMemByCategoryBound.resize(sMaxCatagories) ; +} + +//static +void LLImageGL::cleanupClass() +{ + sTextureMemByCategory.clear() ; + sTextureMemByCategoryBound.clear() ; + sTextureCurMemByCategoryBound.clear() ; +} + +//static +void LLImageGL::setHighlightTexture(S32 category) +{ + const S32 dim = 128; + sHighlightTexturep = new LLImageGL() ; + LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3); + U8* data = image_raw->getData(); + for (S32 i = 0; i<dim; i++) + { + for (S32 j = 0; j<dim; j++) + { + const S32 border = 2; + if (i<border || j<border || i>=(dim-border) || j>=(dim-border)) + { + *data++ = 0xff; + *data++ = 0xff; + *data++ = 0xff; + } + else + { + *data++ = 0xff; + *data++ = 0xff; + *data++ = 0x00; + } + } + } + sHighlightTexturep->createGLTexture(0, image_raw, 0, TRUE, category); + image_raw = NULL; +} //static S32 LLImageGL::dataFormatBits(S32 dataformat) @@ -211,19 +277,31 @@ void LLImageGL::updateStats(F32 current_time) sBoundTextureMemoryInBytes = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; -#if !LL_RELEASE_FOR_DOWNLOAD - for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++) + if(gAuditTexture) { - sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ; - sTextureCurBoundCounter[i] = 0 ; + for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++) + { + sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ; + sTextureCurBoundCounter[i] = 0 ; + } + for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++) + { + sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ; + sTextureCurMemByCategoryBound[i] = 0 ; + } } -#endif } //static -S32 LLImageGL::updateBoundTexMem(const S32 delta) +S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) { - LLImageGL::sCurBoundTextureMemory += delta; + if(gAuditTexture && ncomponents > 0 && category > -1) + { + sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ; + sTextureCurMemByCategoryBound[category] += mem ; + } + + LLImageGL::sCurBoundTextureMemory += mem ; return LLImageGL::sCurBoundTextureMemory; } @@ -237,6 +315,7 @@ void LLImageGL::destroyGL(BOOL save_state) gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); } + sAllowReadBackRaw = true ; for (std::set<LLImageGL*>::iterator iter = sImageList.begin(); iter != sImageList.end(); iter++) { @@ -246,7 +325,7 @@ void LLImageGL::destroyGL(BOOL save_state) if (save_state && glimage->isGLTextureCreated() && glimage->mComponents) { glimage->mSaveData = new LLImageRaw; - if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) + if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it. { glimage->mSaveData = NULL ; } @@ -256,6 +335,7 @@ void LLImageGL::destroyGL(BOOL save_state) stop_glerror(); } } + sAllowReadBackRaw = false ; } //static @@ -273,7 +353,7 @@ void LLImageGL::restoreGL() { if (glimage->getComponents() && glimage->mSaveData->getComponents()) { - glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData); + glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory()); stop_glerror(); } glimage->mSaveData = NULL; // deletes data @@ -355,7 +435,7 @@ void LLImageGL::init(BOOL usemipmaps) mPickMask = NULL; mTextureMemory = 0; mLastBindTime = 0.f; - + mTarget = GL_TEXTURE_2D; mBindTarget = LLTexUnit::TT_TEXTURE; mUseMipMaps = usemipmaps; @@ -381,7 +461,11 @@ void LLImageGL::init(BOOL usemipmaps) mHasExplicitFormat = FALSE; mGLTextureCreated = FALSE ; + mIsMask = FALSE; + mCategory = -1 ; + mAlphaStride = 0 ; + mAlphaOffset = 0 ; mNeedsAlphaAndPickMask = TRUE ; mDiscardLevelInAtlas = -1 ; @@ -486,6 +570,10 @@ void LLImageGL::dump() } //---------------------------------------------------------------------------- +void LLImageGL::forceUpdateBindStats(void) const +{ + mLastBindTime = sLastFrameTime; +} BOOL LLImageGL::updateBindStats(S32 tex_mem) const { @@ -499,7 +587,7 @@ BOOL LLImageGL::updateBindStats(S32 tex_mem) const { // we haven't accounted for this texture yet this frame sUniqueCount++; - updateBoundTexMem(tex_mem); + updateBoundTexMem(tex_mem, mComponents, mCategory); mLastBindTime = sLastFrameTime; return TRUE ; @@ -525,6 +613,8 @@ void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_for else mFormatType = type_format; mFormatSwapBytes = swap_bytes; + + calcAlphaChannelOffsetAndStride() ; } //---------------------------------------------------------------------------- @@ -540,7 +630,6 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { - llpushcallstacks ; bool is_compressed = false; if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { @@ -749,7 +838,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } stop_glerror(); mGLTextureCreated = true; - llpushcallstacks ; } BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image) @@ -840,7 +928,6 @@ void LLImageGL::postAddToAtlas() BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) { - llpushcallstacks ; if (!width || !height) { return TRUE; @@ -930,7 +1017,6 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 stop_glerror(); mGLTextureCreated = true; } - llpushcallstacks ; return TRUE; } @@ -942,8 +1028,9 @@ BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S3 // Copy sub image from frame buffer BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height) { - if (gGL.getTexUnit(0)->bind(this)) + if (gGL.getTexUnit(0)->bind(this, false, true)) { + //checkTexSize() ; glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); mGLTextureCreated = true; stop_glerror(); @@ -1007,7 +1094,7 @@ BOOL LLImageGL::createGLTexture() return TRUE ; } -BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) +BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category) { if (gGLManager.mIsDisabled) { @@ -1027,8 +1114,10 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); // Actual image width/height = raw image width/height * 2^discard_level - S32 w = imageraw->getWidth() << discard_level; - S32 h = imageraw->getHeight() << discard_level; + S32 raw_w = imageraw->getWidth() ; + S32 raw_h = imageraw->getHeight() ; + S32 w = raw_w << discard_level; + S32 h = raw_h << discard_level; // setSize may call destroyGLTexture if the size does not match setSize(w, h, imageraw->getComponents()); @@ -1062,15 +1151,25 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S default: llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl; } + + calcAlphaChannelOffsetAndStride() ; } + if(!to_create) //not create a gl texture + { + destroyGLTexture(); + mCurrentDiscardLevel = discard_level; + mLastBindTime = sLastFrameTime; + return TRUE ; + } + + setCategory(category) ; const U8* rawdata = imageraw->getData(); return createGLTexture(discard_level, rawdata, FALSE, usename); } BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) { - llpushcallstacks ; llassert(data_in); if (discard_level < 0) @@ -1137,11 +1236,14 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (old_name != 0) { sGlobalTextureMemoryInBytes -= mTextureMemory; -#if !LL_RELEASE_FOR_DOWNLOAD - decTextureCounter(mTextureMemory / mComponents) ; -#endif + + if(gAuditTexture) + { + decTextureCounter(mTextureMemory, mComponents, mCategory) ; + } LLImageGL::deleteTextures(1, &old_name); + stop_glerror(); } @@ -1149,82 +1251,20 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ sGlobalTextureMemoryInBytes += mTextureMemory; mTexelsInGLTexture = getWidth() * getHeight() ; -#if !LL_RELEASE_FOR_DOWNLOAD - incTextureCounter(mTextureMemory / mComponents) ; -#endif - + if(gAuditTexture) + { + incTextureCounter(mTextureMemory, mComponents, mCategory) ; + } // mark this as bound at this point, so we don't throw it out immediately mLastBindTime = sLastFrameTime; - - llpushcallstacks ; return TRUE; } -BOOL LLImageGL::setDiscardLevel(S32 discard_level) -{ - llassert(discard_level >= 0); - llassert(mCurrentDiscardLevel >= 0); - - discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - - if (discard_level == mCurrentDiscardLevel) - { - // nothing to do - return FALSE; - } - else if (discard_level < mCurrentDiscardLevel) - { - // larger image - dump(); - llerrs << "LLImageGL::setDiscardLevel() called with larger discard level; use createGLTexture()" << llendl; - return FALSE; - } - else if (mUseMipMaps) - { - LLPointer<LLImageRaw> imageraw = new LLImageRaw; - while(discard_level > mCurrentDiscardLevel) - { - if (readBackRaw(discard_level, imageraw, false)) - { - break; - } - discard_level--; - } - if (discard_level == mCurrentDiscardLevel) - { - // unable to increase the discard level - return FALSE; - } - return createGLTexture(discard_level, imageraw); - } - else - { -#if !LL_LINUX && !LL_SOLARIS - // *FIX: This should not be skipped for the linux client. - llerrs << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl; -#endif - return FALSE; - } -} - -BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) -{ - assert_glerror(); - S32 gl_discard = discard_level - mCurrentDiscardLevel; - LLGLint glwidth = 0; - glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth); - LLGLint glheight = 0; - glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_HEIGHT, (GLint*)&glheight); - LLGLint glcomponents = 0 ; - glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&glcomponents); - assert_glerror(); - - return glwidth >= image_width && glheight >= image_height && (GL_RGB8 == glcomponents || GL_RGBA8 == glcomponents) ; -} - BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const { - llpushcallstacks ; + llassert_always(sAllowReadBackRaw) ; + //llerrs << "should not call this function!" << llendl ; + if (discard_level < 0) { discard_level = mCurrentDiscardLevel; @@ -1327,7 +1367,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre return FALSE ; } //----------------------------------------------------------------------------------------------- - llpushcallstacks ; + return TRUE ; } @@ -1345,25 +1385,26 @@ void LLImageGL::deleteDeadTextures() stop_glerror(); } } - + glDeleteTextures(1, &tex); stop_glerror(); } } - + void LLImageGL::destroyGLTexture() { if (mTexName != 0) { if(mTextureMemory) { -#if !LL_RELEASE_FOR_DOWNLOAD - decTextureCounter(mTextureMemory / mComponents) ; -#endif + if(gAuditTexture) + { + decTextureCounter(mTextureMemory, mComponents, mCategory) ; + } sGlobalTextureMemoryInBytes -= mTextureMemory; mTextureMemory = 0; } - + LLImageGL::deleteTextures(1, &mTexName); mTexName = 0; mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. @@ -1479,6 +1520,11 @@ S32 LLImageGL::getMipBytes(S32 discard_level) const return res; } +BOOL LLImageGL::isJustBound() const +{ + return (BOOL)(sLastFrameTime - mLastBindTime < 0.5f); +} + BOOL LLImageGL::getBoundRecently() const { return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME); @@ -1490,44 +1536,104 @@ void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType b mBindTarget = bind_target; } -void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) +const S8 INVALID_OFFSET = -99 ; +void LLImageGL::setNeedsAlphaAndPickMask(BOOL need_mask) { - if(!mNeedsAlphaAndPickMask) + if(mNeedsAlphaAndPickMask != need_mask) { - return ; + mNeedsAlphaAndPickMask = need_mask; + + if(mNeedsAlphaAndPickMask) + { + mAlphaOffset = 0 ; + } + else //do not need alpha mask + { + mAlphaOffset = INVALID_OFFSET ; + mIsMask = FALSE; + } } +} - if (mFormatType != GL_UNSIGNED_BYTE) +void LLImageGL::calcAlphaChannelOffsetAndStride() +{ + if(mAlphaOffset == INVALID_OFFSET)//do not need alpha mask { - llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl; + return ; } - U32 stride = 0; + mAlphaStride = -1 ; switch (mFormatPrimary) { case GL_LUMINANCE: case GL_ALPHA: - stride = 1; + mAlphaStride = 1; break; case GL_LUMINANCE_ALPHA: - stride = 2; + mAlphaStride = 2; break; case GL_RGB: - //no alpha + mNeedsAlphaAndPickMask = FALSE ; mIsMask = FALSE; - return; + return ; //no alpha channel. case GL_RGBA: - stride = 4; + mAlphaStride = 4; break; case GL_BGRA_EXT: - stride = 4; + mAlphaStride = 4; break; default: - return; + break; + } + + mAlphaOffset = -1 ; + if (mFormatType == GL_UNSIGNED_BYTE) + { + mAlphaOffset = mAlphaStride - 1 ; + } + else if(is_little_endian()) + { + if (mFormatType == GL_UNSIGNED_INT_8_8_8_8) + { + mAlphaOffset = 0 ; + } + else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV) + { + mAlphaOffset = 3 ; + } + } + else //big endian + { + if (mFormatType == GL_UNSIGNED_INT_8_8_8_8) + { + mAlphaOffset = 3 ; + } + else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV) + { + mAlphaOffset = 0 ; + } + } + + if( mAlphaStride < 1 || //unsupported format + mAlphaOffset < 0 || //unsupported type + (mFormatPrimary == GL_BGRA_EXT && mFormatType != GL_UNSIGNED_BYTE)) //unknown situation + { + llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl; + + mNeedsAlphaAndPickMask = FALSE ; + mIsMask = FALSE; + } +} + +void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) +{ + if(!mNeedsAlphaAndPickMask) + { + return ; } U32 length = w * h; - const GLubyte* current = ((const GLubyte*) data_in)+stride-1; + const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset ; S32 sample[16]; memset(sample, 0, sizeof(S32)*16); @@ -1535,7 +1641,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) for (U32 i = 0; i < length; i++) { ++sample[*current/16]; - current += stride; + current += mAlphaStride ; } U32 total = 0; @@ -1638,8 +1744,30 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) return res; } -//---------------------------------------------------------------------------- -#if !LL_RELEASE_FOR_DOWNLOAD +void LLImageGL::setCategory(S32 category) +{ + if(!gAuditTexture) + { + return ; + } + if(mCategory != category) + { + if(mCategory > -1) + { + sTextureMemByCategory[mCategory] -= mTextureMemory ; + } + if(category > -1 && category < sMaxCatagories) + { + sTextureMemByCategory[category] += mTextureMemory ; + mCategory = category; + } + else + { + mCategory = -1 ; + } + } +} + //for debug use //val is a "power of two" number S32 LLImageGL::getTextureCounterIndex(U32 val) @@ -1663,18 +1791,33 @@ S32 LLImageGL::getTextureCounterIndex(U32 val) return ret ; } } -void LLImageGL::incTextureCounter(U32 val) + +//static +void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category) { sTextureLoadedCounter[getTextureCounterIndex(val)]++ ; + sTextureMemByCategory[category] += (S32)val * ncomponents ; } -void LLImageGL::decTextureCounter(U32 val) + +//static +void LLImageGL::decTextureCounter(U32 val, S32 ncomponents, S32 category) { sTextureLoadedCounter[getTextureCounterIndex(val)]-- ; + sTextureMemByCategory[category] += (S32)val * ncomponents ; } -void LLImageGL::setCurTexSizebar(S32 index) + +void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size) { sCurTexSizeBar = index ; - sCurTexPickSize = (1 << index) ; + + if(set_pick_size) + { + sCurTexPickSize = (1 << index) ; + } + else + { + sCurTexPickSize = -1 ; + } } void LLImageGL::resetCurTexSizebar() { @@ -1682,7 +1825,9 @@ void LLImageGL::resetCurTexSizebar() sCurTexPickSize = -1 ; } //---------------------------------------------------------------------------- -#endif + +//---------------------------------------------------------------------------- + // Manual Mip Generation /* diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index a094605607..937065043c 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -47,7 +47,6 @@ class LLTextureAtlas ; #define MEGA_BYTES_TO_BYTES(x) ((x) << 20) //============================================================================ - class LLImageGL : public LLRefCount { friend class LLTexUnit; @@ -63,6 +62,7 @@ public: BOOL updateBindStats(S32 tex_mem) const ; F32 getTimePassedSinceLastBound(); + void forceUpdateBindStats(void) const; // needs to be called every frame static void updateStats(F32 current_time); @@ -71,8 +71,9 @@ public: static void destroyGL(BOOL save_state = TRUE); static void restoreGL(); - // Sometimes called externally for textures not using LLImageGL (should go away...) - static S32 updateBoundTexMem(const S32 delta); + // Sometimes called externally for textures not using LLImageGL (should go away...) + static S32 updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) ; + static bool checkSize(S32 width, S32 height); //for server side use only. @@ -91,6 +92,7 @@ protected: virtual ~LLImageGL(); void analyzeAlpha(const void* data_in, S32 w, S32 h); + void calcAlphaChannelOffsetAndStride(); public: virtual void dump(); // debugging info to llinfos @@ -105,14 +107,15 @@ public: static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels); BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0); + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, + S32 category = sMaxCatagories - 1); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); void setImage(const LLImageRaw* imageraw); void setImage(const U8* data_in, BOOL data_hasmips = FALSE); BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); - BOOL setDiscardLevel(S32 discard_level); + // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const; void destroyGLTexture(); @@ -131,6 +134,7 @@ public: S32 getBytes(S32 discard_level = -1) const; S32 getMipBytes(S32 discard_level = -1) const; BOOL getBoundRecently() const; + BOOL isJustBound() const; LLGLenum getPrimaryFormat() const { return mFormatPrimary; } LLGLenum getFormatType() const { return mFormatType; } @@ -150,8 +154,6 @@ public: BOOL getUseMipMaps() const { return mUseMipMaps; } void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; } - BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ; - void updatePickMask(S32 width, S32 height, const U8* data_in); BOOL getMask(const LLVector2 &tc); @@ -178,7 +180,7 @@ public: void init(BOOL usemipmaps); virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors - void setNeedsAlphaAndPickMask(BOOL need_mask) {mNeedsAlphaAndPickMask = need_mask;} + void setNeedsAlphaAndPickMask(BOOL need_mask); BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image); void postAddToAtlas() ; @@ -187,7 +189,7 @@ public: // Various GL/Rendering options S32 mTextureMemory; mutable F32 mLastBindTime; // last time this was bound, by discard level - + private: LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel @@ -197,13 +199,15 @@ private: BOOL mIsMask; BOOL mNeedsAlphaAndPickMask; - + S8 mAlphaStride ; + S8 mAlphaOffset ; + bool mGLTextureCreated ; LLGLuint mTexName; U16 mWidth; U16 mHeight; S8 mCurrentDiscardLevel; - + S8 mDiscardLevelInAtlas; U32 mTexelsInAtlas ; U32 mTexelsInGLTexture; @@ -233,7 +237,7 @@ public: static S32 sCount; static F32 sLastFrameTime; - + static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID // Global memory statistics @@ -246,30 +250,61 @@ public: static LLImageGL* sDefaultGLTexture ; static BOOL sAutomatedTest; -#if !LL_RELEASE_FOR_DOWNLOAD +#if DEBUG_MISS + BOOL mMissed; // Missed on last bind? + BOOL getMissed() const { return mMissed; }; +#else + BOOL getMissed() const { return FALSE; }; +#endif + +public: + static void initClass(S32 num_catagories) ; + static void cleanupClass() ; +private: + static S32 sMaxCatagories ; + + //the flag to allow to call readBackRaw(...). + //can be removed if we do not use that function at all. + static BOOL sAllowReadBackRaw ; +// +//**************************************************************************************************** +//The below for texture auditing use only +//**************************************************************************************************** +private: + S32 mCategory ; +public: + void setCategory(S32 category) ; + S32 getCategory()const {return mCategory ;} + //for debug use: show texture size distribution //---------------------------------------- - static LLPointer<LLImageGL> sDefaultTexturep; //default texture to replace normal textures + static LLPointer<LLImageGL> sHighlightTexturep; //default texture to replace normal textures static std::vector<S32> sTextureLoadedCounter ; static std::vector<S32> sTextureBoundCounter ; static std::vector<S32> sTextureCurBoundCounter ; static S32 sCurTexSizeBar ; static S32 sCurTexPickSize ; - + + static void setHighlightTexture(S32 category) ; static S32 getTextureCounterIndex(U32 val) ; - static void incTextureCounter(U32 val) ; - static void decTextureCounter(U32 val) ; - static void setCurTexSizebar(S32 index) ; + static void incTextureCounter(U32 val, S32 ncomponents, S32 category) ; + static void decTextureCounter(U32 val, S32 ncomponents, S32 category) ; + static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ; static void resetCurTexSizebar(); //---------------------------------------- -#endif -#if DEBUG_MISS - BOOL mMissed; // Missed on last bind? - BOOL getMissed() const { return mMissed; }; -#else - BOOL getMissed() const { return FALSE; }; -#endif + //for debug use: show texture category distribution + //---------------------------------------- + + static std::vector<S32> sTextureMemByCategory; + static std::vector<S32> sTextureMemByCategoryBound ; + static std::vector<S32> sTextureCurMemByCategoryBound ; + //---------------------------------------- +//**************************************************************************************************** +//End of definitions for texture auditing use only +//**************************************************************************************************** + }; +extern BOOL gAuditTexture; #endif // LL_LLIMAGEGL_H diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index b74d824c9e..fc45df8153 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -179,7 +179,7 @@ void LLTexUnit::disable(void) } } -bool LLTexUnit::bind(LLTexture* texture, bool forceBind) +bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) { stop_glerror(); if (mIndex < 0) return false; @@ -198,9 +198,19 @@ bool LLTexUnit::bind(LLTexture* texture, bool forceBind) //if deleted, will re-generate it immediately texture->forceImmediateUpdate() ; + gl_tex->forceUpdateBindStats() ; return texture->bindDefaultImage(mIndex); } + //in audit, replace the selected texture by the default one. + if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0) + { + if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize) + { + gl_tex->updateBindStats(gl_tex->mTextureMemory); + return bind(LLImageGL::sHighlightTexturep.get()); + } + } if ((mCurrTexture != gl_tex->getTexName()) || forceBind) { activate(); @@ -223,7 +233,7 @@ bool LLTexUnit::bind(LLTexture* texture, bool forceBind) return true; } -bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) +bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) { stop_glerror(); if (mIndex < 0) return false; @@ -260,6 +270,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) setTextureFilteringOption(texture->mFilterOption); } } + return true; } diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index cb2a4d4450..0121a190ee 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -149,8 +149,8 @@ public: // Binds the LLImageGL to this texture unit // (automatically enables the unit for the LLImageGL's texture type) - bool bind(LLImageGL* texture, bool forceBind = false); - bool bind(LLTexture* texture, bool forceBind = false); + bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false); + bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false); // Binds a cubemap to this texture unit // (automatically enables the texture unit for cubemaps) diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index 0cd9667644..7034e9199d 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -63,7 +63,7 @@ public: // virtual S8 getType() const = 0 ; virtual void setKnownDrawSize(S32 width, S32 height) = 0 ; - virtual bool bindDefaultImage(const S32 stage = 0) const = 0 ; + virtual bool bindDefaultImage(const S32 stage = 0) = 0 ; virtual void forceImmediateUpdate() = 0 ; virtual void setActive() = 0 ; virtual S32 getWidth(S32 discard_level = -1) const = 0 ; diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index a7946cacf5..bbaf908d2e 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -95,8 +95,7 @@ LLButton::Params::Params() is_toggle("is_toggle", false), scale_image("scale_image", true), hover_glow_amount("hover_glow_amount"), - commit_on_return("commit_on_return", true), - picture_style("picture_style", false) + commit_on_return("commit_on_return", true) { addSynonym(is_toggle, "toggle"); held_down_delay.seconds = 0.5f; @@ -153,17 +152,9 @@ LLButton::LLButton(const LLButton::Params& p) static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0); static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>()); - //if we aren't a picture_style button set label as name if not provided - if (!p.picture_style.isProvided() || !p.picture_style) + if (!p.label_selected.isProvided()) { - if (!p.label.isProvided()) - { - mUnselectedLabel = p.name(); - } - if (!p.label_selected.isProvided()) - { - mSelectedLabel = mUnselectedLabel.getString(); - } + mSelectedLabel = mUnselectedLabel; } // Hack to make sure there is space for at least one character @@ -1100,18 +1091,3 @@ void LLButton::resetMouseDownTimer() mMouseDownTimer.stop(); mMouseDownTimer.reset(); } - - -// *TODO: Remove this function after the initial XUI XML re-export pass. -// static -void LLButton::setupParamsForExport(Params& p, LLView* parent) -{ - std::string label = p.label; - if (label.empty()) - { - //if our label is empty this is a picture style button - p.picture_style = true; - } - - LLUICtrl::setupParamsForExport(p, parent); -} diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 85580a98bf..08f289092f 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -115,8 +115,7 @@ public: // misc Optional<bool> is_toggle, scale_image, - commit_on_return, - picture_style; //if true, don't display label + commit_on_return; Optional<F32> hover_glow_amount; Optional<TimeIntervalParam> held_down_delay; @@ -247,8 +246,6 @@ protected: LLFrameTimer mMouseDownTimer; - // If the label is empty, set the picture_style attribute - static void setupParamsForExport(Params& p, LLView* parent); private: void drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size); void resetMouseDownTimer(); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 99aebbcb30..aac27e6562 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1832,7 +1832,6 @@ void LLFloater::buildButtons() LLButton::Params p; p.name(sButtonNames[i]); p.rect(btn_rect); - p.label(""); p.image_unselected.name(sButtonActiveImageNames[i]); // Selected, no matter if hovered or not, is "pressed" p.image_selected.name(sButtonPressedImageNames[i]); @@ -1845,6 +1844,7 @@ void LLFloater::buildButtons() p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT); p.tool_tip(sButtonToolTips[i]); p.scale_image(true); + p.chrome(true); LLButton* buttonp = LLUICtrlFactory::create<LLButton>(p); addChild(buttonp); diff --git a/indra/llui/llflyoutbutton.cpp b/indra/llui/llflyoutbutton.cpp index 3483bac782..abb0b869eb 100644 --- a/indra/llui/llflyoutbutton.cpp +++ b/indra/llui/llflyoutbutton.cpp @@ -48,6 +48,7 @@ LLFlyoutButton::LLFlyoutButton(const Params& p) // Text label button LLButton::Params bp(p.action_button); bp.name(p.label); + bp.label(p.label); bp.rect.left(0).bottom(0).width(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH).height(getRect().getHeight()); bp.click_callback.function(boost::bind(&LLFlyoutButton::onActionButtonClick, this, _2)); bp.follows.flags(FOLLOWS_ALL); diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp index 058b6ae178..43c21e250c 100644 --- a/indra/llui/lllocalcliprect.cpp +++ b/indra/llui/lllocalcliprect.cpp @@ -113,6 +113,9 @@ void LLScreenClipRect::updateScissorRegion() { if (sClipRectStack.empty()) return; + // finish any deferred calls in the old clipping region + gGL.flush(); + LLRect rect = sClipRectStack.top(); stop_glerror(); S32 x,y,w,h; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 91e7e46195..c6a38c7ca7 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -118,6 +118,7 @@ const F32 PIE_SHRINK_TIME = 0.2f; // time of transition between unbounded and bo const F32 ACTIVATE_HIGHLIGHT_TIME = 0.3f; +static MenuRegistry::Register<LLMenuItemGL> register_menu_item("menu_item"); static MenuRegistry::Register<LLMenuItemSeparatorGL> register_separator("menu_item_separator"); static MenuRegistry::Register<LLMenuItemCallGL> register_menu_item_call("menu_item_call"); static MenuRegistry::Register<LLMenuItemCheckGL> register_menu_item_check("menu_item_check"); @@ -132,6 +133,28 @@ static LLDefaultChildRegistry::Register<LLMenuGL> register_menu_default("menu"); ///============================================================================ /// Class LLMenuItemGL ///============================================================================ + +LLMenuItemGL::Params::Params() +: shortcut("shortcut"), + jump_key("jump_key", KEY_NONE), + use_mac_ctrl("use_mac_ctrl", false), + rect("rect"), + left("left"), + top("top"), + right("right"), + bottom("bottom"), + width("width"), + height("height"), + bottom_delta("bottom_delta"), + left_delta("left_delta"), + enabled_color("enabled_color"), + disabled_color("disabled_color"), + highlight_bg_color("highlight_bg_color"), + highlight_fg_color("highlight_fg_color") +{ + mouse_opaque = true; +} + // Default constructor LLMenuItemGL::LLMenuItemGL(const LLMenuItemGL::Params& p) : LLUICtrl(p), @@ -459,12 +482,6 @@ void LLMenuItemGL::draw( void ) LLColor4 color; - LLFontGL::ShadowType shadow_style = LLFontGL::NO_SHADOW; - if (getEnabled() && !mDrawTextDisabled ) - { - shadow_style = LLFontGL::DROP_SHADOW_SOFT; - } - if ( getEnabled() && getHighlight() ) { color = mHighlightForeground.get(); @@ -482,26 +499,26 @@ void LLMenuItemGL::draw( void ) if (mBriefItem) { mFont->render( mLabel, 0, BRIEF_PAD_PIXELS / 2, 0, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, shadow_style ); + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL); } else { if( !mDrawBoolLabel.empty() ) { mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, shadow_style, S32_MAX, S32_MAX, NULL, FALSE ); + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, shadow_style, S32_MAX, S32_MAX, NULL, FALSE ); + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); if( !mDrawAccelLabel.empty() ) { mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, - LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, shadow_style, S32_MAX, S32_MAX, NULL, FALSE ); + LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } if( !mDrawBranchLabel.empty() ) { mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, - LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, shadow_style, S32_MAX, S32_MAX, NULL, FALSE ); + LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } } @@ -1460,12 +1477,6 @@ void LLMenuItemBranchDownGL::draw( void ) gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 ); } - LLFontGL::ShadowType shadow_style = LLFontGL::NO_SHADOW; - if (getEnabled() && !getDrawTextDisabled() ) - { - shadow_style = LLFontGL::DROP_SHADOW_SOFT; - } - LLColor4 color; if (getHighlight()) { @@ -1480,7 +1491,7 @@ void LLMenuItemBranchDownGL::draw( void ) color = mDisabledColor.get(); } getFont()->render( mLabel.getWString(), 0, (F32)getRect().getWidth() / 2.f, (F32)LABEL_BOTTOM_PAD_PIXELS, color, - LLFontGL::HCENTER, LLFontGL::BOTTOM, LLFontGL::NORMAL, shadow_style ); + LLFontGL::HCENTER, LLFontGL::BOTTOM, LLFontGL::NORMAL); // underline navigation key only when keyboard navigation has been initiated @@ -1555,8 +1566,6 @@ LLMenuScrollItem::LLMenuScrollItem(const Params& p) } LLButton::Params bparams; - bparams.label(""); - bparams.label_selected(""); bparams.mouse_opaque(true); bparams.scale_image(false); bparams.click_callback(p.scroll_callback); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 09d9e407c7..dc8ed3b3fd 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -79,26 +79,7 @@ public: highlight_fg_color; - Params() - : shortcut("shortcut"), - jump_key("jump_key", KEY_NONE), - use_mac_ctrl("use_mac_ctrl", false), - rect("rect"), - left("left"), - top("top"), - right("right"), - bottom("bottom"), - width("width"), - height("height"), - bottom_delta("bottom_delta"), - left_delta("left_delta"), - enabled_color("enabled_color"), - disabled_color("disabled_color"), - highlight_bg_color("highlight_bg_color"), - highlight_fg_color("highlight_fg_color") - { - mouse_opaque = true; - } + Params(); }; protected: diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index cde4c75518..b67f753d39 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -155,7 +155,7 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) mTotalTabWidth(0), mTabPosition(p.tab_position), mFontHalign(p.font_halign), - mFont(p.font.isProvided() ? p.font() : (mIsVertical ? LLFontGL::getFontSansSerif() : LLFontGL::getFontSansSerifSmall())), + mFont(p.font), mFirstTabParams(p.first_tab), mMiddleTabParams(p.middle_tab), mLastTabParams(p.last_tab) @@ -927,7 +927,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) textbox = LLUICtrlFactory::create<LLTextBox> (params); LLButton::Params p; - p.name(""); + p.name("placeholder"); btn = LLUICtrlFactory::create<LLButton>(p); } else @@ -946,6 +946,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) p.scale_image(true); p.font_halign = mFontHalign; p.tab_stop(false); + p.label_shadow(false); if (indent) { p.pad_left(indent); @@ -965,6 +966,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) p.image_unselected(tab_img); p.image_selected(tab_selected_img); p.tab_stop(false); + p.label_shadow(false); // Try to squeeze in a bit more text p.pad_left(4); p.pad_right(2); @@ -986,7 +988,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) p.follows.flags = p.follows.flags() | FOLLOWS_BOTTOM; } - btn = LLUICtrlFactory::create<LLButton>(p); +++ btn = LLUICtrlFactory::create<LLButton>(p); } } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 9a26f0b472..97ba691341 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1108,7 +1108,7 @@ void LLTextBase::reflow(S32 start_index) S32_MAX); S32 segment_width, segment_height; - segment->getDimensions(seg_offset, character_count, segment_width, segment_height); + bool force_newline = segment->getDimensions(seg_offset, character_count, segment_width, segment_height); // grow line height as necessary based on reported height of this segment line_height = llmax(line_height, segment_height); remaining_pixels -= segment_width; @@ -1153,6 +1153,18 @@ void LLTextBase::reflow(S32 start_index) else { // subtract pixels used and increment segment + if (force_newline) + { + mLineInfoList.push_back(line_info( + line_start_index, + last_segment_char_on_line, + line_rect, + line_count)); + line_start_index = segment->getStart() + seg_offset; + cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels; + line_height = 0; + remaining_pixels = text_width; + } ++seg_iter; seg_offset = 0; } @@ -1419,6 +1431,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url)); registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url)); registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url)); + registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url)); registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url)); registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url)); @@ -1450,9 +1463,7 @@ void LLTextBase::setText(const LLStringExplicit &utf8str) appendText(text, false); - //resetDirty(); onValueChange(0, getLength()); - needsReflow(); } //virtual @@ -1630,8 +1641,6 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen insertStringNoUndo(getLength(), wide_text, &segments); } - needsReflow(); - // Set the cursor and scroll position if( selection_start != selection_end ) { @@ -2115,7 +2124,7 @@ LLRect LLTextBase::getVisibleDocumentRect() const LLRect doc_rect = mDocumentView->getLocalRect(); doc_rect.mLeft -= mDocumentView->getRect().mLeft; // adjust for height of text above widget baseline - doc_rect.mBottom = llmin(0, doc_rect.getHeight() - mTextRect.getHeight()); + doc_rect.mBottom = doc_rect.getHeight() - mTextRect.getHeight(); return doc_rect; } } @@ -2127,7 +2136,7 @@ LLRect LLTextBase::getVisibleDocumentRect() const LLTextSegment::~LLTextSegment() {} -void LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { width = 0; height = 0; } +bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { width = 0; height = 0; return false;} S32 LLTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { return 0; } S32 LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { return 0; } void LLTextSegment::updateLayout(const LLTextBase& editor) {} @@ -2355,12 +2364,13 @@ void LLNormalTextSegment::setToolTip(const std::string& tooltip) mTooltip = tooltip; } -void LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { LLWString text = mEditor.getWText(); height = mFontHeight; width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); + return num_chars >= 1 && text[mStart + num_chars - 1] == '\n'; } S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const @@ -2407,8 +2417,9 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin // but not both S32 last_char_in_run = mStart + segment_offset + num_chars; // check length first to avoid indexing off end of string - if (last_char_in_run >= mEditor.getLength() - || text[last_char_in_run] == '\n') + if (last_char_in_run < mEnd + && (last_char_in_run >= mEditor.getLength() + || text[last_char_in_run] == '\n')) { num_chars++; } @@ -2447,7 +2458,7 @@ LLInlineViewSegment::~LLInlineViewSegment() mView->die(); } -void LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { if (first_char == 0 && num_chars == 0) { @@ -2461,6 +2472,8 @@ void LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt width = mLeftPad + mRightPad + mView->getRect().getWidth(); height = mBottomPad + mTopPad + mView->getRect().getHeight(); } + + return false; } S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 4cca522a23..8cae8fde22 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -370,7 +370,7 @@ public: LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){}; virtual ~LLTextSegment(); - virtual void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; + virtual bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; virtual S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; virtual void updateLayout(const class LLTextBase& editor); @@ -421,7 +421,7 @@ public: LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor ); LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE); - /*virtual*/ void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; + /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const; /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); @@ -474,7 +474,7 @@ public: LLInlineViewSegment(const Params& p, S32 start, S32 end); ~LLInlineViewSegment(); - /*virtual*/ void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; + /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; /*virtual*/ void updateLayout(const class LLTextBase& editor); /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 20bceb4675..00f1d833a3 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -45,6 +45,9 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p) mClickedCallback(NULL) {} +LLTextBox::~LLTextBox() +{} + BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = LLTextBase::handleMouseDown(x, y, mask); @@ -97,6 +100,18 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask) return handled; } +BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLTextBase::handleHover(x, y, mask); + if (!handled && mClickedCallback) + { + // Clickable text boxes change the cursor to a hand + LLUI::getWindow()->setCursor(UI_CURSOR_HAND); + return TRUE; + } + return handled; +} + void LLTextBox::setText(const LLStringExplicit& text) { // does string argument insertion @@ -105,6 +120,11 @@ void LLTextBox::setText(const LLStringExplicit& text) LLTextBase::setText(mText.getString()); } +void LLTextBox::setClickedCallback( boost::function<void (void*)> cb, void* userdata /*= NULL */ ) +{ + mClickedCallback = boost::bind(cb, userdata); +} + S32 LLTextBox::getTextPixelWidth() { return getContentsRect().getWidth(); @@ -115,6 +135,12 @@ S32 LLTextBox::getTextPixelHeight() return getContentsRect().getHeight(); } + +LLSD LLTextBox::getValue() const +{ + return LLSD(getText()); +} + BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text ) { mText.setArg(key, text); diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index da0bcbe972..73f8a7c299 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -33,8 +33,6 @@ #ifndef LL_LLTEXTBOX_H #define LL_LLTEXTBOX_H -#include "v4color.h" -#include "llstring.h" #include "lluistring.h" #include "lltextbase.h" @@ -54,28 +52,25 @@ protected: friend class LLUICtrlFactory; public: - virtual ~LLTextBox() {} + virtual ~LLTextBox(); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ void setText( const LLStringExplicit& text ); + /*virtual*/ void setText( const LLStringExplicit& text ); void setRightAlign() { mHAlign = LLFontGL::RIGHT; } void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } - void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ){ mClickedCallback = boost::bind(cb, userdata); } // mouse down and up within button - - //const LLFontGL* getFont() const { return mDefaultFont; } - //void setFont(const LLFontGL* font) { mDefaultFont = font; } + void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ); void reshapeToFitText(); - //const std::string& getText() const { return mText.getString(); } S32 getTextPixelWidth(); S32 getTextPixelHeight(); - virtual LLSD getValue() const { return LLSD(getText()); } - virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); + /*virtual*/ LLSD getValue() const; + /*virtual*/ BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); protected: void onUrlLabelUpdated(const std::string &url, const std::string &label); diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 23c87c7522..4bc9a9c042 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -198,6 +198,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) { LLButton::Params icon_params; icon_params.name = "tooltip_info"; + icon_params.label(""); // provid label but set to empty so name does not overwrite it -angela LLRect icon_rect; LLUIImage* imagep = p.image; TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16); @@ -206,6 +207,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) //icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM; icon_params.image_unselected(imagep); icon_params.image_selected(imagep); + icon_params.scale_image(true); icon_params.flash_color(icon_params.highlight_color()); mInfoButton = LLUICtrlFactory::create<LLButton>(icon_params); @@ -223,6 +225,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) { LLButton::Params p_button; p_button.name(std::string("play_media")); + p_button.label(""); // provid label but set to empty so name does not overwrite it -angela TOOLTIP_PLAYBUTTON_SIZE = 16; LLRect button_rect; button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE); @@ -247,6 +250,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) { LLButton::Params p_w_button; p_w_button.name(std::string("home_page")); + p_w_button.label(""); // provid label but set to empty so name does not overwrite it -angela TOOLTIP_PLAYBUTTON_SIZE = 16; LLRect button_rect; button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE); diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index f3401f91f7..679db5e39b 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -121,6 +121,18 @@ void LLUrlAction::teleportToLocation(std::string url) } } +void LLUrlAction::showLocationOnMap(std::string url) +{ + LLUrlMatch match; + if (LLUrlRegistry::instance().findUrl(url, match)) + { + if (! match.getLocation().empty()) + { + executeSLURL("secondlife:///app/worldmap/" + match.getLocation()); + } + } +} + void LLUrlAction::copyURLToClipboard(std::string url) { LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(url)); diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index 6b9d565b44..4830cf27ef 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -67,6 +67,9 @@ public: /// if the Url specifies an SL location, teleport there static void teleportToLocation(std::string url); + /// if the Url specifies an SL location, show it on a map + static void showLocationOnMap(std::string url); + /// perform the appropriate action for left-clicking on a Url static void clickAction(std::string url); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 52e4229fb4..dae4b512d1 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -145,6 +145,18 @@ void LLUrlEntryBase::callObservers(const std::string &id, const std::string &lab } } +static std::string getStringAfterToken(const std::string str, const std::string token) +{ + size_t pos = str.find(token); + if (pos == std::string::npos) + { + return ""; + } + + pos += token.size(); + return str.substr(pos, str.size() - pos); +} + // // LLUrlEntryHTTP Describes generic http: and https: Urls // @@ -154,7 +166,6 @@ LLUrlEntryHTTP::LLUrlEntryHTTP() boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_http.xml"; mTooltip = LLTrans::getString("TooltipHttpUrl"); - //mIcon = "gear.tga"; } std::string LLUrlEntryHTTP::getLabel(const std::string &url, const LLUrlLabelCallback &cb) @@ -390,7 +401,7 @@ std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelC } // -// LLUrlEntryPlace Describes secondlife:///<location> URLs +// LLUrlEntryPlace Describes secondlife://<location> URLs // LLUrlEntryPlace::LLUrlEntryPlace() { @@ -433,15 +444,7 @@ std::string LLUrlEntryPlace::getLabel(const std::string &url, const LLUrlLabelCa std::string LLUrlEntryPlace::getLocation(const std::string &url) const { // return the part of the Url after secondlife:// part - const std::string search_string = "://"; - size_t pos = url.find(search_string); - if (pos == std::string::npos) - { - return ""; - } - - pos += search_string.size(); - return url.substr(pos, url.size() - pos); + return ::getStringAfterToken(url, "://"); } // @@ -468,6 +471,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe LLURI uri(url); LLSD path_array = uri.pathArray(); S32 path_parts = path_array.size(); + const std::string label = LLTrans::getString("SLurlLabelTeleport"); if (path_parts == 6) { // handle teleport url with (X,Y,Z) coordinates @@ -475,7 +479,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe std::string x = path_array[path_parts-3]; std::string y = path_array[path_parts-2]; std::string z = path_array[path_parts-1]; - return "Teleport to " + location + " (" + x + "," + y + "," + z + ")"; + return label + " " + location + " (" + x + "," + y + "," + z + ")"; } else if (path_parts == 5) { @@ -483,20 +487,20 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe std::string location = unescapeUrl(path_array[path_parts-3]); std::string x = path_array[path_parts-2]; std::string y = path_array[path_parts-1]; - return "Teleport to " + location + " (" + x + "," + y + ")"; + return label + " " + location + " (" + x + "," + y + ")"; } else if (path_parts == 4) { // handle teleport url with (X) coordinate only std::string location = unescapeUrl(path_array[path_parts-2]); std::string x = path_array[path_parts-1]; - return "Teleport to " + location + " (" + x + ")"; + return label + " " + location + " (" + x + ")"; } else if (path_parts == 3) { // handle teleport url with no coordinates std::string location = unescapeUrl(path_array[path_parts-1]); - return "Teleport to " + location; + return label + " " + location; } return url; @@ -505,15 +509,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe std::string LLUrlEntryTeleport::getLocation(const std::string &url) const { // return the part of the Url after ///app/teleport - const std::string search_string = "teleport"; - size_t pos = url.find(search_string); - if (pos == std::string::npos) - { - return ""; - } - - pos += search_string.size() + 1; - return url.substr(pos, url.size() - pos); + return ::getStringAfterToken(url, "app/teleport/"); } /// @@ -599,3 +595,43 @@ std::string LLUrlEntrySLLabel::getUrl(const std::string &string) return getUrlFromWikiLink(string); } +// +// LLUrlEntryWorldMap Describes secondlife:///<location> URLs +// +LLUrlEntryWorldMap::LLUrlEntryWorldMap() +{ + mPattern = boost::regex("secondlife:///app/worldmap/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*", + boost::regex::perl|boost::regex::icase); + mMenuName = "menu_url_map.xml"; + mTooltip = LLTrans::getString("TooltipMapUrl"); +} + +std::string LLUrlEntryWorldMap::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ + // + // we handle SLURLs in the following formats: + // - secondlife:///app/worldmap/PLACE/X/Y/Z + // - secondlife:///app/worldmap/PLACE/X/Y + // - secondlife:///app/worldmap/PLACE/X + // + LLURI uri(url); + LLSD path_array = uri.pathArray(); + S32 path_parts = path_array.size(); + if (path_parts < 3) + { + return url; + } + + const std::string label = LLTrans::getString("SLurlLabelShowOnMap"); + std::string location = path_array[2]; + std::string x = (path_parts > 3) ? path_array[3] : "128"; + std::string y = (path_parts > 4) ? path_array[4] : "128"; + std::string z = (path_parts > 5) ? path_array[5] : "0"; + return label + " " + location + " (" + x + "," + y + "," + z + ")"; +} + +std::string LLUrlEntryWorldMap::getLocation(const std::string &url) const +{ + // return the part of the Url after secondlife:///app/worldmap/ part + return ::getStringAfterToken(url, "app/worldmap/"); +} diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index afb2fdcde9..4507572b1e 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -186,7 +186,7 @@ public: /// /// LLUrlEntryPlace Describes a Second Life location Url, e.g., -/// secondlife:///Ahern/50/50/50 +/// secondlife://Ahern/50/50/50 /// class LLUrlEntryPlace : public LLUrlEntryBase { @@ -243,4 +243,16 @@ public: /*virtual*/ std::string getUrl(const std::string &string); }; +/// +/// LLUrlEntryWorldMap Describes a Second Life worldmap Url, e.g., +/// secondlife:///app/worldmap/Ahern/50/50/50 +/// +class LLUrlEntryWorldMap : public LLUrlEntryBase +{ +public: + LLUrlEntryWorldMap(); + /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + /*virtual*/ std::string getLocation(const std::string &url) const; +}; + #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 249c7320d6..60275b60bc 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -51,6 +51,7 @@ LLUrlRegistry::LLUrlRegistry() registerUrl(new LLUrlEntryGroup()); registerUrl(new LLUrlEntryParcel()); registerUrl(new LLUrlEntryTeleport()); + registerUrl(new LLUrlEntryWorldMap()); registerUrl(new LLUrlEntryObjectIM()); registerUrl(new LLUrlEntryPlace()); registerUrl(new LLUrlEntrySL()); diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 781321e5e4..c0c6e592d5 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -580,7 +580,7 @@ void LLDir::setLindenUserDir(const std::string &first, const std::string &last) } else { - llerrs << "Invalid name for LLDir::setLindenUserDir" << llendl; + llerrs << "Invalid name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl; } dumpCurrentDirectories(); diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp index 704e1ab142..e85cc437f4 100644 --- a/indra/llvfs/lllfsthread.cpp +++ b/indra/llvfs/lllfsthread.cpp @@ -189,7 +189,7 @@ bool LLLFSThread::Request::processRequest() { llassert(mOffset >= 0); LLAPRFile infile ; - infile.open(mThread->getLocalAPRFilePool(), mFileName, LL_APR_RB); + infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool()); if (!infile.getFileHandle()) { llwarns << "LLLFS: Unable to read file: " << mFileName << llendl; @@ -213,7 +213,7 @@ bool LLLFSThread::Request::processRequest() if (mOffset < 0) flags |= APR_APPEND; LLAPRFile outfile ; - outfile.open(mThread->getLocalAPRFilePool(), mFileName, flags); + outfile.open(mFileName, flags, mThread->getLocalAPRFilePool()); if (!outfile.getFileHandle()) { llwarns << "LLLFS: Unable to write file: " << mFileName << llendl; diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 9f03c8f695..e671fc8a83 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -418,7 +418,6 @@ static int x11_detect_VRAM_kb() BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync) { //bool glneedsinit = false; -// const char *gllibname = null; llinfos << "createContext, fullscreen=" << fullscreen << " size=" << width << "x" << height << llendl; diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index fb6d5b2905..de927de1cd 100644 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -1,1098 +1,1098 @@ -/**
- * @file media_plugin_quicktime.cpp
- * @brief QuickTime plugin for LLMedia API plugin system
- *
- * $LicenseInfo:firstyear=2008&license=viewergpl$
- *
- * Copyright (c) 2008, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llgl.h"
-
-#include "llplugininstance.h"
-#include "llpluginmessage.h"
-#include "llpluginmessageclasses.h"
-#include "media_plugin_base.h"
-
-#if LL_QUICKTIME_ENABLED
-
-#if defined(LL_DARWIN)
- #include <QuickTime/QuickTime.h>
-#elif defined(LL_WINDOWS)
- #include "MacTypes.h"
- #include "QTML.h"
- #include "Movies.h"
- #include "QDoffscreen.h"
- #include "FixMath.h"
- #include "QTLoadLibraryUtils.h"
-#endif
-
-// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
-////////////////////////////////////////////////////////////////////////////////
-//
-class MediaPluginQuickTime : public MediaPluginBase
-{
-public:
- MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
- ~MediaPluginQuickTime();
-
- /* virtual */ void receiveMessage(const char *message_string);
-
-private:
-
- int mNaturalWidth;
- int mNaturalHeight;
- Movie mMovieHandle;
- GWorldPtr mGWorldHandle;
- ComponentInstance mMovieController;
- int mCurVolume;
- bool mMediaSizeChanging;
- bool mIsLooping;
- std::string mMovieTitle;
- bool mReceivedTitle;
- const int mMinWidth;
- const int mMaxWidth;
- const int mMinHeight;
- const int mMaxHeight;
- F64 mPlayRate;
- std::string mNavigateURL;
-
- enum ECommand {
- COMMAND_NONE,
- COMMAND_STOP,
- COMMAND_PLAY,
- COMMAND_FAST_FORWARD,
- COMMAND_FAST_REWIND,
- COMMAND_PAUSE,
- COMMAND_SEEK,
- };
- ECommand mCommand;
-
- // Override this to add current time and duration to the message
- /*virtual*/ void setDirty(int left, int top, int right, int bottom)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
-
- message.setValueS32("left", left);
- message.setValueS32("top", top);
- message.setValueS32("right", right);
- message.setValueS32("bottom", bottom);
-
- if(mMovieHandle)
- {
- message.setValueReal("current_time", getCurrentTime());
- message.setValueReal("duration", getDuration());
- message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle)));
- }
-
- sendMessage(message);
- }
-
-
- static Rect rectFromSize(int width, int height)
- {
- Rect result;
-
-
- result.left = 0;
- result.top = 0;
- result.right = width;
- result.bottom = height;
-
- return result;
- }
-
- Fixed getPlayRate(void)
- {
- Fixed result;
- if(mPlayRate == 0.0f)
- {
- // Default to the movie's preferred rate
- result = GetMoviePreferredRate(mMovieHandle);
- if(result == 0)
- {
- // Don't return a 0 play rate, ever.
- std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl;
- result = X2Fix(1.0f);
- }
- }
- else
- {
- result = X2Fix(mPlayRate);
- }
-
- return result;
- }
-
- void load( const std::string url )
- {
-
- if ( url.empty() )
- return;
-
- // Stop and unload any existing movie before starting another one.
- unload();
-
- setStatus(STATUS_LOADING);
-
- //In case std::string::c_str() makes a copy of the url data,
- //make sure there is memory to hold it before allocating memory for handle.
- //if fails, NewHandleClear(...) should return NULL.
- const char* url_string = url.c_str() ;
- Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) );
-
- if ( NULL == handle || noErr != MemError() || NULL == *handle )
- {
- setStatus(STATUS_ERROR);
- return;
- }
-
- BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) );
-
- OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType );
- DisposeHandle( handle );
- if ( noErr != err )
- {
- setStatus(STATUS_ERROR);
- return;
- };
-
- mNavigateURL = url;
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
- message.setValue("uri", mNavigateURL);
- sendMessage(message);
-
- // do pre-roll actions (typically fired for streaming movies but not always)
- PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this );
-
- Rect movie_rect = rectFromSize(mWidth, mHeight);
-
- // make a new movie controller
- mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie );
-
- // movie controller
- MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this );
-
- SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize );
-
- // function that gets called when a frame is drawn
- SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this );
-
- setStatus(STATUS_LOADED);
-
- sizeChanged();
- };
-
- bool unload()
- {
- // new movie and have to get title again
- mReceivedTitle = false;
-
- if ( mMovieHandle )
- {
- StopMovie( mMovieHandle );
- if ( mMovieController )
- {
- MCMovieChanged( mMovieController, mMovieHandle );
- };
- };
-
- if ( mMovieController )
- {
- MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this );
- DisposeMovieController( mMovieController );
- mMovieController = NULL;
- };
-
- if ( mMovieHandle )
- {
- SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this );
- DisposeMovie( mMovieHandle );
- mMovieHandle = NULL;
- };
-
- if ( mGWorldHandle )
- {
- DisposeGWorld( mGWorldHandle );
- mGWorldHandle = NULL;
- };
-
- setStatus(STATUS_NONE);
-
- return true;
- }
-
- bool navigateTo( const std::string url )
- {
- unload();
- load( url );
-
- return true;
- };
-
- bool sizeChanged()
- {
- if ( ! mMovieHandle )
- return false;
-
- // Check to see whether the movie's natural size has updated
- {
- int width, height;
- getMovieNaturalSize(&width, &height);
- if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight)))
- {
- mNaturalWidth = width;
- mNaturalHeight = height;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
- message.setValue("name", mTextureSegmentName);
- message.setValueS32("width", width);
- message.setValueS32("height", height);
- sendMessage(message);
- //std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl;
- }
- }
-
- // sanitize destination size
- Rect dest_rect = rectFromSize(mWidth, mHeight);
-
- // media depth won't change
- int depth_bits = mDepth * 8;
- long rowbytes = mDepth * mTextureWidth;
-
- GWorldPtr old_gworld_handle = mGWorldHandle;
-
- if(mPixels != NULL)
- {
- // We have pixels. Set up a GWorld pointing at the texture.
- OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
- if ( noErr != result )
- {
- // TODO: unrecoverable?? throw exception? return something?
- return false;
- }
- }
- else
- {
- // We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally.
- Rect tempRect = rectFromSize(1, 1);
- OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
- if ( noErr != result )
- {
- // TODO: unrecoverable?? throw exception? return something?
- return false;
- }
- }
-
- SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) );
-
- // If the GWorld was already set up, delete it.
- if(old_gworld_handle != NULL)
- {
- DisposeGWorld( old_gworld_handle );
- }
-
- // Set up the movie display matrix
- {
- // scale movie to fit rect and invert vertically to match opengl image format
- MatrixRecord transform;
- SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix
- double scaleX = (double) mWidth / mNaturalWidth;
- double scaleY = -1.0 * (double) mHeight / mNaturalHeight;
- double centerX = mWidth / 2.0;
- double centerY = mHeight / 2.0;
- ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) );
- SetMovieMatrix( mMovieHandle, &transform );
- }
-
- // update movie controller
- if ( mMovieController )
- {
- MCSetControllerPort( mMovieController, mGWorldHandle );
- MCPositionController( mMovieController, &dest_rect, &dest_rect,
- mcTopLeftMovie | mcPositionDontInvalidate );
- MCMovieChanged( mMovieController, mMovieHandle );
- }
-
-
- // Emit event with size change so the calling app knows about it too
- // TODO:
- //LLMediaEvent event( this );
- //mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event );
-
- return true;
- }
- static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref )
- {
- Boolean result = false;
-
- MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
-
- switch( action )
- {
- // handle window resizing
- case mcActionControllerSizeChanged:
- // Ensure that the movie draws correctly at the new size
- self->sizeChanged();
- break;
-
- // Block any movie controller actions that open URLs.
- case mcActionLinkToURL:
- case mcActionGetNextURL:
- case mcActionLinkToURLExtended:
- // Prevent the movie controller from handling the message
- result = true;
- break;
-
- default:
- break;
- };
-
- return result;
- };
-
- static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref )
- {
- MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
-
- // IMPORTANT: typically, a consumer who is observing this event will set a flag
- // when this event is fired then render later. Be aware that the media stream
- // can change during this period - dimensions, depth, format etc.
- //LLMediaEvent event( self );
-// self->updateQuickTime();
- // TODO ^^^
-
-
- if ( self->mWidth > 0 && self->mHeight > 0 )
- self->setDirty( 0, 0, self->mWidth, self->mHeight );
-
- return noErr;
- };
-
- static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref )
- {
- MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
-
- // TODO:
- //LLMediaEvent event( self );
- //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event );
-
- // Send a "navigate complete" event.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
- message.setValue("uri", self->mNavigateURL);
- message.setValueS32("result_code", 200);
- message.setValue("result_string", "OK");
- self->sendMessage(message);
- };
-
-
- void rewind()
- {
- GoToBeginningOfMovie( mMovieHandle );
- MCMovieChanged( mMovieController, mMovieHandle );
- };
-
- bool processState()
- {
- if ( mCommand == COMMAND_PLAY )
- {
- if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE )
- {
- long state = GetMovieLoadState( mMovieHandle );
-
- if ( state >= kMovieLoadStatePlaythroughOK )
- {
- // if the movie is at the end (generally because it reached it naturally)
- // and we play is requested, jump back to the start of the movie.
- // note: this is different from having loop flag set.
- if ( IsMovieDone( mMovieHandle ) )
- {
- Fixed rate = X2Fix( 0.0 );
- MCDoAction( mMovieController, mcActionPlay, (void*)rate );
- rewind();
- };
-
- MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
- MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
- setStatus(STATUS_PLAYING);
- mCommand = COMMAND_NONE;
- };
- };
- }
- else
- if ( mCommand == COMMAND_STOP )
- {
- if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE )
- {
- if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
- {
- Fixed rate = X2Fix( 0.0 );
- MCDoAction( mMovieController, mcActionPlay, (void*)rate );
- rewind();
-
- setStatus(STATUS_LOADED);
- mCommand = COMMAND_NONE;
- };
- };
- }
- else
- if ( mCommand == COMMAND_PAUSE )
- {
- if ( mStatus == STATUS_PLAYING )
- {
- if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
- {
- Fixed rate = X2Fix( 0.0 );
- MCDoAction( mMovieController, mcActionPlay, (void*)rate );
- setStatus(STATUS_PAUSED);
- mCommand = COMMAND_NONE;
- };
- };
- };
-
- return true;
- };
-
- void play(F64 rate)
- {
- mPlayRate = rate;
- mCommand = COMMAND_PLAY;
- };
-
- void stop()
- {
- mCommand = COMMAND_STOP;
- };
-
- void pause()
- {
- mCommand = COMMAND_PAUSE;
- };
-
- void getMovieNaturalSize(int *movie_width, int *movie_height)
- {
- Rect rect;
-
- GetMovieNaturalBoundsRect( mMovieHandle, &rect );
-
- int width = ( rect.right - rect.left );
- int height = ( rect.bottom - rect.top );
-
- // make sure width and height fall in valid range
- if ( width < mMinWidth )
- width = mMinWidth;
-
- if ( width > mMaxWidth )
- width = mMaxWidth;
-
- if ( height < mMinHeight )
- height = mMinHeight;
-
- if ( height > mMaxHeight )
- height = mMaxHeight;
-
- // return the new rect
- *movie_width = width;
- *movie_height = height;
- }
-
- void updateQuickTime(int milliseconds)
- {
- if ( ! mMovieHandle )
- return;
-
- if ( ! mMovieController )
- return;
-
- // service QuickTime
- // Calling it this way doesn't have good behavior on Windows...
-// MoviesTask( mMovieHandle, milliseconds );
- // This was the original, but I think using both MoviesTask and MCIdle is redundant. Trying with only MCIdle.
-// MoviesTask( mMovieHandle, 0 );
-
- MCIdle( mMovieController );
-
- if ( ! mGWorldHandle )
- return;
-
- if ( mMediaSizeChanging )
- return;
-
- // update state machine
- processState();
-
- // see if title arrived and if so, update member variable with contents
- checkTitle();
-
- // QT call to see if we are at the end - can't do with controller
- if ( IsMovieDone( mMovieHandle ) )
- {
- // special code for looping - need to rewind at the end of the movie
- if ( mIsLooping )
- {
- // go back to start
- rewind();
-
- if ( mMovieController )
- {
- // kick off new play
- MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
-
- // set the volume
- MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
- };
- }
- else
- {
- if(mStatus == STATUS_PLAYING)
- {
- setStatus(STATUS_DONE);
- }
- }
- }
-
- };
-
- int getDataWidth() const
- {
- if ( mGWorldHandle )
- {
- int depth = mDepth;
-
- if (depth < 1)
- depth = 1;
-
- // ALWAYS use the row bytes from the PixMap if we have a GWorld because
- // sometimes it's not the same as mMediaDepth * mMediaWidth !
- PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle );
- return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth;
- }
- else
- {
- // TODO : return LLMediaImplCommon::getaDataWidth();
- return 0;
- }
- };
-
- void seek( F64 time )
- {
- if ( mMovieController )
- {
- TimeRecord when;
- when.scale = GetMovieTimeScale( mMovieHandle );
- when.base = 0;
-
- // 'time' is in (floating point) seconds. The timebase time will be in 'units', where
- // there are 'scale' units per second.
- SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) );
-
- when.value.hi = ( SInt32 )( raw_time >> 32 );
- when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) );
-
- MCDoAction( mMovieController, mcActionGoToTime, &when );
- };
- };
-
- F64 getLoadedDuration()
- {
- TimeValue duration;
- if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr)
- {
- // If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie.
- duration = GetMovieDuration( mMovieHandle );
- }
- TimeValue scale = GetMovieTimeScale( mMovieHandle );
-
- return (F64)duration / (F64)scale;
- };
-
- F64 getDuration()
- {
- TimeValue duration = GetMovieDuration( mMovieHandle );
- TimeValue scale = GetMovieTimeScale( mMovieHandle );
-
- return (F64)duration / (F64)scale;
- };
-
- F64 getCurrentTime()
- {
- TimeValue curr_time = GetMovieTime( mMovieHandle, 0 );
- TimeValue scale = GetMovieTimeScale( mMovieHandle );
-
- return (F64)curr_time / (F64)scale;
- };
-
- void setVolume( F64 volume )
- {
- mCurVolume = (short)(volume * ( double ) 0x100 );
-
- if ( mMovieController )
- {
- MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
- };
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void update(int milliseconds = 0)
- {
- updateQuickTime(milliseconds);
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void mouseDown( int x, int y )
- {
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void mouseUp( int x, int y )
- {
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void mouseMove( int x, int y )
- {
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void keyPress( unsigned char key )
- {
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- // Grab movie title into mMovieTitle - should be called repeatedly
- // until it returns true since movie title takes a while to become
- // available.
- const bool getMovieTitle()
- {
- // grab meta data from movie
- QTMetaDataRef media_data_ref;
- OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref );
- if ( noErr != result )
- return false;
-
- // look up "Display Name" in meta data
- OSType meta_data_key = kQTMetaDataCommonKeyDisplayName;
- QTMetaDataItem item = kQTMetaDataItemUninitialized;
- result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard,
- 0, kQTMetaDataKeyFormatCommon,
- (const UInt8 *)&meta_data_key,
- sizeof( meta_data_key ), &item );
- if ( noErr != result )
- return false;
-
- // find the size of the title
- ByteCount size;
- result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size );
- if ( noErr != result || size <= 0 )
- return false;
-
- // allocate some space and grab it
- UInt8* item_data = new UInt8( size );
- memset( item_data, 0, size * sizeof( UInt8* ) );
- result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
- if ( noErr != result )
- return false;
-
- // save it
- mMovieTitle = std::string( (char* )item_data );
-
- // clean up
- delete [] item_data;
-
- return true;
- };
-
- // called regularly to see if title changed
- void checkTitle()
- {
- // we did already receive title so keep checking
- if ( ! mReceivedTitle )
- {
- // grab title from movie meta data
- if ( getMovieTitle() )
- {
- // pass back to host application
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
- message.setValue("name", mMovieTitle );
- sendMessage( message );
-
- // stop looking once we find a title for this movie.
- // TODO: this may to be reset if movie title changes
- // during playback but this is okay for now
- mReceivedTitle = true;
- };
- };
- };
-};
-
-MediaPluginQuickTime::MediaPluginQuickTime(
- LLPluginInstance::sendMessageFunction host_send_func,
- void *host_user_data ) :
- MediaPluginBase(host_send_func, host_user_data),
- mMinWidth( 0 ),
- mMaxWidth( 2048 ),
- mMinHeight( 0 ),
- mMaxHeight( 2048 )
-{
-// std::cerr << "MediaPluginQuickTime constructor" << std::endl;
-
- mNaturalWidth = -1;
- mNaturalHeight = -1;
- mMovieHandle = 0;
- mGWorldHandle = 0;
- mMovieController = 0;
- mCurVolume = 0x99;
- mMediaSizeChanging = false;
- mIsLooping = false;
- mMovieTitle = std::string();
- mReceivedTitle = false;
- mCommand = COMMAND_NONE;
- mPlayRate = 0.0f;
- mStatus = STATUS_NONE;
-}
-
-MediaPluginQuickTime::~MediaPluginQuickTime()
-{
-// std::cerr << "MediaPluginQuickTime destructor" << std::endl;
-
- ExitMovies();
-
-#ifdef LL_WINDOWS
- TerminateQTML();
-// std::cerr << "QuickTime closing down" << std::endl;
-#endif
-}
-
-
-void MediaPluginQuickTime::receiveMessage(const char *message_string)
-{
-// std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
- LLPluginMessage message_in;
-
- if(message_in.parse(message_string) >= 0)
- {
- std::string message_class = message_in.getClass();
- std::string message_name = message_in.getName();
- if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
- {
- if(message_name == "init")
- {
- LLPluginMessage message("base", "init_response");
- LLSD versions = LLSD::emptyMap();
- versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
- versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
- // Normally a plugin would only specify one of these two subclasses, but this is a demo...
- versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
- message.setValueLLSD("versions", versions);
-
- #ifdef LL_WINDOWS
-
- // QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime
- // according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html
- // The solution presented there appears to work.
- QTLoadLibrary("qtcf.dll");
-
- // main initialization for QuickTime - only required on Windows
- OSErr result = InitializeQTML( 0L );
- if ( result != noErr )
- {
- //TODO: If no QT on Windows, this fails - respond accordingly.
- }
- else
- {
- //std::cerr << "QuickTime initialized" << std::endl;
- };
- #endif
-
- // required for both Windows and Mac
- EnterMovies();
-
- std::string plugin_version = "QuickTime media plugin, QuickTime version ";
-
- long version = 0;
- Gestalt( gestaltQuickTimeVersion, &version );
- std::ostringstream codec( "" );
- codec << std::hex << version << std::dec;
- plugin_version += codec.str();
- message.setValue("plugin_version", plugin_version);
- sendMessage(message);
-
- // Plugin gets to decide the texture parameters to use.
- message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
- #if defined(LL_WINDOWS)
- // Values for Windows
- mDepth = 3;
- message.setValueU32("format", GL_RGB);
- message.setValueU32("type", GL_UNSIGNED_BYTE);
-
- // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even.
- // Padding to a multiple of 3*32 guarantees it'll divide out properly.
- message.setValueU32("padding", 32 * 3);
- #else
- // Values for Mac
- mDepth = 4;
- message.setValueU32("format", GL_BGRA_EXT);
- #ifdef __BIG_ENDIAN__
- message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV );
- #else
- message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8);
- #endif
-
- // Pad texture width to a multiple of 32 bytes, to line up with cache lines.
- message.setValueU32("padding", 32);
- #endif
- message.setValueS32("depth", mDepth);
- message.setValueU32("internalformat", GL_RGB);
- message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
- message.setValueBoolean("allow_downsample", true);
- sendMessage(message);
- }
- else if(message_name == "idle")
- {
- // no response is necessary here.
- F64 time = message_in.getValueReal("time");
-
- // Convert time to milliseconds for update()
- update((int)(time * 1000.0f));
- }
- else if(message_name == "cleanup")
- {
- // TODO: clean up here
- }
- else if(message_name == "shm_added")
- {
- SharedSegmentInfo info;
- info.mAddress = message_in.getValuePointer("address");
- info.mSize = (size_t)message_in.getValueS32("size");
- std::string name = message_in.getValue("name");
-// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name
-// << ", size: " << info.mSize
-// << ", address: " << info.mAddress
-// << std::endl;
-
- mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
-
- }
- else if(message_name == "shm_remove")
- {
- std::string name = message_in.getValue("name");
-
-// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl;
-
- SharedSegmentMap::iterator iter = mSharedSegments.find(name);
- if(iter != mSharedSegments.end())
- {
- if(mPixels == iter->second.mAddress)
- {
- // This is the currently active pixel buffer. Make sure we stop drawing to it.
- mPixels = NULL;
- mTextureSegmentName.clear();
-
- // Make sure the movie GWorld is no longer pointed at the shared segment.
- sizeChanged();
- }
- mSharedSegments.erase(iter);
- }
- else
- {
-// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl;
- }
-
- // Send the response so it can be cleaned up.
- LLPluginMessage message("base", "shm_remove_response");
- message.setValue("name", name);
- sendMessage(message);
- }
- else
- {
-// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
- {
- if(message_name == "size_change")
- {
- std::string name = message_in.getValue("name");
- S32 width = message_in.getValueS32("width");
- S32 height = message_in.getValueS32("height");
- S32 texture_width = message_in.getValueS32("texture_width");
- S32 texture_height = message_in.getValueS32("texture_height");
-
- //std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
- message.setValue("name", name);
- message.setValueS32("width", width);
- message.setValueS32("height", height);
- message.setValueS32("texture_width", texture_width);
- message.setValueS32("texture_height", texture_height);
- sendMessage(message);
-
- if(!name.empty())
- {
- // Find the shared memory region with this name
- SharedSegmentMap::iterator iter = mSharedSegments.find(name);
- if(iter != mSharedSegments.end())
- {
-// std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl;
-// std::cerr << "%%%% texture size is " << texture_width << " by " << texture_height << std::endl;
-
- mPixels = (unsigned char*)iter->second.mAddress;
- mTextureSegmentName = name;
- mWidth = width;
- mHeight = height;
-
- mTextureWidth = texture_width;
- mTextureHeight = texture_height;
-
- mMediaSizeChanging = false;
-
- sizeChanged();
-
- update();
- };
- };
- }
- else if(message_name == "load_uri")
- {
- std::string uri = message_in.getValue("uri");
- load( uri );
- sendStatus();
- }
- else if(message_name == "mouse_event")
- {
- std::string event = message_in.getValue("event");
- S32 x = message_in.getValueS32("x");
- S32 y = message_in.getValueS32("y");
-
- if(event == "down")
- {
- mouseDown(x, y);
- }
- else if(event == "up")
- {
- mouseUp(x, y);
- }
- else if(event == "move")
- {
- mouseMove(x, y);
- };
- };
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
- {
- if(message_name == "stop")
- {
- stop();
- }
- else if(message_name == "start")
- {
- F64 rate = 0.0;
- if(message_in.hasValue("rate"))
- {
- rate = message_in.getValueReal("rate");
- }
- play(rate);
- }
- else if(message_name == "pause")
- {
- pause();
- }
- else if(message_name == "seek")
- {
- F64 time = message_in.getValueReal("time");
- seek(time);
- }
- else if(message_name == "set_loop")
- {
- bool loop = message_in.getValueBoolean("loop");
- mIsLooping = loop;
- }
- else if(message_name == "set_volume")
- {
- F64 volume = message_in.getValueReal("volume");
- setVolume(volume);
- }
- }
- else
- {
-// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl;
- };
- };
-}
-
-int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
-{
- MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data);
- *plugin_send_func = MediaPluginQuickTime::staticReceiveMessage;
- *plugin_user_data = (void*)self;
-
- return 0;
-}
-
-#else // LL_QUICKTIME_ENABLED
-
-// Stubbed-out class with constructor/destructor (necessary or windows linker
-// will just think its dead code and optimize it all out)
-class MediaPluginQuickTime : public MediaPluginBase
-{
-public:
- MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
- ~MediaPluginQuickTime();
- /* virtual */ void receiveMessage(const char *message_string);
-};
-
-MediaPluginQuickTime::MediaPluginQuickTime(
- LLPluginInstance::sendMessageFunction host_send_func,
- void *host_user_data ) :
- MediaPluginBase(host_send_func, host_user_data)
-{
- // no-op
-}
-
-MediaPluginQuickTime::~MediaPluginQuickTime()
-{
- // no-op
-}
-
-void MediaPluginQuickTime::receiveMessage(const char *message_string)
-{
- // no-op
-}
-
-// We're building without quicktime enabled. Just refuse to initialize.
-int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
-{
- return -1;
-}
-
-#endif // LL_QUICKTIME_ENABLED
+/** + * @file media_plugin_quicktime.cpp + * @brief QuickTime plugin for LLMedia API plugin system + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#if LL_QUICKTIME_ENABLED + +#if defined(LL_DARWIN) + #include <QuickTime/QuickTime.h> +#elif defined(LL_WINDOWS) + #include "MacTypes.h" + #include "QTML.h" + #include "Movies.h" + #include "QDoffscreen.h" + #include "FixMath.h" + #include "QTLoadLibraryUtils.h" +#endif + +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginQuickTime : public MediaPluginBase +{ +public: + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginQuickTime(); + + /* virtual */ void receiveMessage(const char *message_string); + +private: + + int mNaturalWidth; + int mNaturalHeight; + Movie mMovieHandle; + GWorldPtr mGWorldHandle; + ComponentInstance mMovieController; + int mCurVolume; + bool mMediaSizeChanging; + bool mIsLooping; + std::string mMovieTitle; + bool mReceivedTitle; + const int mMinWidth; + const int mMaxWidth; + const int mMinHeight; + const int mMaxHeight; + F64 mPlayRate; + std::string mNavigateURL; + + enum ECommand { + COMMAND_NONE, + COMMAND_STOP, + COMMAND_PLAY, + COMMAND_FAST_FORWARD, + COMMAND_FAST_REWIND, + COMMAND_PAUSE, + COMMAND_SEEK, + }; + ECommand mCommand; + + // Override this to add current time and duration to the message + /*virtual*/ void setDirty(int left, int top, int right, int bottom) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + + message.setValueS32("left", left); + message.setValueS32("top", top); + message.setValueS32("right", right); + message.setValueS32("bottom", bottom); + + if(mMovieHandle) + { + message.setValueReal("current_time", getCurrentTime()); + message.setValueReal("duration", getDuration()); + message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle))); + } + + sendMessage(message); + } + + + static Rect rectFromSize(int width, int height) + { + Rect result; + + + result.left = 0; + result.top = 0; + result.right = width; + result.bottom = height; + + return result; + } + + Fixed getPlayRate(void) + { + Fixed result; + if(mPlayRate == 0.0f) + { + // Default to the movie's preferred rate + result = GetMoviePreferredRate(mMovieHandle); + if(result == 0) + { + // Don't return a 0 play rate, ever. + std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl; + result = X2Fix(1.0f); + } + } + else + { + result = X2Fix(mPlayRate); + } + + return result; + } + + void load( const std::string url ) + { + + if ( url.empty() ) + return; + + // Stop and unload any existing movie before starting another one. + unload(); + + setStatus(STATUS_LOADING); + + //In case std::string::c_str() makes a copy of the url data, + //make sure there is memory to hold it before allocating memory for handle. + //if fails, NewHandleClear(...) should return NULL. + const char* url_string = url.c_str() ; + Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) ); + + if ( NULL == handle || noErr != MemError() || NULL == *handle ) + { + setStatus(STATUS_ERROR); + return; + } + + BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) ); + + OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType ); + DisposeHandle( handle ); + if ( noErr != err ) + { + setStatus(STATUS_ERROR); + return; + }; + + mNavigateURL = url; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + message.setValue("uri", mNavigateURL); + sendMessage(message); + + // do pre-roll actions (typically fired for streaming movies but not always) + PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this ); + + Rect movie_rect = rectFromSize(mWidth, mHeight); + + // make a new movie controller + mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie ); + + // movie controller + MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this ); + + SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize ); + + // function that gets called when a frame is drawn + SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this ); + + setStatus(STATUS_LOADED); + + sizeChanged(); + }; + + bool unload() + { + // new movie and have to get title again + mReceivedTitle = false; + + if ( mMovieHandle ) + { + StopMovie( mMovieHandle ); + if ( mMovieController ) + { + MCMovieChanged( mMovieController, mMovieHandle ); + }; + }; + + if ( mMovieController ) + { + MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this ); + DisposeMovieController( mMovieController ); + mMovieController = NULL; + }; + + if ( mMovieHandle ) + { + SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this ); + DisposeMovie( mMovieHandle ); + mMovieHandle = NULL; + }; + + if ( mGWorldHandle ) + { + DisposeGWorld( mGWorldHandle ); + mGWorldHandle = NULL; + }; + + setStatus(STATUS_NONE); + + return true; + } + + bool navigateTo( const std::string url ) + { + unload(); + load( url ); + + return true; + }; + + bool sizeChanged() + { + if ( ! mMovieHandle ) + return false; + + // Check to see whether the movie's natural size has updated + { + int width, height; + getMovieNaturalSize(&width, &height); + if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight))) + { + mNaturalWidth = width; + mNaturalHeight = height; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); + message.setValue("name", mTextureSegmentName); + message.setValueS32("width", width); + message.setValueS32("height", height); + sendMessage(message); + //std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl; + } + } + + // sanitize destination size + Rect dest_rect = rectFromSize(mWidth, mHeight); + + // media depth won't change + int depth_bits = mDepth * 8; + long rowbytes = mDepth * mTextureWidth; + + GWorldPtr old_gworld_handle = mGWorldHandle; + + if(mPixels != NULL) + { + // We have pixels. Set up a GWorld pointing at the texture. + OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes); + if ( noErr != result ) + { + // TODO: unrecoverable?? throw exception? return something? + return false; + } + } + else + { + // We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally. + Rect tempRect = rectFromSize(1, 1); + OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0); + if ( noErr != result ) + { + // TODO: unrecoverable?? throw exception? return something? + return false; + } + } + + SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) ); + + // If the GWorld was already set up, delete it. + if(old_gworld_handle != NULL) + { + DisposeGWorld( old_gworld_handle ); + } + + // Set up the movie display matrix + { + // scale movie to fit rect and invert vertically to match opengl image format + MatrixRecord transform; + SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix + double scaleX = (double) mWidth / mNaturalWidth; + double scaleY = -1.0 * (double) mHeight / mNaturalHeight; + double centerX = mWidth / 2.0; + double centerY = mHeight / 2.0; + ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) ); + SetMovieMatrix( mMovieHandle, &transform ); + } + + // update movie controller + if ( mMovieController ) + { + MCSetControllerPort( mMovieController, mGWorldHandle ); + MCPositionController( mMovieController, &dest_rect, &dest_rect, + mcTopLeftMovie | mcPositionDontInvalidate ); + MCMovieChanged( mMovieController, mMovieHandle ); + } + + + // Emit event with size change so the calling app knows about it too + // TODO: + //LLMediaEvent event( this ); + //mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); + + return true; + } + static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref ) + { + Boolean result = false; + + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + switch( action ) + { + // handle window resizing + case mcActionControllerSizeChanged: + // Ensure that the movie draws correctly at the new size + self->sizeChanged(); + break; + + // Block any movie controller actions that open URLs. + case mcActionLinkToURL: + case mcActionGetNextURL: + case mcActionLinkToURLExtended: + // Prevent the movie controller from handling the message + result = true; + break; + + default: + break; + }; + + return result; + }; + + static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref ) + { + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + // IMPORTANT: typically, a consumer who is observing this event will set a flag + // when this event is fired then render later. Be aware that the media stream + // can change during this period - dimensions, depth, format etc. + //LLMediaEvent event( self ); +// self->updateQuickTime(); + // TODO ^^^ + + + if ( self->mWidth > 0 && self->mHeight > 0 ) + self->setDirty( 0, 0, self->mWidth, self->mHeight ); + + return noErr; + }; + + static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref ) + { + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + // TODO: + //LLMediaEvent event( self ); + //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event ); + + // Send a "navigate complete" event. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + message.setValue("uri", self->mNavigateURL); + message.setValueS32("result_code", 200); + message.setValue("result_string", "OK"); + self->sendMessage(message); + }; + + + void rewind() + { + GoToBeginningOfMovie( mMovieHandle ); + MCMovieChanged( mMovieController, mMovieHandle ); + }; + + bool processState() + { + if ( mCommand == COMMAND_PLAY ) + { + if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE ) + { + long state = GetMovieLoadState( mMovieHandle ); + + if ( state >= kMovieLoadStatePlaythroughOK ) + { + // if the movie is at the end (generally because it reached it naturally) + // and we play is requested, jump back to the start of the movie. + // note: this is different from having loop flag set. + if ( IsMovieDone( mMovieHandle ) ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + rewind(); + }; + + MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + setStatus(STATUS_PLAYING); + mCommand = COMMAND_NONE; + }; + }; + } + else + if ( mCommand == COMMAND_STOP ) + { + if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE ) + { + if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + rewind(); + + setStatus(STATUS_LOADED); + mCommand = COMMAND_NONE; + }; + }; + } + else + if ( mCommand == COMMAND_PAUSE ) + { + if ( mStatus == STATUS_PLAYING ) + { + if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + setStatus(STATUS_PAUSED); + mCommand = COMMAND_NONE; + }; + }; + }; + + return true; + }; + + void play(F64 rate) + { + mPlayRate = rate; + mCommand = COMMAND_PLAY; + }; + + void stop() + { + mCommand = COMMAND_STOP; + }; + + void pause() + { + mCommand = COMMAND_PAUSE; + }; + + void getMovieNaturalSize(int *movie_width, int *movie_height) + { + Rect rect; + + GetMovieNaturalBoundsRect( mMovieHandle, &rect ); + + int width = ( rect.right - rect.left ); + int height = ( rect.bottom - rect.top ); + + // make sure width and height fall in valid range + if ( width < mMinWidth ) + width = mMinWidth; + + if ( width > mMaxWidth ) + width = mMaxWidth; + + if ( height < mMinHeight ) + height = mMinHeight; + + if ( height > mMaxHeight ) + height = mMaxHeight; + + // return the new rect + *movie_width = width; + *movie_height = height; + } + + void updateQuickTime(int milliseconds) + { + if ( ! mMovieHandle ) + return; + + if ( ! mMovieController ) + return; + + // service QuickTime + // Calling it this way doesn't have good behavior on Windows... +// MoviesTask( mMovieHandle, milliseconds ); + // This was the original, but I think using both MoviesTask and MCIdle is redundant. Trying with only MCIdle. +// MoviesTask( mMovieHandle, 0 ); + + MCIdle( mMovieController ); + + if ( ! mGWorldHandle ) + return; + + if ( mMediaSizeChanging ) + return; + + // update state machine + processState(); + + // see if title arrived and if so, update member variable with contents + checkTitle(); + + // QT call to see if we are at the end - can't do with controller + if ( IsMovieDone( mMovieHandle ) ) + { + // special code for looping - need to rewind at the end of the movie + if ( mIsLooping ) + { + // go back to start + rewind(); + + if ( mMovieController ) + { + // kick off new play + MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); + + // set the volume + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + }; + } + else + { + if(mStatus == STATUS_PLAYING) + { + setStatus(STATUS_DONE); + } + } + } + + }; + + int getDataWidth() const + { + if ( mGWorldHandle ) + { + int depth = mDepth; + + if (depth < 1) + depth = 1; + + // ALWAYS use the row bytes from the PixMap if we have a GWorld because + // sometimes it's not the same as mMediaDepth * mMediaWidth ! + PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle ); + return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth; + } + else + { + // TODO : return LLMediaImplCommon::getaDataWidth(); + return 0; + } + }; + + void seek( F64 time ) + { + if ( mMovieController ) + { + TimeRecord when; + when.scale = GetMovieTimeScale( mMovieHandle ); + when.base = 0; + + // 'time' is in (floating point) seconds. The timebase time will be in 'units', where + // there are 'scale' units per second. + SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) ); + + when.value.hi = ( SInt32 )( raw_time >> 32 ); + when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) ); + + MCDoAction( mMovieController, mcActionGoToTime, &when ); + }; + }; + + F64 getLoadedDuration() + { + TimeValue duration; + if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr) + { + // If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie. + duration = GetMovieDuration( mMovieHandle ); + } + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)duration / (F64)scale; + }; + + F64 getDuration() + { + TimeValue duration = GetMovieDuration( mMovieHandle ); + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)duration / (F64)scale; + }; + + F64 getCurrentTime() + { + TimeValue curr_time = GetMovieTime( mMovieHandle, 0 ); + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)curr_time / (F64)scale; + }; + + void setVolume( F64 volume ) + { + mCurVolume = (short)(volume * ( double ) 0x100 ); + + if ( mMovieController ) + { + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void update(int milliseconds = 0) + { + updateQuickTime(milliseconds); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseDown( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseUp( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseMove( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyPress( unsigned char key ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // Grab movie title into mMovieTitle - should be called repeatedly + // until it returns true since movie title takes a while to become + // available. + const bool getMovieTitle() + { + // grab meta data from movie + QTMetaDataRef media_data_ref; + OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref ); + if ( noErr != result ) + return false; + + // look up "Display Name" in meta data + OSType meta_data_key = kQTMetaDataCommonKeyDisplayName; + QTMetaDataItem item = kQTMetaDataItemUninitialized; + result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard, + 0, kQTMetaDataKeyFormatCommon, + (const UInt8 *)&meta_data_key, + sizeof( meta_data_key ), &item ); + if ( noErr != result ) + return false; + + // find the size of the title + ByteCount size; + result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size ); + if ( noErr != result || size <= 0 ) + return false; + + // allocate some space and grab it + UInt8* item_data = new UInt8( size ); + memset( item_data, 0, size * sizeof( UInt8* ) ); + result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL ); + if ( noErr != result ) + return false; + + // save it + mMovieTitle = std::string( (char* )item_data ); + + // clean up + delete [] item_data; + + return true; + }; + + // called regularly to see if title changed + void checkTitle() + { + // we did already receive title so keep checking + if ( ! mReceivedTitle ) + { + // grab title from movie meta data + if ( getMovieTitle() ) + { + // pass back to host application + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", mMovieTitle ); + sendMessage( message ); + + // stop looking once we find a title for this movie. + // TODO: this may to be reset if movie title changes + // during playback but this is okay for now + mReceivedTitle = true; + }; + }; + }; +}; + +MediaPluginQuickTime::MediaPluginQuickTime( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data), + mMinWidth( 0 ), + mMaxWidth( 2048 ), + mMinHeight( 0 ), + mMaxHeight( 2048 ) +{ +// std::cerr << "MediaPluginQuickTime constructor" << std::endl; + + mNaturalWidth = -1; + mNaturalHeight = -1; + mMovieHandle = 0; + mGWorldHandle = 0; + mMovieController = 0; + mCurVolume = 0x99; + mMediaSizeChanging = false; + mIsLooping = false; + mMovieTitle = std::string(); + mReceivedTitle = false; + mCommand = COMMAND_NONE; + mPlayRate = 0.0f; + mStatus = STATUS_NONE; +} + +MediaPluginQuickTime::~MediaPluginQuickTime() +{ +// std::cerr << "MediaPluginQuickTime destructor" << std::endl; + + ExitMovies(); + +#ifdef LL_WINDOWS + TerminateQTML(); +// std::cerr << "QuickTime closing down" << std::endl; +#endif +} + + +void MediaPluginQuickTime::receiveMessage(const char *message_string) +{ +// std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + // Normally a plugin would only specify one of these two subclasses, but this is a demo... + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + + #ifdef LL_WINDOWS + + // QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime + // according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html + // The solution presented there appears to work. + QTLoadLibrary("qtcf.dll"); + + // main initialization for QuickTime - only required on Windows + OSErr result = InitializeQTML( 0L ); + if ( result != noErr ) + { + //TODO: If no QT on Windows, this fails - respond accordingly. + } + else + { + //std::cerr << "QuickTime initialized" << std::endl; + }; + #endif + + // required for both Windows and Mac + EnterMovies(); + + std::string plugin_version = "QuickTime media plugin, QuickTime version "; + + long version = 0; + Gestalt( gestaltQuickTimeVersion, &version ); + std::ostringstream codec( "" ); + codec << std::hex << version << std::dec; + plugin_version += codec.str(); + message.setValue("plugin_version", plugin_version); + sendMessage(message); + + // Plugin gets to decide the texture parameters to use. + message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + #if defined(LL_WINDOWS) + // Values for Windows + mDepth = 3; + message.setValueU32("format", GL_RGB); + message.setValueU32("type", GL_UNSIGNED_BYTE); + + // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even. + // Padding to a multiple of 3*32 guarantees it'll divide out properly. + message.setValueU32("padding", 32 * 3); + #else + // Values for Mac + mDepth = 4; + message.setValueU32("format", GL_BGRA_EXT); + #ifdef __BIG_ENDIAN__ + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV ); + #else + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8); + #endif + + // Pad texture width to a multiple of 32 bytes, to line up with cache lines. + message.setValueU32("padding", 32); + #endif + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + message.setValueBoolean("allow_downsample", true); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + F64 time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + // TODO: clean up here + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); +// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name +// << ", size: " << info.mSize +// << ", address: " << info.mAddress +// << std::endl; + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + +// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl; + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + + // Make sure the movie GWorld is no longer pointed at the shared segment. + sizeChanged(); + } + mSharedSegments.erase(iter); + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + //std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { +// std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl; +// std::cerr << "%%%% texture size is " << texture_width << " by " << texture_height << std::endl; + + mPixels = (unsigned char*)iter->second.mAddress; + mTextureSegmentName = name; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + + mMediaSizeChanging = false; + + sizeChanged(); + + update(); + }; + }; + } + else if(message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + load( uri ); + sendStatus(); + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + if(event == "down") + { + mouseDown(x, y); + } + else if(event == "up") + { + mouseUp(x, y); + } + else if(event == "move") + { + mouseMove(x, y); + }; + }; + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if(message_name == "stop") + { + stop(); + } + else if(message_name == "start") + { + F64 rate = 0.0; + if(message_in.hasValue("rate")) + { + rate = message_in.getValueReal("rate"); + } + play(rate); + } + else if(message_name == "pause") + { + pause(); + } + else if(message_name == "seek") + { + F64 time = message_in.getValueReal("time"); + seek(time); + } + else if(message_name == "set_loop") + { + bool loop = message_in.getValueBoolean("loop"); + mIsLooping = loop; + } + else if(message_name == "set_volume") + { + F64 volume = message_in.getValueReal("volume"); + setVolume(volume); + } + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl; + }; + }; +} + +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data); + *plugin_send_func = MediaPluginQuickTime::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + +#else // LL_QUICKTIME_ENABLED + +// Stubbed-out class with constructor/destructor (necessary or windows linker +// will just think its dead code and optimize it all out) +class MediaPluginQuickTime : public MediaPluginBase +{ +public: + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginQuickTime(); + /* virtual */ void receiveMessage(const char *message_string); +}; + +MediaPluginQuickTime::MediaPluginQuickTime( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data) +{ + // no-op +} + +MediaPluginQuickTime::~MediaPluginQuickTime() +{ + // no-op +} + +void MediaPluginQuickTime::receiveMessage(const char *message_string) +{ + // no-op +} + +// We're building without quicktime enabled. Just refuse to initialize. +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return -1; +} + +#endif // LL_QUICKTIME_ENABLED diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index fde942ad11..08e43da9e4 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -216,7 +216,6 @@ set(viewer_SOURCE_FILES llfloaterwhitelistentry.cpp llfloaterwindlight.cpp llfloaterworldmap.cpp - llfoldertype.cpp llfolderview.cpp llfolderviewitem.cpp llfollowcam.cpp @@ -239,7 +238,6 @@ set(viewer_SOURCE_FILES llhudrender.cpp llhudtext.cpp llhudview.cpp - llimcontrolpanel.cpp llimfloater.cpp llimhandler.cpp llimpanel.cpp @@ -251,7 +249,9 @@ set(viewer_SOURCE_FILES llinventorybridge.cpp llinventoryclipboard.cpp llinventoryfilter.cpp + llinventoryfunctions.cpp llinventorymodel.cpp + llinventorypanel.cpp llinventorysubtreepanel.cpp lljoystickbutton.cpp lllandmarkactions.cpp @@ -268,7 +268,6 @@ set(viewer_SOURCE_FILES llmaniprotate.cpp llmanipscale.cpp llmaniptranslate.cpp - llmapresponders.cpp llmediactrl.cpp llmediadataclient.cpp llmediaremotectrl.cpp @@ -290,6 +289,7 @@ set(viewer_SOURCE_FILES llnotificationalerthandler.cpp llnotificationgrouphandler.cpp llnotificationmanager.cpp + llnotificationofferhandler.cpp llnotificationscripthandler.cpp llnotificationtiphandler.cpp llnotify.cpp @@ -313,7 +313,6 @@ set(viewer_SOURCE_FILES llpanelgroupnotices.cpp llpanelgrouproles.cpp llpanelimcontrolpanel.cpp - llpanelinventory.cpp llpanelland.cpp llpanellandaudio.cpp llpanellandmarkinfo.cpp @@ -322,11 +321,13 @@ set(viewer_SOURCE_FILES llpanellogin.cpp llpanellookinfo.cpp llpanellooks.cpp + llpanelmaininventory.cpp llpanelmediasettingsgeneral.cpp llpanelmediasettingspermissions.cpp llpanelmediasettingssecurity.cpp llpanelmeprofile.cpp llpanelobject.cpp + llpanelobjectinventory.cpp llpanelpeople.cpp llpanelpeoplemenus.cpp llpanelpermissions.cpp @@ -367,11 +368,16 @@ set(viewer_SOURCE_FILES llsearchcombobox.cpp llsearchhistory.cpp llselectmgr.cpp + llsidepanelinventory.cpp + llsidepanelinventorysubpanel.cpp + llsidepaneliteminfo.cpp + llsidepaneltaskinfo.cpp llsidetray.cpp llsidetraypanelcontainer.cpp llsky.cpp llslurl.cpp llspatialpartition.cpp + llspeakbutton.cpp llspeakers.cpp llsplitbutton.cpp llsprite.cpp @@ -392,6 +398,10 @@ set(viewer_SOURCE_FILES lltexturecache.cpp lltexturectrl.cpp lltexturefetch.cpp + lltextureinfo.cpp + lltextureinfodetails.cpp + lltexturestats.cpp + lltexturestatsuploader.cpp lltextureview.cpp lltoast.cpp lltoastalertpanel.cpp @@ -432,12 +442,14 @@ set(viewer_SOURCE_FILES llvectorperfoptions.cpp llviewchildren.cpp llviewerassetstorage.cpp + llviewerassettype.cpp llvieweraudio.cpp llviewercamera.cpp llviewercontrol.cpp llviewercontrollistener.cpp llviewerdisplay.cpp llviewerfloaterreg.cpp + llviewerfoldertype.cpp llviewergenericmessage.cpp llviewergesture.cpp llviewerhelp.cpp @@ -515,6 +527,8 @@ set(viewer_SOURCE_FILES llwlparamset.cpp llworld.cpp llworldmap.cpp + llworldmapmessage.cpp + llworldmipmap.cpp llworldmapview.cpp llxmlrpclistener.cpp llxmlrpctransaction.cpp @@ -698,7 +712,6 @@ set(viewer_HEADER_FILES llfloaterwhitelistentry.h llfloaterwindlight.h llfloaterworldmap.h - llfoldertype.h llfolderview.h llfoldervieweventlistener.h llfolderviewitem.h @@ -721,7 +734,6 @@ set(viewer_HEADER_FILES llhudrender.h llhudtext.h llhudview.h - llimcontrolpanel.h llimfloater.h llimpanel.h llimview.h @@ -732,7 +744,9 @@ set(viewer_HEADER_FILES llinventorybridge.h llinventoryclipboard.h llinventoryfilter.h + llinventoryfunctions.h llinventorymodel.h + llinventorypanel.h llinventorysubtreepanel.h lljoystickbutton.h lllandmarkactions.h @@ -750,7 +764,6 @@ set(viewer_HEADER_FILES llmaniprotate.h llmanipscale.h llmaniptranslate.h - llmapresponders.h llmediactrl.h llmediadataclient.h llmediaremotectrl.h @@ -792,7 +805,6 @@ set(viewer_HEADER_FILES llpanelgroupnotices.h llpanelgrouproles.h llpanelimcontrolpanel.h - llpanelinventory.h llpanelland.h llpanellandaudio.h llpanellandmarkinfo.h @@ -801,11 +813,13 @@ set(viewer_HEADER_FILES llpanellogin.h llpanellookinfo.h llpanellooks.h + llpanelmaininventory.h llpanelmediasettingsgeneral.h llpanelmediasettingspermissions.h llpanelmediasettingssecurity.h llpanelmeprofile.h llpanelobject.h + llpanelobjectinventory.h llpanelpeople.h llpanelpeoplemenus.h llpanelpermissions.h @@ -848,11 +862,16 @@ set(viewer_HEADER_FILES llsearchcombobox.h llsearchhistory.h llselectmgr.h + llsidepanelinventory.h + llsidepanelinventorysubpanel.h + llsidepaneliteminfo.h + llsidepaneltaskinfo.h llsidetray.h llsidetraypanelcontainer.h llsky.h llslurl.h llspatialpartition.h + llspeakbutton.h llspeakers.h llsplitbutton.h llsprite.h @@ -874,6 +893,10 @@ set(viewer_HEADER_FILES lltexturecache.h lltexturectrl.h lltexturefetch.h + lltextureinfo.h + lltextureinfodetails.h + lltexturestats.h + lltexturestatsuploader.h lltextureview.h lltoast.h lltoastalertpanel.h @@ -915,6 +938,7 @@ set(viewer_HEADER_FILES llvectorperfoptions.h llviewchildren.h llviewerassetstorage.h + llviewerassettype.h llvieweraudio.h llviewerbuild.h llviewercamera.h @@ -922,6 +946,7 @@ set(viewer_HEADER_FILES llviewercontrollistener.h llviewerdisplay.h llviewerfloaterreg.h + llviewerfoldertype.h llviewergenericmessage.h llviewergesture.h llviewerhelp.h @@ -998,6 +1023,8 @@ set(viewer_HEADER_FILES llwlparamset.h llworld.h llworldmap.h + llworldmapmessage.h + llworldmipmap.h llworldmapview.h llxmlrpclistener.h llxmlrpctransaction.h @@ -1650,6 +1677,12 @@ LL_ADD_INTEGRATION_TEST(llcapabilitylistener ) #ADD_VIEWER_BUILD_TEST(llmemoryview viewer) +#ADD_VIEWER_BUILD_TEST(llagentaccess viewer) +#ADD_VIEWER_BUILD_TEST(llworldmap viewer) +#ADD_VIEWER_BUILD_TEST(llworldmipmap viewer) +#ADD_VIEWER_BUILD_TEST(lltextureinfo viewer) +#ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer) +#ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer) # Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index dceaba9a43..879408d6e4 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -2,6 +2,6 @@ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 2.0.0.3256"; -CFBundleGetInfoString = "Second Life version 2.0.0.3256, Copyright 2004-2009 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 2.0.0.200030"; +CFBundleGetInfoString = "Second Life version 2.0.0.200030, Copyright 2004-2009 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 7aec8a343d..38ebb22b84 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>2.0.0.3256</string> + <string>2.0.0.200030</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/app_settings/foldertypes.xml b/indra/newview/app_settings/foldertypes.xml index 2038779c4f..0d539177f3 100644 --- a/indra/newview/app_settings/foldertypes.xml +++ b/indra/newview/app_settings/foldertypes.xml @@ -1,66 +1,61 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <ensemble_defs> <ensemble - asset_num="-1" - xui_name="default" - icon_name="inv_plain_closed.tga" - /> - <ensemble - asset_num="27" + foldertype_num="27" xui_name="head" icon_name="inv_folder_outfit_head.tga" allowed="hair,eyes" /> <ensemble - asset_num="28" + foldertype_num="28" xui_name="gloves" icon_name="inv_folder_outfit_gloves.tga" allowed="gloves" /> <ensemble - asset_num="29" + foldertype_num="29" xui_name="jacket" icon_name="inv_folder_outfit_jacket.tga" allowed="jacket" /> <ensemble - asset_num="30" + foldertype_num="30" xui_name="pants" icon_name="inv_folder_outfit_pants.tga" allowed="pants,underpants" /> <ensemble - asset_num="31" + foldertype_num="31" xui_name="shape" icon_name="inv_folder_outfit_shape.tga" allowed="shape,skin,hair,eyes" /> <ensemble - asset_num="32" + foldertype_num="32" xui_name="shoes" icon_name="inv_folder_outfit_shoes.tga" allowed="shoes,socks" /> <ensemble - asset_num="33" + foldertype_num="33" xui_name="shirt" icon_name="inv_folder_outfit_shirt.tga" allowed="shirt,undershirt" /> <ensemble - asset_num="34" + foldertype_num="34" xui_name="skirt" icon_name="inv_folder_outfit_skirt.tga" allowed="" /> <ensemble - asset_num="35" + foldertype_num="35" xui_name="underpants" icon_name="inv_folder_outfit_underpants.tga" allowed="underpants" /> <ensemble - asset_num="36" + foldertype_num="36" xui_name="undershirt" icon_name="inv_folder_outfit_undershirt.tga" allowed="undershirt" diff --git a/indra/newview/app_settings/ignorable_dialogs.xml b/indra/newview/app_settings/ignorable_dialogs.xml index 669235af1b..ab18febccc 100644 --- a/indra/newview/app_settings/ignorable_dialogs.xml +++ b/indra/newview/app_settings/ignorable_dialogs.xml @@ -1,291 +1,291 @@ -<?xml version="1.0" ?>
-<llsd>
-<map>
- <key>FirstAppearance</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstAppearance warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstAttach</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstAttach warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstBalanceDecrease</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstBalanceDecrease warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstBalanceIncrease</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstBalanceIncrease warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstBuild</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstBuild warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstDebugMenus</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstDebugMenus warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstFlexible</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstFlexible warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstGoTo</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstGoTo warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstInventory</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstInventory warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstLeftClickNoHit</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstLeftClickNoHit warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstMap</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstMap warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstMedia</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstMedia warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstOverrideKeys</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstOverrideKeys warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstSandbox</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstSandbox warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstSculptedPrim</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstSculptedPrim warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstSit</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstSit warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstStreamingMusic</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstStreamingMusic warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstStreamingVideo</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstStreamingVideo warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstTeleport</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstTeleport warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>FirstVoice</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstVoice warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>AboutDirectX9</key>
- <map>
- <key>Comment</key>
- <string>Enables AboutDirectX9 warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>BrowserLaunch</key>
- <map>
- <key>Comment</key>
- <string>Enables BrowserLaunch warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>DeedObject</key>
- <map>
- <key>Comment</key>
- <string>Enables DeedObject warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>NewClassified</key>
- <map>
- <key>Comment</key>
- <string>Enables NewClassified warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>QuickTimeInstalled</key>
- <map>
- <key>Comment</key>
- <string>Enables QuickTimeInstalled warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>ReturnToOwner</key>
- <map>
- <key>Comment</key>
- <string>Enables ReturnToOwner warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- </map>
-</llsd>
+<?xml version="1.0" ?> +<llsd> +<map> + <key>FirstAppearance</key> + <map> + <key>Comment</key> + <string>Enables FirstAppearance warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstAttach</key> + <map> + <key>Comment</key> + <string>Enables FirstAttach warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstBalanceDecrease</key> + <map> + <key>Comment</key> + <string>Enables FirstBalanceDecrease warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstBalanceIncrease</key> + <map> + <key>Comment</key> + <string>Enables FirstBalanceIncrease warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstBuild</key> + <map> + <key>Comment</key> + <string>Enables FirstBuild warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstDebugMenus</key> + <map> + <key>Comment</key> + <string>Enables FirstDebugMenus warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstFlexible</key> + <map> + <key>Comment</key> + <string>Enables FirstFlexible warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstGoTo</key> + <map> + <key>Comment</key> + <string>Enables FirstGoTo warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstInventory</key> + <map> + <key>Comment</key> + <string>Enables FirstInventory warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstLeftClickNoHit</key> + <map> + <key>Comment</key> + <string>Enables FirstLeftClickNoHit warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstMap</key> + <map> + <key>Comment</key> + <string>Enables FirstMap warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstMedia</key> + <map> + <key>Comment</key> + <string>Enables FirstMedia warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstOverrideKeys</key> + <map> + <key>Comment</key> + <string>Enables FirstOverrideKeys warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstSandbox</key> + <map> + <key>Comment</key> + <string>Enables FirstSandbox warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstSculptedPrim</key> + <map> + <key>Comment</key> + <string>Enables FirstSculptedPrim warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstSit</key> + <map> + <key>Comment</key> + <string>Enables FirstSit warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstStreamingMusic</key> + <map> + <key>Comment</key> + <string>Enables FirstStreamingMusic warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstStreamingVideo</key> + <map> + <key>Comment</key> + <string>Enables FirstStreamingVideo warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstTeleport</key> + <map> + <key>Comment</key> + <string>Enables FirstTeleport warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FirstVoice</key> + <map> + <key>Comment</key> + <string>Enables FirstVoice warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>AboutDirectX9</key> + <map> + <key>Comment</key> + <string>Enables AboutDirectX9 warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BrowserLaunch</key> + <map> + <key>Comment</key> + <string>Enables BrowserLaunch warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>DeedObject</key> + <map> + <key>Comment</key> + <string>Enables DeedObject warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>NewClassified</key> + <map> + <key>Comment</key> + <string>Enables NewClassified warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>QuickTimeInstalled</key> + <map> + <key>Comment</key> + <string>Enables QuickTimeInstalled warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ReturnToOwner</key> + <map> + <key>Comment</key> + <string>Enables ReturnToOwner warning dialog</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + </map> +</llsd> diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index 544f1c598e..5f6fd6e4a7 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -560,7 +560,8 @@ STATUS_WHITELIST_FAILED URL failed to pass whitelist NULL_KEY Indicates an empty key EOF Indicates the last line of a notecard was read TEXTURE_BLANK UUID for the "Blank" texture -TEXTURE_DEFAULT UUID for the "Default Media" texture +TEXTURE_DEFAULT Alias for TEXTURE_PLYWOOD +TEXTURE_MEDIA UUID for the "Default Media" texture TEXTURE_PLYWOOD UUID for the default "Plywood" texture TEXTURE_TRANSPARENT UUID for the "White - Transparent" texture diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 768fdd4103..6f6d5fb979 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -133,7 +133,7 @@ <key>Value</key> <integer>1</integer> </map> - <key>ArrowKeysMoveAvatar</key> + <key>ArrowKeysAlwaysMove</key> <map> <key>Comment</key> <string>While cursor is in chat entry box, arrow keys still control your avatar</string> @@ -142,7 +142,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> <key>AskedAboutCrashReports</key> <map> @@ -309,7 +309,18 @@ <key>Value</key> <integer>0</integer> </map> - <key>AutoAcceptNewInventory</key> + <key>AuditTexture</key> + <map> + <key>Comment</key> + <string>Enable texture auditting.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>AutoAcceptNewInventory</key> <map> <key>Comment</key> <string>Automatically accept new notecards/textures/landmarks</string> @@ -3574,7 +3585,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://www.google.com/search?q=site%3Awiki.secondlife.com+[TOPIC]&ignore_channel=[CHANNEL]&ignore_version=[VERSION]&ignore_os=[OS]&ignore_language=[LANGUAGE]&ignore_version_major=[VERSION_MAJOR]&ignore_version_minor=[VERSION_MINOR]&ignore_version_patch=[VERSION_PATCH]&ignore_version_build=[VERSION_BUILD]</string> + <string>http://docs.lindenlab.com/help/helpfloater.php?topic=[TOPIC]&channel=[CHANNEL]&version=[VERSION]&os=[OS]&language=[LANGUAGE]&version_major=[VERSION_MAJOR]&version_minor=[VERSION_MINOR]&version_patch=[VERSION_PATCH]&version_build=[VERSION_BUILD]</string> </map> <key>HighResSnapshot</key> <map> @@ -4567,6 +4578,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>MiniMapPrimMaxRadius</key> + <map> + <key>Comment</key> + <string>Radius of the largest prim to show on the MiniMap. Increasing beyond 256 may cause client lag.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>256.0</real> + </map> <key>MiniMapRotate</key> <map> <key>Comment</key> @@ -4581,7 +4603,7 @@ <key>MiniMapScale</key> <map> <key>Comment</key> - <string>Miniature world map zoom levle (pixels per region)</string> + <string>Miniature world map zoom level (pixels per region)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -5473,7 +5495,18 @@ <key>QAModeEventHostPort</key> <map> <key>Comment</key> - <string>Enable Testing Features.</string> + <string>Port on which lleventhost should listen</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>-1</integer> + </map> + <key>QAModeTermCode</key> + <map> + <key>Comment</key> + <string>On LL_ERRS, terminate with this code instead of OS message box</string> <key>Persist</key> <integer>0</integer> <key>Type</key> @@ -5558,6 +5591,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RegInClient</key> + <map> + <key>Comment</key> + <string>Experimental: Embed registration in login screen</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RegionTextureSize</key> <map> <key>Comment</key> @@ -6225,7 +6269,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>RenderHighlightFadeTime</key> @@ -8589,6 +8633,28 @@ <key>Value</key> <real>20.0</real> </map> + <key>TextureDisable</key> + <map> + <key>Comment</key> + <string>If TRUE, do not load textures for in-world content</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>TextureLoadFullRes</key> + <map> + <key>Comment</key> + <string>If TRUE, always load textures at full resolution (discard = 0)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>TextureMemory</key> <map> <key>Comment</key> @@ -10647,5 +10713,38 @@ <key>Value</key> <integer>0</integer> </map> - </map> + <key>LogTextureDownloadsToViewerLog</key> + <map> + <key>Comment</key> + <string>Send texture download details to the viewer log</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>LogTextureDownloadsToSimulator</key> + <map> + <key>Comment</key> + <string>Send a digest of texture info to the sim</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>TextureLoggingThreshold</key> + <map> + <key>Comment</key> + <string>Specifies the byte threshold at which texture download data should be sent to the sim.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>1</integer> + </map> +</map> </llsd> diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index c43ba27984..10c197d09e 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="US-ASCII" standalone="yes"?> <linden_avatar - version="1.0" wearable_definition_version="23"> + version="1.0" wearable_definition_version="24"> <!-- The wearable_definition_version is checked during asset upload. --> <!-- If you increment it, check indra/lib/python/indra/assetutil.py. --> <skeleton @@ -8985,7 +8985,7 @@ render_pass="bump"> id="1017" /> <driven - id="1033" /> + id="1035" /> <driven id="914" diff --git a/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt b/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt index 185c0180fb..30f9349111 100644 --- a/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt +++ b/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt @@ -1,6 +1,6 @@ -The language files in this directory are Unicode (Little-Endian) format, also known as UTF-16 LE.
-
-This is the format required for NSIS Unicode. See http://www.scratchpaper.com/ for details.
-
-James Cook
-September 2008
+The language files in this directory are Unicode (Little-Endian) format, also known as UTF-16 LE. + +This is the format required for NSIS Unicode. See http://www.scratchpaper.com/ for details. + +James Cook +September 2008 diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 75a72e5b17..24bdf66c2a 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -75,6 +75,8 @@ #include "llstatusbar.h" #include "llteleportflags.h" #include "llteleporthistory.h" +#include "lltexturestats.h" +#include "lltexturestats.h" #include "lltool.h" #include "lltoolcomp.h" #include "lltoolmgr.h" @@ -6085,17 +6087,16 @@ void LLAgent::teleportCancel() void LLAgent::teleportViaLocation(const LLVector3d& pos_global) { LLViewerRegion* regionp = getRegion(); - LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); + U64 handle = to_region_handle(pos_global); + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); if(regionp && info) { - U32 x_pos; - U32 y_pos; - from_region_handle(info->mHandle, &x_pos, &y_pos); + LLVector3d region_origin = info->getGlobalOrigin(); LLVector3 pos_local( - (F32)(pos_global.mdV[VX] - x_pos), - (F32)(pos_global.mdV[VY] - y_pos), + (F32)(pos_global.mdV[VX] - region_origin.mdV[VX]), + (F32)(pos_global.mdV[VY] - region_origin.mdV[VY]), (F32)(pos_global.mdV[VZ])); - teleportRequest(info->mHandle, pos_local); + teleportRequest(handle, pos_local); } else if(regionp && teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY]))) @@ -6512,3 +6513,4 @@ LLAgentQueryManager::~LLAgentQueryManager() } // EOF + diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 380469f5b3..3fc1055acd 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -39,6 +39,7 @@ #include "llfloaterinventory.h" #include "llinventorybridge.h" #include "llinventorymodel.h" +#include "llinventorypanel.h" #include "llnotify.h" #include "llviewerregion.h" #include "llvoavatarself.h" @@ -433,7 +434,7 @@ void LLAgentWearables::saveWearableAs(const EWearableType type, if (save_in_lost_and_found) { category_id = gInventory.findCategoryUUIDForType( - LLAssetType::AT_LOST_AND_FOUND); + LLFolderType::FT_LOST_AND_FOUND); } else { @@ -839,7 +840,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs } // Get the UUID of the current outfit folder (will be created if it doesn't exist) - LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); LLInitialWearablesFetch* outfit = new LLInitialWearablesFetch(); @@ -980,8 +981,7 @@ void LLAgentWearables::recoverMissingWearable(const EWearableType type, U32 inde // Add a new one in the lost and found folder. // (We used to overwrite the "not found" one, but that could potentially // destory content.) JC - LLUUID lost_and_found_id = - gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); LLPointer<LLInventoryCallback> cb = new addWearableToAgentInventoryCallback( LLPointer<LLRefCount>(NULL), @@ -1122,8 +1122,8 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name, // First, make a folder in the Clothes directory. LLUUID folder_id = gInventory.createNewCategory( - gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING), - LLAssetType::AT_NONE, + gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING), + LLFolderType::FT_NONE, new_folder_name); bool found_first_item = false; @@ -1256,10 +1256,10 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name) } // First, make a folder in the My Outfits directory. - LLUUID parent_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_MY_OUTFITS); + const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); LLUUID folder_id = gInventory.createNewCategory( parent_id, - LLAssetType::AT_OUTFIT, + LLFolderType::FT_OUTFIT, new_folder_name); LLAppearanceManager::shallowCopyCategory(LLAppearanceManager::getCOF(),folder_id, NULL); @@ -1392,6 +1392,7 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem const LLUUID &item_id = getWearableItemID(type,i); popWearable(type,i); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + LLAppearanceManager::removeItemLinks(item_id,false); //queryWearableCache(); // moved below if (old_wearable) @@ -1408,6 +1409,7 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem const LLUUID &item_id = getWearableItemID(type,index); popWearable(type, index); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + LLAppearanceManager::removeItemLinks(item_id,false); //queryWearableCache(); // moved below @@ -1721,10 +1723,8 @@ void LLAgentWearables::queryWearableCache() // MULTI_WEARABLE: need a way to specify by wearable rather than by type. // User has picked "remove from avatar" from a menu. // static -void LLAgentWearables::userRemoveWearable(void* userdata) +void LLAgentWearables::userRemoveWearable(EWearableType& type) { - EWearableType type = (EWearableType)(intptr_t)userdata; - if (!(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR)) //&& //!((!gAgent.isTeen()) && (type==WT_UNDERPANTS || type==WT_UNDERSHIRT))) { @@ -1734,7 +1734,7 @@ void LLAgentWearables::userRemoveWearable(void* userdata) } // static -void LLAgentWearables::userRemoveAllClothes(void* userdata) +void LLAgentWearables::userRemoveAllClothes() { // We have to do this up front to avoid having to deal with the case of multiple wearables being dirty. if (gFloaterCustomize) @@ -2014,7 +2014,8 @@ void LLInitialWearablesFetch::done() LLFindWearables is_wearable; gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH, is_wearable); - + + LLAppearanceManager::setAttachmentInvLinkEnable(true); if (wearable_array.count() > 0) { LLAppearanceManager::instance().updateAppearanceFromCOF(); @@ -2030,7 +2031,7 @@ void LLInitialWearablesFetch::processWearablesMessage() { if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead. { - LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); for (U8 i = 0; i < mAgentInitialWearables.size(); ++i) { // Populate the current outfit folder with links to the wearables passed in the message diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 97de785c87..317f4a7e4f 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -191,9 +191,9 @@ public: //-------------------------------------------------------------------- public: // MULTI-WEARABLE: assuming one wearable per type. Need upstream changes. - static void userRemoveWearable(void* userdata); // userdata is EWearableType - static void userRemoveAllClothes(void* userdata); // userdata is NULL - + static void userRemoveWearable(EWearableType& type); + static void userRemoveAllClothes(); + typedef std::vector<LLViewerObject*> llvo_vec_t; static void userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4e022aeb29..41cd77b45d 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -130,11 +130,11 @@ void LLOutfitObserver::done() { if(LLInventoryType::IT_GESTURE == item->getInventoryType()) { - pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE); + pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); } else { - pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); } break; } @@ -146,7 +146,7 @@ void LLOutfitObserver::done() LLUUID cat_id = gInventory.createNewCategory( pid, - LLAssetType::AT_NONE, + LLFolderType::FT_NONE, name); mCatID = cat_id; LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(mCatID, mAppend); @@ -296,15 +296,39 @@ struct LLWearableHoldingPattern bool append; }; +/* static */ void removeDuplicateItems(LLInventoryModel::item_array_t& items) +{ + LLInventoryModel::item_array_t new_items; + std::set<LLUUID> items_seen; + std::deque<LLViewerInventoryItem*> tmp_list; + // Traverse from the front and keep the first of each item + // encountered, so we actually keep the *last* of each duplicate + // item. This is needed to give the right priority when adding + // duplicate items to an existing outfit. + for (S32 i=items.count()-1; i>=0; i--) + { + LLViewerInventoryItem *item = items.get(i); + LLUUID item_id = item->getLinkedUUID(); + if (items_seen.find(item_id)!=items_seen.end()) + continue; + items_seen.insert(item_id); + tmp_list.push_front(item); + } + for (std::deque<LLViewerInventoryItem*>::iterator it = tmp_list.begin(); + it != tmp_list.end(); + ++it) + { + new_items.put(*it); + } + items = new_items; +} void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventoryModel::item_array_t& src) { LLInventoryModel::item_array_t new_dst; std::set<LLUUID> mark_inventory; - std::set<LLUUID> mark_asset; S32 inventory_dups = 0; - S32 asset_dups = 0; for (LLInventoryModel::item_array_t::const_iterator src_pos = src.begin(); src_pos != src.end(); @@ -312,8 +336,6 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory { LLUUID src_item_id = (*src_pos)->getLinkedUUID(); mark_inventory.insert(src_item_id); - LLUUID src_asset_id = (*src_pos)->getAssetUUID(); - mark_asset.insert(src_asset_id); } for (LLInventoryModel::item_array_t::const_iterator dst_pos = dst.begin(); @@ -324,36 +346,25 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory if (mark_inventory.find(dst_item_id) == mark_inventory.end()) { - } - else - { - inventory_dups++; - } - - LLUUID dst_asset_id = (*dst_pos)->getAssetUUID(); - - if (mark_asset.find(dst_asset_id) == mark_asset.end()) - { // Item is not already present in COF. new_dst.put(*dst_pos); - mark_asset.insert(dst_item_id); + mark_inventory.insert(dst_item_id); } else { - asset_dups++; + inventory_dups++; } } llinfos << "removeDups, original " << dst.count() << " final " << new_dst.count() - << " inventory dups " << inventory_dups << " asset_dups " << asset_dups << llendl; + << " inventory dups " << inventory_dups << llendl; dst = new_dst; } - /* static */ LLUUID LLAppearanceManager::getCOF() { - return gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); } // Update appearance from outfit folder. @@ -363,6 +374,9 @@ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, boo if (!proceed) return; +#if 1 + updateCOF(category,append); +#else if (append) { updateCOFFromCategory(category, append); // append is true - add non-duplicates to COF. @@ -370,16 +384,17 @@ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, boo else { LLViewerInventoryCategory* catp = gInventory.getCategory(category); - if (catp->getPreferredType() == LLAssetType::AT_NONE || - LLAssetType::lookupIsEnsembleCategoryType(catp->getPreferredType())) + if (catp->getPreferredType() == LLFolderType::FT_NONE || + LLFolderType::lookupIsEnsembleType(catp->getPreferredType())) { updateCOFFromCategory(category, append); // append is false - rebuild COF. } - else if (catp->getPreferredType() == LLAssetType::AT_OUTFIT) + else if (catp->getPreferredType() == LLFolderType::FT_OUTFIT) { rebuildCOFFromOutfit(category); } } +#endif } // Append to current COF contents by recursively traversing a folder. @@ -401,7 +416,7 @@ void LLAppearanceManager::updateCOFFromCategory(const LLUUID& category, bool app return; } - const LLUUID ¤t_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); // Processes that take time should show the busy cursor //inc_busy_count(); @@ -499,7 +514,7 @@ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID { LLViewerInventoryCategory *catp = item->getLinkedCategory(); // Skip copying outfit links. - if (catp && catp->getPreferredType() != LLAssetType::AT_OUTFIT) + if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT) { link_inventory_item(gAgent.getID(), item->getLinkedUUID(), @@ -520,6 +535,130 @@ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID } } } +/* static */ void LLAppearanceManager::purgeCategory(const LLUUID& category, bool keep_outfit_links) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(category, cats, items, + LLInventoryModel::EXCLUDE_TRASH); + for (S32 i = 0; i < items.count(); ++i) + { + LLViewerInventoryItem *item = items.get(i); + if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER)) + continue; + gInventory.purgeObject(item->getUUID()); + } +} + +// Keep the last N wearables of each type. For viewer 2.0, N is 1 for +// both body parts and clothing items. +/* static */ void LLAppearanceManager::filterWearableItems( + LLInventoryModel::item_array_t& items, S32 max_per_type) +{ + // Divvy items into arrays by wearable type. + std::vector<LLInventoryModel::item_array_t> items_by_type(WT_COUNT); + for (S32 i=0; i<items.count(); i++) + { + LLViewerInventoryItem *item = items.get(i); + // Ignore non-wearables. + if (!item->isWearableType()) + continue; + EWearableType type = item->getWearableType(); + items_by_type[type].push_back(item); + } + + // rebuild items list, retaining the last max_per_type of each array + items.clear(); + for (S32 i=0; i<WT_COUNT; i++) + { + S32 size = items_by_type[i].size(); + if (size <= 0) + continue; + S32 start_index = llmax(0,size-max_per_type); + for (S32 j = start_index; j<size; j++) + { + items.push_back(items_by_type[i][j]); + } + } +} + +// Create links to all listed items. +/* static */ void LLAppearanceManager::linkAll(const LLUUID& category, + LLInventoryModel::item_array_t& items, + LLPointer<LLInventoryCallback> cb) +{ + for (S32 i=0; i<items.count(); i++) + { + const LLInventoryItem* item = items.get(i).get(); + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + category, + item->getName(), + LLAssetType::AT_LINK, + cb); + } +} + +/* static */ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) +{ + const LLUUID cof = getCOF(); + + // Collect and filter descendents to determine new COF contents. + + // - Body parts: always include COF contents as a fallback in case any + // required parts are missing. + LLInventoryModel::item_array_t body_items; + getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false); + getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false); + // Reduce body items to max of one per type. + removeDuplicateItems(body_items); + filterWearableItems(body_items, 1); + + // - Wearables: include COF contents only if appending. + LLInventoryModel::item_array_t wear_items; + if (append) + getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING, false); + getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING, false); + // Reduce wearables to max of one per type. + removeDuplicateItems(wear_items); + filterWearableItems(wear_items, 1); + + // - Attachments: include COF contents only if appending. + LLInventoryModel::item_array_t obj_items; + if (append) + getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT, false); + getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT, false); + removeDuplicateItems(obj_items); + + // - Gestures: include COF contents only if appending. + LLInventoryModel::item_array_t gest_items; + if (append) + getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false); + getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE, false); + removeDuplicateItems(gest_items); + + // Remove current COF contents. + bool keep_outfit_links = append; + purgeCategory(cof, keep_outfit_links); + gInventory.notifyObservers(); + + // Create links to new COF contents. + LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; + + linkAll(cof, body_items, link_waiter); + linkAll(cof, wear_items, link_waiter); + linkAll(cof, obj_items, link_waiter); + linkAll(cof, gest_items, link_waiter); + + // Add link to outfit if category is an outfit. + LLViewerInventoryCategory* catp = gInventory.getCategory(category); + if (!append && catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) + { + link_inventory_item(gAgent.getID(), category, cof, catp->getName(), + LLAssetType::AT_LINK_FOLDER, link_waiter); + } + +} /* static */ bool LLAppearanceManager::isMandatoryWearableType(EWearableType type) @@ -604,7 +743,7 @@ void LLAppearanceManager::rebuildCOFFromOutfit(const LLUUID& category) LLNotifications::instance().add("CouldNotPutOnOutfit"); return; } - + // Processes that take time should show the busy cursor //inc_busy_count(); @@ -622,7 +761,7 @@ void LLAppearanceManager::rebuildCOFFromOutfit(const LLUUID& category) // Create a link to the outfit that we wore. LLViewerInventoryCategory* catp = gInventory.getCategory(category); - if (catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT) + if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) { link_inventory_item(gAgent.getID(), category, current_outfit_id, catp->getName(), LLAssetType::AT_LINK_FOLDER, link_waiter); @@ -792,6 +931,22 @@ void LLAppearanceManager::getCOFValidDescendents(const LLUUID& category, follow_folder_links); } +/* static */ +void LLAppearanceManager::getDescendentsOfAssetType(const LLUUID& category, + LLInventoryModel::item_array_t& items, + LLAssetType::EType type, + bool follow_folder_links) +{ + LLInventoryModel::cat_array_t cats; + LLIsType is_of_type(type); + gInventory.collectDescendentsIf(category, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_of_type, + follow_folder_links); +} + /* static */ void LLAppearanceManager::getUserDescendents(const LLUUID& category, LLInventoryModel::item_array_t& wear_items, @@ -924,9 +1079,21 @@ void LLAppearanceManager::wearOutfitByName(const std::string& name) //dec_busy_count(); } +bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventoryItem *b) +{ + return (a->isWearableType() && b->isWearableType() && + (a->getWearableType() == b->getWearableType())); +} /* static */ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update ) { + LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item); + if (!vitem) + { + llwarns << "not an llviewerinventoryitem, failed" << llendl; + return; + } + LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; gInventory.collectDescendents(LLAppearanceManager::getCOF(), @@ -936,11 +1103,20 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update ) bool linked_already = false; for (S32 i=0; i<item_array.count(); i++) { - const LLInventoryItem* inv_item = item_array.get(i).get(); + // Are these links to the same object? + const LLViewerInventoryItem* inv_item = item_array.get(i).get(); if (inv_item->getLinkedUUID() == item->getLinkedUUID()) { linked_already = true; - break; + } + // Are these links to different items of the same wearable + // type? If so, new item will replace old. + // MULTI-WEARABLES: revisit if more than one per type is allowed. + else if (areMatchingWearables(vitem,inv_item)) + { + gAgentWearables.removeWearable(inv_item->getWearableType(),true,0); + gInventory.purgeObject(inv_item->getUUID()); + gInventory.notifyObservers(); } } if (linked_already) @@ -952,9 +1128,9 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update ) { LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0; link_inventory_item( gAgent.getID(), - item->getLinkedUUID(), + vitem->getLinkedUUID(), getCOF(), - item->getName(), + vitem->getName(), LLAssetType::AT_LINK, cb); } @@ -998,14 +1174,16 @@ void LLAppearanceManager::removeItemLinks(const LLUUID& item_id, bool do_update) } } +//#define DUMP_CAT_VERBOSE + /* static */ -void LLAppearanceManager::dumpCat(const LLUUID& cat_id, std::string str) +void LLAppearanceManager::dumpCat(const LLUUID& cat_id, const std::string& msg) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; gInventory.collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); -#if 0 +#ifdef DUMP_CAT_VERBOSE llinfos << llendl; llinfos << str << llendl; S32 hitcount = 0; @@ -1017,6 +1195,89 @@ void LLAppearanceManager::dumpCat(const LLUUID& cat_id, std::string str) llinfos << i <<" "<< item->getName() <<llendl; } #endif - llinfos << str << " count " << items.count() << llendl; + llinfos << msg << " count " << items.count() << llendl; +} + +/* static */ +void LLAppearanceManager::dumpItemArray(const LLInventoryModel::item_array_t& items, + const std::string& msg) +{ + llinfos << msg << llendl; + for (S32 i=0; i<items.count(); i++) + { + LLViewerInventoryItem *item = items.get(i); + llinfos << i <<" " << item->getName() << llendl; + } + llinfos << llendl; +} + + +std::set<LLUUID> LLAppearanceManager::sRegisteredAttachments; +bool LLAppearanceManager::sAttachmentInvLinkEnabled(false); + +/* static */ +void LLAppearanceManager::setAttachmentInvLinkEnable(bool val) +{ + llinfos << "setAttachmentInvLinkEnable => " << (int) val << llendl; + sAttachmentInvLinkEnabled = val; +} + +void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg) +{ + llinfos << msg << llendl; + for (std::set<LLUUID>::const_iterator it = atts.begin(); + it != atts.end(); + ++it) + { + LLUUID item_id = *it; + LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (item) + llinfos << "atts " << item->getName() << llendl; + else + llinfos << "atts " << "UNKNOWN[" << item_id.asString() << "]" << llendl; + } + llinfos << llendl; } +/* static */ +void LLAppearanceManager::registerAttachment(const LLUUID& item_id) +{ + sRegisteredAttachments.insert(item_id); + dumpAttachmentSet(sRegisteredAttachments,"after register:"); + + if (sAttachmentInvLinkEnabled) + { + LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (item) + { + LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Adding attachment link:"); + LLAppearanceManager::wearItem(item,false); // Add COF link for item. + gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + gInventory.notifyObservers(); + } + } + else + { + llinfos << "no link changes, inv link not enabled" << llendl; + } +} + +/* static */ +void LLAppearanceManager::unregisterAttachment(const LLUUID& item_id) +{ + sRegisteredAttachments.erase(item_id); + dumpAttachmentSet(sRegisteredAttachments,"after unregister:"); + + if (sAttachmentInvLinkEnabled) + { + LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Removing attachment link:"); + LLAppearanceManager::removeItemLinks(item_id, false); + // BAP - needs to change for label to track link. + gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + gInventory.notifyObservers(); + } + else + { + llinfos << "no link changes, inv link not enabled" << llendl; + } +} diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 828af32101..56f54dfc23 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -46,6 +46,7 @@ public: static void updateAppearanceFromCOF(); static bool needToSaveCOF(); static void changeOutfit(bool proceed, const LLUUID& category, bool append); + static void updateCOF(const LLUUID& category, bool append = false); static void updateCOFFromCategory(const LLUUID& category, bool append); static void rebuildCOFFromOutfit(const LLUUID& category); static void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append); @@ -65,9 +66,23 @@ public: static void removeItemLinks(const LLUUID& item_id, bool do_update = true); // For debugging - could be moved elsewhere. - static void dumpCat(const LLUUID& cat_id, std::string str); + static void dumpCat(const LLUUID& cat_id, const std::string& msg); + static void dumpItemArray(const LLInventoryModel::item_array_t& items, const std::string& msg); + static void unregisterAttachment(const LLUUID& item_id); + static void registerAttachment(const LLUUID& item_id); + static void setAttachmentInvLinkEnable(bool val); private: + static void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type); + static void linkAll(const LLUUID& category, + LLInventoryModel::item_array_t& items, + LLPointer<LLInventoryCallback> cb); + + static void getDescendentsOfAssetType(const LLUUID& category, + LLInventoryModel::item_array_t& items, + LLAssetType::EType type, + bool follow_folder_links); + static void getCOFValidDescendents(const LLUUID& category, LLInventoryModel::item_array_t& items); @@ -81,6 +96,11 @@ private: static bool isMandatoryWearableType(EWearableType type); static void checkMandatoryWearableTypes(const LLUUID& category, std::set<EWearableType>& types_found); static void purgeCOFBeforeRebuild(const LLUUID& category); + static void purgeCategory(const LLUUID& category, bool keep_outfit_links); + + static std::set<LLUUID> sRegisteredAttachments; + static bool sAttachmentInvLinkEnabled; + }; #define SUPPORT_ENSEMBLES 0 diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 873215169e..8e6d6b885d 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -57,6 +57,8 @@ #include "llallocator.h" #include "llares.h" #include "llcurl.h" +#include "lltexturestats.h" +#include "lltexturestats.h" #include "llviewerwindow.h" #include "llviewerdisplay.h" #include "llviewermedia.h" @@ -255,9 +257,6 @@ F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME; BOOL gDisconnected = FALSE; -// Map scale in pixels per region -F32 gMapScale = 128.f; - // used to restore texture state after a mode switch LLFrameTimer gRestoreGLTimer; BOOL gRestoreGL = FALSE; @@ -419,7 +418,7 @@ static void settings_to_globals() gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc"); gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); - gMapScale = gSavedSettings.getF32("MapScale"); + LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale"); LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); } @@ -432,7 +431,7 @@ static void settings_modify() LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession; gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); - + gAuditTexture = gSavedSettings.getBOOL("AuditTexture"); #if LL_VECTORIZE if (gSysCPU.hasAltivec()) { @@ -553,7 +552,7 @@ LLAppViewer* LLAppViewer::sInstance = NULL; const std::string LLAppViewer::sGlobalSettingsName = "Global"; LLTextureCache* LLAppViewer::sTextureCache = NULL; -LLWorkerThread* LLAppViewer::sImageDecodeThread = NULL; +LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; LLTextureFetch* LLAppViewer::sTextureFetch = NULL; LLAppViewer::LLAppViewer() : @@ -620,7 +619,19 @@ bool LLAppViewer::init() if (!initConfiguration()) return false; - + + // Although initLogging() 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(boost::bind(_exit, rc)); + } + mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); // *NOTE:Mani - LLCurl::initClass is not thread safe. @@ -645,6 +656,9 @@ bool LLAppViewer::init() ////////////////////////////////////////////////////////////////////////////// // *FIX: The following code isn't grouped into functions yet. + // Statistics / debug timer initialization + init_statistics(); + // // Various introspection concerning the libs we're using - particularly // the libs involved in getting to a full login screen. @@ -1625,14 +1639,14 @@ bool LLAppViewer::initThreads() LLWatchdog::getInstance()->init(watchdog_killer_callback); } - LLVFSThread::initClass(enable_threads && true); - LLLFSThread::initClass(enable_threads && true); + LLVFSThread::initClass(enable_threads && false); + LLLFSThread::initClass(enable_threads && false); // Image decoding - LLAppViewer::sImageDecodeThread = new LLWorkerThread("ImageDecode", enable_threads && true); + LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true); LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true); - LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), enable_threads && false); - LLImage::initClass(LLAppViewer::getImageDecodeThread()); + LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true); + LLImage::initClass(); if (LLFastTimer::sLog || LLFastTimer::sMetricLog) { @@ -1665,7 +1679,7 @@ bool LLAppViewer::initLogging() LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); LLError::setFatalFunction(errorCallback); - + // Remove the last ".old" log file. std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.old"); @@ -2425,7 +2439,7 @@ void LLAppViewer::cleanupSavedSettings() } } - gSavedSettings.setF32("MapScale", gMapScale ); + gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale ); // Some things are cached in LLAgent. if (gAgent.mInitialized) @@ -2751,7 +2765,7 @@ void LLAppViewer::initMarkerFile() // Create the marker file for this execution & lock it apr_status_t s; - s = mMarkerFile.open(mMarkerFileName, LL_APR_W, gAPRPoolp); + s = mMarkerFile.open(mMarkerFileName, LL_APR_W, TRUE); if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) { diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 73256a8fe6..c1bfbca868 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -41,15 +41,13 @@ class LLCommandLineParser; class LLFrameTimer; class LLPumpIO; class LLTextureCache; +class LLImageDecodeThread; class LLTextureFetch; -class LLTimer; -class LLVFS; class LLWatchdogTimeout; -class LLWorkerThread; +class LLCommandLineParser; struct apr_dso_handle_t; - class LLAppViewer : public LLApp { public: @@ -100,7 +98,7 @@ public: // Thread accessors static LLTextureCache* getTextureCache() { return sTextureCache; } - static LLWorkerThread* getImageDecodeThread() { return sImageDecodeThread; } + static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; } static LLTextureFetch* getTextureFetch() { return sTextureFetch; } const std::string& getSerialNumber() { return mSerialNumber; } @@ -232,7 +230,7 @@ private: // Thread objects. static LLTextureCache* sTextureCache; - static LLWorkerThread* sImageDecodeThread; + static LLImageDecodeThread* sImageDecodeThread; static LLTextureFetch* sTextureFetch; S32 mNumSessions; @@ -320,9 +318,6 @@ extern F32 gSimFrames; extern BOOL gDisconnected; -// Map scale in pixels per region -extern F32 gMapScale; - extern LLFrameTimer gRestoreGLTimer; extern BOOL gRestoreGL; extern BOOL gUseWireframe; diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index cd3963050f..4d85ecb97c 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -41,6 +41,7 @@ #include "llfilepicker.h" #include "llnotify.h" #include "llinventorymodel.h" +#include "llinventorypanel.h" #include "llfloaterinventory.h" #include "llpermissionsflags.h" #include "llpreviewnotecard.h" @@ -333,7 +334,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) LLAssetStorage::LLStoreAssetCallback callback = NULL; void *userdata = NULL; upload_new_resource(next_file, asset_name, asset_name, - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, next_owner_perms, group_perms, everyone_perms, display_name, callback, expected_upload_cost, userdata); @@ -368,7 +369,7 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content) std::string result = content["state"]; LLUUID new_id = content["new_asset"]; - llinfos << "LLSendTexLayerResponder::result from capabilities: " << result << llendl; + llinfos << "result: " << result << "new_id:" << new_id << llendl; if (result == "complete" && mBakedUploadData != NULL) { // Invoke @@ -382,6 +383,14 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content) } } +void LLSendTexLayerResponder::error(U32 statusNum, const std::string& reason) +{ + llinfos << "status: " << statusNum << " reason: " << reason << llendl; + + // Invoke the original callback with an error result + LLTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); + mBakedUploadData = NULL; // deleted in onTextureUploadComplete() +} LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, const LLUUID& vfile_id, diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index a08d70213c..e656351305 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -84,6 +84,7 @@ public: ~LLSendTexLayerResponder(); virtual void uploadComplete(const LLSD& content); + virtual void error(U32 statusNum, const std::string& reason); LLBakedUploadData * mBakedUploadData; }; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 2f67401301..3fc37aa3d5 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -57,6 +57,7 @@ #include "llviewerobjectlist.h" #include "llviewermessage.h" // for handle_lure #include "llviewerregion.h" +#include "llimfloater.h" // static @@ -176,7 +177,11 @@ void LLAvatarActions::startIM(const LLUUID& id) std::string name; gCacheName->getFullName(id, name); - gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id); + LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } make_ui_sound("UISndStartIM"); } @@ -189,7 +194,11 @@ void LLAvatarActions::startConference(const std::vector<LLUUID>& ids) { id_array.push_back(*it); } - gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], id_array); + LLUUID session_id = gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], id_array); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } make_ui_sound("UISndStartIM"); } @@ -343,7 +352,7 @@ bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& re // Servers older than 1.25 require the text of the message to be the // calling card folder ID for the offering user. JC LLUUID calling_card_folder_id = - gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); std::string message = calling_card_folder_id.asString(); requestFriendship(notification["payload"]["id"].asUUID(), notification["payload"]["name"].asString(), @@ -355,7 +364,7 @@ bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& re // static void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message) { - LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + const LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); send_improved_im(target_id, target_name, message, diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index b56e8d1ec2..0ee3e78409 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -44,6 +44,7 @@ #include "llcachename.h" #include "llagentdata.h" +#include "llimfloater.h" #define MENU_ITEM_VIEW_PROFILE 0 #define MENU_ITEM_SEND_IM 1 @@ -354,7 +355,11 @@ void LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked(const LLSD& userdata) name.append(" "); name.append(getLastName()); - gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id); + LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } } else if (level == "add") { diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index ddcee5f453..a17ba79078 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -47,7 +47,7 @@ LLBottomTray::LLBottomTray(const LLSD&) : mChicletPanel(NULL), mSysWell(NULL), - mTalkBtn(NULL), + mSpeakBtn(NULL), mNearbyChatBar(NULL), mToolbarStack(NULL) diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index a28f1e42ec..02588a1975 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -43,7 +43,7 @@ class LLChicletPanel; class LLLineEditor; class LLLayoutStack; class LLNotificationChiclet; -class LLTalkButton; +class LLSpeakButton; class LLNearbyChatBar; class LLIMChiclet; @@ -110,7 +110,7 @@ protected: LLChicletPanel* mChicletPanel; LLNotificationChiclet* mSysWell; - LLTalkButton* mTalkBtn; + LLSpeakButton* mSpeakBtn; LLNearbyChatBar* mNearbyChatBar; LLLayoutStack* mToolbarStack; LLMenuGL* mBottomTrayContextMenu; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index e561507e69..2ccd6b7d35 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -132,8 +132,7 @@ public: menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mPopupMenuHandleObject = menu->getHandle(); - LLPanel* visible_panel = getChild<LLPanel>("im_header"); - visible_panel->setMouseDownCallback(boost::bind(&LLChatHistoryHeader::onHeaderPanelClick, this, _2, _3, _4)); + setMouseDownCallback(boost::bind(&LLChatHistoryHeader::onHeaderPanelClick, this, _2, _3, _4)); return LLPanel::postBuild(); } @@ -290,7 +289,11 @@ mMessageSeparatorFilename(p.message_separator), mLeftTextPad(p.left_text_pad), mRightTextPad(p.right_text_pad), mLeftWidgetPad(p.left_widget_pad), -mRightWidgetPad(p.right_widget_pad) +mRightWidgetPad(p.right_widget_pad), +mTopSeparatorPad(p.top_separator_pad), +mBottomSeparatorPad(p.bottom_separator_pad), +mTopHeaderPad(p.top_header_pad), +mBottomHeaderPad(p.bottom_header_pad) { } @@ -332,16 +335,30 @@ void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& sty LLView* view = NULL; std::string view_text; + LLInlineViewSegment::Params p; + p.force_newline = true; + p.left_pad = mLeftWidgetPad; + p.right_pad = mRightWidgetPad; + if (mLastFromName == chat.mFromName) { view = getSeparator(); view_text = "\n"; + p.top_pad = mTopSeparatorPad; + p.bottom_pad = mBottomSeparatorPad; } else { view = getHeader(chat); view_text = chat.mFromName + MESSAGE_USERNAME_DATE_SEPARATOR + formatCurrentTime() + '\n'; + if (getText().size() == 0) + p.top_pad = 0; + else + p.top_pad = mTopHeaderPad; + p.bottom_pad = mBottomHeaderPad; } + p.view = view; + //Prepare the rect for the view LLRect target_rect = getDocumentView()->getRect(); // squeeze down the widget by subtracting padding off left and right @@ -350,12 +367,6 @@ void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& sty view->reshape(target_rect.getWidth(), view->getRect().getHeight()); view->setOrigin(target_rect.mLeft, view->getRect().mBottom); - LLInlineViewSegment::Params p; - p.view = view; - p.force_newline = true; - p.left_pad = mLeftWidgetPad; - p.right_pad = mRightWidgetPad; - appendWidget(p, view_text, false); //Append the text message diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 92dcfdd958..3789ebff4e 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -54,6 +54,14 @@ class LLChatHistory : public LLTextEditor Optional<S32> left_widget_pad; //Widget right padding from the scroll rect Optional<S32> right_widget_pad; + //Separator top padding + Optional<S32> top_separator_pad; + //Separator bottom padding + Optional<S32> bottom_separator_pad; + //Header top padding + Optional<S32> top_header_pad; + //Header bottom padding + Optional<S32> bottom_header_pad; Params() : message_header("message_header"), @@ -61,7 +69,11 @@ class LLChatHistory : public LLTextEditor left_text_pad("left_text_pad"), right_text_pad("right_text_pad"), left_widget_pad("left_widget_pad"), - right_widget_pad("right_widget_pad") + right_widget_pad("right_widget_pad"), + top_separator_pad("top_separator_pad"), + bottom_separator_pad("bottom_separator_pad"), + top_header_pad("top_header_pad"), + bottom_header_pad("bottom_header_pad") { } @@ -105,9 +117,16 @@ class LLChatHistory : public LLTextEditor std::string mLastFromName; std::string mMessageHeaderFilename; std::string mMessageSeparatorFilename; + S32 mLeftTextPad; S32 mRightTextPad; + S32 mLeftWidgetPad; S32 mRightWidgetPad; + + S32 mTopSeparatorPad; + S32 mBottomSeparatorPad; + S32 mTopHeaderPad; + S32 mBottomHeaderPad; }; #endif /* LLCHATHISTORY_H_ */ diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 594385b4ef..53c4bb32ca 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -51,10 +51,9 @@ #include "lltransientfloatermgr.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); -static LLDefaultChildRegistry::Register<LLTalkButton> t2("chiclet_talk"); -static LLDefaultChildRegistry::Register<LLNotificationChiclet> t3("chiclet_notification"); -static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t4("chiclet_im_p2p"); -static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t5("chiclet_im_group"); +static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification"); +static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p"); +static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group"); S32 LLNotificationChiclet::mUreadSystemNotifications = 0; @@ -212,7 +211,7 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) LLRect chiclet_rect = p.rect; LLRect overlay_icon_rect = LLRect(chiclet_rect.getWidth()/2, chiclet_rect.mTop, chiclet_rect.mRight, chiclet_rect.getHeight()/2); // shift an icon a little bit to the right and up corner of a chiclet - overlay_icon_rect.translate(overlay_icon_rect.getWidth()/4, overlay_icon_rect.getHeight()/4); + overlay_icon_rect.translate(overlay_icon_rect.getWidth()/5, overlay_icon_rect.getHeight()/5); mNewMessagesIcon->setRect(overlay_icon_rect); addChild(mNewMessagesIcon); @@ -247,8 +246,6 @@ BOOL LLIMChiclet::handleMouseDown(S32 x, S32 y, MASK mask) void LLIMChiclet::draw() { LLUICtrl::draw(); - - gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE); } // static @@ -1249,153 +1246,6 @@ bool LLChicletPanel::isAnyIMFloaterDoked() ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -// *TODO Vadim: Move this out of llchiclet.cpp. - -LLTalkButton::Params::Params() - : speak_button("speak_button") - , show_button("show_button") - , monitor("monitor") -{ - // *TODO Vadim: move hardcoded labels (!) and other params to XUI. - speak_button.name("left"); - speak_button.label("Speak"); - speak_button.label_selected("Speak"); - speak_button.font(LLFontGL::getFontSansSerifSmall()); - speak_button.tab_stop(false); - speak_button.is_toggle(true); - speak_button.picture_style(true); - // Use default button art. JC - //speak_button.image_selected(LLUI::getUIImage("SegmentedBtn_Left_Selected")); - //speak_button.image_unselected(LLUI::getUIImage("SegmentedBtn_Left_Off")); - - show_button.name("right"); - show_button.label(LLStringUtil::null); - show_button.rect(LLRect(0, 0, 20, 0)); - show_button.tab_stop(false); - show_button.is_toggle(true); - show_button.picture_style(true); - show_button.image_selected(LLUI::getUIImage("ComboButton_Selected")); - show_button.image_unselected(LLUI::getUIImage("ComboButton_Off")); - - monitor.name("monitor"); - // *TODO: Make this data driven. - monitor.rect(LLRect(0, 18, 18, 0)); -} - -LLTalkButton::LLTalkButton(const Params& p) -: LLUICtrl(p) -, mPrivateCallPanel(NULL) -, mOutputMonitor(NULL) -, mSpeakBtn(NULL) -, mShowBtn(NULL) -{ - LLRect rect = p.rect(); - LLRect speak_rect(0, rect.getHeight(), rect.getWidth(), 0); - LLRect show_rect = p.show_button.rect(); - show_rect.set(0, rect.getHeight(), show_rect.getWidth(), 0); - - speak_rect.mRight -= show_rect.getWidth(); - show_rect.mLeft = speak_rect.getWidth(); - show_rect.mRight = rect.getWidth(); - - LLButton::Params speak_params = p.speak_button; - speak_params.rect(speak_rect); - mSpeakBtn = LLUICtrlFactory::create<LLButton>(speak_params); - addChild(mSpeakBtn); - LLTransientFloaterMgr::getInstance()->addControlView(mSpeakBtn); - - mSpeakBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_SpeakBtn, this)); - mSpeakBtn->setToggleState(FALSE); - - LLButton::Params show_params = p.show_button; - show_params.rect(show_rect); - mShowBtn = LLUICtrlFactory::create<LLButton>(show_params); - addChild(mShowBtn); - LLTransientFloaterMgr::getInstance()->addControlView(mShowBtn); - - mShowBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_ShowBtn, this)); - mShowBtn->setToggleState(FALSE); - - static const S32 MONITOR_RIGHT_PAD = 2; - - LLRect monitor_rect = p.monitor.rect(); - S32 monitor_height = monitor_rect.getHeight(); - monitor_rect.mLeft = speak_rect.getWidth() - monitor_rect.getWidth() - MONITOR_RIGHT_PAD; - monitor_rect.mRight = speak_rect.getWidth() - MONITOR_RIGHT_PAD; - monitor_rect.mBottom = (rect.getHeight() / 2) - (monitor_height / 2); - monitor_rect.mTop = monitor_rect.mBottom + monitor_height; - - LLOutputMonitorCtrl::Params monitor_params = p.monitor; - monitor_params.draw_border(false); - monitor_params.rect(monitor_rect); - monitor_params.auto_update(true); - monitor_params.speaker_id(gAgentID); - mOutputMonitor = LLUICtrlFactory::create<LLOutputMonitorCtrl>(monitor_params); - mSpeakBtn->addChild(mOutputMonitor); - - // never show "muted" because you can't mute yourself - mOutputMonitor->setIsMuted(false); - mOutputMonitor->setIsAgentControl(true); -} - -LLTalkButton::~LLTalkButton() -{ -} - -void LLTalkButton::setSpeakBtnToggleState(bool state) -{ - mSpeakBtn->setToggleState(state); -} - -void LLTalkButton::onClick_SpeakBtn() -{ - bool speaking = mSpeakBtn->getToggleState(); - gVoiceClient->setUserPTTState(speaking); -} - -void LLTalkButton::onClick_ShowBtn() -{ - if(!mShowBtn->getToggleState()) - { - mPrivateCallPanel->onClickClose(mPrivateCallPanel); - delete mPrivateCallPanel; - mPrivateCallPanel = NULL; - mShowBtn->setToggleState(FALSE); - return; - } - - S32 x = mSpeakBtn->getRect().mLeft; - S32 y = 0; - - localPointToScreen(x, y, &x, &y); - - mPrivateCallPanel = new LLVoiceControlPanel; - getRootView()->addChild(mPrivateCallPanel); - - y = LLBottomTray::getInstance()->getRect().getHeight() + mPrivateCallPanel->getRect().getHeight(); - - LLRect rect; - rect.setLeftTopAndSize(x, y, mPrivateCallPanel->getRect().getWidth(), mPrivateCallPanel->getRect().getHeight()); - mPrivateCallPanel->setRect(rect); - - - LLAvatarListItem* item = new LLAvatarListItem(); - item->showLastInteractionTime(false); - item->showInfoBtn(true); - item->showSpeakingIndicator(true); - item->reshape(mPrivateCallPanel->getRect().getWidth(), item->getRect().getHeight(), FALSE); - - mPrivateCallPanel->addItem(item); - mPrivateCallPanel->setVisible(TRUE); - mPrivateCallPanel->setFrontmost(TRUE); - - mShowBtn->setToggleState(TRUE); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - LLChicletNotificationCounterCtrl::LLChicletNotificationCounterCtrl(const Params& p) : LLTextBox(p) , mCounter(0) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index a830240b7d..b50702205c 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -853,42 +853,6 @@ protected: bool mShowControls; }; -/* - * Button displaying voice chat status. Displays voice chat options When clicked. -*/ -class LLTalkButton : public LLUICtrl -{ -public: - - struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> - { - Optional<LLButton::Params> speak_button, - show_button; - - Optional<LLOutputMonitorCtrl::Params> monitor; - - Params(); - }; - - /*virtual*/ ~LLTalkButton(); - - void setSpeakBtnToggleState(bool state); - -protected: - friend class LLUICtrlFactory; - LLTalkButton(const Params& p); - - void onClick_SpeakBtn(); - - void onClick_ShowBtn(); - -private: - LLButton* mSpeakBtn; - LLButton* mShowBtn; - LLVoiceControlPanel* mPrivateCallPanel; - LLOutputMonitorCtrl* mOutputMonitor; -}; - template<class T> T* LLChicletPanel::createChiclet(const LLUUID& session_id, S32 index) { diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 7b75c77a1e..442e9ab27b 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -228,7 +228,8 @@ void LLColorSwatchCtrl::draw() { if (!mFallbackImageName.empty()) { - LLPointer<LLViewerTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + LLPointer<LLViewerFetchedTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE, + LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if( fallback_image->getComponents() == 4 ) { gl_rect_2d_checkerboard( interior ); diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp index c4bfd71999..319cbf8209 100644 --- a/indra/newview/llcurrencyuimanager.cpp +++ b/indra/newview/llcurrencyuimanager.cpp @@ -76,8 +76,15 @@ public: bool mUserEnteredCurrencyBuy; // from website - bool mSiteCurrencyEstimated; - S32 mSiteCurrencyEstimatedCost; + + // pre-viewer 2.0, the server returned estimates as an + // integer US cents value, e.g., "1000" for $10.00 + // post-viewer 2.0, the server may also return estimates + // as a string with currency embedded, e.g., "10.00 Euros" + bool mUSDCurrencyEstimated; + S32 mUSDCurrencyEstimatedCost; + bool mLocalCurrencyEstimated; + std::string mLocalCurrencyEstimatedCost; std::string mSiteConfirm; bool mBought; @@ -101,6 +108,10 @@ public: void startCurrencyBuy(const std::string& password); void finishCurrencyBuy(); + + void clearEstimate(); + bool hasEstimate() const; + std::string getLocalEstimate() const; void startTransaction(TransactionType type, const char* method, LLXMLRPCValue params); @@ -126,12 +137,11 @@ LLCurrencyUIManager::Impl::Impl(LLPanel& dialog) mError(false), mUserCurrencyBuy(2000), // note, this is a default, real value set in llfloaterbuycurrency.cpp mUserEnteredCurrencyBuy(false), - mSiteCurrencyEstimated(false), - mSiteCurrencyEstimatedCost(0), mBought(false), mTransactionType(TransactionNone), mTransaction(0), mCurrencyChanged(false) { + clearEstimate(); } LLCurrencyUIManager::Impl::~Impl() @@ -141,14 +151,13 @@ LLCurrencyUIManager::Impl::~Impl() void LLCurrencyUIManager::Impl::updateCurrencyInfo() { - mSiteCurrencyEstimated = false; - mSiteCurrencyEstimatedCost = 0; + clearEstimate(); mBought = false; mCurrencyChanged = false; if (mUserCurrencyBuy == 0) { - mSiteCurrencyEstimated = true; + mLocalCurrencyEstimated = true; return; } @@ -185,9 +194,21 @@ void LLCurrencyUIManager::Impl::finishCurrencyInfo() } LLXMLRPCValue currency = result["currency"]; - mSiteCurrencyEstimated = true; - mSiteCurrencyEstimatedCost = currency["estimatedCost"].asInt(); - + + // old XML-RPC server: estimatedCost = value in US cents + mUSDCurrencyEstimated = currency["estimatedCost"].isValid(); + if (mUSDCurrencyEstimated) + { + mUSDCurrencyEstimatedCost = currency["estimatedCost"].asInt(); + } + + // newer XML-RPC server: estimatedLocalCost = local currency string + mLocalCurrencyEstimated = currency["estimatedLocalCost"].isValid(); + if (mLocalCurrencyEstimated) + { + mLocalCurrencyEstimatedCost = currency["estimatedLocalCost"].asString(); + } + S32 newCurrencyBuy = currency["currencyBuy"].asInt(); if (newCurrencyBuy != mUserCurrencyBuy) { @@ -200,17 +221,20 @@ void LLCurrencyUIManager::Impl::finishCurrencyInfo() void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password) { - mSiteCurrencyEstimated = false; - mSiteCurrencyEstimatedCost = 0; - mCurrencyChanged = false; - LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct(); keywordArgs.appendString("agentId", gAgent.getID().asString()); keywordArgs.appendString( "secureSessionId", gAgent.getSecureSessionID().asString()); keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy); - keywordArgs.appendInt("estimatedCost", mSiteCurrencyEstimatedCost); + if (mUSDCurrencyEstimated) + { + keywordArgs.appendInt("estimatedCost", mUSDCurrencyEstimatedCost); + } + if (mLocalCurrencyEstimated) + { + keywordArgs.appendString("estimatedLocalCost", mLocalCurrencyEstimatedCost); + } keywordArgs.appendString("confirm", mSiteConfirm); if (!password.empty()) { @@ -226,6 +250,9 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password) params.append(keywordArgs); startTransaction(TransactionBuy, "buyCurrency", params); + + clearEstimate(); + mCurrencyChanged = false; } void LLCurrencyUIManager::Impl::finishCurrencyBuy() @@ -270,6 +297,34 @@ void LLCurrencyUIManager::Impl::startTransaction(TransactionType type, clearError(); } +void LLCurrencyUIManager::Impl::clearEstimate() +{ + mUSDCurrencyEstimated = false; + mUSDCurrencyEstimatedCost = 0; + mLocalCurrencyEstimated = false; + mLocalCurrencyEstimatedCost = "0"; +} + +bool LLCurrencyUIManager::Impl::hasEstimate() const +{ + return (mUSDCurrencyEstimated || mLocalCurrencyEstimated); +} + +std::string LLCurrencyUIManager::Impl::getLocalEstimate() const +{ + if (mLocalCurrencyEstimated) + { + // we have the new-style local currency string + return mLocalCurrencyEstimatedCost; + } + if (mUSDCurrencyEstimated) + { + // we have the old-style USD-specific value + return "US$ " + llformat("%#.2f", mUSDCurrencyEstimatedCost / 100.0); + } + return ""; +} + bool LLCurrencyUIManager::Impl::checkTransaction() { if (!mTransaction) @@ -342,8 +397,8 @@ void LLCurrencyUIManager::Impl::currencyKey(S32 value) mUserCurrencyBuy = value; - if (mSiteCurrencyEstimated) { - mSiteCurrencyEstimated = false; + if (hasEstimate()) { + clearEstimate(); //cannot just simply refresh the whole UI, as the edit field will // get reset and the cursor will change... @@ -406,8 +461,8 @@ void LLCurrencyUIManager::Impl::updateUI() } } - mPanel.childSetTextArg("currency_est", "[LOCALAMOUNT]", "US$ " + llformat("%#.2f", mSiteCurrencyEstimatedCost / 100.0)); - mPanel.childSetVisible("currency_est", mSiteCurrencyEstimated && mUserCurrencyBuy > 0); + mPanel.childSetTextArg("currency_est", "[LOCALAMOUNT]", getLocalEstimate()); + mPanel.childSetVisible("currency_est", hasEstimate() && mUserCurrencyBuy > 0); if (mPanel.childIsEnabled("buy_btn") ||mPanel.childIsVisible("currency_est") @@ -448,18 +503,32 @@ void LLCurrencyUIManager::setZeroMessage(const std::string& message) impl.mZeroMessage = message; } -void LLCurrencyUIManager::setEstimate(int amount) +void LLCurrencyUIManager::setUSDEstimate(int amount) +{ + impl.mUSDCurrencyEstimatedCost = amount; + impl.mUSDCurrencyEstimated = true; + impl.updateUI(); + + impl.mCurrencyChanged = false; +} + +int LLCurrencyUIManager::getUSDEstimate() +{ + return impl.mUSDCurrencyEstimated ? impl.mUSDCurrencyEstimatedCost : 0; +} + +void LLCurrencyUIManager::setLocalEstimate(const std::string &amount) { - impl.mSiteCurrencyEstimatedCost = amount; - impl.mSiteCurrencyEstimated = true; + impl.mLocalCurrencyEstimatedCost = amount; + impl.mLocalCurrencyEstimated = true; impl.updateUI(); impl.mCurrencyChanged = false; } -int LLCurrencyUIManager::getEstimate() +std::string LLCurrencyUIManager::getLocalEstimate() const { - return impl.mSiteCurrencyEstimated ? impl.mSiteCurrencyEstimatedCost : 0; + return impl.getLocalEstimate(); } void LLCurrencyUIManager::prepare() @@ -490,7 +559,7 @@ void LLCurrencyUIManager::buy(const std::string& buy_msg) LLUIString msg = buy_msg; msg.setArg("[LINDENS]", llformat("%d", impl.mUserCurrencyBuy)); - msg.setArg("[LOCALAMOUNT]", "US$ " + llformat("%#.2f", impl.mSiteCurrencyEstimatedCost / 100.0)); + msg.setArg("[LOCALAMOUNT]", getLocalEstimate()); LLConfirmationManager::confirm(impl.mSiteConfirm, msg, impl, @@ -511,7 +580,7 @@ bool LLCurrencyUIManager::canCancel() bool LLCurrencyUIManager::canBuy() { return impl.mTransactionType == Impl::TransactionNone - && impl.mSiteCurrencyEstimated + && impl.hasEstimate() && impl.mUserCurrencyBuy > 0; } diff --git a/indra/newview/llcurrencyuimanager.h b/indra/newview/llcurrencyuimanager.h index 93427aed7f..dfe027098d 100644 --- a/indra/newview/llcurrencyuimanager.h +++ b/indra/newview/llcurrencyuimanager.h @@ -57,11 +57,16 @@ public: void setZeroMessage(const std::string& message); // sets the gray message to show when zero - void setEstimate(int); - int getEstimate(); + void setUSDEstimate(int); // deprecated in 2.0 + int getUSDEstimate(); // deprecated in 2.0 // the amount in US$ * 100 (in otherwords, in cents) // use set when you get this information from elsewhere + void setLocalEstimate(const std::string &local_est); + std::string getLocalEstimate() const; + // the estimated cost in the user's local currency + // for example, "US$ 10.00" or "10.00 Euros" + void prepare(); // call once after dialog is built, from postBuild() void updateUI(bool show = true); diff --git a/indra/newview/lldebugmessagebox.cpp b/indra/newview/lldebugmessagebox.cpp index 29e375c9fa..7814e94dfd 100644 --- a/indra/newview/lldebugmessagebox.cpp +++ b/indra/newview/lldebugmessagebox.cpp @@ -124,6 +124,7 @@ LLDebugVarMessageBox::LLDebugVarMessageBox(const std::string& title, EDebugVarTy LLButton::Params p; p.name(std::string("Animate")); + p.label(std::string("Animate")); p.rect(LLRect(20, 45, 180, 25)); p.click_callback.function(boost::bind(&LLDebugVarMessageBox::onAnimateClicked, this, _2)); mAnimateButton = LLUICtrlFactory::create<LLButton>(p); diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp index 24a57cb0c1..9057d84f63 100644 --- a/indra/newview/lldebugview.cpp +++ b/indra/newview/lldebugview.cpp @@ -45,7 +45,7 @@ #include "llviewerwindow.h" #include "llappviewer.h" #include "llmemoryview.h" - +#include "llviewertexture.h" // // Globals // @@ -102,17 +102,29 @@ LLDebugView::LLDebugView(const LLDebugView::Params& p) gTextureView = LLUICtrlFactory::create<LLTextureView>(tvp); addChild(gTextureView); //gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE); -#if !LL_RELEASE_FOR_DOWNLOAD - r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100); - LLTextureSizeView::Params tsvp; - tsvp.name("gTextureSizeView"); - tsvp.rect(r); - tsvp.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT); - tsvp.visible(false); - gTextureSizeView = LLUICtrlFactory::create<LLTextureSizeView>(tsvp); - addChild(gTextureSizeView); -#endif + if(gAuditTexture) + { + r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100); + LLTextureSizeView::Params tsv ; + tsv.name("gTextureSizeView"); + tsv.rect(r); + tsv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT); + tsv.visible(false); + gTextureSizeView = LLUICtrlFactory::create<LLTextureSizeView>(tsv); + addChild(gTextureSizeView); + gTextureSizeView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_SIZE) ; + + r.set(150, rect.getHeight() - 50, 900 + LLViewerTexture::getTotalNumOfCategories() * 30, 100); + LLTextureSizeView::Params tcv ; + tcv.name("gTextureCategoryView"); + tcv.rect(r); + tcv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT); + tcv.visible(false); + gTextureCategoryView = LLUICtrlFactory::create<LLTextureSizeView>(tcv); + gTextureCategoryView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_CATEGORY); + addChild(gTextureCategoryView); + } } @@ -122,5 +134,6 @@ LLDebugView::~LLDebugView() gDebugView = NULL; gTextureView = NULL; gTextureSizeView = NULL; + gTextureCategoryView = NULL; } diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 069155c255..03a3f2b43d 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -105,7 +105,7 @@ void LLDrawable::init() mVObjp = NULL; // mFaces mSpatialGroupp = NULL; - mVisible = 0; + mVisible = sCurVisible - 2;//invisible for the current frame and the last frame. mRadius = 0.f; mGeneration = -1; diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index d8c34581d5..95ddacb722 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -279,7 +279,7 @@ S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage) iter != face_list.end(); iter++) { LLFace *facep = *iter; - gGL.getTexUnit(stage)->bind(facep->getTexture()); + gGL.getTexUnit(stage)->bind(facep->getTexture(), TRUE) ; gGL.getTexUnit(0)->activate(); res += facep->renderIndexed(); } @@ -475,17 +475,13 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) { if (params.mTexture.notNull()) { - gGL.getTexUnit(0)->bind(params.mTexture.get()); + gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; if (params.mTextureMatrix) { glMatrixMode(GL_TEXTURE); glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); gPipeline.mTextureMatrixOps++; } - if(params.mTexture.notNull())//will be removed. - { - params.mTexture->addTextureStats(params.mVSize); - } } else { diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index a5a29dea7b..6d77361414 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -219,7 +219,7 @@ void LLDrawPoolAlpha::render(S32 pass) gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); glColor4f(1,0,0,1); LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep) ; + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ; renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index e087feeaec..5f845c3721 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -144,7 +144,7 @@ void LLStandardBumpmap::restoreGL() gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id), TRUE, - FALSE, + LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 790e75cfaa..9dc22cddcd 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -72,7 +72,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); mAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga", - TRUE, TRUE, + TRUE, LLViewerTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, GL_ALPHA8, GL_ALPHA, LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); @@ -81,7 +81,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", - TRUE, TRUE, + TRUE, LLViewerTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, GL_ALPHA8, GL_ALPHA, LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 8d2cbc583c..5521fb05a8 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -253,7 +253,7 @@ void LLDrawPoolTree::renderTree(BOOL selecting) LLGLState normalize(GL_NORMALIZE, TRUE); // Bind the texture for this tree. - gGL.getTexUnit(sDiffTex)->bind(mTexturep.get()); + gGL.getTexUnit(sDiffTex)->bind(mTexturep.get(), TRUE); U32 indices_drawn = 0; diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 21e17cc207..107de934df 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -69,11 +69,11 @@ LLVector3 LLDrawPoolWater::sLightDir; LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER) { - mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, TRUE); + mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[0]) ; mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP); - mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, TRUE); + mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[1]); mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 527656ab6b..45f4b4fbd0 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -224,7 +224,6 @@ void LLDriverParam::setAvatar(LLVOAvatar *avatarp) } } *new_param = *this; - new_param->setIsDummy(FALSE); return new_param; } diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 0bb5edf3f9..e41c4104eb 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -104,7 +104,7 @@ void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum { setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); } - createGLTexture(0, raw_image); + createGLTexture(0, raw_image, 0, TRUE, LLViewerTexture::DYNAMIC_TEX); setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); mGLTexturep->setGLTextureCreated(false); } diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 7bc48185e6..424d635321 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -48,11 +48,12 @@ public: mExpanderLabel(more_text) {} - /*virtual*/ void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const + /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { // more label always spans width of text box width = mEditor.getTextRect().getWidth() - mEditor.getHPad(); height = llceil(mStyle->getFont()->getLineHeight()); + return true; } /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 09b3ce1e86..c54b83d865 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -52,6 +52,7 @@ #include "llvovolume.h" #include "pipeline.h" #include "llviewerregion.h" +#include "llviewerwindow.h" #define LL_MAX_INDICES_COUNT 1000000 @@ -175,6 +176,9 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mLastIndicesCount = mIndicesCount; mLastIndicesIndex = mIndicesIndex; + mImportanceToCamera = 0.f ; + mBoundingSphereRadius = 0.0f ; + mAtlasInfop = NULL ; mUsingAtlas = FALSE ; } @@ -186,6 +190,7 @@ void LLFace::destroy() { mTexture->removeFace(this) ; } + if (mDrawPoolp) { mDrawPoolp->removeFace(this); @@ -207,7 +212,7 @@ void LLFace::destroy() } } } - + setDrawInfo(NULL); removeAtlas(); @@ -256,6 +261,7 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep) } mDrawPoolp = new_pool; } + setTexture(texturep) ; } @@ -515,8 +521,8 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) /* removed in lieu of raycast uv detection void LLFace::renderSelectedUV() { - LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, TRUE); - LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test2.tga", TRUE, TRUE); + LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, LLViewerTexture::BOOST_UI); + LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test2.tga", TRUE, LLViewerTexture::BOOST_UI); LLGLSUVSelect object_select; @@ -750,7 +756,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, } mCenterLocal = (newMin+newMax)*0.5f; - + LLVector3 tmp = (newMin - newMax) ; + mBoundingSphereRadius = tmp.length() * 0.5f ; + updateCenterAgent(); } @@ -1314,6 +1322,151 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, return TRUE; } +const F32 LEAST_IMPORTANCE = 0.05f ; +const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ; + +F32 LLFace::getTextureVirtualSize() +{ + F32 radius; + F32 cos_angle_to_view_dir; + mPixelArea = calcPixelArea(cos_angle_to_view_dir, radius); + + if (mPixelArea <= 0) + { + return 0.f; + } + + //get area of circle in texture space + LLVector2 tdim = mTexExtents[1] - mTexExtents[0]; + F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; + if (texel_area <= 0) + { + // Probably animated, use default + texel_area = 1.f; + } + + //apply texel area to face area to get accurate ratio + //face_area /= llclamp(texel_area, 1.f/64.f, 16.f); + F32 face_area = mPixelArea / llclamp(texel_area, 0.015625f, 128.f); + + if(face_area > LLViewerTexture::sMaxSmallImageSize) + { + if(mImportanceToCamera < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res. + { + static const F32 MAX_LEAST_IMPORTANCE_IMAGE_SIZE = 128.0f * 128.0f ; + face_area = llmin(face_area * 0.5f, MAX_LEAST_IMPORTANCE_IMAGE_SIZE) ; + } + else if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. + { + if(mImportanceToCamera < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res. + { + face_area = LLViewerTexture::sMinLargeImageSize ; + } + else if(mTexture.notNull() && mTexture->isLargeImage()) + { + face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius ); + } + } + } + + return face_area; +} + +F32 LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) +{ + //get area of circle around face + LLVector3 center = getPositionAgent(); + LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f; + + LLVector3 lookAt = center - LLViewerCamera::getInstance()->getOrigin(); + F32 dist = lookAt.normVec() ; + + //get area of circle around node + F32 app_angle = atanf(size.length()/dist); + radius = app_angle*LLDrawable::sCurPixelAngle; + F32 face_area = radius*radius * 3.14159f; + + if(dist < mBoundingSphereRadius) //camera is very close + { + cos_angle_to_view_dir = 1.0f ; + mImportanceToCamera = 1.0f ; + } + else + { + cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; + mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ; + } + + return face_area ; +} + +//the projection of the face partially overlaps with the screen +F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ) +{ + F32 screen_radius = (F32)llmax(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()) ; + F32 center_angle = acosf(cos_angle_to_view_dir) ; + F32 d = center_angle * LLDrawable::sCurPixelAngle ; + + if(d + radius > screen_radius + 5.f) + { + //---------------------------------------------- + //calculate the intersection area of two circles + //F32 radius_square = radius * radius ; + //F32 d_square = d * d ; + //F32 screen_radius_square = screen_radius * screen_radius ; + //face_area = + // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) + + // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) - + // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ; + //---------------------------------------------- + + //the above calculation is too expensive + //the below is a good estimation: bounding box of the bounding sphere: + F32 alpha = 0.5f * (radius + screen_radius - d) / radius ; + alpha = llclamp(alpha, 0.f, 1.f) ; + return alpha * alpha ; + } + return 1.0f ; +} + +const S8 FACE_IMPORTANCE_LEVEL = 4 ; +const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight} + {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ; +const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight} + {{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ; + +//static +F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist) +{ + F32 importance = 0.f ; + + if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && + dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) + { + F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; + F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); + + if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f) + { + //if camera moves or rotates too fast, ignore the importance factor + return 0.f ; + } + + //F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ; + + S32 i = 0 ; + for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i); + i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; + F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ; + + for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ; + i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; + importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ; + } + + return importance ; +} + BOOL LLFace::verify(const U32* indices_array) const { BOOL ok = TRUE; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 2b134c8c31..68eee061b8 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -188,6 +188,9 @@ public: void setIndicesIndex(S32 idx) { mIndicesIndex = idx; } void setDrawInfo(LLDrawInfo* draw_info); + F32 getTextureVirtualSize() ; + F32 getImportanceToCamera()const {return mImportanceToCamera ;} + //for atlas LLTextureAtlasSlot* getAtlasInfo() ; void setAtlasInUse(BOOL flag); @@ -200,6 +203,12 @@ public: void removeAtlas() ; BOOL switchTexture() ; +private: + F32 adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ); + F32 calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) ; +public: + static F32 calcImportanceToCamera(F32 to_view_dir, F32 dist); + public: LLVector3 mCenterLocal; @@ -214,7 +223,7 @@ public: LLMatrix4* mTextureMatrix; LLDrawInfo* mDrawInfo; -protected: +private: friend class LLGeometryManager; friend class LLVolumeGeometryManager; @@ -244,6 +253,13 @@ protected: F32 mVSize; F32 mPixelArea; + //importance factor, in the range [0, 1.0]. + //1.0: the most important. + //based on the distance from the face to the view point and the angle from the face center to the view direction. + F32 mImportanceToCamera ; + F32 mBoundingSphereRadius ; + + //atlas LLPointer<LLTextureAtlasSlot> mAtlasInfop ; BOOL mUsingAtlas ; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index a6afbc05be..18135fc558 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -437,7 +437,7 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, } else { - LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + const LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); if (item->getParentUUID() == favorites_id) { llwarns << "Attemt to copy a favorite item into the same folder." << llendl; @@ -539,7 +539,7 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con LLToolDragAndDrop* tool_dad = LLToolDragAndDrop::getInstance(); if (tool_dad->getSource() == LLToolDragAndDrop::SOURCE_NOTECARD) { - viewer_item->setType(LLAssetType::AT_FAVORITE); + viewer_item->setType(LLAssetType::AT_LANDMARK); copy_inventory_from_notecard(tool_dad->getObjectID(), tool_dad->getSourceID(), viewer_item.get(), gInventoryCallbacks.registerCB(cb)); } else @@ -561,7 +561,7 @@ void LLFavoritesBarCtrl::changed(U32 mask) { if (mFavoriteFolderId.isNull()) { - mFavoriteFolderId = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + mFavoriteFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); if (mFavoriteFolderId.notNull()) { @@ -750,6 +750,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) bparams.tab_stop(false); bparams.font(mFont); bparams.name(">>"); + bparams.label(">>"); bparams.tool_tip(mChevronButtonToolTip); bparams.click_callback.function(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this)); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 88658f7b9f..b01293d17c 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -1,343 +1,343 @@ -/**
- * @file llfloaterabout.cpp
- * @author James Cook
- * @brief The about box from Help->About
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterabout.h"
-
-// Viewer includes
-#include "llagent.h"
-#include "llappviewer.h"
-#include "llsecondlifeurls.h"
-#include "llvoiceclient.h"
-#include "lluictrlfactory.h"
-#include "llviewertexteditor.h"
-#include "llviewercontrol.h"
-#include "llviewerstats.h"
-#include "llviewerregion.h"
-#include "llversionviewer.h"
-#include "llviewerbuild.h"
-#include "llweb.h"
-
-// Linden library includes
-#include "llaudioengine.h"
-#include "llbutton.h"
-#include "llcurl.h"
-#include "llglheaders.h"
-#include "llfloater.h"
-#include "llfloaterreg.h"
-#include "llimagej2c.h"
-#include "llsys.h"
-#include "lltrans.h"
-#include "lluri.h"
-#include "v3dmath.h"
-#include "llwindow.h"
-#include "stringize.h"
-#include "llsdutil_math.h"
-#include "lleventdispatcher.h"
-
-#if LL_WINDOWS
-#include "lldxhardware.h"
-#endif
-
-extern LLMemoryInfo gSysMemory;
-extern U32 gPacketsIn;
-
-static std::string get_viewer_release_notes_url();
-
-
-///----------------------------------------------------------------------------
-/// Class LLFloaterAbout
-///----------------------------------------------------------------------------
-class LLFloaterAbout
- : public LLFloater
-{
- friend class LLFloaterReg;
-private:
- LLFloaterAbout(const LLSD& key);
- virtual ~LLFloaterAbout();
-
-public:
- /*virtual*/ BOOL postBuild();
-
- /// Obtain the data used to fill out the contents string. This is
- /// separated so that we can programmatically access the same info.
- static LLSD getInfo();
- void onClickCopyToClipboard();
-};
-
-
-// Default constructor
-LLFloaterAbout::LLFloaterAbout(const LLSD& key)
-: LLFloater(key)
-{
- //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml");
-
-}
-
-// Destroys the object
-LLFloaterAbout::~LLFloaterAbout()
-{
-}
-
-BOOL LLFloaterAbout::postBuild()
-{
- center();
- LLViewerTextEditor *support_widget =
- getChild<LLViewerTextEditor>("support_editor", true);
-
- LLViewerTextEditor *credits_widget =
- getChild<LLViewerTextEditor>("credits_editor", true);
-
- getChild<LLUICtrl>("copy_btn")->setCommitCallback(
- boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
-
-#if LL_WINDOWS
- getWindow()->incBusyCount();
- getWindow()->setCursor(UI_CURSOR_ARROW);
-#endif
- LLSD info(getInfo());
-#if LL_WINDOWS
- getWindow()->decBusyCount();
- getWindow()->setCursor(UI_CURSOR_ARROW);
-#endif
-
- std::ostringstream support;
-
- // Render the LLSD from getInfo() as a format_map_t
- LLStringUtil::format_map_t args;
- // For reasons I don't yet understand, [ReleaseNotes] is not part of the
- // default substitution strings whereas [APP_NAME] is. But it works to
- // simply copy it into these specific args.
- args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes");
- 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] = getString("none");
- }
- 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 << getString("AboutHeader", args);
- if (info.has("COMPILER"))
- {
- support << "\n\n" << getString("AboutCompiler", args);
- }
- if (info.has("REGION"))
- {
- support << "\n\n" << getString("AboutPosition", args);
- }
- support << "\n\n" << getString("AboutSystem", args);
- if (info.has("GRAPHICS_DRIVER_VERSION"))
- {
- support << "\n\n" << getString("AboutDriver", args);
- }
- support << "\n\n" << getString("AboutLibs", args);
- if (info.has("PACKETS_IN"))
- {
- support << '\n' << getString("AboutTraffic", args);
- }
-
- support_widget->appendText(support.str(),
- FALSE,
- LLStyle::Params()
- .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
- support_widget->blockUndo();
-
- // Fix views
- support_widget->setCursorPos(0);
- support_widget->setEnabled(FALSE);
-
- credits_widget->setCursorPos(0);
- credits_widget->setEnabled(FALSE);
-
- return TRUE;
-}
-
-// static
-LLSD LLFloaterAbout::getInfo()
-{
- // 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;
- LLSD version;
- version.append(LL_VERSION_MAJOR);
- version.append(LL_VERSION_MINOR);
- version.append(LL_VERSION_PATCH);
- version.append(LL_VERSION_BUILD);
- info["VIEWER_VERSION"] = version;
- info["VIEWER_VERSION_STR"] = STRINGIZE(version[0].asInteger() << '.' <<
- version[1].asInteger() << '.' <<
- version[2].asInteger() << '.' <<
- version[3].asInteger());
- info["BUILD_DATE"] = __DATE__;
- info["BUILD_TIME"] = __TIME__;
- info["CHANNEL"] = gSavedSettings.getString("VersionChannelName");
-
- info["VIEWER_RELEASE_NOTES_URL"] = get_viewer_release_notes_url();
-
-#if LL_MSVC
- info["COMPILER"] = "MSVC";
- info["COMPILER_VERSION"] = _MSC_VER;
-#elif LL_GNUC
- info["COMPILER"] = "GCC";
- info["COMPILER_VERSION"] = GCC_VERSION;
-#endif
-
- // Position
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- const LLVector3d &pos = gAgent.getPositionGlobal();
- info["POSITION"] = ll_sd_from_vector3d(pos);
- info["REGION"] = gAgent.getRegion()->getName();
- info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName();
- info["HOSTIP"] = gAgent.getRegion()->getHost().getString();
- info["SERVER_VERSION"] = gLastVersionChannel;
- info["SERVER_RELEASE_NOTES_URL"] = LLWeb::escapeURL(region->getCapability("ServerReleaseNotes"));
- }
-
- // CPU
- info["CPU"] = gSysCPU.getCPUString();
- info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB() / 1024);
- // Moved hack adjustment to Windows memory size into llsys.cpp
- info["OS_VERSION"] = LLAppViewer::instance()->getOSInfo().getOSString();
- info["GRAPHICS_CARD_VENDOR"] = (const char*)(glGetString(GL_VENDOR));
- info["GRAPHICS_CARD"] = (const char*)(glGetString(GL_RENDERER));
-
-#if LL_WINDOWS
- LLSD driver_info = gDXHardware.getDisplayInfo();
- if (driver_info.has("DriverVersion"))
- {
- info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
- }
-#endif
-
- info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION));
- info["LIBCURL_VERSION"] = LLCurl::getVersionString();
- info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
- bool want_fullname = true;
- info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
- info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : "Unknown";
-
- // TODO: Implement media plugin version query
- info["QT_WEBKIT_VERSION"] = "4.5.2";
-
- if (gPacketsIn > 0)
- {
- info["PACKETS_LOST"] = LLViewerStats::getInstance()->mPacketsLostStat.getCurrent();
- info["PACKETS_IN"] = F32(gPacketsIn);
- info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal();
- }
-
- return info;
-}
-
-static std::string get_viewer_release_notes_url()
-{
- std::ostringstream version;
- version << LL_VERSION_MAJOR << "."
- << LL_VERSION_MINOR << "."
- << LL_VERSION_PATCH << "."
- << LL_VERSION_BUILD;
-
- LLSD query;
- query["channel"] = gSavedSettings.getString("VersionChannelName");
- query["version"] = version.str();
-
- std::ostringstream url;
- url << LLTrans::getString("RELEASE_NOTES_BASE_URL") << LLURI::mapToQueryString(query);
-
- return LLWeb::escapeURL(url.str());
-}
-
-class LLFloaterAboutListener: public LLDispatchListener
-{
-public:
- LLFloaterAboutListener():
- LLDispatchListener("LLFloaterAbout", "op")
- {
- add("getInfo", &LLFloaterAboutListener::getInfo, LLSD().insert("reply", LLSD()));
- }
-
-private:
- void getInfo(const LLSD& request) const
- {
- LLReqID reqid(request);
- LLSD reply(LLFloaterAbout::getInfo());
- reqid.stamp(reply);
- LLEventPumps::instance().obtain(request["reply"]).post(reply);
- }
-};
-
-static LLFloaterAboutListener floaterAboutListener;
-
-void LLFloaterAbout::onClickCopyToClipboard()
-{
- LLViewerTextEditor *support_widget =
- getChild<LLViewerTextEditor>("support_editor", true);
- support_widget->selectAll();
- support_widget->copy();
- support_widget->deselect();
-}
-
-///----------------------------------------------------------------------------
-/// LLFloaterAboutUtil
-///----------------------------------------------------------------------------
-void LLFloaterAboutUtil::registerFloater()
-{
- LLFloaterReg::add("sl_about", "floater_about.xml",
- &LLFloaterReg::build<LLFloaterAbout>);
-
-}
+/** + * @file llfloaterabout.cpp + * @author James Cook + * @brief The about box from Help->About + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterabout.h" + +// Viewer includes +#include "llagent.h" +#include "llappviewer.h" +#include "llsecondlifeurls.h" +#include "llvoiceclient.h" +#include "lluictrlfactory.h" +#include "llviewertexteditor.h" +#include "llviewercontrol.h" +#include "llviewerstats.h" +#include "llviewerregion.h" +#include "llversionviewer.h" +#include "llviewerbuild.h" +#include "llweb.h" + +// Linden library includes +#include "llaudioengine.h" +#include "llbutton.h" +#include "llcurl.h" +#include "llglheaders.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "llimagej2c.h" +#include "llsys.h" +#include "lltrans.h" +#include "lluri.h" +#include "v3dmath.h" +#include "llwindow.h" +#include "stringize.h" +#include "llsdutil_math.h" +#include "lleventdispatcher.h" + +#if LL_WINDOWS +#include "lldxhardware.h" +#endif + +extern LLMemoryInfo gSysMemory; +extern U32 gPacketsIn; + +static std::string get_viewer_release_notes_url(); + + +///---------------------------------------------------------------------------- +/// Class LLFloaterAbout +///---------------------------------------------------------------------------- +class LLFloaterAbout + : public LLFloater +{ + friend class LLFloaterReg; +private: + LLFloaterAbout(const LLSD& key); + virtual ~LLFloaterAbout(); + +public: + /*virtual*/ BOOL postBuild(); + + /// Obtain the data used to fill out the contents string. This is + /// separated so that we can programmatically access the same info. + static LLSD getInfo(); + void onClickCopyToClipboard(); +}; + + +// Default constructor +LLFloaterAbout::LLFloaterAbout(const LLSD& key) +: LLFloater(key) +{ + //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml"); + +} + +// Destroys the object +LLFloaterAbout::~LLFloaterAbout() +{ +} + +BOOL LLFloaterAbout::postBuild() +{ + center(); + LLViewerTextEditor *support_widget = + getChild<LLViewerTextEditor>("support_editor", true); + + LLViewerTextEditor *credits_widget = + getChild<LLViewerTextEditor>("credits_editor", true); + + getChild<LLUICtrl>("copy_btn")->setCommitCallback( + boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this)); + +#if LL_WINDOWS + getWindow()->incBusyCount(); + getWindow()->setCursor(UI_CURSOR_ARROW); +#endif + LLSD info(getInfo()); +#if LL_WINDOWS + getWindow()->decBusyCount(); + getWindow()->setCursor(UI_CURSOR_ARROW); +#endif + + std::ostringstream support; + + // Render the LLSD from getInfo() as a format_map_t + LLStringUtil::format_map_t args; + // For reasons I don't yet understand, [ReleaseNotes] is not part of the + // default substitution strings whereas [APP_NAME] is. But it works to + // simply copy it into these specific args. + args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes"); + 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] = getString("none"); + } + 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 << getString("AboutHeader", args); + if (info.has("COMPILER")) + { + support << "\n\n" << getString("AboutCompiler", args); + } + if (info.has("REGION")) + { + support << "\n\n" << getString("AboutPosition", args); + } + support << "\n\n" << getString("AboutSystem", args); + if (info.has("GRAPHICS_DRIVER_VERSION")) + { + support << "\n\n" << getString("AboutDriver", args); + } + support << "\n\n" << getString("AboutLibs", args); + if (info.has("PACKETS_IN")) + { + support << '\n' << getString("AboutTraffic", args); + } + + support_widget->appendText(support.str(), + FALSE, + LLStyle::Params() + .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor"))); + support_widget->blockUndo(); + + // Fix views + support_widget->setCursorPos(0); + support_widget->setEnabled(FALSE); + + credits_widget->setCursorPos(0); + credits_widget->setEnabled(FALSE); + + return TRUE; +} + +// static +LLSD LLFloaterAbout::getInfo() +{ + // 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; + LLSD version; + version.append(LL_VERSION_MAJOR); + version.append(LL_VERSION_MINOR); + version.append(LL_VERSION_PATCH); + version.append(LL_VERSION_BUILD); + info["VIEWER_VERSION"] = version; + info["VIEWER_VERSION_STR"] = STRINGIZE(version[0].asInteger() << '.' << + version[1].asInteger() << '.' << + version[2].asInteger() << '.' << + version[3].asInteger()); + info["BUILD_DATE"] = __DATE__; + info["BUILD_TIME"] = __TIME__; + info["CHANNEL"] = gSavedSettings.getString("VersionChannelName"); + + info["VIEWER_RELEASE_NOTES_URL"] = get_viewer_release_notes_url(); + +#if LL_MSVC + info["COMPILER"] = "MSVC"; + info["COMPILER_VERSION"] = _MSC_VER; +#elif LL_GNUC + info["COMPILER"] = "GCC"; + info["COMPILER_VERSION"] = GCC_VERSION; +#endif + + // Position + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + const LLVector3d &pos = gAgent.getPositionGlobal(); + info["POSITION"] = ll_sd_from_vector3d(pos); + info["REGION"] = gAgent.getRegion()->getName(); + info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName(); + info["HOSTIP"] = gAgent.getRegion()->getHost().getString(); + info["SERVER_VERSION"] = gLastVersionChannel; + info["SERVER_RELEASE_NOTES_URL"] = LLWeb::escapeURL(region->getCapability("ServerReleaseNotes")); + } + + // CPU + info["CPU"] = gSysCPU.getCPUString(); + info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB() / 1024); + // Moved hack adjustment to Windows memory size into llsys.cpp + info["OS_VERSION"] = LLAppViewer::instance()->getOSInfo().getOSString(); + info["GRAPHICS_CARD_VENDOR"] = (const char*)(glGetString(GL_VENDOR)); + info["GRAPHICS_CARD"] = (const char*)(glGetString(GL_RENDERER)); + +#if LL_WINDOWS + LLSD driver_info = gDXHardware.getDisplayInfo(); + if (driver_info.has("DriverVersion")) + { + info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"]; + } +#endif + + info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION)); + info["LIBCURL_VERSION"] = LLCurl::getVersionString(); + info["J2C_VERSION"] = LLImageJ2C::getEngineInfo(); + bool want_fullname = true; + info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD(); + info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : "Unknown"; + + // TODO: Implement media plugin version query + info["QT_WEBKIT_VERSION"] = "4.5.2"; + + if (gPacketsIn > 0) + { + info["PACKETS_LOST"] = LLViewerStats::getInstance()->mPacketsLostStat.getCurrent(); + info["PACKETS_IN"] = F32(gPacketsIn); + info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal(); + } + + return info; +} + +static std::string get_viewer_release_notes_url() +{ + std::ostringstream version; + version << LL_VERSION_MAJOR << "." + << LL_VERSION_MINOR << "." + << LL_VERSION_PATCH << "." + << LL_VERSION_BUILD; + + LLSD query; + query["channel"] = gSavedSettings.getString("VersionChannelName"); + query["version"] = version.str(); + + std::ostringstream url; + url << LLTrans::getString("RELEASE_NOTES_BASE_URL") << LLURI::mapToQueryString(query); + + return LLWeb::escapeURL(url.str()); +} + +class LLFloaterAboutListener: public LLDispatchListener +{ +public: + LLFloaterAboutListener(): + LLDispatchListener("LLFloaterAbout", "op") + { + add("getInfo", &LLFloaterAboutListener::getInfo, LLSD().insert("reply", LLSD())); + } + +private: + void getInfo(const LLSD& request) const + { + LLReqID reqid(request); + LLSD reply(LLFloaterAbout::getInfo()); + reqid.stamp(reply); + LLEventPumps::instance().obtain(request["reply"]).post(reply); + } +}; + +static LLFloaterAboutListener floaterAboutListener; + +void LLFloaterAbout::onClickCopyToClipboard() +{ + LLViewerTextEditor *support_widget = + getChild<LLViewerTextEditor>("support_editor", true); + support_widget->selectAll(); + support_widget->copy(); + support_widget->deselect(); +} + +///---------------------------------------------------------------------------- +/// LLFloaterAboutUtil +///---------------------------------------------------------------------------- +void LLFloaterAboutUtil::registerFloater() +{ + LLFloaterReg::add("sl_about", "floater_about.xml", + &LLFloaterReg::build<LLFloaterAbout>); + +} diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 55b7ed0c99..095fe0a220 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -989,7 +989,7 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata) name, desc, 0, - LLAssetType::AT_NONE, + LLFolderType::FT_NONE, LLInventoryType::IT_ANIMATION, LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), name, diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp index 7cb8987879..538b44c056 100644 --- a/indra/newview/llfloaterbulkpermission.cpp +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -264,7 +264,6 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, Invent ( asstype == LLAssetType::AT_BODYPART && gSavedSettings.getBOOL("BulkChangeIncludeBodyParts" )) || ( asstype == LLAssetType::AT_CLOTHING && gSavedSettings.getBOOL("BulkChangeIncludeClothing" )) || ( asstype == LLAssetType::AT_GESTURE && gSavedSettings.getBOOL("BulkChangeIncludeGestures" )) || - ( asstype == LLAssetType::AT_FAVORITE && gSavedSettings.getBOOL("BulkChangeIncludeFavourite" )) || ( asstype == LLAssetType::AT_NOTECARD && gSavedSettings.getBOOL("BulkChangeIncludeNotecards" )) || ( asstype == LLAssetType::AT_OBJECT && gSavedSettings.getBOOL("BulkChangeIncludeObjects" )) || ( asstype == LLAssetType::AT_LSL_TEXT && gSavedSettings.getBOOL("BulkChangeIncludeScripts" )) || diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index 9d07362edc..cefd7a3808 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -45,6 +45,7 @@ #include "llinventorymodel.h" // for gInventory #include "llfloaterreg.h" #include "llfloaterinventory.h" // for get_item_icon +#include "llinventoryfunctions.h" #include "llselectmgr.h" #include "llscrolllistctrl.h" #include "llviewerobject.h" @@ -292,7 +293,7 @@ void LLFloaterBuy::onClickBuy() { // Put the items where we put new folders. LLUUID category_id; - category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); + category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); // *NOTE: doesn't work for multiple object buy, which UI does not // currently support sale info is used for verification only, if diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index 3a4171c6be..32802f6a20 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -45,6 +45,7 @@ #include "llagent.h" // for agent id #include "llalertdialog.h" #include "llcheckboxctrl.h" +#include "llinventoryfunctions.h" #include "llinventorymodel.h" // for gInventory #include "llfloaterreg.h" #include "llfloaterinventory.h" // for get_item_icon @@ -280,12 +281,12 @@ void LLFloaterBuyContents::onClickBuy() // We may want to wear this item if (childGetValue("wear_check")) { - LLFloaterInventory::sWearNewClothing = TRUE; + LLInventoryState::sWearNewClothing = TRUE; } // Put the items where we put new folders. LLUUID category_id; - category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CATEGORY); + category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CATEGORY); // *NOTE: doesn't work for multiple object buy, which UI does not // currently support sale info is used for verification only, if diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 36f0315790..467796b4a3 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -685,7 +685,14 @@ void LLFloaterBuyLandUI::finishWebSiteInfo() mSiteLandUseAction = landUse["action"].asString(); LLXMLRPCValue currency = result["currency"]; - mCurrency.setEstimate(currency["estimatedCost"].asInt()); + if (currency["estimatedCost"].isValid()) + { + mCurrency.setUSDEstimate(currency["estimatedCost"].asInt()); + } + if (currency["estimatedLocalCost"].isValid()) + { + mCurrency.setLocalEstimate(currency["estimatedLocalCost"].asString()); + } mSiteConfirm = result["confirm"].asString(); } @@ -733,7 +740,8 @@ void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password) keywordArgs.appendInt("billableArea", mIsForGroup ? 0 : mParcelBillableArea); keywordArgs.appendInt("currencyBuy", mCurrency.getAmount()); - keywordArgs.appendInt("estimatedCost", mCurrency.getEstimate()); + keywordArgs.appendInt("estimatedCost", mCurrency.getUSDEstimate()); + keywordArgs.appendString("estimatedLocalCost", mCurrency.getLocalEstimate()); keywordArgs.appendString("confirm", mSiteConfirm); if (!password.empty()) { @@ -1217,7 +1225,7 @@ void LLFloaterBuyLandUI::refreshUI() childSetText("currency_reason", getString("not_enough_lindens", string_args)); - childSetTextArg("currency_est", "[AMOUNT2]", llformat("%#.2f", mCurrency.getEstimate() / 100.0)); + childSetTextArg("currency_est", "[LOCAL_AMOUNT]", mCurrency.getLocalEstimate()); } if (willHaveEnough) @@ -1297,7 +1305,7 @@ void LLFloaterBuyLandUI::startBuyPreConfirm() { LLStringUtil::format_map_t string_args; string_args["[AMOUNT]"] = llformat("%d", mCurrency.getAmount()); - string_args["[AMOUNT2]"] = llformat("%#.2f", mCurrency.getEstimate() / 100.0); + string_args["[LOCAL_AMOUNT]"] = mCurrency.getLocalEstimate(); action += getString("buy_for_US", string_args); } diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index 1300103423..c114eed4a2 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -44,6 +44,7 @@ #include "llcombobox.h" #include "llgesturemgr.h" #include "llinventorymodel.h" +#include "llinventorypanel.h" #include "llfloaterinventory.h" #include "llkeyboard.h" #include "lllineeditor.h" diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index e26937e93f..13ca7638c5 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -88,32 +88,7 @@ LLFloaterInspect::~LLFloaterInspect(void) } //sInstance = NULL; } -/* -BOOL LLFloaterInspect::isVisible() -{ - return (!!sInstance); -}*/ -/* -void LLFloaterInspect::show(void* ignored) -{ - // setForceSelection ensures that the pie menu does not deselect things when it - // looses the focus (this can happen with "select own objects only" enabled - // VWR-1471 - BOOL forcesel = LLSelectMgr::getInstance()->setForceSelection(TRUE); - - if (!sInstance) // first use - { - sInstance = new LLFloaterInspect; - } - sInstance->openFloater(); - LLToolMgr::getInstance()->setTransientTool(LLToolCompInspect::getInstance()); - LLSelectMgr::getInstance()->setForceSelection(forcesel); // restore previouis value - - sInstance->mObjectSelection = LLSelectMgr::getInstance()->getSelection(); - sInstance->refresh(); -} -*/ void LLFloaterInspect::onOpen(const LLSD& key) { BOOL forcesel = LLSelectMgr::getInstance()->setForceSelection(TRUE); diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index 274c2234de..92778510e7 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -32,539 +32,35 @@ #include "llviewerprecompiledheaders.h" -#include <utility> // for std::pair<> - #include "llfloaterinventory.h" -// library includes #include "llagent.h" -#include "llagentwearables.h" -#include "llcallingcard.h" -#include "llfloaterreg.h" -#include "llsdserialize.h" -#include "llfiltereditor.h" -#include "llspinctrl.h" -#include "llui.h" -#include "message.h" - -// newview includes -#include "llappearancemgr.h" -#include "llappviewer.h" #include "llfirstuse.h" -#include "llfloaterchat.h" -#include "llfloatercustomize.h" -#include "llfocusmgr.h" -#include "llfolderview.h" -#include "llgesturemgr.h" -#include "lliconctrl.h" -#include "llimview.h" -#include "llinventorybridge.h" -#include "llinventoryclipboard.h" +#include "llfloaterreg.h" #include "llinventorymodel.h" -#include "lllineeditor.h" -#include "llmenugl.h" -#include "llpreviewanim.h" -#include "llpreviewgesture.h" -#include "llpreviewnotecard.h" -#include "llpreviewscript.h" -#include "llpreviewsound.h" -#include "llpreviewtexture.h" +#include "llpanelmaininventory.h" #include "llresmgr.h" -#include "llscrollbar.h" -#include "llscrollcontainer.h" -#include "llselectmgr.h" -#include "lltabcontainer.h" -#include "lltooldraganddrop.h" -#include "lluictrlfactory.h" -#include "llviewerinventory.h" -#include "llviewermessage.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" -#include "llviewerwindow.h" -#include "llvoavatarself.h" -#include "llwearablelist.h" - -static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel"); - -//BOOL LLFloaterInventory::sOpenNextNewItem = FALSE; -BOOL LLFloaterInventory::sWearNewClothing = FALSE; -LLUUID LLFloaterInventory::sWearNewClothingTransactionID; - -///---------------------------------------------------------------------------- -/// LLFloaterInventoryFinder -///---------------------------------------------------------------------------- - -LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLFloaterInventory* inventory_view) -: LLFloater(LLSD()), - mFloaterInventory(inventory_view), - mFilter(inventory_view->mActivePanel->getFilter()) -{ - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_view_finder.xml", NULL); - updateElementsFromFilter(); -} - - -void LLFloaterInventoryFinder::onCheckSinceLogoff(LLUICtrl *ctrl, void *user_data) -{ - LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; - if (!self) return; - - bool since_logoff= self->childGetValue("check_since_logoff"); - - if (!since_logoff && - !( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) ) - { - self->mSpinSinceHours->set(1.0f); - } -} -BOOL LLFloaterInventoryFinder::postBuild() -{ - const LLRect& viewrect = mFloaterInventory->getRect(); - setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight())); - - childSetAction("All", selectAllTypes, this); - childSetAction("None", selectNoTypes, this); - - mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago"); - childSetCommitCallback("spin_hours_ago", onTimeAgo, this); - - mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago"); - childSetCommitCallback("spin_days_ago", onTimeAgo, this); - - // mCheckSinceLogoff = getChild<LLSpinCtrl>("check_since_logoff"); - childSetCommitCallback("check_since_logoff", onCheckSinceLogoff, this); - - childSetAction("Close", onCloseBtn, this); - - updateElementsFromFilter(); - return TRUE; -} -void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data) -{ - LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; - if (!self) return; - - bool since_logoff=true; - if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) - { - since_logoff = false; - } - self->childSetValue("check_since_logoff", since_logoff); -} - -void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter) -{ - mFilter = filter; - updateElementsFromFilter(); -} - -void LLFloaterInventoryFinder::updateElementsFromFilter() -{ - if (!mFilter) - return; - - // Get data needed for filter display - U32 filter_types = mFilter->getFilterTypes(); - std::string filter_string = mFilter->getFilterSubString(); - LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState(); - U32 hours = mFilter->getHoursAgo(); - - // update the ui elements - LLFloater::setTitle(mFilter->getName()); - childSetValue("check_animation", (S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION)); - - childSetValue("check_calling_card", (S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD)); - childSetValue("check_clothing", (S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE)); - childSetValue("check_gesture", (S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE)); - childSetValue("check_landmark", (S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK)); - childSetValue("check_notecard", (S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD)); - childSetValue("check_object", (S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT)); - childSetValue("check_script", (S32) (filter_types & 0x1 << LLInventoryType::IT_LSL)); - childSetValue("check_sound", (S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND)); - childSetValue("check_texture", (S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE)); - childSetValue("check_snapshot", (S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT)); - childSetValue("check_show_empty", show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS); - childSetValue("check_since_logoff", mFilter->isSinceLogoff()); - mSpinSinceHours->set((F32)(hours % 24)); - mSpinSinceDays->set((F32)(hours / 24)); -} - -void LLFloaterInventoryFinder::draw() -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_DRAW); - U32 filter = 0xffffffff; - BOOL filtered_by_all_types = TRUE; - - if (!childGetValue("check_animation")) - { - filter &= ~(0x1 << LLInventoryType::IT_ANIMATION); - filtered_by_all_types = FALSE; - } - - - if (!childGetValue("check_calling_card")) - { - filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_clothing")) - { - filter &= ~(0x1 << LLInventoryType::IT_WEARABLE); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_gesture")) - { - filter &= ~(0x1 << LLInventoryType::IT_GESTURE); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_landmark")) - - - { - filter &= ~(0x1 << LLInventoryType::IT_LANDMARK); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_notecard")) - { - filter &= ~(0x1 << LLInventoryType::IT_NOTECARD); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_object")) - { - filter &= ~(0x1 << LLInventoryType::IT_OBJECT); - filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_script")) - { - filter &= ~(0x1 << LLInventoryType::IT_LSL); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_sound")) - { - filter &= ~(0x1 << LLInventoryType::IT_SOUND); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_texture")) - { - filter &= ~(0x1 << LLInventoryType::IT_TEXTURE); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_snapshot")) - { - filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT); - filtered_by_all_types = FALSE; - } - - if (!filtered_by_all_types) - { - // don't include folders in filter, unless I've selected everything - filter &= ~(0x1 << LLInventoryType::IT_CATEGORY); - } - - // update the panel, panel will update the filter - mFloaterInventory->mActivePanel->setShowFolderState(getCheckShowEmpty() ? - LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mFloaterInventory->mActivePanel->setFilterTypes(filter); - if (getCheckSinceLogoff()) - { - mSpinSinceDays->set(0); - mSpinSinceHours->set(0); - } - U32 days = (U32)mSpinSinceDays->get(); - U32 hours = (U32)mSpinSinceHours->get(); - if (hours > 24) - { - days += hours / 24; - hours = (U32)hours % 24; - mSpinSinceDays->set((F32)days); - mSpinSinceHours->set((F32)hours); - } - hours += days * 24; - mFloaterInventory->mActivePanel->setHoursAgo(hours); - mFloaterInventory->mActivePanel->setSinceLogoff(getCheckSinceLogoff()); - mFloaterInventory->setFilterTextFromFilter(); - - LLFloater::draw(); -} - -BOOL LLFloaterInventoryFinder::getCheckShowEmpty() -{ - return childGetValue("check_show_empty"); -} - -BOOL LLFloaterInventoryFinder::getCheckSinceLogoff() -{ - return childGetValue("check_since_logoff"); -} - -void LLFloaterInventoryFinder::onCloseBtn(void* user_data) -{ - LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data; - finderp->closeFloater(); -} - -// static -void LLFloaterInventoryFinder::selectAllTypes(void* user_data) -{ - LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; - if(!self) return; - - self->childSetValue("check_animation", TRUE); - self->childSetValue("check_calling_card", TRUE); - self->childSetValue("check_clothing", TRUE); - self->childSetValue("check_gesture", TRUE); - self->childSetValue("check_landmark", TRUE); - self->childSetValue("check_notecard", TRUE); - self->childSetValue("check_object", TRUE); - self->childSetValue("check_script", TRUE); - self->childSetValue("check_sound", TRUE); - self->childSetValue("check_texture", TRUE); - self->childSetValue("check_snapshot", TRUE); - -/* - self->mCheckCallingCard->set(TRUE); - self->mCheckClothing->set(TRUE); - self->mCheckGesture->set(TRUE); - self->mCheckLandmark->set(TRUE); - self->mCheckNotecard->set(TRUE); - self->mCheckObject->set(TRUE); - self->mCheckScript->set(TRUE); - self->mCheckSound->set(TRUE); - self->mCheckTexture->set(TRUE); - self->mCheckSnapshot->set(TRUE);*/ -} - -//static -void LLFloaterInventoryFinder::selectNoTypes(void* user_data) -{ - LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; - if(!self) return; - - /* - self->childSetValue("check_animation", FALSE); - self->mCheckCallingCard->set(FALSE); - self->mCheckClothing->set(FALSE); - self->mCheckGesture->set(FALSE); - self->mCheckLandmark->set(FALSE); - self->mCheckNotecard->set(FALSE); - self->mCheckObject->set(FALSE); - self->mCheckScript->set(FALSE); - self->mCheckSound->set(FALSE); - self->mCheckTexture->set(FALSE); - self->mCheckSnapshot->set(FALSE);*/ - - - self->childSetValue("check_animation", FALSE); - self->childSetValue("check_calling_card", FALSE); - self->childSetValue("check_clothing", FALSE); - self->childSetValue("check_gesture", FALSE); - self->childSetValue("check_landmark", FALSE); - self->childSetValue("check_notecard", FALSE); - self->childSetValue("check_object", FALSE); - self->childSetValue("check_script", FALSE); - self->childSetValue("check_sound", FALSE); - self->childSetValue("check_texture", FALSE); - self->childSetValue("check_snapshot", FALSE); -} - +#include "llviewerfoldertype.h" ///---------------------------------------------------------------------------- /// LLFloaterInventory ///---------------------------------------------------------------------------- -void LLSaveFolderState::setApply(BOOL apply) -{ - mApply = apply; - // before generating new list of open folders, clear the old one - if(!apply) - { - clearOpenFolders(); - } -} - -void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); - if(mApply) - { - // we're applying the open state - LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); - if(!bridge) return; - LLUUID id(bridge->getUUID()); - if(mOpenFolders.find(id) != mOpenFolders.end()) - { - folder->setOpen(TRUE); - } - else - { - // keep selected filter in its current state, this is less jarring to user - if (!folder->isSelected()) - { - folder->setOpen(FALSE); - } - } - } - else - { - // we're recording state at this point - if(folder->isOpen()) - { - LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); - if(!bridge) return; - mOpenFolders.insert(bridge->getUUID()); - } - } -} LLFloaterInventory::LLFloaterInventory(const LLSD& key) : LLFloater(key) { - LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_INIT); - // Menu Callbacks (non contex menus) - mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLFloaterInventory::doToSelected, this, _2)); - mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLFloaterInventory::closeAllFolders, this)); - mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLAssetType::AT_TRASH)); - mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLAssetType::AT_LOST_AND_FOUND)); - mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLFloaterInventory::doCreate, this, _2)); -// mCommitCallbackRegistrar.add("Inventory.NewWindow", boost::bind(&LLFloaterInventory::newWindow, this)); - mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLFloaterInventory::toggleFindOptions, this)); - mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLFloaterInventory::resetFilters, this)); - mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLFloaterInventory::setSortBy, this, _2)); - - // Controls - // *TODO: Just use persistant settings for each of these - U32 sort_order = gSavedSettings.getU32("InventorySortOrder"); - BOOL sort_by_name = ! ( sort_order & LLInventoryFilter::SO_DATE ); - BOOL sort_folders_by_name = ( sort_order & LLInventoryFilter::SO_FOLDERS_BY_NAME ); - BOOL sort_system_folders_to_top = ( sort_order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ); - - gSavedSettings.declareBOOL("Inventory.SortByName", sort_by_name, "Declared in code", FALSE); - gSavedSettings.declareBOOL("Inventory.SortByDate", !sort_by_name, "Declared in code", FALSE); - gSavedSettings.declareBOOL("Inventory.FoldersAlwaysByName", sort_folders_by_name, "Declared in code", FALSE); - gSavedSettings.declareBOOL("Inventory.SystemFoldersToTop", sort_system_folders_to_top, "Declared in code", FALSE); - - mSavedFolderState = new LLSaveFolderState(); - mSavedFolderState->setApply(FALSE); +} - //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory.xml"); +LLFloaterInventory::~LLFloaterInventory() +{ } BOOL LLFloaterInventory::postBuild() { - gInventory.addObserver(this); - - mFilterTabs = getChild<LLTabContainer>("inventory filter tabs"); - mFilterTabs->setCommitCallback(boost::bind(&LLFloaterInventory::onFilterSelected, this)); - - //panel->getFilter()->markDefault(); - - // Set up the default inv. panel/filter settings. - mActivePanel = getChild<LLInventoryPanel>("All Items"); - if (mActivePanel) - { - // "All Items" is the previous only view, so it gets the InventorySortOrder - mActivePanel->setSortOrder(gSavedSettings.getU32("InventorySortOrder")); - mActivePanel->getFilter()->markDefault(); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - mActivePanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mActivePanel, _1, _2)); - } - LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); - if (recent_items_panel) - { - recent_items_panel->setSinceLogoff(TRUE); - recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); - recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - recent_items_panel->getFilter()->markDefault(); - recent_items_panel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, recent_items_panel, _1, _2)); - } - - // Now load the stored settings from disk, if available. - std::ostringstream filterSaveName; - filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); - llinfos << "LLFloaterInventory::init: reading from " << filterSaveName << llendl; - llifstream file(filterSaveName.str()); - LLSD savedFilterState; - if (file.is_open()) - { - LLSDSerialize::fromXML(savedFilterState, file); - file.close(); - - // Load the persistent "Recent Items" settings. - // Note that the "All Items" settings do not persist. - if(recent_items_panel) - { - if(savedFilterState.has(recent_items_panel->getFilter()->getName())) - { - LLSD recent_items = savedFilterState.get( - recent_items_panel->getFilter()->getName()); - recent_items_panel->getFilter()->fromLLSD(recent_items); - } - } - - } - - - mFilterEditor = getChild<LLFilterEditor>("inventory search editor"); - if (mFilterEditor) - { - mFilterEditor->setCommitCallback(boost::bind(&LLFloaterInventory::onFilterEdit, this, _2)); - } - - // *TODO:Get the cost info from the server - const std::string upload_cost("10"); - childSetLabelArg("Upload Image", "[COST]", upload_cost); - childSetLabelArg("Upload Sound", "[COST]", upload_cost); - childSetLabelArg("Upload Animation", "[COST]", upload_cost); - childSetLabelArg("Bulk Upload", "[COST]", upload_cost); - + mPanelMainInventory = getChild<LLPanelMainInventory>("Inventory Panel"); return TRUE; } -// Destroys the object -LLFloaterInventory::~LLFloaterInventory( void ) -{ - // Save the filters state. - LLSD filterRoot; - LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items"); - if (all_items_panel) - { - LLInventoryFilter* filter = all_items_panel->getFilter(); - LLSD filterState; - filter->toLLSD(filterState); - filterRoot[filter->getName()] = filterState; - } - - LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); - if (recent_items_panel) - { - LLInventoryFilter* filter = recent_items_panel->getFilter(); - LLSD filterState; - filter->toLLSD(filterState); - filterRoot[filter->getName()] = filterState; - } - - std::ostringstream filterSaveName; - filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); - llofstream filtersFile(filterSaveName.str()); - if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile)) - { - llwarns << "Could not write to filters save file " << filterSaveName << llendl; - } - else - filtersFile.close(); - - gInventory.removeObserver(this); - delete mSavedFolderState; -} void LLFloaterInventory::draw() { @@ -575,113 +71,6 @@ void LLFloaterInventory::draw() LLFloater::draw(); } -void LLOpenFilteredFolders::doItem(LLFolderViewItem *item) -{ - if (item->getFiltered()) - { - item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); - } -} - -void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder) -{ - if (folder->getFiltered() && 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->getFiltered() && !folder->hasFilteredDescendants()) - { - folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO); - } -} - -void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) -{ - if (item->getFiltered() && !mItemSelected) - { - item->getRoot()->setSelection(item, FALSE, FALSE); - if (item->getParentFolder()) - { - item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); - } - item->getRoot()->scrollToShowSelection(); - mItemSelected = TRUE; - } -} - -void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder) -{ - if (folder->getFiltered() && !mItemSelected) - { - folder->getRoot()->setSelection(folder, FALSE, FALSE); - if (folder->getParentFolder()) - { - folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); - } - folder->getRoot()->scrollToShowSelection(); - mItemSelected = TRUE; - } -} - -void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item) -{ - 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); - } -} - -void LLFloaterInventory::startSearch() -{ - // this forces focus to line editor portion of search editor - if (mFilterEditor) - { - mFilterEditor->focusFirstItem(TRUE); - } -} - -void LLFloaterInventory::onOpen(const LLSD& key) -{ - LLFirstUse::useInventory(); -} - -BOOL LLFloaterInventory::handleKeyHere(KEY key, MASK mask) -{ - LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL; - if (root_folder) - { - // first check for user accepting current search results - if (mFilterEditor - && mFilterEditor->hasFocus() - && (key == KEY_RETURN - || key == KEY_DOWN) - && mask == MASK_NONE) - { - // move focus to inventory proper - mActivePanel->setFocus(TRUE); - root_folder->scrollToShowSelection(); - return TRUE; - } - - if (mActivePanel->hasFocus() && key == KEY_UP) - { - startSearch(); - } - } - - return LLFloater::handleKeyHere(key, mask); - -} - void LLFloaterInventory::updateTitle() { LLLocale locale(LLLocale::USER_LOCALE); @@ -690,7 +79,7 @@ void LLFloaterInventory::updateTitle() LLStringUtil::format_map_t string_args; string_args["[ITEM_COUNT]"] = item_count_string; - string_args["[FILTER]"] = mFilterText; + string_args["[FILTER]"] = mPanelMainInventory->getFilterText(); if (LLInventoryModel::backgroundFetchActive()) { @@ -699,102 +88,21 @@ void LLFloaterInventory::updateTitle() else { setTitle(getString("TitleCompleted", string_args)); - } + } } - void LLFloaterInventory::changed(U32 mask) { updateTitle(); } -//---------------------------------------------------------------------------- -// menu callbacks - -void LLFloaterInventory::doToSelected(const LLSD& userdata) -{ - getPanel()->getRootFolder()->doToSelected(&gInventory, userdata); -} - -void LLFloaterInventory::closeAllFolders() -{ - getPanel()->getRootFolder()->closeAllFolders(); -} - -void LLFloaterInventory::doCreate(const LLSD& userdata) -{ - menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata); -} - -void LLFloaterInventory::resetFilters() -{ - LLFloaterInventoryFinder *finder = getFinder(); - getActivePanel()->getFilter()->resetDefault(); - if (finder) - { - finder->updateElementsFromFilter(); - } - - setFilterTextFromFilter(); -} - -void LLFloaterInventory::setSortBy(const LLSD& userdata) +LLInventoryPanel* LLFloaterInventory::getPanel() { - std::string sort_field = userdata.asString(); - if (sort_field == "name") - { - U32 order = getActivePanel()->getSortOrder(); - getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE ); - - gSavedSettings.setBOOL("Inventory.SortByName", TRUE ); - gSavedSettings.setBOOL("Inventory.SortByDate", FALSE ); - } - else if (sort_field == "date") - { - U32 order = getActivePanel()->getSortOrder(); - getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE ); - - gSavedSettings.setBOOL("Inventory.SortByName", FALSE ); - gSavedSettings.setBOOL("Inventory.SortByDate", TRUE ); - } - else if (sort_field == "foldersalwaysbyname") - { - U32 order = getActivePanel()->getSortOrder(); - if ( order & LLInventoryFilter::SO_FOLDERS_BY_NAME ) - { - order &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; - - gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", FALSE ); - } - else - { - order |= LLInventoryFilter::SO_FOLDERS_BY_NAME; - - gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", TRUE ); - } - getActivePanel()->setSortOrder( order ); - } - else if (sort_field == "systemfolderstotop") - { - U32 order = getActivePanel()->getSortOrder(); - if ( order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ) - { - order &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - - gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", FALSE ); - } - else - { - order |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - - gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE ); - } - getActivePanel()->setSortOrder( order ); - } + if (mPanelMainInventory) + return mPanelMainInventory->getPanel(); + return NULL; } -//---------------------------------------------------------------------------- - // static LLFloaterInventory* LLFloaterInventory::showAgentInventory() { @@ -842,1125 +150,7 @@ void LLFloaterInventory::cleanup() } } -void LLFloaterInventory::toggleFindOptions() -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE); - LLFloater *floater = getFinder(); - if (!floater) - { - LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this); - mFinderHandle = finder->getHandle(); - finder->openFloater(); - addDependentFloater(mFinderHandle); - - // start background fetch of folders - gInventory.startBackgroundFetch(); - } - else - { - floater->closeFloater(); - } -} - -// static -BOOL LLFloaterInventory::filtersVisible(void* user_data) -{ - LLFloaterInventory* self = (LLFloaterInventory*)user_data; - if(!self) return FALSE; - - return self->getFinder() != NULL; -} - -void LLFloaterInventory::onClearSearch() -{ - LLFloater *finder = getFinder(); - if (mActivePanel) - { - mActivePanel->setFilterSubString(LLStringUtil::null); - mActivePanel->setFilterTypes(0xffffffff); - } - - if (finder) - { - LLFloaterInventoryFinder::selectAllTypes(finder); - } - - // re-open folders that were initially open - if (mActivePanel) - { - mSavedFolderState->setApply(TRUE); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - LLOpenFoldersWithSelection opener; - mActivePanel->getRootFolder()->applyFunctorRecursively(opener); - mActivePanel->getRootFolder()->scrollToShowSelection(); - } -} - -void LLFloaterInventory::onFilterEdit(const std::string& search_string ) -{ - if (search_string == "") - { - onClearSearch(); - } - if (!mActivePanel) - { - return; - } - - gInventory.startBackgroundFetch(); - - std::string uppercase_search_string = search_string; - LLStringUtil::toUpper(uppercase_search_string); - if (mActivePanel->getFilterSubString().empty() && uppercase_search_string.empty()) - { - // current filter and new filter empty, do nothing - return; - } - - // save current folder open state if no filter currently applied - if (!mActivePanel->getRootFolder()->isFilterModified()) - { - mSavedFolderState->setApply(FALSE); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - } - - // set new filter string - mActivePanel->setFilterSubString(uppercase_search_string); -} - - - //static - BOOL LLFloaterInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward) - { - LLFloaterInventory* active_view = NULL; - - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) - { - LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter); - if (iv) - { - if (gFocusMgr.childHasKeyboardFocus(iv)) - { - active_view = iv; - break; - } - } - } - - if (!active_view) - { - return FALSE; - } - - std::string search_string(find_text); - - if (search_string.empty()) - { - return FALSE; - } - - if (active_view->mActivePanel && - active_view->mActivePanel->getRootFolder()->search(first_item, search_string, backward)) - { - return TRUE; - } - - return FALSE; - } - -void LLFloaterInventory::onFilterSelected() -{ - // Find my index - mActivePanel = (LLInventoryPanel*)childGetVisibleTab("inventory filter tabs"); - - if (!mActivePanel) - { - return; - } - LLInventoryFilter* filter = mActivePanel->getFilter(); - LLFloaterInventoryFinder *finder = getFinder(); - if (finder) - { - finder->changeFilter(filter); - } - if (filter->isActive()) - { - // If our filter is active we may be the first thing requiring a fetch so we better start it here. - gInventory.startBackgroundFetch(); - } - setFilterTextFromFilter(); -} - -BOOL LLFloaterInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - // Check to see if we are auto scrolling from the last frame - LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel(); - BOOL needsToScroll = panel->getScrollableContainer()->autoScroll(x, y); - if(mFilterTabs) - { - if(needsToScroll) - { - mFilterTabs->startDragAndDropDelayTimer(); - } - } - - BOOL handled = LLFloater::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - - return handled; -} -const std::string& get_item_icon_name(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 attachment_point, - BOOL item_is_multi ) -{ - EInventoryIcon idx = OBJECT_ICON_NAME; - if ( item_is_multi ) - { - idx = OBJECT_MULTI_ICON_NAME; - } - - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - if(LLInventoryType::IT_SNAPSHOT == inventory_type) - { - idx = SNAPSHOT_ICON_NAME; - } - else - { - idx = TEXTURE_ICON_NAME; - } - break; - - case LLAssetType::AT_SOUND: - idx = SOUND_ICON_NAME; - break; - case LLAssetType::AT_CALLINGCARD: - if(attachment_point!= 0) - { - idx = CALLINGCARD_ONLINE_ICON_NAME; - } - else - { - idx = CALLINGCARD_OFFLINE_ICON_NAME; - } - break; - case LLAssetType::AT_LANDMARK: - if(attachment_point!= 0) - { - idx = LANDMARK_VISITED_ICON_NAME; - } - else - { - idx = LANDMARK_ICON_NAME; - } - break; - case LLAssetType::AT_SCRIPT: - case LLAssetType::AT_LSL_TEXT: - case LLAssetType::AT_LSL_BYTECODE: - idx = SCRIPT_ICON_NAME; - break; - case LLAssetType::AT_CLOTHING: - idx = CLOTHING_ICON_NAME; - case LLAssetType::AT_BODYPART : - if(LLAssetType::AT_BODYPART == asset_type) - { - idx = BODYPART_ICON_NAME; - } - switch(LLInventoryItem::II_FLAGS_WEARABLES_MASK & attachment_point) - { - case WT_SHAPE: - idx = BODYPART_SHAPE_ICON_NAME; - break; - case WT_SKIN: - idx = BODYPART_SKIN_ICON_NAME; - break; - case WT_HAIR: - idx = BODYPART_HAIR_ICON_NAME; - break; - case WT_EYES: - idx = BODYPART_EYES_ICON_NAME; - break; - case WT_SHIRT: - idx = CLOTHING_SHIRT_ICON_NAME; - break; - case WT_PANTS: - idx = CLOTHING_PANTS_ICON_NAME; - break; - case WT_SHOES: - idx = CLOTHING_SHOES_ICON_NAME; - break; - case WT_SOCKS: - idx = CLOTHING_SOCKS_ICON_NAME; - break; - case WT_JACKET: - idx = CLOTHING_JACKET_ICON_NAME; - break; - case WT_GLOVES: - idx = CLOTHING_GLOVES_ICON_NAME; - break; - case WT_UNDERSHIRT: - idx = CLOTHING_UNDERSHIRT_ICON_NAME; - break; - case WT_UNDERPANTS: - idx = CLOTHING_UNDERPANTS_ICON_NAME; - break; - case WT_SKIRT: - idx = CLOTHING_SKIRT_ICON_NAME; - break; - case WT_ALPHA: - idx = CLOTHING_ALPHA_ICON_NAME; - break; - case WT_TATTOO: - idx = CLOTHING_TATTOO_ICON_NAME; - break; - default: - // no-op, go with choice above - break; - } - break; - case LLAssetType::AT_NOTECARD: - idx = NOTECARD_ICON_NAME; - break; - case LLAssetType::AT_ANIMATION: - idx = ANIMATION_ICON_NAME; - break; - case LLAssetType::AT_GESTURE: - idx = GESTURE_ICON_NAME; - break; - case LLAssetType::AT_FAVORITE: - //TODO - need bette idx - idx = LANDMARK_ICON_NAME; - break; - case LLAssetType::AT_LINK: - idx = LINKITEM_ICON_NAME; - break; - case LLAssetType::AT_LINK_FOLDER: - idx = LINKFOLDER_ICON_NAME; - break; - default: - break; - } - - return ICON_NAME[idx]; -} - -LLUIImagePtr get_item_icon(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 attachment_point, - BOOL item_is_multi) -{ - const std::string& icon_name = get_item_icon_name(asset_type, inventory_type, attachment_point, item_is_multi ); - return LLUI::getUIImage(icon_name); -} - -const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder"); -const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder"); -const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); -static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; - -LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) -: LLPanel(p), - mInventoryObserver(NULL), - mFolders(NULL), - mScroller(NULL), - mSortOrderSetting(p.sort_order_setting), - mInventory(p.inventory), - mAllowMultiSelect(p.allow_multi_select), - mHasInventoryConnection(false), - mStartFolderString(p.start_folder) -, mBuildDefaultHierarchy(true) -, mInvFVBridgeBuilder(NULL) -{ - mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; - - // contex menu callbacks - mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2)); - mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLAssetType::AT_TRASH)); - mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLAssetType::AT_LOST_AND_FOUND)); - mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLInventoryPanel::doCreate, this, _2)); - mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2)); - mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this)); - - setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor")); - setBackgroundVisible(TRUE); - setBackgroundOpaque(TRUE); -} - -BOOL LLInventoryPanel::postBuild() -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD); - - mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves - - // create root folder - { - LLRect folder_rect(0, - 0, - getRect().getWidth(), - 0); - LLFolderView::Params p; - p.name = getName(); - p.rect = folder_rect; - p.parent_panel = this; - mFolders = LLUICtrlFactory::create<LLFolderView>(p); - mFolders->setAllowMultiSelect(mAllowMultiSelect); - } - - mCommitCallbackRegistrar.popScope(); - - mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); - - // scroller - { - LLRect scroller_view_rect = getRect(); - scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); - LLScrollContainer::Params p; - p.name("Inventory Scroller"); - p.rect(scroller_view_rect); - p.follows.flags(FOLLOWS_ALL); - p.reserve_scroll_corner(true); - p.tab_stop(true); - mScroller = LLUICtrlFactory::create<LLScrollContainer>(p); - } - addChild(mScroller); - mScroller->addChild(mFolders); - - mFolders->setScrollContainer(mScroller); - - // set up the callbacks from the inventory we're viewing, and then - // build everything. - mInventoryObserver = new LLInventoryPanelObserver(this); - mInventory->addObserver(mInventoryObserver); - - // determine the root folder, if any, so inventory contents show just the children - // of that folder (i.e. not including the folder itself). - const LLAssetType::EType preferred_type = LLAssetType::lookupHumanReadable(mStartFolderString); - - if ("inventory" == mStartFolderString) - { - mStartFolderID = gInventory.getRootFolderID(); - } - else if ("library" == mStartFolderString) - { - mStartFolderID = gInventory.getLibraryRootFolderID(); - } - else - { - mStartFolderID = (preferred_type != LLAssetType::AT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null); - } - - // build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback - if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection) - { - rebuildViewsFor(mStartFolderID); - mHasInventoryConnection = true; - } - - // bit of a hack to make sure the inventory is open. - mFolders->openFolder(preferred_type != LLAssetType::AT_NONE ? LLAssetType::lookupCategoryName(preferred_type) : "My Inventory"); - - if (mSortOrderSetting != INHERIT_SORT_ORDER) - { - setSortOrder(gSavedSettings.getU32(mSortOrderSetting)); - } - else - { - setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER)); - } - mFolders->setSortOrder(mFolders->getFilter()->getSortOrder()); - - return TRUE; -} - -LLInventoryPanel::~LLInventoryPanel() -{ - // should this be a global setting? - if (mFolders) - { - U32 sort_order = mFolders->getSortOrder(); - if (mSortOrderSetting != INHERIT_SORT_ORDER) - { - gSavedSettings.setU32(mSortOrderSetting, sort_order); - } - } - - // LLView destructor will take care of the sub-views. - mInventory->removeObserver(mInventoryObserver); - delete mInventoryObserver; - mScroller = NULL; -} - -LLMemType mt(LLMemType::MTYPE_INVENTORY_FROM_XML); // ! BUG ! Should this be removed? -void LLInventoryPanel::draw() -{ - // select the desired item (in case it wasn't loaded when the selection was requested) - mFolders->updateSelection(); - LLPanel::draw(); -} - -void LLInventoryPanel::setFilterTypes(U64 filter_types, BOOL filter_for_categories) -{ - mFolders->getFilter()->setFilterTypes(filter_types, filter_for_categories); -} - -void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask) -{ - mFolders->getFilter()->setFilterPermissions(filter_perm_mask); -} - -void LLInventoryPanel::setFilterSubString(const std::string& string) -{ - mFolders->getFilter()->setFilterSubString(string); -} - -void LLInventoryPanel::setSortOrder(U32 order) -{ - mFolders->getFilter()->setSortOrder(order); - if (mFolders->getFilter()->isModified()) - { - mFolders->setSortOrder(order); - // try to keep selection onscreen, even if it wasn't to start with - mFolders->scrollToShowSelection(); - } -} - -void LLInventoryPanel::setSinceLogoff(BOOL sl) -{ - mFolders->getFilter()->setDateRangeLastLogoff(sl); -} - -void LLInventoryPanel::setHoursAgo(U32 hours) -{ - mFolders->getFilter()->setHoursAgo(hours); -} - -void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show) -{ - mFolders->getFilter()->setShowFolderState(show); -} - -LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState() -{ - return mFolders->getFilter()->getShowFolderState(); -} - -static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); - -void LLInventoryPanel::modelChanged(U32 mask) -{ - LLFastTimer t2(FTM_REFRESH); - - bool handled = false; - - // inventory just initialized, do complete build - if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection) - { - rebuildViewsFor(mStartFolderID); - mHasInventoryConnection = true; - return; - } - - if(mask & LLInventoryObserver::LABEL) - { - handled = true; - // label change - empty out the display name for each object - // in this change set. - const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); - std::set<LLUUID>::const_iterator id_it = changed_items.begin(); - std::set<LLUUID>::const_iterator id_end = changed_items.end(); - LLFolderViewItem* view = NULL; - LLInvFVBridge* bridge = NULL; - for (;id_it != id_end; ++id_it) - { - view = mFolders->getItemByID(*id_it); - if(view) - { - // request refresh on this item (also flags for filtering) - bridge = (LLInvFVBridge*)view->getListener(); - if(bridge) - { // Clear the display name first, so it gets properly re-built during refresh() - bridge->clearDisplayName(); - } - view->refresh(); - } - } - } - if((mask & (LLInventoryObserver::STRUCTURE - | LLInventoryObserver::ADD - | LLInventoryObserver::REMOVE)) != 0) - { - handled = true; - // Record which folders are open by uuid. - LLInventoryModel* model = getModel(); - if (model) - { - const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); - - std::set<LLUUID>::const_iterator id_it = changed_items.begin(); - std::set<LLUUID>::const_iterator id_end = changed_items.end(); - for (;id_it != id_end; ++id_it) - { - // sync view with model - LLInventoryObject* model_item = model->getObject(*id_it); - LLFolderViewItem* view_item = mFolders->getItemByID(*id_it); - - if (model_item) - { - if (!view_item) - { - // this object was just created, need to build a view for it - if ((mask & LLInventoryObserver::ADD) != LLInventoryObserver::ADD) - { - llwarns << *id_it << " is in model but not in view, but ADD flag not set" << llendl; - } - buildNewViews(*id_it); - - // select any newly created object - // that has the auto rename at top of folder - // root set - if(mFolders->getRoot()->needsAutoRename()) - { - setSelection(*id_it, FALSE); - } - } - else - { - // this object was probably moved, check its parent - if ((mask & LLInventoryObserver::STRUCTURE) != LLInventoryObserver::STRUCTURE) - { - llwarns << *id_it << " is in model and in view, but STRUCTURE flag not set" << llendl; - } - - LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID()); - - // added check against NULL for cases when Inventory panel contains startFolder. - // in this case parent is LLFolderView (LLInventoryPanel::mFolders) itself. - // this check is a fix for bug EXT-1859. - if (NULL != new_parent && view_item->getParentFolder() != new_parent) - { - view_item->getParentFolder()->extractItem(view_item); - view_item->addToFolder(new_parent, mFolders); - } -/* - on the other side in case Inventory Panel has content of the any folder - it is possible that item moved to some folder which is absent in current - Panel. For ex. removing item (via moving to trash). - In this case we need to check if new parent is other then inventory start folder - and simply remove its View from the hierarchy. - See details in EXT-2098. -*/ - // So, let check if item was moved into folder out of this Inventory Panel. - else if (mStartFolderID.notNull() && NULL == new_parent && model_item->getParentUUID() != mStartFolderID) - { - view_item->getParentFolder()->extractItem(view_item); - } - } - } - else - { - if (view_item) - { - if ((mask & LLInventoryObserver::REMOVE) != LLInventoryObserver::REMOVE) - { - llwarns << *id_it << " is not in model but in view, but REMOVE flag not set" << llendl; - } - // item in view but not model, need to delete view - view_item->destroyView(); - } - else - { - llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl; - } - } - } - } - } - - if (!handled) - { - // it's a small change that only requires a refresh. - // *TODO: figure out a more efficient way to do the refresh - // since it is expensive on large inventories - mFolders->refresh(); - } -} - - -void LLInventoryPanel::rebuildViewsFor(const LLUUID& id) -{ - LLFolderViewItem* old_view = NULL; - - // get old LLFolderViewItem - old_view = mFolders->getItemByID(id); - if (old_view && id.notNull()) - { - old_view->destroyView(); - } - - buildNewViews(id); -} - -void LLInventoryPanel::buildNewViews(const LLUUID& id) -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS); - LLFolderViewItem* itemp = NULL; - LLInventoryObject* objectp = NULL; - - // Don't add the start folder (the inventory panel will show contents - // beginning with the children of the starting folder, excluding the starting folder itself). - if (id != mStartFolderID) - { - objectp = gInventory.getObject(id); - if (objectp) - { - const LLUUID &parent_id = objectp->getParentUUID(); - // If this item's parent is the starting folder, then just add it to the top level (recall that - // the starting folder isn't actually represented in the view, parent_folder would be NULL in - // this case otherwise). - LLFolderViewFolder* parent_folder = (parent_id == mStartFolderID ? - mFolders : (LLFolderViewFolder*)mFolders->getItemByID(parent_id)); - - // This item exists outside the inventory's hierarchy, so don't add it. - if (!parent_folder) - { - return; - } - - if (objectp->getType() <= LLAssetType::AT_NONE || - objectp->getType() >= LLAssetType::AT_COUNT) - { - llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " << - ((S32) objectp->getType()) << llendl; - return; - } - - if (objectp->getType() == LLAssetType::AT_CATEGORY && - objectp->getActualType() != LLAssetType::AT_LINK_FOLDER) - { - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), - objectp->getType(), - LLInventoryType::IT_CATEGORY, - this, - objectp->getUUID()); - - if (new_listener) - { - LLFolderViewFolder::Params p; - p.name = new_listener->getDisplayName(); - p.icon = new_listener->getIcon(); - p.root = mFolders; - p.listener = new_listener; - LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(p); - - folderp->setItemSortOrder(mFolders->getSortOrder()); - itemp = folderp; - } - } - else - { - // Build new view for item - LLInventoryItem* item = (LLInventoryItem*)objectp; - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), - item->getActualType(), - item->getInventoryType(), - this, - item->getUUID(), - item->getFlags()); - - if (new_listener) - { - LLFolderViewItem::Params params; - params.name(new_listener->getDisplayName()); - params.icon(new_listener->getIcon()); - params.creation_date(new_listener->getCreationDate()); - params.root(mFolders); - params.listener(new_listener); - params.rect(LLRect (0, 0, 0, 0)); - itemp = LLUICtrlFactory::create<LLFolderViewItem> (params); - } - } - - if (itemp) - { - itemp->addToFolder(parent_folder, mFolders); - } - } - } - - // If this is a folder, add the children of the folder and recursively add any - // child folders. - if ((id == mStartFolderID) || - (objectp && objectp->getType() == LLAssetType::AT_CATEGORY)) - { - LLViewerInventoryCategory::cat_array_t* categories; - LLViewerInventoryItem::item_array_t* items; - - mInventory->lockDirectDescendentArrays(id, categories, items); - if(categories) - { - S32 count = categories->count(); - for(S32 i = 0; i < count; ++i) - { - LLInventoryCategory* cat = categories->get(i); - buildNewViews(cat->getUUID()); - } - } - if(items) - { - S32 count = items->count(); - for(S32 i = 0; i < count; ++i) - { - LLInventoryItem* item = items->get(i); - buildNewViews(item->getUUID()); - } - } - mInventory->unlockDirectDescendentArrays(id); - } -} - -struct LLConfirmPurgeData -{ - LLUUID mID; - LLInventoryModel* mModel; -}; - -class LLIsNotWorn : public LLInventoryCollectFunctor -{ -public: - LLIsNotWorn() {} - virtual ~LLIsNotWorn() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item) - { - return !gAgentWearables.isWearingItem(item->getUUID()); - } -}; - -class LLOpenFolderByID : public LLFolderViewFunctor -{ -public: - LLOpenFolderByID(const LLUUID& id) : mID(id) {} - virtual ~LLOpenFolderByID() {} - virtual void doFolder(LLFolderViewFolder* folder) - { - if (folder->getListener() && folder->getListener()->getUUID() == mID) folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); - } - virtual void doItem(LLFolderViewItem* item) {} -protected: - const LLUUID& mID; -}; - - -void LLInventoryPanel::openSelected() -{ - LLFolderViewItem* folder_item = mFolders->getCurSelectedItem(); - if(!folder_item) return; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); - if(!bridge) return; - bridge->openItem(); -} - -BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask) -{ - BOOL handled = LLView::handleHover(x, y, mask); - if(handled) - { - ECursorType cursor = getWindow()->getCursor(); - if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW) - { - // replace arrow cursor with arrow and hourglass cursor - getWindow()->setCursor(UI_CURSOR_WORKING); - } - } - else - { - getWindow()->setCursor(UI_CURSOR_ARROW); - } - return TRUE; -} - -BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - - BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - - if (handled) - { - mFolders->setDragAndDropThisFrame(); - } - - return handled; -} - -void LLInventoryPanel::onFocusLost() -{ - // inventory no longer handles cut/copy/paste/delete - if (LLEditMenuHandler::gEditMenuHandler == mFolders) - { - LLEditMenuHandler::gEditMenuHandler = NULL; - } - - LLPanel::onFocusLost(); -} - -void LLInventoryPanel::onFocusReceived() -{ - // inventory now handles cut/copy/paste/delete - LLEditMenuHandler::gEditMenuHandler = mFolders; - - LLPanel::onFocusReceived(); -} - - -void LLInventoryPanel::openAllFolders() -{ - mFolders->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); - mFolders->arrangeAll(); -} - -void LLInventoryPanel::openDefaultFolderForType(LLAssetType::EType type) -{ - LLUUID category_id = mInventory->findCategoryUUIDForType(type); - LLOpenFolderByID opener(category_id); - mFolders->applyFunctorRecursively(opener); -} - -void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus) -{ - // Don't select objects in COF (e.g. to prevent refocus when items are worn). - const LLInventoryObject *obj = gInventory.getObject(obj_id); - if (obj && obj->getParentUUID() == LLAppearanceManager::getCOF()) - { - return; - } - mFolders->setSelectionByID(obj_id, take_keyboard_focus); -} - -void LLInventoryPanel::clearSelection() -{ - mFolders->clearSelection(); -} - -void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action) -{ - LLFolderView* fv = getRootFolder(); - if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename - { - fv->setNeedsAutoRename(FALSE); - if (items.size()) // new asset is visible and selected - { - fv->startRenamingSelectedItem(); - } - } - // Seraph - Put determineFolderType in here for ensemble typing? -} - -//---------------------------------------------------------------------------- - -void LLInventoryPanel::doToSelected(const LLSD& userdata) -{ - mFolders->doToSelected(&gInventory, userdata); -} - -void LLInventoryPanel::doCreate(const LLSD& userdata) -{ - menu_create_inventory_item(mFolders, LLFolderBridge::sSelf, userdata); -} - -bool LLInventoryPanel::beginIMSession() -{ - std::set<LLUUID> selected_items; - mFolders->getSelectionList(selected_items); - - std::string name; - static int session_num = 1; - - LLDynamicArray<LLUUID> members; - EInstantMessage type = IM_SESSION_CONFERENCE_START; - - std::set<LLUUID>::const_iterator iter; - for (iter = selected_items.begin(); iter != selected_items.end(); iter++) - { - - LLUUID item = *iter; - LLFolderViewItem* folder_item = mFolders->getItemByID(item); - - if(folder_item) - { - LLFolderViewEventListener* fve_listener = folder_item->getListener(); - if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY)) - { - - LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); - if(!bridge) return true; - LLViewerInventoryCategory* cat = bridge->getCategory(); - if(!cat) return true; - name = cat->getName(); - LLUniqueBuddyCollector is_buddy; - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendentsIf(bridge->getUUID(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_buddy); - S32 count = item_array.count(); - if(count > 0) - { - LLFloaterReg::showInstance("communicate"); - // create the session - LLAvatarTracker& at = LLAvatarTracker::instance(); - LLUUID id; - for(S32 i = 0; i < count; ++i) - { - id = item_array.get(i)->getCreatorUUID(); - if(at.isBuddyOnline(id)) - { - members.put(id); - } - } - } - } - else - { - LLFolderViewItem* folder_item = mFolders->getItemByID(item); - if(!folder_item) return true; - LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); - - if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD) - { - LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID()); - - if (inv_item) - { - LLAvatarTracker& at = LLAvatarTracker::instance(); - LLUUID id = inv_item->getCreatorUUID(); - - if(at.isBuddyOnline(id)) - { - members.put(id); - } - } - } //if IT_CALLINGCARD - } //if !IT_CATEGORY - } - } //for selected_items - - // the session_id is randomly generated UUID which will be replaced later - // with a server side generated number - - if (name.empty()) - { - name = llformat("Session %d", session_num++); - } - - gIMMgr->addSession(name, type, members[0], members); - - return true; -} - -bool LLInventoryPanel::attachObject(const LLSD& userdata) -{ - std::set<LLUUID> selected_items; - mFolders->getSelectionList(selected_items); - - std::string joint_name = userdata.asString(); - LLVOAvatar *avatarp = static_cast<LLVOAvatar*>(gAgent.getAvatarObject()); - LLViewerJointAttachment* attachmentp = NULL; - for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); - iter != avatarp->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - if (attachment->getName() == joint_name) - { - attachmentp = attachment; - break; - } - } - if (attachmentp == NULL) - { - return true; - } - - for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin(); - set_iter != selected_items.end(); - ++set_iter) - { - const LLUUID &id = *set_iter; - LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id); - if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID())) - { - rez_attachment(item, attachmentp); - } - else if(item && item->isComplete()) - { - // must be in library. copy it to our inventory and put it on. - LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp); - copy_inventory_item(gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - } - gFocusMgr.setKeyboardFocus(NULL); - - return true; -} - - -//---------------------------------------------------------------------------- - -// static DEBUG ONLY: -void LLInventoryPanel::dumpSelectionInformation(void* user_data) -{ - LLInventoryPanel* iv = (LLInventoryPanel*)user_data; - iv->mFolders->dumpSelectionInformation(); -} - -BOOL LLInventoryPanel::getSinceLogoff() -{ - return mFolders->getFilter()->isSinceLogoff(); -} - -void example_param_block_usage() +void LLFloaterInventory::onOpen(const LLSD& key) { - LLInventoryPanel::Params param_block; - param_block.name(std::string("inventory")); - - param_block.sort_order_setting(LLInventoryPanel::RECENTITEMS_SORT_ORDER); - param_block.allow_multi_select(true); - param_block.filter(LLInventoryPanel::Filter() - .sort_order(1) - .types(0xffff0000)); - param_block.inventory(&gInventory); - param_block.has_border(true); - - LLUICtrlFactory::create<LLInventoryPanel>(param_block); - - param_block = LLInventoryPanel::Params(); - param_block.name(std::string("inventory")); - - //LLSD param_block_sd; - //param_block_sd["sort_order_setting"] = LLInventoryPanel::RECENTITEMS_SORT_ORDER; - //param_block_sd["allow_multi_select"] = true; - //param_block_sd["filter"]["sort_order"] = 1; - //param_block_sd["filter"]["types"] = (S32)0xffff0000; - //param_block_sd["has_border"] = true; - - //LLInitParam::LLSDParser(param_block_sd).parse(param_block); - - LLUICtrlFactory::create<LLInventoryPanel>(param_block); + LLFirstUse::useInventory(); } diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h index 4c9ac5d4c6..c0de89bff2 100644 --- a/indra/newview/llfloaterinventory.h +++ b/indra/newview/llfloaterinventory.h @@ -31,366 +31,55 @@ * $/LicenseInfo$ */ -#ifndef LL_LLINVENTORYVIEW_H -#define LL_LLINVENTORYVIEW_H +#ifndef LL_LLFLOATERINVENTORY_H +#define LL_LLFLOATERINVENTORY_H -#include "llassetstorage.h" -#include "lldarray.h" #include "llfloater.h" -#include "llinventory.h" -#include "llinventoryfilter.h" -#include "llfolderview.h" -#include "llinventorymodel.h" -#include "lluictrlfactory.h" -#include <set> +#include "llfoldertype.h" +class LLInventoryPanel; +class LLPanelMainInventory; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFloaterInventory // -// This is the agent inventory _floater_. -// It deals with the buttons and views used to navigate as -// well as controls the behavior of the overall object. +// This deals with the buttons and views used to navigate as +// well as controlling the behavior of the overall object. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLFolderViewItem; -class LLInventoryFilter; -class LLInventoryModel; -class LLInvFVBridge; -class LLInventoryFVBridgeBuilder; -class LLMenuBarGL; -class LLCheckBoxCtrl; -class LLSpinCtrl; -class LLScrollContainer; -class LLTextBox; -class LLIconCtrl; -class LLSaveFolderState; -class LLFilterEditor; -class LLTabContainer; - -class LLInventoryPanel : public LLPanel +class LLFloaterInventory : public LLFloater { public: - static const std::string DEFAULT_SORT_ORDER; - static const std::string RECENTITEMS_SORT_ORDER; - static const std::string INHERIT_SORT_ORDER; - - struct Filter : public LLInitParam::Block<Filter> - { - Optional<U32> sort_order; - Optional<U32> types; - Optional<std::string> search_string; - - Filter() - : sort_order("sort_order"), - types("types", 0xffffffff), - search_string("search_string") - {} - }; - - struct Params - : public LLInitParam::Block<Params, LLPanel::Params> - { - Optional<std::string> sort_order_setting; - Optional<LLInventoryModel*> inventory; - Optional<bool> allow_multi_select; - Optional<Filter> filter; - Optional<std::string> start_folder; - - Params() - : sort_order_setting("sort_order_setting"), - inventory("", &gInventory), - allow_multi_select("allow_multi_select", true), - filter("filter"), - start_folder("start_folder") - {} - }; - -protected: - LLInventoryPanel(const Params&); - friend class LLUICtrlFactory; - -public: - virtual ~LLInventoryPanel(); - - LLInventoryModel* getModel() { return mInventory; } - - BOOL postBuild(); - - // LLView methods - void draw(); - BOOL handleHover(S32 x, S32 y, MASK mask); - BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - // LLUICtrl methods - /*virtual*/ void onFocusLost(); - /*virtual*/ void onFocusReceived(); - - // Call this method to set the selection. - void openAllFolders(); - void openDefaultFolderForType(LLAssetType::EType); - void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus); - void setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { if (mFolders) mFolders->setSelectCallback(cb); } - void clearSelection(); - LLInventoryFilter* getFilter() { return mFolders->getFilter(); } - void setFilterTypes(U64 filter, BOOL filter_for_categories = FALSE); // if filter_for_categories is true, operate on folder preferred asset type - U32 getFilterTypes() const { return mFolders->getFilterTypes(); } - void setFilterPermMask(PermissionMask filter_perm_mask); - U32 getFilterPermMask() const { return mFolders->getFilterPermissions(); } - void setFilterSubString(const std::string& string); - const std::string getFilterSubString() { return mFolders->getFilterSubString(); } - void setSortOrder(U32 order); - U32 getSortOrder() { return mFolders->getSortOrder(); } - void setSinceLogoff(BOOL sl); - void setHoursAgo(U32 hours); - BOOL getSinceLogoff(); - - void setShowFolderState(LLInventoryFilter::EFolderShow show); - LLInventoryFilter::EFolderShow getShowFolderState(); - void setAllowMultiSelect(BOOL allow) { mFolders->setAllowMultiSelect(allow); } - // This method is called when something has changed about the inventory. - void modelChanged(U32 mask); - LLFolderView* getRootFolder() { return mFolders; } - LLScrollContainer* getScrollableContainer() { return mScroller; } - - void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); - - // Callbacks - void doToSelected(const LLSD& userdata); - void doCreate(const LLSD& userdata); - bool beginIMSession(); - bool attachObject(const LLSD& userdata); - - // DEBUG ONLY: - static void dumpSelectionInformation(void* user_data); - - void openSelected(); - void unSelectAll() { mFolders->setSelection(NULL, FALSE, FALSE); } - -protected: - // Given the id and the parent, build all of the folder views. - void rebuildViewsFor(const LLUUID& id); - virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719 - -protected: - LLInventoryModel* mInventory; - LLInventoryObserver* mInventoryObserver; - BOOL mAllowMultiSelect; - std::string mSortOrderSetting; - -//private: // Can not make these private - needed by llinventorysubtreepanel - LLFolderView* mFolders; - std::string mStartFolderString; - - /** - * Contains UUID of Inventory item from which hierarchy should be built. - * Can be set with the "start_folder" xml property. - * Default is LLUUID::null that means total Inventory hierarchy. - */ - LLUUID mStartFolderID; - LLScrollContainer* mScroller; - bool mHasInventoryConnection; - - /** - * Flag specified if default inventory hierarchy should be created in postBuild() - */ - bool mBuildDefaultHierarchy; - - LLUUID mRootInventoryItemUUID; - - /** - * Pointer to LLInventoryFVBridgeBuilder. - * - * It is set in LLInventoryPanel's constructor and can be overridden in derived classes with - * another implementation. - * Take into account it will not be deleted by LLInventoryPanel itself. - */ - const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder; - -}; - -class LLFloaterInventory; - -class LLFloaterInventoryFinder : public LLFloater -{ -public: - LLFloaterInventoryFinder( LLFloaterInventory* inventory_view); - virtual void draw(); - /*virtual*/ BOOL postBuild(); - void changeFilter(LLInventoryFilter* filter); - void updateElementsFromFilter(); - BOOL getCheckShowEmpty(); - BOOL getCheckSinceLogoff(); - - static void onTimeAgo(LLUICtrl*, void *); - static void onCheckSinceLogoff(LLUICtrl*, void *); - static void onCloseBtn(void* user_data); - static void selectAllTypes(void* user_data); - static void selectNoTypes(void* user_data); - -protected: - LLFloaterInventory* mFloaterInventory; - LLSpinCtrl* mSpinSinceDays; - LLSpinCtrl* mSpinSinceHours; - LLInventoryFilter* mFilter; -}; - -class LLFloaterInventory : public LLFloater, LLInventoryObserver -{ -friend class LLFloaterInventoryFinder; - -public: LLFloaterInventory(const LLSD& key); ~LLFloaterInventory(); - /*virtual*/ void changed(U32 mask); - - BOOL postBuild(); - - // - // Misc functions - // - void setFilterTextFromFilter() { mFilterText = mActivePanel->getFilter()->getFilterText(); } - void startSearch(); - - // This method makes sure that an inventory view exists, is - // visible, and has focus. The view chosen is returned. - static LLFloaterInventory* showAgentInventory(); + BOOL postBuild(); // Return the active inventory view if there is one. Active is // defined as the inventory that is the closest to the front, and // is visible. static LLFloaterInventory* getActiveInventory(); - // This method calls showAgentInventory() if no views are visible, - // or hides/destroyes them all if any are visible. - static void toggleVisibility(); - static void toggleVisibility(void*) { toggleVisibility(); } + // This method makes sure that an inventory view exists, is + // visible, and has focus. The view chosen is returned. + static LLFloaterInventory* showAgentInventory(); // Final cleanup, destroy all open inventory views. static void cleanup(); - // LLView & LLFloater functionality - virtual void onOpen(const LLSD& key); - virtual void draw(); - virtual BOOL handleKeyHere(KEY key, MASK mask); - - BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - - - LLInventoryPanel* getPanel() { return mActivePanel; } - LLInventoryPanel* getActivePanel() { return mActivePanel; } - - static BOOL filtersVisible(void* user_data); - void onClearSearch(); - static void onFoldersByName(void *user_data); - static BOOL checkFoldersByName(void *user_data); - void onFilterEdit(const std::string& search_string ); - static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward); - void onFilterSelected(); - - const std::string getFilterSubString() { return mActivePanel->getFilterSubString(); } - void setFilterSubString(const std::string& string) { mActivePanel->setFilterSubString(string); } - - // menu callbacks - void doToSelected(const LLSD& userdata); - void closeAllFolders(); - void doCreate(const LLSD& userdata); - void resetFilters(); - void setSortBy(const LLSD& userdata); - - // HACK: Until we can route this info through the instant message hierarchy - static BOOL sWearNewClothing; - static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction - - void toggleFindOptions(); - - LLFloaterInventoryFinder* getFinder() { return (LLFloaterInventoryFinder*)mFinderHandle.get(); } + // Inherited functionality + /*virtual*/ void changed(U32 mask); + /*virtual*/ void draw(); + /*virtual*/ void onOpen(const LLSD& key); + LLInventoryPanel* getPanel(); protected: - LLFilterEditor* mFilterEditor; - LLTabContainer* mFilterTabs; - LLHandle<LLFloater> mFinderHandle; - LLInventoryPanel* mActivePanel; - LLSaveFolderState* mSavedFolderState; - - std::string mFilterText; - -private: void updateTitle(); +private: + LLPanelMainInventory* mPanelMainInventory; }; -class LLSelectFirstFilteredItem : public LLFolderViewFunctor -{ -public: - LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} - virtual ~LLSelectFirstFilteredItem() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - BOOL wasItemSelected() { return mItemSelected; } -protected: - BOOL mItemSelected; -}; - -class LLOpenFilteredFolders : public LLFolderViewFunctor -{ -public: - LLOpenFilteredFolders() {} - virtual ~LLOpenFilteredFolders() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -class LLSaveFolderState : public LLFolderViewFunctor -{ -public: - LLSaveFolderState() : mApply(FALSE) {} - virtual ~LLSaveFolderState() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item) {} - void setApply(BOOL apply); - void clearOpenFolders() { mOpenFolders.clear(); } -protected: - std::set<LLUUID> mOpenFolders; - BOOL mApply; -}; - -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: - LLOpenFoldersWithSelection() {} - virtual ~LLOpenFoldersWithSelection() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -///---------------------------------------------------------------------------- -/// Function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -// useful functions with the inventory view - -class LLInventoryCategory; -class LLInventoryItem; - -const std::string& get_item_icon_name(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 attachment_point, - BOOL item_is_multi ); - -LLUIImagePtr get_item_icon(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 attachment_point, - BOOL item_is_multi ); - -#endif // LL_LLINVENTORYVIEW_H +#endif // LL_LLFLOATERINVENTORY_H diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp index 0c9a759f32..3fe711a166 100644 --- a/indra/newview/llfloatermap.cpp +++ b/indra/newview/llfloatermap.cpp @@ -51,11 +51,26 @@ #include "llviewermenu.h" // +// Constants +// +const F32 MAP_MINOR_DIR_THRESHOLD = 0.08f; + +// // Member functions // LLFloaterMap::LLFloaterMap(const LLSD& key) - : LLFloater(key) + : LLFloater(key), + mPopupMenu(NULL), + mTextBoxEast(NULL), + mTextBoxNorth(NULL), + mTextBoxWest(NULL), + mTextBoxSouth(NULL), + mTextBoxSouthEast(NULL), + mTextBoxNorthEast(NULL), + mTextBoxNorthWest(NULL), + mTextBoxSouthWest(NULL), + mMap(NULL) { //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_map.xml", FALSE); } @@ -92,6 +107,8 @@ BOOL LLFloaterMap::postBuild() mPopupMenu->setItemEnabled ("Stop Tracking", false); } + updateMinorDirections(); + // Get the drag handle all the way in back sendChildToBack(getDragHandle()); @@ -139,6 +156,23 @@ void LLFloaterMap::setDirectionPos( LLTextBox* text_box, F32 rotation ) llround(map_half_height - text_half_height + radius * sin( rotation )) ); } +void LLFloaterMap::updateMinorDirections() +{ + if (mTextBoxNorthEast == NULL) + { + return; + } + + // Hide minor directions if they cover too much of the map + bool show_minors = mTextBoxNorthEast->getRect().getHeight() < MAP_MINOR_DIR_THRESHOLD * + llmin(getRect().getWidth(), getRect().getHeight()); + + mTextBoxNorthEast->setVisible(show_minors); + mTextBoxNorthWest->setVisible(show_minors); + mTextBoxSouthWest->setVisible(show_minors); + mTextBoxSouthEast->setVisible(show_minors); +} + // virtual void LLFloaterMap::draw() { @@ -180,17 +214,23 @@ void LLFloaterMap::draw() LLFloater::draw(); } +void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLFloater::reshape(width, height, called_from_parent); + updateMinorDirections(); +} + void LLFloaterMap::handleZoom(const LLSD& userdata) { std::string level = userdata.asString(); F32 scale = 0.0f; if (level == std::string("close")) - scale = MAP_SCALE_MAX; + scale = LLNetMap::MAP_SCALE_MAX; else if (level == std::string("medium")) - scale = MAP_SCALE_MID; + scale = LLNetMap::MAP_SCALE_MID; else if (level == std::string("far")) - scale = MAP_SCALE_MIN; + scale = LLNetMap::MAP_SCALE_MIN; if (scale != 0.0f) { gSavedSettings.setF32("MiniMapScale", scale ); diff --git a/indra/newview/llfloatermap.h b/indra/newview/llfloatermap.h index 501777ed07..6c9138c6a7 100644 --- a/indra/newview/llfloatermap.h +++ b/indra/newview/llfloatermap.h @@ -51,12 +51,14 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); /*virtual*/ void draw(); private: void handleZoom(const LLSD& userdata); void handleStopTracking (const LLSD& userdata); void setDirectionPos( LLTextBox* text_box, F32 rotation ); + void updateMinorDirections(); LLMenuGL* mPopupMenu; diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index ed7d2c71ea..b7296518d4 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -176,7 +176,7 @@ void LLFloaterNameDesc::onBtnOK( ) upload_new_resource(mFilenameAndPath, // file childGetValue("name_form").asString(), childGetValue("description_form").asString(), - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), display_name, callback, expected_upload_cost, nruserdata); closeFloater(false); diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index aa82dc34b7..e277aba493 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -32,7 +32,7 @@ /* * Shows the contents of an object. - * A floater wrapper for llpanelinventory + * A floater wrapper for LLPanelObjectInventory */ #include "llviewerprecompiledheaders.h" @@ -47,7 +47,8 @@ #include "llinventorybridge.h" #include "llfloaterinventory.h" #include "llinventorymodel.h" -#include "llpanelinventory.h" +#include "llinventorypanel.h" +#include "llpanelobjectinventory.h" #include "llfloaterreg.h" #include "llselectmgr.h" #include "lluiconstants.h" @@ -58,7 +59,7 @@ LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key) : LLFloater(key), - mPanelInventory(NULL), + mPanelInventoryObject(NULL), mDirty(TRUE) { // LLUICtrlFactory::getInstance()->buildFloater(this,"floater_openobject.xml"); @@ -74,7 +75,7 @@ LLFloaterOpenObject::~LLFloaterOpenObject() BOOL LLFloaterOpenObject::postBuild() { childSetTextArg("object_name", "[DESC]", std::string("Object") ); // *Note: probably do not want to translate this - mPanelInventory = getChild<LLPanelInventory>("object_contents"); + mPanelInventoryObject = getChild<LLPanelObjectInventory>("object_contents"); return TRUE; } @@ -96,7 +97,7 @@ void LLFloaterOpenObject::onOpen(const LLSD& key) } void LLFloaterOpenObject::refresh() { - mPanelInventory->refresh(); + mPanelInventoryObject->refresh(); std::string name; BOOL enabled; @@ -157,14 +158,14 @@ void LLFloaterOpenObject::moveToInventory(bool wear) if (wear) { parent_category_id = gInventory.findCategoryUUIDForType( - LLAssetType::AT_CLOTHING); + LLFolderType::FT_CLOTHING); } else { parent_category_id = gInventory.getRootFolderID(); } LLUUID category_id = gInventory.createNewCategory(parent_category_id, - LLAssetType::AT_NONE, + LLFolderType::FT_NONE, name); LLCatAndWear* data = new LLCatAndWear; diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h index a61cc04941..10d96b7ea3 100644 --- a/indra/newview/llfloateropenobject.h +++ b/indra/newview/llfloateropenobject.h @@ -41,7 +41,7 @@ #include "llfloater.h" class LLObjectSelection; -class LLPanelInventory; +class LLPanelObjectInventory; class LLFloaterOpenObject : public LLFloater @@ -77,7 +77,7 @@ private: protected: - LLPanelInventory* mPanelInventory; + LLPanelObjectInventory* mPanelInventoryObject; LLSafeHandle<LLObjectSelection> mObjectSelection; BOOL mDirty; }; diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp index 88811d06fe..c2389e73a0 100644 --- a/indra/newview/llfloaterpay.cpp +++ b/indra/newview/llfloaterpay.cpp @@ -444,13 +444,11 @@ void LLFloaterPay::onCacheOwnerName(const LLUUID& owner_id, { if (is_group) { - childSetVisible("payee_group",true); - childSetVisible("payee_resident",false); + setTitle(getString("payee_group")); } else { - childSetVisible("payee_group",false); - childSetVisible("payee_resident",true); + setTitle(getString("payee_resident")); } childSetTextArg("payee_name", "[FIRST]", firstname); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 70a3ad5252..1002697fe5 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -770,7 +770,7 @@ void LLFloaterReporter::takeScreenshot() if (COMPLAINT_REPORT == mReportType) { mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE; - mResourceDatap->mPreferredLocation = LLAssetType::EType(-2); + mResourceDatap->mPreferredLocation = LLFolderType::EType(LLResourceData::INVALID_LOCATION); } else { @@ -789,8 +789,8 @@ void LLFloaterReporter::takeScreenshot() // store in the image list so it doesn't try to fetch from the server LLPointer<LLViewerFetchedTexture> image_in_list = - LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, FALSE, LLViewerTexture::FETCHED_TEXTURE); - image_in_list->createGLTexture(0, raw); + LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE); + image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerTexture::OTHER); // the texture picker then uses that texture LLTexturePicker* texture = getChild<LLTextureCtrl>("screenshot"); @@ -838,7 +838,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, } EReportType report_type = UNKNOWN_REPORT; - if (data->mPreferredLocation == -2) + if (data->mPreferredLocation == LLResourceData::INVALID_LOCATION) { report_type = COMPLAINT_REPORT; } diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index 3bf1848efb..eeea71cc4c 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -106,7 +106,7 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std: if (objectp) { - objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, TRUE)); + objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLViewerTexture::BOOST_UI)); floater_label = llformat("%s(%.2f, %.2f)", user_name.c_str(), objectp->getPositionRegion().mV[VX], objectp->getPositionRegion().mV[VY]); } else diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index bd9798c18e..97c573ddea 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -34,8 +34,8 @@ #include "llviewerprecompiledheaders.h" #include "llfloatersearch.h" #include "llmediactrl.h" -#include "llagent.h" - +#include "lllogininstance.h" +#include "lluri.h" LLFloaterSearch::LLFloaterSearch(const LLSD& key) : LLFloater(key), @@ -116,15 +116,11 @@ void LLFloaterSearch::search(const LLSD &key) // append the search query string std::string search_text = key.has("id") ? key["id"].asString() : ""; - url += std::string("?q=") + search_text; + url += std::string("?q=") + LLURI::escape(search_text); - // append the maturity and teen capabilities for this agent - BOOL godlike = gAgent.isGodlike(); - bool mature_enabled = gAgent.canAccessMature() || godlike; - bool adult_enabled = gAgent.canAccessAdult() || godlike; - std::string mature = (mature_enabled) ? "True" : "False"; - std::string teen = (!adult_enabled) ? "True" : "False"; - url += "&t=" + teen + "&m=" + mature; + // append the permissions token that login.cgi gave us + LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token"); + url += "&p=" + search_token.asString(); // and load the URL in the web view mBrowser->navigateTo(url); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 235e819218..fd2e7b3487 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -980,7 +980,7 @@ void LLSnapshotLivePreview::saveTexture() "Snapshot : " + pos_string, "Taken by " + who_took_it + " at " + pos_string, 0, - LLAssetType::AT_SNAPSHOT_CATEGORY, + LLFolderType::FT_SNAPSHOT_CATEGORY, LLInventoryType::IT_SNAPSHOT, PERM_ALL, // Note: Snapshots to inventory is a special case of content upload PERM_NONE, // that ignores the user's premissions preferences and continues to @@ -1373,8 +1373,10 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, void LLFloaterSnapshot::Impl::onClickDiscard(void* data) { LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + if (view) { + view->getParent()->setMouseOpaque(FALSE); view->closeFloater(); } } diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 5fee84190b..3aef15a35c 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -54,7 +54,7 @@ #include "llpanelcontents.h" #include "llpanelface.h" #include "llpanelland.h" -#include "llpanelinventory.h" +#include "llpanelobjectinventory.h" #include "llpanelobject.h" #include "llpanelvolume.h" #include "llpanelpermissions.h" diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 2fe21f28de..663bd232f7 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -670,6 +670,15 @@ void LLFloaterUIPreview::refreshList() } } + found = TRUE; + while(found) // for every sidepanel file that matches the pattern + { + if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name, FALSE))) // get next file matching pattern + { + addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) + } + } + if(!mFileList->isEmpty()) // if there were any matching files, just select the first one (so we don't have to worry about disabling buttons when no entry is selected) { mFileList->selectFirstItem(); diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp index aca9198f59..43024a4bd0 100644 --- a/indra/newview/llfloatervoicedevicesettings.cpp +++ b/indra/newview/llfloatervoicedevicesettings.cpp @@ -49,6 +49,9 @@ #include "lluictrlfactory.h" +static LLRegisterPanelClassWrapper<LLPanelVoiceDeviceSettings> t_panel_group_general("panel_voice_device_settings"); + + LLPanelVoiceDeviceSettings::LLPanelVoiceDeviceSettings() : LLPanel() { @@ -82,8 +85,25 @@ BOOL LLPanelVoiceDeviceSettings::postBuild() return TRUE; } +// virtual +void LLPanelVoiceDeviceSettings::handleVisibilityChange ( BOOL new_visibility ) +{ + if (new_visibility) + { + initialize(); + } + else + { + cleanup(); + // when closing this window, turn of visiblity control so that + // next time preferences is opened we don't suspend voice + gSavedSettings.setBOOL("ShowDeviceSettings", FALSE); + } +} void LLPanelVoiceDeviceSettings::draw() { + refresh(); + // let user know that volume indicator is not yet available bool is_in_tuning_mode = gVoiceClient->inTuningMode(); childSetVisible("wait_text", !is_in_tuning_mode); diff --git a/indra/newview/llfloatervoicedevicesettings.h b/indra/newview/llfloatervoicedevicesettings.h index f1603dc414..d67283d0a2 100644 --- a/indra/newview/llfloatervoicedevicesettings.h +++ b/indra/newview/llfloatervoicedevicesettings.h @@ -50,6 +50,8 @@ public: void initialize(); void cleanup(); + /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); + protected: static void onCommitInputDevice(LLUICtrl* ctrl, void* user_data); static void onCommitOutputDevice(LLUICtrl* ctrl, void* user_data); diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index b7e8835fb8..7d2eb98111 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -45,6 +45,7 @@ #include "llcallingcard.h" #include "llcombobox.h" #include "llviewercontrol.h" +#include "llcommandhandler.h" #include "lldraghandle.h" #include "llfirstuse.h" #include "llfloaterreg.h" // getTypedInstance() @@ -55,7 +56,6 @@ #include "llregionhandle.h" #include "llscrolllistctrl.h" #include "llslurl.h" -#include "lltabcontainer.h" #include "lltextbox.h" #include "lltracker.h" #include "lltrans.h" @@ -63,7 +63,9 @@ #include "llviewermenu.h" #include "llviewerregion.h" #include "llviewerstats.h" +#include "llviewertexture.h" #include "llworldmap.h" +#include "llworldmapmessage.h" #include "llworldmapview.h" #include "lluictrlfactory.h" #include "llappviewer.h" @@ -79,6 +81,12 @@ //--------------------------------------------------------------------------- static const F32 MAP_ZOOM_TIME = 0.2f; +// Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed +// width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across +// sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit. +// Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window. +static const S32 MAX_VISIBLE_REGIONS = 512; + enum EPanDirection { PAN_UP, @@ -96,6 +104,35 @@ static const F32 SIM_COORD_DEFAULT = 128.f; // Globals //--------------------------------------------------------------------------- +// handle secondlife:///app/worldmap/{NAME}/{COORDS} URLs +class LLWorldMapHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, + LLMediaCtrl* web) + { + if (params.size() == 0) + { + return false; + } + + const std::string region_name = params[0].asString(); + S32 x = (params.size() > 1) ? params[1].asInteger() : 128; + S32 y = (params.size() > 2) ? params[2].asInteger() : 128; + S32 z = (params.size() > 3) ? params[3].asInteger() : 0; + + LLFloaterWorldMap::getInstance()->trackURL(region_name, x, y, z); + LLFloaterReg::showInstance("world_map", "center"); + + return true; + } +}; +LLWorldMapHandler gWorldMapHandler; + + LLFloaterWorldMap* gFloaterWorldMap = NULL; class LLMapInventoryObserver : public LLInventoryObserver @@ -160,11 +197,11 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key) gFloaterWorldMap = this; mFactoryMap["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL); - mFactoryMap["terrain_mapview"] = LLCallbackMap(createWorldMapView, NULL); //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_world_map.xml", FALSE); mCommitCallbackRegistrar.add("WMap.Location", boost::bind(&LLFloaterWorldMap::onLocationCommit, this)); mCommitCallbackRegistrar.add("WMap.AvatarCombo", boost::bind(&LLFloaterWorldMap::onAvatarComboCommit, this)); + mCommitCallbackRegistrar.add("WMap.Landmark", boost::bind(&LLFloaterWorldMap::onLandmarkComboCommit, this)); mCommitCallbackRegistrar.add("WMap.SearchResult", boost::bind(&LLFloaterWorldMap::onCommitSearchResult, this)); mCommitCallbackRegistrar.add("WMap.CommitLocation", boost::bind(&LLFloaterWorldMap::onCommitLocation, this)); mCommitCallbackRegistrar.add("WMap.GoHome", boost::bind(&LLFloaterWorldMap::onGoHome, this)); @@ -183,17 +220,7 @@ void* LLFloaterWorldMap::createWorldMapView(void* data) BOOL LLFloaterWorldMap::postBuild() { - mTabs = getChild<LLTabContainer>("maptab"); - if (!mTabs) return FALSE; - - mTabs->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCommitBackground, this)); - - // The following callback syncs the worlmap tabs with the images. - // Commented out since it was crashing when LLWorldMap became a singleton. - // We should be fine without it but override the onOpen method and put it - // there if it turns out to be needed. -MG - // - //onCommitBackground(); + mPanel = getChild<LLPanel>("objects_mapview"); LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo"); if (avatar_combo) @@ -221,8 +248,8 @@ BOOL LLFloaterWorldMap::postBuild() landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); } - mCurZoomVal = log(gMapScale)/log(2.f); - childSetValue("zoom slider", gMapScale); + mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f); + childSetValue("zoom slider", LLWorldMapView::sMapScale); setDefaultBtn(NULL); @@ -235,7 +262,7 @@ BOOL LLFloaterWorldMap::postBuild() LLFloaterWorldMap::~LLFloaterWorldMap() { // All cleaned up by LLView destructor - mTabs = NULL; + mPanel = NULL; // Inventory deletes all observers on shutdown mInventory = NULL; @@ -268,7 +295,7 @@ void LLFloaterWorldMap::onOpen(const LLSD& key) mIsClosing = FALSE; LLWorldMapView* map_panel; - map_panel = (LLWorldMapView*)mTabs->getCurrentPanel(); + map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; map_panel->clearLastClick(); { @@ -279,15 +306,8 @@ void LLFloaterWorldMap::onOpen(const LLSD& key) } map_panel->updateVisibleBlocks(); - // Reload the agent positions when we show the window - LLWorldMap::getInstance()->eraseItems(); - - // Reload any maps that may have changed - LLWorldMap::getInstance()->clearSimFlags(); - - const S32 panel_num = mTabs->getCurrentPanelIndex(); - const bool request_from_sim = true; - LLWorldMap::getInstance()->setCurrentLayer(panel_num, request_from_sim); + // Reload items as they may have changed + LLWorldMap::getInstance()->reloadItems(); // We may already have a bounding box for the regions of the world, // so use that to adjust the view. @@ -297,7 +317,7 @@ void LLFloaterWorldMap::onOpen(const LLSD& key) LLFirstUse::useMap(); // Start speculative download of landmarks - LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + const LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); gInventory.startBackgroundFetch(landmark_folder_id); childSetFocus("location", TRUE); @@ -321,12 +341,9 @@ void LLFloaterWorldMap::onOpen(const LLSD& key) // static void LLFloaterWorldMap::reloadIcons(void*) { - LLWorldMap::getInstance()->eraseItems(); - - LLWorldMap::getInstance()->sendMapLayerRequest(); + LLWorldMap::getInstance()->reloadItems(); } - // virtual BOOL LLFloaterWorldMap::handleHover(S32 x, S32 y, MASK mask) { @@ -358,12 +375,6 @@ BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks) void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent ) { LLFloater::reshape( width, height, called_from_parent ); - - // Might have changed size of world display area - // JC: Technically, this is correct, but it makes the slider "pop" - // if you resize the window, then draw the slider. Just leaving it - // the way it was when you opened the window seems better. - // adjustZoomSliderBounds(); } @@ -427,7 +438,7 @@ void LLFloaterWorldMap::draw() { F64 seconds = LLTimer::getElapsedSeconds(); double value = fmod(seconds, 2); - value = 0.5 + 0.5*cos(value * 3.14159f); + value = 0.5 + 0.5*cos(value * F_PI); LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0); childSetColor("location_icon", loading_color); } @@ -445,7 +456,7 @@ void LLFloaterWorldMap::draw() childSetEnabled("Teleport", (BOOL)tracking_status); // childSetEnabled("Clear", (BOOL)tracking_status); - childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->mIsTrackingUnknownLocation); + childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->isTracking()); childSetEnabled("copy_slurl", (mSLURL.size() > 0) ); setMouseOpaque(TRUE); @@ -465,6 +476,18 @@ void LLFloaterWorldMap::draw() mCurZoomVal = lerp(mCurZoomVal, (F32)childGetValue("zoom slider").asReal(), interp); F32 map_scale = 256.f*pow(2.f, mCurZoomVal); LLWorldMapView::setScale( map_scale ); + + // Enable/disable checkboxes depending on the zoom level + // If above threshold level (i.e. low res) -> Disable all checkboxes + // If under threshold level (i.e. high res) -> Enable all checkboxes + bool enable = LLWorldMapView::showRegionInfo(); + childSetEnabled("people_chk", enable); + childSetEnabled("infohub_chk", enable); + childSetEnabled("telehub_chk", enable); + childSetEnabled("land_for_sale_chk", enable); + childSetEnabled("event_chk", enable); + childSetEnabled("event_mature_chk", enable); + childSetEnabled("event_adult_chk", enable); LLFloater::draw(); } @@ -553,14 +576,14 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id ) void LLFloaterWorldMap::trackEvent(const LLItemInfo &event_info) { mTrackedStatus = LLTracker::TRACKING_LOCATION; - LLTracker::trackLocation(event_info.mPosGlobal, event_info.mName, event_info.mToolTip, LLTracker::LOCATION_EVENT); + LLTracker::trackLocation(event_info.getGlobalPosition(), event_info.getName(), event_info.getToolTip(), LLTracker::LOCATION_EVENT); setDefaultBtn("Teleport"); } void LLFloaterWorldMap::trackGenericItem(const LLItemInfo &item) { mTrackedStatus = LLTracker::TRACKING_LOCATION; - LLTracker::trackLocation(item.mPosGlobal, item.mName, item.mToolTip, LLTracker::LOCATION_ITEM); + LLTracker::trackLocation(item.getGlobalPosition(), item.getName(), item.getToolTip(), LLTracker::LOCATION_ITEM); setDefaultBtn("Teleport"); } @@ -569,29 +592,27 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); if (!sim_info) { - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE; - LLWorldMap::getInstance()->mInvalidLocation = FALSE; - LLWorldMap::getInstance()->mUnknownLocation = pos_global; + // We haven't found a region for that point yet, leave the tracking to the world map + LLWorldMap::getInstance()->setTracking(pos_global); LLTracker::stopTracking(NULL); S32 world_x = S32(pos_global.mdV[0] / 256); S32 world_y = S32(pos_global.mdV[1] / 256); - LLWorldMap::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true); + LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true); setDefaultBtn(""); return; } - if (sim_info->mAccess == SIM_ACCESS_DOWN) + if (sim_info->isDown()) { - // Down sim. Show the blue circle of death! - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE; - LLWorldMap::getInstance()->mUnknownLocation = pos_global; - LLWorldMap::getInstance()->mInvalidLocation = TRUE; + // Down region. Show the blue circle of death! + // i.e. let the world map that this and tell it it's invalid + LLWorldMap::getInstance()->setTracking(pos_global); + LLWorldMap::getInstance()->setTrackingInvalid(); LLTracker::stopTracking(NULL); setDefaultBtn(""); return; } - std::string sim_name; - LLWorldMap::getInstance()->simNameFromPosGlobal( pos_global, sim_name ); + std::string sim_name = sim_info->getName(); F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS ); F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS ); std::string full_name = llformat("%s (%d, %d, %d)", @@ -603,9 +624,7 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) std::string tooltip(""); mTrackedStatus = LLTracker::TRACKING_LOCATION; LLTracker::trackLocation(pos_global, full_name, tooltip); - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; - LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE; - LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; + LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking setDefaultBtn("Teleport"); } @@ -718,9 +737,9 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3 // pass sim name to combo box gFloaterWorldMap->mCompletingRegionName = region_name; - LLWorldMap::getInstance()->sendNamedRegionRequest(region_name); + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name); LLStringUtil::toLower(gFloaterWorldMap->mCompletingRegionName); - LLWorldMap::getInstance()->mIsTrackingCommit = TRUE; + LLWorldMap::getInstance()->setTrackingCommit(); } } @@ -787,19 +806,12 @@ void LLFloaterWorldMap::buildAvatarIDList() // Delete all but the "None" entry S32 list_size = list->getItemCount(); - while (list_size > 1) + if (list_size > 1) { - list->selectNthItem(1); + list->selectItemRange(1, -1); list->operateOnSelection(LLCtrlListInterface::OP_DELETE); - --list_size; } - LLSD default_column; - default_column["name"] = "friend name"; - default_column["label"] = "Friend Name"; - default_column["width"] = 500; - list->addColumn(default_column); - // Get all of the calling cards for avatar that are currently online LLCollectMappableBuddies collector; LLAvatarTracker::instance().applyFunctor(collector); @@ -820,10 +832,7 @@ void LLFloaterWorldMap::buildAvatarIDList() void LLFloaterWorldMap::buildLandmarkIDLists() { LLCtrlListInterface *list = childGetListInterface("landmark combo"); - if (!list) - { - return; - } + if (!list) return; // Delete all but the "None" entry S32 list_size = list->getItemCount(); @@ -864,7 +873,6 @@ void LLFloaterWorldMap::buildLandmarkIDLists() mLandmarkAssetIDList.put( item->getAssetUUID() ); mLandmarkItemIDList.put( item->getUUID() ); } - list->sortByColumn(std::string("landmark name"), TRUE); list->selectFirstItem(); } @@ -901,7 +909,7 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) { childSetValue("spin z", 0); } - LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; + LLWorldMap::getInstance()->cancelTracking(); mCompletingRegionName = ""; } @@ -937,18 +945,16 @@ void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui) // can see the whole world, plus a little. void LLFloaterWorldMap::adjustZoomSliderBounds() { - // World size in regions - S32 world_width_regions = LLWorldMap::getInstance()->getWorldWidth() / REGION_WIDTH_UNITS; - S32 world_height_regions = LLWorldMap::getInstance()->getWorldHeight() / REGION_WIDTH_UNITS; - - // Pad the world size a little bit, so we have a nice border on - // the edge - world_width_regions++; - world_height_regions++; + // Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed + // width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across + // sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit. + // Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window. + S32 world_width_regions = MAX_VISIBLE_REGIONS; + S32 world_height_regions = MAX_VISIBLE_REGIONS; // Find how much space we have to display the world LLWorldMapView* map_panel; - map_panel = (LLWorldMapView*)mTabs->getCurrentPanel(); + map_panel = (LLWorldMapView*)mPanel; LLRect view_rect = map_panel->getRect(); // View size in pixels @@ -1161,15 +1167,15 @@ void LLFloaterWorldMap::onLocationCommit() LLStringUtil::toLower(str); mCompletingRegionName = str; - LLWorldMap::getInstance()->mIsTrackingCommit = TRUE; + LLWorldMap::getInstance()->setTrackingCommit(); if (str.length() >= 3) { - LLWorldMap::getInstance()->sendNamedRegionRequest(str); + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str); } else { str += "#"; - LLWorldMap::getInstance()->sendNamedRegionRequest(str); + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str); } } @@ -1177,8 +1183,8 @@ void LLFloaterWorldMap::onClearBtn() { mTrackedStatus = LLTracker::TRACKING_NOTHING; LLTracker::stopTracking((void *)(intptr_t)TRUE); - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; - mSLURL = ""; // Clear the SLURL since it's invalid + LLWorldMap::getInstance()->cancelTracking(); + mSLURL = ""; // Clear the SLURL since it's invalid mSetToUserPosition = TRUE; // Revert back to the current user position } @@ -1230,9 +1236,9 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate) pos_global = LLTracker::getTrackedPositionGlobal() - gAgent.getCameraPositionGlobal(); } } - else if(LLWorldMap::getInstance()->mIsTrackingUnknownLocation) + else if(LLWorldMap::getInstance()->isTracking()) { - pos_global = LLWorldMap::getInstance()->mUnknownLocation - gAgent.getCameraPositionGlobal();; + pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgent.getCameraPositionGlobal();; } else { @@ -1240,8 +1246,8 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate) pos_global.clearVec(); } - LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sPixelsPerMeter)), - -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sPixelsPerMeter)), + LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), + -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), !animate); mWaitingForTracker = FALSE; } @@ -1399,13 +1405,6 @@ void LLFloaterWorldMap::flyToAvatar() } } -void LLFloaterWorldMap::onCommitBackground() -{ - // Find my index - S32 index = mTabs->getCurrentPanelIndex(); - LLWorldMap::getInstance()->setCurrentLayer(index); -} - void LLFloaterWorldMap::updateSims(bool found_null_sim) { if (mCompletingRegionName == "") @@ -1422,24 +1421,23 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) S32 num_results = 0; std::map<U64, LLSimInfo*>::const_iterator it; - for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) + for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) { - LLSimInfo* info = (*it).second; - std::string sim_name = info->mName; - std::string sim_name_lower = sim_name; + LLSimInfo* info = it->second; + std::string sim_name_lower = info->getName(); LLStringUtil::toLower(sim_name_lower); if (sim_name_lower.substr(0, name_length) == mCompletingRegionName) { if (sim_name_lower == mCompletingRegionName) { - match = sim_name; + match = info->getName(); } LLSD value; - value["id"] = sim_name; + value["id"] = info->getName(); value["columns"][0]["column"] = "sim_name"; - value["columns"][0]["value"] = sim_name; + value["columns"][0]["value"] = info->getName(); list->addElement(value); num_results++; } @@ -1496,15 +1494,13 @@ void LLFloaterWorldMap::onCommitSearchResult() LLStringUtil::toLower(sim_name); std::map<U64, LLSimInfo*>::const_iterator it; - for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) + for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) { - LLSimInfo* info = (*it).second; - std::string info_sim_name = info->mName; - LLStringUtil::toLower(info_sim_name); + LLSimInfo* info = it->second; - if (sim_name == info_sim_name) + if (info->isName(sim_name)) { - LLVector3d pos_global = from_region_handle( info->mHandle ); + LLVector3d pos_global = info->getGlobalOrigin(); F64 local_x = childGetValue("spin x"); F64 local_y = childGetValue("spin y"); F64 local_z = childGetValue("spin z"); diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 20a8e6d321..7feebb583d 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -96,7 +96,7 @@ public: static const LLUUID& getHomeID() { return sHomeID; } // A z_attenuation of 0.0f collapses the distance into the X-Y plane - F32 getDistanceToDestination(const LLVector3d& pos_global, F32 z_attenuation = 0.5f) const; + F32 getDistanceToDestination(const LLVector3d& pos_global, F32 z_attenuation = 0.5f) const; void clearLocationSelection(BOOL clear_ui = FALSE); void clearAvatarSelection(BOOL clear_ui = FALSE); @@ -121,8 +121,6 @@ protected: void onAvatarComboPrearrange(); void onAvatarComboCommit(); - void onCommitBackground(); - void onComboTextEntry( ); void onSearchTextEntry( LLLineEditor* ctrl ); @@ -155,10 +153,10 @@ protected: void cacheLandmarkPosition(); -protected: - LLTabContainer* mTabs; +private: + LLPanel* mPanel; // Panel displaying the map - // Sets gMapScale, in pixels per region + // Ties to LLWorldMapView::sMapScale, in pixels per region F32 mCurZoomVal; LLFrameTimer mZoomTimer; diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index de18e74752..7863c373c6 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -38,6 +38,7 @@ #include "llinventorybridge.h" #include "llinventoryclipboard.h" // *TODO: remove this once hack below gone. #include "llinventoryfilter.h" +#include "llinventoryfunctions.h" #include "llfoldertype.h" #include "llfloaterinventory.h"// hacked in for the bonus context menu items. #include "llkeyboard.h" @@ -54,6 +55,7 @@ #include "llviewermenu.h" #include "lluictrlfactory.h" #include "llviewercontrol.h" +#include "llviewerfoldertype.h" #include "llviewerwindow.h" #include "llvoavatar.h" #include "llfloaterproperties.h" @@ -1107,7 +1109,7 @@ void LLFolderView::propertiesSelectedItems( void ) } } -void LLFolderView::changeType(LLInventoryModel *model, LLAssetType::EType new_folder_type) +void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type) { LLFolderBridge *folder_bridge = LLFolderBridge::sSelf; @@ -1957,7 +1959,7 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) if (action.length() > change_folder_string.length() && (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) { - LLAssetType::EType new_folder_type = LLFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); + LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); changeType(model, new_folder_type); return true; } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index ebfb4efde2..0bd65b5f90 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -192,7 +192,7 @@ public: void propertiesSelectedItems( void ); // change the folder type - void changeType(LLInventoryModel *model, LLAssetType::EType new_folder_type); + void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type); void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index ff38da279a..60ece75cea 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -32,6 +32,7 @@ #define LLFOLDERVIEWEVENTLISTENER_H #include "lldarray.h" // JAMESDEBUG convert to std::vector +#include "llfoldertype.h" #include "llfontgl.h" // just for StyleFlags enum #include "llpointer.h" @@ -57,7 +58,7 @@ public: virtual const LLUUID& getUUID() const = 0; virtual time_t getCreationDate() const = 0; // UTC seconds virtual PermissionMask getPermissionMask() const = 0; - virtual LLAssetType::EType getPreferredType() const = 0; + virtual LLFolderType::EType getPreferredType() const = 0; virtual LLPointer<LLUIImage> getIcon() const = 0; virtual LLFontGL::StyleFlags getLabelStyle() const = 0; virtual std::string getLabelSuffix() const = 0; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index f83a426cda..6fdaefd21a 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -248,13 +248,13 @@ void LLFolderViewItem::refreshFromListener() if(mListener) { mLabel = mListener->getDisplayName(); - LLAssetType::EType preferred_type = mListener->getPreferredType(); + LLFolderType::EType preferred_type = mListener->getPreferredType(); // *TODO: to be removed when database supports multi language. This is a // temporary attempt to display the inventory folder in the user locale. // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID // it uses the same way to find localized string - if (LLAssetType::lookupIsProtectedCategoryType(preferred_type)) + if (LLFolderType::lookupIsProtectedType(preferred_type)) { LLTrans::findString(mLabel, "InvFolder " + mLabel); }; @@ -1753,7 +1753,7 @@ bool LLFolderViewFolder::isTrash() const { if (mAmTrash == LLFolderViewFolder::UNKNOWN) { - mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH; + mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH; } return mAmTrash == LLFolderViewFolder::TRASH; } @@ -2167,7 +2167,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) { const LLUUID &cat_uuid = getListener()->getUUID(); const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); - if (cat && cat->getPreferredType() == LLAssetType::AT_OUTFIT) + if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) { getListener()->performAction(NULL, NULL,"replaceoutfit"); return TRUE; @@ -2490,7 +2490,7 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde && b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) { - static LLUUID favorites_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID(); LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID(); diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 724b18ded2..c956657825 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -171,14 +171,14 @@ const LLUUID LLFriendCardsManager::extractAvatarID(const LLUUID& avatarID) // and this method must be called before any actions with friend list void LLFriendCardsManager::ensureFriendFoldersExist() { - LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); LLUUID friendFolderUUID = findFriendFolderUUIDImpl(); if (friendFolderUUID.isNull()) { friendFolderUUID = gInventory.createNewCategory(callingCardsFolderID, - LLAssetType::AT_CALLINGCARD, get_friend_folder_name()); + LLFolderType::FT_CALLINGCARD, get_friend_folder_name()); } LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl(); @@ -186,7 +186,7 @@ void LLFriendCardsManager::ensureFriendFoldersExist() if (friendAllSubfolderUUID.isNull()) { friendAllSubfolderUUID = gInventory.createNewCategory(friendFolderUUID, - LLAssetType::AT_CALLINGCARD, get_friend_all_subfolder_name()); + LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name()); } } @@ -411,7 +411,7 @@ void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBud /************************************************************************/ const LLUUID& LLFriendCardsManager::findFriendFolderUUIDImpl() const { - LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); std::string friendFolderName = get_friend_folder_name(); diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index c46eedbef2..e60bde9fd8 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -43,6 +43,7 @@ #include "llimview.h" // for gIMMgr #include "llsidetray.h" #include "llstatusbar.h" // can_afford_transaction() +#include "llimfloater.h" // // Globals @@ -279,10 +280,14 @@ void LLGroupActions::startChat(const LLUUID& group_id) LLGroupData group_data; if (gAgent.getGroupData(group_id, group_data)) { - gIMMgr->addSession( + LLUUID session_id = gIMMgr->addSession( group_data.mName, IM_SESSION_GROUP_START, group_id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } make_ui_sound("UISndStartIM"); } else diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 2e2b2d5101..010ed23918 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -183,6 +183,11 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL item->childSetVisible("info_btn", false); item->setGroupIconVisible(mShowIcons); + if (id.isNull()) + { + item->childSetVisible("profile_btn", false); + } + addItem(item, id, pos); // setCommentVisible(false); diff --git a/indra/newview/llhudview.cpp b/indra/newview/llhudview.cpp index 027cd2ab07..261d9f1df7 100644 --- a/indra/newview/llhudview.cpp +++ b/indra/newview/llhudview.cpp @@ -71,20 +71,6 @@ void LLHUDView::draw() LLView::draw(); } - -// public -const LLColor4& LLHUDView::colorFromType(S32 type) -{ - switch (type) - { - case 0: - return LLColor4::green; - default: - return LLColor4::black; - } -} - - /*virtual*/ BOOL LLHUDView::handleMouseDown(S32 x, S32 y, MASK mask) { diff --git a/indra/newview/llhudview.h b/indra/newview/llhudview.h index 05ff9c8596..0946e2c5c8 100644 --- a/indra/newview/llhudview.h +++ b/indra/newview/llhudview.h @@ -47,8 +47,6 @@ public: virtual void draw(); - const LLColor4& colorFromType(S32 type); - protected: /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); }; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 85863ed85b..a634a1b0fd 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -115,7 +115,7 @@ void LLIMFloater::onClose(bool app_quitting) /* static */ void LLIMFloater::newIMCallback(const LLSD& data){ - if (data["num_unread"].asInteger() > 0) + if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull()) { LLUUID session_id = data["session_id"].asUUID(); @@ -235,7 +235,7 @@ BOOL LLIMFloater::postBuild() std::string session_name(LLIMModel::instance().getName(mSessionID)); - mInputEditor->setLabel(mInputEditor->getLabel() + " " + session_name); + mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + session_name); LLStringUtil::toUpper(session_name); setTitle(session_name); @@ -498,7 +498,8 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* // Allow enabling the LLIMFloater input editor only if session can accept text LLIMModel::LLIMSession* im_session = LLIMModel::instance().findIMSession(self->mSessionID); - if( im_session && im_session->mTextIMPossible ) + //TODO: While disabled lllineeditor can receive focus we need to check if it is enabled (EK) + if( im_session && im_session->mTextIMPossible && !self->mInputEditor->getEnabled()) { //in disconnected state IM input editor should be disabled self->mInputEditor->setEnabled(!gDisconnected); @@ -588,6 +589,32 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) } } +void LLIMFloater::processAgentListUpdates(const LLSD& body) +{ + if ( !body.isMap() ) return; + + if ( body.has("agent_updates") && body["agent_updates"].isMap() ) + { + LLSD agent_data = body["agent_updates"].get(gAgentID.asString()); + if (agent_data.isMap() && agent_data.has("info")) + { + LLSD agent_info = agent_data["info"]; + + if (agent_info.has("mutes")) + { + BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); + mInputEditor->setEnabled(!moderator_muted_text); + std::string label; + if (moderator_muted_text) + label = LLTrans::getString("IM_muted_text_label"); + else + label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID); + mInputEditor->setLabel(label); + } + } + } +} + void LLIMFloater::processSessionUpdate(const LLSD& session_update) { // *TODO : verify following code when moderated mode will be implemented diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index f5edb3188a..065441b188 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -90,6 +90,7 @@ public: void onVisibilityChange(const LLSD& new_visibility); void processIMTyping(const LLIMInfo* im_info, BOOL typing); + void processAgentListUpdates(const LLSD& body); void processSessionUpdate(const LLSD& session_update); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index c4beb666ea..0b8b5935f8 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -70,6 +70,7 @@ #include "llpanelimcontrolpanel.h" #include "llrecentpeople.h" #include "llresmgr.h" +#include "lltooldraganddrop.h" #include "lltrans.h" #include "lltabcontainer.h" #include "llviewertexteditor.h" @@ -320,6 +321,9 @@ void LLFloaterIMPanel::draw() // hide/show start call and end call buttons LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID); + if (!voice_channel) + return; + childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED); childSetEnabled("start_call_btn", enable_connect); @@ -769,10 +773,13 @@ void LLFloaterIMPanel::onVisibilityChange(const LLSD& new_visibility) } LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID); - if (new_visibility.asBoolean() && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) - LLFloaterReg::showInstance("voice_call", mSessionUUID); - else - LLFloaterReg::hideInstance("voice_call", mSessionUUID); + if (voice_channel && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) + { + if (new_visibility.asBoolean()) + LLFloaterReg::showInstance("voice_call", mSessionUUID); + else + LLFloaterReg::hideInstance("voice_call", mSessionUUID); + } } void LLFloaterIMPanel::sendMsg() diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 66a3e3e85c..fdf119fbee 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -134,7 +134,6 @@ void LLIMModel::setActiveSessionID(const LLUUID& session_id) LLIMModel::LLIMModel() { addNewMsgCallback(LLIMFloater::newIMCallback); - addNoUnreadMsgsCallback(LLIMFloater::newIMCallback); addNewMsgCallback(toast_callback); } @@ -440,7 +439,8 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co addToHistory(session_id, from, from_id, utf8_text); if (log2file) logToFile(session_id, from, from_id, utf8_text); - session->mNumUnread++; + //we do not count system messages + if (from_id.notNull()) session->mNumUnread++; // notify listeners LLSD arg; @@ -1192,10 +1192,14 @@ void LLIncomingCallDialog::processCallResponse(S32 response) } else { - gIMMgr->addSession( + LLUUID session_id = gIMMgr->addSession( mPayload["session_name"].asString(), type, session_id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } std::string url = gAgent.getRegion()->getCapability( "ChatSessionRequest"); @@ -1279,10 +1283,14 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) } else { - gIMMgr->addSession( + LLUUID session_id = gIMMgr->addSession( payload["session_name"].asString(), type, session_id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } std::string url = gAgent.getRegion()->getCapability( "ChatSessionRequest"); @@ -1350,13 +1358,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) LLIMMgr::LLIMMgr() : mIMReceived(FALSE) { - static bool registered_dialog = false; - if (!registered_dialog) - { - LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>); - registered_dialog = true; - } - mPendingInvitations = LLSD::emptyMap(); mPendingAgentListUpdates = LLSD::emptyMap(); } @@ -1555,6 +1556,10 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name, const std::string& caller_uri) { LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); if (speaker_mgr) @@ -1604,7 +1609,6 @@ LLUUID LLIMMgr::addSession( LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids); } - LLIMFloater::show(session_id); //*TODO remove this "floater" thing when Communicate Floater's gone LLFloaterIMPanel* floater = findFloaterBySession(session_id); @@ -1849,6 +1853,29 @@ void LLIMMgr::clearPendingInvitation(const LLUUID& session_id) } } +void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body) +{ + LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + if ( im_floater ) + { + im_floater->processAgentListUpdates(body); + } + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); + if (speaker_mgr) + { + speaker_mgr->updateSpeakers(body); + } + else + { + //we don't have a speaker manager yet..something went wrong + //we are probably receiving an update here before + //a start or an acceptance of an invitation. Race condition. + gIMMgr->addPendingAgentListUpdates( + session_id, + body); + } +} + LLSD LLIMMgr::getPendingAgentListUpdates(const LLUUID& session_id) { if ( mPendingAgentListUpdates.has(session_id.asString()) ) @@ -2233,20 +2260,7 @@ public: const LLSD& input) const { const LLUUID& session_id = input["body"]["session_id"].asUUID(); - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - if (speaker_mgr) - { - speaker_mgr->updateSpeakers(input["body"]); - } - else - { - //we don't have a speaker manager yet..something went wrong - //we are probably receiving an update here before - //a start or an acceptance of an invitation. Race condition. - gIMMgr->addPendingAgentListUpdates( - input["body"]["session_id"].asUUID(), - input["body"]); - } + gIMMgr->processAgentListUpdates(session_id, input["body"]); } }; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index f986d9dcdb..bd55bd2c30 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -66,7 +66,10 @@ public: EInstantMessage mType; LLUUID mOtherParticipantID; std::vector<LLUUID> mInitialTargetIDs; + + //does NOT include system messages S32 mNumUnread; + std::list<LLSD> mMsgs; LLVoiceChannel* mVoiceChannel; @@ -315,6 +318,7 @@ public: void clearPendingInvitation(const LLUUID& session_id); + void processAgentListUpdates(const LLUUID& session_id, const LLSD& body); LLSD getPendingAgentListUpdates(const LLUUID& session_id); void addPendingAgentListUpdates( const LLUUID& sessioN_id, diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index bfad2b1624..8dc7833f6a 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -47,6 +47,7 @@ #include "llstartup.h" #include "llviewermenu.h" #include "llvoiceclient.h" +#include "llviewerobjectlist.h" // Linden libraries #include "llfloater.h" @@ -113,6 +114,7 @@ private: void onClickFindOnMap(); bool onVisibleFindOnMap(); bool onVisibleFreezeEject(); + bool onVisibleZoomIn(); void onClickMuteVolume(); void onVolumeChange(const LLSD& data); @@ -188,7 +190,8 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd) { mCommitCallbackRegistrar.add("InspectAvatar.ViewProfile", boost::bind(&LLInspectAvatar::onClickViewProfile, this)); mCommitCallbackRegistrar.add("InspectAvatar.AddFriend", boost::bind(&LLInspectAvatar::onClickAddFriend, this)); - mCommitCallbackRegistrar.add("InspectAvatar.IM", boost::bind(&LLInspectAvatar::onClickIM, this)); + mCommitCallbackRegistrar.add("InspectAvatar.IM", + boost::bind(&LLInspectAvatar::onClickIM, this)); mCommitCallbackRegistrar.add("InspectAvatar.Teleport", boost::bind(&LLInspectAvatar::onClickTeleport, this)); mCommitCallbackRegistrar.add("InspectAvatar.InviteToGroup", boost::bind(&LLInspectAvatar::onClickInviteToGroup, this)); mCommitCallbackRegistrar.add("InspectAvatar.Pay", boost::bind(&LLInspectAvatar::onClickPay, this)); @@ -203,6 +206,8 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd) mVisibleCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap", boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this)); mVisibleCallbackRegistrar.add("InspectAvatar.VisibleFreezeEject", boost::bind(&LLInspectAvatar::onVisibleFreezeEject, this)); + mVisibleCallbackRegistrar.add("InspectAvatar.VisibleZoomIn", + boost::bind(&LLInspectAvatar::onVisibleZoomIn, this)); // can't make the properties request until the widgets are constructed // as it might return immediately, so do it in postBuild. @@ -306,7 +311,21 @@ void LLInspectAvatar::requestUpdate() // You can't re-add someone as a friend if they are already your friend bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL; bool is_self = (mAvatarID == gAgentID); - childSetEnabled("add_friend_btn", !is_friend && !is_self); + if (is_self) + { + getChild<LLUICtrl>("add_friend_btn")->setVisible(false); + getChild<LLUICtrl>("im_btn")->setVisible(false); + } + else if (is_friend) + { + getChild<LLUICtrl>("add_friend_btn")->setVisible(false); + getChild<LLUICtrl>("im_btn")->setVisible(true); + } + else + { + getChild<LLUICtrl>("add_friend_btn")->setVisible(true); + getChild<LLUICtrl>("im_btn")->setVisible(false); + } // Use an avatar_icon even though the image id will come down with the // avatar properties because the avatar_icon code maintains a cache of icons @@ -464,6 +483,11 @@ bool LLInspectAvatar::onVisibleFreezeEject() return enable_freeze_eject( LLSD(mAvatarID) ); } +bool LLInspectAvatar::onVisibleZoomIn() +{ + return gObjectList.findObject(mAvatarID); +} + void LLInspectAvatar::onClickIM() { LLAvatarActions::startIM(mAvatarID); diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp index 050a61c79b..e3780f93ff 100644 --- a/indra/newview/llinspectobject.cpp +++ b/indra/newview/llinspectobject.cpp @@ -112,6 +112,7 @@ private: LLUUID mObjectID; S32 mObjectFace; viewer_media_t mMediaImpl; + LLMediaEntry* mMediaEntry; LLSafeHandle<LLObjectSelection> mObjectSelection; }; @@ -120,7 +121,8 @@ LLInspectObject::LLInspectObject(const LLSD& sd) mObjectID(NULL), // set in onOpen() mObjectFace(0), mObjectSelection(NULL), - mMediaImpl(NULL) + mMediaImpl(NULL), + mMediaEntry(NULL) { // can't make the properties request until the widgets are constructed // as it might return immediately, so do it in postBuild. @@ -231,11 +233,11 @@ void LLInspectObject::onOpen(const LLSD& data) if (!tep) return; - const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; - if(!mep) + mMediaEntry = tep->hasMedia() ? tep->getMediaData() : NULL; + if(!mMediaEntry) return; - mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mMediaEntry->getMediaID()); } } @@ -282,11 +284,11 @@ void LLInspectObject::update() if (!tep) return; - const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; - if(!mep) + mMediaEntry = tep->hasMedia() ? tep->getMediaData() : NULL; + if(!mMediaEntry) return; - mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mMediaEntry->getMediaID()); updateMediaCurrentURL(); updateSecureBrowsing(); @@ -430,14 +432,17 @@ void LLInspectObject::updateDescription(LLSelectNode* nodep) void LLInspectObject::updateMediaCurrentURL() { + if(!mMediaEntry) + return; LLTextBox* textbox = getChild<LLTextBox>("object_media_url"); std::string media_url = ""; textbox->setValue(media_url); textbox->setToolTip(media_url); + LLStringUtil::format_map_t args; if(mMediaImpl.notNull() && mMediaImpl->hasMedia()) { - LLStringUtil::format_map_t args; + LLPluginClassMedia* media_plugin = NULL; media_plugin = mMediaImpl->getMediaPlugin(); if(media_plugin) @@ -451,15 +456,17 @@ void LLInspectObject::updateMediaCurrentURL() args["[CurrentURL]"] = media_plugin->getLocation(); } media_url = LLTrans::getString("CurrentURL", args); - textbox->setText(media_url); - textbox->setToolTip(media_url); + } } - else + else if(mMediaEntry->getCurrentURL() != "") { - textbox->setText(media_url); - textbox->setToolTip(media_url); + args["[CurrentURL]"] = mMediaEntry->getCurrentURL(); + media_url = LLTrans::getString("CurrentURL", args); } + + textbox->setText(media_url); + textbox->setToolTip(media_url); } void LLInspectObject::updateCreator(LLSelectNode* nodep) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 59f70ea1bd..90e48d22ec 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1,5139 +1,5204 @@ -/** - * @file llinventorybridge.cpp - * @brief Implementation of the Inventory-Folder-View-Bridge classes. - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include <utility> // for std::pair<> - -#include "llfloaterinventory.h" -#include "llinventorybridge.h" - -#include "message.h" - -#include "llagent.h" -#include "llagentwearables.h" -#include "llcallingcard.h" -#include "llcheckboxctrl.h" // for radio buttons -#include "llfloaterreg.h" -#include "llradiogroup.h" -#include "llspinctrl.h" -#include "lltextbox.h" -#include "llui.h" - -#include "llviewercontrol.h" -#include "llfirstuse.h" -#include "llfoldertype.h" -#include "llfloaterchat.h" -#include "llfloatercustomize.h" -#include "llfloaterproperties.h" -#include "llfloaterworldmap.h" -#include "llfocusmgr.h" -#include "llfolderview.h" -#include "llfriendcard.h" -#include "llavataractions.h" -#include "llgesturemgr.h" -#include "lliconctrl.h" -#include "llinventorymodel.h" -#include "llinventoryclipboard.h" -#include "lllineeditor.h" -#include "llmenugl.h" -#include "llpreviewanim.h" -#include "llpreviewgesture.h" -#include "llpreviewnotecard.h" -#include "llpreviewscript.h" -#include "llpreviewsound.h" -#include "llpreviewtexture.h" -#include "llresmgr.h" -#include "llscrollcontainer.h" -#include "llimview.h" -#include "lltooldraganddrop.h" -#include "llviewertexturelist.h" -#include "llviewerinventory.h" -#include "llviewerobjectlist.h" -#include "llviewerwindow.h" -#include "llvoavatar.h" -#include "llwearable.h" -#include "llwearablelist.h" -#include "llviewermessage.h" -#include "llviewerregion.h" -#include "llvoavatarself.h" -#include "lltabcontainer.h" -#include "lluictrlfactory.h" -#include "llselectmgr.h" -#include "llsidetray.h" -#include "llfloateropenobject.h" -#include "lltrans.h" -#include "llappearancemgr.h" - -using namespace LLOldEvents; - -// Helpers -// bug in busy count inc/dec right now, logic is complex... do we really need it? -void inc_busy_count() -{ -// gViewerWindow->getWindow()->incBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} -void dec_busy_count() -{ -// gViewerWindow->getWindow()->decBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} - -// Function declarations -void wear_add_inventory_item_on_avatar(LLInventoryItem* item); -void remove_inventory_category_from_avatar(LLInventoryCategory* category); -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id); -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); -bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response); - -std::string ICON_NAME[ICON_NAME_COUNT] = -{ - "Inv_Texture", - "Inv_Sound", - "Inv_CallingCard", - "Inv_CallingCard", - "Inv_Landmark", - "Inv_Landmark", - "Inv_Script", - "Inv_Clothing", - "Inv_Object", - "Inv_Object", - "Inv_Notecard", - "Inv_Skin", - "Inv_Snapshot", - - "Inv_BodyShape", - "Inv_Skin", - "Inv_Hair", - "Inv_Eye", - "Inv_Shirt", - "Inv_Pants", - "Inv_Shoe", - "Inv_Socks", - "Inv_Jacket", - "Inv_Gloves", - "Inv_Undershirt", - "Inv_Underpants", - "Inv_Skirt", - "Inv_Alpha", - "Inv_Tattoo", - - "Inv_Animation", - "Inv_Gesture", - - "inv_item_linkitem.tga", - "inv_item_linkfolder.tga" -}; - - -// +=================================================+ -// | LLInventoryPanelObserver | -// +=================================================+ -void LLInventoryPanelObserver::changed(U32 mask) -{ - mIP->modelChanged(mask); -} - - -// +=================================================+ -// | LLInvFVBridge | -// +=================================================+ - -LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) : -mUUID(uuid), mInvType(LLInventoryType::IT_NONE) -{ - mInventoryPanel = inventory->getHandle(); -} - -const std::string& LLInvFVBridge::getName() const -{ - LLInventoryObject* obj = getInventoryObject(); - if(obj) - { - return obj->getName(); - } - return LLStringUtil::null; -} - -const std::string& LLInvFVBridge::getDisplayName() const -{ - return getName(); -} - -// Folders have full perms -PermissionMask LLInvFVBridge::getPermissionMask() const -{ - - return PERM_ALL; -} - -// virtual -LLAssetType::EType LLInvFVBridge::getPreferredType() const -{ - return LLAssetType::AT_NONE; -} - - -// Folders don't have creation dates. -time_t LLInvFVBridge::getCreationDate() const -{ - return 0; -} - -// Can be destoryed (or moved to trash) -BOOL LLInvFVBridge::isItemRemovable() -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) - { - return TRUE; - } - return FALSE; -} - -// Sends an update to all link items that point to the base item. -void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name) -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - if (itemp->getIsLinkType()) - { - return; - } - - LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id); - for (LLInventoryModel::item_array_t::iterator iter = item_array.begin(); - iter != item_array.end(); - iter++) - { - LLViewerInventoryItem *linked_item = (*iter); - if (linked_item->getUUID() == item_id) continue; - - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item); - new_item->rename(new_name); - new_item->updateServer(FALSE); - model->updateItem(new_item); - // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID()); - } - model->notifyObservers(); -} - -// Can be moved to another folder -BOOL LLInvFVBridge::isItemMovable() const -{ - return TRUE; -} - -/*virtual*/ -/** - * @brief Adds this item into clipboard storage - */ -void LLInvFVBridge::cutToClipboard() -{ - if(isItemMovable()) - { - LLInventoryClipboard::instance().cut(mUUID); - } -} -// *TODO: make sure this does the right thing -void LLInvFVBridge::showProperties() -{ - LLFloaterReg::showInstance("properties", mUUID); -} - -void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) -{ - // Deactivate gestures when moving them into Trash - LLInvFVBridge* bridge; - LLInventoryModel* model = getInventoryModel(); - LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - S32 count = batch.count(); - S32 i,j; - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); - if (item) - { - if(LLAssetType::AT_GESTURE == item->getType()) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } - } - } - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); - if (cat) - { - gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE ); - for (j=0; j<descendent_items.count(); j++) - { - if(LLAssetType::AT_GESTURE == descendent_items[j]->getType()) - { - LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID()); - } - } - } - } - removeBatchNoCheck(batch); -} - -void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch) -{ - // this method moves a bunch of items and folders to the trash. As - // per design guidelines for the inventory model, the message is - // built and the accounting is performed first. After all of that, - // we call LLInventoryModel::moveObject() to move everything - // around. - LLInvFVBridge* bridge; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLMessageSystem* msg = gMessageSystem; - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - std::vector<LLUUID> move_ids; - LLInventoryModel::update_map_t update; - bool start_new_message = true; - S32 count = batch.count(); - S32 i; - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); - if(item) - { - if(item->getParentUUID() == trash_id) continue; - move_ids.push_back(item->getUUID()); - LLPreview::hide(item->getUUID()); - --update[item->getParentUUID()]; - ++update[trash_id]; - 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, TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); - msg->addUUIDFast(_PREHASH_FolderID, trash_id); - msg->addString("NewName", NULL); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - } - } - if(!start_new_message) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); - if(cat) - { - if(cat->getParentUUID() == trash_id) continue; - move_ids.push_back(cat->getUUID()); - --update[cat->getParentUUID()]; - ++update[trash_id]; - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(_PREHASH_MoveInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOL("Stamp", TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID()); - msg->addUUIDFast(_PREHASH_ParentID, trash_id); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - } - } - if(!start_new_message) - { - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - } - - // move everything. - std::vector<LLUUID>::iterator it = move_ids.begin(); - std::vector<LLUUID>::iterator end = move_ids.end(); - for(; it != end; ++it) - { - gInventory.moveObject((*it), trash_id); - } - - // notify inventory observers. - model->notifyObservers(); -} - -BOOL LLInvFVBridge::isClipboardPasteable() const -{ - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) - { - return FALSE; - } - LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - const LLUUID &agent_id = gAgent.getID(); - - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLUUID &item_id = objects.get(i); - - // Can't paste folders - const LLInventoryCategory *cat = model->getCategory(item_id); - if (cat) - { - return FALSE; - } - - const LLInventoryItem *item = model->getItem(item_id); - if (item) - { - if (!item->getPermissions().allowCopyBy(agent_id)) - { - return FALSE; - } - } - } - return TRUE; -} - -BOOL LLInvFVBridge::isClipboardPasteableAsLink() const -{ - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) - { - return FALSE; - } - const LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLInventoryItem *item = model->getItem(objects.get(i)); - if (item) - { - if (!LLAssetType::lookupCanLink(item->getActualType())) - { - return FALSE; - } - } - const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); - if (cat && !LLAssetType::lookupCanLink(cat->getPreferredType())) - { - return FALSE; - } - } - return TRUE; -} - -void hideContextEntries(LLMenuGL& menu, - const std::vector<std::string> &entries_to_show, - const std::vector<std::string> &disabled_entries) -{ - const LLView::child_list_t *list = menu.getChildList(); - - LLView::child_list_t::const_iterator itor; - for (itor = list->begin(); itor != list->end(); ++itor) - { - std::string name = (*itor)->getName(); - - // descend into split menus: - LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor); - if ((name == "More") && branchp) - { - hideContextEntries(*branchp->getBranch(), entries_to_show, disabled_entries); - } - - - bool found = false; - std::vector<std::string>::const_iterator itor2; - for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) - { - if (*itor2 == name) - { - found = true; - } - } - if (!found) - { - (*itor)->setVisible(FALSE); - } - else - { - for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) - { - if (*itor2 == name) - { - (*itor)->setEnabled(FALSE); - } - } - } - } -} - -// Helper for commonly-used entries -void LLInvFVBridge::getClipboardEntries(bool show_asset_id, - std::vector<std::string> &items, - std::vector<std::string> &disabled_items, U32 flags) -{ - items.push_back(std::string("Rename")); - if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Rename")); - } - - if (show_asset_id) - { - items.push_back(std::string("Copy Asset UUID")); - if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) - || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Copy Asset UUID")); - } - } - - items.push_back(std::string("Copy Separator")); - - items.push_back(std::string("Copy")); - if (!isItemCopyable()) - { - disabled_items.push_back(std::string("Copy")); - } - - items.push_back(std::string("Paste")); - if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Paste")); - } - - items.push_back(std::string("Paste As Link")); - if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Paste As Link")); - } - items.push_back(std::string("Paste Separator")); - - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } -} - -void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) - { - items.push_back(std::string("PurgeItem")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("PurgeItem")); - } - items.push_back(std::string("RestoreItem")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - hideContextEntries(menu, items, disabled_items); -} - -// *TODO: remove this -BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const -{ - BOOL rv = FALSE; - - const LLInventoryObject* obj = getInventoryObject(); - - if(obj) - { - *type = LLAssetType::lookupDragAndDropType(obj->getActualType()); - if(*type == DAD_NONE) - { - return FALSE; - } - - *id = obj->getUUID(); - //object_ids.put(obj->getUUID()); - - if (*type == DAD_CATEGORY) - { - gInventory.startBackgroundFetch(obj->getUUID()); - } - - rv = TRUE; - } - - return rv; -} - -LLInventoryObject* LLInvFVBridge::getInventoryObject() const -{ - LLInventoryObject* obj = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - obj = (LLInventoryObject*)model->getObject(mUUID); - } - return obj; -} - -LLInventoryModel* LLInvFVBridge::getInventoryModel() const -{ - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - return panel ? panel->getModel() : NULL; -} - -BOOL LLInvFVBridge::isInTrash() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - return model->isObjectDescendentOf(mUUID, trash_id); -} - -BOOL LLInvFVBridge::isLinkedObjectInTrash() const -{ - if (isInTrash()) return TRUE; - - const LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id); - } - return FALSE; -} - -BOOL LLInvFVBridge::isAgentInventory() const -{ - const LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - if(gInventory.getRootFolderID() == mUUID) return TRUE; - return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); -} - -BOOL LLInvFVBridge::isCOFFolder() const -{ - const LLInventoryModel* model = getInventoryModel(); - if(!model) return TRUE; - const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); - if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id)) - { - return TRUE; - } - return FALSE; -} - -BOOL LLInvFVBridge::isItemPermissive() const -{ - return FALSE; -} - -// static -void LLInvFVBridge::changeItemParent(LLInventoryModel* model, - LLViewerInventoryItem* item, - const LLUUID& new_parent, - BOOL restamp) -{ - if(item->getParentUUID() != new_parent) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - new_item->setParent(new_parent); - new_item->updateParentOnServer(restamp); - model->updateItem(new_item); - model->notifyObservers(); - } -} - -// static -void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, - LLViewerInventoryCategory* cat, - const LLUUID& new_parent, - BOOL restamp) -{ - if(cat->getParentUUID() != new_parent) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); - new_cat->setParent(new_parent); - new_cat->updateParentOnServer(restamp); - model->updateCategory(new_cat); - model->notifyObservers(); - } -} - - -const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type) -{ - const std::string rv= LLInventoryType::lookup(inv_type); - if(rv.empty()) - { - return std::string("<invalid>"); - } - return rv; -} - -LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - const LLUUID& uuid, - U32 flags) -{ - LLInvFVBridge* new_listener = NULL; - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLTextureBridge(inventory, uuid, inv_type); - break; - - case LLAssetType::AT_SOUND: - if(!(inv_type == LLInventoryType::IT_SOUND)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLSoundBridge(inventory, uuid); - break; - - case LLAssetType::AT_LANDMARK: - if(!(inv_type == LLInventoryType::IT_LANDMARK)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLLandmarkBridge(inventory, uuid, flags); - break; - - case LLAssetType::AT_CALLINGCARD: - if(!(inv_type == LLInventoryType::IT_CALLINGCARD)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLCallingCardBridge(inventory, uuid); - break; - - case LLAssetType::AT_SCRIPT: - if(!(inv_type == LLInventoryType::IT_LSL)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLScriptBridge(inventory, uuid); - break; - - case LLAssetType::AT_OBJECT: - if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags); - break; - - case LLAssetType::AT_NOTECARD: - if(!(inv_type == LLInventoryType::IT_NOTECARD)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLNotecardBridge(inventory, uuid); - break; - - case LLAssetType::AT_ANIMATION: - if(!(inv_type == LLInventoryType::IT_ANIMATION)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLAnimationBridge(inventory, uuid); - break; - - case LLAssetType::AT_GESTURE: - if(!(inv_type == LLInventoryType::IT_GESTURE)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLGestureBridge(inventory, uuid); - break; - - case LLAssetType::AT_LSL_TEXT: - if(!(inv_type == LLInventoryType::IT_LSL)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLLSLTextBridge(inventory, uuid); - break; - - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - if(!(inv_type == LLInventoryType::IT_WEARABLE)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags); - break; - case LLAssetType::AT_CATEGORY: - case LLAssetType::AT_ROOT_CATEGORY: - if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) - { - // Create a link folder handler instead. - new_listener = new LLLinkFolderBridge(inventory, uuid); - break; - } - new_listener = new LLFolderBridge(inventory, uuid); - break; - case LLAssetType::AT_LINK: - // Only should happen for broken links. - new_listener = new LLLinkItemBridge(inventory, uuid); - break; - case LLAssetType::AT_LINK_FOLDER: - // Only should happen for broken links. - new_listener = new LLLinkItemBridge(inventory, uuid); - break; - default: - llinfos << "Unhandled asset type (llassetstorage.h): " - << (S32)asset_type << llendl; - break; - } - - if (new_listener) - { - new_listener->mInvType = inv_type; - } - - return new_listener; -} - -void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) -{ - LLInventoryCategory* cat = model->getCategory(uuid); - if (cat) - { - model->purgeDescendentsOf(uuid); - model->notifyObservers(); - } - LLInventoryObject* obj = model->getObject(uuid); - if (obj) - { - model->purgeObject(uuid); - model->notifyObservers(); - } -} - -// +=================================================+ -// | InventoryFVBridgeBuilder | -// +=================================================+ -LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - const LLUUID& uuid, - U32 flags /* = 0x00 */) const -{ - return LLInvFVBridge::createBridge(asset_type, - actual_asset_type, - inv_type, - inventory, - uuid, - flags); -} - -// +=================================================+ -// | LLItemBridge | -// +=================================================+ - -void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("goto" == action) - { - gotoItem(folder); - } - if ("open" == action) - { - openItem(); - return; - } - else if ("properties" == action) - { - showProperties(); - return; - } - else if ("purge" == action) - { - purgeItem(model, mUUID); - return; - } - else if ("restoreToWorld" == action) - { - restoreToWorld(); - return; - } - else if ("restore" == action) - { - restoreItem(); - return; - } - else if ("copy_uuid" == action) - { - // Single item only - LLInventoryItem* item = model->getItem(mUUID); - if(!item) return; - LLUUID asset_id = item->getAssetUUID(); - std::string buffer; - asset_id.toString(buffer); - - gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); - return; - } - else if ("copy" == action) - { - copyToClipboard(); - return; - } - else if ("paste" == action) - { - // Single item only - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); - if (!folder_view_itemp) return; - - folder_view_itemp->getListener()->pasteFromClipboard(); - return; - } - else if ("paste_link" == action) - { - // Single item only - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); - if (!folder_view_itemp) return; - - folder_view_itemp->getListener()->pasteLinkFromClipboard(); - return; - } -} - -void LLItemBridge::selectItem() -{ - LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); - if(item && !item->isComplete()) - { - item->fetchFromServer(); - } -} - -void LLItemBridge::restoreItem() -{ - LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); - if(item) - { - LLInventoryModel* model = getInventoryModel(); - const LLUUID new_parent = model->findCategoryUUIDForType(item->getType()); - // do not restamp on restore. - LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE); - } -} - -void LLItemBridge::restoreToWorld() -{ - LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem(); - if (itemp) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("RezRestoreToWorld"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - msg->nextBlockFast(_PREHASH_InventoryData); - itemp->packMessage(msg); - msg->sendReliable(gAgent.getRegion()->getHost()); - } - - //Similar functionality to the drag and drop rez logic - BOOL remove_from_inventory = FALSE; - - //remove local inventory copy, sim will deal with permissions and removing the item - //from the actual inventory if its a no-copy etc - if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) - { - remove_from_inventory = TRUE; - } - - // Check if it's in the trash. (again similar to the normal rez logic) - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); - if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) - { - remove_from_inventory = TRUE; - } - - if(remove_from_inventory) - { - gInventory.deleteObject(itemp->getUUID()); - gInventory.notifyObservers(); - } -} - -void LLItemBridge::gotoItem(LLFolderView *folder) -{ - LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); - if (active_panel) - { - active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); - } - } -} - -LLUIImagePtr LLItemBridge::getIcon() const -{ - return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]); -} - -PermissionMask LLItemBridge::getPermissionMask() const -{ - LLViewerInventoryItem* item = getItem(); - PermissionMask perm_mask = 0; - if(item) - { - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); - - if (copy) perm_mask |= PERM_COPY; - if (mod) perm_mask |= PERM_MODIFY; - if (xfer) perm_mask |= PERM_TRANSFER; - - } - return perm_mask; -} - -const std::string& LLItemBridge::getDisplayName() const -{ - if(mDisplayName.empty()) - { - buildDisplayName(getItem(), mDisplayName); - } - return mDisplayName; -} - -void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) -{ - if(item) - { - name.assign(item->getName()); - } - else - { - name.assign(LLStringUtil::null); - } -} - -LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const -{ - U8 font = LLFontGL::NORMAL; - - if( gAgentWearables.isWearingItem( mUUID ) ) - { - // llinfos << "BOLD" << llendl; - font |= LLFontGL::BOLD; - } - - const LLViewerInventoryItem* item = getItem(); - if (item && item->getIsLinkType()) - { - font |= LLFontGL::ITALIC; - } - return (LLFontGL::StyleFlags)font; -} - -std::string LLItemBridge::getLabelSuffix() const -{ - // String table is loaded before login screen and inventory items are - // loaded after login, so LLTrans should be ready. - static std::string NO_COPY =LLTrans::getString("no_copy"); - static std::string NO_MOD = LLTrans::getString("no_modify"); - static std::string NO_XFER = LLTrans::getString("no_transfer"); - static std::string LINK = LLTrans::getString("link"); - static std::string BROKEN_LINK = LLTrans::getString("broken_link"); - std::string suffix; - LLInventoryItem* item = getItem(); - if(item) - { - // it's a bit confusing to put nocopy/nomod/etc on calling cards. - if(LLAssetType::AT_CALLINGCARD != item->getType() - && item->getPermissions().getOwner() == gAgent.getID()) - { - BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType()); - if (broken_link) return BROKEN_LINK; - - BOOL link = item->getIsLinkType(); - if (link) return LINK; - - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - if (!copy) - { - suffix += NO_COPY; - } - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - if (!mod) - { - suffix += NO_MOD; - } - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); - if (!xfer) - { - suffix += NO_XFER; - } - } - } - return suffix; -} - -time_t LLItemBridge::getCreationDate() const -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - return item->getCreationDate(); - } - return 0; -} - - -BOOL LLItemBridge::isItemRenameable() const -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - // (For now) Don't allow calling card rename since that may confuse users as to - // what the calling card points to. - if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD) - { - return FALSE; - } - return (item->getPermissions().allowModifyBy(gAgent.getID())); - } - return FALSE; -} - -BOOL LLItemBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLPreview::dirty(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryItem* item = getItem(); - if(item && (item->getName() != new_name)) - { - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); - new_item->updateServer(FALSE); - model->updateItem(new_item); - - model->notifyObservers(); - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - - -BOOL LLItemBridge::removeItem() -{ - if(!isItemRemovable()) - { - return FALSE; - } - // move it to the trash - LLPreview::hide(mUUID, TRUE); - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - LLViewerInventoryItem* item = getItem(); - - // if item is not already in trash - if(item && !model->isObjectDescendentOf(mUUID, trash_id)) - { - // move to trash, and restamp - LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); - // delete was successful - return TRUE; - } - else - { - // tried to delete already item in trash (should purge?) - return FALSE; - } -} - -BOOL LLItemBridge::isItemCopyable() const -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - // can't copy worn objects. DEV-15183 - LLVOAvatarSelf *avatarp = gAgent.getAvatarObject(); - if( !avatarp ) - { - return FALSE; - } - - if(avatarp->isWearingAttachment(mUUID)) - { - return FALSE; - } - - // All items can be copied, not all can be pasted. - // The only time an item can't be copied is if it's a link - // return (item->getPermissions().allowCopyBy(gAgent.getID())); - if (item->getIsLinkType()) - { - return FALSE; - } - return TRUE; - } - return FALSE; -} -BOOL LLItemBridge::copyToClipboard() const -{ - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); - return TRUE; - } - return FALSE; -} - -LLViewerInventoryItem* LLItemBridge::getItem() const -{ - LLViewerInventoryItem* item = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - item = (LLViewerInventoryItem*)model->getItem(mUUID); - } - return item; -} - -BOOL LLItemBridge::isItemPermissive() const -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - U32 mask = item->getPermissions().getMaskBase(); - if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - { - return TRUE; - } - } - return FALSE; -} - -// +=================================================+ -// | LLFolderBridge | -// +=================================================+ - -LLFolderBridge* LLFolderBridge::sSelf=NULL; - -// Can be moved to another folder -BOOL LLFolderBridge::isItemMovable() const -{ - LLInventoryObject* obj = getInventoryObject(); - if(obj) - { - return (!LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)obj)->getPreferredType())); - } - return FALSE; -} - -void LLFolderBridge::selectItem() -{ -} - - -// Can be destroyed (or moved to trash) -BOOL LLFolderBridge::isItemRemovable() -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) - { - return FALSE; - } - - if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) - { - return FALSE; - } - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( !avatar ) - { - return FALSE; - } - - LLInventoryCategory* category = model->getCategory(mUUID); - if( !category ) - { - return FALSE; - } - - if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())) - { - return FALSE; - } - - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); - - S32 i; - for( i = 0; i < descendent_categories.count(); i++ ) - { - LLInventoryCategory* category = descendent_categories[i]; - if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())) - { - return FALSE; - } - } - - for( i = 0; i < descendent_items.count(); i++ ) - { - LLInventoryItem* item = descendent_items[i]; - if( (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART) ) - { - if(gAgentWearables.isWearingItem(item->getUUID())) - { - return FALSE; - } - } - else - if( item->getType() == LLAssetType::AT_OBJECT ) - { - if(avatar->isWearingAttachment(item->getUUID())) - { - return FALSE; - } - } - } - - return TRUE; -} - -BOOL LLFolderBridge::isUpToDate() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if( !category ) - { - return FALSE; - } - - return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; -} - -BOOL LLFolderBridge::isItemCopyable() const -{ - return TRUE; -} - -BOOL LLFolderBridge::copyToClipboard() const -{ - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); - return TRUE; - } - return FALSE; -} - -BOOL LLFolderBridge::isClipboardPasteable() const -{ - if ( ! LLInvFVBridge::isClipboardPasteable() ) - return FALSE; - - // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 - if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) ) - { - LLInventoryModel* model = getInventoryModel(); - if ( !model ) - { - return FALSE; - } - - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - const LLViewerInventoryCategory *current_cat = getCategory(); - - // Search for the direct descendent of current Friends subfolder among all pasted items, - // and return false if is found. - for(S32 i = objects.count() - 1; i >= 0; --i) - { - const LLUUID &obj_id = objects.get(i); - if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) - { - return FALSE; - } - } - - } - return TRUE; -} - -BOOL LLFolderBridge::isClipboardPasteableAsLink() const -{ - // Check normal paste-as-link permissions - if (!LLInvFVBridge::isClipboardPasteableAsLink()) - { - return FALSE; - } - - const LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - const LLViewerInventoryCategory *current_cat = getCategory(); - if (current_cat) - { - const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat ); - const LLUUID ¤t_cat_id = current_cat->getUUID(); - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLUUID &obj_id = objects.get(i); - const LLInventoryCategory *cat = model->getCategory(obj_id); - if (cat) - { - const LLUUID &cat_id = cat->getUUID(); - // Don't allow recursive pasting - if ((cat_id == current_cat_id) || - model->isObjectDescendentOf(current_cat_id, cat_id)) - { - return FALSE; - } - } - // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 - if ( is_in_friend_folder ) - { - // If object is direct descendent of current Friends subfolder than return false. - // Note: We can't use 'const LLInventoryCategory *cat', because it may be null - // in case type of obj_id is LLInventoryItem. - if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) - { - return FALSE; - } - } - } - } - return TRUE; - -} - -BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, - BOOL drop) -{ - // This should never happen, but if an inventory item is incorrectly parented, - // the UI will get confused and pass in a NULL. - if(!inv_cat) return FALSE; - - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - - // cannot drag categories into library - if(!isAgentInventory()) - { - return FALSE; - } - - // check to make sure source is agent inventory, and is represented there. - LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) - && (LLToolDragAndDrop::SOURCE_AGENT == source); - - BOOL accept = FALSE; - S32 i; - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - if(is_agent_inventory) - { - const LLUUID& cat_id = inv_cat->getUUID(); - - // Is the destination the trash? - const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - BOOL move_is_into_trash = (mUUID == trash_id) - || model->isObjectDescendentOf(mUUID, trash_id); - BOOL is_movable = (!LLAssetType::lookupIsProtectedCategoryType(inv_cat->getPreferredType())); - LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); - BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT); - if (move_is_into_current_outfit || move_is_into_outfit) - { - // BAP - restrictions? - is_movable = true; - } - - if (mUUID == gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE)) - { - is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604 - } - - if( is_movable ) - { - gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE ); - - for( i = 0; i < descendent_categories.count(); i++ ) - { - LLInventoryCategory* category = descendent_categories[i]; - if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())) - { - // ...can't move "special folders" like Textures - is_movable = FALSE; - break; - } - } - - if( is_movable ) - { - if( move_is_into_trash ) - { - for( i = 0; i < descendent_items.count(); i++ ) - { - LLInventoryItem* item = descendent_items[i]; - if( (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART) ) - { - if( gAgentWearables.isWearingItem( item->getUUID() ) ) - { - is_movable = FALSE; // It's generally movable, but not into the trash! - break; - } - } - else - if( item->getType() == LLAssetType::AT_OBJECT ) - { - if( avatar->isWearingAttachment( item->getUUID() ) ) - { - is_movable = FALSE; // It's generally movable, but not into the trash! - break; - } - } - } - } - } - } - - - accept = is_movable - && (mUUID != cat_id) // Can't move a folder into itself - && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing - && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity - if(accept && drop) - { - // Look for any gestures and deactivate them - if (move_is_into_trash) - { - for (i = 0; i < descendent_items.count(); i++) - { - LLInventoryItem* item = descendent_items[i]; - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(item->getUUID())) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } - } - } - // if target is an outfit or current outfit folder we use link - if (move_is_into_current_outfit || move_is_into_outfit) - { -#if SUPPORT_ENSEMBLES - // BAP - should skip if dup. - if (move_is_into_current_outfit) - { - LLAppearanceManager::wearEnsemble(inv_cat); - } - else - { - LLPointer<LLInventoryCallback> cb = NULL; - link_inventory_item( - gAgent.getID(), - inv_cat->getUUID(), - mUUID, - inv_cat->getName(), - LLAssetType::AT_LINK_FOLDER, - cb); - } -#endif - } - else - { - - // Reparent the folder and restamp children if it's moving - // into trash. - LLInvFVBridge::changeCategoryParent( - model, - (LLViewerInventoryCategory*)inv_cat, - mUUID, - move_is_into_trash); - } - } - } - else if(LLToolDragAndDrop::SOURCE_WORLD == source) - { - // content category has same ID as object itself - LLUUID object_id = inv_cat->getUUID(); - LLUUID category_id = mUUID; - accept = move_inv_category_world_to_agent(object_id, category_id, drop); - } - return accept; -} - -void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) -{ - const char* dialog = NULL; - if (object->flagScripted()) - { - dialog = "MoveInventoryFromScriptedObject"; - } - else - { - dialog = "MoveInventoryFromObject"; - } - LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); -} - -// Move/copy all inventory items from the Contents folder of an in-world -// object to the agent's inventory, inside a given category. -BOOL move_inv_category_world_to_agent(const LLUUID& object_id, - const LLUUID& category_id, - BOOL drop, - void (*callback)(S32, void*), - void* user_data) -{ - // Make sure the object exists. If we allowed dragging from - // anonymous objects, it would be possible to bypass - // permissions. - // content category has same ID as object itself - LLViewerObject* object = gObjectList.findObject(object_id); - if(!object) - { - llinfos << "Object not found for drop." << llendl; - return FALSE; - } - - // this folder is coming from an object, as there is only one folder in an object, the root, - // we need to collect the entire contents and handle them as a group - InventoryObjectList inventory_objects; - object->getInventoryContents(inventory_objects); - - if (inventory_objects.empty()) - { - llinfos << "Object contents not found for drop." << llendl; - return FALSE; - } - - BOOL accept = TRUE; - BOOL is_move = FALSE; - - // coming from a task. Need to figure out if the person can - // move/copy this item. - InventoryObjectList::iterator it = inventory_objects.begin(); - InventoryObjectList::iterator end = inventory_objects.end(); - for ( ; it != end; ++it) - { - // coming from a task. Need to figure out if the person can - // move/copy this item. - LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions()); - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) - && perm.allowTransferTo(gAgent.getID()))) -// || gAgent.isGodlike()) - { - accept = TRUE; - } - else if(object->permYouOwner()) - { - // If the object cannot be copied, but the object the - // inventory is owned by the agent, then the item can be - // moved from the task to agent inventory. - is_move = TRUE; - accept = TRUE; - } - else - { - accept = FALSE; - break; - } - } - - if(drop && accept) - { - it = inventory_objects.begin(); - InventoryObjectList::iterator first_it = inventory_objects.begin(); - LLMoveInv* move_inv = new LLMoveInv; - move_inv->mObjectID = object_id; - move_inv->mCategoryID = category_id; - move_inv->mCallback = callback; - move_inv->mUserData = user_data; - - for ( ; it != end; ++it) - { - two_uuids_t two(category_id, (*it)->getUUID()); - move_inv->mMoveList.push_back(two); - } - - if(is_move) - { - // Callback called from within here. - warn_move_inventory(object, move_inv); - } - else - { - LLNotification::Params params("MoveInventoryFromObject"); - params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); - LLNotifications::instance().forceResponse(params, 0); - } - } - return accept; -} - -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(); // BAP - safe? - 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 - safe? - // BAP remove AT_NONE support after ensembles are fully working? - return (linked_category && - ((linked_category->getPreferredType() == LLAssetType::AT_NONE) || - (LLAssetType::lookupIsEnsembleCategoryType(linked_category->getPreferredType())))); - } -} - - -bool LLFindWearables::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) -{ - if(item) - { - if((item->getType() == LLAssetType::AT_CLOTHING) - || (item->getType() == LLAssetType::AT_BODYPART)) - { - return TRUE; - } - } - return FALSE; -} - - - -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver -{ -public: - LLRightClickInventoryFetchObserver() : - mCopyItems(false) - { }; - LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) : - mCatID(cat_id), - mCopyItems(copy_items) - { }; - virtual void done() - { - // we've downloaded all the items, so repaint the dialog - LLFolderBridge::staticFolderOptionsMenu(); - - gInventory.removeObserver(this); - delete this; - } - - -protected: - LLUUID mCatID; - bool mCopyItems; - -}; - -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver -{ -public: - LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {} - ~LLRightClickInventoryFetchDescendentsObserver() {} - virtual void done(); -protected: - bool mCopyItems; -}; - -void LLRightClickInventoryFetchDescendentsObserver::done() -{ - // Avoid passing a NULL-ref as mCompleteFolders.front() down to - // gInventory.collectDescendents() - if( mCompleteFolders.empty() ) - { - llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - return; - } - - // What we do here is get the complete information on the items in - // the library, and set up an observer that will wait for that to - // happen. - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(mCompleteFolders.front(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH); - S32 count = item_array.count(); -#if 0 // HACK/TODO: Why? - // This early causes a giant menu to get produced, and doesn't seem to be needed. - if(!count) - { - llwarns << "Nothing fetched in category " << mCompleteFolders.front() - << llendl; - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - return; - } -#endif - - LLRightClickInventoryFetchObserver* outfit; - outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems); - LLInventoryFetchObserver::item_ref_t ids; - for(S32 i = 0; i < count; ++i) - { - ids.push_back(item_array.get(i)->getUUID()); - } - - // clean up, and remove this as an observer since the call to the - // outfit could notify observers and throw us into an infinite - // loop. - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - - // increment busy count and either tell the inventory to check & - // call done, or add this object to the inventory for observation. - inc_busy_count(); - - // do the fetch - outfit->fetchItems(ids); - outfit->done(); //Not interested in waiting and this will be right 99% of the time. -//Uncomment the following code for laggy Inventory UI. -/* if(outfit->isEverythingComplete()) - { - // everything is already here - call done. - outfit->done(); - } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(outfit); - }*/ -} - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryWearObserver -// -// Observer for "copy and wear" operation to support knowing -// when the all of the contents have been added to inventory. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryCopyAndWearObserver : public LLInventoryObserver -{ -public: - LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {} - virtual ~LLInventoryCopyAndWearObserver() {} - virtual void changed(U32 mask); - -protected: - LLUUID mCatID; - int mContentsCount; - BOOL mFolderAdded; -}; - - - -void LLInventoryCopyAndWearObserver::changed(U32 mask) -{ - if((mask & (LLInventoryObserver::ADD)) != 0) - { - if (!mFolderAdded) - { - const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); - - std::set<LLUUID>::const_iterator id_it = changed_items.begin(); - std::set<LLUUID>::const_iterator id_end = changed_items.end(); - for (;id_it != id_end; ++id_it) - { - if ((*id_it) == mCatID) - { - mFolderAdded = TRUE; - break; - } - } - } - - if (mFolderAdded) - { - LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); - - if (NULL == category) - { - llwarns << "gInventory.getCategory(" << mCatID - << ") was NULL" << llendl; - } - else - { - if (category->getDescendentCount() == - mContentsCount) - { - gInventory.removeObserver(this); - LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE); - delete this; - } - } - } - - } -} - - - -void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("open" == action) - { - openItem(); - return; - } - else if ("paste" == action) - { - pasteFromClipboard(); - return; - } - else if ("paste_link" == action) - { - pasteLinkFromClipboard(); - return; - } - else if ("properties" == action) - { - showProperties(); - return; - } - else if ("replaceoutfit" == action) - { - modifyOutfit(FALSE); - return; - } -#if SUPPORT_ENSEMBLES - else if ("wearasensemble" == action) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - LLAppearanceManager::wearEnsemble(cat,true); - return; - } -#endif - else if ("addtooutfit" == action) - { - modifyOutfit(TRUE); - return; - } - else if ("copy" == action) - { - copyToClipboard(); - return; - } - else if ("removefromoutfit" == action) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - - remove_inventory_category_from_avatar ( cat ); - return; - } - else if ("purge" == action) - { - purgeItem(model, mUUID); - return; - } - else if ("restore" == action) - { - restoreItem(); - return; - } -} - -void LLFolderBridge::openItem() -{ - lldebugs << "LLFolderBridge::openItem()" << llendl; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - bool fetching_inventory = model->fetchDescendentsOf(mUUID); - // Only change folder type if we have the folder contents. - if (!fetching_inventory) - { - // Disabling this for now, it's causing crash when new items are added to folders - // since folder type may change before new item item has finished processing. - // determineFolderType(); - } -} - -void LLFolderBridge::closeItem() -{ - determineFolderType(); -} - -void LLFolderBridge::determineFolderType() -{ - if (isUpToDate()) - { - LLInventoryModel* model = getInventoryModel(); - LLViewerInventoryCategory* category = model->getCategory(mUUID); - category->determineFolderType(); - } -} - -BOOL LLFolderBridge::isItemRenameable() const -{ - LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory(); - if(cat && !LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()) - && (cat->getOwnerID() == gAgent.getID())) - { - return TRUE; - } - return FALSE; -} - -void LLFolderBridge::restoreItem() -{ - LLViewerInventoryCategory* cat; - cat = (LLViewerInventoryCategory*)getCategory(); - if(cat) - { - LLInventoryModel* model = getInventoryModel(); - LLUUID new_parent = model->findCategoryUUIDForType(cat->getType()); - // do not restamp children on restore - LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE); - } -} - -LLAssetType::EType LLFolderBridge::getPreferredType() const -{ - LLAssetType::EType preferred_type = LLAssetType::AT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - preferred_type = cat->getPreferredType(); - } - - return preferred_type; -} - -// Icons for folders are based on the preferred type -LLUIImagePtr LLFolderBridge::getIcon() const -{ - LLAssetType::EType preferred_type = LLAssetType::AT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - preferred_type = cat->getPreferredType(); - } - return getIcon(preferred_type); -} - -LLUIImagePtr LLFolderBridge::getIcon(LLAssetType::EType preferred_type) -{ - // we only have one folder image now - return LLUI::getUIImage("Inv_FolderClosed"); -} - -BOOL LLFolderBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat && (cat->getName() != new_name)) - { - LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); - new_cat->rename(new_name); - new_cat->updateServer(FALSE); - model->updateCategory(new_cat); - - model->notifyObservers(); - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - -BOOL LLFolderBridge::removeItem() -{ - if(!isItemRemovable()) - { - return FALSE; - } - // move it to the trash - LLPreview::hide(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - - // Look for any gestures and deactivate them - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); - - S32 i; - for (i = 0; i < descendent_items.count(); i++) - { - LLInventoryItem* item = descendent_items[i]; - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(item->getUUID())) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } - } - - // go ahead and do the normal remove if no 'last calling - // cards' are being removed. - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); - } - - return TRUE; -} - -void LLFolderBridge::pasteFromClipboard() -{ - LLInventoryModel* model = getInventoryModel(); - if(model && isClipboardPasteable()) - { - LLInventoryItem* item = NULL; - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - const LLUUID parent_id(mUUID); - for(S32 i = 0; i < count; i++) - { - item = model->getItem(objects.get(i)); - if (item) - { - if(LLInventoryClipboard::instance().isCutMode()) - { - // move_inventory_item() is not enough, - //we have to update inventory locally too - changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE); - } - else - { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - parent_id, - std::string(), - LLPointer<LLInventoryCallback>(NULL)); - } - } - } - } -} - -void LLFolderBridge::pasteLinkFromClipboard() -{ - const LLInventoryModel* model = getInventoryModel(); - if(model) - { - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - LLUUID parent_id(mUUID); - for(S32 i = 0; i < count; i++) - { - const LLUUID &object_id = objects.get(i); -#if SUPPORT_ENSEMBLES - if (LLInventoryCategory *cat = model->getCategory(object_id)) - { - link_inventory_item( - gAgent.getID(), - cat->getUUID(), - parent_id, - cat->getName(), - LLAssetType::AT_LINK_FOLDER, - LLPointer<LLInventoryCallback>(NULL)); - } - else -#endif - if (LLInventoryItem *item = model->getItem(object_id)) - { - link_inventory_item( - gAgent.getID(), - item->getUUID(), - parent_id, - item->getName(), - LLAssetType::AT_LINK, - LLPointer<LLInventoryCallback>(NULL)); - } - } - } -} - -void LLFolderBridge::staticFolderOptionsMenu() -{ - if (!sSelf) return; - sSelf->folderOptionsMenu(); -} - -void LLFolderBridge::folderOptionsMenu() -{ - std::vector<std::string> disabled_items; - - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - - const LLInventoryCategory* category = model->getCategory(mUUID); - LLAssetType::EType type = category->getPreferredType(); - const bool is_default_folder = category && LLAssetType::lookupIsProtectedCategoryType(type); - // BAP change once we're no longer treating regular categories as ensembles. - const bool is_ensemble = category && (type == LLAssetType::AT_NONE || - LLAssetType::lookupIsEnsembleCategoryType(type)); - - // calling card related functionality for folders. - - // Only enable calling-card related options for non-default folders. - if (!is_default_folder) - { - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) - { - mItems.push_back(std::string("Calling Card Separator")); - mItems.push_back(std::string("Conference Chat Folder")); - mItems.push_back(std::string("IM All Contacts In Folder")); - } - } - - // wearables related functionality for folders. - //is_wearable - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - - if (mWearables || - checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) - { - mItems.push_back(std::string("Folder Wearables Separator")); - - // Only enable add/replace outfit for non-default folders. - if (!is_default_folder) - { - mItems.push_back(std::string("Add To Outfit")); - mItems.push_back(std::string("Replace Outfit")); - } - if (is_ensemble) - { - mItems.push_back(std::string("Wear As Ensemble")); - } - mItems.push_back(std::string("Take Off Items")); - } - hideContextEntries(*mMenu, mItems, disabled_items); -} - -BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) -{ - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - model->collectDescendentsIf(mUUID, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_type); - return ((item_array.count() > 0) ? TRUE : FALSE ); -} - -// Flags unused -void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - mItems.clear(); - mDisabledItems.clear(); - - lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; -// std::vector<std::string> disabled_items; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); - - mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point) - mDisabledItems.clear(); //adding code to clear out disabled members from previous - if (lost_and_found_id == mUUID) - { - // This is the lost+found folder. - mItems.push_back(std::string("Empty Lost And Found")); - } - - if(trash_id == mUUID) - { - // This is the trash. - mItems.push_back(std::string("Empty Trash")); - } - else if(model->isObjectDescendentOf(mUUID, trash_id)) - { - // This is a folder in the trash. - mItems.clear(); // clear any items that used to exist - mItems.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - mDisabledItems.push_back(std::string("Purge Item")); - } - - mItems.push_back(std::string("Restore Item")); - } - else if(isAgentInventory()) // do not allow creating in library - { - LLViewerInventoryCategory *cat = getCategory(); - - // BAP removed protected check to re-enable standard ops in untyped folders. - // Not sure what the right thing is to do here. - if (!isCOFFolder() && cat /*&& - LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/) - { - // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. - if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) - mItems.push_back(std::string("New Folder")); - mItems.push_back(std::string("New Script")); - mItems.push_back(std::string("New Note")); - mItems.push_back(std::string("New Gesture")); - mItems.push_back(std::string("New Clothes")); - mItems.push_back(std::string("New Body Parts")); - mItems.push_back(std::string("Change Type")); - - LLViewerInventoryCategory *cat = getCategory(); - if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())) - { - mDisabledItems.push_back(std::string("Change Type")); - } - - getClipboardEntries(false, mItems, mDisabledItems, flags); - } - else - { - // Want some but not all of the items from getClipboardEntries for outfits. - if (cat && cat->getPreferredType()==LLAssetType::AT_OUTFIT) - { - mItems.push_back(std::string("Rename")); - mItems.push_back(std::string("Delete")); - } - } - - //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06 - mCallingCards = mWearables = FALSE; - - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (checkFolderForContentsOfType(model, is_callingcard)) - { - mCallingCards=TRUE; - } - - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - - if (checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) - { - mWearables=TRUE; - } - - mMenu = &menu; - sSelf = this; - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE); - - LLInventoryFetchDescendentsObserver::folder_ref_t folders; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if (category) - { - folders.push_back(category->getUUID()); - } - fetch->fetchDescendents(folders); - inc_busy_count(); - if(fetch->isEverythingComplete()) - { - // everything is already here - call done. - fetch->done(); - } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(fetch); - } - } - else - { - mItems.push_back(std::string("--no options--")); - mDisabledItems.push_back(std::string("--no options--")); - } - hideContextEntries(menu, mItems, mDisabledItems); -} - -BOOL LLFolderBridge::hasChildren() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - LLInventoryModel::EHasChildren has_children; - has_children = gInventory.categoryHasChildren(mUUID); - return has_children != LLInventoryModel::CHILDREN_NO; -} - -BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) -{ - //llinfos << "LLFolderBridge::dragOrDrop()" << llendl; - BOOL accept = FALSE; - switch(cargo_type) - { - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_CALLINGCARD: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_CLOTHING: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: - case DAD_LINK: - accept = dragItemIntoFolder((LLInventoryItem*)cargo_data, - drop); - break; - case DAD_CATEGORY: - if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID)) - { - accept = FALSE; - } - else - { - accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop); - } - break; - default: - break; - } - return accept; -} - -LLViewerInventoryCategory* LLFolderBridge::getCategory() const -{ - LLViewerInventoryCategory* cat = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - cat = (LLViewerInventoryCategory*)model->getCategory(mUUID); - } - return cat; -} - - -// static -void LLFolderBridge::pasteClipboard(void* user_data) -{ - LLFolderBridge* self = (LLFolderBridge*)user_data; - if(self) self->pasteFromClipboard(); -} - -void LLFolderBridge::createNewCategory(void* user_data) -{ - LLFolderBridge* bridge = (LLFolderBridge*)user_data; - if(!bridge) return; - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get()); - if (!panel) return; - LLInventoryModel* model = panel->getModel(); - if(!model) return; - LLUUID id; - id = model->createNewCategory(bridge->getUUID(), - LLAssetType::AT_NONE, - LLStringUtil::null); - model->notifyObservers(); - - // At this point, the bridge has probably been deleted, but the - // view is still there. - panel->setSelection(id, TAKE_FOCUS_YES); -} - -void LLFolderBridge::createNewShirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT); -} - -void LLFolderBridge::createNewPants(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS); -} - -void LLFolderBridge::createNewShoes(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES); -} - -void LLFolderBridge::createNewSocks(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS); -} - -void LLFolderBridge::createNewJacket(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET); -} - -void LLFolderBridge::createNewSkirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT); -} - -void LLFolderBridge::createNewGloves(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES); -} - -void LLFolderBridge::createNewUndershirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT); -} - -void LLFolderBridge::createNewUnderpants(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS); -} - -void LLFolderBridge::createNewShape(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE); -} - -void LLFolderBridge::createNewSkin(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN); -} - -void LLFolderBridge::createNewHair(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR); -} - -void LLFolderBridge::createNewEyes(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES); -} - -// static -void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type) -{ - if(!bridge) return; - LLUUID parent_id = bridge->getUUID(); - createWearable(parent_id, type); -} - -// Separate function so can be called by global menu as well as right-click -// menu. -// static -void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type) -{ - LLWearable* wearable = LLWearableList::instance().createNewWearable(type); - LLAssetType::EType asset_type = wearable->getAssetType(); - LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; - create_inventory_item(gAgent.getID(), gAgent.getSessionID(), - parent_id, wearable->getTransactionID(), wearable->getName(), - wearable->getDescription(), asset_type, inv_type, wearable->getType(), - wearable->getPermissions().getMaskNextOwner(), - LLPointer<LLInventoryCallback>(NULL)); -} - -void LLFolderBridge::modifyOutfit(BOOL append) -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - - // BAP - was: - // wear_inventory_category_on_avatar( cat, append ); - LLAppearanceManager::wearInventoryCategory( cat, FALSE, append ); -} - -// helper stuff -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv) -{ - LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData; - LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID); - S32 option = LLNotification::getSelectedOption(notification, response); - - if(option == 0 && object) - { - if (cat_and_wear && cat_and_wear->mWear) - { - InventoryObjectList inventory_objects; - object->getInventoryContents(inventory_objects); - int contents_count = inventory_objects.size()-1; //subtract one for containing folder - - LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count); - gInventory.addObserver(inventoryObserver); - } - - two_uuids_list_t::iterator move_it; - for (move_it = move_inv->mMoveList.begin(); - move_it != move_inv->mMoveList.end(); - ++move_it) - { - object->moveInventory(move_it->first, move_it->second); - } - - // update the UI. - dialog_refresh_all(); - } - - if (move_inv->mCallback) - { - move_inv->mCallback(option, move_inv->mUserData); - } - - delete move_inv; - return false; -} - -/* -Next functions intended to reorder items in the inventory folder and save order on server -Is now used for Favorites folder. - -*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel -*/ -void saveItemsOrder(LLInventoryModel::item_array_t& items) -{ - int sortField = 0; - - // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - LLViewerInventoryItem* item = *i; - - item->setSortField(++sortField); - item->setComplete(TRUE); - item->updateServer(FALSE); - - gInventory.updateItem(item); - } - - gInventory.notifyObservers(); -} - -LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id) -{ - LLInventoryModel::item_array_t::iterator result = items.end(); - - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - if ((*i)->getUUID() == id) - { - result = i; - break; - } - } - - return result; -} - -void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId) -{ - LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId); - LLViewerInventoryItem* destItem = gInventory.getItem(destItemId); - - items.erase(findItemByUUID(items, srcItem->getUUID())); - items.insert(findItemByUUID(items, destItem->getUUID()), srcItem); -} - -BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, - BOOL drop) -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - - // cannot drag into library - if(!isAgentInventory()) - { - return FALSE; - } - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - - LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - BOOL accept = FALSE; - LLViewerObject* object = NULL; - if(LLToolDragAndDrop::SOURCE_AGENT == source) - { - - BOOL is_movable = TRUE; - switch( inv_item->getActualType() ) - { - case LLAssetType::AT_ROOT_CATEGORY: - is_movable = FALSE; - break; - - case LLAssetType::AT_CATEGORY: - is_movable = !LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)inv_item)->getPreferredType()); - break; - default: - break; - } - - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); - BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT); - - if(is_movable && move_is_into_trash) - { - switch(inv_item->getType()) - { - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID()); - break; - - case LLAssetType::AT_OBJECT: - is_movable = !avatar->isWearingAttachment(inv_item->getUUID()); - break; - default: - break; - } - } - - if ( is_movable ) - { - // Don't allow creating duplicates in the Calling Card/Friends - // subfolders, see bug EXT-1599. Check is item direct descendent - // of target folder and forbid item's movement if it so. - // Note: isItemDirectDescendentOfCategory checks if - // passed category is in the Calling Card/Friends folder - is_movable = ! LLFriendCardsManager::instance() - .isObjDirectDescendentOfCategory (inv_item, getCategory()); - } - - LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE); - - // we can move item inside a folder only if this folder is Favorites. See EXT-719 - accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id)); - if(accept && drop) - { - if (inv_item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) - { - LLGestureManager::instance().deactivateGesture(inv_item->getUUID()); - } - // If an item is being dragged between windows, unselect - // everything in the active window so that we don't follow - // the selection to its new location (which is very - // annoying). - if (LLFloaterInventory::getActiveInventory()) - { - LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - if (active_panel && (panel != active_panel)) - { - active_panel->unSelectAll(); - } - } - - // if dragging from/into favorites folder only reorder items - if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID)) - { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLIsType is_type(LLAssetType::AT_LANDMARK); - model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; - if (itemp) - { - LLUUID srcItemId = inv_item->getUUID(); - LLUUID destItemId = itemp->getListener()->getUUID(); - - // update order - updateItemsOrder(items, srcItemId, destItemId); - - saveItemsOrder(items); - } - } - else if (favorites_id == mUUID) // if target is the favorites folder we use copy - { - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - mUUID, - std::string(), - LLPointer<LLInventoryCallback>(NULL)); - } - else if (move_is_into_current_outfit || move_is_into_outfit) - { - // BAP - should skip if dup. - if (move_is_into_current_outfit) - { - LLAppearanceManager::wearItem(inv_item); - } - else - { - LLPointer<LLInventoryCallback> cb = NULL; - link_inventory_item( - gAgent.getID(), - inv_item->getUUID(), - mUUID, - std::string(), - LLAssetType::AT_LINK, - cb); - } - } - else - { - // restamp if the move is into the trash. - LLInvFVBridge::changeItemParent( - model, - (LLViewerInventoryItem*)inv_item, - mUUID, - move_is_into_trash); - } - } - } - else if(LLToolDragAndDrop::SOURCE_WORLD == source) - { - // Make sure the object exists. If we allowed dragging from - // anonymous objects, it would be possible to bypass - // permissions. - object = gObjectList.findObject(inv_item->getParentUUID()); - if(!object) - { - llinfos << "Object not found for drop." << llendl; - return FALSE; - } - - // coming from a task. Need to figure out if the person can - // move/copy this item. - LLPermissions perm(inv_item->getPermissions()); - BOOL is_move = FALSE; - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) - && perm.allowTransferTo(gAgent.getID()))) -// || gAgent.isGodlike()) - - { - accept = TRUE; - } - else if(object->permYouOwner()) - { - // If the object cannot be copied, but the object the - // inventory is owned by the agent, then the item can be - // moved from the task to agent inventory. - is_move = TRUE; - accept = TRUE; - } - if(drop && accept) - { - LLMoveInv* move_inv = new LLMoveInv; - move_inv->mObjectID = inv_item->getParentUUID(); - two_uuids_t item_pair(mUUID, inv_item->getUUID()); - move_inv->mMoveList.push_back(item_pair); - move_inv->mCallback = NULL; - move_inv->mUserData = NULL; - if(is_move) - { - warn_move_inventory(object, move_inv); - } - else - { - LLNotification::Params params("MoveInventoryFromObject"); - params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); - LLNotifications::instance().forceResponse(params, 0); - } - } - - } - else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) - { - accept = TRUE; - if(drop) - { - copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(), - LLToolDragAndDrop::getInstance()->getSourceID(), inv_item); - } - } - else if(LLToolDragAndDrop::SOURCE_LIBRARY == source) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item; - if(item && item->isComplete()) - { - accept = TRUE; - if(drop) - { - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - mUUID, - std::string(), - LLPointer<LLInventoryCallback>(NULL)); - } - } - } - else - { - llwarns << "unhandled drag source" << llendl; - } - return accept; -} - -// +=================================================+ -// | LLScriptBridge (DEPRECTED) | -// +=================================================+ - -LLUIImagePtr LLScriptBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); -} - -// +=================================================+ -// | LLTextureBridge | -// +=================================================+ - -LLUIImagePtr LLTextureBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE); -} - -void LLTextureBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -} - -// +=================================================+ -// | LLSoundBridge | -// +=================================================+ - -LLUIImagePtr LLSoundBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE); -} - -void LLSoundBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* -// Changed this back to the way it USED to work: -// only open the preview dialog through the contextual right-click menu -// double-click just plays the sound - - LLViewerInventoryItem* item = getItem(); - if(item) - { - openSoundPreview((void*)this); - //send_uuid_sound_trigger(item->getAssetUUID(), 1.0); - } -*/ -} - -void LLSoundBridge::previewItem() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - send_sound_trigger(item->getAssetUUID(), 1.0); - } -} - -void LLSoundBridge::openSoundPreview(void* which) -{ - LLSoundBridge *me = (LLSoundBridge *)which; - LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES); -} - -void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Sound Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Sound Separator")); - items.push_back(std::string("Sound Play")); - - hideContextEntries(menu, items, disabled_items); -} - -// +=================================================+ -// | LLLandmarkBridge | -// +=================================================+ - -LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) : -LLItemBridge(inventory, uuid) -{ - mVisited = FALSE; - if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED) - { - mVisited = TRUE; - } -} - -LLUIImagePtr LLLandmarkBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE); -} - -void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Landmark Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Landmark Separator")); - items.push_back(std::string("About Landmark")); - - // Disable "About Landmark" menu item for - // multiple landmarks selected. Only one landmark - // info panel can be shown at a time. - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("About Landmark")); - } - - hideContextEntries(menu, items, disabled_items); -} - -// Convenience function for the two functions below. -void teleport_via_landmark(const LLUUID& asset_id) -{ - gAgent.teleportViaLandmark( asset_id ); - - // we now automatically track the landmark you're teleporting to - // because you'll probably arrive at a telehub instead - LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); - if( floater_world_map ) - { - floater_world_map->trackLandmark( asset_id ); - } -} - -// virtual -void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("teleport" == action) - { - LLViewerInventoryItem* item = getItem(); - if(item) - { - teleport_via_landmark(item->getAssetUUID()); - } - } - else if ("about" == action) - { - LLViewerInventoryItem* item = getItem(); - if(item) - { - LLSD key; - key["type"] = "landmark"; - key["id"] = item->getUUID(); - - LLSideTray::getInstance()->showPanel("panel_places", key); - } - } - else - { - LLItemBridge::performAction(folder, model, action); - } -} - -static bool open_landmark_callback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - - LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); - if (option == 0) - { - teleport_via_landmark(asset_id); - } - - return false; -} -static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback); - - -void LLLandmarkBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if( item ) - { - // Opening (double-clicking) a landmark immediately teleports, - // but warns you the first time. - // open_landmark(item); - LLSD payload; - payload["asset_id"] = item->getAssetUUID(); - LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); - } -*/ -} - - -// +=================================================+ -// | LLCallingCardObserver | -// +=================================================+ -void LLCallingCardObserver::changed(U32 mask) -{ - mBridgep->refreshFolderViewItem(); -} - -// +=================================================+ -// | LLCallingCardBridge | -// +=================================================+ - -LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) : - LLItemBridge(inventory, uuid) -{ - mObserver = new LLCallingCardObserver(this); - LLAvatarTracker::instance().addObserver(mObserver); -} - -LLCallingCardBridge::~LLCallingCardBridge() -{ - LLAvatarTracker::instance().removeObserver(mObserver); - delete mObserver; -} - -void LLCallingCardBridge::refreshFolderViewItem() -{ - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; - if (itemp) - { - itemp->refresh(); - } -} - -// virtual -void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("begin_im" == action) - { - LLViewerInventoryItem *item = getItem(); - if (item && (item->getCreatorUUID() != gAgent.getID()) && - (!item->getCreatorUUID().isNull())) - { - std::string callingcard_name; - gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); - gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); - } - } - else if ("lure" == action) - { - LLViewerInventoryItem *item = getItem(); - if (item && (item->getCreatorUUID() != gAgent.getID()) && - (!item->getCreatorUUID().isNull())) - { - LLAvatarActions::offerTeleport(item->getCreatorUUID()); - } - } - else LLItemBridge::performAction(folder, model, action); -} - -LLUIImagePtr LLCallingCardBridge::getIcon() const -{ - BOOL online = FALSE; - LLViewerInventoryItem* item = getItem(); - if(item) - { - online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()); - } - return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE); -} - -std::string LLCallingCardBridge::getLabelSuffix() const -{ - LLViewerInventoryItem* item = getItem(); - if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) ) - { - return LLItemBridge::getLabelSuffix() + " (online)"; - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -void LLCallingCardBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if(item && !item->getCreatorUUID().isNull()) - { - LLAvatarActions::showProfile(item->getCreatorUUID()); - } -*/ -} - -void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - LLInventoryItem* item = getItem(); - BOOL good_card = (item - && (LLUUID::null != item->getCreatorUUID()) - && (item->getCreatorUUID() != gAgent.getID())); - BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); - items.push_back(std::string("Send Instant Message Separator")); - items.push_back(std::string("Send Instant Message")); - items.push_back(std::string("Offer Teleport...")); - items.push_back(std::string("Conference Chat")); - - if (!good_card) - { - disabled_items.push_back(std::string("Send Instant Message")); - } - if (!good_card || !user_online) - { - disabled_items.push_back(std::string("Offer Teleport...")); - disabled_items.push_back(std::string("Conference Chat")); - } - } - hideContextEntries(menu, items, disabled_items); -} - -BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) -{ - LLViewerInventoryItem* item = getItem(); - BOOL rv = FALSE; - if(item) - { - // check the type - switch(cargo_type) - { - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_CLOTHING: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: - { - LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; - const LLPermissions& perm = inv_item->getPermissions(); - if(gInventory.getItem(inv_item->getUUID()) - && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID())) - { - rv = TRUE; - if(drop) - { - LLToolDragAndDrop::giveInventory(item->getCreatorUUID(), - (LLInventoryItem*)cargo_data); - } - } - else - { - // It's not in the user's inventory (it's probably in - // an object's contents), so disallow dragging it here. - // You can't give something you don't yet have. - rv = FALSE; - } - break; - } - case DAD_CATEGORY: - { - LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data; - if( gInventory.getCategory( inv_cat->getUUID() ) ) - { - rv = TRUE; - if(drop) - { - LLToolDragAndDrop::giveInventoryCategory( - item->getCreatorUUID(), - inv_cat); - } - } - else - { - // It's not in the user's inventory (it's probably in - // an object's contents), so disallow dragging it here. - // You can't give something you don't yet have. - rv = FALSE; - } - break; - } - default: - break; - } - } - return rv; -} - -BOOL LLCallingCardBridge::removeItem() -{ - if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem())) - { - LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID()); - return FALSE; - } - else - { - return LLItemBridge::removeItem(); - } -} -// +=================================================+ -// | LLNotecardBridge | -// +=================================================+ - -LLUIImagePtr LLNotecardBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE); -} - -void LLNotecardBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); - } -*/ -} - - -// +=================================================+ -// | LLGestureBridge | -// +=================================================+ - -LLUIImagePtr LLGestureBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE); -} - -LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const -{ - if( LLGestureManager::instance().isGestureActive(mUUID) ) - { - return LLFontGL::BOLD; - } - else - { - return LLFontGL::NORMAL; - } -} - -std::string LLGestureBridge::getLabelSuffix() const -{ - if( LLGestureManager::instance().isGestureActive(mUUID) ) - { - return LLItemBridge::getLabelSuffix() + " (active)"; - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -// virtual -void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("activate" == action) - { - LLGestureManager::instance().activateGesture(mUUID); - - LLViewerInventoryItem* item = gInventory.getItem(mUUID); - if (!item) return; - - // Since we just changed the suffix to indicate (active) - // the server doesn't need to know, just the viewer. - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - else if ("deactivate" == action) - { - LLGestureManager::instance().deactivateGesture(mUUID); - - LLViewerInventoryItem* item = gInventory.getItem(mUUID); - if (!item) return; - - // Since we just changed the suffix to indicate (active) - // the server doesn't need to know, just the viewer. - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - else LLItemBridge::performAction(folder, model, action); -} - -void LLGestureBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); - preview->setFocus(TRUE); - } -*/ -} - -BOOL LLGestureBridge::removeItem() -{ - // Force close the preview window, if it exists - LLGestureManager::instance().deactivateGesture(mUUID); - return LLItemBridge::removeItem(); -} - -void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLGestureBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Gesture Separator")); - items.push_back(std::string("Activate")); - items.push_back(std::string("Deactivate")); - } - hideContextEntries(menu, items, disabled_items); -} - -// +=================================================+ -// | LLAnimationBridge | -// +=================================================+ - -LLUIImagePtr LLAnimationBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE); -} - -void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Animation Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Animation Separator")); - items.push_back(std::string("Animation Play")); - items.push_back(std::string("Animation Audition")); - - hideContextEntries(menu, items, disabled_items); - -} - -// virtual -void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ((action == "playworld") || (action == "playlocal")) - { - if (getItem()) - { - LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; - if ("playworld" == action) activate = LLPreviewAnim::PLAY; - if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; - - LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID)); - if (preview) - { - preview->activate(activate); - } - } - } - else - { - LLItemBridge::performAction(folder, model, action); - } -} - -void LLAnimationBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); - } -*/ -} - -// +=================================================+ -// | LLObjectBridge | -// +=================================================+ - -// static -LLUUID LLObjectBridge::sContextMenuItemID; - -LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) : -LLItemBridge(inventory, uuid), mInvType(type) -{ - mAttachPt = (flags & 0xff); // low bye of inventory flags - - mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE; -} - -BOOL LLObjectBridge::isItemRemovable() -{ - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - if(avatar->isWearingAttachment(mUUID)) return FALSE; - return LLInvFVBridge::isItemRemovable(); -} - -LLUIImagePtr LLObjectBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject ); -} - -LLInventoryObject* LLObjectBridge::getObject() const -{ - LLInventoryObject* object = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - object = (LLInventoryObject*)model->getObject(mUUID); - } - return object; -} - -// virtual -void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("attach" == action) - { - LLUUID object_id = mUUID; - LLViewerInventoryItem* item; - item = (LLViewerInventoryItem*)gInventory.getItem(object_id); - if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) - { - rez_attachment(item, NULL); - } - else if(item && item->isComplete()) - { - // must be in library. copy it to our inventory and put it on. - LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - gFocusMgr.setKeyboardFocus(NULL); - } - else if ("detach" == action) - { - LLInventoryItem* item = gInventory.getItem(mUUID); - if(item) - { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); - gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); - } - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = - gObjectList.findObject(item->getUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } - else - { - llwarns << "object not found - ignoring" << llendl; - } - } - else LLItemBridge::performAction(folder, model, action); -} - -void LLObjectBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - - /* - LLFloaterReg::showInstance("properties", mUUID); - */ -} - -LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const -{ - U8 font = LLFontGL::NORMAL; - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar && avatar->isWearingAttachment( mUUID ) ) - { - font |= LLFontGL::BOLD; - } - - LLInventoryItem* item = getItem(); - if (item && item->getIsLinkType()) - { - font |= LLFontGL::ITALIC; - } - - return (LLFontGL::StyleFlags)font; -} - -std::string LLObjectBridge::getLabelSuffix() const -{ - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar && avatar->isWearingAttachment( mUUID ) ) - { - std::string attachment_point_name = avatar->getAttachedPointName(mUUID); - LLStringUtil::toLower(attachment_point_name); - - LLStringUtil::format_map_t args; - args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str(); - return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment) -{ - LLSD payload; - payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link. - - S32 attach_pt = 0; - if (gAgent.getAvatarObject() && attachment) - { - for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin(); - iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter) - { - if (iter->second == attachment) - { - attach_pt = iter->first; - break; - } - } - } - - payload["attachment_point"] = attach_pt; - -#if !ENABLE_MULTIATTACHMENTS - if (attachment && attachment->getNumObjects() > 0) - { - LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); - } - else -#endif - { - LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); - } -} - -bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response) -{ - LLVOAvatar *avatarp = gAgent.getAvatarObject(); - - if (!avatarp->canAttachMoreObjects()) - { - LLSD args; - args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); - LLNotifications::instance().add("MaxAttachmentsOnOutfit", args); - return false; - } - - S32 option = LLNotification::getSelectedOption(notification, response); - if (option == 0/*YES*/) - { - LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID()); - - if (itemp) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); - U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); -#if ENABLE_MULTIATTACHMENTS - attachment_pt |= ATTACHMENT_ADD; -#endif - msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); - pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); - msg->addStringFast(_PREHASH_Name, itemp->getName()); - msg->addStringFast(_PREHASH_Description, itemp->getDescription()); - msg->sendReliable(gAgent.getRegion()->getHost()); - } - } - return false; -} -static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez); - -void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - LLInventoryItem* item = getItem(); - if (item && item->getIsLinkType()) - { - items.push_back(std::string("Goto Link")); - } - - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - LLObjectBridge::sContextMenuItemID = mUUID; - - if(item) - { - LLVOAvatarSelf* avatarp = gAgent.getAvatarObject(); - if( !avatarp ) - { - return; - } - - if( avatarp->isWearingAttachment( mUUID ) ) - { - items.push_back(std::string("Detach From Yourself")); - } - else - if( !isInTrash() && !isLinkedObjectInTrash() ) - { - items.push_back(std::string("Attach Separator")); - items.push_back(std::string("Object Wear")); - items.push_back(std::string("Attach To")); - items.push_back(std::string("Attach To HUD")); - // commented out for DEV-32347 - //items.push_back(std::string("Restore to Last Position")); - - if (!avatarp->canAttachMoreObjects()) - { - disabled_items.push_back(std::string("Object Wear")); - disabled_items.push_back(std::string("Attach To")); - disabled_items.push_back(std::string("Attach To HUD")); - } - LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE); - LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE); - LLVOAvatar *avatarp = gAgent.getAvatarObject(); - if (attach_menu - && (attach_menu->getChildCount() == 0) - && attach_hud_menu - && (attach_hud_menu->getChildCount() == 0) - && avatarp) - { - for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); - iter != avatarp->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - LLMenuItemCallGL::Params p; - std::string submenu_name = attachment->getName(); - if (LLTrans::getString(submenu_name) != "") - { - p.name = (" ")+LLTrans::getString(submenu_name)+" "; - } - else - { - p.name = submenu_name; - } - LLSD cbparams; - cbparams["index"] = curiter->first; - cbparams["label"] = attachment->getName(); - p.on_click.function_name = "Inventory.AttachObject"; - p.on_click.parameter = LLSD(attachment->getName()); - p.on_enable.function_name = "Attachment.Label"; - p.on_enable.parameter = cbparams; - LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu; - LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); - } - } - } - } - } - hideContextEntries(menu, items, disabled_items); -} - -BOOL LLObjectBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLPreview::dirty(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryItem* item = getItem(); - if(item && (item->getName() != new_name)) - { - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); - new_item->updateServer(FALSE); - model->updateItem(new_item); - - model->notifyObservers(); - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar ) - { - LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() ); - if( obj ) - { - LLSelectMgr::getInstance()->deselectAll(); - LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); - LLSelectMgr::getInstance()->selectionSetObjectName( new_name ); - LLSelectMgr::getInstance()->deselectAll(); - } - } - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - -// +=================================================+ -// | LLLSLTextBridge | -// +=================================================+ - -LLUIImagePtr LLLSLTextBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); -} - -void LLLSLTextBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - /* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); - } - */ -} - -// +=================================================+ -// | LLWearableBridge | -// +=================================================+ - -// *NOTE: hack to get from avatar inventory to avatar -void wear_inventory_item_on_avatar( LLInventoryItem* item ) -{ - if(item) - { - lldebugs << "wear_inventory_item_on_avatar( " << item->getName() - << " )" << llendl; - - LLAppearanceManager::wearItem(item); - } -} - -void wear_add_inventory_item_on_avatar( LLInventoryItem* item ) -{ - if(item) - { - lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName() - << " )" << llendl; - - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onWearAddOnAvatarArrived, - new LLUUID(item->getUUID())); - } -} - -void remove_inventory_category_from_avatar( LLInventoryCategory* category ) -{ - if(!category) return; - lldebugs << "remove_inventory_category_from_avatar( " << category->getName() - << " )" << llendl; - - - if( gFloaterCustomize ) - { - gFloaterCustomize->askToSaveIfDirty( - boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID())); - } - else - { - remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() ); - } -} - -struct OnRemoveStruct -{ - LLUUID mUUID; - OnRemoveStruct(const LLUUID& uuid): - mUUID(uuid) - { - } -}; - -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id) -{ - - // Find all the wearables that are in the category's subtree. - lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl; - if(proceed) - { - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - LLFindWearables is_wearable; - gInventory.collectDescendentsIf(category_id, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_wearable); - S32 i; - S32 wearable_count = item_array.count(); - - LLInventoryModel::cat_array_t obj_cat_array; - LLInventoryModel::item_array_t obj_item_array; - LLIsType is_object( LLAssetType::AT_OBJECT ); - gInventory.collectDescendentsIf(category_id, - obj_cat_array, - obj_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_object); - S32 obj_count = obj_item_array.count(); - - // Find all gestures in this folder - LLInventoryModel::cat_array_t gest_cat_array; - LLInventoryModel::item_array_t gest_item_array; - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - gInventory.collectDescendentsIf(category_id, - gest_cat_array, - gest_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_gesture); - S32 gest_count = gest_item_array.count(); - - if (wearable_count > 0) //Loop through wearables. If worn, remove. - { - for(i = 0; i < wearable_count; ++i) - { - if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) ) - { - LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(), - item_array.get(i)->getName(), - item_array.get(i)->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(item_array.get(i)->getUUID())); - - } - } - } - - - if (obj_count > 0) - { - for(i = 0; i < obj_count; ++i) - { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() ); - - gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); - - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } - else - { - llwarns << "object not found, ignoring" << llendl; - } - } - } - - if (gest_count > 0) - { - for(i = 0; i < gest_count; ++i) - { - if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) ) - { - LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() ); - gInventory.updateItem( gest_item_array.get(i) ); - gInventory.notifyObservers(); - } - - } - } - } -} - -BOOL LLWearableBridge::renameItem(const std::string& new_name) -{ - if( gAgentWearables.isWearingItem( mUUID ) ) - { - gAgentWearables.setWearableName( mUUID, new_name ); - } - return LLItemBridge::renameItem(new_name); -} - -BOOL LLWearableBridge::isItemRemovable() -{ - if (gAgentWearables.isWearingItem(mUUID)) return FALSE; - return LLInvFVBridge::isItemRemovable(); -} - -std::string LLWearableBridge::getLabelSuffix() const -{ - if( gAgentWearables.isWearingItem( mUUID ) ) - { - return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -LLUIImagePtr LLWearableBridge::getIcon() const -{ - return get_item_icon(mAssetType, mInvType, mWearableType, FALSE); -} - -// virtual -void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("wear" == action) - { - wearOnAvatar(); - } - else if ("wear_add" == action) - { - wearAddOnAvatar(); - } - else if ("edit" == action) - { - editOnAvatar(); - return; - } - else if ("take_off" == action) - { - if(gAgentWearables.isWearingItem(mUUID)) - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(mUUID)); - } - } - } - else LLItemBridge::performAction(folder, model, action); -} - -void LLWearableBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - /* - if( isInTrash() ) - { - LLNotifications::instance().add("CannotWearTrash"); - } - else if(isAgentInventory()) - { - if( !gAgentWearables.isWearingItem( mUUID ) ) - { - wearOnAvatar(); - } - } - else - { - // must be in the inventory library. copy it to our inventory - // and put it on right away. - LLViewerInventoryItem* item = getItem(); - if(item && item->isComplete()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else if(item) - { - // *TODO: We should fetch the item details, and then do - // the operation above. - LLNotifications::instance().add("CannotWearInfoNotComplete"); - } - } - */ -} - -void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLWearableBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere - BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM); - - // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976 - LLViewerInventoryItem* item = getItem(); - if( !no_open && item ) - { - no_open = (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART); - } - if (!no_open) - { - items.push_back(std::string("Open")); - } - - if (item && item->getIsLinkType()) - { - items.push_back(std::string("Goto Link")); - } - - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Wearable Separator")); - - items.push_back(std::string("Wearable Wear")); - items.push_back(std::string("Wearable Add")); - items.push_back(std::string("Wearable Edit")); - - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Wearable Edit")); - } - // Don't allow items to be worn if their baseobj is in the trash. - if (isLinkedObjectInTrash()) - { - disabled_items.push_back(std::string("Wearable Wear")); - disabled_items.push_back(std::string("Wearable Add")); - disabled_items.push_back(std::string("Wearable Edit")); - } - - // Disable wear and take off based on whether the item is worn. - if(item) - { - switch (item->getType()) - { - case LLAssetType::AT_CLOTHING: - items.push_back(std::string("Take Off")); - case LLAssetType::AT_BODYPART: - if (gAgentWearables.isWearingItem(item->getUUID())) - { - disabled_items.push_back(std::string("Wearable Wear")); - disabled_items.push_back(std::string("Wearable Add")); - } - else - { - disabled_items.push_back(std::string("Take Off")); - } - break; - default: - break; - } - } - } - hideContextEntries(menu, items, disabled_items); -} - -// Called from menus -// static -BOOL LLWearableBridge::canWearOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return FALSE; - if(!self->isAgentInventory()) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem(); - if(!item || !item->isComplete()) return FALSE; - } - return (!gAgentWearables.isWearingItem(self->mUUID)); -} - -// Called from menus -// static -void LLWearableBridge::onWearOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return; - self->wearOnAvatar(); -} - -void LLWearableBridge::wearOnAvatar() -{ - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); - return; - } - - LLViewerInventoryItem* item = getItem(); - if(item) - { - if(!isAgentInventory()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - wear_inventory_item_on_avatar(item); - } - } -} - -void LLWearableBridge::wearAddOnAvatar() -{ - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); - return; - } - - LLViewerInventoryItem* item = getItem(); - if(item) - { - if(!isAgentInventory()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - wear_add_inventory_item_on_avatar(item); - } - } -} - -// static -void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata ) -{ - LLUUID* item_id = (LLUUID*) userdata; - if(wearable) - { - LLViewerInventoryItem* item = NULL; - item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); - if(item) - { - if(item->getAssetUUID() == wearable->getAssetID()) - { - gAgentWearables.setWearableItem(item, wearable); - gInventory.notifyObservers(); - //self->getFolderItem()->refreshFromRoot(); - } - else - { - llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; - } - } - } - delete item_id; -} - -// static -// BAP remove the "add" code path once everything is fully COF-ified. -void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ) -{ - LLUUID* item_id = (LLUUID*) userdata; - if(wearable) - { - LLViewerInventoryItem* item = NULL; - item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); - if(item) - { - if(item->getAssetUUID() == wearable->getAssetID()) - { - bool do_append = true; - gAgentWearables.setWearableItem(item, wearable, do_append); - gInventory.notifyObservers(); - //self->getFolderItem()->refreshFromRoot(); - } - else - { - llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; - } - } - } - delete item_id; -} - -// static -BOOL LLWearableBridge::canEditOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return FALSE; - - return (gAgentWearables.isWearingItem(self->mUUID)); -} - -// static -void LLWearableBridge::onEditOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(self) - { - self->editOnAvatar(); - } -} - -void LLWearableBridge::editOnAvatar() -{ - const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID); - if( wearable ) - { - // Set the tab to the right wearable. - if (gFloaterCustomize) - gFloaterCustomize->setCurrentWearableType( wearable->getType() ); - - if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() ) - { - // Start Avatar Customization - gAgent.changeCameraToCustomizeAvatar(); - } - } -} - -// static -BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if( self && (LLAssetType::AT_BODYPART != self->mAssetType) ) - { - return gAgentWearables.isWearingItem( self->mUUID ); - } - return FALSE; -} - -// static -void LLWearableBridge::onRemoveFromAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return; - if(gAgentWearables.isWearingItem(self->mUUID)) - { - LLViewerInventoryItem* item = self->getItem(); - if (item) - { - LLUUID parent_id = item->getParentUUID(); - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - onRemoveFromAvatarArrived, - new OnRemoveStruct(LLUUID(self->mUUID))); - } - } -} - -// static -void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, - void* userdata) -{ - OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; - const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID); - if(wearable) - { - if( gAgentWearables.isWearingItem( item_id ) ) - { - EWearableType type = wearable->getType(); - - if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&& - //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) - { - // MULTI_WEARABLE: FIXME HACK - always remove all - bool do_remove_all = false; - gAgentWearables.removeWearable( type, do_remove_all, 0 ); - } - } - } - - // Find and remove this item from the COF. - LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::getCOF()); - llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF. - for (LLInventoryModel::item_array_t::const_iterator iter = items.begin(); - iter != items.end(); - ++iter) - { - const LLViewerInventoryItem *linked_item = (*iter); - const LLUUID &item_id = linked_item->getUUID(); - gInventory.purgeObject(item_id); - } - gInventory.notifyObservers(); - - delete on_remove_struct; -} - -LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, - const LLUUID& uuid,LLInventoryModel* model) -{ - LLInvFVBridgeAction* action = NULL; - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - action = new LLTextureBridgeAction(uuid,model); - break; - - case LLAssetType::AT_SOUND: - action = new LLSoundBridgeAction(uuid,model); - break; - - case LLAssetType::AT_LANDMARK: - action = new LLLandmarkBridgeAction(uuid,model); - break; - - case LLAssetType::AT_CALLINGCARD: - action = new LLCallingCardBridgeAction(uuid,model); - break; - - case LLAssetType::AT_OBJECT: - action = new LLObjectBridgeAction(uuid,model); - break; - - case LLAssetType::AT_NOTECARD: - action = new LLNotecardBridgeAction(uuid,model); - break; - - case LLAssetType::AT_ANIMATION: - action = new LLAnimationBridgeAction(uuid,model); - break; - - case LLAssetType::AT_GESTURE: - action = new LLGestureBridgeAction(uuid,model); - break; - - case LLAssetType::AT_LSL_TEXT: - action = new LLLSLTextBridgeAction(uuid,model); - break; - - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - action = new LLWearableBridgeAction(uuid,model); - - break; - - default: - break; - } - return action; -} - -//static -void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, - const LLUUID& uuid,LLInventoryModel* model) -{ - LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); - if(action) - { - action->doIt(); - delete action; - } -} - -//static -void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model) -{ - LLAssetType::EType asset_type = model->getItem(uuid)->getType(); - LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); - if(action) - { - action->doIt(); - delete action; - } -} - -LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const -{ - if(mModel) - return (LLViewerInventoryItem*)mModel->getItem(mUUID); - return NULL; -} - -//virtual -void LLTextureBridgeAction::doIt() -{ - if (getItem()) - { - LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void LLSoundBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLLandmarkBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if( item ) - { - // Opening (double-clicking) a landmark immediately teleports, - // but warns you the first time. - LLSD payload; - payload["asset_id"] = item->getAssetUUID(); - LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); - } - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLCallingCardBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if(item && item->getCreatorUUID().notNull()) - { - LLAvatarActions::showProfile(item->getCreatorUUID()); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void -LLNotecardBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void LLGestureBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); - preview->setFocus(TRUE); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void LLAnimationBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLObjectBridgeAction::doIt() -{ - LLFloaterReg::showInstance("properties", mUUID); - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLLSLTextBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - - -BOOL LLWearableBridgeAction::isInTrash() const -{ - if(!mModel) return FALSE; - LLUUID trash_id = mModel->findCategoryUUIDForType(LLAssetType::AT_TRASH); - return mModel->isObjectDescendentOf(mUUID, trash_id); -} - -BOOL LLWearableBridgeAction::isAgentInventory() const -{ - if(!mModel) return FALSE; - if(gInventory.getRootFolderID() == mUUID) return TRUE; - return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); -} - -void LLWearableBridgeAction::wearOnAvatar() -{ - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); - return; - } - - LLViewerInventoryItem* item = getItem(); - if(item) - { - if(!isAgentInventory()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - wear_inventory_item_on_avatar(item); - } - } -} - -//virtual -void LLWearableBridgeAction::doIt() -{ - if(isInTrash()) - { - LLNotifications::instance().add("CannotWearTrash"); - } - else if(isAgentInventory()) - { - if(!gAgentWearables.isWearingItem(mUUID)) - { - wearOnAvatar(); - } - } - else - { - // must be in the inventory library. copy it to our inventory - // and put it on right away. - LLViewerInventoryItem* item = getItem(); - if(item && item->isComplete()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else if(item) - { - // *TODO: We should fetch the item details, and then do - // the operation above. - LLNotifications::instance().add("CannotWearInfoNotComplete"); - } - } - - LLInvFVBridgeAction::doIt(); -} - -// +=================================================+ -// | LLLinkItemBridge | -// +=================================================+ -// For broken links - -std::string LLLinkItemBridge::sPrefix("Link: "); - - -LLUIImagePtr LLLinkItemBridge::getIcon() const -{ - if (LLViewerInventoryItem *item = getItem()) - { - return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE); - } - return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE); -} - -void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - // *TODO: Translate - lldebugs << "LLLink::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } - } - hideContextEntries(menu, items, disabled_items); -} - - -// +=================================================+ -// | LLLinkBridge | -// +=================================================+ -// For broken links. - -std::string LLLinkFolderBridge::sPrefix("Link: "); - - -LLUIImagePtr LLLinkFolderBridge::getIcon() const -{ - LLAssetType::EType preferred_type = LLAssetType::AT_NONE; - if (LLViewerInventoryItem *item = getItem()) - { - if (const LLViewerInventoryCategory* cat = item->getLinkedCategory()) - { - preferred_type = cat->getPreferredType(); - } - } - return LLFolderBridge::getIcon(preferred_type); -} - -void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - // *TODO: Translate - lldebugs << "LLLink::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Goto Link")); - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } - } - hideContextEntries(menu, items, disabled_items); -} - -void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("goto" == action) - { - gotoItem(folder); - return; - } - LLItemBridge::performAction(folder,model,action); -} - -void LLLinkFolderBridge::gotoItem(LLFolderView *folder) -{ - const LLUUID &cat_uuid = getFolderID(); - if (!cat_uuid.isNull()) - { - if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid)) - { - if (LLInventoryModel* model = getInventoryModel()) - { - model->fetchDescendentsOf(cat_uuid); - } - base_folder->setOpen(TRUE); - folder->setSelectionFromRoot(base_folder,TRUE); - folder->scrollToShowSelection(); - } - } -} - -const LLUUID &LLLinkFolderBridge::getFolderID() const -{ - if (LLViewerInventoryItem *link_item = getItem()) - { - if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory()) - { - const LLUUID& cat_uuid = cat->getUUID(); - return cat_uuid; - } - } - return LLUUID::null; -} +/**
+ * @file llinventorybridge.cpp
+ * @brief Implementation of the Inventory-Folder-View-Bridge classes.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include <utility> // for std::pair<>
+
+#include "llfloaterinventory.h"
+#include "llinventorybridge.h"
+
+#include "message.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llcallingcard.h"
+#include "llcheckboxctrl.h" // for radio buttons
+#include "llfloaterreg.h"
+#include "llradiogroup.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+#include "llui.h"
+
+#include "llviewercontrol.h"
+#include "llfirstuse.h"
+#include "llfoldertype.h"
+#include "llfloaterchat.h"
+#include "llfloatercustomize.h"
+#include "llfloaterproperties.h"
+#include "llfloaterworldmap.h"
+#include "llfocusmgr.h"
+#include "llfolderview.h"
+#include "llfriendcard.h"
+#include "llavataractions.h"
+#include "llgesturemgr.h"
+#include "lliconctrl.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llinventorypanel.h"
+#include "llinventoryclipboard.h"
+#include "lllineeditor.h"
+#include "llmenugl.h"
+#include "llpreviewanim.h"
+#include "llpreviewgesture.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewscript.h"
+#include "llpreviewsound.h"
+#include "llpreviewtexture.h"
+#include "llresmgr.h"
+#include "llscrollcontainer.h"
+#include "llimview.h"
+#include "lltooldraganddrop.h"
+#include "llviewerfoldertype.h"
+#include "llviewertexturelist.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+#include "llviewerwindow.h"
+#include "llvoavatar.h"
+#include "llwearable.h"
+#include "llwearablelist.h"
+#include "llviewerassettype.h"
+#include "llviewermessage.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+#include "lltabcontainer.h"
+#include "lluictrlfactory.h"
+#include "llselectmgr.h"
+#include "llsidetray.h"
+#include "llfloateropenobject.h"
+#include "lltrans.h"
+#include "llappearancemgr.h"
+#include "llimfloater.h"
+
+using namespace LLOldEvents;
+
+// Helpers
+// bug in busy count inc/dec right now, logic is complex... do we really need it?
+void inc_busy_count()
+{
+// gViewerWindow->getWindow()->incBusyCount();
+// check balance of these calls if this code is changed to ever actually
+// *do* something!
+}
+void dec_busy_count()
+{
+// gViewerWindow->getWindow()->decBusyCount();
+// check balance of these calls if this code is changed to ever actually
+// *do* something!
+}
+
+// Function declarations
+void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
+void remove_inventory_category_from_avatar(LLInventoryCategory* category);
+void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
+bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
+bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response);
+
+std::string ICON_NAME[ICON_NAME_COUNT] =
+{
+ "Inv_Texture",
+ "Inv_Sound",
+ "Inv_CallingCard",
+ "Inv_CallingCard",
+ "Inv_Landmark",
+ "Inv_Landmark",
+ "Inv_Script",
+ "Inv_Clothing",
+ "Inv_Object",
+ "Inv_Object",
+ "Inv_Notecard",
+ "Inv_Skin",
+ "Inv_Snapshot",
+
+ "Inv_BodyShape",
+ "Inv_Skin",
+ "Inv_Hair",
+ "Inv_Eye",
+ "Inv_Shirt",
+ "Inv_Pants",
+ "Inv_Shoe",
+ "Inv_Socks",
+ "Inv_Jacket",
+ "Inv_Gloves",
+ "Inv_Undershirt",
+ "Inv_Underpants",
+ "Inv_Skirt",
+ "Inv_Alpha",
+ "Inv_Tattoo",
+
+ "Inv_Animation",
+ "Inv_Gesture",
+
+ "inv_item_linkitem.tga",
+ "inv_item_linkfolder.tga"
+};
+
+
+// +=================================================+
+// | LLInventoryPanelObserver |
+// +=================================================+
+void LLInventoryPanelObserver::changed(U32 mask)
+{
+ mIP->modelChanged(mask);
+}
+
+
+// +=================================================+
+// | LLInvFVBridge |
+// +=================================================+
+
+LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
+mUUID(uuid), mInvType(LLInventoryType::IT_NONE)
+{
+ mInventoryPanel = inventory->getHandle();
+}
+
+const std::string& LLInvFVBridge::getName() const
+{
+ LLInventoryObject* obj = getInventoryObject();
+ if(obj)
+ {
+ return obj->getName();
+ }
+ return LLStringUtil::null;
+}
+
+const std::string& LLInvFVBridge::getDisplayName() const
+{
+ return getName();
+}
+
+// Folders have full perms
+PermissionMask LLInvFVBridge::getPermissionMask() const
+{
+
+ return PERM_ALL;
+}
+
+// virtual
+LLFolderType::EType LLInvFVBridge::getPreferredType() const
+{
+ return LLFolderType::FT_NONE;
+}
+
+
+// Folders don't have creation dates.
+time_t LLInvFVBridge::getCreationDate() const
+{
+ return 0;
+}
+
+// Can be destoryed (or moved to trash)
+BOOL LLInvFVBridge::isItemRemovable()
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// Sends an update to all link items that point to the base item.
+void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name)
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ if (itemp->getIsLinkType())
+ {
+ return;
+ }
+
+ LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id);
+ for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
+ iter != item_array.end();
+ iter++)
+ {
+ LLViewerInventoryItem *linked_item = (*iter);
+ if (linked_item->getUUID() == item_id) continue;
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item);
+ new_item->rename(new_name);
+ new_item->updateServer(FALSE);
+ model->updateItem(new_item);
+ // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
+ }
+ model->notifyObservers();
+}
+
+// Can be moved to another folder
+BOOL LLInvFVBridge::isItemMovable() const
+{
+ return TRUE;
+}
+
+/*virtual*/
+/**
+ * @brief Adds this item into clipboard storage
+ */
+void LLInvFVBridge::cutToClipboard()
+{
+ if(isItemMovable())
+ {
+ LLInventoryClipboard::instance().cut(mUUID);
+ }
+}
+// *TODO: make sure this does the right thing
+void LLInvFVBridge::showProperties()
+{
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ LLFloaterReg::showInstance("properties", mUUID);
+}
+
+void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
+{
+ // Deactivate gestures when moving them into Trash
+ LLInvFVBridge* bridge;
+ LLInventoryModel* model = getInventoryModel();
+ LLViewerInventoryItem* item = NULL;
+ LLViewerInventoryCategory* cat = NULL;
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ S32 count = batch.count();
+ S32 i,j;
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
+ if (item)
+ {
+ if(LLAssetType::AT_GESTURE == item->getType())
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+ }
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
+ if (cat)
+ {
+ gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE );
+ for (j=0; j<descendent_items.count(); j++)
+ {
+ if(LLAssetType::AT_GESTURE == descendent_items[j]->getType())
+ {
+ LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID());
+ }
+ }
+ }
+ }
+ removeBatchNoCheck(batch);
+}
+
+void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch)
+{
+ // this method moves a bunch of items and folders to the trash. As
+ // per design guidelines for the inventory model, the message is
+ // built and the accounting is performed first. After all of that,
+ // we call LLInventoryModel::moveObject() to move everything
+ // around.
+ LLInvFVBridge* bridge;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLMessageSystem* msg = gMessageSystem;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLViewerInventoryItem* item = NULL;
+ LLViewerInventoryCategory* cat = NULL;
+ std::vector<LLUUID> move_ids;
+ LLInventoryModel::update_map_t update;
+ bool start_new_message = true;
+ S32 count = batch.count();
+ S32 i;
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
+ if(item)
+ {
+ if(item->getParentUUID() == trash_id) continue;
+ move_ids.push_back(item->getUUID());
+ LLPreview::hide(item->getUUID());
+ --update[item->getParentUUID()];
+ ++update[trash_id];
+ 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, TRUE);
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_ItemID, item->getUUID());
+ msg->addUUIDFast(_PREHASH_FolderID, trash_id);
+ msg->addString("NewName", NULL);
+ if(msg->isSendFullFast(_PREHASH_InventoryData))
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ update.clear();
+ }
+ }
+ }
+ if(!start_new_message)
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ update.clear();
+ }
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
+ if(cat)
+ {
+ if(cat->getParentUUID() == trash_id) continue;
+ move_ids.push_back(cat->getUUID());
+ --update[cat->getParentUUID()];
+ ++update[trash_id];
+ if(start_new_message)
+ {
+ start_new_message = false;
+ msg->newMessageFast(_PREHASH_MoveInventoryFolder);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addBOOL("Stamp", TRUE);
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID());
+ msg->addUUIDFast(_PREHASH_ParentID, trash_id);
+ if(msg->isSendFullFast(_PREHASH_InventoryData))
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ update.clear();
+ }
+ }
+ }
+ if(!start_new_message)
+ {
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ }
+
+ // move everything.
+ std::vector<LLUUID>::iterator it = move_ids.begin();
+ std::vector<LLUUID>::iterator end = move_ids.end();
+ for(; it != end; ++it)
+ {
+ gInventory.moveObject((*it), trash_id);
+ }
+
+ // notify inventory observers.
+ model->notifyObservers();
+}
+
+BOOL LLInvFVBridge::isClipboardPasteable() const
+{
+ if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ {
+ return FALSE;
+ }
+ LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ const LLUUID &agent_id = gAgent.getID();
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &item_id = objects.get(i);
+
+ // Can't paste folders
+ const LLInventoryCategory *cat = model->getCategory(item_id);
+ if (cat)
+ {
+ return FALSE;
+ }
+
+ const LLInventoryItem *item = model->getItem(item_id);
+ if (item)
+ {
+ if (!item->getPermissions().allowCopyBy(agent_id))
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
+{
+ if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ {
+ return FALSE;
+ }
+ const LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLInventoryItem *item = model->getItem(objects.get(i));
+ if (item)
+ {
+ if (!LLAssetType::lookupCanLink(item->getActualType()))
+ {
+ return FALSE;
+ }
+ }
+ const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
+ if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void hide_context_entries(LLMenuGL& menu,
+ const std::vector<std::string> &entries_to_show,
+ const std::vector<std::string> &disabled_entries)
+{
+ const LLView::child_list_t *list = menu.getChildList();
+
+ LLView::child_list_t::const_iterator itor;
+ for (itor = list->begin(); itor != list->end(); ++itor)
+ {
+ std::string name = (*itor)->getName();
+
+ // descend into split menus:
+ LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor);
+ if ((name == "More") && branchp)
+ {
+ hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
+ }
+
+
+ bool found = false;
+ std::vector<std::string>::const_iterator itor2;
+ for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
+ {
+ if (*itor2 == name)
+ {
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ (*itor)->setVisible(FALSE);
+ }
+ else
+ {
+ for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
+ {
+ if (*itor2 == name)
+ {
+ (*itor)->setEnabled(FALSE);
+ }
+ }
+ }
+ }
+}
+
+// Helper for commonly-used entries
+void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
+ std::vector<std::string> &items,
+ std::vector<std::string> &disabled_items, U32 flags)
+{
+ items.push_back(std::string("Rename"));
+ if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Rename"));
+ }
+
+ if (show_asset_id)
+ {
+ items.push_back(std::string("Copy Asset UUID"));
+ if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
+ || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Copy Asset UUID"));
+ }
+ }
+
+ items.push_back(std::string("Copy Separator"));
+
+ items.push_back(std::string("Copy"));
+ if (!isItemCopyable())
+ {
+ disabled_items.push_back(std::string("Copy"));
+ }
+
+ items.push_back(std::string("Paste"));
+ if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Paste"));
+ }
+
+ items.push_back(std::string("Paste As Link"));
+ if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Paste As Link"));
+ }
+ items.push_back(std::string("Paste Separator"));
+
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+
+ // If multiple items are selected, disable properties (if it exists).
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Properties"));
+ }
+}
+
+void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("PurgeItem"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("PurgeItem"));
+ }
+ items.push_back(std::string("RestoreItem"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// *TODO: remove this
+BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
+{
+ BOOL rv = FALSE;
+
+ const LLInventoryObject* obj = getInventoryObject();
+
+ if(obj)
+ {
+ *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
+ if(*type == DAD_NONE)
+ {
+ return FALSE;
+ }
+
+ *id = obj->getUUID();
+ //object_ids.put(obj->getUUID());
+
+ if (*type == DAD_CATEGORY)
+ {
+ gInventory.startBackgroundFetch(obj->getUUID());
+ }
+
+ rv = TRUE;
+ }
+
+ return rv;
+}
+
+LLInventoryObject* LLInvFVBridge::getInventoryObject() const
+{
+ LLInventoryObject* obj = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ obj = (LLInventoryObject*)model->getObject(mUUID);
+ }
+ return obj;
+}
+
+LLInventoryModel* LLInvFVBridge::getInventoryModel() const
+{
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ return panel ? panel->getModel() : NULL;
+}
+
+BOOL LLInvFVBridge::isInTrash() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return model->isObjectDescendentOf(mUUID, trash_id);
+}
+
+BOOL LLInvFVBridge::isLinkedObjectInTrash() const
+{
+ if (isInTrash()) return TRUE;
+
+ const LLInventoryObject *obj = getInventoryObject();
+ if (obj && obj->getIsLinkType())
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
+ }
+ return FALSE;
+}
+
+BOOL LLInvFVBridge::isAgentInventory() const
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ if(gInventory.getRootFolderID() == mUUID) return TRUE;
+ return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
+}
+
+BOOL LLInvFVBridge::isCOFFolder() const
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model) return TRUE;
+ const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLInvFVBridge::isItemPermissive() const
+{
+ return FALSE;
+}
+
+// static
+void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
+ LLViewerInventoryItem* item,
+ const LLUUID& new_parent,
+ BOOL restamp)
+{
+ if(item->getParentUUID() != new_parent)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->setParent(new_parent);
+ new_item->updateParentOnServer(restamp);
+ model->updateItem(new_item);
+ model->notifyObservers();
+ }
+}
+
+// static
+void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
+ LLViewerInventoryCategory* cat,
+ const LLUUID& new_parent,
+ BOOL restamp)
+{
+ if(cat->getParentUUID() != new_parent)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
+ new_cat->setParent(new_parent);
+ new_cat->updateParentOnServer(restamp);
+ model->updateCategory(new_cat);
+ model->notifyObservers();
+ }
+}
+
+
+const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type)
+{
+ const std::string rv= LLInventoryType::lookup(inv_type);
+ if(rv.empty())
+ {
+ return std::string("<invalid>");
+ }
+ return rv;
+}
+
+LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags)
+{
+ LLInvFVBridge* new_listener = NULL;
+ switch(asset_type)
+ {
+ case LLAssetType::AT_TEXTURE:
+ if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLTextureBridge(inventory, uuid, inv_type);
+ break;
+
+ case LLAssetType::AT_SOUND:
+ if(!(inv_type == LLInventoryType::IT_SOUND))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLSoundBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_LANDMARK:
+ if(!(inv_type == LLInventoryType::IT_LANDMARK))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLLandmarkBridge(inventory, uuid, flags);
+ break;
+
+ case LLAssetType::AT_CALLINGCARD:
+ if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLCallingCardBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_SCRIPT:
+ if(!(inv_type == LLInventoryType::IT_LSL))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLScriptBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
+ break;
+
+ case LLAssetType::AT_NOTECARD:
+ if(!(inv_type == LLInventoryType::IT_NOTECARD))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLNotecardBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_ANIMATION:
+ if(!(inv_type == LLInventoryType::IT_ANIMATION))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLAnimationBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_GESTURE:
+ if(!(inv_type == LLInventoryType::IT_GESTURE))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLGestureBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_LSL_TEXT:
+ if(!(inv_type == LLInventoryType::IT_LSL))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLLSLTextBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ if(!(inv_type == LLInventoryType::IT_WEARABLE))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
+ break;
+ case LLAssetType::AT_CATEGORY:
+ case LLAssetType::AT_ROOT_CATEGORY:
+ if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
+ {
+ // Create a link folder handler instead.
+ new_listener = new LLLinkFolderBridge(inventory, uuid);
+ break;
+ }
+ new_listener = new LLFolderBridge(inventory, uuid);
+ break;
+ case LLAssetType::AT_LINK:
+ // Only should happen for broken links.
+ new_listener = new LLLinkItemBridge(inventory, uuid);
+ break;
+ case LLAssetType::AT_LINK_FOLDER:
+ // Only should happen for broken links.
+ new_listener = new LLLinkItemBridge(inventory, uuid);
+ break;
+ default:
+ llinfos << "Unhandled asset type (llassetstorage.h): "
+ << (S32)asset_type << llendl;
+ break;
+ }
+
+ if (new_listener)
+ {
+ new_listener->mInvType = inv_type;
+ }
+
+ return new_listener;
+}
+
+void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
+{
+ LLInventoryCategory* cat = model->getCategory(uuid);
+ if (cat)
+ {
+ model->purgeDescendentsOf(uuid);
+ model->notifyObservers();
+ }
+ LLInventoryObject* obj = model->getObject(uuid);
+ if (obj)
+ {
+ model->purgeObject(uuid);
+ model->notifyObservers();
+ }
+}
+
+// +=================================================+
+// | InventoryFVBridgeBuilder |
+// +=================================================+
+LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags /* = 0x00 */) const
+{
+ return LLInvFVBridge::createBridge(asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ uuid,
+ flags);
+}
+
+// +=================================================+
+// | LLItemBridge |
+// +=================================================+
+
+void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ }
+ if ("open" == action)
+ {
+ openItem();
+ return;
+ }
+ else if ("properties" == action)
+ {
+ showProperties();
+ return;
+ }
+ else if ("purge" == action)
+ {
+ purgeItem(model, mUUID);
+ return;
+ }
+ else if ("restoreToWorld" == action)
+ {
+ restoreToWorld();
+ return;
+ }
+ else if ("restore" == action)
+ {
+ restoreItem();
+ return;
+ }
+ else if ("copy_uuid" == action)
+ {
+ // Single item only
+ LLInventoryItem* item = model->getItem(mUUID);
+ if(!item) return;
+ LLUUID asset_id = item->getAssetUUID();
+ std::string buffer;
+ asset_id.toString(buffer);
+
+ gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
+ return;
+ }
+ else if ("copy" == action)
+ {
+ copyToClipboard();
+ return;
+ }
+ else if ("paste" == action)
+ {
+ // Single item only
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+ if (!folder_view_itemp) return;
+
+ folder_view_itemp->getListener()->pasteFromClipboard();
+ return;
+ }
+ else if ("paste_link" == action)
+ {
+ // Single item only
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+ if (!folder_view_itemp) return;
+
+ folder_view_itemp->getListener()->pasteLinkFromClipboard();
+ return;
+ }
+}
+
+void LLItemBridge::selectItem()
+{
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
+ if(item && !item->isComplete())
+ {
+ item->fetchFromServer();
+ }
+}
+
+void LLItemBridge::restoreItem()
+{
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
+ if(item)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
+ // do not restamp on restore.
+ LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
+ }
+}
+
+void LLItemBridge::restoreToWorld()
+{
+ LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem();
+ if (itemp)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("RezRestoreToWorld");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ itemp->packMessage(msg);
+ msg->sendReliable(gAgent.getRegion()->getHost());
+ }
+
+ //Similar functionality to the drag and drop rez logic
+ BOOL remove_from_inventory = FALSE;
+
+ //remove local inventory copy, sim will deal with permissions and removing the item
+ //from the actual inventory if its a no-copy etc
+ if(!itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ remove_from_inventory = TRUE;
+ }
+
+ // Check if it's in the trash. (again similar to the normal rez logic)
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id))
+ {
+ remove_from_inventory = TRUE;
+ }
+
+ if(remove_from_inventory)
+ {
+ gInventory.deleteObject(itemp->getUUID());
+ gInventory.notifyObservers();
+ }
+}
+
+void LLItemBridge::gotoItem(LLFolderView *folder)
+{
+ LLInventoryObject *obj = getInventoryObject();
+ if (obj && obj->getIsLinkType())
+ {
+ LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
+ if (active_panel)
+ {
+ active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
+ }
+ }
+}
+
+LLUIImagePtr LLItemBridge::getIcon() const
+{
+ return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
+}
+
+PermissionMask LLItemBridge::getPermissionMask() const
+{
+ LLViewerInventoryItem* item = getItem();
+ PermissionMask perm_mask = 0;
+ if(item)
+ {
+ BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
+ BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
+ BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
+ gAgent.getID());
+
+ if (copy) perm_mask |= PERM_COPY;
+ if (mod) perm_mask |= PERM_MODIFY;
+ if (xfer) perm_mask |= PERM_TRANSFER;
+
+ }
+ return perm_mask;
+}
+
+const std::string& LLItemBridge::getDisplayName() const
+{
+ if(mDisplayName.empty())
+ {
+ buildDisplayName(getItem(), mDisplayName);
+ }
+ return mDisplayName;
+}
+
+void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
+{
+ if(item)
+ {
+ name.assign(item->getName());
+ }
+ else
+ {
+ name.assign(LLStringUtil::null);
+ }
+}
+
+LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
+{
+ U8 font = LLFontGL::NORMAL;
+
+ if( gAgentWearables.isWearingItem( mUUID ) )
+ {
+ // llinfos << "BOLD" << llendl;
+ font |= LLFontGL::BOLD;
+ }
+
+ const LLViewerInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ font |= LLFontGL::ITALIC;
+ }
+ return (LLFontGL::StyleFlags)font;
+}
+
+std::string LLItemBridge::getLabelSuffix() const
+{
+ // String table is loaded before login screen and inventory items are
+ // loaded after login, so LLTrans should be ready.
+ static std::string NO_COPY =LLTrans::getString("no_copy");
+ static std::string NO_MOD = LLTrans::getString("no_modify");
+ static std::string NO_XFER = LLTrans::getString("no_transfer");
+ static std::string LINK = LLTrans::getString("link");
+ static std::string BROKEN_LINK = LLTrans::getString("broken_link");
+ std::string suffix;
+ LLInventoryItem* item = getItem();
+ if(item)
+ {
+ // it's a bit confusing to put nocopy/nomod/etc on calling cards.
+ if(LLAssetType::AT_CALLINGCARD != item->getType()
+ && item->getPermissions().getOwner() == gAgent.getID())
+ {
+ BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
+ if (broken_link) return BROKEN_LINK;
+
+ BOOL link = item->getIsLinkType();
+ if (link) return LINK;
+
+ BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
+ if (!copy)
+ {
+ suffix += NO_COPY;
+ }
+ BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
+ if (!mod)
+ {
+ suffix += NO_MOD;
+ }
+ BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
+ gAgent.getID());
+ if (!xfer)
+ {
+ suffix += NO_XFER;
+ }
+ }
+ }
+ return suffix;
+}
+
+time_t LLItemBridge::getCreationDate() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ return item->getCreationDate();
+ }
+ return 0;
+}
+
+
+BOOL LLItemBridge::isItemRenameable() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ // (For now) Don't allow calling card rename since that may confuse users as to
+ // what the calling card points to.
+ if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
+ {
+ return FALSE;
+ }
+ return (item->getPermissions().allowModifyBy(gAgent.getID()));
+ }
+ return FALSE;
+}
+
+BOOL LLItemBridge::renameItem(const std::string& new_name)
+{
+ if(!isItemRenameable())
+ return FALSE;
+ LLPreview::dirty(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
+ LLViewerInventoryItem* item = getItem();
+ if(item && (item->getName() != new_name))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(new_name);
+ buildDisplayName(new_item, mDisplayName);
+ new_item->updateServer(FALSE);
+ model->updateItem(new_item);
+
+ model->notifyObservers();
+ }
+ // return FALSE because we either notified observers (& therefore
+ // rebuilt) or we didn't update.
+ return FALSE;
+}
+
+
+BOOL LLItemBridge::removeItem()
+{
+ if(!isItemRemovable())
+ {
+ return FALSE;
+ }
+ // move it to the trash
+ LLPreview::hide(mUUID, TRUE);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLViewerInventoryItem* item = getItem();
+
+ // if item is not already in trash
+ if(item && !model->isObjectDescendentOf(mUUID, trash_id))
+ {
+ // move to trash, and restamp
+ LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE);
+ // delete was successful
+ return TRUE;
+ }
+ else
+ {
+ // tried to delete already item in trash (should purge?)
+ return FALSE;
+ }
+}
+
+BOOL LLItemBridge::isItemCopyable() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ // can't copy worn objects. DEV-15183
+ LLVOAvatarSelf *avatarp = gAgent.getAvatarObject();
+ if( !avatarp )
+ {
+ return FALSE;
+ }
+
+ if(avatarp->isWearingAttachment(mUUID))
+ {
+ return FALSE;
+ }
+
+ // All items can be copied, not all can be pasted.
+ // The only time an item can't be copied is if it's a link
+ // return (item->getPermissions().allowCopyBy(gAgent.getID()));
+ if (item->getIsLinkType())
+ {
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+BOOL LLItemBridge::copyToClipboard() const
+{
+ if(isItemCopyable())
+ {
+ LLInventoryClipboard::instance().add(mUUID);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+LLViewerInventoryItem* LLItemBridge::getItem() const
+{
+ LLViewerInventoryItem* item = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ item = (LLViewerInventoryItem*)model->getItem(mUUID);
+ }
+ return item;
+}
+
+BOOL LLItemBridge::isItemPermissive() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ U32 mask = item->getPermissions().getMaskBase();
+ if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+// +=================================================+
+// | LLFolderBridge |
+// +=================================================+
+
+LLFolderBridge* LLFolderBridge::sSelf=NULL;
+
+// Can be moved to another folder
+BOOL LLFolderBridge::isItemMovable() const
+{
+ LLInventoryObject* obj = getInventoryObject();
+ if(obj)
+ {
+ return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType()));
+ }
+ return FALSE;
+}
+
+void LLFolderBridge::selectItem()
+{
+}
+
+
+// Can be destroyed (or moved to trash)
+BOOL LLFolderBridge::isItemRemovable()
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ {
+ return FALSE;
+ }
+
+ if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
+ {
+ return FALSE;
+ }
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( !avatar )
+ {
+ return FALSE;
+ }
+
+ LLInventoryCategory* category = model->getCategory(mUUID);
+ if( !category )
+ {
+ return FALSE;
+ }
+
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ return FALSE;
+ }
+
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
+
+ S32 i;
+ for( i = 0; i < descendent_categories.count(); i++ )
+ {
+ LLInventoryCategory* category = descendent_categories[i];
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ return FALSE;
+ }
+ }
+
+ for( i = 0; i < descendent_items.count(); i++ )
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if( (item->getType() == LLAssetType::AT_CLOTHING) ||
+ (item->getType() == LLAssetType::AT_BODYPART) )
+ {
+ if(gAgentWearables.isWearingItem(item->getUUID()))
+ {
+ return FALSE;
+ }
+ }
+ else
+ if( item->getType() == LLAssetType::AT_OBJECT )
+ {
+ if(avatar->isWearingAttachment(item->getUUID()))
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL LLFolderBridge::isUpToDate() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ if( !category )
+ {
+ return FALSE;
+ }
+
+ return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
+}
+
+BOOL LLFolderBridge::isItemCopyable() const
+{
+ return TRUE;
+}
+
+BOOL LLFolderBridge::copyToClipboard() const
+{
+ if(isItemCopyable())
+ {
+ LLInventoryClipboard::instance().add(mUUID);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLFolderBridge::isClipboardPasteable() const
+{
+ if ( ! LLInvFVBridge::isClipboardPasteable() )
+ return FALSE;
+
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) )
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if ( !model )
+ {
+ return FALSE;
+ }
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ const LLViewerInventoryCategory *current_cat = getCategory();
+
+ // Search for the direct descendent of current Friends subfolder among all pasted items,
+ // and return false if is found.
+ for(S32 i = objects.count() - 1; i >= 0; --i)
+ {
+ const LLUUID &obj_id = objects.get(i);
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
+
+ }
+ return TRUE;
+}
+
+BOOL LLFolderBridge::isClipboardPasteableAsLink() const
+{
+ // Check normal paste-as-link permissions
+ if (!LLInvFVBridge::isClipboardPasteableAsLink())
+ {
+ return FALSE;
+ }
+
+ const LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ const LLViewerInventoryCategory *current_cat = getCategory();
+ if (current_cat)
+ {
+ const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat );
+ const LLUUID ¤t_cat_id = current_cat->getUUID();
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &obj_id = objects.get(i);
+ const LLInventoryCategory *cat = model->getCategory(obj_id);
+ if (cat)
+ {
+ const LLUUID &cat_id = cat->getUUID();
+ // Don't allow recursive pasting
+ if ((cat_id == current_cat_id) ||
+ model->isObjectDescendentOf(current_cat_id, cat_id))
+ {
+ return FALSE;
+ }
+ }
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( is_in_friend_folder )
+ {
+ // If object is direct descendent of current Friends subfolder than return false.
+ // Note: We can't use 'const LLInventoryCategory *cat', because it may be null
+ // in case type of obj_id is LLInventoryItem.
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+
+}
+
+BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
+ BOOL drop)
+{
+ // This should never happen, but if an inventory item is incorrectly parented,
+ // the UI will get confused and pass in a NULL.
+ if(!inv_cat) return FALSE;
+
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if(!avatar) return FALSE;
+
+ // cannot drag categories into library
+ if(!isAgentInventory())
+ {
+ return FALSE;
+ }
+
+ // check to make sure source is agent inventory, and is represented there.
+ LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
+ BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
+ && (LLToolDragAndDrop::SOURCE_AGENT == source);
+
+ BOOL accept = FALSE;
+ S32 i;
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ if(is_agent_inventory)
+ {
+ const LLUUID& cat_id = inv_cat->getUUID();
+
+ // Is the destination the trash?
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ BOOL move_is_into_trash = (mUUID == trash_id)
+ || model->isObjectDescendentOf(mUUID, trash_id);
+ BOOL is_movable = (!LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()));
+ const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ // BAP - restrictions?
+ is_movable = true;
+ }
+
+ if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))
+ {
+ is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604
+ }
+
+ if( is_movable )
+ {
+ gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
+
+ for( i = 0; i < descendent_categories.count(); i++ )
+ {
+ LLInventoryCategory* category = descendent_categories[i];
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ // ...can't move "special folders" like Textures
+ is_movable = FALSE;
+ break;
+ }
+ }
+
+ if( is_movable )
+ {
+ if( move_is_into_trash )
+ {
+ for( i = 0; i < descendent_items.count(); i++ )
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if( (item->getType() == LLAssetType::AT_CLOTHING) ||
+ (item->getType() == LLAssetType::AT_BODYPART) )
+ {
+ if( gAgentWearables.isWearingItem( item->getUUID() ) )
+ {
+ is_movable = FALSE; // It's generally movable, but not into the trash!
+ break;
+ }
+ }
+ else
+ if( item->getType() == LLAssetType::AT_OBJECT )
+ {
+ if( avatar->isWearingAttachment( item->getUUID() ) )
+ {
+ is_movable = FALSE; // It's generally movable, but not into the trash!
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ accept = is_movable
+ && (mUUID != cat_id) // Can't move a folder into itself
+ && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
+ && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity
+ if(accept && drop)
+ {
+ // Look for any gestures and deactivate them
+ if (move_is_into_trash)
+ {
+ for (i = 0; i < descendent_items.count(); i++)
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if (item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(item->getUUID()))
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+ }
+ // if target is an outfit or current outfit folder we use link
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+#if SUPPORT_ENSEMBLES
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::wearEnsemble(inv_cat);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_cat->getUUID(),
+ mUUID,
+ inv_cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ cb);
+ }
+#endif
+ }
+ else
+ {
+
+ // Reparent the folder and restamp children if it's moving
+ // into trash.
+ LLInvFVBridge::changeCategoryParent(
+ model,
+ (LLViewerInventoryCategory*)inv_cat,
+ mUUID,
+ move_is_into_trash);
+ }
+ }
+ }
+ else if(LLToolDragAndDrop::SOURCE_WORLD == source)
+ {
+ // content category has same ID as object itself
+ LLUUID object_id = inv_cat->getUUID();
+ LLUUID category_id = mUUID;
+ accept = move_inv_category_world_to_agent(object_id, category_id, drop);
+ }
+ return accept;
+}
+
+void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
+{
+ const char* dialog = NULL;
+ if (object->flagScripted())
+ {
+ dialog = "MoveInventoryFromScriptedObject";
+ }
+ else
+ {
+ dialog = "MoveInventoryFromObject";
+ }
+ LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+}
+
+// Move/copy all inventory items from the Contents folder of an in-world
+// object to the agent's inventory, inside a given category.
+BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
+ const LLUUID& category_id,
+ BOOL drop,
+ void (*callback)(S32, void*),
+ void* user_data)
+{
+ // Make sure the object exists. If we allowed dragging from
+ // anonymous objects, it would be possible to bypass
+ // permissions.
+ // content category has same ID as object itself
+ LLViewerObject* object = gObjectList.findObject(object_id);
+ if(!object)
+ {
+ llinfos << "Object not found for drop." << llendl;
+ return FALSE;
+ }
+
+ // this folder is coming from an object, as there is only one folder in an object, the root,
+ // we need to collect the entire contents and handle them as a group
+ InventoryObjectList inventory_objects;
+ object->getInventoryContents(inventory_objects);
+
+ if (inventory_objects.empty())
+ {
+ llinfos << "Object contents not found for drop." << llendl;
+ return FALSE;
+ }
+
+ BOOL accept = TRUE;
+ BOOL is_move = FALSE;
+
+ // coming from a task. Need to figure out if the person can
+ // move/copy this item.
+ InventoryObjectList::iterator it = inventory_objects.begin();
+ InventoryObjectList::iterator end = inventory_objects.end();
+ for ( ; it != end; ++it)
+ {
+ // coming from a task. Need to figure out if the person can
+ // move/copy this item.
+ LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions());
+ if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
+ && perm.allowTransferTo(gAgent.getID())))
+// || gAgent.isGodlike())
+ {
+ accept = TRUE;
+ }
+ else if(object->permYouOwner())
+ {
+ // If the object cannot be copied, but the object the
+ // inventory is owned by the agent, then the item can be
+ // moved from the task to agent inventory.
+ is_move = TRUE;
+ accept = TRUE;
+ }
+ else
+ {
+ accept = FALSE;
+ break;
+ }
+ }
+
+ if(drop && accept)
+ {
+ it = inventory_objects.begin();
+ InventoryObjectList::iterator first_it = inventory_objects.begin();
+ LLMoveInv* move_inv = new LLMoveInv;
+ move_inv->mObjectID = object_id;
+ move_inv->mCategoryID = category_id;
+ move_inv->mCallback = callback;
+ move_inv->mUserData = user_data;
+
+ for ( ; it != end; ++it)
+ {
+ two_uuids_t two(category_id, (*it)->getUUID());
+ move_inv->mMoveList.push_back(two);
+ }
+
+ if(is_move)
+ {
+ // Callback called from within here.
+ warn_move_inventory(object, move_inv);
+ }
+ else
+ {
+ LLNotification::Params params("MoveInventoryFromObject");
+ params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+ }
+ return accept;
+}
+
+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(); // BAP - safe?
+ 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 - safe?
+ // 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 LLFindWearables::operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+{
+ if(item)
+ {
+ if((item->getType() == LLAssetType::AT_CLOTHING)
+ || (item->getType() == LLAssetType::AT_BODYPART))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+
+//Used by LLFolderBridge as callback for directory recursion.
+class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
+{
+public:
+ LLRightClickInventoryFetchObserver() :
+ mCopyItems(false)
+ { };
+ LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) :
+ mCatID(cat_id),
+ mCopyItems(copy_items)
+ { };
+ virtual void done()
+ {
+ // we've downloaded all the items, so repaint the dialog
+ LLFolderBridge::staticFolderOptionsMenu();
+
+ gInventory.removeObserver(this);
+ delete this;
+ }
+
+
+protected:
+ LLUUID mCatID;
+ bool mCopyItems;
+
+};
+
+//Used by LLFolderBridge as callback for directory recursion.
+class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
+{
+public:
+ LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {}
+ ~LLRightClickInventoryFetchDescendentsObserver() {}
+ virtual void done();
+protected:
+ bool mCopyItems;
+};
+
+void LLRightClickInventoryFetchDescendentsObserver::done()
+{
+ // Avoid passing a NULL-ref as mCompleteFolders.front() down to
+ // gInventory.collectDescendents()
+ if( mCompleteFolders.empty() )
+ {
+ llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl;
+ dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+ return;
+ }
+
+ // What we do here is get the complete information on the items in
+ // the library, and set up an observer that will wait for that to
+ // happen.
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(mCompleteFolders.front(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ S32 count = item_array.count();
+#if 0 // HACK/TODO: Why?
+ // This early causes a giant menu to get produced, and doesn't seem to be needed.
+ if(!count)
+ {
+ llwarns << "Nothing fetched in category " << mCompleteFolders.front()
+ << llendl;
+ dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+ return;
+ }
+#endif
+
+ LLRightClickInventoryFetchObserver* outfit;
+ outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems);
+ LLInventoryFetchObserver::item_ref_t ids;
+ for(S32 i = 0; i < count; ++i)
+ {
+ ids.push_back(item_array.get(i)->getUUID());
+ }
+
+ // clean up, and remove this as an observer since the call to the
+ // outfit could notify observers and throw us into an infinite
+ // loop.
+ dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+
+ // increment busy count and either tell the inventory to check &
+ // call done, or add this object to the inventory for observation.
+ inc_busy_count();
+
+ // do the fetch
+ outfit->fetchItems(ids);
+ outfit->done(); //Not interested in waiting and this will be right 99% of the time.
+//Uncomment the following code for laggy Inventory UI.
+/* if(outfit->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ outfit->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(outfit);
+ }*/
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryWearObserver
+//
+// Observer for "copy and wear" operation to support knowing
+// when the all of the contents have been added to inventory.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryCopyAndWearObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {}
+ virtual ~LLInventoryCopyAndWearObserver() {}
+ virtual void changed(U32 mask);
+
+protected:
+ LLUUID mCatID;
+ int mContentsCount;
+ BOOL mFolderAdded;
+};
+
+
+
+void LLInventoryCopyAndWearObserver::changed(U32 mask)
+{
+ if((mask & (LLInventoryObserver::ADD)) != 0)
+ {
+ if (!mFolderAdded)
+ {
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ if ((*id_it) == mCatID)
+ {
+ mFolderAdded = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (mFolderAdded)
+ {
+ LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
+
+ if (NULL == category)
+ {
+ llwarns << "gInventory.getCategory(" << mCatID
+ << ") was NULL" << llendl;
+ }
+ else
+ {
+ if (category->getDescendentCount() ==
+ mContentsCount)
+ {
+ gInventory.removeObserver(this);
+ LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
+ delete this;
+ }
+ }
+ }
+
+ }
+}
+
+
+
+void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("open" == action)
+ {
+ openItem();
+ return;
+ }
+ else if ("paste" == action)
+ {
+ pasteFromClipboard();
+ return;
+ }
+ else if ("paste_link" == action)
+ {
+ pasteLinkFromClipboard();
+ return;
+ }
+ else if ("properties" == action)
+ {
+ showProperties();
+ return;
+ }
+ else if ("replaceoutfit" == action)
+ {
+ modifyOutfit(FALSE);
+ return;
+ }
+#if SUPPORT_ENSEMBLES
+ else if ("wearasensemble" == action)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+ LLAppearanceManager::wearEnsemble(cat,true);
+ return;
+ }
+#endif
+ else if ("addtooutfit" == action)
+ {
+ modifyOutfit(TRUE);
+ return;
+ }
+ else if ("copy" == action)
+ {
+ copyToClipboard();
+ return;
+ }
+ else if ("removefromoutfit" == action)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+
+ remove_inventory_category_from_avatar ( cat );
+ return;
+ }
+ else if ("purge" == action)
+ {
+ purgeItem(model, mUUID);
+ return;
+ }
+ else if ("restore" == action)
+ {
+ restoreItem();
+ return;
+ }
+}
+
+void LLFolderBridge::openItem()
+{
+ lldebugs << "LLFolderBridge::openItem()" << llendl;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ bool fetching_inventory = model->fetchDescendentsOf(mUUID);
+ // Only change folder type if we have the folder contents.
+ if (!fetching_inventory)
+ {
+ // Disabling this for now, it's causing crash when new items are added to folders
+ // since folder type may change before new item item has finished processing.
+ // determineFolderType();
+ }
+}
+
+void LLFolderBridge::closeItem()
+{
+ determineFolderType();
+}
+
+void LLFolderBridge::determineFolderType()
+{
+ if (isUpToDate())
+ {
+ LLInventoryModel* model = getInventoryModel();
+ LLViewerInventoryCategory* category = model->getCategory(mUUID);
+ category->determineFolderType();
+ }
+}
+
+BOOL LLFolderBridge::isItemRenameable() const
+{
+ LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
+ if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
+ && (cat->getOwnerID() == gAgent.getID()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void LLFolderBridge::restoreItem()
+{
+ LLViewerInventoryCategory* cat;
+ cat = (LLViewerInventoryCategory*)getCategory();
+ if(cat)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType()));
+ // do not restamp children on restore
+ LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE);
+ }
+}
+
+LLFolderType::EType LLFolderBridge::getPreferredType() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ preferred_type = cat->getPreferredType();
+ }
+
+ return preferred_type;
+}
+
+// Icons for folders are based on the preferred type
+LLUIImagePtr LLFolderBridge::getIcon() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ preferred_type = cat->getPreferredType();
+ }
+ return getIcon(preferred_type);
+}
+
+LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
+{
+ // we only have one folder image now
+ return LLUI::getUIImage("Inv_FolderClosed");
+}
+
+BOOL LLFolderBridge::renameItem(const std::string& new_name)
+{
+ if(!isItemRenameable())
+ return FALSE;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat && (cat->getName() != new_name))
+ {
+ LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
+ new_cat->rename(new_name);
+ new_cat->updateServer(FALSE);
+ model->updateCategory(new_cat);
+
+ model->notifyObservers();
+ }
+ // return FALSE because we either notified observers (& therefore
+ // rebuilt) or we didn't update.
+ return FALSE;
+}
+
+BOOL LLFolderBridge::removeItem()
+{
+ if(!isItemRemovable())
+ {
+ return FALSE;
+ }
+ // move it to the trash
+ LLPreview::hide(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+
+ // Look for any gestures and deactivate them
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
+
+ S32 i;
+ for (i = 0; i < descendent_items.count(); i++)
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if (item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(item->getUUID()))
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+
+ // go ahead and do the normal remove if no 'last calling
+ // cards' are being removed.
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
+ }
+
+ return TRUE;
+}
+
+void LLFolderBridge::pasteFromClipboard()
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(model && isClipboardPasteable())
+ {
+ LLInventoryItem* item = NULL;
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ const LLUUID parent_id(mUUID);
+ for(S32 i = 0; i < count; i++)
+ {
+ item = model->getItem(objects.get(i));
+ if (item)
+ {
+ if(LLInventoryClipboard::instance().isCutMode())
+ {
+ // move_inventory_item() is not enough,
+ //we have to update inventory locally too
+ changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ parent_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+ }
+}
+
+void LLFolderBridge::pasteLinkFromClipboard()
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ LLUUID parent_id(mUUID);
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &object_id = objects.get(i);
+#if SUPPORT_ENSEMBLES
+ if (LLInventoryCategory *cat = model->getCategory(object_id))
+ {
+ link_inventory_item(
+ gAgent.getID(),
+ cat->getUUID(),
+ parent_id,
+ cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else
+#endif
+ if (LLInventoryItem *item = model->getItem(object_id))
+ {
+ link_inventory_item(
+ gAgent.getID(),
+ item->getUUID(),
+ parent_id,
+ item->getName(),
+ LLAssetType::AT_LINK,
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+}
+
+void LLFolderBridge::staticFolderOptionsMenu()
+{
+ if (!sSelf) return;
+ sSelf->folderOptionsMenu();
+}
+
+void LLFolderBridge::folderOptionsMenu()
+{
+ std::vector<std::string> disabled_items;
+
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+
+ const LLInventoryCategory* category = model->getCategory(mUUID);
+ LLFolderType::EType type = category->getPreferredType();
+ const bool is_default_folder = category && LLFolderType::lookupIsProtectedType(type);
+ // BAP change once we're no longer treating regular categories as ensembles.
+ const bool is_ensemble = category && (type == LLFolderType::FT_NONE ||
+ LLFolderType::lookupIsEnsembleType(type));
+
+ // calling card related functionality for folders.
+
+ // Only enable calling-card related options for non-default folders.
+ if (!is_default_folder)
+ {
+ LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
+ if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
+ {
+ mItems.push_back(std::string("Calling Card Separator"));
+ mItems.push_back(std::string("Conference Chat Folder"));
+ mItems.push_back(std::string("IM All Contacts In Folder"));
+ }
+ }
+
+ // wearables related functionality for folders.
+ //is_wearable
+ LLFindWearables is_wearable;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+
+ if (mWearables ||
+ checkFolderForContentsOfType(model, is_wearable) ||
+ checkFolderForContentsOfType(model, is_object) ||
+ checkFolderForContentsOfType(model, is_gesture) )
+ {
+ mItems.push_back(std::string("Folder Wearables Separator"));
+
+ // Only enable add/replace outfit for non-default folders.
+ if (!is_default_folder)
+ {
+ mItems.push_back(std::string("Add To Outfit"));
+ mItems.push_back(std::string("Replace Outfit"));
+ }
+ if (is_ensemble)
+ {
+ mItems.push_back(std::string("Wear As Ensemble"));
+ }
+ mItems.push_back(std::string("Take Off Items"));
+ }
+ hide_context_entries(*mMenu, mItems, disabled_items);
+}
+
+BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ model->collectDescendentsIf(mUUID,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_type);
+ return ((item_array.count() > 0) ? TRUE : FALSE );
+}
+
+// Flags unused
+void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ mItems.clear();
+ mDisabledItems.clear();
+
+ lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
+// std::vector<std::string> disabled_items;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+
+ mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
+ mDisabledItems.clear(); //adding code to clear out disabled members from previous
+ if (lost_and_found_id == mUUID)
+ {
+ // This is the lost+found folder.
+ mItems.push_back(std::string("Empty Lost And Found"));
+ }
+
+ if(trash_id == mUUID)
+ {
+ // This is the trash.
+ mItems.push_back(std::string("Empty Trash"));
+ }
+ else if(model->isObjectDescendentOf(mUUID, trash_id))
+ {
+ // This is a folder in the trash.
+ mItems.clear(); // clear any items that used to exist
+ mItems.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ mDisabledItems.push_back(std::string("Purge Item"));
+ }
+
+ mItems.push_back(std::string("Restore Item"));
+ }
+ else if(isAgentInventory()) // do not allow creating in library
+ {
+ LLViewerInventoryCategory *cat = getCategory();
+ // BAP removed protected check to re-enable standard ops in untyped folders.
+ // Not sure what the right thing is to do here.
+ if (!isCOFFolder() && cat /*&&
+ LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/)
+ {
+ // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+ if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+ mItems.push_back(std::string("New Folder"));
+ mItems.push_back(std::string("New Script"));
+ mItems.push_back(std::string("New Note"));
+ mItems.push_back(std::string("New Gesture"));
+ mItems.push_back(std::string("New Clothes"));
+ mItems.push_back(std::string("New Body Parts"));
+ mItems.push_back(std::string("Change Type"));
+
+ LLViewerInventoryCategory *cat = getCategory();
+ if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ mDisabledItems.push_back(std::string("Change Type"));
+ }
+
+ getClipboardEntries(false, mItems, mDisabledItems, flags);
+ }
+ else
+ {
+ // Want some but not all of the items from getClipboardEntries for outfits.
+ if (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT)
+ {
+ mItems.push_back(std::string("Rename"));
+ mItems.push_back(std::string("Delete"));
+ }
+ }
+
+ //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
+ mCallingCards = mWearables = FALSE;
+
+ LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
+ if (checkFolderForContentsOfType(model, is_callingcard))
+ {
+ mCallingCards=TRUE;
+ }
+
+ LLFindWearables is_wearable;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+
+ if (checkFolderForContentsOfType(model, is_wearable) ||
+ checkFolderForContentsOfType(model, is_object) ||
+ checkFolderForContentsOfType(model, is_gesture) )
+ {
+ mWearables=TRUE;
+ }
+
+ mMenu = &menu;
+ sSelf = this;
+ LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
+
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ if (category)
+ {
+ folders.push_back(category->getUUID());
+ }
+ fetch->fetchDescendents(folders);
+ inc_busy_count();
+ if(fetch->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ fetch->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(fetch);
+ }
+ }
+ else
+ {
+ mItems.push_back(std::string("--no options--"));
+ mDisabledItems.push_back(std::string("--no options--"));
+ }
+ hide_context_entries(menu, mItems, mDisabledItems);
+}
+
+BOOL LLFolderBridge::hasChildren() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ LLInventoryModel::EHasChildren has_children;
+ has_children = gInventory.categoryHasChildren(mUUID);
+ return has_children != LLInventoryModel::CHILDREN_NO;
+}
+
+BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data)
+{
+ //llinfos << "LLFolderBridge::dragOrDrop()" << llendl;
+ BOOL accept = FALSE;
+ switch(cargo_type)
+ {
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_CALLINGCARD:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_CLOTHING:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ case DAD_LINK:
+ accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
+ drop);
+ break;
+ case DAD_CATEGORY:
+ if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
+ {
+ accept = FALSE;
+ }
+ else
+ {
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop);
+ }
+ break;
+ default:
+ break;
+ }
+ return accept;
+}
+
+LLViewerInventoryCategory* LLFolderBridge::getCategory() const
+{
+ LLViewerInventoryCategory* cat = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ cat = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ }
+ return cat;
+}
+
+
+// static
+void LLFolderBridge::pasteClipboard(void* user_data)
+{
+ LLFolderBridge* self = (LLFolderBridge*)user_data;
+ if(self) self->pasteFromClipboard();
+}
+
+void LLFolderBridge::createNewCategory(void* user_data)
+{
+ LLFolderBridge* bridge = (LLFolderBridge*)user_data;
+ if(!bridge) return;
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get());
+ if (!panel) return;
+ LLInventoryModel* model = panel->getModel();
+ if(!model) return;
+ LLUUID id;
+ id = model->createNewCategory(bridge->getUUID(),
+ LLFolderType::FT_NONE,
+ LLStringUtil::null);
+ model->notifyObservers();
+
+ // At this point, the bridge has probably been deleted, but the
+ // view is still there.
+ panel->setSelection(id, TAKE_FOCUS_YES);
+}
+
+void LLFolderBridge::createNewShirt(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT);
+}
+
+void LLFolderBridge::createNewPants(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS);
+}
+
+void LLFolderBridge::createNewShoes(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES);
+}
+
+void LLFolderBridge::createNewSocks(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS);
+}
+
+void LLFolderBridge::createNewJacket(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET);
+}
+
+void LLFolderBridge::createNewSkirt(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT);
+}
+
+void LLFolderBridge::createNewGloves(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES);
+}
+
+void LLFolderBridge::createNewUndershirt(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT);
+}
+
+void LLFolderBridge::createNewUnderpants(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS);
+}
+
+void LLFolderBridge::createNewShape(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE);
+}
+
+void LLFolderBridge::createNewSkin(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN);
+}
+
+void LLFolderBridge::createNewHair(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR);
+}
+
+void LLFolderBridge::createNewEyes(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES);
+}
+
+// static
+void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type)
+{
+ if(!bridge) return;
+ LLUUID parent_id = bridge->getUUID();
+ createWearable(parent_id, type);
+}
+
+// Separate function so can be called by global menu as well as right-click
+// menu.
+// static
+void LLFolderBridge::createWearable(const LLUUID &parent_id, EWearableType type)
+{
+ LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
+ LLAssetType::EType asset_type = wearable->getAssetType();
+ LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ parent_id, wearable->getTransactionID(), wearable->getName(),
+ wearable->getDescription(), asset_type, inv_type, wearable->getType(),
+ wearable->getPermissions().getMaskNextOwner(),
+ LLPointer<LLInventoryCallback>(NULL));
+}
+
+void LLFolderBridge::modifyOutfit(BOOL append)
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+
+ // BAP - was:
+ // wear_inventory_category_on_avatar( cat, append );
+ LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
+}
+
+// helper stuff
+bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv)
+{
+ LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData;
+ LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID);
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ if(option == 0 && object)
+ {
+ if (cat_and_wear && cat_and_wear->mWear)
+ {
+ InventoryObjectList inventory_objects;
+ object->getInventoryContents(inventory_objects);
+ int contents_count = inventory_objects.size()-1; //subtract one for containing folder
+
+ LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count);
+ gInventory.addObserver(inventoryObserver);
+ }
+
+ two_uuids_list_t::iterator move_it;
+ for (move_it = move_inv->mMoveList.begin();
+ move_it != move_inv->mMoveList.end();
+ ++move_it)
+ {
+ object->moveInventory(move_it->first, move_it->second);
+ }
+
+ // update the UI.
+ dialog_refresh_all();
+ }
+
+ if (move_inv->mCallback)
+ {
+ move_inv->mCallback(option, move_inv->mUserData);
+ }
+
+ delete move_inv;
+ return false;
+}
+
+/*
+Next functions intended to reorder items in the inventory folder and save order on server
+Is now used for Favorites folder.
+
+*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel
+*/
+void saveItemsOrder(LLInventoryModel::item_array_t& items)
+{
+ int sortField = 0;
+
+ // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ LLViewerInventoryItem* item = *i;
+
+ item->setSortField(++sortField);
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+
+ gInventory.updateItem(item);
+ }
+
+ gInventory.notifyObservers();
+}
+
+LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
+{
+ LLInventoryModel::item_array_t::iterator result = items.end();
+
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i)->getUUID() == id)
+ {
+ result = i;
+ break;
+ }
+ }
+
+ return result;
+}
+
+void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
+{
+ LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
+ LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
+
+ items.erase(findItemByUUID(items, srcItem->getUUID()));
+ items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
+}
+
+BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
+ BOOL drop)
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ // cannot drag into library
+ if(!isAgentInventory())
+ {
+ return FALSE;
+ }
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if(!avatar) return FALSE;
+
+ LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
+ BOOL accept = FALSE;
+ LLViewerObject* object = NULL;
+ if(LLToolDragAndDrop::SOURCE_AGENT == source)
+ {
+
+ BOOL is_movable = TRUE;
+ switch( inv_item->getActualType() )
+ {
+ case LLAssetType::AT_ROOT_CATEGORY:
+ is_movable = FALSE;
+ break;
+
+ case LLAssetType::AT_CATEGORY:
+ is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType());
+ break;
+ default:
+ break;
+ }
+
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
+ const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+
+ if(is_movable && move_is_into_trash)
+ {
+ switch(inv_item->getType())
+ {
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID());
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ( is_movable )
+ {
+ // Don't allow creating duplicates in the Calling Card/Friends
+ // subfolders, see bug EXT-1599. Check is item direct descendent
+ // of target folder and forbid item's movement if it so.
+ // Note: isItemDirectDescendentOfCategory checks if
+ // passed category is in the Calling Card/Friends folder
+ is_movable = ! LLFriendCardsManager::instance()
+ .isObjDirectDescendentOfCategory (inv_item, getCategory());
+ }
+
+ const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+
+ // we can move item inside a folder only if this folder is Favorites. See EXT-719
+ accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id));
+ if(accept && drop)
+ {
+ if (inv_item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
+ {
+ LLGestureManager::instance().deactivateGesture(inv_item->getUUID());
+ }
+ // If an item is being dragged between windows, unselect
+ // everything in the active window so that we don't follow
+ // the selection to its new location (which is very
+ // annoying).
+ if (LLFloaterInventory::getActiveInventory())
+ {
+ LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ if (active_panel && (panel != active_panel))
+ {
+ active_panel->unSelectAll();
+ }
+ }
+
+ // if dragging from/into favorites folder only reorder items
+ if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID))
+ {
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLIsType is_type(LLAssetType::AT_LANDMARK);
+ model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ if (itemp)
+ {
+ LLUUID srcItemId = inv_item->getUUID();
+ LLUUID destItemId = itemp->getListener()->getUUID();
+
+ // update order
+ updateItemsOrder(items, srcItemId, destItemId);
+
+ saveItemsOrder(items);
+ }
+ }
+ else if (favorites_id == mUUID) // if target is the favorites folder we use copy
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ inv_item->getPermissions().getOwner(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::wearItem(inv_item);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLAssetType::AT_LINK,
+ cb);
+ }
+ }
+ else
+ {
+ // restamp if the move is into the trash.
+ LLInvFVBridge::changeItemParent(
+ model,
+ (LLViewerInventoryItem*)inv_item,
+ mUUID,
+ move_is_into_trash);
+ }
+ }
+ }
+ else if(LLToolDragAndDrop::SOURCE_WORLD == source)
+ {
+ // Make sure the object exists. If we allowed dragging from
+ // anonymous objects, it would be possible to bypass
+ // permissions.
+ object = gObjectList.findObject(inv_item->getParentUUID());
+ if(!object)
+ {
+ llinfos << "Object not found for drop." << llendl;
+ return FALSE;
+ }
+
+ // coming from a task. Need to figure out if the person can
+ // move/copy this item.
+ LLPermissions perm(inv_item->getPermissions());
+ BOOL is_move = FALSE;
+ if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
+ && perm.allowTransferTo(gAgent.getID())))
+// || gAgent.isGodlike())
+
+ {
+ accept = TRUE;
+ }
+ else if(object->permYouOwner())
+ {
+ // If the object cannot be copied, but the object the
+ // inventory is owned by the agent, then the item can be
+ // moved from the task to agent inventory.
+ is_move = TRUE;
+ accept = TRUE;
+ }
+ if(drop && accept)
+ {
+ LLMoveInv* move_inv = new LLMoveInv;
+ move_inv->mObjectID = inv_item->getParentUUID();
+ two_uuids_t item_pair(mUUID, inv_item->getUUID());
+ move_inv->mMoveList.push_back(item_pair);
+ move_inv->mCallback = NULL;
+ move_inv->mUserData = NULL;
+ if(is_move)
+ {
+ warn_move_inventory(object, move_inv);
+ }
+ else
+ {
+ LLNotification::Params params("MoveInventoryFromObject");
+ params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+ }
+
+ }
+ else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
+ {
+ accept = TRUE;
+ if(drop)
+ {
+ copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(),
+ LLToolDragAndDrop::getInstance()->getSourceID(), inv_item);
+ }
+ }
+ else if(LLToolDragAndDrop::SOURCE_LIBRARY == source)
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item;
+ if(item && item->isComplete())
+ {
+ accept = TRUE;
+ if(drop)
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ inv_item->getPermissions().getOwner(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+ else
+ {
+ llwarns << "unhandled drag source" << llendl;
+ }
+ return accept;
+}
+
+// +=================================================+
+// | LLScriptBridge (DEPRECTED) |
+// +=================================================+
+
+LLUIImagePtr LLScriptBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
+}
+
+// +=================================================+
+// | LLTextureBridge |
+// +=================================================+
+
+LLUIImagePtr LLTextureBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
+}
+
+void LLTextureBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+}
+
+void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Texture Separator"));
+ items.push_back(std::string("Save As"));
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// virtual
+void LLTextureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("save_as" == action)
+ {
+ LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
+ if (preview_texture)
+ {
+ preview_texture->openToSave();
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+// +=================================================+
+// | LLSoundBridge |
+// +=================================================+
+
+LLUIImagePtr LLSoundBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
+}
+
+void LLSoundBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+// Changed this back to the way it USED to work:
+// only open the preview dialog through the contextual right-click menu
+// double-click just plays the sound
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ openSoundPreview((void*)this);
+ //send_uuid_sound_trigger(item->getAssetUUID(), 1.0);
+ }
+*/
+}
+
+void LLSoundBridge::previewItem()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ send_sound_trigger(item->getAssetUUID(), 1.0);
+ }
+}
+
+void LLSoundBridge::openSoundPreview(void* which)
+{
+ LLSoundBridge *me = (LLSoundBridge *)which;
+ LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES);
+}
+
+void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLSoundBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Sound Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Sound Separator"));
+ items.push_back(std::string("Sound Play"));
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// +=================================================+
+// | LLLandmarkBridge |
+// +=================================================+
+
+LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
+LLItemBridge(inventory, uuid)
+{
+ mVisited = FALSE;
+ if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
+ {
+ mVisited = TRUE;
+ }
+}
+
+LLUIImagePtr LLLandmarkBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE);
+}
+
+void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Landmark Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Landmark Separator"));
+ items.push_back(std::string("About Landmark"));
+
+ // Disable "About Landmark" menu item for
+ // multiple landmarks selected. Only one landmark
+ // info panel can be shown at a time.
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("About Landmark"));
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// Convenience function for the two functions below.
+void teleport_via_landmark(const LLUUID& asset_id)
+{
+ gAgent.teleportViaLandmark( asset_id );
+
+ // we now automatically track the landmark you're teleporting to
+ // because you'll probably arrive at a telehub instead
+ LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
+ if( floater_world_map )
+ {
+ floater_world_map->trackLandmark( asset_id );
+ }
+}
+
+// virtual
+void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("teleport" == action)
+ {
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ teleport_via_landmark(item->getAssetUUID());
+ }
+ }
+ else if ("about" == action)
+ {
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = item->getUUID();
+
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+ }
+ else
+ {
+ LLItemBridge::performAction(folder, model, action);
+ }
+}
+
+static bool open_landmark_callback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ LLUUID asset_id = notification["payload"]["asset_id"].asUUID();
+ if (option == 0)
+ {
+ teleport_via_landmark(asset_id);
+ }
+
+ return false;
+}
+static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback);
+
+
+void LLLandmarkBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if( item )
+ {
+ // Opening (double-clicking) a landmark immediately teleports,
+ // but warns you the first time.
+ // open_landmark(item);
+ LLSD payload;
+ payload["asset_id"] = item->getAssetUUID();
+ LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
+ }
+*/
+}
+
+
+// +=================================================+
+// | LLCallingCardObserver |
+// +=================================================+
+void LLCallingCardObserver::changed(U32 mask)
+{
+ mBridgep->refreshFolderViewItem();
+}
+
+// +=================================================+
+// | LLCallingCardBridge |
+// +=================================================+
+
+LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) :
+ LLItemBridge(inventory, uuid)
+{
+ mObserver = new LLCallingCardObserver(this);
+ LLAvatarTracker::instance().addObserver(mObserver);
+}
+
+LLCallingCardBridge::~LLCallingCardBridge()
+{
+ LLAvatarTracker::instance().removeObserver(mObserver);
+ delete mObserver;
+}
+
+void LLCallingCardBridge::refreshFolderViewItem()
+{
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;
+ if (itemp)
+ {
+ itemp->refresh();
+ }
+}
+
+// virtual
+void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("begin_im" == action)
+ {
+ LLViewerInventoryItem *item = getItem();
+ if (item && (item->getCreatorUUID() != gAgent.getID()) &&
+ (!item->getCreatorUUID().isNull()))
+ {
+ std::string callingcard_name;
+ gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
+ LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+ }
+ }
+ else if ("lure" == action)
+ {
+ LLViewerInventoryItem *item = getItem();
+ if (item && (item->getCreatorUUID() != gAgent.getID()) &&
+ (!item->getCreatorUUID().isNull()))
+ {
+ LLAvatarActions::offerTeleport(item->getCreatorUUID());
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+LLUIImagePtr LLCallingCardBridge::getIcon() const
+{
+ BOOL online = FALSE;
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
+ }
+ return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE);
+}
+
+std::string LLCallingCardBridge::getLabelSuffix() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) )
+ {
+ return LLItemBridge::getLabelSuffix() + " (online)";
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+void LLCallingCardBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if(item && !item->getCreatorUUID().isNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+*/
+}
+
+void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ LLInventoryItem* item = getItem();
+ BOOL good_card = (item
+ && (LLUUID::null != item->getCreatorUUID())
+ && (item->getCreatorUUID() != gAgent.getID()));
+ BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()));
+ items.push_back(std::string("Send Instant Message Separator"));
+ items.push_back(std::string("Send Instant Message"));
+ items.push_back(std::string("Offer Teleport..."));
+ items.push_back(std::string("Conference Chat"));
+
+ if (!good_card)
+ {
+ disabled_items.push_back(std::string("Send Instant Message"));
+ }
+ if (!good_card || !user_online)
+ {
+ disabled_items.push_back(std::string("Offer Teleport..."));
+ disabled_items.push_back(std::string("Conference Chat"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data)
+{
+ LLViewerInventoryItem* item = getItem();
+ BOOL rv = FALSE;
+ if(item)
+ {
+ // check the type
+ switch(cargo_type)
+ {
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_CLOTHING:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ {
+ LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
+ const LLPermissions& perm = inv_item->getPermissions();
+ if(gInventory.getItem(inv_item->getUUID())
+ && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+ {
+ rv = TRUE;
+ if(drop)
+ {
+ LLToolDragAndDrop::giveInventory(item->getCreatorUUID(),
+ (LLInventoryItem*)cargo_data);
+ }
+ }
+ else
+ {
+ // It's not in the user's inventory (it's probably in
+ // an object's contents), so disallow dragging it here.
+ // You can't give something you don't yet have.
+ rv = FALSE;
+ }
+ break;
+ }
+ case DAD_CATEGORY:
+ {
+ LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data;
+ if( gInventory.getCategory( inv_cat->getUUID() ) )
+ {
+ rv = TRUE;
+ if(drop)
+ {
+ LLToolDragAndDrop::giveInventoryCategory(
+ item->getCreatorUUID(),
+ inv_cat);
+ }
+ }
+ else
+ {
+ // It's not in the user's inventory (it's probably in
+ // an object's contents), so disallow dragging it here.
+ // You can't give something you don't yet have.
+ rv = FALSE;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return rv;
+}
+
+BOOL LLCallingCardBridge::removeItem()
+{
+ if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
+ {
+ LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
+ return FALSE;
+ }
+ else
+ {
+ return LLItemBridge::removeItem();
+ }
+}
+// +=================================================+
+// | LLNotecardBridge |
+// +=================================================+
+
+LLUIImagePtr LLNotecardBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
+}
+
+void LLNotecardBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+*/
+}
+
+
+// +=================================================+
+// | LLGestureBridge |
+// +=================================================+
+
+LLUIImagePtr LLGestureBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
+}
+
+LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
+{
+ if( LLGestureManager::instance().isGestureActive(mUUID) )
+ {
+ return LLFontGL::BOLD;
+ }
+ else
+ {
+ return LLFontGL::NORMAL;
+ }
+}
+
+std::string LLGestureBridge::getLabelSuffix() const
+{
+ if( LLGestureManager::instance().isGestureActive(mUUID) )
+ {
+ return LLItemBridge::getLabelSuffix() + " (active)";
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+// virtual
+void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("activate" == action)
+ {
+ LLGestureManager::instance().activateGesture(mUUID);
+
+ LLViewerInventoryItem* item = gInventory.getItem(mUUID);
+ if (!item) return;
+
+ // Since we just changed the suffix to indicate (active)
+ // the server doesn't need to know, just the viewer.
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+ else if ("deactivate" == action)
+ {
+ LLGestureManager::instance().deactivateGesture(mUUID);
+
+ LLViewerInventoryItem* item = gInventory.getItem(mUUID);
+ if (!item) return;
+
+ // Since we just changed the suffix to indicate (active)
+ // the server doesn't need to know, just the viewer.
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+void LLGestureBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
+ preview->setFocus(TRUE);
+ }
+*/
+}
+
+BOOL LLGestureBridge::removeItem()
+{
+ // Force close the preview window, if it exists
+ LLGestureManager::instance().deactivateGesture(mUUID);
+ return LLItemBridge::removeItem();
+}
+
+void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLGestureBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Gesture Separator"));
+ items.push_back(std::string("Activate"));
+ items.push_back(std::string("Deactivate"));
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// +=================================================+
+// | LLAnimationBridge |
+// +=================================================+
+
+LLUIImagePtr LLAnimationBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
+}
+
+void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Animation Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Animation Separator"));
+ items.push_back(std::string("Animation Play"));
+ items.push_back(std::string("Animation Audition"));
+
+ hide_context_entries(menu, items, disabled_items);
+
+}
+
+// virtual
+void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ((action == "playworld") || (action == "playlocal"))
+ {
+ if (getItem())
+ {
+ LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
+ if ("playworld" == action) activate = LLPreviewAnim::PLAY;
+ if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
+
+ LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
+ if (preview)
+ {
+ preview->activate(activate);
+ }
+ }
+ }
+ else
+ {
+ LLItemBridge::performAction(folder, model, action);
+ }
+}
+
+void LLAnimationBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+*/
+}
+
+// +=================================================+
+// | LLObjectBridge |
+// +=================================================+
+
+// static
+LLUUID LLObjectBridge::sContextMenuItemID;
+
+LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) :
+LLItemBridge(inventory, uuid), mInvType(type)
+{
+ mAttachPt = (flags & 0xff); // low bye of inventory flags
+
+ mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE;
+}
+
+BOOL LLObjectBridge::isItemRemovable()
+{
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if(!avatar) return FALSE;
+ if(avatar->isWearingAttachment(mUUID)) return FALSE;
+ return LLInvFVBridge::isItemRemovable();
+}
+
+LLUIImagePtr LLObjectBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
+}
+
+LLInventoryObject* LLObjectBridge::getObject() const
+{
+ LLInventoryObject* object = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ object = (LLInventoryObject*)model->getObject(mUUID);
+ }
+ return object;
+}
+
+// virtual
+void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("attach" == action)
+ {
+ LLUUID object_id = mUUID;
+ LLViewerInventoryItem* item;
+ item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
+ if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
+ {
+ rez_attachment(item, NULL);
+ }
+ else if(item && item->isComplete())
+ {
+ // must be in library. copy it to our inventory and put it on.
+ LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
+ else if ("detach" == action)
+ {
+ LLInventoryItem* item = gInventory.getItem(mUUID);
+ if(item)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
+ gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
+ }
+ // this object might have been selected, so let the selection manager know it's gone now
+ LLViewerObject *found_obj =
+ gObjectList.findObject(item->getUUID());
+ if (found_obj)
+ {
+ LLSelectMgr::getInstance()->remove(found_obj);
+ }
+ else
+ {
+ llwarns << "object not found - ignoring" << llendl;
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+void LLObjectBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
+}
+
+LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
+{
+ U8 font = LLFontGL::NORMAL;
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar && avatar->isWearingAttachment( mUUID ) )
+ {
+ font |= LLFontGL::BOLD;
+ }
+
+ LLInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ font |= LLFontGL::ITALIC;
+ }
+
+ return (LLFontGL::StyleFlags)font;
+}
+
+std::string LLObjectBridge::getLabelSuffix() const
+{
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar && avatar->isWearingAttachment( mUUID ) )
+ {
+ std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
+ LLStringUtil::toLower(attachment_point_name);
+
+ LLStringUtil::format_map_t args;
+ args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str();
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
+{
+ LLSD payload;
+ payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link.
+
+ S32 attach_pt = 0;
+ if (gAgent.getAvatarObject() && attachment)
+ {
+ for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
+ iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter)
+ {
+ if (iter->second == attachment)
+ {
+ attach_pt = iter->first;
+ break;
+ }
+ }
+ }
+
+ payload["attachment_point"] = attach_pt;
+
+#if !ENABLE_MULTIATTACHMENTS
+ if (attachment && attachment->getNumObjects() > 0)
+ {
+ LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
+ }
+ else
+#endif
+ {
+ LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
+ }
+}
+
+bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
+{
+ LLVOAvatar *avatarp = gAgent.getAvatarObject();
+
+ if (!avatarp->canAttachMoreObjects())
+ {
+ LLSD args;
+ args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS);
+ LLNotifications::instance().add("MaxAttachmentsOnOutfit", args);
+ return false;
+ }
+
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (option == 0/*YES*/)
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
+
+ if (itemp)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
+ msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
+ U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
+#if ENABLE_MULTIATTACHMENTS
+ attachment_pt |= ATTACHMENT_ADD;
+#endif
+ msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
+ pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
+ msg->addStringFast(_PREHASH_Name, itemp->getName());
+ msg->addStringFast(_PREHASH_Description, itemp->getDescription());
+ msg->sendReliable(gAgent.getRegion()->getHost());
+ }
+ }
+ return false;
+}
+static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez);
+
+void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ LLInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ items.push_back(std::string("Goto Link"));
+ }
+
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ LLObjectBridge::sContextMenuItemID = mUUID;
+
+ if(item)
+ {
+ LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
+ if( !avatarp )
+ {
+ return;
+ }
+
+ if( avatarp->isWearingAttachment( mUUID ) )
+ {
+ items.push_back(std::string("Detach From Yourself"));
+ }
+ else
+ if( !isInTrash() && !isLinkedObjectInTrash() )
+ {
+ items.push_back(std::string("Attach Separator"));
+ items.push_back(std::string("Object Wear"));
+ items.push_back(std::string("Attach To"));
+ items.push_back(std::string("Attach To HUD"));
+ // commented out for DEV-32347
+ //items.push_back(std::string("Restore to Last Position"));
+
+ if (!avatarp->canAttachMoreObjects())
+ {
+ disabled_items.push_back(std::string("Object Wear"));
+ disabled_items.push_back(std::string("Attach To"));
+ disabled_items.push_back(std::string("Attach To HUD"));
+ }
+ LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
+ LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
+ LLVOAvatar *avatarp = gAgent.getAvatarObject();
+ if (attach_menu
+ && (attach_menu->getChildCount() == 0)
+ && attach_hud_menu
+ && (attach_hud_menu->getChildCount() == 0)
+ && avatarp)
+ {
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ iter != avatarp->mAttachmentPoints.end(); )
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ LLMenuItemCallGL::Params p;
+ std::string submenu_name = attachment->getName();
+ if (LLTrans::getString(submenu_name) != "")
+ {
+ p.name = (" ")+LLTrans::getString(submenu_name)+" ";
+ }
+ else
+ {
+ p.name = submenu_name;
+ }
+ LLSD cbparams;
+ cbparams["index"] = curiter->first;
+ cbparams["label"] = attachment->getName();
+ p.on_click.function_name = "Inventory.AttachObject";
+ p.on_click.parameter = LLSD(attachment->getName());
+ p.on_enable.function_name = "Attachment.Label";
+ p.on_enable.parameter = cbparams;
+ LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu;
+ LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
+ }
+ }
+ }
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+BOOL LLObjectBridge::renameItem(const std::string& new_name)
+{
+ if(!isItemRenameable())
+ return FALSE;
+ LLPreview::dirty(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
+ LLViewerInventoryItem* item = getItem();
+ if(item && (item->getName() != new_name))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(new_name);
+ buildDisplayName(new_item, mDisplayName);
+ new_item->updateServer(FALSE);
+ model->updateItem(new_item);
+
+ model->notifyObservers();
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
+ if( obj )
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
+ LLSelectMgr::getInstance()->selectionSetObjectName( new_name );
+ LLSelectMgr::getInstance()->deselectAll();
+ }
+ }
+ }
+ // return FALSE because we either notified observers (& therefore
+ // rebuilt) or we didn't update.
+ return FALSE;
+}
+
+// +=================================================+
+// | LLLSLTextBridge |
+// +=================================================+
+
+LLUIImagePtr LLLSLTextBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
+}
+
+void LLLSLTextBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+ /*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+ */
+}
+
+// +=================================================+
+// | LLWearableBridge |
+// +=================================================+
+
+// *NOTE: hack to get from avatar inventory to avatar
+void wear_inventory_item_on_avatar( LLInventoryItem* item )
+{
+ if(item)
+ {
+ lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
+ << " )" << llendl;
+
+ LLAppearanceManager::wearItem(item);
+ }
+}
+
+void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
+{
+ if(item)
+ {
+ lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
+ << " )" << llendl;
+
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onWearAddOnAvatarArrived,
+ new LLUUID(item->getUUID()));
+ }
+}
+
+void remove_inventory_category_from_avatar( LLInventoryCategory* category )
+{
+ if(!category) return;
+ lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
+ << " )" << llendl;
+
+
+ if( gFloaterCustomize )
+ {
+ gFloaterCustomize->askToSaveIfDirty(
+ boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID()));
+ }
+ else
+ {
+ remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() );
+ }
+}
+
+struct OnRemoveStruct
+{
+ LLUUID mUUID;
+ OnRemoveStruct(const LLUUID& uuid):
+ mUUID(uuid)
+ {
+ }
+};
+
+void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id)
+{
+
+ // Find all the wearables that are in the category's subtree.
+ lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl;
+ if(proceed)
+ {
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ LLFindWearables is_wearable;
+ gInventory.collectDescendentsIf(category_id,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_wearable);
+ S32 i;
+ S32 wearable_count = item_array.count();
+
+ LLInventoryModel::cat_array_t obj_cat_array;
+ LLInventoryModel::item_array_t obj_item_array;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ gInventory.collectDescendentsIf(category_id,
+ obj_cat_array,
+ obj_item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_object);
+ S32 obj_count = obj_item_array.count();
+
+ // Find all gestures in this folder
+ LLInventoryModel::cat_array_t gest_cat_array;
+ LLInventoryModel::item_array_t gest_item_array;
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+ gInventory.collectDescendentsIf(category_id,
+ gest_cat_array,
+ gest_item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_gesture);
+ S32 gest_count = gest_item_array.count();
+
+ if (wearable_count > 0) //Loop through wearables. If worn, remove.
+ {
+ for(i = 0; i < wearable_count; ++i)
+ {
+ if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) )
+ {
+ LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(),
+ item_array.get(i)->getName(),
+ item_array.get(i)->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(item_array.get(i)->getUUID()));
+
+ }
+ }
+ }
+
+
+ if (obj_count > 0)
+ {
+ for(i = 0; i < obj_count; ++i)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() );
+
+ gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
+
+ // this object might have been selected, so let the selection manager know it's gone now
+ LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID());
+ if (found_obj)
+ {
+ LLSelectMgr::getInstance()->remove(found_obj);
+ }
+ else
+ {
+ llwarns << "object not found, ignoring" << llendl;
+ }
+ }
+ }
+
+ if (gest_count > 0)
+ {
+ for(i = 0; i < gest_count; ++i)
+ {
+ if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) )
+ {
+ LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() );
+ gInventory.updateItem( gest_item_array.get(i) );
+ gInventory.notifyObservers();
+ }
+
+ }
+ }
+ }
+}
+
+BOOL LLWearableBridge::renameItem(const std::string& new_name)
+{
+ if( gAgentWearables.isWearingItem( mUUID ) )
+ {
+ gAgentWearables.setWearableName( mUUID, new_name );
+ }
+ return LLItemBridge::renameItem(new_name);
+}
+
+BOOL LLWearableBridge::isItemRemovable()
+{
+ if (gAgentWearables.isWearingItem(mUUID)) return FALSE;
+ return LLInvFVBridge::isItemRemovable();
+}
+
+std::string LLWearableBridge::getLabelSuffix() const
+{
+ if( gAgentWearables.isWearingItem( mUUID ) )
+ {
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+LLUIImagePtr LLWearableBridge::getIcon() const
+{
+ return get_item_icon(mAssetType, mInvType, mWearableType, FALSE);
+}
+
+// virtual
+void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("wear" == action)
+ {
+ wearOnAvatar();
+ }
+ else if ("wear_add" == action)
+ {
+ wearAddOnAvatar();
+ }
+ else if ("edit" == action)
+ {
+ editOnAvatar();
+ return;
+ }
+ else if ("take_off" == action)
+ {
+ if(gAgentWearables.isWearingItem(mUUID))
+ {
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(mUUID));
+ }
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+void LLWearableBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+ /*
+ if( isInTrash() )
+ {
+ LLNotifications::instance().add("CannotWearTrash");
+ }
+ else if(isAgentInventory())
+ {
+ if( !gAgentWearables.isWearingItem( mUUID ) )
+ {
+ wearOnAvatar();
+ }
+ }
+ else
+ {
+ // must be in the inventory library. copy it to our inventory
+ // and put it on right away.
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->isComplete())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else if(item)
+ {
+ // *TODO: We should fetch the item details, and then do
+ // the operation above.
+ LLNotifications::instance().add("CannotWearInfoNotComplete");
+ }
+ }
+ */
+}
+
+void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLWearableBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere
+ BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM);
+
+ // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976
+ LLViewerInventoryItem* item = getItem();
+ if( !no_open && item )
+ {
+ no_open = (item->getType() == LLAssetType::AT_CLOTHING) ||
+ (item->getType() == LLAssetType::AT_BODYPART);
+ }
+ if (!no_open)
+ {
+ items.push_back(std::string("Open"));
+ }
+
+ if (item && item->getIsLinkType())
+ {
+ items.push_back(std::string("Goto Link"));
+ }
+
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Wearable Separator"));
+
+ items.push_back(std::string("Wearable Wear"));
+ items.push_back(std::string("Wearable Add"));
+ items.push_back(std::string("Wearable Edit"));
+
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Wearable Edit"));
+ }
+ // Don't allow items to be worn if their baseobj is in the trash.
+ if (isLinkedObjectInTrash())
+ {
+ disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ disabled_items.push_back(std::string("Wearable Edit"));
+ }
+
+ // Disable wear and take off based on whether the item is worn.
+ if(item)
+ {
+ switch (item->getType())
+ {
+ case LLAssetType::AT_CLOTHING:
+ items.push_back(std::string("Take Off"));
+ case LLAssetType::AT_BODYPART:
+ if (gAgentWearables.isWearingItem(item->getUUID()))
+ {
+ disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ }
+ else
+ {
+ disabled_items.push_back(std::string("Take Off"));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// Called from menus
+// static
+BOOL LLWearableBridge::canWearOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return FALSE;
+ if(!self->isAgentInventory())
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
+ if(!item || !item->isComplete()) return FALSE;
+ }
+ return (!gAgentWearables.isWearingItem(self->mUUID));
+}
+
+// Called from menus
+// static
+void LLWearableBridge::onWearOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return;
+ self->wearOnAvatar();
+}
+
+void LLWearableBridge::wearOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+void LLWearableBridge::wearAddOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_add_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+// static
+void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata )
+{
+ LLUUID* item_id = (LLUUID*) userdata;
+ if(wearable)
+ {
+ LLViewerInventoryItem* item = NULL;
+ item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
+ if(item)
+ {
+ if(item->getAssetUUID() == wearable->getAssetID())
+ {
+ gAgentWearables.setWearableItem(item, wearable);
+ gInventory.notifyObservers();
+ //self->getFolderItem()->refreshFromRoot();
+ }
+ else
+ {
+ llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
+ }
+ }
+ }
+ delete item_id;
+}
+
+// static
+// BAP remove the "add" code path once everything is fully COF-ified.
+void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata )
+{
+ LLUUID* item_id = (LLUUID*) userdata;
+ if(wearable)
+ {
+ LLViewerInventoryItem* item = NULL;
+ item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
+ if(item)
+ {
+ if(item->getAssetUUID() == wearable->getAssetID())
+ {
+ bool do_append = true;
+ gAgentWearables.setWearableItem(item, wearable, do_append);
+ gInventory.notifyObservers();
+ //self->getFolderItem()->refreshFromRoot();
+ }
+ else
+ {
+ llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
+ }
+ }
+ }
+ delete item_id;
+}
+
+// static
+BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return FALSE;
+
+ return (gAgentWearables.isWearingItem(self->mUUID));
+}
+
+// static
+void LLWearableBridge::onEditOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(self)
+ {
+ self->editOnAvatar();
+ }
+}
+
+void LLWearableBridge::editOnAvatar()
+{
+ const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID);
+ if( wearable )
+ {
+ // Set the tab to the right wearable.
+ if (gFloaterCustomize)
+ gFloaterCustomize->setCurrentWearableType( wearable->getType() );
+
+ if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() )
+ {
+ // Start Avatar Customization
+ gAgent.changeCameraToCustomizeAvatar();
+ }
+ }
+}
+
+// static
+BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if( self && (LLAssetType::AT_BODYPART != self->mAssetType) )
+ {
+ return gAgentWearables.isWearingItem( self->mUUID );
+ }
+ return FALSE;
+}
+
+// static
+void LLWearableBridge::onRemoveFromAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return;
+ if(gAgentWearables.isWearingItem(self->mUUID))
+ {
+ LLViewerInventoryItem* item = self->getItem();
+ if (item)
+ {
+ LLUUID parent_id = item->getParentUUID();
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ onRemoveFromAvatarArrived,
+ new OnRemoveStruct(LLUUID(self->mUUID)));
+ }
+ }
+}
+
+// static
+void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
+ void* userdata)
+{
+ OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
+ const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID);
+ if(wearable)
+ {
+ if( gAgentWearables.isWearingItem( item_id ) )
+ {
+ EWearableType type = wearable->getType();
+
+ if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&&
+ //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
+ {
+ // MULTI_WEARABLE: FIXME HACK - always remove all
+ bool do_remove_all = false;
+ gAgentWearables.removeWearable( type, do_remove_all, 0 );
+ }
+ }
+ }
+
+ // Find and remove this item from the COF.
+ LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::getCOF());
+ llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF.
+ for (LLInventoryModel::item_array_t::const_iterator iter = items.begin();
+ iter != items.end();
+ ++iter)
+ {
+ const LLViewerInventoryItem *linked_item = (*iter);
+ const LLUUID &item_id = linked_item->getUUID();
+ gInventory.purgeObject(item_id);
+ }
+ gInventory.notifyObservers();
+
+ delete on_remove_struct;
+}
+
+LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,LLInventoryModel* model)
+{
+ LLInvFVBridgeAction* action = NULL;
+ switch(asset_type)
+ {
+ case LLAssetType::AT_TEXTURE:
+ action = new LLTextureBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_SOUND:
+ action = new LLSoundBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_LANDMARK:
+ action = new LLLandmarkBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_CALLINGCARD:
+ action = new LLCallingCardBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ action = new LLObjectBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_NOTECARD:
+ action = new LLNotecardBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_ANIMATION:
+ action = new LLAnimationBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_GESTURE:
+ action = new LLGestureBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_LSL_TEXT:
+ action = new LLLSLTextBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ action = new LLWearableBridgeAction(uuid,model);
+
+ break;
+
+ default:
+ break;
+ }
+ return action;
+}
+
+//static
+void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,LLInventoryModel* model)
+{
+ LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ if(action)
+ {
+ action->doIt();
+ delete action;
+ }
+}
+
+//static
+void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
+{
+ LLAssetType::EType asset_type = model->getItem(uuid)->getType();
+ LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ if(action)
+ {
+ action->doIt();
+ delete action;
+ }
+}
+
+LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
+{
+ if(mModel)
+ return (LLViewerInventoryItem*)mModel->getItem(mUUID);
+ return NULL;
+}
+
+//virtual
+void LLTextureBridgeAction::doIt()
+{
+ if (getItem())
+ {
+ LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLSoundBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLLandmarkBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if( item )
+ {
+ // Opening (double-clicking) a landmark immediately teleports,
+ // but warns you the first time.
+ LLSD payload;
+ payload["asset_id"] = item->getAssetUUID();
+ LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLCallingCardBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->getCreatorUUID().notNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void
+LLNotecardBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLGestureBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
+ preview->setFocus(TRUE);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLAnimationBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLObjectBridgeAction::doIt()
+{
+ LLFloaterReg::showInstance("properties", mUUID);
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLLSLTextBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+BOOL LLWearableBridgeAction::isInTrash() const
+{
+ if(!mModel) return FALSE;
+ const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return mModel->isObjectDescendentOf(mUUID, trash_id);
+}
+
+BOOL LLWearableBridgeAction::isAgentInventory() const
+{
+ if(!mModel) return FALSE;
+ if(gInventory.getRootFolderID() == mUUID) return TRUE;
+ return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
+}
+
+void LLWearableBridgeAction::wearOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+//virtual
+void LLWearableBridgeAction::doIt()
+{
+ if(isInTrash())
+ {
+ LLNotifications::instance().add("CannotWearTrash");
+ }
+ else if(isAgentInventory())
+ {
+ if(!gAgentWearables.isWearingItem(mUUID))
+ {
+ wearOnAvatar();
+ }
+ }
+ else
+ {
+ // must be in the inventory library. copy it to our inventory
+ // and put it on right away.
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->isComplete())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else if(item)
+ {
+ // *TODO: We should fetch the item details, and then do
+ // the operation above.
+ LLNotifications::instance().add("CannotWearInfoNotComplete");
+ }
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+// +=================================================+
+// | LLLinkItemBridge |
+// +=================================================+
+// For broken links
+
+std::string LLLinkItemBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkItemBridge::getIcon() const
+{
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE);
+ }
+ return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);
+}
+
+void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ lldebugs << "LLLink::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+
+// +=================================================+
+// | LLLinkBridge |
+// +=================================================+
+// For broken links.
+
+std::string LLLinkFolderBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkFolderBridge::getIcon() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ if (const LLViewerInventoryCategory* cat = item->getLinkedCategory())
+ {
+ preferred_type = cat->getPreferredType();
+ }
+ }
+ return LLFolderBridge::getIcon(preferred_type);
+}
+
+void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ lldebugs << "LLLink::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Goto Link"));
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ return;
+ }
+ LLItemBridge::performAction(folder,model,action);
+}
+
+void LLLinkFolderBridge::gotoItem(LLFolderView *folder)
+{
+ const LLUUID &cat_uuid = getFolderID();
+ if (!cat_uuid.isNull())
+ {
+ if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid))
+ {
+ if (LLInventoryModel* model = getInventoryModel())
+ {
+ model->fetchDescendentsOf(cat_uuid);
+ }
+ base_folder->setOpen(TRUE);
+ folder->setSelectionFromRoot(base_folder,TRUE);
+ folder->scrollToShowSelection();
+ }
+ }
+}
+
+const LLUUID &LLLinkFolderBridge::getFolderID() const
+{
+ if (LLViewerInventoryItem *link_item = getItem())
+ {
+ if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory())
+ {
+ const LLUUID& cat_uuid = cat->getUUID();
+ return cat_uuid;
+ }
+ }
+ return LLUUID::null;
+}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 6b2a2d32de..3ffeb55d6c 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -41,6 +41,7 @@ #include "llfoldervieweventlistener.h" class LLInventoryPanel; +class LLMenuGL; enum EInventoryIcon { @@ -121,7 +122,7 @@ protected: }; const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type); -void hideContextEntries(LLMenuGL& menu, +void hide_context_entries(LLMenuGL& menu, const std::vector<std::string> &entries_to_show, const std::vector<std::string> &disabled_entries); @@ -158,7 +159,7 @@ public: virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; virtual PermissionMask getPermissionMask() const; - virtual LLAssetType::EType getPreferredType() const; + virtual LLFolderType::EType getPreferredType() const; virtual time_t getCreationDate() const; virtual LLFontGL::StyleFlags getLabelStyle() const { @@ -297,9 +298,9 @@ public: virtual void selectItem(); virtual void restoreItem(); - virtual LLAssetType::EType getPreferredType() const; + virtual LLFolderType::EType getPreferredType() const; virtual LLUIImagePtr getIcon() const; - static LLUIImagePtr getIcon(LLAssetType::EType asset_type); + static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); virtual BOOL renameItem(const std::string& new_name); virtual BOOL removeItem(); @@ -320,7 +321,7 @@ public: virtual BOOL copyToClipboard() const; static void createWearable(LLFolderBridge* bridge, EWearableType type); - static void createWearable(LLUUID parent_folder_id, EWearableType type); + static void createWearable(const LLUUID &parent_folder_id, EWearableType type); LLViewerInventoryCategory* getCategory() const; @@ -382,6 +383,8 @@ class LLTextureBridge : public LLItemBridge public: virtual LLUIImagePtr getIcon() const; virtual void openItem(); + virtual void buildContextMenu(LLMenuGL& menu, U32 flags); + virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action); protected: LLTextureBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type) : @@ -807,5 +810,9 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, void teleport_via_landmark(const LLUUID& asset_id); +// Utility function to hide all entries except those in the list +void hide_context_entries(LLMenuGL& menu, + const std::vector<std::string> &entries_to_show, + const std::vector<std::string> &disabled_entries); #endif // LL_LLINVENTORYBRIDGE_H diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp new file mode 100644 index 0000000000..75218e98e0 --- /dev/null +++ b/indra/newview/llinventoryfunctions.cpp @@ -0,0 +1,340 @@ +/** + * @file llfloaterinventory.cpp + * @brief Implementation of the inventory view and associated stuff. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include <utility> // for std::pair<> + +#include "llinventoryfunctions.h" + +// library includes +#include "llagent.h" +#include "llagentwearables.h" +#include "llcallingcard.h" +#include "llfloaterreg.h" +#include "llsdserialize.h" +#include "llfiltereditor.h" +#include "llspinctrl.h" +#include "llui.h" +#include "message.h" + +// newview includes +#include "llappearancemgr.h" +#include "llappviewer.h" +#include "llfirstuse.h" +#include "llfloaterchat.h" +#include "llfloatercustomize.h" +#include "llfocusmgr.h" +#include "llfolderview.h" +#include "llgesturemgr.h" +#include "lliconctrl.h" +#include "llimview.h" +#include "llinventorybridge.h" +#include "llinventoryclipboard.h" +#include "llinventorymodel.h" +#include "llinventorypanel.h" +#include "lllineeditor.h" +#include "llmenugl.h" +#include "llpreviewanim.h" +#include "llpreviewgesture.h" +#include "llpreviewnotecard.h" +#include "llpreviewscript.h" +#include "llpreviewsound.h" +#include "llpreviewtexture.h" +#include "llresmgr.h" +#include "llscrollbar.h" +#include "llscrollcontainer.h" +#include "llselectmgr.h" +#include "lltabcontainer.h" +#include "lltooldraganddrop.h" +#include "lluictrlfactory.h" +#include "llviewerinventory.h" +#include "llviewermessage.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llviewerwindow.h" +#include "llvoavatarself.h" +#include "llwearablelist.h" + +BOOL LLInventoryState::sWearNewClothing = FALSE; +LLUUID LLInventoryState::sWearNewClothingTransactionID; + +void LLSaveFolderState::setApply(BOOL apply) +{ + mApply = apply; + // before generating new list of open folders, clear the old one + if(!apply) + { + clearOpenFolders(); + } +} + +void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) +{ + LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); + if(mApply) + { + // we're applying the open state + LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); + if(!bridge) return; + LLUUID id(bridge->getUUID()); + if(mOpenFolders.find(id) != mOpenFolders.end()) + { + folder->setOpen(TRUE); + } + else + { + // keep selected filter in its current state, this is less jarring to user + if (!folder->isSelected()) + { + folder->setOpen(FALSE); + } + } + } + else + { + // we're recording state at this point + if(folder->isOpen()) + { + LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); + if(!bridge) return; + mOpenFolders.insert(bridge->getUUID()); + } + } +} + +void LLOpenFilteredFolders::doItem(LLFolderViewItem *item) +{ + if (item->getFiltered()) + { + item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } +} + +void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder) +{ + if (folder->getFiltered() && 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->getFiltered() && !folder->hasFilteredDescendants()) + { + folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO); + } +} + +void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) +{ + if (item->getFiltered() && !mItemSelected) + { + item->getRoot()->setSelection(item, FALSE, FALSE); + if (item->getParentFolder()) + { + item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } + item->getRoot()->scrollToShowSelection(); + mItemSelected = TRUE; + } +} + +void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder) +{ + if (folder->getFiltered() && !mItemSelected) + { + folder->getRoot()->setSelection(folder, FALSE, FALSE); + if (folder->getParentFolder()) + { + folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); + } + folder->getRoot()->scrollToShowSelection(); + mItemSelected = TRUE; + } +} + +void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item) +{ + 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); + } +} + +const std::string& get_item_icon_name(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi ) +{ + EInventoryIcon idx = OBJECT_ICON_NAME; + if ( item_is_multi ) + { + idx = OBJECT_MULTI_ICON_NAME; + } + + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + if(LLInventoryType::IT_SNAPSHOT == inventory_type) + { + idx = SNAPSHOT_ICON_NAME; + } + else + { + idx = TEXTURE_ICON_NAME; + } + break; + + case LLAssetType::AT_SOUND: + idx = SOUND_ICON_NAME; + break; + case LLAssetType::AT_CALLINGCARD: + if(attachment_point!= 0) + { + idx = CALLINGCARD_ONLINE_ICON_NAME; + } + else + { + idx = CALLINGCARD_OFFLINE_ICON_NAME; + } + break; + case LLAssetType::AT_LANDMARK: + if(attachment_point!= 0) + { + idx = LANDMARK_VISITED_ICON_NAME; + } + else + { + idx = LANDMARK_ICON_NAME; + } + break; + case LLAssetType::AT_SCRIPT: + case LLAssetType::AT_LSL_TEXT: + case LLAssetType::AT_LSL_BYTECODE: + idx = SCRIPT_ICON_NAME; + break; + case LLAssetType::AT_CLOTHING: + idx = CLOTHING_ICON_NAME; + case LLAssetType::AT_BODYPART : + if(LLAssetType::AT_BODYPART == asset_type) + { + idx = BODYPART_ICON_NAME; + } + switch(LLInventoryItem::II_FLAGS_WEARABLES_MASK & attachment_point) + { + case WT_SHAPE: + idx = BODYPART_SHAPE_ICON_NAME; + break; + case WT_SKIN: + idx = BODYPART_SKIN_ICON_NAME; + break; + case WT_HAIR: + idx = BODYPART_HAIR_ICON_NAME; + break; + case WT_EYES: + idx = BODYPART_EYES_ICON_NAME; + break; + case WT_SHIRT: + idx = CLOTHING_SHIRT_ICON_NAME; + break; + case WT_PANTS: + idx = CLOTHING_PANTS_ICON_NAME; + break; + case WT_SHOES: + idx = CLOTHING_SHOES_ICON_NAME; + break; + case WT_SOCKS: + idx = CLOTHING_SOCKS_ICON_NAME; + break; + case WT_JACKET: + idx = CLOTHING_JACKET_ICON_NAME; + break; + case WT_GLOVES: + idx = CLOTHING_GLOVES_ICON_NAME; + break; + case WT_UNDERSHIRT: + idx = CLOTHING_UNDERSHIRT_ICON_NAME; + break; + case WT_UNDERPANTS: + idx = CLOTHING_UNDERPANTS_ICON_NAME; + break; + case WT_SKIRT: + idx = CLOTHING_SKIRT_ICON_NAME; + break; + case WT_ALPHA: + idx = CLOTHING_ALPHA_ICON_NAME; + break; + case WT_TATTOO: + idx = CLOTHING_TATTOO_ICON_NAME; + break; + default: + // no-op, go with choice above + break; + } + break; + case LLAssetType::AT_NOTECARD: + idx = NOTECARD_ICON_NAME; + break; + case LLAssetType::AT_ANIMATION: + idx = ANIMATION_ICON_NAME; + break; + case LLAssetType::AT_GESTURE: + idx = GESTURE_ICON_NAME; + break; + case LLAssetType::AT_LINK: + idx = LINKITEM_ICON_NAME; + break; + case LLAssetType::AT_LINK_FOLDER: + idx = LINKFOLDER_ICON_NAME; + break; + default: + break; + } + + return ICON_NAME[idx]; +} + +LLUIImagePtr get_item_icon(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi) +{ + const std::string& icon_name = get_item_icon_name(asset_type, inventory_type, attachment_point, item_is_multi ); + return LLUI::getUIImage(icon_name); +} diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h new file mode 100644 index 0000000000..95cc68ddbe --- /dev/null +++ b/indra/newview/llinventoryfunctions.h @@ -0,0 +1,136 @@ +/** + * @file llinventoryfunctions.h + * @brief Miscellaneous inventory-related functions and classes + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYFUNCTIONS_H +#define LL_LLINVENTORYFUNCTIONS_H + +#include "llassetstorage.h" +#include "lldarray.h" +#include "llfloater.h" +#include "llinventory.h" +#include "llinventoryfilter.h" +#include "llfolderview.h" +#include "llinventorymodel.h" +#include "lluictrlfactory.h" +#include <set> + + +class LLFolderViewItem; +class LLInventoryFilter; +class LLInventoryModel; +class LLInventoryPanel; +class LLInvFVBridge; +class LLInventoryFVBridgeBuilder; +class LLMenuBarGL; +class LLCheckBoxCtrl; +class LLSpinCtrl; +class LLScrollContainer; +class LLTextBox; +class LLIconCtrl; +class LLSaveFolderState; +class LLFilterEditor; +class LLTabContainer; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// This is a collection of miscellaneous functions and classes +// that don't fit cleanly into any other class header. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +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 +}; + +class LLSelectFirstFilteredItem : public LLFolderViewFunctor +{ +public: + LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} + virtual ~LLSelectFirstFilteredItem() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + BOOL wasItemSelected() { return mItemSelected; } +protected: + BOOL mItemSelected; +}; + +class LLOpenFilteredFolders : public LLFolderViewFunctor +{ +public: + LLOpenFilteredFolders() {} + virtual ~LLOpenFilteredFolders() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: + LLSaveFolderState() : mApply(FALSE) {} + virtual ~LLSaveFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + void setApply(BOOL apply); + void clearOpenFolders() { mOpenFolders.clear(); } +protected: + std::set<LLUUID> mOpenFolders; + BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: + LLOpenFoldersWithSelection() {} + virtual ~LLOpenFoldersWithSelection() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +const std::string& get_item_icon_name(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi ); + +LLUIImagePtr get_item_icon(LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + U32 attachment_point, + BOOL item_is_multi ); + +#endif // LL_LLINVENTORYFUNCTIONS_H + + + diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 1d7cbde0d5..baf34b42ff 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -46,7 +46,10 @@ #include "llfloater.h" #include "llfocusmgr.h" #include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llinventorypanel.h" #include "llfloaterinventory.h" +#include "llviewerfoldertype.h" #include "llviewerinventory.h" #include "llviewermessage.h" #include "llviewerwindow.h" @@ -314,7 +317,7 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id) // specifies 'type' as what it defaults to containing. The category is // not necessarily only for that type. *NOTE: This will create a new // inventory category on the fly if one does not exist. -LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool create_folder) +const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType t, bool create_folder) { const LLUUID &rv = findCatUUID(t); if(rv.isNull() && isInventoryUsable() && create_folder) @@ -330,10 +333,10 @@ LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool crea // Internal method which looks for a category with the specified // preferred type. Returns LLUUID::null if not found. -const LLUUID &LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type) const +const LLUUID &LLInventoryModel::findCatUUID(LLFolderType::EType preferred_type) const { const LLUUID &root_id = gInventory.getRootFolderID(); - if(LLAssetType::AT_CATEGORY == preferred_type) + if(LLFolderType::FT_CATEGORY == preferred_type) { return root_id; } @@ -361,7 +364,7 @@ const LLUUID &LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type) c // version will take care of details like what the name should be // based on preferred type. Returns the UUID of the new category. LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, - LLAssetType::EType preferred_type, + LLFolderType::EType preferred_type, const std::string& pname) { LLUUID id; @@ -371,9 +374,9 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, return id; } - if(preferred_type == LLAssetType::AT_SIMSTATE) + if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup()) { - lldebugs << "Attempt to create simstate category." << llendl; + lldebugs << "Attempt to create undefined category." << llendl; return id; } @@ -385,7 +388,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, } else { - name.assign(LLAssetType::lookupCategoryName(preferred_type)); + name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type)); } // Add the category to the internal representation @@ -449,7 +452,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, // Start with categories if(!include_trash) { - const LLUUID trash_id = findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH); if(trash_id.notNull() && (trash_id == id)) return; } @@ -483,7 +486,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, if (item->getActualType() == LLAssetType::AT_LINK_FOLDER) { LLViewerInventoryCategory *linked_cat = item->getLinkedCategory(); - if (linked_cat && linked_cat->getPreferredType() != LLAssetType::AT_OUTFIT) + if (linked_cat && linked_cat->getPreferredType() != LLFolderType::FT_OUTFIT) // BAP - was // LLAssetType::lookupIsEnsembleCategoryType(linked_cat->getPreferredType())) // Change back once ensemble typing is in place. @@ -663,7 +666,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) if(item->getParentUUID().isNull()) { - LLUUID category_id = findCategoryUUIDForType(new_item->getType()); + 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 ) @@ -687,7 +690,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) LLUUID parent_id = item->getParentUUID(); if(parent_id == CATEGORIZE_LOST_AND_FOUND_ID) { - parent_id = findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); new_item->setParent(parent_id); } item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, parent_id); @@ -700,7 +703,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) // Whoops! No such parent, make one. llinfos << "Lost item: " << new_item->getUUID() << " - " << new_item->getName() << llendl; - parent_id = findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + 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) @@ -1182,7 +1185,7 @@ void LLInventoryModel::mock(const LLUUID& root_id) root_id, LLUUID::null, LLAssetType::AT_CATEGORY, - LLAssetType::lookupCategoryName(LLAssetType::AT_ROOT_CATEGORY), + LLFolderType::lookupNewCategoryName(LLFolderType::FT_ROOT_CATEGORY), gAgent.getID()); addCategory(cat); gInventory.buildParentChildMap(); @@ -1340,7 +1343,7 @@ void fetchDescendentsResponder::result(const LLSD& content) item_it != folder_sd["items"].endArray(); ++item_it) { - LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + const LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); if (lost_uuid.notNull()) { LLSD item = *item_it; @@ -2047,11 +2050,11 @@ bool LLInventoryModel::loadSkeleton( cat->setUUID(folder_id.asUUID()); cat->setParent(parent_id.asUUID()); - LLAssetType::EType preferred_type = LLAssetType::AT_NONE; + LLFolderType::EType preferred_type = LLFolderType::FT_NONE; LLSD type_default = (*it)["type_default"]; if(type_default.isDefined()) { - preferred_type = (LLAssetType::EType)type_default.asInteger(); + preferred_type = (LLFolderType::EType)type_default.asInteger(); } cat->setPreferredType(preferred_type); cat->setVersion(version.asInteger()); @@ -2398,12 +2401,12 @@ void LLInventoryModel::buildParentChildMap() << cat->getName() << llendl; ++lost; // plop it into the lost & found. - LLAssetType::EType pref = cat->getPreferredType(); - if(LLAssetType::AT_NONE == pref) + LLFolderType::EType pref = cat->getPreferredType(); + if(LLFolderType::FT_NONE == pref) { - cat->setParent(findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND)); + cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); } - else if(LLAssetType::AT_CATEGORY == pref) + else if(LLFolderType::FT_CATEGORY == pref) { // it's the root cat->setParent(LLUUID::null); @@ -2462,7 +2465,7 @@ void LLInventoryModel::buildParentChildMap() ++lost; // plop it into the lost & found. // - item->setParent(findCategoryUUIDForType(LLAssetType::AT_LOST_AND_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(); @@ -2483,7 +2486,7 @@ void LLInventoryModel::buildParentChildMap() llwarns << "Found " << lost << " lost items." << llendl; LLMessageSystem* msg = gMessageSystem; BOOL start_new_message = TRUE; - LLUUID lnf = findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + const LLUUID lnf = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); for(std::vector<LLUUID>::iterator it = lost_item_ids.begin() ; it < lost_item_ids.end(); ++it) { if(start_new_message) @@ -2936,7 +2939,7 @@ void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg, lastfolder = tfolder; tfolder->unpackMessage(msg, _PREHASH_FolderData, i); // make sure it's not a protected folder - tfolder->setPreferredType(LLAssetType::AT_NONE); + tfolder->setPreferredType(LLFolderType::FT_NONE); folders.push_back(tfolder); // examine update for changes. LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID()); @@ -3174,13 +3177,13 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) // 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 (LLFloaterInventory::sWearNewClothing) + if (LLInventoryState::sWearNewClothing) { - LLFloaterInventory::sWearNewClothingTransactionID = tid; - LLFloaterInventory::sWearNewClothing = FALSE; + LLInventoryState::sWearNewClothingTransactionID = tid; + LLInventoryState::sWearNewClothing = FALSE; } - if (tid == LLFloaterInventory::sWearNewClothingTransactionID) + if (tid == LLInventoryState::sWearNewClothingTransactionID) { count = wearable_ids.size(); for (i = 0; i < count; ++i) @@ -3323,31 +3326,31 @@ void LLInventoryModel::processMoveInventoryItem(LLMessageSystem* msg, void**) //---------------------------------------------------------------------------- -// Trash: LLAssetType::AT_TRASH, "ConfirmEmptyTrash" -// Lost&Found: LLAssetType::AT_LOST_AND_FOUND, "ConfirmEmptyLostAndFound" +// Trash: LLFolderType::FT_TRASH, "ConfirmEmptyTrash" +// Lost&Found: LLFolderType::FT_LOST_AND_FOUND, "ConfirmEmptyLostAndFound" -bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLAssetType::EType folder_type) +bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLFolderType::EType preferred_type) { S32 option = LLNotification::getSelectedOption(notification, response); if (option == 0) // YES { - LLUUID folder_id = findCategoryUUIDForType(folder_type); + const LLUUID folder_id = findCategoryUUIDForType(preferred_type); purgeDescendentsOf(folder_id); notifyObservers(); } return false; } -void LLInventoryModel::emptyFolderType(const std::string notification, LLAssetType::EType folder_type) +void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderType::EType preferred_type) { if (!notification.empty()) { LLNotifications::instance().add(notification, LLSD(), LLSD(), - boost::bind(&LLInventoryModel::callbackEmptyFolderType, this, _1, _2, folder_type)); + boost::bind(&LLInventoryModel::callbackEmptyFolderType, this, _1, _2, preferred_type)); } else { - LLUUID folder_id = findCategoryUUIDForType(folder_type); + const LLUUID folder_id = findCategoryUUIDForType(preferred_type); purgeDescendentsOf(folder_id); notifyObservers(); } @@ -3358,7 +3361,7 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLAssetTy void LLInventoryModel::removeItem(const LLUUID& item_id) { LLViewerInventoryItem* item = getItem(item_id); - const LLUUID new_parent = findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH); if (item && item->getParentUUID() != new_parent) { LLInventoryModel::update_list_t update; diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index d51460b374..aba0a619db 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -34,6 +34,7 @@ #define LL_LLINVENTORYMODEL_H #include "llassettype.h" +#include "llfoldertype.h" #include "lldarray.h" #include "llframetimer.h" #include "llhttpclient.h" @@ -280,7 +281,7 @@ public: // SDK: Added flag to specify whether the folder should be created if not found. This fixes the horrible // multiple trash can bug. - LLUUID findCategoryUUIDForType(LLAssetType::EType preferred_type, bool create_folder = true); + const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder = true); // Call this method when it's time to update everyone on a new // state, by default, the inventory model will not update @@ -329,7 +330,7 @@ public: // category. If you want to use the default name based on type, // pass in a NULL to the 'name parameter. LLUUID createNewCategory(const LLUUID& parent_id, - LLAssetType::EType preferred_type, + LLFolderType::EType preferred_type, const std::string& name); // methods to load up inventory skeleton & meat. These are used @@ -385,9 +386,9 @@ public: bool isCategoryComplete(const LLUUID& cat_id) const; // callbacks - // Trigger a notification and empty the folder type (AT_TRASH or AT_LOST_AND_FOUND) if confirmed - void emptyFolderType(const std::string notification, LLAssetType::EType folder_type); - bool callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLAssetType::EType folder_type); + // Trigger a notification and empty the folder type (FT_TRASH or FT_LOST_AND_FOUND) if confirmed + void emptyFolderType(const std::string notification, LLFolderType::EType folder_type); + bool callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLFolderType::EType preferred_type); // Utility Functions void removeItem(const LLUUID& item_id); @@ -431,7 +432,7 @@ protected: // // Internal method which looks for a category with the specified // preferred type. Returns LLUUID::null if not found - const LLUUID &findCatUUID(LLAssetType::EType preferred_type) const; + const LLUUID &findCatUUID(LLFolderType::EType preferred_type) const; // Empty the entire contents void empty(); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp new file mode 100644 index 0000000000..7f69ce9641 --- /dev/null +++ b/indra/newview/llinventorypanel.cpp @@ -0,0 +1,907 @@ +/*
+ * @file llinventorypanel.cpp
+ * @brief Implementation of the inventory panel and associated stuff.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include <utility> // for std::pair<>
+
+#include "llinventorypanel.h"
+
+// Seraph TODO: Remove unnecessary headers
+
+// library includes
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llcallingcard.h"
+#include "llfloaterreg.h"
+#include "llsdserialize.h"
+#include "llfiltereditor.h"
+#include "llspinctrl.h"
+#include "llui.h"
+#include "message.h"
+
+// newview includes
+#include "llappearancemgr.h"
+#include "llappviewer.h"
+#include "llfirstuse.h"
+#include "llfloaterchat.h"
+#include "llfloatercustomize.h"
+#include "llfocusmgr.h"
+#include "llfolderview.h"
+#include "llgesturemgr.h"
+#include "lliconctrl.h"
+#include "llimview.h"
+#include "llinventorybridge.h"
+#include "llinventoryclipboard.h"
+#include "llinventorymodel.h"
+#include "lllineeditor.h"
+#include "llmenugl.h"
+#include "llpreviewanim.h"
+#include "llpreviewgesture.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewscript.h"
+#include "llpreviewsound.h"
+#include "llpreviewtexture.h"
+#include "llresmgr.h"
+#include "llscrollbar.h"
+#include "llscrollcontainer.h"
+#include "llselectmgr.h"
+#include "lltabcontainer.h"
+#include "lltooldraganddrop.h"
+#include "lluictrlfactory.h"
+#include "llviewerfoldertype.h"
+#include "llviewerinventory.h"
+#include "llviewermessage.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+#include "llvoavatarself.h"
+#include "llwearablelist.h"
+#include "llimfloater.h"
+
+static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");
+
+const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
+const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");
+const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string("");
+static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER;
+
+LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
+ LLPanel(p),
+ mInventoryObserver(NULL),
+ mFolders(NULL),
+ mScroller(NULL),
+ mSortOrderSetting(p.sort_order_setting),
+ mInventory(p.inventory),
+ mAllowMultiSelect(p.allow_multi_select),
+ mHasInventoryConnection(false),
+ mStartFolderString(p.start_folder),
+ mBuildDefaultHierarchy(true),
+ mInvFVBridgeBuilder(NULL)
+{
+ mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
+
+ // contex menu callbacks
+ mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
+ mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
+ mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLInventoryPanel::doCreate, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
+
+ setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor"));
+ setBackgroundVisible(TRUE);
+ setBackgroundOpaque(TRUE);
+}
+
+BOOL LLInventoryPanel::postBuild()
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD);
+
+ mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
+
+ // create root folder
+ {
+ LLRect folder_rect(0,
+ 0,
+ getRect().getWidth(),
+ 0);
+ LLFolderView::Params p;
+ p.name = getName();
+ p.rect = folder_rect;
+ p.parent_panel = this;
+ mFolders = LLUICtrlFactory::create<LLFolderView>(p);
+ mFolders->setAllowMultiSelect(mAllowMultiSelect);
+ }
+
+ mCommitCallbackRegistrar.popScope();
+
+ mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);
+
+ // scroller
+ {
+ LLRect scroller_view_rect = getRect();
+ scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ LLScrollContainer::Params p;
+ p.name("Inventory Scroller");
+ p.rect(scroller_view_rect);
+ p.follows.flags(FOLLOWS_ALL);
+ p.reserve_scroll_corner(true);
+ p.tab_stop(true);
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+ }
+ addChild(mScroller);
+ mScroller->addChild(mFolders);
+
+ mFolders->setScrollContainer(mScroller);
+
+ // set up the callbacks from the inventory we're viewing, and then
+ // build everything.
+ mInventoryObserver = new LLInventoryPanelObserver(this);
+ mInventory->addObserver(mInventoryObserver);
+
+ // determine the root folder, if any, so inventory contents show just the children
+ // of that folder (i.e. not including the folder itself).
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
+
+ if ("INVENTORY" == mStartFolderString)
+ {
+ mStartFolderID = gInventory.getRootFolderID();
+ }
+ else if ("LIBRARY" == mStartFolderString)
+ {
+ mStartFolderID = gInventory.getLibraryRootFolderID();
+ }
+ else
+ {
+ mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
+ }
+
+ // build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback
+ if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection)
+ {
+ rebuildViewsFor(mStartFolderID);
+ mHasInventoryConnection = true;
+ }
+
+ // bit of a hack to make sure the inventory is open.
+ mFolders->openFolder(preferred_type != LLFolderType::FT_NONE ? LLViewerFolderType::lookupNewCategoryName(preferred_type) : "My Inventory");
+
+ if (mSortOrderSetting != INHERIT_SORT_ORDER)
+ {
+ setSortOrder(gSavedSettings.getU32(mSortOrderSetting));
+ }
+ else
+ {
+ setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER));
+ }
+ mFolders->setSortOrder(mFolders->getFilter()->getSortOrder());
+
+ return TRUE;
+}
+
+LLInventoryPanel::~LLInventoryPanel()
+{
+ // should this be a global setting?
+ if (mFolders)
+ {
+ U32 sort_order = mFolders->getSortOrder();
+ if (mSortOrderSetting != INHERIT_SORT_ORDER)
+ {
+ gSavedSettings.setU32(mSortOrderSetting, sort_order);
+ }
+ }
+
+ // LLView destructor will take care of the sub-views.
+ mInventory->removeObserver(mInventoryObserver);
+ delete mInventoryObserver;
+ mScroller = NULL;
+}
+
+LLMemType mt(LLMemType::MTYPE_INVENTORY_FROM_XML); // ! BUG ! Should this be removed?
+void LLInventoryPanel::draw()
+{
+ // select the desired item (in case it wasn't loaded when the selection was requested)
+ mFolders->updateSelection();
+ LLPanel::draw();
+}
+
+LLInventoryFilter* LLInventoryPanel::getFilter()
+{
+ if (mFolders) return mFolders->getFilter();
+ return NULL;
+}
+
+void LLInventoryPanel::setFilterTypes(U64 filter_types, BOOL filter_for_categories)
+{
+ mFolders->getFilter()->setFilterTypes(filter_types, filter_for_categories);
+}
+
+void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
+{
+ mFolders->getFilter()->setFilterPermissions(filter_perm_mask);
+}
+
+void LLInventoryPanel::setFilterSubString(const std::string& string)
+{
+ mFolders->getFilter()->setFilterSubString(string);
+}
+
+void LLInventoryPanel::setSortOrder(U32 order)
+{
+ mFolders->getFilter()->setSortOrder(order);
+ if (mFolders->getFilter()->isModified())
+ {
+ mFolders->setSortOrder(order);
+ // try to keep selection onscreen, even if it wasn't to start with
+ mFolders->scrollToShowSelection();
+ }
+}
+
+void LLInventoryPanel::setSinceLogoff(BOOL sl)
+{
+ mFolders->getFilter()->setDateRangeLastLogoff(sl);
+}
+
+void LLInventoryPanel::setHoursAgo(U32 hours)
+{
+ mFolders->getFilter()->setHoursAgo(hours);
+}
+
+void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show)
+{
+ mFolders->getFilter()->setShowFolderState(show);
+}
+
+LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
+{
+ return mFolders->getFilter()->getShowFolderState();
+}
+
+static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh");
+
+void LLInventoryPanel::modelChanged(U32 mask)
+{
+ LLFastTimer t2(FTM_REFRESH);
+
+ bool handled = false;
+
+ // inventory just initialized, do complete build
+ if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection)
+ {
+ rebuildViewsFor(mStartFolderID);
+ mHasInventoryConnection = true;
+ return;
+ }
+
+ if(mask & LLInventoryObserver::LABEL)
+ {
+ handled = true;
+ // label change - empty out the display name for each object
+ // in this change set.
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ LLFolderViewItem* view = NULL;
+ LLInvFVBridge* bridge = NULL;
+ for (;id_it != id_end; ++id_it)
+ {
+ view = mFolders->getItemByID(*id_it);
+ if(view)
+ {
+ // request refresh on this item (also flags for filtering)
+ bridge = (LLInvFVBridge*)view->getListener();
+ if(bridge)
+ { // Clear the display name first, so it gets properly re-built during refresh()
+ bridge->clearDisplayName();
+ }
+ view->refresh();
+ }
+ }
+ }
+ if((mask & (LLInventoryObserver::STRUCTURE
+ | LLInventoryObserver::ADD
+ | LLInventoryObserver::REMOVE)) != 0)
+ {
+ handled = true;
+ // Record which folders are open by uuid.
+ LLInventoryModel* model = getModel();
+ if (model)
+ {
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ // sync view with model
+ LLInventoryObject* model_item = model->getObject(*id_it);
+ LLFolderViewItem* view_item = mFolders->getItemByID(*id_it);
+
+ if (model_item)
+ {
+ if (!view_item)
+ {
+ // this object was just created, need to build a view for it
+ if ((mask & LLInventoryObserver::ADD) != LLInventoryObserver::ADD)
+ {
+ llwarns << *id_it << " is in model but not in view, but ADD flag not set" << llendl;
+ }
+ buildNewViews(*id_it);
+
+ // select any newly created object
+ // that has the auto rename at top of folder
+ // root set
+ if(mFolders->getRoot()->needsAutoRename())
+ {
+ setSelection(*id_it, FALSE);
+ }
+ }
+ else
+ {
+ // this object was probably moved, check its parent
+ if ((mask & LLInventoryObserver::STRUCTURE) != LLInventoryObserver::STRUCTURE)
+ {
+ llwarns << *id_it << " is in model and in view, but STRUCTURE flag not set" << llendl;
+ }
+
+ LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
+
+ // added check against NULL for cases when Inventory panel contains startFolder.
+ // in this case parent is LLFolderView (LLInventoryPanel::mFolders) itself.
+ // this check is a fix for bug EXT-1859.
+ if (NULL != new_parent && view_item->getParentFolder() != new_parent)
+ {
+ view_item->getParentFolder()->extractItem(view_item);
+ view_item->addToFolder(new_parent, mFolders);
+ }
+/*
+ on the other side in case Inventory Panel has content of the any folder
+ it is possible that item moved to some folder which is absent in current
+ Panel. For ex. removing item (via moving to trash).
+ In this case we need to check if new parent is other then inventory start folder
+ and simply remove its View from the hierarchy.
+ See details in EXT-2098.
+*/
+ // So, let check if item was moved into folder out of this Inventory Panel.
+ else if (mStartFolderID.notNull() && NULL == new_parent && model_item->getParentUUID() != mStartFolderID)
+ {
+ view_item->getParentFolder()->extractItem(view_item);
+ }
+ }
+ }
+ else
+ {
+ if (view_item)
+ {
+ if ((mask & LLInventoryObserver::REMOVE) != LLInventoryObserver::REMOVE)
+ {
+ llwarns << *id_it << " is not in model but in view, but REMOVE flag not set" << llendl;
+ }
+ // item in view but not model, need to delete view
+ view_item->destroyView();
+ }
+ else
+ {
+ llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl;
+ }
+ }
+ }
+ }
+ }
+
+ if (!handled)
+ {
+ // it's a small change that only requires a refresh.
+ // *TODO: figure out a more efficient way to do the refresh
+ // since it is expensive on large inventories
+ mFolders->refresh();
+ }
+}
+
+
+void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
+{
+ LLFolderViewItem* old_view = NULL;
+
+ // get old LLFolderViewItem
+ old_view = mFolders->getItemByID(id);
+ if (old_view && id.notNull())
+ {
+ old_view->destroyView();
+ }
+
+ buildNewViews(id);
+}
+
+void LLInventoryPanel::buildNewViews(const LLUUID& id)
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS);
+ LLFolderViewItem* itemp = NULL;
+ LLInventoryObject* objectp = NULL;
+
+ // Don't add the start folder (the inventory panel will show contents
+ // beginning with the children of the starting folder, excluding the starting folder itself).
+ if (id != mStartFolderID)
+ {
+ objectp = gInventory.getObject(id);
+ if (objectp)
+ {
+ const LLUUID &parent_id = objectp->getParentUUID();
+ // If this item's parent is the starting folder, then just add it to the top level (recall that
+ // the starting folder isn't actually represented in the view, parent_folder would be NULL in
+ // this case otherwise).
+ LLFolderViewFolder* parent_folder = (parent_id == mStartFolderID ?
+ mFolders : (LLFolderViewFolder*)mFolders->getItemByID(parent_id));
+
+ // This item exists outside the inventory's hierarchy, so don't add it.
+ if (!parent_folder)
+ {
+ return;
+ }
+
+ if (objectp->getType() <= LLAssetType::AT_NONE ||
+ objectp->getType() >= LLAssetType::AT_COUNT)
+ {
+ lldebugs << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " <<
+ ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() << llendl;
+ return;
+ }
+
+ if (objectp->getType() == LLAssetType::AT_CATEGORY &&
+ objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)
+ {
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
+ objectp->getType(),
+ LLInventoryType::IT_CATEGORY,
+ this,
+ objectp->getUUID());
+
+ if (new_listener)
+ {
+ LLFolderViewFolder::Params p;
+ p.name = new_listener->getDisplayName();
+ p.icon = new_listener->getIcon();
+ p.root = mFolders;
+ p.listener = new_listener;
+ LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(p);
+
+ folderp->setItemSortOrder(mFolders->getSortOrder());
+ itemp = folderp;
+ }
+ }
+ else
+ {
+ // Build new view for item
+ LLInventoryItem* item = (LLInventoryItem*)objectp;
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
+ item->getActualType(),
+ item->getInventoryType(),
+ this,
+ item->getUUID(),
+ item->getFlags());
+
+ if (new_listener)
+ {
+ LLFolderViewItem::Params params;
+ params.name(new_listener->getDisplayName());
+ params.icon(new_listener->getIcon());
+ params.creation_date(new_listener->getCreationDate());
+ params.root(mFolders);
+ params.listener(new_listener);
+ params.rect(LLRect (0, 0, 0, 0));
+ itemp = LLUICtrlFactory::create<LLFolderViewItem> (params);
+ }
+ }
+
+ if (itemp)
+ {
+ itemp->addToFolder(parent_folder, mFolders);
+ }
+ }
+ }
+
+ // If this is a folder, add the children of the folder and recursively add any
+ // child folders.
+ if ((id == mStartFolderID) ||
+ (objectp && objectp->getType() == LLAssetType::AT_CATEGORY))
+ {
+ LLViewerInventoryCategory::cat_array_t* categories;
+ LLViewerInventoryItem::item_array_t* items;
+
+ mInventory->lockDirectDescendentArrays(id, categories, items);
+ if(categories)
+ {
+ S32 count = categories->count();
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLInventoryCategory* cat = categories->get(i);
+ buildNewViews(cat->getUUID());
+ }
+ }
+ if(items)
+ {
+ S32 count = items->count();
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLInventoryItem* item = items->get(i);
+ buildNewViews(item->getUUID());
+ }
+ }
+ mInventory->unlockDirectDescendentArrays(id);
+ }
+}
+
+struct LLConfirmPurgeData
+{
+ LLUUID mID;
+ LLInventoryModel* mModel;
+};
+
+class LLIsNotWorn : public LLInventoryCollectFunctor
+{
+public:
+ LLIsNotWorn() {}
+ virtual ~LLIsNotWorn() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+ {
+ return !gAgentWearables.isWearingItem(item->getUUID());
+ }
+};
+
+class LLOpenFolderByID : public LLFolderViewFunctor
+{
+public:
+ LLOpenFolderByID(const LLUUID& id) : mID(id) {}
+ virtual ~LLOpenFolderByID() {}
+ virtual void doFolder(LLFolderViewFolder* folder)
+ {
+ if (folder->getListener() && folder->getListener()->getUUID() == mID) folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+ virtual void doItem(LLFolderViewItem* item) {}
+protected:
+ const LLUUID& mID;
+};
+
+
+void LLInventoryPanel::openSelected()
+{
+ LLFolderViewItem* folder_item = mFolders->getCurSelectedItem();
+ if(!folder_item) return;
+ LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener();
+ if(!bridge) return;
+ bridge->openItem();
+}
+
+BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLView::handleHover(x, y, mask);
+ if(handled)
+ {
+ ECursorType cursor = getWindow()->getCursor();
+ if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
+ {
+ // replace arrow cursor with arrow and hourglass cursor
+ getWindow()->setCursor(UI_CURSOR_WORKING);
+ }
+ }
+ else
+ {
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+ }
+ return TRUE;
+}
+
+BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+
+ BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+
+ if (handled)
+ {
+ mFolders->setDragAndDropThisFrame();
+ }
+
+ return handled;
+}
+
+void LLInventoryPanel::onFocusLost()
+{
+ // inventory no longer handles cut/copy/paste/delete
+ if (LLEditMenuHandler::gEditMenuHandler == mFolders)
+ {
+ LLEditMenuHandler::gEditMenuHandler = NULL;
+ }
+
+ LLPanel::onFocusLost();
+}
+
+void LLInventoryPanel::onFocusReceived()
+{
+ // inventory now handles cut/copy/paste/delete
+ LLEditMenuHandler::gEditMenuHandler = mFolders;
+
+ LLPanel::onFocusReceived();
+}
+
+
+void LLInventoryPanel::openAllFolders()
+{
+ mFolders->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
+ mFolders->arrangeAll();
+}
+
+void LLInventoryPanel::openDefaultFolderForType(LLFolderType::EType type)
+{
+ LLUUID category_id = mInventory->findCategoryUUIDForType(type);
+ LLOpenFolderByID opener(category_id);
+ mFolders->applyFunctorRecursively(opener);
+}
+
+void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus)
+{
+ // Don't select objects in COF (e.g. to prevent refocus when items are worn).
+ const LLInventoryObject *obj = gInventory.getObject(obj_id);
+ if (obj && obj->getParentUUID() == LLAppearanceManager::getCOF())
+ {
+ return;
+ }
+ mFolders->setSelectionByID(obj_id, take_keyboard_focus);
+}
+
+void LLInventoryPanel::clearSelection()
+{
+ mFolders->clearSelection();
+}
+
+void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action)
+{
+ LLFolderView* fv = getRootFolder();
+ if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename
+ {
+ fv->setNeedsAutoRename(FALSE);
+ if (items.size()) // new asset is visible and selected
+ {
+ fv->startRenamingSelectedItem();
+ }
+ }
+ // Seraph - Put determineFolderType in here for ensemble typing?
+}
+
+//----------------------------------------------------------------------------
+
+void LLInventoryPanel::doToSelected(const LLSD& userdata)
+{
+ mFolders->doToSelected(&gInventory, userdata);
+}
+
+void LLInventoryPanel::doCreate(const LLSD& userdata)
+{
+ menu_create_inventory_item(mFolders, LLFolderBridge::sSelf, userdata);
+}
+
+bool LLInventoryPanel::beginIMSession()
+{
+ std::set<LLUUID> selected_items;
+ mFolders->getSelectionList(selected_items);
+
+ std::string name;
+ static int session_num = 1;
+
+ LLDynamicArray<LLUUID> members;
+ EInstantMessage type = IM_SESSION_CONFERENCE_START;
+
+ std::set<LLUUID>::const_iterator iter;
+ for (iter = selected_items.begin(); iter != selected_items.end(); iter++)
+ {
+
+ LLUUID item = *iter;
+ LLFolderViewItem* folder_item = mFolders->getItemByID(item);
+
+ if(folder_item)
+ {
+ LLFolderViewEventListener* fve_listener = folder_item->getListener();
+ if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY))
+ {
+
+ LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener();
+ if(!bridge) return true;
+ LLViewerInventoryCategory* cat = bridge->getCategory();
+ if(!cat) return true;
+ name = cat->getName();
+ LLUniqueBuddyCollector is_buddy;
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendentsIf(bridge->getUUID(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_buddy);
+ S32 count = item_array.count();
+ if(count > 0)
+ {
+ LLFloaterReg::showInstance("communicate");
+ // create the session
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ LLUUID id;
+ for(S32 i = 0; i < count; ++i)
+ {
+ id = item_array.get(i)->getCreatorUUID();
+ if(at.isBuddyOnline(id))
+ {
+ members.put(id);
+ }
+ }
+ }
+ }
+ else
+ {
+ LLFolderViewItem* folder_item = mFolders->getItemByID(item);
+ if(!folder_item) return true;
+ LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener();
+
+ if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
+ {
+ LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID());
+
+ if (inv_item)
+ {
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ LLUUID id = inv_item->getCreatorUUID();
+
+ if(at.isBuddyOnline(id))
+ {
+ members.put(id);
+ }
+ }
+ } //if IT_CALLINGCARD
+ } //if !IT_CATEGORY
+ }
+ } //for selected_items
+
+ // the session_id is randomly generated UUID which will be replaced later
+ // with a server side generated number
+
+ if (name.empty())
+ {
+ name = llformat("Session %d", session_num++);
+ }
+
+ LLUUID session_id = gIMMgr->addSession(name, type, members[0], members);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+
+ return true;
+}
+
+bool LLInventoryPanel::attachObject(const LLSD& userdata)
+{
+ std::set<LLUUID> selected_items;
+ mFolders->getSelectionList(selected_items);
+
+ std::string joint_name = userdata.asString();
+ LLVOAvatar *avatarp = static_cast<LLVOAvatar*>(gAgent.getAvatarObject());
+ LLViewerJointAttachment* attachmentp = NULL;
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ iter != avatarp->mAttachmentPoints.end(); )
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ if (attachment->getName() == joint_name)
+ {
+ attachmentp = attachment;
+ break;
+ }
+ }
+ if (attachmentp == NULL)
+ {
+ return true;
+ }
+
+ for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin();
+ set_iter != selected_items.end();
+ ++set_iter)
+ {
+ const LLUUID &id = *set_iter;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id);
+ if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID()))
+ {
+ rez_attachment(item, attachmentp);
+ }
+ else if(item && item->isComplete())
+ {
+ // must be in library. copy it to our inventory and put it on.
+ LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp);
+ copy_inventory_item(gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ }
+ gFocusMgr.setKeyboardFocus(NULL);
+
+ return true;
+}
+
+
+//----------------------------------------------------------------------------
+
+// static DEBUG ONLY:
+void LLInventoryPanel::dumpSelectionInformation(void* user_data)
+{
+ LLInventoryPanel* iv = (LLInventoryPanel*)user_data;
+ iv->mFolders->dumpSelectionInformation();
+}
+
+BOOL LLInventoryPanel::getSinceLogoff()
+{
+ return mFolders->getFilter()->isSinceLogoff();
+}
+
+void example_param_block_usage()
+{
+ LLInventoryPanel::Params param_block;
+ param_block.name(std::string("inventory"));
+
+ param_block.sort_order_setting(LLInventoryPanel::RECENTITEMS_SORT_ORDER);
+ param_block.allow_multi_select(true);
+ param_block.filter(LLInventoryPanel::Filter()
+ .sort_order(1)
+ .types(0xffff0000));
+ param_block.inventory(&gInventory);
+ param_block.has_border(true);
+
+ LLUICtrlFactory::create<LLInventoryPanel>(param_block);
+
+ param_block = LLInventoryPanel::Params();
+ param_block.name(std::string("inventory"));
+
+ //LLSD param_block_sd;
+ //param_block_sd["sort_order_setting"] = LLInventoryPanel::RECENTITEMS_SORT_ORDER;
+ //param_block_sd["allow_multi_select"] = true;
+ //param_block_sd["filter"]["sort_order"] = 1;
+ //param_block_sd["filter"]["types"] = (S32)0xffff0000;
+ //param_block_sd["has_border"] = true;
+
+ //LLInitParam::LLSDParser(param_block_sd).parse(param_block);
+
+ LLUICtrlFactory::create<LLInventoryPanel>(param_block);
+}
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h new file mode 100644 index 0000000000..9f74fad5c1 --- /dev/null +++ b/indra/newview/llinventorypanel.h @@ -0,0 +1,206 @@ +/** + * @file llinventorypanel.h + * @brief LLInventoryPanel + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYPANEL_H +#define LL_LLINVENTORYPANEL_H + +#include "llassetstorage.h" +#include "lldarray.h" +#include "llfloater.h" +#include "llinventory.h" +#include "llinventoryfilter.h" +#include "llfolderview.h" +#include "llinventorymodel.h" +#include "lluictrlfactory.h" +#include <set> + +class LLFolderViewItem; +class LLInventoryFilter; +class LLInventoryModel; +class LLInvFVBridge; +class LLInventoryFVBridgeBuilder; +class LLMenuBarGL; +class LLCheckBoxCtrl; +class LLSpinCtrl; +class LLScrollContainer; +class LLTextBox; +class LLIconCtrl; +class LLSaveFolderState; +class LLFilterEditor; +class LLTabContainer; + +class LLInventoryPanel : public LLPanel +{ +public: + static const std::string DEFAULT_SORT_ORDER; + static const std::string RECENTITEMS_SORT_ORDER; + static const std::string INHERIT_SORT_ORDER; + + struct Filter : public LLInitParam::Block<Filter> + { + Optional<U32> sort_order; + Optional<U32> types; + Optional<std::string> search_string; + + Filter() + : sort_order("sort_order"), + types("types", 0xffffffff), + search_string("search_string") + {} + }; + + struct Params + : public LLInitParam::Block<Params, LLPanel::Params> + { + Optional<std::string> sort_order_setting; + Optional<LLInventoryModel*> inventory; + Optional<bool> allow_multi_select; + Optional<Filter> filter; + Optional<std::string> start_folder; + + Params() + : sort_order_setting("sort_order_setting"), + inventory("", &gInventory), + allow_multi_select("allow_multi_select", true), + filter("filter"), + start_folder("start_folder") + {} + }; + +protected: + LLInventoryPanel(const Params&); + friend class LLUICtrlFactory; + +public: + virtual ~LLInventoryPanel(); + + LLInventoryModel* getModel() { return mInventory; } + + BOOL postBuild(); + + // LLView methods + void draw(); + BOOL handleHover(S32 x, S32 y, MASK mask); + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + // LLUICtrl methods + /*virtual*/ void onFocusLost(); + /*virtual*/ void onFocusReceived(); + + // Call this method to set the selection. + void openAllFolders(); + void openDefaultFolderForType(LLFolderType::EType); + void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus); + void setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { if (mFolders) mFolders->setSelectCallback(cb); } + void clearSelection(); + LLInventoryFilter* getFilter(); + void setFilterTypes(U64 filter, BOOL filter_for_categories = FALSE); // if filter_for_categories is true, operate on folder preferred asset type + U32 getFilterTypes() const { return mFolders->getFilterTypes(); } + void setFilterPermMask(PermissionMask filter_perm_mask); + U32 getFilterPermMask() const { return mFolders->getFilterPermissions(); } + void setFilterSubString(const std::string& string); + const std::string getFilterSubString() { return mFolders->getFilterSubString(); } + void setSortOrder(U32 order); + U32 getSortOrder() { return mFolders->getSortOrder(); } + void setSinceLogoff(BOOL sl); + void setHoursAgo(U32 hours); + BOOL getSinceLogoff(); + + void setShowFolderState(LLInventoryFilter::EFolderShow show); + LLInventoryFilter::EFolderShow getShowFolderState(); + void setAllowMultiSelect(BOOL allow) { mFolders->setAllowMultiSelect(allow); } + // This method is called when something has changed about the inventory. + void modelChanged(U32 mask); + LLFolderView* getRootFolder() { return mFolders; } + LLScrollContainer* getScrollableContainer() { return mScroller; } + + void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); + + // Callbacks + void doToSelected(const LLSD& userdata); + void doCreate(const LLSD& userdata); + bool beginIMSession(); + bool attachObject(const LLSD& userdata); + + // DEBUG ONLY: + static void dumpSelectionInformation(void* user_data); + + void openSelected(); + void unSelectAll() { mFolders->setSelection(NULL, FALSE, FALSE); } + +protected: + // Given the id and the parent, build all of the folder views. + void rebuildViewsFor(const LLUUID& id); + virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719 + +protected: + LLInventoryModel* mInventory; + LLInventoryObserver* mInventoryObserver; + BOOL mAllowMultiSelect; + std::string mSortOrderSetting; + +//private: // Can not make these private - needed by llinventorysubtreepanel + LLFolderView* mFolders; + std::string mStartFolderString; + + /** + * Contains UUID of Inventory item from which hierarchy should be built. + * Can be set with the "start_folder" xml property. + * Default is LLUUID::null that means total Inventory hierarchy. + */ + LLUUID mStartFolderID; + LLScrollContainer* mScroller; + bool mHasInventoryConnection; + + /** + * Flag specified if default inventory hierarchy should be created in postBuild() + */ + bool mBuildDefaultHierarchy; + + LLUUID mRootInventoryItemUUID; + + /** + * Pointer to LLInventoryFVBridgeBuilder. + * + * It is set in LLInventoryPanel's constructor and can be overridden in derived classes with + * another implementation. + * Take into account it will not be deleted by LLInventoryPanel itself. + */ + const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder; + +}; + +#endif // LL_LLINVENTORYPANEL_H diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp index 4fd3b7bddc..bd6702a0b2 100644 --- a/indra/newview/lljoystickbutton.cpp +++ b/indra/newview/lljoystickbutton.cpp @@ -517,43 +517,52 @@ void LLJoystickCameraRotate::draw() LLGLSUIDefault gls_ui; getImageUnselected()->draw( 0, 0 ); + LLPointer<LLUIImage> image = getImageSelected(); if( mInTop ) { - drawRotatedImage( getImageSelected()->getImage(), 0 ); + drawRotatedImage( getImageSelected(), 0 ); } if( mInRight ) { - drawRotatedImage( getImageSelected()->getImage(), 1 ); + drawRotatedImage( getImageSelected(), 1 ); } if( mInBottom ) { - drawRotatedImage( getImageSelected()->getImage(), 2 ); + drawRotatedImage( getImageSelected(), 2 ); } if( mInLeft ) { - drawRotatedImage( getImageSelected()->getImage(), 3 ); + drawRotatedImage( getImageSelected(), 3 ); } } // Draws image rotated by multiples of 90 degrees -void LLJoystickCameraRotate::drawRotatedImage( LLTexture* image, S32 rotations ) +void LLJoystickCameraRotate::drawRotatedImage( LLPointer<LLUIImage> image, S32 rotations ) { S32 width = image->getWidth(); S32 height = image->getHeight(); - + LLTexture* texture = image->getImage(); + + /* + * Scale texture coordinate system + * to handle the different between image size and size of texture. + * If we will use default matrix, + * it may break texture mapping after rotation. + * see EXT-2023 Camera floater: arrows became shifted when pressed. + */ F32 uv[][2] = { - { 1.f, 1.f }, - { 0.f, 1.f }, + { (F32)width/texture->getWidth(), (F32)height/texture->getHeight() }, + { 0.f, (F32)height/texture->getHeight() }, { 0.f, 0.f }, - { 1.f, 0.f } + { (F32)width/texture->getWidth(), 0.f } }; - gGL.getTexUnit(0)->bind(image); + gGL.getTexUnit(0)->bind(texture); gGL.color4fv(UI_VERTEX_COLOR.mV); diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h index 8caef30fa4..4c657913b8 100644 --- a/indra/newview/lljoystickbutton.h +++ b/indra/newview/lljoystickbutton.h @@ -150,7 +150,7 @@ public: protected: F32 getOrbitRate(); virtual void updateSlop(); - void drawRotatedImage( LLTexture* image, S32 rotations ); + void drawRotatedImage( LLPointer<LLUIImage> image, S32 rotations ); protected: BOOL mInLeft; diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp index 319212f604..e0dc1b6f0f 100644 --- a/indra/newview/lllandmarkactions.cpp +++ b/indra/newview/lllandmarkactions.cpp @@ -49,6 +49,7 @@ #include "llstring.h" #include "llviewerinventory.h" #include "llviewerparcelmgr.h" +#include "llworldmapmessage.h" #include "llviewerwindow.h" #include "llwindow.h" #include "llworldmap.h" @@ -165,8 +166,7 @@ static void fetch_landmarks(LLInventoryModel::cat_array_t& cats, LLInventoryCollectFunctor& add) { // Look in "My Favorites" - LLUUID favorites_folder_id = - gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + const LLUUID favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); gInventory.collectDescendentsIf(favorites_folder_id, cats, items, @@ -174,8 +174,7 @@ static void fetch_landmarks(LLInventoryModel::cat_array_t& cats, add); // Look in "Landmarks" - LLUUID landmarks_folder_id = - gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + const LLUUID landmarks_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); gInventory.collectDescendentsIf(landmarks_folder_id, cats, items, @@ -287,7 +286,7 @@ void LLLandmarkActions::createLandmarkHere() LLAgentUI::buildLocationString(landmark_name, LLAgentUI::LOCATION_FORMAT_LANDMARK); LLAgentUI::buildLocationString(landmark_desc, LLAgentUI::LOCATION_FORMAT_FULL); - LLUUID folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); createLandmarkHere(landmark_name, landmark_desc, folder_id); } @@ -307,13 +306,13 @@ void LLLandmarkActions::getSLURLfromPosGlobal(const LLVector3d& global_pos, slur { U64 new_region_handle = to_region_handle(global_pos); - LLWorldMap::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseSLURL, + LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseSLURL, cb, global_pos, escaped, _2); - LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false); + LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false); } } @@ -324,18 +323,19 @@ void LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(const LLVector3d& gl if (sim_infop) { LLVector3 pos = sim_infop->getLocalPos(global_pos); - cb(sim_infop->mName, llround(pos.mV[VX]), llround(pos.mV[VY])); + std::string name = sim_infop->getName() ; + cb(name, llround(pos.mV[VX]), llround(pos.mV[VY])); } else { U64 new_region_handle = to_region_handle(global_pos); - LLWorldMap::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseNameAndCoords, + LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseNameAndCoords, cb, global_pos, _1); - LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false); + LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false); } } @@ -367,7 +367,8 @@ void LLLandmarkActions::onRegionResponseNameAndCoords(region_name_and_coords_cal if (sim_infop) { LLVector3 local_pos = sim_infop->getLocalPos(global_pos); - cb(sim_infop->mName, llround(local_pos.mV[VX]), llround(local_pos.mV[VY])); + std::string name = sim_infop->getName() ; + cb(name, llround(local_pos.mV[VX]), llround(local_pos.mV[VY])); } } diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp index 6f0b8a3c1e..2a1f42c3c4 100644 --- a/indra/newview/llloginhandler.cpp +++ b/indra/newview/llloginhandler.cpp @@ -56,7 +56,7 @@ bool LLLoginHandler::parseDirectLogin(std::string url) LLURI uri(url); parse(uri.queryMap()); - if (mWebLoginKey.isNull() || + if (/*mWebLoginKey.isNull() ||*/ mFirstName.empty() || mLastName.empty()) { @@ -71,7 +71,7 @@ bool LLLoginHandler::parseDirectLogin(std::string url) void LLLoginHandler::parse(const LLSD& queryMap) { - mWebLoginKey = queryMap["web_login_key"].asUUID(); + //mWebLoginKey = queryMap["web_login_key"].asUUID(); mFirstName = queryMap["first_name"].asString(); mLastName = queryMap["last_name"].asString(); @@ -165,7 +165,15 @@ void LLLoginHandler::parse(const LLSD& queryMap) bool LLLoginHandler::handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) -{ +{ + if (tokens.size() == 1 + && tokens[0].asString() == "show") + { + // We're using reg-in-client, so show the XUI login widgets + LLPanelLogin::showLoginWidgets(); + return true; + } + parse(query_map); //if we haven't initialized stuff yet, this is @@ -200,14 +208,15 @@ bool LLLoginHandler::handle(const LLSD& tokens, LLPanelLogin::setFields(mFirstName, mLastName, password); } - if (mWebLoginKey.isNull()) - { - LLPanelLogin::loadLoginPage(); - } - else - { - LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); - } + //if (mWebLoginKey.isNull()) + //{ + // LLPanelLogin::loadLoginPage(); + //} + //else + //{ + // LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); + //} + LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); } return true; } diff --git a/indra/newview/llloginhandler.h b/indra/newview/llloginhandler.h index d36ceaf3cc..ac4648761b 100644 --- a/indra/newview/llloginhandler.h +++ b/indra/newview/llloginhandler.h @@ -48,7 +48,9 @@ class LLLoginHandler : public LLCommandHandler std::string getFirstName() const { return mFirstName; } std::string getLastName() const { return mLastName; } - LLUUID getWebLoginKey() const { return mWebLoginKey; } + + // Web-based login unsupported + //LLUUID getWebLoginKey() const { return mWebLoginKey; } private: void parse(const LLSD& queryMap); @@ -56,7 +58,7 @@ private: private: std::string mFirstName; std::string mLastName; - LLUUID mWebLoginKey; + //LLUUID mWebLoginKey; }; extern LLLoginHandler gLoginHandler; diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 2153f77336..f1b3a37677 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -163,7 +163,7 @@ void LLManipTranslate::restoreGL() GLuint* d = new GLuint[rez*rez]; - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName()); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName(), true); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); while (rez >= 1) diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 1312949f54..63794be085 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -52,7 +52,7 @@ #include "llviewerinventory.h" #include "llviewermenu.h" #include "llviewerparcelmgr.h" -#include "llworldmap.h" +#include "llworldmapmessage.h" #include "llappviewer.h" #include "llviewercontrol.h" #include "llfloatermediabrowser.h" @@ -174,8 +174,6 @@ LLNavigationBar::LLNavigationBar() mSearchComboBox(NULL), mPurgeTPHistoryItems(false) { - setIsChrome(TRUE); - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_navigation_bar.xml"); // set a listener function for LoginComplete event @@ -395,14 +393,13 @@ void LLNavigationBar::onLocationSelection() // Resolve the region name to its global coordinates. // If resolution succeeds we'll teleport. - LLWorldMap::url_callback_t cb = boost::bind( + LLWorldMapMessage::url_callback_t cb = boost::bind( &LLNavigationBar::onRegionNameResponse, this, typed_location, region_name, local_coords, _1, _2, _3, _4); // connect the callback each time, when user enter new location to get real location of agent after teleport mTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> setTeleportFinishedCallback(boost::bind(&LLNavigationBar::onTeleportFinished, this, _1,typed_location)); - - LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false); + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false); } void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos, const std::string& typed_location) diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index d7a5ff289c..bcb4edd7c1 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -36,6 +36,7 @@ #include "lltrans.h" #include "llnearbychatbar.h" +#include "llspeakbutton.h" #include "llbottomtray.h" #include "llagent.h" #include "llgesturemgr.h" @@ -233,11 +234,11 @@ BOOL LLNearbyChatBar::postBuild() mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); mOutputMonitor->setVisible(FALSE); - mTalkBtn = getParent()->getChild<LLTalkButton>("talk"); + mSpeakBtn = getParent()->getChild<LLSpeakButton>("talk"); // Speak button should be initially disabled because // it takes some time between logging in to world and connecting to voice channel. - mTalkBtn->setEnabled(FALSE); + mSpeakBtn->setEnabled(FALSE); // Registering Chat Bar to receive Voice client status change notifications. gVoiceClient->addObserver(this); @@ -696,7 +697,7 @@ LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channe void LLNearbyChatBar::setPTTState(bool state) { - mTalkBtn->setSpeakBtnToggleState(state); + mSpeakBtn->setSpeakBtnToggleState(state); } void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) @@ -752,7 +753,7 @@ void LLNearbyChatBar::onChange(EStatusType status, const std::string &channelURI break; } - mTalkBtn->setEnabled(enable); + mSpeakBtn->setEnabled(enable); } // Creating the object registers with the dispatcher. diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index 0307eee7bf..aa25b6aa68 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -37,11 +37,14 @@ #include "llcombobox.h" #include "llgesturemgr.h" #include "llchat.h" -#include "llchiclet.h" #include "llvoiceclient.h" #include "lloutputmonitorctrl.h" #include "llspeakers.h" + +class LLSpeakButton; + + class LLGestureComboBox : public LLComboBox , public LLGestureManagerObserver @@ -125,7 +128,7 @@ protected: static S32 sLastSpecialChatChannel; LLLineEditor* mChatBox; - LLTalkButton* mTalkBtn; + LLSpeakButton* mSpeakBtn; LLOutputMonitorCtrl* mOutputMonitor; LLLocalSpeakerMgr* mSpeakerMgr; }; diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index b6b433c28f..4286582cdc 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -65,9 +65,15 @@ static LLDefaultChildRegistry::Register<LLNetMap> r1("net_map"); +const F32 LLNetMap::MAP_SCALE_MIN = 32; +const F32 LLNetMap::MAP_SCALE_MID = 1024; +const F32 LLNetMap::MAP_SCALE_MAX = 4096; + const F32 MAP_SCALE_INCREMENT = 16; -const F32 MAP_MIN_PICK_DIST = 4; -const F32 MAX_PRIM_RADIUS = 256.0f; // Don't try to draw giant mega-prims on the mini map +const F32 MAP_SCALE_ZOOM_FACTOR = 1.04f; // Zoom in factor per click of scroll wheel (4%) +const F32 MIN_DOT_RADIUS = 3.5f; +const F32 DOT_SCALE = 0.75f; +const F32 MIN_PICK_SCALE = 2.f; LLNetMap::LLNetMap (const Params & p) : LLUICtrl (p), @@ -89,6 +95,7 @@ LLNetMap::LLNetMap (const Params & p) mRotateMap(FALSE), mToolTipMsg() { + mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS); } LLNetMap::~LLNetMap() @@ -101,17 +108,18 @@ void LLNetMap::setScale( F32 scale ) if (mObjectImagep.notNull()) { - F32 half_width = (F32)(getRect().getWidth() / 2); - F32 half_height = (F32)(getRect().getHeight() / 2); - F32 radius = sqrt( half_width * half_width + half_height * half_height ); - F32 region_widths = (2.f*radius)/mScale; + F32 width = (F32)(getRect().getWidth()); + F32 height = (F32)(getRect().getHeight()); + F32 diameter = sqrt(width * width + height * height); + F32 region_widths = diameter / mScale; F32 meters = region_widths * LLWorld::getInstance()->getRegionWidthInMeters(); F32 num_pixels = (F32)mObjectImagep->getWidth(); - mObjectMapTPM = num_pixels/meters; - mObjectMapPixels = 2.f*radius; + mObjectMapTPM = num_pixels / meters; + mObjectMapPixels = diameter; } mPixelsPerMeter = mScale / REGION_WIDTH_METERS; + mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS); mUpdateNow = TRUE; } @@ -302,6 +310,7 @@ void LLNetMap::draw() LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); mClosestAgentToCursor.setNull(); F32 closest_dist = F32_MAX; + F32 min_pick_dist = mDotRadius * MIN_PICK_SCALE; // Draw avatars for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -345,10 +354,10 @@ void LLNetMap::draw() LLWorldMapView::drawAvatar( pos_map.mV[VX], pos_map.mV[VY], show_as_friend ? map_avatar_friend_color : map_avatar_color, - pos_map.mV[VZ]); + pos_map.mV[VZ], mDotRadius); F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y)); - if(dist_to_cursor < MAP_MIN_PICK_DIST && dist_to_cursor < closest_dist) + if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist) { closest_dist = dist_to_cursor; mClosestAgentToCursor = regionp->mMapAvatarIDs.get(i); @@ -378,10 +387,12 @@ void LLNetMap::draw() // Draw dot for self avatar position pos_global = gAgent.getPositionGlobal(); pos_map = globalPosToView(pos_global); - LLUIImagePtr you = LLWorldMapView::sAvatarYouSmallImage; - you->draw( - llround(pos_map.mV[VX]) - you->getWidth()/2, - llround(pos_map.mV[VY]) - you->getHeight()/2); + LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage; + S32 dot_width = llround(mDotRadius * 2.f); + you->draw(llround(pos_map.mV[VX] - mDotRadius), + llround(pos_map.mV[VY] - mDotRadius), + dot_width, + dot_width); // Draw frustum F32 meters_to_pixels = mScale/ LLWorld::getInstance()->getRegionWidthInMeters(); @@ -429,6 +440,12 @@ void LLNetMap::draw() LLUICtrl::draw(); } +void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLUICtrl::reshape(width, height, called_from_parent); + createObjectImage(); +} + LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos ) { LLVector3d relative_pos_global = global_pos - gAgent.getCameraPositionGlobal(); @@ -504,8 +521,12 @@ LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y ) BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks) { - // note that clicks are reversed from what you'd think - setScale(llclamp(mScale - clicks*MAP_SCALE_INCREMENT, MAP_SCALE_MIN, MAP_SCALE_MAX)); + // note that clicks are reversed from what you'd think: i.e. > 0 means zoom out, < 0 means zoom in + F32 scale = mScale; + + scale *= pow(MAP_SCALE_ZOOM_FACTOR, -clicks); + setScale(llclamp(scale, MAP_SCALE_MIN, MAP_SCALE_MAX)); + return TRUE; } @@ -567,9 +588,7 @@ void LLNetMap::renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U & LLVector3 local_pos; local_pos.setVec( pos - mObjectImageCenterGlobal ); - F32 radius_clamped = llmin(radius_meters, MAX_PRIM_RADIUS); - - S32 diameter_pixels = llround(2 * radius_clamped * mObjectMapTPM); + S32 diameter_pixels = llround(2 * radius_meters * mObjectMapTPM); renderPoint( local_pos, color, diameter_pixels ); } @@ -662,13 +681,13 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color, void LLNetMap::createObjectImage() { // Find the size of the side of a square that surrounds the circle that surrounds getRect(). - F32 half_width = (F32)(getRect().getWidth() / 2); - F32 half_height = (F32)(getRect().getHeight() / 2); - F32 radius = sqrt( half_width * half_width + half_height * half_height ); - S32 square_size = S32( 2 * radius ); + // ... which is, the diagonal of the rect. + F32 width = (F32)getRect().getWidth(); + F32 height = (F32)getRect().getHeight(); + S32 square_size = llround( sqrt(width*width + height*height) ); // Find the least power of two >= the minimum size. - const S32 MIN_SIZE = 32; + const S32 MIN_SIZE = 64; const S32 MAX_SIZE = 256; S32 img_size = MIN_SIZE; while( (img_size*2 < square_size ) && (img_size < MAX_SIZE) ) @@ -684,7 +703,7 @@ void LLNetMap::createObjectImage() U8* data = mObjectRawImagep->getData(); memset( data, 0, img_size * img_size * 4 ); mObjectImagep = LLViewerTextureManager::getLocalTexture( mObjectRawImagep.get(), FALSE); - setScale(mScale); } + setScale(mScale); mUpdateNow = TRUE; } diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index 5ebdd13384..7088ab3e70 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -70,9 +70,14 @@ protected: public: virtual ~LLNetMap(); + static const F32 MAP_SCALE_MIN; + static const F32 MAP_SCALE_MID; + static const F32 MAP_SCALE_MAX; + /*virtual*/ void draw(); /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); /*virtual*/ BOOL handleToolTip( S32 x, S32 y, MASK mask); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); void setScale( F32 scale ); void setRotateMap( BOOL b ) { mRotateMap = b; } @@ -94,16 +99,17 @@ private: void drawTracking( const LLVector3d& pos_global, const LLColor4& color, BOOL draw_arrow = TRUE); - - void createObjectImage(); + void createObjectImage(); + private: LLUIColor mBackgroundColor; F32 mScale; // Size of a region in pixels F32 mPixelsPerMeter; // world meters to map pixels F32 mObjectMapTPM; // texels per meter on map - F32 mObjectMapPixels; // Width of object map in pixels; + F32 mObjectMapPixels; // Width of object map in pixels + F32 mDotRadius; // Size of avatar markers F32 mTargetPanX; F32 mTargetPanY; F32 mCurPanX; diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index cd4e640ec4..23998a0e5d 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -53,7 +53,8 @@ typedef enum e_notification_type NT_GROUPCHAT, NT_NEARBYCHAT, NT_ALERT, - NT_ALERTMODAL + NT_ALERTMODAL, + NT_OFFER } ENotificationType; /** @@ -231,6 +232,27 @@ protected: bool mIsModal; }; +/** + * Handler for offers notices. + * It manages life time of offer notices. + */ +class LLOfferHandler : public LLSysHandler +{ +public: + LLOfferHandler(e_notification_type type, const LLSD& id); + virtual ~LLOfferHandler(); + + // base interface functions + virtual bool processNotification(const LLSD& notify); + +protected: + virtual void onDeleteToast(LLToast* toast); + virtual void initChannel(); + + // own handlers + void onRejectToast(LLUUID& id); +}; + } #endif diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 81a6b32917..1083cf3634 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -63,6 +63,7 @@ void LLNotificationManager::init() LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); LLNotificationChannel::buildChannel("IM Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytoast")); + LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer")); LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); @@ -70,6 +71,7 @@ void LLNotificationManager::init() LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); + LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD())); mNotifyHandlers["notifytip"] = boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); @@ -80,6 +82,7 @@ void LLNotificationManager::init() mNotifyHandlers["notifytoast"] = boost::shared_ptr<LLEventHandler>(new LLIMHandler(NT_IMCHAT, LLSD())); mNotifyHandlers["nearbychat"] = boost::shared_ptr<LLEventHandler>(new LLNearbyChatHandler(NT_NEARBYCHAT, LLSD())); + mNotifyHandlers["offer"] = boost::shared_ptr<LLEventHandler>(new LLOfferHandler(NT_OFFER, LLSD())); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp new file mode 100644 index 0000000000..75ef5208e7 --- /dev/null +++ b/indra/newview/llnotificationofferhandler.cpp @@ -0,0 +1,157 @@ +/** + * @file llnotificationofferhandler.cpp + * @brief Notification Handler Class for Simple Notifications and Notification Tips + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" // must be first include + +#include "llnotificationhandler.h" +#include "lltoastnotifypanel.h" +#include "llviewercontrol.h" +#include "llviewerwindow.h" +#include "llimview.h" +#include "llimfloater.h" +#include "llnotificationmanager.h" + +using namespace LLNotificationsUI; + +//-------------------------------------------------------------------------- +LLOfferHandler::LLOfferHandler(e_notification_type type, const LLSD& id) +{ + mType = type; + + // Getting a Channel for our notifications + mChannel = LLChannelManager::getInstance()->createNotificationChannel(); + mChannel->setControlHovering(true); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1)); +} + +//-------------------------------------------------------------------------- +LLOfferHandler::~LLOfferHandler() +{ +} + +//-------------------------------------------------------------------------- +void LLOfferHandler::initChannel() +{ + S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); + S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); + mChannel->init(channel_right_bound - channel_width, channel_right_bound); +} + +//-------------------------------------------------------------------------- +bool LLOfferHandler::processNotification(const LLSD& notify) +{ + if(!mChannel) + { + return false; + } + + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); + + if(!notification) + return false; + + // arrange a channel on a screen + if(!mChannel->getVisible()) + { + initChannel(); + } + + if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") + { + // add message to IM + LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, notification->getPayload()["from_id"]); + if (!LLIMMgr::instance().hasSession(session_id)) + { + // create session with faked type to avoid creating chicklets + session_id = LLIMMgr::instance().addSession( + notification->getSubstitutions()["NAME"], IM_NOTHING_SPECIAL, + notification->getPayload()["from_id"]); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } + } + LLIMMgr::instance().addMessage(session_id, LLUUID(), + notification->getSubstitutions()["NAME"], + notification->getMessage()); + + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); + + // send a signal to the counter manager + mNewNotificationSignal(); + } + else if (notify["sigtype"].asString() == "delete") + { + mChannel->killToastByNotificationID(notification->getID()); + } + + return true; +} + +//-------------------------------------------------------------------------- + +void LLOfferHandler::onDeleteToast(LLToast* toast) +{ + // send a signal to the counter manager + mDelNotificationSignal(); + + // send a signal to a listener to let him perform some action + // in this case listener is a SysWellWindow and it will remove a corresponding item from its list + mNotificationIDSignal(toast->getNotificationID()); +} + +//-------------------------------------------------------------------------- +void LLOfferHandler::onRejectToast(LLUUID& id) +{ + LLNotificationPtr notification = LLNotifications::instance().find(id); + + if (notification + && LLNotificationManager::getInstance()->getHandlerForNotification( + notification->getType()) == this) + { + LLNotifications::instance().cancel(notification); + } +} diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 070af432d6..dac7a4ca3a 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -37,6 +37,7 @@ #include "lltoastnotifypanel.h" #include "llviewercontrol.h" #include "llviewerwindow.h" +#include "llnotificationmanager.h" using namespace LLNotificationsUI; @@ -129,7 +130,9 @@ void LLScriptHandler::onRejectToast(LLUUID& id) { LLNotificationPtr notification = LLNotifications::instance().find(id); - if(notification) + if (notification + && LLNotificationManager::getInstance()->getHandlerForNotification( + notification->getType()) == this) { LLNotifications::instance().cancel(notification); } diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index ea528a1df8..9d591ef43d 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -51,7 +51,7 @@ // project includes #include "llagent.h" #include "llfloaterbulkpermission.h" -#include "llpanelinventory.h" +#include "llpanelobjectinventory.h" #include "llpreviewscript.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -59,6 +59,7 @@ #include "lltoolcomp.h" #include "lltoolmgr.h" #include "lltrans.h" +#include "llviewerassettype.h" #include "llviewerobject.h" #include "llviewerregion.h" #include "llviewerwindow.h" @@ -89,14 +90,14 @@ BOOL LLPanelContents::postBuild() childSetAction("button new script",&LLPanelContents::onClickNewScript, this); childSetAction("button permissions",&LLPanelContents::onClickPermissions, this); - mPanelInventory = getChild<LLPanelInventory>("contents_inventory"); + mPanelInventoryObject = getChild<LLPanelObjectInventory>("contents_inventory"); return TRUE; } LLPanelContents::LLPanelContents() : LLPanel(), - mPanelInventory(NULL) + mPanelInventoryObject(NULL) { } @@ -139,9 +140,9 @@ void LLPanelContents::refresh() LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(children_ok); getState(object); - if (mPanelInventory) + if (mPanelInventoryObject) { - mPanelInventory->refresh(); + mPanelInventoryObject->refresh(); } } @@ -167,7 +168,7 @@ void LLPanelContents::onClickNewScript(void *userdata) PERM_NONE, PERM_MOVE | PERM_TRANSFER); std::string desc; - LLAssetType::generateDescriptionFor(LLAssetType::AT_LSL_TEXT, desc); + LLViewerAssetType::generateDescriptionFor(LLAssetType::AT_LSL_TEXT, desc); LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem( LLUUID::null, diff --git a/indra/newview/llpanelcontents.h b/indra/newview/llpanelcontents.h index bab980b524..14256845a6 100644 --- a/indra/newview/llpanelcontents.h +++ b/indra/newview/llpanelcontents.h @@ -35,9 +35,14 @@ #include "v3math.h" #include "llpanel.h" +#include "llinventory.h" +#include "lluuid.h" +#include "llmap.h" +#include "llviewerobject.h" +#include "llvoinventorylistener.h" class LLButton; -class LLPanelInventory; +class LLPanelObjectInventory; class LLViewerObject; class LLCheckBoxCtrl; class LLSpinCtrl; @@ -70,7 +75,7 @@ protected: void getState(LLViewerObject *object); public: - LLPanelInventory* mPanelInventory; + LLPanelObjectInventory* mPanelInventoryObject; }; -#endif +#endif // LL_LLPANELCONTENTS_H diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 10f015774a..61f2396168 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -291,6 +291,7 @@ void LLPanelGroup::update(LLGroupChange gc) if(gdatap) { childSetValue("group_name", gdatap->mName); + childSetToolTip("group_name",gdatap->mName); LLButton* btn_join = getChild<LLButton>("btn_join"); LLUICtrl* join_text = getChild<LLUICtrl>("join_cost_text"); @@ -337,7 +338,10 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); if(gdatap) + { childSetValue("group_name", gdatap->mName); + childSetToolTip("group_name",gdatap->mName); + } LLButton* button_apply = findChild<LLButton>("btn_apply"); LLButton* button_refresh = findChild<LLButton>("btn_refresh"); diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 0ce85818dd..22138a81ec 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -38,6 +38,7 @@ #include "llinventory.h" #include "llviewerinventory.h" +#include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "llfloaterinventory.h" #include "llagent.h" diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index fe01fc6307..f94a59ecef 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -35,6 +35,7 @@ #include "llpanellandmarkinfo.h" #include "llcombobox.h" +#include "lliconctrl.h" #include "lllineeditor.h" #include "lltextbox.h" #include "lltexteditor.h" @@ -58,6 +59,11 @@ static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats); static LLRegisterPanelClassWrapper<LLPanelLandmarkInfo> t_landmark_info("panel_landmark_info"); +// Statics for textures filenames +static std::string icon_pg; +static std::string icon_m; +static std::string icon_r; + LLPanelLandmarkInfo::LLPanelLandmarkInfo() : LLPanelPlaceInfo() {} @@ -79,6 +85,10 @@ BOOL LLPanelLandmarkInfo::postBuild() mNotesEditor = getChild<LLTextEditor>("notes_editor"); mFolderCombo = getChild<LLComboBox>("folder_combo"); + icon_pg = getString("icon_PG"); + icon_m = getString("icon_M"); + icon_r = getString("icon_R"); + return TRUE; } @@ -101,9 +111,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type) LLPanel* landmark_info_panel = getChild<LLPanel>("landmark_info_panel"); bool is_info_type_create_landmark = type == CREATE_LANDMARK; - bool is_info_type_landmark = type == LANDMARK; - landmark_info_panel->setVisible(is_info_type_landmark); + landmark_info_panel->setVisible(type == LANDMARK); getChild<LLTextBox>("folder_label")->setVisible(is_info_type_create_landmark); mFolderCombo->setVisible(is_info_type_create_landmark); @@ -136,6 +145,24 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data) { LLPanelPlaceInfo::processParcelInfo(parcel_data); + // HACK: Flag 0x2 == adult region, + // Flag 0x1 == mature region, otherwise assume PG + if (parcel_data.flags & 0x2) + { + mMaturityRatingIcon->setValue(icon_r); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_ADULT)); + } + else if (parcel_data.flags & 0x1) + { + mMaturityRatingIcon->setValue(icon_m); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_MATURE)); + } + else + { + mMaturityRatingIcon->setValue(icon_pg); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG)); + } + S32 region_x; S32 region_y; S32 region_z; @@ -327,7 +354,7 @@ void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id) LLStringUtil::replaceChar(desc, '\n', ' '); // If no folder chosen use the "Landmarks" folder. LLLandmarkActions::createLandmarkHere(name, desc, - folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK)); + folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK)); } // static @@ -362,7 +389,7 @@ void LLPanelLandmarkInfo::populateFoldersList() mFolderCombo->removeall(); // Put the "Landmarks" folder first in list. - LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); const LLViewerInventoryCategory* cat = gInventory.getCategory(landmarks_id); if (!cat) { @@ -394,7 +421,7 @@ static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right) static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats) { - LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); // Add descendent folders of the "Landmarks" category. LLInventoryModel::item_array_t items; // unused @@ -407,7 +434,7 @@ static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats) is_category); // Add the "My Favorites" category. - LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id); if (!favorites_cat) { diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 34c146826f..ce1a7f98df 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -47,6 +47,7 @@ #include "lldndbutton.h" #include "llfloaterworldmap.h" #include "llfolderviewitem.h" +#include "llinventorypanel.h" #include "llinventorysubtreepanel.h" #include "lllandmarkactions.h" #include "llplacesinventorybridge.h" @@ -100,6 +101,8 @@ BOOL LLLandmarksPanel::postBuild() initLandmarksInventroyPanel(); initMyInventroyPanel(); initLibraryInventroyPanel(); + getChild<LLAccordionCtrlTab>("tab_favorites")->setDisplayChildren(true); + getChild<LLAccordionCtrlTab>("tab_landmarks")->setDisplayChildren(true); gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this); return TRUE; @@ -264,7 +267,7 @@ LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const return NULL; } -LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem () const +LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const { return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL; } @@ -421,6 +424,7 @@ void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLIn mAccordionTabs.push_back(accordion_tab); accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list)); + accordion_tab->setDisplayChildren(false); } void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list) @@ -495,6 +499,7 @@ void LLLandmarksPanel::updateListCommands() // keep Options & Add Landmark buttons always enabled mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled); mListCommands->childSetEnabled(TRASH_BUTTON_NAME, trash_enabled); + mListCommands->childSetEnabled(OPTIONS_BUTTON_NAME,getCurSelectedItem() != NULL); } void LLLandmarksPanel::onActionsButtonClick() @@ -585,7 +590,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const menu_create_inventory_item(mCurrentSelectedList->getRootFolder(), dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD( "category"), gInventory.findCategoryUUIDForType( - LLAssetType::AT_LANDMARK)); + LLFolderType::FT_LANDMARK)); } } } @@ -617,21 +622,19 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) { - LLFolderView* landmarks_folder = mLandmarksInventoryPanel->getRootFolder(); - LLFolderView* fav_folder = mFavoritesInventoryPanel->getRootFolder(); + if(!mCurrentSelectedList) return; + + LLFolderView* root_folder = mCurrentSelectedList->getRootFolder(); std::string command_name = userdata.asString(); if ("expand_all" == command_name) { - landmarks_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); - fav_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); - landmarks_folder->arrangeAll(); - fav_folder->arrangeAll(); + root_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); + root_folder->arrangeAll(); } else if ("collapse_all" == command_name) { - landmarks_folder->closeAllFolders(); - fav_folder->closeAllFolders(); + root_folder->closeAllFolders(); } else if ( "sort_by_date" == command_name) { @@ -642,9 +645,6 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) } else { - if(!mCurrentSelectedList) return; - - LLFolderView* root_folder = mCurrentSelectedList->getRootFolder(); root_folder->doToSelected(&gInventory, userdata); } } @@ -830,17 +830,18 @@ bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) co // then ask LLFolderView permissions if (can_be_modified) { + LLFolderViewItem* selected = getCurSelectedItem(); if ("cut" == command_name) { can_be_modified = mCurrentSelectedList->getRootFolder()->canCut(); } else if ("rename" == command_name) { - can_be_modified = getCurSelectedItem()->getListener()->isItemRenameable(); + can_be_modified = selected? selected->getListener()->isItemRenameable() : false; } else if ("delete" == command_name) { - can_be_modified = getCurSelectedItem()->getListener()->isItemRemovable(); + can_be_modified = selected? selected->getListener()->isItemRemovable(): false; } else if("paste" == command_name) { diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index d54761ed59..745f9364c2 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -69,7 +69,7 @@ protected: bool isLandmarkSelected() const; bool isReceivedFolderSelected() const; LLLandmark* getCurSelectedLandmark() const; - LLFolderViewItem* getCurSelectedItem () const; + LLFolderViewItem* getCurSelectedItem() const; void updateSortOrder(LLInventoryPanel* panel, bool byDate); //LLRemoteParcelInfoObserver interface diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 24e76e2c6e..5d826f0a56 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -198,7 +198,16 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, //leave room for the login menu bar setRect(LLRect(0, rect.getHeight()-18, rect.getWidth(), 0)); #endif - reshape(rect.getWidth(), rect.getHeight()); + // Legacy login web page is hidden under the menu bar. + // Adjust reg-in-client web browser widget to not be hidden. + if (gSavedSettings.getBOOL("RegInClient")) + { + reshape(rect.getWidth(), rect.getHeight() - MENU_BAR_HEIGHT); + } + else + { + reshape(rect.getWidth(), rect.getHeight()); + } #if !USE_VIEWER_AUTH childSetPrevalidate("first_name_edit", LLLineEditor::prevalidatePrintableNoSpace); @@ -234,9 +243,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, childSetAction("connect_btn", onClickConnect, this); - setDefaultBtn("connect_btn"); - - // childSetAction("quit_btn", onClickQuit, this); + getChild<LLPanel>("login_widgets")->setDefaultBtn("connect_btn"); std::string channel = gSavedSettings.getString("VersionChannelName"); std::string version = llformat("%d.%d.%d (%d)", @@ -267,19 +274,20 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, web_browser->setTabStop(FALSE); // web_browser->navigateToLocalPage( "loading", "loading.html" ); - // make links open in external browser - web_browser->setOpenInExternalBrowser( true ); + if (gSavedSettings.getBOOL("RegInClient")) + { + // need to follow links in the internal browser + web_browser->setOpenInExternalBrowser( false ); - // force the size to be correct (XML doesn't seem to be sufficient to do this) (with some padding so the other login screen doesn't show through) - LLRect htmlRect = getRect(); -#if USE_VIEWER_AUTH - htmlRect.setCenterAndSize( getRect().getCenterX() - 2, getRect().getCenterY(), getRect().getWidth() + 6, getRect().getHeight()); -#else - htmlRect.setCenterAndSize( getRect().getCenterX() - 2, getRect().getCenterY() + 40, getRect().getWidth() + 6, getRect().getHeight() - 78 ); -#endif - web_browser->setRect( htmlRect ); - web_browser->reshape( htmlRect.getWidth(), htmlRect.getHeight(), TRUE ); - reshape( getRect().getWidth(), getRect().getHeight(), 1 ); + getChild<LLView>("login_widgets")->setVisible(false); + } + else + { + // make links open in external browser + web_browser->setOpenInExternalBrowser( true ); + + reshapeBrowser(); + } // kick off a request to grab the url manually gResponsePtr = LLIamHereLogin::build( this ); @@ -297,6 +305,27 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, } +// force the size to be correct (XML doesn't seem to be sufficient to do this) +// (with some padding so the other login screen doesn't show through) +void LLPanelLogin::reshapeBrowser() +{ + LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html"); + LLRect rect = gViewerWindow->getVirtualWindowRect(); + LLRect html_rect; +#if USE_VIEWER_AUTH + html_rect.setCenterAndSize( + rect.getCenterX() - 2, rect.getCenterY(), + rect.getWidth() + 6, rect.getHeight()); +#else + html_rect.setCenterAndSize( + rect.getCenterX() - 2, rect.getCenterY() + 40, + rect.getWidth() + 6, rect.getHeight() - 78 ); +#endif + web_browser->setRect( html_rect ); + web_browser->reshape( html_rect.getWidth(), html_rect.getHeight(), TRUE ); + reshape( rect.getWidth(), rect.getHeight(), 1 ); +} + void LLPanelLogin::setSiteIsAlive( bool alive ) { LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html"); @@ -384,10 +413,14 @@ void LLPanelLogin::draw() if ( mHtmlAvailable ) { #if !USE_VIEWER_AUTH - // draw a background box in black - gl_rect_2d( 0, height - 264, width, 264, LLColor4( 0.0f, 0.0f, 0.0f, 1.f ) ); - // draw the bottom part of the background image - just the blue background to the native client UI - mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight()); + if (getChild<LLView>("login_widgets")->getVisible()) + { + // draw a background box in black + gl_rect_2d( 0, height - 264, width, 264, LLColor4::black ); + // draw the bottom part of the background image + // just the blue background to the native client UI + mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight()); + } #endif } else @@ -418,12 +451,6 @@ BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask) return TRUE; } - if (KEY_RETURN == key && MASK_NONE == mask) - { - // let the panel handle UICtrl processing: calls onClickConnect() - return LLPanel::handleKeyHere(key, mask); - } - return LLPanel::handleKeyHere(key, mask); } @@ -483,6 +510,19 @@ void LLPanelLogin::giveFocus() #endif } +// static +void LLPanelLogin::showLoginWidgets() +{ + sInstance->childSetVisible("login_widgets", true); + LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html"); + web_browser->setOpenInExternalBrowser( true ); + sInstance->reshapeBrowser(); + // *TODO: Append all the usual login parameters, like first_login=Y etc. + std::string splash_screen_url = sInstance->getString("real_url"); + web_browser->navigateTo( splash_screen_url, "text/html" ); + LLUICtrl* first_name_edit = sInstance->getChild<LLUICtrl>("first_name_edit"); + first_name_edit->setFocus(TRUE); +} // static void LLPanelLogin::show(const LLRect &rect, @@ -797,8 +837,17 @@ void LLPanelLogin::loadLoginPage() LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html"); - // navigate to the "real" page - web_browser->navigateTo( oStr.str(), "text/html" ); + // navigate to the "real" page + if (gSavedSettings.getBOOL("RegInClient")) + { + web_browser->setFocus(TRUE); + login_page = sInstance->getString("reg_in_client_url"); + web_browser->navigateTo(login_page, "text/html"); + } + else + { + web_browser->navigateTo( oStr.str(), "text/html" ); + } } void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event) @@ -883,22 +932,6 @@ void LLPanelLogin::onClickNewAccount(void*) } -// *NOTE: This function is dead as of 2008 August. I left it here in case -// we suddenly decide to put the Quit button back. JC -// static -void LLPanelLogin::onClickQuit(void*) -{ - if (sInstance && sInstance->mCallback) - { - // tell the responder we're not here anymore - if ( gResponsePtr ) - gResponsePtr->setParent( 0 ); - - sInstance->mCallback(1, sInstance->mCallbackData); - } -} - - // static void LLPanelLogin::onClickVersion(void*) { diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 5692b8d345..acb2001c22 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -56,6 +56,10 @@ public: virtual void draw(); virtual void setFocus( BOOL b ); + // Show the XUI first name, last name, and password widgets. They are + // hidden on startup for reg-in-client + static void showLoginWidgets(); + static void show(const LLRect &rect, BOOL show_server, void (*callback)(S32 option, void* user_data), void* callback_data); @@ -86,10 +90,10 @@ public: /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); private: + void reshapeBrowser(); static void onClickConnect(void*); static void onClickNewAccount(void*); // static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response); - static void onClickQuit(void*); static void onClickVersion(void*); static void onClickForgotPassword(void*); static void onPassKey(LLLineEditor* caller, void* user_data); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp new file mode 100644 index 0000000000..15a75cb930 --- /dev/null +++ b/indra/newview/llpanelmaininventory.cpp @@ -0,0 +1,1025 @@ +/**
+ * @file llsidepanelmaininventory.cpp
+ * @brief Implementation of llsidepanelmaininventory.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llpanelmaininventory.h"
+
+#include "lldndbutton.h"
+#include "llfilepicker.h"
+#include "llfloaterinventory.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorypanel.h"
+#include "llfiltereditor.h"
+#include "llfloaterreg.h"
+#include "llpreviewtexture.h"
+#include "llscrollcontainer.h"
+#include "llsdserialize.h"
+#include "llspinctrl.h"
+#include "lltooldraganddrop.h"
+#include "llviewermenu.h"
+#include "llviewertexturelist.h"
+
+static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory"); // Seraph is this redundant with constructor?
+
+void on_file_loaded_for_save(BOOL success,
+ LLViewerFetchedTexture *src_vi,
+ LLImageRaw* src,
+ LLImageRaw* aux_src,
+ S32 discard_level,
+ BOOL final,
+ void* userdata);
+
+///----------------------------------------------------------------------------
+/// LLFloaterInventoryFinder
+///----------------------------------------------------------------------------
+
+class LLFloaterInventoryFinder : public LLFloater
+{
+public:
+ LLFloaterInventoryFinder( LLPanelMainInventory* inventory_view);
+ virtual void draw();
+ /*virtual*/ BOOL postBuild();
+ void changeFilter(LLInventoryFilter* filter);
+ void updateElementsFromFilter();
+ BOOL getCheckShowEmpty();
+ BOOL getCheckSinceLogoff();
+
+ static void onTimeAgo(LLUICtrl*, void *);
+ static void onCheckSinceLogoff(LLUICtrl*, void *);
+ static void onCloseBtn(void* user_data);
+ static void selectAllTypes(void* user_data);
+ static void selectNoTypes(void* user_data);
+private:
+ LLPanelMainInventory* mPanelMainInventory;
+ LLSpinCtrl* mSpinSinceDays;
+ LLSpinCtrl* mSpinSinceHours;
+ LLInventoryFilter* mFilter;
+};
+
+///----------------------------------------------------------------------------
+/// LLPanelMainInventory
+///----------------------------------------------------------------------------
+
+LLPanelMainInventory::LLPanelMainInventory()
+ : LLPanel(),
+ mActivePanel(NULL),
+ mSavedFolderState(NULL),
+ mFilterText(""),
+ mMenuGearDefault(NULL),
+ mMenuAdd(NULL)
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_INIT);
+ // Menu Callbacks (non contex menus)
+ mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLPanelMainInventory::closeAllFolders, this));
+ mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
+ mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
+ mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLPanelMainInventory::doCreate, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow, this));
+ mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this));
+ mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this));
+ mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2));
+
+ // Controls
+ // *TODO: Just use persistant settings for each of these
+ U32 sort_order = gSavedSettings.getU32("InventorySortOrder");
+ BOOL sort_by_name = ! ( sort_order & LLInventoryFilter::SO_DATE );
+ BOOL sort_folders_by_name = ( sort_order & LLInventoryFilter::SO_FOLDERS_BY_NAME );
+ BOOL sort_system_folders_to_top = ( sort_order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP );
+
+ gSavedSettings.declareBOOL("Inventory.SortByName", sort_by_name, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("Inventory.SortByDate", !sort_by_name, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("Inventory.FoldersAlwaysByName", sort_folders_by_name, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("Inventory.SystemFoldersToTop", sort_system_folders_to_top, "Declared in code", FALSE);
+
+ mSavedFolderState = new LLSaveFolderState();
+ mSavedFolderState->setApply(FALSE);
+}
+
+BOOL LLPanelMainInventory::postBuild()
+{
+ gInventory.addObserver(this);
+
+ mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");
+ mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this));
+
+ //panel->getFilter()->markDefault();
+
+ // Set up the default inv. panel/filter settings.
+ mActivePanel = getChild<LLInventoryPanel>("All Items");
+ if (mActivePanel)
+ {
+ // "All Items" is the previous only view, so it gets the InventorySortOrder
+ mActivePanel->setSortOrder(gSavedSettings.getU32("InventorySortOrder"));
+ mActivePanel->getFilter()->markDefault();
+ mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2));
+ }
+ LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
+ if (recent_items_panel)
+ {
+ recent_items_panel->setSinceLogoff(TRUE);
+ recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE);
+ recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ recent_items_panel->getFilter()->markDefault();
+ recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2));
+ }
+
+ // Now load the stored settings from disk, if available.
+ std::ostringstream filterSaveName;
+ filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml");
+ llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName << llendl;
+ llifstream file(filterSaveName.str());
+ LLSD savedFilterState;
+ if (file.is_open())
+ {
+ LLSDSerialize::fromXML(savedFilterState, file);
+ file.close();
+
+ // Load the persistent "Recent Items" settings.
+ // Note that the "All Items" settings do not persist.
+ if(recent_items_panel)
+ {
+ if(savedFilterState.has(recent_items_panel->getFilter()->getName()))
+ {
+ LLSD recent_items = savedFilterState.get(
+ recent_items_panel->getFilter()->getName());
+ recent_items_panel->getFilter()->fromLLSD(recent_items);
+ }
+ }
+
+ }
+
+ mFilterEditor = getChild<LLFilterEditor>("inventory search editor");
+ if (mFilterEditor)
+ {
+ mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2));
+ }
+
+ // *TODO:Get the cost info from the server
+ const std::string upload_cost("10");
+ childSetLabelArg("Upload Image", "[COST]", upload_cost);
+ childSetLabelArg("Upload Sound", "[COST]", upload_cost);
+ childSetLabelArg("Upload Animation", "[COST]", upload_cost);
+ childSetLabelArg("Bulk Upload", "[COST]", upload_cost);
+
+ initListCommandsHandlers();
+ return TRUE;
+}
+
+void LLPanelMainInventory::initListCommandsHandlers()
+{
+ mListCommands = getChild<LLPanel>("bottom_panel");
+
+ mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
+ mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
+ mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
+ /*
+ mListCommands->getChild<LLButton>("add_btn")->setHeldDownCallback(boost::bind(&LLPanelMainInventory::onAddButtonHeldDown, this));
+ static const LLSD add_landmark_command("add_landmark");
+ mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddAction, this, add_landmark_command));
+ */
+
+ LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
+ trash_btn->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
+ , _4 // BOOL drop
+ , _5 // EDragAndDropType cargo_type
+ , _7 // EAcceptance* accept
+ ));
+
+ mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
+ mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
+ mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+
+}
+
+// Destroys the object
+LLPanelMainInventory::~LLPanelMainInventory( void )
+{
+ // Save the filters state.
+ LLSD filterRoot;
+ LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");
+ if (all_items_panel)
+ {
+ LLInventoryFilter* filter = all_items_panel->getFilter();
+ if (filter)
+ {
+ LLSD filterState;
+ filter->toLLSD(filterState);
+ filterRoot[filter->getName()] = filterState;
+ }
+ }
+
+ LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
+ if (recent_items_panel)
+ {
+ LLInventoryFilter* filter = recent_items_panel->getFilter();
+ if (filter)
+ {
+ LLSD filterState;
+ filter->toLLSD(filterState);
+ filterRoot[filter->getName()] = filterState;
+ }
+ }
+
+ std::ostringstream filterSaveName;
+ filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml");
+ llofstream filtersFile(filterSaveName.str());
+ if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile))
+ {
+ llwarns << "Could not write to filters save file " << filterSaveName << llendl;
+ }
+ else
+ filtersFile.close();
+
+ gInventory.removeObserver(this);
+ delete mSavedFolderState;
+}
+
+void LLPanelMainInventory::startSearch()
+{
+ // this forces focus to line editor portion of search editor
+ if (mFilterEditor)
+ {
+ mFilterEditor->focusFirstItem(TRUE);
+ }
+}
+
+BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask)
+{
+ LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL;
+ if (root_folder)
+ {
+ // first check for user accepting current search results
+ if (mFilterEditor
+ && mFilterEditor->hasFocus()
+ && (key == KEY_RETURN
+ || key == KEY_DOWN)
+ && mask == MASK_NONE)
+ {
+ // move focus to inventory proper
+ mActivePanel->setFocus(TRUE);
+ root_folder->scrollToShowSelection();
+ return TRUE;
+ }
+
+ if (mActivePanel->hasFocus() && key == KEY_UP)
+ {
+ startSearch();
+ }
+ }
+
+ return LLPanel::handleKeyHere(key, mask);
+
+}
+
+//----------------------------------------------------------------------------
+// menu callbacks
+
+void LLPanelMainInventory::doToSelected(const LLSD& userdata)
+{
+ getPanel()->getRootFolder()->doToSelected(&gInventory, userdata);
+}
+
+void LLPanelMainInventory::closeAllFolders()
+{
+ getPanel()->getRootFolder()->closeAllFolders();
+}
+
+void LLPanelMainInventory::newWindow()
+{
+ LLFloaterInventory::showAgentInventory();
+}
+
+void LLPanelMainInventory::doCreate(const LLSD& userdata)
+{
+ menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata);
+}
+
+void LLPanelMainInventory::resetFilters()
+{
+ LLFloaterInventoryFinder *finder = getFinder();
+ getActivePanel()->getFilter()->resetDefault();
+ if (finder)
+ {
+ finder->updateElementsFromFilter();
+ }
+
+ setFilterTextFromFilter();
+}
+
+void LLPanelMainInventory::setSortBy(const LLSD& userdata)
+{
+ std::string sort_field = userdata.asString();
+ if (sort_field == "name")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
+
+ gSavedSettings.setBOOL("Inventory.SortByName", TRUE );
+ gSavedSettings.setBOOL("Inventory.SortByDate", FALSE );
+ }
+ else if (sort_field == "date")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE );
+
+ gSavedSettings.setBOOL("Inventory.SortByName", FALSE );
+ gSavedSettings.setBOOL("Inventory.SortByDate", TRUE );
+ }
+ else if (sort_field == "foldersalwaysbyname")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ if ( order & LLInventoryFilter::SO_FOLDERS_BY_NAME )
+ {
+ order &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME;
+
+ gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", FALSE );
+ }
+ else
+ {
+ order |= LLInventoryFilter::SO_FOLDERS_BY_NAME;
+
+ gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", TRUE );
+ }
+ getActivePanel()->setSortOrder( order );
+ }
+ else if (sort_field == "systemfolderstotop")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ if ( order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP )
+ {
+ order &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
+
+ gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", FALSE );
+ }
+ else
+ {
+ order |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
+
+ gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE );
+ }
+ getActivePanel()->setSortOrder( order );
+ }
+}
+
+// static
+BOOL LLPanelMainInventory::filtersVisible(void* user_data)
+{
+ LLPanelMainInventory* self = (LLPanelMainInventory*)user_data;
+ if(!self) return FALSE;
+
+ return self->getFinder() != NULL;
+}
+
+void LLPanelMainInventory::onClearSearch()
+{
+ LLFloater *finder = getFinder();
+ if (mActivePanel)
+ {
+ mActivePanel->setFilterSubString(LLStringUtil::null);
+ mActivePanel->setFilterTypes(0xffffffff);
+ }
+
+ if (finder)
+ {
+ LLFloaterInventoryFinder::selectAllTypes(finder);
+ }
+
+ // re-open folders that were initially open
+ if (mActivePanel)
+ {
+ mSavedFolderState->setApply(TRUE);
+ mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ LLOpenFoldersWithSelection opener;
+ mActivePanel->getRootFolder()->applyFunctorRecursively(opener);
+ mActivePanel->getRootFolder()->scrollToShowSelection();
+ }
+}
+
+void LLPanelMainInventory::onFilterEdit(const std::string& search_string )
+{
+ if (search_string == "")
+ {
+ onClearSearch();
+ }
+ if (!mActivePanel)
+ {
+ return;
+ }
+
+ gInventory.startBackgroundFetch();
+
+ std::string uppercase_search_string = search_string;
+ LLStringUtil::toUpper(uppercase_search_string);
+ if (mActivePanel->getFilterSubString().empty() && uppercase_search_string.empty())
+ {
+ // current filter and new filter empty, do nothing
+ return;
+ }
+
+ // save current folder open state if no filter currently applied
+ if (!mActivePanel->getRootFolder()->isFilterModified())
+ {
+ mSavedFolderState->setApply(FALSE);
+ mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ }
+
+ // set new filter string
+ mActivePanel->setFilterSubString(uppercase_search_string);
+}
+
+
+ //static
+ BOOL LLPanelMainInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward)
+ {
+ LLPanelMainInventory* active_view = NULL;
+
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
+ {
+ LLPanelMainInventory* iv = dynamic_cast<LLPanelMainInventory*>(*iter);
+ if (iv)
+ {
+ if (gFocusMgr.childHasKeyboardFocus(iv))
+ {
+ active_view = iv;
+ break;
+ }
+ }
+ }
+
+ if (!active_view)
+ {
+ return FALSE;
+ }
+
+ std::string search_string(find_text);
+
+ if (search_string.empty())
+ {
+ return FALSE;
+ }
+
+ if (active_view->getPanel() &&
+ active_view->getPanel()->getRootFolder()->search(first_item, search_string, backward))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+void LLPanelMainInventory::onFilterSelected()
+{
+ // Find my index
+ mActivePanel = (LLInventoryPanel*)childGetVisibleTab("inventory filter tabs");
+
+ if (!mActivePanel)
+ {
+ return;
+ }
+ LLInventoryFilter* filter = mActivePanel->getFilter();
+ LLFloaterInventoryFinder *finder = getFinder();
+ if (finder)
+ {
+ finder->changeFilter(filter);
+ }
+ if (filter->isActive())
+ {
+ // If our filter is active we may be the first thing requiring a fetch so we better start it here.
+ gInventory.startBackgroundFetch();
+ }
+ setFilterTextFromFilter();
+}
+
+const std::string LLPanelMainInventory::getFilterSubString()
+{
+ return mActivePanel->getFilterSubString();
+}
+
+void LLPanelMainInventory::setFilterSubString(const std::string& string)
+{
+ mActivePanel->setFilterSubString(string);
+}
+
+BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ // Check to see if we are auto scrolling from the last frame
+ LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel();
+ BOOL needsToScroll = panel->getScrollableContainer()->autoScroll(x, y);
+ if(mFilterTabs)
+ {
+ if(needsToScroll)
+ {
+ mFilterTabs->startDragAndDropDelayTimer();
+ }
+ }
+
+ BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+
+ return handled;
+}
+
+void LLPanelMainInventory::changed(U32 mask)
+{
+}
+
+
+void LLPanelMainInventory::setFilterTextFromFilter()
+{
+ mFilterText = mActivePanel->getFilter()->getFilterText();
+}
+
+void LLPanelMainInventory::toggleFindOptions()
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE);
+ LLFloater *floater = getFinder();
+ if (!floater)
+ {
+ LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this);
+ mFinderHandle = finder->getHandle();
+ finder->openFloater();
+
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
+ if (parent_floater) // Seraph: Fix this, shouldn't be null even for sidepanel
+ parent_floater->addDependentFloater(mFinderHandle);
+ // start background fetch of folders
+ gInventory.startBackgroundFetch();
+ }
+ else
+ {
+ floater->closeFloater();
+ }
+}
+
+void LLPanelMainInventory::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
+{
+ getChild<LLInventoryPanel>("All Items")->setSelectCallback(cb);
+ getChild<LLInventoryPanel>("Recent Items")->setSelectCallback(cb);
+}
+
+void LLPanelMainInventory::onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action)
+{
+ updateListCommands();
+ panel->onSelectionChange(items, user_action);
+}
+
+///----------------------------------------------------------------------------
+/// LLFloaterInventoryFinder
+///----------------------------------------------------------------------------
+
+LLFloaterInventoryFinder* LLPanelMainInventory::getFinder()
+{
+ return (LLFloaterInventoryFinder*)mFinderHandle.get();
+}
+
+
+LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) :
+ LLFloater(LLSD()),
+ mPanelMainInventory(inventory_view),
+ mFilter(inventory_view->getPanel()->getFilter())
+{
+ LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_view_finder.xml", NULL);
+ updateElementsFromFilter();
+}
+
+
+void LLFloaterInventoryFinder::onCheckSinceLogoff(LLUICtrl *ctrl, void *user_data)
+{
+ LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data;
+ if (!self) return;
+
+ bool since_logoff= self->childGetValue("check_since_logoff");
+
+ if (!since_logoff &&
+ !( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) )
+ {
+ self->mSpinSinceHours->set(1.0f);
+ }
+}
+BOOL LLFloaterInventoryFinder::postBuild()
+{
+ const LLRect& viewrect = mPanelMainInventory->getRect();
+ setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight()));
+
+ childSetAction("All", selectAllTypes, this);
+ childSetAction("None", selectNoTypes, this);
+
+ mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago");
+ childSetCommitCallback("spin_hours_ago", onTimeAgo, this);
+
+ mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago");
+ childSetCommitCallback("spin_days_ago", onTimeAgo, this);
+
+ // mCheckSinceLogoff = getChild<LLSpinCtrl>("check_since_logoff");
+ childSetCommitCallback("check_since_logoff", onCheckSinceLogoff, this);
+
+ childSetAction("Close", onCloseBtn, this);
+
+ updateElementsFromFilter();
+ return TRUE;
+}
+void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data)
+{
+ LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data;
+ if (!self) return;
+
+ bool since_logoff=true;
+ if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() )
+ {
+ since_logoff = false;
+ }
+ self->childSetValue("check_since_logoff", since_logoff);
+}
+
+void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter)
+{
+ mFilter = filter;
+ updateElementsFromFilter();
+}
+
+void LLFloaterInventoryFinder::updateElementsFromFilter()
+{
+ if (!mFilter)
+ return;
+
+ // Get data needed for filter display
+ U32 filter_types = mFilter->getFilterTypes();
+ std::string filter_string = mFilter->getFilterSubString();
+ LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState();
+ U32 hours = mFilter->getHoursAgo();
+
+ // update the ui elements
+ setTitle(mFilter->getName());
+
+ childSetValue("check_animation", (S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION));
+
+ childSetValue("check_calling_card", (S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD));
+ childSetValue("check_clothing", (S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
+ childSetValue("check_gesture", (S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
+ childSetValue("check_landmark", (S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
+ childSetValue("check_notecard", (S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
+ childSetValue("check_object", (S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
+ childSetValue("check_script", (S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
+ childSetValue("check_sound", (S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND));
+ childSetValue("check_texture", (S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE));
+ childSetValue("check_snapshot", (S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT));
+ childSetValue("check_show_empty", show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS);
+ childSetValue("check_since_logoff", mFilter->isSinceLogoff());
+ mSpinSinceHours->set((F32)(hours % 24));
+ mSpinSinceDays->set((F32)(hours / 24));
+}
+
+void LLFloaterInventoryFinder::draw()
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_DRAW);
+ U32 filter = 0xffffffff;
+ BOOL filtered_by_all_types = TRUE;
+
+ if (!childGetValue("check_animation"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_ANIMATION);
+ filtered_by_all_types = FALSE;
+ }
+
+
+ if (!childGetValue("check_calling_card"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_clothing"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_WEARABLE);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_gesture"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_GESTURE);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_landmark"))
+
+
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_LANDMARK);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_notecard"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_object"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_OBJECT);
+ filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_script"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_LSL);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_sound"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_SOUND);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_texture"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_TEXTURE);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_snapshot"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!filtered_by_all_types)
+ {
+ // don't include folders in filter, unless I've selected everything
+ filter &= ~(0x1 << LLInventoryType::IT_CATEGORY);
+ }
+
+ // update the panel, panel will update the filter
+ mPanelMainInventory->getPanel()->setShowFolderState(getCheckShowEmpty() ?
+ LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ mPanelMainInventory->getPanel()->setFilterTypes(filter);
+ if (getCheckSinceLogoff())
+ {
+ mSpinSinceDays->set(0);
+ mSpinSinceHours->set(0);
+ }
+ U32 days = (U32)mSpinSinceDays->get();
+ U32 hours = (U32)mSpinSinceHours->get();
+ if (hours > 24)
+ {
+ days += hours / 24;
+ hours = (U32)hours % 24;
+ mSpinSinceDays->set((F32)days);
+ mSpinSinceHours->set((F32)hours);
+ }
+ hours += days * 24;
+ mPanelMainInventory->getPanel()->setHoursAgo(hours);
+ mPanelMainInventory->getPanel()->setSinceLogoff(getCheckSinceLogoff());
+ mPanelMainInventory->setFilterTextFromFilter();
+
+ LLPanel::draw();
+}
+
+BOOL LLFloaterInventoryFinder::getCheckShowEmpty()
+{
+ return childGetValue("check_show_empty");
+}
+
+BOOL LLFloaterInventoryFinder::getCheckSinceLogoff()
+{
+ return childGetValue("check_since_logoff");
+}
+
+void LLFloaterInventoryFinder::onCloseBtn(void* user_data)
+{
+ LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data;
+ finderp->closeFloater();
+}
+
+// static
+void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
+{
+ LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
+ if(!self) return;
+
+ self->childSetValue("check_animation", TRUE);
+ self->childSetValue("check_calling_card", TRUE);
+ self->childSetValue("check_clothing", TRUE);
+ self->childSetValue("check_gesture", TRUE);
+ self->childSetValue("check_landmark", TRUE);
+ self->childSetValue("check_notecard", TRUE);
+ self->childSetValue("check_object", TRUE);
+ self->childSetValue("check_script", TRUE);
+ self->childSetValue("check_sound", TRUE);
+ self->childSetValue("check_texture", TRUE);
+ self->childSetValue("check_snapshot", TRUE);
+}
+
+//static
+void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
+{
+ LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
+ if(!self) return;
+
+ self->childSetValue("check_animation", FALSE);
+ self->childSetValue("check_calling_card", FALSE);
+ self->childSetValue("check_clothing", FALSE);
+ self->childSetValue("check_gesture", FALSE);
+ self->childSetValue("check_landmark", FALSE);
+ self->childSetValue("check_notecard", FALSE);
+ self->childSetValue("check_object", FALSE);
+ self->childSetValue("check_script", FALSE);
+ self->childSetValue("check_sound", FALSE);
+ self->childSetValue("check_texture", FALSE);
+ self->childSetValue("check_snapshot", FALSE);
+}
+
+
+
+
+
+void LLPanelMainInventory::updateListCommands()
+{
+ bool trash_enabled = isActionEnabled("delete");
+
+ mListCommands->childSetEnabled("trash_btn", trash_enabled);
+}
+
+void LLPanelMainInventory::onGearButtonClick()
+{
+ showActionMenu(mMenuGearDefault,"options_gear_btn");
+}
+
+void LLPanelMainInventory::onAddButtonClick()
+{
+ showActionMenu(mMenuAdd,"add_btn");
+}
+
+void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
+{
+ if (menu)
+ {
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLView* spawning_view = getChild<LLView> (spawning_view_name);
+ S32 menu_x, menu_y;
+ //show menu in co-ordinates of panel
+ spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
+ menu_y += menu->getRect().getHeight();
+ LLMenuGL::showPopup(this, menu, menu_x, menu_y);
+ }
+}
+
+void LLPanelMainInventory::onTrashButtonClick()
+{
+ onClipboardAction("delete");
+}
+
+void LLPanelMainInventory::onClipboardAction(const LLSD& userdata)
+{
+ std::string command_name = userdata.asString();
+ getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name);
+}
+
+void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
+{
+ if (!isActionEnabled(userdata))
+ return;
+
+ const std::string command_name = userdata.asString();
+ if (command_name == "new_window")
+ {
+ newWindow();
+ }
+ if (command_name == "sort_by_name")
+ {
+ const LLSD arg = "name";
+ setSortBy(arg);
+ }
+ if (command_name == "sort_by_recent")
+ {
+ const LLSD arg = "date";
+ setSortBy(arg);
+ }
+ if (command_name == "show_filters")
+ {
+ toggleFindOptions();
+ }
+ if (command_name == "reset_filters")
+ {
+ resetFilters();
+ }
+ if (command_name == "close_folders")
+ {
+ closeAllFolders();
+ }
+ if (command_name == "empty_trash")
+ {
+ const std::string notification = "ConfirmEmptyTrash";
+ gInventory.emptyFolderType(notification, LLFolderType::FT_TRASH);
+ }
+ if (command_name == "empty_lostnfound")
+ {
+ const std::string notification = "ConfirmEmptyLostAndFound";
+ gInventory.emptyFolderType(notification, LLFolderType::FT_LOST_AND_FOUND);
+ }
+ if (command_name == "save_texture")
+ {
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+
+ const LLUUID& item_id = current_item->getListener()->getUUID();
+ LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES);
+ if (preview_texture)
+ {
+ preview_texture->openToSave();
+ }
+ }
+}
+
+BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
+{
+ const std::string command_name = userdata.asString();
+ if (command_name == "delete")
+ {
+ BOOL can_delete = FALSE;
+ LLFolderView *folder = getActivePanel()->getRootFolder();
+ if (folder)
+ {
+ can_delete = TRUE;
+ std::set<LLUUID> selection_set;
+ folder->getSelectionList(selection_set);
+ for (std::set<LLUUID>::iterator iter = selection_set.begin();
+ iter != selection_set.end();
+ ++iter)
+ {
+ const LLUUID &item_id = (*iter);
+ LLFolderViewItem *item = folder->getItemByID(item_id);
+ can_delete &= item->getListener()->isItemRemovable();
+ }
+ return can_delete;
+ }
+ return FALSE;
+ }
+ if (command_name == "save_texture")
+ {
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (current_item)
+ {
+ return (current_item->getListener()->getInventoryType() == LLInventoryType::IT_TEXTURE);
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
+{
+ *accept = ACCEPT_NO;
+
+ const bool is_enabled = isActionEnabled("delete");
+ if (is_enabled) *accept = ACCEPT_YES_MULTI;
+
+ if (is_enabled && drop)
+ {
+ onClipboardAction("delete");
+ }
+ return true;
+}
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h new file mode 100644 index 0000000000..29e9baa6cf --- /dev/null +++ b/indra/newview/llpanelmaininventory.h @@ -0,0 +1,145 @@ +/**
+ * @file llpanelmaininventory.h
+ * @brief llpanelmaininventory.h
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMAININVENTORY_H
+#define LL_LLPANELMAININVENTORY_H
+
+#include "llpanel.h"
+#include "llinventorymodel.h"
+#include "llfolderview.h"
+
+class LLFolderViewItem;
+class LLInventoryPanel;
+class LLSaveFolderState;
+class LLFilterEditor;
+class LLTabContainer;
+class LLFloaterInventoryFinder;
+class LLMenuGL;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLPanelMainInventory
+//
+// This is a panel used to view and control an agent's inventory,
+// including all the fixin's (e.g. AllItems/RecentItems tabs, filter floaters).
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLPanelMainInventory : public LLPanel, LLInventoryObserver
+{
+public:
+ friend class LLFloaterInventoryFinder;
+
+ LLPanelMainInventory();
+ ~LLPanelMainInventory();
+
+ BOOL postBuild();
+
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ // Inherited functionality
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
+ /*virtual*/ void changed(U32 mask);
+
+ LLInventoryPanel* getPanel() { return mActivePanel; }
+ LLInventoryPanel* getActivePanel() { return mActivePanel; }
+ const LLInventoryPanel* getActivePanel() const { return mActivePanel; }
+
+ const std::string& getFilterText() const { return mFilterText; }
+
+ void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);
+
+protected:
+ //
+ // Misc functions
+ //
+ void setFilterTextFromFilter();
+ void startSearch();
+
+ void toggleFindOptions();
+ void onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action);
+
+ static BOOL filtersVisible(void* user_data);
+ void onClearSearch();
+ static void onFoldersByName(void *user_data);
+ static BOOL checkFoldersByName(void *user_data);
+ void onFilterEdit(const std::string& search_string );
+ static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward);
+ void onFilterSelected();
+
+ const std::string getFilterSubString();
+ void setFilterSubString(const std::string& string);
+
+ // menu callbacks
+ void doToSelected(const LLSD& userdata);
+ void closeAllFolders();
+ void newWindow();
+ void doCreate(const LLSD& userdata);
+ void resetFilters();
+ void setSortBy(const LLSD& userdata);
+
+ // List Commands Handlers
+ void initListCommandsHandlers();
+ void updateListCommands();
+ void onGearButtonClick();
+ void onAddButtonClick();
+ void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+ void onTrashButtonClick();
+ void onClipboardAction(const LLSD& userdata);
+ BOOL isActionEnabled(const LLSD& command_name);
+ void onCustomAction(const LLSD& command_name);
+ bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
+
+
+private:
+ LLFloaterInventoryFinder* getFinder();
+
+ LLFilterEditor* mFilterEditor;
+ LLTabContainer* mFilterTabs;
+ LLHandle<LLFloater> mFinderHandle;
+ LLInventoryPanel* mActivePanel;
+ LLSaveFolderState* mSavedFolderState;
+
+ LLPanel* mListCommands;
+ LLMenuGL* mMenuGearDefault;
+ LLMenuGL* mMenuAdd;
+
+ std::string mFilterText;
+};
+
+#endif // LL_LLPANELMAININVENTORY_H
+
+
+
diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index a198499b47..5186a5888b 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -1,453 +1,480 @@ -/**
- * @file llpanelmediasettingsgeneral.cpp
- * @brief LLPanelMediaSettingsGeneral class implementation
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llagent.h"
-#include "llpanelmediasettingsgeneral.h"
-#include "llcombobox.h"
-#include "llcheckboxctrl.h"
-#include "llspinctrl.h"
-#include "lluictrlfactory.h"
-#include "llviewerwindow.h"
-#include "llviewermedia.h"
-#include "llsdutil.h"
-#include "llselectmgr.h"
-#include "llbutton.h"
-#include "lltexturectrl.h"
-#include "llurl.h"
-#include "llwindow.h"
-#include "llmediaentry.h"
-#include "llmediactrl.h"
-#include "llpanelcontents.h"
-#include "llpermissions.h"
-#include "llpluginclassmedia.h"
-#include "llfloatermediasettings.h"
-#include "llfloatertools.h"
-#include "lltrans.h"
-
-////////////////////////////////////////////////////////////////////////////////
-//
-LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() :
- mControls( NULL ),
- mAutoLoop( NULL ),
- mFirstClick( NULL ),
- mAutoZoom( NULL ),
- mAutoPlay( NULL ),
- mAutoScale( NULL ),
- mWidthPixels( NULL ),
- mHeightPixels( NULL ),
- mHomeURL( NULL ),
- mCurrentURL( NULL ),
- mParent( NULL ),
- mMediaEditable(false)
-{
- // build dialog from XML
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml");
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-BOOL LLPanelMediaSettingsGeneral::postBuild()
-{
- // connect member vars with UI widgets
- mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY );
- mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY );
- mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );
- mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY );
- mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY );
- mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY );
- mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
- mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY );
- mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY );
- mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY );
- mPreviewMedia = getChild<LLMediaCtrl>("preview_media");
-
- // watch commit action for HOME URL
- childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this);
- childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this);
- // interrogates controls and updates widgets as required
- updateMediaPreview();
- updateCurrentURL();
-
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral()
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::draw()
-{
- // housekeeping
- LLPanel::draw();
-
- // enable/disable pixel values image entry based on auto scale checkbox
- if ( mAutoScale->getValue().asBoolean() == false )
- {
- childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true );
- childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true );
- }
- else
- {
- childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false );
- childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false );
- };
-
- // enable/disable UI based on type of media
- bool reset_button_is_active = true;
- if( mPreviewMedia )
- {
- LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
- if( media_plugin )
- {
- // turn off volume (if we can) for preview. Note: this really only
- // works for QuickTime movies right now - no way to control the
- // volume of a flash app embedded in a page for example
- media_plugin->setVolume( 0 );
-
- // some controls are only appropriate for time or browser type plugins
- // so we selectively enable/disable them - need to do it in draw
- // because the information from plugins arrives assynchronously
- bool show_time_controls = media_plugin->pluginSupportsMediaTime();
- if ( show_time_controls )
- {
- childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false );
- reset_button_is_active = false;
- childSetEnabled( "current_url_label", false );
- childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true );
- }
- else
- {
- childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true );
- reset_button_is_active = true;
- childSetEnabled( "current_url_label", true );
- childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false );
- };
- };
- };
-
- // current URL can change over time.
-// updateCurrentURL();
-
- LLPermissions perm;
- bool user_can_press_reset = mMediaEditable;
-
- // several places modify this widget so we must collect states in one place
- if ( reset_button_is_active )
- {
- // user has perms to press reset button and it is active
- if ( user_can_press_reset )
- {
- childSetEnabled( "current_url_reset_btn", true );
- }
- // user does not has perms to press reset button and it is active
- else
- {
- childSetEnabled( "current_url_reset_btn", false );
- };
- }
- else
- // reset button is inactive so we just slam it to off - other states don't matter
- {
- childSetEnabled( "current_url_reset_btn", false );
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
-{
- LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
- self->mAutoLoop->clear();
- self->mAutoPlay->clear();
- self->mAutoScale->clear();
- self->mAutoZoom ->clear();
- self->mControls->clear();
- self->mCurrentURL->clear();
- self->mFirstClick->clear();
- self->mHeightPixels->clear();
- self->mHomeURL->clear();
- self->mWidthPixels->clear();
- self->mAutoLoop ->setEnabled(editable);
- self->mAutoPlay ->setEnabled(editable);
- self->mAutoScale ->setEnabled(editable);
- self->mAutoZoom ->setEnabled(editable);
- self->mControls ->setEnabled(editable);
- self->mCurrentURL ->setEnabled(editable);
- self->mFirstClick ->setEnabled(editable);
- self->mHeightPixels ->setEnabled(editable);
- self->mHomeURL ->setEnabled(editable);
- self->mWidthPixels ->setEnabled(editable);
- self->updateMediaPreview();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable)
-{
- LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
- self->mMediaEditable = editable;
-
- //llinfos << "---------------" << llendl;
- //llinfos << ll_pretty_print_sd(media_settings) << llendl;
- //llinfos << "---------------" << llendl;
-
- // IF all the faces have media (or all dont have media)
- if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
- {
- if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)
- {
- self->clearValues(self, self->mMediaEditable);
- // only show multiple
- self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
- return;
- }
-
- }
- else
- {
- if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
- {
- self->clearValues(self, self->mMediaEditable);
- // only show multiple
- self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
- return;
- }
-
- }
- std::string base_key( "" );
- std::string tentative_key( "" );
-
- struct
- {
- std::string key_name;
- LLUICtrl* ctrl_ptr;
- std::string ctrl_type;
-
- } data_set [] =
- {
- { LLMediaEntry::AUTO_LOOP_KEY, self->mAutoLoop, "LLCheckBoxCtrl" },
- { LLMediaEntry::AUTO_PLAY_KEY, self->mAutoPlay, "LLCheckBoxCtrl" },
- { LLMediaEntry::AUTO_SCALE_KEY, self->mAutoScale, "LLCheckBoxCtrl" },
- { LLMediaEntry::AUTO_ZOOM_KEY, self->mAutoZoom, "LLCheckBoxCtrl" },
- { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" },
- { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLLineEditor" },
- { LLMediaEntry::HEIGHT_PIXELS_KEY, self->mHeightPixels, "LLSpinCtrl" },
- { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" },
- { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" },
- { LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" },
- { "", NULL , "" }
- };
-
- for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
- {
- base_key = std::string( data_set[ i ].key_name );
- tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
- // TODO: CP - I bet there is a better way to do this using Boost
- if ( media_settings[ base_key ].isDefined() )
- {
- if ( data_set[ i ].ctrl_type == "LLLineEditor" )
- {
- static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )->
- setText( media_settings[ base_key ].asString() );
- }
- else
- if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
- static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
- setValue( media_settings[ base_key ].asBoolean() );
- else
- if ( data_set[ i ].ctrl_type == "LLComboBox" )
- static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
- setCurrentByIndex( media_settings[ base_key ].asInteger() );
- else
- if ( data_set[ i ].ctrl_type == "LLSpinCtrl" )
- static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )->
- setValue( media_settings[ base_key ].asInteger() );
-
- data_set[ i ].ctrl_ptr->setEnabled(self->mMediaEditable);
- data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
- };
- };
-
- // interrogates controls and updates widgets as required
- self->updateMediaPreview();
- self->updateCurrentURL();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Helper to set media control to media URL as required
-void LLPanelMediaSettingsGeneral::updateMediaPreview()
-{
- if ( mHomeURL->getValue().asString().length() > 0 )
- {
- mPreviewMedia->navigateTo( mHomeURL->getValue().asString() );
- }
- else
- // new home URL will be empty if media is deleted so display a
- // "preview goes here" data url page
- {
- mPreviewMedia->navigateTo( "data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22100%%22 height=%22100%%22 %3E%3Cdefs%3E%3Cpattern id=%22checker%22 patternUnits=%22userSpaceOnUse%22 x=%220%22 y=%220%22 width=%22128%22 height=%22128%22 viewBox=%220 0 128 128%22 %3E%3Crect x=%220%22 y=%220%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3Crect x=%2264%22 y=%2264%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3C/pattern%3E%3C/defs%3E%3Crect x=%220%22 y=%220%22 width=%22100%%22 height=%22100%%22 fill=%22url(#checker)%22 /%3E%3C/svg%3E" );
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Helper to set current URL
-void LLPanelMediaSettingsGeneral::updateCurrentURL()
-{
- if( mCurrentURL->getText().empty() )
- {
- childSetText( "current_url", mHomeURL->getText() );
- }
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-// virtual
-void LLPanelMediaSettingsGeneral::onClose(bool app_quitting)
-{
- if(mPreviewMedia)
- {
- mPreviewMedia->unloadMediaSource();
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata )
-{
- LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
-
- // check url user is trying to enter for home URL will pass whitelist
- // and decline to accept it if it doesn't.
- std::string home_url = self->mHomeURL->getValue().asString();
- if ( ! self->mParent->passesWhiteList( home_url ) )
- {
- LLNotifications::instance().add("WhiteListInvalidatesHomeUrl");
- return;
- };
-
- self->updateMediaPreview();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata)
-{
- LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
- self->navigateHomeSelectedFace();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsGeneral::apply( void* userdata )
-{
- LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
- self->mHomeURL->onCommit();
- // build LLSD Fragment
- LLSD media_data_general;
- self->getValues(media_data_general);
-
- // this merges contents of LLSD passed in with what's there so this is ok
- LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general );
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in )
-{
- fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue();
- fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue();
- fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue();
- fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue();
- fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex();
- fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
- fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue();
- fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue();
- fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue();
- fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent )
-{
- mParent = parent;
-};
-
-bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace()
-{
- // HACK: This is directly referencing an impl name. BAD!
- // This can be removed when we have a truly generic media browser that only
- // builds an impl based on the type of url it is passed.
- struct functor_navigate_media : public LLSelectedTEGetFunctor< bool>
- {
- bool get( LLViewerObject* object, S32 face )
- {
- if ( object )
- if ( object->getTE(face) )
- if ( object->getTE(face)->getMediaData() )
- {
- if(object->permModify())
- {
- viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID());
- if(media_impl)
- {
- media_impl->navigateHome();
- return true;
- }
- }
- }
- return false;
- };
-
- } functor_navigate_media;
-
- bool all_face_media_navigated = false;
- LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
- selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated );
-
- return all_face_media_navigated;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-const std::string LLPanelMediaSettingsGeneral::getHomeUrl()
-{
- return mHomeURL->getValue().asString();
-}
-
+/** + * @file llpanelmediasettingsgeneral.cpp + * @brief LLPanelMediaSettingsGeneral class implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llpanelmediasettingsgeneral.h" +#include "llcombobox.h" +#include "llcheckboxctrl.h" +#include "llspinctrl.h" +#include "lluictrlfactory.h" +#include "llviewerwindow.h" +#include "llviewermedia.h" +#include "llsdutil.h" +#include "llselectmgr.h" +#include "llbutton.h" +#include "lltexturectrl.h" +#include "llurl.h" +#include "llwindow.h" +#include "llmediaentry.h" +#include "llmediactrl.h" +#include "llpanelcontents.h" +#include "llpermissions.h" +#include "llpluginclassmedia.h" +#include "llfloatermediasettings.h" +#include "llfloatertools.h" +#include "lltrans.h" + +const char *CHECKERBOARD_DATA_URL = "data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22100%%22 height=%22100%%22 %3E%3Cdefs%3E%3Cpattern id=%22checker%22 patternUnits=%22userSpaceOnUse%22 x=%220%22 y=%220%22 width=%22128%22 height=%22128%22 viewBox=%220 0 128 128%22 %3E%3Crect x=%220%22 y=%220%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3Crect x=%2264%22 y=%2264%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3C/pattern%3E%3C/defs%3E%3Crect x=%220%22 y=%220%22 width=%22100%%22 height=%22100%%22 fill=%22url(#checker)%22 /%3E%3C/svg%3E"; + +//////////////////////////////////////////////////////////////////////////////// +// +LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() : + mControls( NULL ), + mAutoLoop( NULL ), + mFirstClick( NULL ), + mAutoZoom( NULL ), + mAutoPlay( NULL ), + mAutoScale( NULL ), + mWidthPixels( NULL ), + mHeightPixels( NULL ), + mHomeURL( NULL ), + mCurrentURL( NULL ), + mParent( NULL ), + mMediaEditable(false) +{ + // build dialog from XML + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml"); +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLPanelMediaSettingsGeneral::postBuild() +{ + // connect member vars with UI widgets + mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY ); + mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY ); + mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY ); + mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY ); + mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY ); + mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY ); + mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY ); + mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY ); + mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY ); + mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY ); + mPreviewMedia = getChild<LLMediaCtrl>("preview_media"); + + // watch commit action for HOME URL + childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this); + childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this); + // interrogates controls and updates widgets as required + updateMediaPreview(); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::draw() +{ + // housekeeping + LLPanel::draw(); + + // enable/disable pixel values image entry based on auto scale checkbox + if ( mAutoScale->getValue().asBoolean() == false ) + { + childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true ); + childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true ); + } + else + { + childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false ); + childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false ); + }; + + // enable/disable UI based on type of media + bool reset_button_is_active = true; + if( mPreviewMedia ) + { + LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin(); + if( media_plugin ) + { + // turn off volume (if we can) for preview. Note: this really only + // works for QuickTime movies right now - no way to control the + // volume of a flash app embedded in a page for example + media_plugin->setVolume( 0 ); + + // some controls are only appropriate for time or browser type plugins + // so we selectively enable/disable them - need to do it in draw + // because the information from plugins arrives assynchronously + bool show_time_controls = media_plugin->pluginSupportsMediaTime(); + if ( show_time_controls ) + { + childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false ); + reset_button_is_active = false; + childSetEnabled( "current_url_label", false ); + childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true ); + } + else + { + childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true ); + reset_button_is_active = true; + childSetEnabled( "current_url_label", true ); + childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false ); + }; + }; + }; + + // current URL can change over time, update it here + updateCurrentUrl(); + + LLPermissions perm; + bool user_can_press_reset = mMediaEditable; + + // several places modify this widget so we must collect states in one place + if ( reset_button_is_active ) + { + // user has perms to press reset button and it is active + if ( user_can_press_reset ) + { + childSetEnabled( "current_url_reset_btn", true ); + } + // user does not has perms to press reset button and it is active + else + { + childSetEnabled( "current_url_reset_btn", false ); + }; + } + else + // reset button is inactive so we just slam it to off - other states don't matter + { + childSetEnabled( "current_url_reset_btn", false ); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable) +{ + LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; + self->mAutoLoop->clear(); + self->mAutoPlay->clear(); + self->mAutoScale->clear(); + self->mAutoZoom ->clear(); + self->mControls->clear(); + self->mCurrentURL->clear(); + self->mFirstClick->clear(); + self->mHeightPixels->clear(); + self->mHomeURL->clear(); + self->mWidthPixels->clear(); + self->mAutoLoop ->setEnabled(editable); + self->mAutoPlay ->setEnabled(editable); + self->mAutoScale ->setEnabled(editable); + self->mAutoZoom ->setEnabled(editable); + self->mControls ->setEnabled(editable); + self->mCurrentURL ->setEnabled(editable); + self->mFirstClick ->setEnabled(editable); + self->mHeightPixels ->setEnabled(editable); + self->mHomeURL ->setEnabled(editable); + self->mWidthPixels ->setEnabled(editable); + self->updateMediaPreview(); +} + +// static +bool LLPanelMediaSettingsGeneral::isMultiple() +{ + // IF all the faces have media (or all dont have media) + if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo ) + { + if(LLFloaterMediaSettings::getInstance()->mMultipleMedia) + { + return true; + } + + } + else + { + if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) + { + return true; + } + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable) +{ + LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; + self->mMediaEditable = editable; + + //llinfos << "---------------" << llendl; + //llinfos << ll_pretty_print_sd(media_settings) << llendl; + //llinfos << "---------------" << llendl; + + if ( LLPanelMediaSettingsGeneral::isMultiple() ) + { + self->clearValues(self, self->mMediaEditable); + // only show multiple + self->mHomeURL->setText(LLTrans::getString("Multiple Media")); + self->mCurrentURL->setText(LLTrans::getString("Multiple Media")); + return; + } + + std::string base_key( "" ); + std::string tentative_key( "" ); + + struct + { + std::string key_name; + LLUICtrl* ctrl_ptr; + std::string ctrl_type; + + } data_set [] = + { + { LLMediaEntry::AUTO_LOOP_KEY, self->mAutoLoop, "LLCheckBoxCtrl" }, + { LLMediaEntry::AUTO_PLAY_KEY, self->mAutoPlay, "LLCheckBoxCtrl" }, + { LLMediaEntry::AUTO_SCALE_KEY, self->mAutoScale, "LLCheckBoxCtrl" }, + { LLMediaEntry::AUTO_ZOOM_KEY, self->mAutoZoom, "LLCheckBoxCtrl" }, + { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" }, + { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLLineEditor" }, + { LLMediaEntry::HEIGHT_PIXELS_KEY, self->mHeightPixels, "LLSpinCtrl" }, + { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" }, + { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" }, + { LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" }, + { "", NULL , "" } + }; + + for( int i = 0; data_set[ i ].key_name.length() > 0; ++i ) + { + base_key = std::string( data_set[ i ].key_name ); + tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ); + // TODO: CP - I bet there is a better way to do this using Boost + if ( media_settings[ base_key ].isDefined() ) + { + if ( data_set[ i ].ctrl_type == "LLLineEditor" ) + { + static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )-> + setText( media_settings[ base_key ].asString() ); + } + else + if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" ) + static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )-> + setValue( media_settings[ base_key ].asBoolean() ); + else + if ( data_set[ i ].ctrl_type == "LLComboBox" ) + static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )-> + setCurrentByIndex( media_settings[ base_key ].asInteger() ); + else + if ( data_set[ i ].ctrl_type == "LLSpinCtrl" ) + static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )-> + setValue( media_settings[ base_key ].asInteger() ); + + data_set[ i ].ctrl_ptr->setEnabled(self->mMediaEditable); + data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); + }; + }; + + // interrogates controls and updates widgets as required + self->updateMediaPreview(); +} + +//////////////////////////////////////////////////////////////////////////////// +// Helper to set media control to media URL as required +void LLPanelMediaSettingsGeneral::updateMediaPreview() +{ + if ( mHomeURL->getValue().asString().length() > 0 ) + { + mPreviewMedia->navigateTo( mHomeURL->getValue().asString() ); + } + else + // new home URL will be empty if media is deleted so display a + // "preview goes here" data url page + { + mPreviewMedia->navigateTo( CHECKERBOARD_DATA_URL ); + }; +} + +//////////////////////////////////////////////////////////////////////////////// + +// virtual +void LLPanelMediaSettingsGeneral::onClose(bool app_quitting) +{ + if(mPreviewMedia) + { + mPreviewMedia->unloadMediaSource(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata ) +{ + LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata; + + // check url user is trying to enter for home URL will pass whitelist + // and decline to accept it if it doesn't. + std::string home_url = self->mHomeURL->getValue().asString(); + if ( ! self->mParent->passesWhiteList( home_url ) ) + { + LLNotifications::instance().add("WhiteListInvalidatesHomeUrl"); + return; + }; + + self->updateMediaPreview(); +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata) +{ + LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata; + self->navigateHomeSelectedFace(); +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::apply( void* userdata ) +{ + LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; + self->mHomeURL->onCommit(); + // build LLSD Fragment + LLSD media_data_general; + self->getValues(media_data_general); + + // this merges contents of LLSD passed in with what's there so this is ok + LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in ) +{ + fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue(); + fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue(); + fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue(); + fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue(); + fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex(); + fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue(); + fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue(); + fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue(); + fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue(); + fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent ) +{ + mParent = parent; +}; + +bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace() +{ + // HACK: This is directly referencing an impl name. BAD! + // This can be removed when we have a truly generic media browser that only + // builds an impl based on the type of url it is passed. + struct functor_navigate_media : public LLSelectedTEGetFunctor< bool> + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + { + if(object->permModify()) + { + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID()); + if(media_impl) + { + media_impl->navigateHome(); + return true; + } + } + } + return false; + }; + + } functor_navigate_media; + + bool all_face_media_navigated = false; + LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection(); + selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated ); + + // Note: we don't update the 'current URL' field until the media data itself changes + + return all_face_media_navigated; +} + +//////////////////////////////////////////////////////////////////////////////// +// +const std::string LLPanelMediaSettingsGeneral::getHomeUrl() +{ + return mHomeURL->getValue().asString(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLPanelMediaSettingsGeneral::updateCurrentUrl() +{ + // Get the current URL from the selection + + const LLMediaEntry default_media_data; + std::string value_str = default_media_data.getCurrentURL(); + struct functor_getter_current_url : public LLSelectedTEGetFunctor< std::string > + { + functor_getter_current_url(const LLMediaEntry& entry): mMediaEntry(entry) {} + + std::string get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getCurrentURL(); + return mMediaEntry.getCurrentURL(); + }; + + const LLMediaEntry & mMediaEntry; + + } func_current_url(default_media_data); + bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_current_url, value_str ); + mCurrentURL->setText(value_str); + mCurrentURL->setTentative(identical); +} diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h index e82a31382e..b48e081a1b 100644 --- a/indra/newview/llpanelmediasettingsgeneral.h +++ b/indra/newview/llpanelmediasettingsgeneral.h @@ -63,7 +63,6 @@ public: bool navigateHomeSelectedFace(); void updateMediaPreview(); - void updateCurrentURL(); const std::string getHomeUrl(); @@ -72,8 +71,12 @@ protected: bool mMediaEditable; private: + void updateCurrentUrl(); + static void onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata); static void onCommitHomeURL(LLUICtrl* ctrl, void *userdata ); + + static bool isMultiple(); LLComboBox* mControls; LLCheckBoxCtrl* mAutoLoop; diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp index 33f0952f53..3577f63340 100644 --- a/indra/newview/llpanelmediasettingssecurity.cpp +++ b/indra/newview/llpanelmediasettingssecurity.cpp @@ -235,17 +235,17 @@ void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in ) const std::string LLPanelMediaSettingsSecurity::makeValidUrl( const std::string& src_url )
{
// use LLURI to determine if we have a valid scheme
- LLURI candidate_url( src_url );
- if ( candidate_url.scheme().empty() )
- {
+ LLURI candidate_url( src_url ); + if ( candidate_url.scheme().empty() ) + { // build a URL comprised of default scheme and the original fragment
const std::string default_scheme( "http://" );
return default_scheme + src_url;
- };
-
- // we *could* test the "default scheme" + "original fragment" URL again
- // using LLURI to see if it's valid but I think the outcome is the same
- // in either case - our only option is to return the original URL
+ }; + + // we *could* test the "default scheme" + "original fragment" URL again + // using LLURI to see if it's valid but I think the outcome is the same + // in either case - our only option is to return the original URL // we *think* the original url passed in was valid
return src_url;
@@ -332,10 +332,10 @@ void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata ) self->mWhiteListList->deleteSelectedItems();
}
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLPanelMediaSettingsSecurity::setParent( LLFloaterMediaSettings* parent )
-{
- mParent = parent;
-};
-
+//////////////////////////////////////////////////////////////////////////////// +// +void LLPanelMediaSettingsSecurity::setParent( LLFloaterMediaSettings* parent ) +{ + mParent = parent; +}; + diff --git a/indra/newview/llpanelmediasettingssecurity.h b/indra/newview/llpanelmediasettingssecurity.h index b78ee92193..2555bb8dc8 100644 --- a/indra/newview/llpanelmediasettingssecurity.h +++ b/indra/newview/llpanelmediasettingssecurity.h @@ -55,7 +55,7 @@ class LLPanelMediaSettingsSecurity : public LLPanel void addWhiteListItem(const std::string& url); void setParent( LLFloaterMediaSettings* parent ); const std::string makeValidUrl( const std::string& src_url ); - bool passesWhiteList( const std::string& added_url, const std::string& test_url );
+ bool passesWhiteList( const std::string& added_url, const std::string& test_url ); protected: LLFloaterMediaSettings* mParent; diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 1ab4ff581e..58d9fe9b76 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -45,7 +45,6 @@ class LLUICtrl; class LLButton; class LLViewerObject; class LLComboBox; -class LLPanelInventory; class LLColorSwatchCtrl; class LLTextureCtrl; class LLInventoryItem; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp new file mode 100644 index 0000000000..79b33e29f5 --- /dev/null +++ b/indra/newview/llpanelobjectinventory.cpp @@ -0,0 +1,1927 @@ +/** + * @file llsidepanelinventory.cpp + * @brief LLPanelObjectInventory class implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +//***************************************************************************** +// +// Implementation of the panel inventory - used to view and control a +// task's inventory. +// +//***************************************************************************** + +#include "llviewerprecompiledheaders.h" + +#include "llpanelobjectinventory.h" + +#include "roles_constants.h" + +#include "llagent.h" +#include "llcallbacklist.h" +#include "llfloaterbuycurrency.h" +#include "llfloaterreg.h" +#include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llpreviewanim.h" +#include "llpreviewgesture.h" +#include "llpreviewnotecard.h" +#include "llpreviewscript.h" +#include "llpreviewsound.h" +#include "llpreviewtexture.h" +#include "llscrollcontainer.h" +#include "llselectmgr.h" +#include "llsidetray.h" +#include "llstatusbar.h" +#include "lltrans.h" +#include "llviewerassettype.h" +#include "llviewerregion.h" +#include "llviewerobjectlist.h" +#include "llviewermessage.h" + + +///---------------------------------------------------------------------------- +/// Class LLTaskInvFVBridge +///---------------------------------------------------------------------------- + +class LLTaskInvFVBridge : public LLFolderViewEventListener +{ +protected: + LLUUID mUUID; + std::string mName; + mutable std::string mDisplayName; + LLPanelObjectInventory* mPanel; + U32 mFlags; + + LLInventoryItem* findItem() const; + +public: + LLTaskInvFVBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name, + U32 flags=0); + virtual ~LLTaskInvFVBridge( void ) {} + + virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } + virtual std::string getLabelSuffix() const { return LLStringUtil::null; } + + static LLTaskInvFVBridge* createObjectBridge(LLPanelObjectInventory* panel, + LLInventoryObject* object); + void showProperties(); + void buyItem(); + S32 getPrice(); + static bool commitBuyItem(const LLSD& notification, const LLSD& response); + + // LLFolderViewEventListener functionality + virtual const std::string& getName() const; + virtual const std::string& getDisplayName() const; + virtual PermissionMask getPermissionMask() const { return PERM_NONE; } + /*virtual*/ LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; } + virtual const LLUUID& getUUID() const { return mUUID; } + virtual time_t getCreationDate() const; + virtual LLUIImagePtr getIcon() const; + virtual void openItem(); + virtual void closeItem() {} + virtual void previewItem(); + virtual void selectItem() {} + virtual BOOL isItemRenameable() const; + virtual BOOL renameItem(const std::string& new_name); + virtual BOOL isItemMovable() const; + virtual BOOL isItemRemovable(); + virtual BOOL removeItem(); + virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); + virtual void move(LLFolderViewEventListener* parent_listener); + virtual BOOL isItemCopyable() const; + virtual BOOL copyToClipboard() const; + virtual void cutToClipboard(); + virtual BOOL isClipboardPasteable() const; + virtual void pasteFromClipboard(); + virtual void pasteLinkFromClipboard(); + virtual void buildContextMenu(LLMenuGL& menu, U32 flags); + virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action); + virtual BOOL isUpToDate() const { return TRUE; } + virtual BOOL hasChildren() const { return FALSE; } + virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } + // LLDragAndDropBridge functionality + virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data); +}; + +LLTaskInvFVBridge::LLTaskInvFVBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name, + U32 flags): + mUUID(uuid), + mName(name), + mPanel(panel), + mFlags(flags) +{ + +} + +LLInventoryItem* LLTaskInvFVBridge::findItem() const +{ + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(object) + { + return (LLInventoryItem*)(object->getInventoryObject(mUUID)); + } + return NULL; +} + +void LLTaskInvFVBridge::showProperties() +{ + LLSD key; + key["object"] = mPanel->getTaskUUID(); + key["id"] = mUUID; + LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); + + /* + LLFloaterProperties* floater = LLFloaterReg::showTypedInstance<LLFloaterProperties>("properties", mUUID); + if (floater) + { + floater->setObjectID(mPanel->getTaskUUID()); + } + */ +} + +struct LLBuyInvItemData +{ + LLUUID mTaskID; + LLUUID mItemID; + LLAssetType::EType mType; + + LLBuyInvItemData(const LLUUID& task, + const LLUUID& item, + LLAssetType::EType type) : + mTaskID(task), mItemID(item), mType(type) + {} +}; + +void LLTaskInvFVBridge::buyItem() +{ + llinfos << "LLTaskInvFVBridge::buyItem()" << llendl; + LLInventoryItem* item = findItem(); + if(!item || !item->getSaleInfo().isForSale()) return; + LLBuyInvItemData* inv = new LLBuyInvItemData(mPanel->getTaskUUID(), + mUUID, + item->getType()); + + const LLSaleInfo& sale_info = item->getSaleInfo(); + const LLPermissions& perm = item->getPermissions(); + const std::string owner_name; // no owner name currently... FIXME? + + LLViewerObject* obj; + if( ( obj = gObjectList.findObject( mPanel->getTaskUUID() ) ) && obj->isAttachment() ) + { + LLNotifications::instance().add("Cannot_Purchase_an_Attachment"); + llinfos << "Attempt to purchase an attachment" << llendl; + delete inv; + } + else + { + LLSD args; + args["PRICE"] = llformat("%d",sale_info.getSalePrice()); + args["OWNER"] = owner_name; + if (sale_info.getSaleType() != LLSaleInfo::FS_CONTENTS) + { + U32 next_owner_mask = perm.getMaskNextOwner(); + args["MODIFYPERM"] = LLNotifications::instance().getGlobalString((next_owner_mask & PERM_MODIFY) ? "PermYes" : "PermNo"); + args["COPYPERM"] = LLNotifications::instance().getGlobalString((next_owner_mask & PERM_COPY) ? "PermYes" : "PermNo"); + args["RESELLPERM"] = LLNotifications::instance().getGlobalString((next_owner_mask & PERM_TRANSFER) ? "PermYes" : "PermNo"); + } + + std::string alertdesc; + switch(sale_info.getSaleType()) + { + case LLSaleInfo::FS_ORIGINAL: + alertdesc = owner_name.empty() ? "BuyOriginalNoOwner" : "BuyOriginal"; + break; + case LLSaleInfo::FS_CONTENTS: + alertdesc = owner_name.empty() ? "BuyContentsNoOwner" : "BuyContents"; + break; + case LLSaleInfo::FS_COPY: + default: + alertdesc = owner_name.empty() ? "BuyCopyNoOwner" : "BuyCopy"; + break; + } + + LLSD payload; + payload["task_id"] = inv->mTaskID; + payload["item_id"] = inv->mItemID; + payload["type"] = inv->mType; + LLNotifications::instance().add(alertdesc, args, payload, LLTaskInvFVBridge::commitBuyItem); + } +} + +S32 LLTaskInvFVBridge::getPrice() +{ + LLInventoryItem* item = findItem(); + if(item) + { + return item->getSaleInfo().getSalePrice(); + } + else + { + return -1; + } +} + +// static +bool LLTaskInvFVBridge::commitBuyItem(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if(0 == option) + { + LLViewerObject* object = gObjectList.findObject(notification["payload"]["task_id"].asUUID()); + if(!object || !object->getRegion()) return false; + + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_BuyObjectInventory); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Data); + msg->addUUIDFast(_PREHASH_ObjectID, notification["payload"]["task_id"].asUUID()); + msg->addUUIDFast(_PREHASH_ItemID, notification["payload"]["item_id"].asUUID()); + msg->addUUIDFast(_PREHASH_FolderID, + gInventory.findCategoryUUIDForType((LLFolderType::EType)notification["payload"]["type"].asInteger())); + msg->sendReliable(object->getRegion()->getHost()); + } + return false; +} + +const std::string& LLTaskInvFVBridge::getName() const +{ + return mName; +} + +const std::string& LLTaskInvFVBridge::getDisplayName() const +{ + LLInventoryItem* item = findItem(); + + if(item) + { + if(item->getParentUUID().isNull()) + { + if(item->getName() == "Contents") + { + mDisplayName.assign(LLTrans::getString("ViewerObjectContents")); + } + else + { + mDisplayName.assign(item->getName()); + } + } + else + { + mDisplayName.assign(item->getName()); + } + const LLPermissions& perm(item->getPermissions()); + BOOL copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE); + BOOL mod = gAgent.allowOperation(PERM_MODIFY, perm, GP_OBJECT_MANIPULATE); + BOOL xfer = gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE); + + if(!copy) + { + mDisplayName.append(LLTrans::getString("no_copy")); + } + if(!mod) + { + mDisplayName.append(LLTrans::getString("no_modify")); + } + if(!xfer) + { + mDisplayName.append(LLTrans::getString("no_transfer")); + } + } + + return mDisplayName; +} + +// BUG: No creation dates for task inventory +time_t LLTaskInvFVBridge::getCreationDate() const +{ + return 0; +} + +LLUIImagePtr LLTaskInvFVBridge::getIcon() const +{ + BOOL item_is_multi = FALSE; + if ( mFlags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) + { + item_is_multi = TRUE; + } + + return get_item_icon(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT, 0, item_is_multi ); +} + +void LLTaskInvFVBridge::openItem() +{ + // no-op. + lldebugs << "LLTaskInvFVBridge::openItem()" << llendl; +} + +void LLTaskInvFVBridge::previewItem() +{ + openItem(); +} + +BOOL LLTaskInvFVBridge::isItemRenameable() const +{ + if(gAgent.isGodlike()) return TRUE; + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(object) + { + LLInventoryItem* item; + item = (LLInventoryItem*)(object->getInventoryObject(mUUID)); + if(item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), + GP_OBJECT_MANIPULATE, GOD_LIKE)) + { + return TRUE; + } + } + return FALSE; +} + +BOOL LLTaskInvFVBridge::renameItem(const std::string& new_name) +{ + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(object) + { + LLViewerInventoryItem* item = NULL; + item = (LLViewerInventoryItem*)object->getInventoryObject(mUUID); + if(item && (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), + GP_OBJECT_MANIPULATE, GOD_LIKE))) + { + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + new_item->rename(new_name); + object->updateInventory( + new_item, + TASK_INVENTORY_ITEM_KEY, + false); + } + } + return TRUE; +} + +BOOL LLTaskInvFVBridge::isItemMovable() const +{ + //LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + //if(object && (object->permModify() || gAgent.isGodlike())) + //{ + // return TRUE; + //} + //return FALSE; + return TRUE; +} + +BOOL LLTaskInvFVBridge::isItemRemovable() +{ + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(object + && (object->permModify() || object->permYouOwner())) + { + return TRUE; + } + return FALSE; +} + +bool remove_task_inventory_callback(const LLSD& notification, const LLSD& response, LLPanelObjectInventory* panel) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + LLViewerObject* object = gObjectList.findObject(notification["payload"]["task_id"].asUUID()); + if(option == 0 && object) + { + // yes + LLSD::array_const_iterator list_end = notification["payload"]["inventory_ids"].endArray(); + for (LLSD::array_const_iterator list_it = notification["payload"]["inventory_ids"].beginArray(); + list_it != list_end; + ++list_it) + { + object->removeInventory(list_it->asUUID()); + } + + // refresh the UI. + panel->refresh(); + } + return false; +} + +// helper for remove +// ! REFACTOR ! two_uuids_list_t is also defined in llinevntorybridge.h, but differently. +typedef std::pair<LLUUID, std::list<LLUUID> > panel_two_uuids_list_t; +typedef std::pair<LLPanelObjectInventory*, panel_two_uuids_list_t> remove_data_t; +BOOL LLTaskInvFVBridge::removeItem() +{ + if(isItemRemovable() && mPanel) + { + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(object) + { + if(object->permModify()) + { + // just do it. + object->removeInventory(mUUID); + return TRUE; + } + else + { + remove_data_t* data = new remove_data_t; + data->first = mPanel; + data->second.first = mPanel->getTaskUUID(); + data->second.second.push_back(mUUID); + LLSD payload; + payload["task_id"] = mPanel->getTaskUUID(); + payload["inventory_ids"].append(mUUID); + LLNotifications::instance().add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel)); + return FALSE; + } + } + } + return FALSE; +} + +void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +{ + if (!mPanel) + { + return; + } + + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if (!object) + { + return; + } + + if (!object->permModify()) + { + LLSD payload; + payload["task_id"] = mPanel->getTaskUUID(); + for (S32 i = 0; i < (S32)batch.size(); i++) + { + LLTaskInvFVBridge* itemp = (LLTaskInvFVBridge*)batch[i]; + payload["inventory_ids"].append(itemp->getUUID()); + } + LLNotifications::instance().add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel)); + + } + else + { + for (S32 i = 0; i < (S32)batch.size(); i++) + { + LLTaskInvFVBridge* itemp = (LLTaskInvFVBridge*)batch[i]; + + if(itemp->isItemRemovable()) + { + // just do it. + object->removeInventory(itemp->getUUID()); + } + } + } +} + +void LLTaskInvFVBridge::move(LLFolderViewEventListener* parent_listener) +{ +} + +BOOL LLTaskInvFVBridge::isItemCopyable() const +{ + LLInventoryItem* item = findItem(); + if(!item) return FALSE; + return gAgent.allowOperation(PERM_COPY, item->getPermissions(), + GP_OBJECT_MANIPULATE); +} + +BOOL LLTaskInvFVBridge::copyToClipboard() const +{ + return FALSE; +} + +void LLTaskInvFVBridge::cutToClipboard() +{ +} + +BOOL LLTaskInvFVBridge::isClipboardPasteable() const +{ + return FALSE; +} + +void LLTaskInvFVBridge::pasteFromClipboard() +{ +} + +void LLTaskInvFVBridge::pasteLinkFromClipboard() +{ +} + +BOOL LLTaskInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const +{ + //llinfos << "LLTaskInvFVBridge::startDrag()" << llendl; + if(mPanel) + { + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(object) + { + LLInventoryItem* inv = NULL; + if((inv = (LLInventoryItem*)object->getInventoryObject(mUUID))) + { + const LLPermissions& perm = inv->getPermissions(); + bool can_copy = gAgent.allowOperation(PERM_COPY, perm, + GP_OBJECT_MANIPULATE); + if (object->isAttachment() && !can_copy) + { + //RN: no copy contents of attachments cannot be dragged out + // due to a race condition and possible exploit where + // attached objects do not update their inventory items + // when their contents are manipulated + return FALSE; + } + if((can_copy && perm.allowTransferTo(gAgent.getID())) + || object->permYouOwner()) +// || gAgent.isGodlike()) + + { + *type = LLViewerAssetType::lookupDragAndDropType(inv->getType()); + + *id = inv->getUUID(); + return TRUE; + } + } + } + } + return FALSE; +} + +BOOL LLTaskInvFVBridge::dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data) +{ + //llinfos << "LLTaskInvFVBridge::dragOrDrop()" << llendl; + return FALSE; +} + +// virtual +void LLTaskInvFVBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if (action == "task_buy") + { + // Check the price of the item. + S32 price = getPrice(); + if (-1 == price) + { + llwarns << "label_buy_task_bridged_item: Invalid price" << llendl; + } + else + { + if (price > 0 && price > gStatusBar->getBalance()) + { + LLFloaterBuyCurrency::buyCurrency("This costs", price); + } + else + { + buyItem(); + } + } + } + else if (action == "task_open") + { + openItem(); + } + else if (action == "task_properties") + { + showProperties(); + } +} + +void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + LLInventoryItem* item = findItem(); + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + if (!item) + { + hide_context_entries(menu, items, disabled_items); + return; + } + + if(gAgent.allowOperation(PERM_OWNER, item->getPermissions(), + GP_OBJECT_MANIPULATE) + && item->getSaleInfo().isForSale()) + { + items.push_back(std::string("Task Buy")); + + std::string label= LLTrans::getString("Buy"); + // Check the price of the item. + S32 price = getPrice(); + if (-1 == price) + { + llwarns << "label_buy_task_bridged_item: Invalid price" << llendl; + } + else + { + std::ostringstream info; + info << LLTrans::getString("BuyforL$") << price; + label.assign(info.str()); + } + + const LLView::child_list_t *list = menu.getChildList(); + LLView::child_list_t::const_iterator itor; + for (itor = list->begin(); itor != list->end(); ++itor) + { + std::string name = (*itor)->getName(); + LLMenuItemCallGL* menu_itemp = dynamic_cast<LLMenuItemCallGL*>(*itor); + if (name == "Task Buy" && menu_itemp) + { + menu_itemp->setLabel(label); + } + } + } + else + { + items.push_back(std::string("Task Open")); + if (!isItemCopyable()) + { + disabled_items.push_back(std::string("Task Open")); + } + } + items.push_back(std::string("Task Properties")); + if(isItemRenameable()) + { + items.push_back(std::string("Task Rename")); + } + if(isItemRemovable()) + { + items.push_back(std::string("Task Remove")); + } + + hide_context_entries(menu, items, disabled_items); +} + + +///---------------------------------------------------------------------------- +/// Class LLTaskFolderBridge +///---------------------------------------------------------------------------- + +class LLTaskCategoryBridge : public LLTaskInvFVBridge +{ +public: + LLTaskCategoryBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual LLUIImagePtr getIcon() const; + virtual const std::string& getDisplayName() const { return getName(); } + virtual BOOL isItemRenameable() const; + virtual BOOL renameItem(const std::string& new_name); + virtual BOOL isItemRemovable(); + virtual void buildContextMenu(LLMenuGL& menu, U32 flags); + virtual BOOL hasChildren() const; + virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data); +}; + +LLTaskCategoryBridge::LLTaskCategoryBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskInvFVBridge(panel, uuid, name) +{ +} + +LLUIImagePtr LLTaskCategoryBridge::getIcon() const +{ + return LLUI::getUIImage("Inv_FolderClosed"); +} + +BOOL LLTaskCategoryBridge::isItemRenameable() const +{ + return FALSE; +} + +BOOL LLTaskCategoryBridge::renameItem(const std::string& new_name) +{ + return FALSE; +} + +BOOL LLTaskCategoryBridge::isItemRemovable() +{ + return FALSE; +} + +void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + std::vector<std::string> items; + std::vector<std::string> disabled_items; + items.push_back(std::string("Task Open")); + hide_context_entries(menu, items, disabled_items); +} + +BOOL LLTaskCategoryBridge::hasChildren() const +{ + // return TRUE if we have or do know know if we have children. + // *FIX: For now, return FALSE - we will know for sure soon enough. + return FALSE; +} + +BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const +{ + //llinfos << "LLTaskInvFVBridge::startDrag()" << llendl; + if(mPanel) + { + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(object) + { + LLInventoryItem* inv = NULL; + if((inv = (LLInventoryItem*)object->getInventoryObject(mUUID))) + { + const LLPermissions& perm = inv->getPermissions(); + bool can_copy = gAgent.allowOperation(PERM_COPY, perm, + GP_OBJECT_MANIPULATE); + if((can_copy && perm.allowTransferTo(gAgent.getID())) + || object->permYouOwner()) +// || gAgent.isGodlike()) + + { + *type = LLViewerAssetType::lookupDragAndDropType(inv->getType()); + + *id = inv->getUUID(); + return TRUE; + } + } + } + } + return FALSE; +} + +BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data) +{ + //llinfos << "LLTaskCategoryBridge::dragOrDrop()" << llendl; + BOOL accept = FALSE; + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(object) + { + switch(cargo_type) + { + case DAD_CATEGORY: + accept = LLToolDragAndDrop::getInstance()->dadUpdateInventoryCategory(object,drop); + break; + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_LANDMARK: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_CLOTHING: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: + case DAD_CALLINGCARD: + accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data); + if(accept && drop) + { + LLToolDragAndDrop::dropInventory(object, + (LLViewerInventoryItem*)cargo_data, + LLToolDragAndDrop::getInstance()->getSource(), + LLToolDragAndDrop::getInstance()->getSourceID()); + } + break; + case DAD_SCRIPT: + // *HACK: In order to resolve SL-22177, we need to block + // drags from notecards and objects onto other + // objects. uncomment the simpler version when we have + // that right. + //accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data); + if(LLToolDragAndDrop::isInventoryDropAcceptable( + object, (LLViewerInventoryItem*)cargo_data) + && (LLToolDragAndDrop::SOURCE_WORLD != LLToolDragAndDrop::getInstance()->getSource()) + && (LLToolDragAndDrop::SOURCE_NOTECARD != LLToolDragAndDrop::getInstance()->getSource())) + { + accept = TRUE; + } + if(accept && drop) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)cargo_data; + // rez in the script active by default, rez in + // inactive if the control key is being held down. + BOOL active = ((mask & MASK_CONTROL) == 0); + LLToolDragAndDrop::dropScript(object, item, active, + LLToolDragAndDrop::getInstance()->getSource(), + LLToolDragAndDrop::getInstance()->getSourceID()); + } + break; + default: + break; + } + } + return accept; +} + +///---------------------------------------------------------------------------- +/// Class LLTaskTextureBridge +///---------------------------------------------------------------------------- + +class LLTaskTextureBridge : public LLTaskInvFVBridge +{ +public: + LLTaskTextureBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name, + LLInventoryType::EType it); + + virtual LLUIImagePtr getIcon() const; + virtual void openItem(); +protected: + LLInventoryType::EType mInventoryType; +}; + +LLTaskTextureBridge::LLTaskTextureBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name, + LLInventoryType::EType it) : + LLTaskInvFVBridge(panel, uuid, name), + mInventoryType(it) +{ +} + +LLUIImagePtr LLTaskTextureBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_TEXTURE, mInventoryType, 0, FALSE); +} + +void LLTaskTextureBridge::openItem() +{ + llinfos << "LLTaskTextureBridge::openItem()" << llendl; + LLPreviewTexture* preview = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); + if(preview) + { + preview->setObjectID(mPanel->getTaskUUID()); + } +} + + +///---------------------------------------------------------------------------- +/// Class LLTaskSoundBridge +///---------------------------------------------------------------------------- + +class LLTaskSoundBridge : public LLTaskInvFVBridge +{ +public: + LLTaskSoundBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual LLUIImagePtr getIcon() const; + virtual void openItem(); + virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action); + virtual void buildContextMenu(LLMenuGL& menu, U32 flags); + static void openSoundPreview(void* data); +}; + +LLTaskSoundBridge::LLTaskSoundBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskInvFVBridge(panel, uuid, name) +{ +} + +LLUIImagePtr LLTaskSoundBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE); +} + +void LLTaskSoundBridge::openItem() +{ + openSoundPreview((void*)this); +} + +void LLTaskSoundBridge::openSoundPreview(void* data) +{ + LLTaskSoundBridge* self = (LLTaskSoundBridge*)data; + if(!self) + return; + + LLPreviewSound* preview = LLFloaterReg::showTypedInstance<LLPreviewSound>("preview_sound", LLSD(self->mUUID), TAKE_FOCUS_YES); + if (preview) + { + preview->setObjectID(self->mPanel->getTaskUUID()); + } +} + +// virtual +void LLTaskSoundBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if (action == "task_play") + { + LLInventoryItem* item = findItem(); + if(item) + { + send_sound_trigger(item->getAssetUUID(), 1.0); + } + } + LLTaskInvFVBridge::performAction(folder, model, action); +} + +void LLTaskSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + LLInventoryItem* item = findItem(); + if(!item) return; + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + if(item->getPermissions().getOwner() != gAgent.getID() + && item->getSaleInfo().isForSale()) + { + items.push_back(std::string("Task Buy")); + + std::string label= LLTrans::getString("Buy"); + // Check the price of the item. + S32 price = getPrice(); + if (-1 == price) + { + llwarns << "label_buy_task_bridged_item: Invalid price" << llendl; + } + else + { + std::ostringstream info; + info << LLTrans::getString("BuyforL$") << price; + label.assign(info.str()); + } + + const LLView::child_list_t *list = menu.getChildList(); + LLView::child_list_t::const_iterator itor; + for (itor = list->begin(); itor != list->end(); ++itor) + { + std::string name = (*itor)->getName(); + LLMenuItemCallGL* menu_itemp = dynamic_cast<LLMenuItemCallGL*>(*itor); + if (name == "Task Buy" && menu_itemp) + { + menu_itemp->setLabel(label); + } + } + } + else + { + items.push_back(std::string("Task Open")); + if (!isItemCopyable()) + { + disabled_items.push_back(std::string("Task Open")); + } + } + items.push_back(std::string("Task Properties")); + if(isItemRenameable()) + { + items.push_back(std::string("Task Rename")); + } + if(isItemRemovable()) + { + items.push_back(std::string("Task Remove")); + } + + items.push_back(std::string("Task Play")); + + + hide_context_entries(menu, items, disabled_items); +} + +///---------------------------------------------------------------------------- +/// Class LLTaskLandmarkBridge +///---------------------------------------------------------------------------- + +class LLTaskLandmarkBridge : public LLTaskInvFVBridge +{ +public: + LLTaskLandmarkBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual LLUIImagePtr getIcon() const; +}; + +LLTaskLandmarkBridge::LLTaskLandmarkBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskInvFVBridge(panel, uuid, name) +{ +} + +LLUIImagePtr LLTaskLandmarkBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, 0, FALSE); +} + + +///---------------------------------------------------------------------------- +/// Class LLTaskCallingCardBridge +///---------------------------------------------------------------------------- + +class LLTaskCallingCardBridge : public LLTaskInvFVBridge +{ +public: + LLTaskCallingCardBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual LLUIImagePtr getIcon() const; + virtual BOOL isItemRenameable() const; + virtual BOOL renameItem(const std::string& new_name); +}; + +LLTaskCallingCardBridge::LLTaskCallingCardBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskInvFVBridge(panel, uuid, name) +{ +} + +LLUIImagePtr LLTaskCallingCardBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, 0, FALSE); +} + +BOOL LLTaskCallingCardBridge::isItemRenameable() const +{ + return FALSE; +} + +BOOL LLTaskCallingCardBridge::renameItem(const std::string& new_name) +{ + return FALSE; +} + + +///---------------------------------------------------------------------------- +/// Class LLTaskScriptBridge +///---------------------------------------------------------------------------- + +class LLTaskScriptBridge : public LLTaskInvFVBridge +{ +public: + LLTaskScriptBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual LLUIImagePtr getIcon() const; + //static BOOL enableIfCopyable( void* userdata ); +}; + +LLTaskScriptBridge::LLTaskScriptBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskInvFVBridge(panel, uuid, name) +{ +} + +LLUIImagePtr LLTaskScriptBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); +} + + +class LLTaskLSLBridge : public LLTaskScriptBridge +{ +public: + LLTaskLSLBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual void openItem(); + virtual BOOL removeItem(); + //virtual void buildContextMenu(LLMenuGL& menu); + + //static void copyToInventory(void* userdata); +}; + +LLTaskLSLBridge::LLTaskLSLBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskScriptBridge(panel, uuid, name) +{ +} + +void LLTaskLSLBridge::openItem() +{ + llinfos << "LLTaskLSLBridge::openItem() " << mUUID << llendl; + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(!object || object->isInventoryPending()) + { + return; + } + LLLiveLSLEditor* preview = LLFloaterReg::showTypedInstance<LLLiveLSLEditor>("preview_scriptedit", LLSD(mUUID), TAKE_FOCUS_YES); + if (preview && (object->permModify() || gAgent.isGodlike())) + { + preview->setObjectID(mPanel->getTaskUUID()); + } +} + +BOOL LLTaskLSLBridge::removeItem() +{ + LLFloaterReg::hideInstance("preview_scriptedit", LLSD(mUUID)); + return LLTaskInvFVBridge::removeItem(); +} + +///---------------------------------------------------------------------------- +/// Class LLTaskObjectBridge +///---------------------------------------------------------------------------- + +class LLTaskObjectBridge : public LLTaskInvFVBridge +{ +public: + LLTaskObjectBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual LLUIImagePtr getIcon() const; +}; + +LLTaskObjectBridge::LLTaskObjectBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskInvFVBridge(panel, uuid, name) +{ +} + +LLUIImagePtr LLTaskObjectBridge::getIcon() const +{ + BOOL item_is_multi = FALSE; + if ( mFlags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) + { + item_is_multi = TRUE; + } + + return get_item_icon(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT, 0, item_is_multi); +} + +///---------------------------------------------------------------------------- +/// Class LLTaskNotecardBridge +///---------------------------------------------------------------------------- + +class LLTaskNotecardBridge : public LLTaskInvFVBridge +{ +public: + LLTaskNotecardBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual LLUIImagePtr getIcon() const; + virtual void openItem(); + virtual BOOL removeItem(); +}; + +LLTaskNotecardBridge::LLTaskNotecardBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskInvFVBridge(panel, uuid, name) +{ +} + +LLUIImagePtr LLTaskNotecardBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE); +} + +void LLTaskNotecardBridge::openItem() +{ + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(!object || object->isInventoryPending()) + { + return; + } + if(object->permModify() || gAgent.isGodlike()) + { + LLPreviewNotecard* preview = LLFloaterReg::showTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(mUUID), TAKE_FOCUS_YES); + if (preview) + { + preview->setObjectID(mPanel->getTaskUUID()); + } + } +} + +BOOL LLTaskNotecardBridge::removeItem() +{ + LLFloaterReg::hideInstance("preview_notecard", LLSD(mUUID)); + return LLTaskInvFVBridge::removeItem(); +} + +///---------------------------------------------------------------------------- +/// Class LLTaskGestureBridge +///---------------------------------------------------------------------------- + +class LLTaskGestureBridge : public LLTaskInvFVBridge +{ +public: + LLTaskGestureBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual LLUIImagePtr getIcon() const; + virtual void openItem(); + virtual BOOL removeItem(); +}; + +LLTaskGestureBridge::LLTaskGestureBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskInvFVBridge(panel, uuid, name) +{ +} + +LLUIImagePtr LLTaskGestureBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE); +} + +void LLTaskGestureBridge::openItem() +{ + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(!object || object->isInventoryPending()) + { + return; + } + LLPreviewGesture::show(mUUID, mPanel->getTaskUUID()); +} + +BOOL LLTaskGestureBridge::removeItem() +{ + // Don't need to deactivate gesture because gestures inside objects can never be active. + LLFloaterReg::hideInstance("preview_gesture", LLSD(mUUID)); + return LLTaskInvFVBridge::removeItem(); +} + +///---------------------------------------------------------------------------- +/// Class LLTaskAnimationBridge +///---------------------------------------------------------------------------- + +class LLTaskAnimationBridge : public LLTaskInvFVBridge +{ +public: + LLTaskAnimationBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name); + + virtual LLUIImagePtr getIcon() const; + virtual void openItem(); + virtual BOOL removeItem(); +}; + +LLTaskAnimationBridge::LLTaskAnimationBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name) : + LLTaskInvFVBridge(panel, uuid, name) +{ +} + +LLUIImagePtr LLTaskAnimationBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE); +} + +void LLTaskAnimationBridge::openItem() +{ + LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); + if(!object || object->isInventoryPending()) + { + return; + } + + LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); + if (preview && (object->permModify() || gAgent.isGodlike())) + { + preview->setObjectID(mPanel->getTaskUUID()); + } +} + +BOOL LLTaskAnimationBridge::removeItem() +{ + LLFloaterReg::hideInstance("preview_anim", LLSD(mUUID)); + return LLTaskInvFVBridge::removeItem(); +} + +///---------------------------------------------------------------------------- +/// Class LLTaskWearableBridge +///---------------------------------------------------------------------------- + +class LLTaskWearableBridge : public LLTaskInvFVBridge +{ +public: + LLTaskWearableBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name, + LLAssetType::EType asset_type, + U32 flags); + + virtual LLUIImagePtr getIcon() const; + +protected: + LLAssetType::EType mAssetType; +}; + +LLTaskWearableBridge::LLTaskWearableBridge( + LLPanelObjectInventory* panel, + const LLUUID& uuid, + const std::string& name, + LLAssetType::EType asset_type, + U32 flags) : + LLTaskInvFVBridge(panel, uuid, name, flags), + mAssetType( asset_type ) +{ +} + +LLUIImagePtr LLTaskWearableBridge::getIcon() const +{ + return get_item_icon(mAssetType, LLInventoryType::IT_WEARABLE, mFlags, FALSE ); +} + + +///---------------------------------------------------------------------------- +/// LLTaskInvFVBridge impl +//---------------------------------------------------------------------------- + +LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory* panel, + LLInventoryObject* object) +{ + LLTaskInvFVBridge* new_bridge = NULL; + LLAssetType::EType type = object->getType(); + LLInventoryItem* item = NULL; + switch(type) + { + case LLAssetType::AT_TEXTURE: + item = (LLInventoryItem*)object; + new_bridge = new LLTaskTextureBridge(panel, + object->getUUID(), + object->getName(), + item->getInventoryType()); + break; + case LLAssetType::AT_SOUND: + new_bridge = new LLTaskSoundBridge(panel, + object->getUUID(), + object->getName()); + break; + case LLAssetType::AT_LANDMARK: + new_bridge = new LLTaskLandmarkBridge(panel, + object->getUUID(), + object->getName()); + break; + case LLAssetType::AT_CALLINGCARD: + new_bridge = new LLTaskCallingCardBridge(panel, + object->getUUID(), + object->getName()); + break; + case LLAssetType::AT_SCRIPT: + // OLD SCRIPTS DEPRECATED - JC + llwarns << "Old script" << llendl; + //new_bridge = new LLTaskOldScriptBridge(panel, + // object->getUUID(), + // object->getName()); + break; + case LLAssetType::AT_OBJECT: + new_bridge = new LLTaskObjectBridge(panel, + object->getUUID(), + object->getName()); + break; + case LLAssetType::AT_NOTECARD: + new_bridge = new LLTaskNotecardBridge(panel, + object->getUUID(), + object->getName()); + break; + case LLAssetType::AT_ANIMATION: + new_bridge = new LLTaskAnimationBridge(panel, + object->getUUID(), + object->getName()); + break; + case LLAssetType::AT_GESTURE: + new_bridge = new LLTaskGestureBridge(panel, + object->getUUID(), + object->getName()); + break; + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + item = (LLInventoryItem*)object; + new_bridge = new LLTaskWearableBridge(panel, + object->getUUID(), + object->getName(), + type, + item->getFlags()); + break; + case LLAssetType::AT_CATEGORY: + new_bridge = new LLTaskCategoryBridge(panel, + object->getUUID(), + object->getName()); + break; + case LLAssetType::AT_LSL_TEXT: + new_bridge = new LLTaskLSLBridge(panel, + object->getUUID(), + object->getName()); + break; + + break; + default: + llinfos << "Unhandled inventory type (llassetstorage.h): " + << (S32)type << llendl; + break; + } + return new_bridge; +} + + +///---------------------------------------------------------------------------- +/// Class LLPanelObjectInventory +///---------------------------------------------------------------------------- + +static LLDefaultChildRegistry::Register<LLPanelObjectInventory> r("panel_inventory_object"); + +void do_nothing() +{ +} + +// Default constructor +LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Params& p) : + LLPanel(p), + mScroller(NULL), + mFolders(NULL), + mHaveInventory(FALSE), + mIsInventoryEmpty(TRUE), + mInventoryNeedsUpdate(FALSE) +{ + // Setup context menu callbacks + mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelObjectInventory::doToSelected, this, _2)); + mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); + mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); + mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&do_nothing)); + mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&do_nothing)); + mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&do_nothing)); +} + +// Destroys the object +LLPanelObjectInventory::~LLPanelObjectInventory() +{ + if (!gIdleCallbacks.deleteFunction(idle, this)) + { + llwarns << "LLPanelObjectInventory::~LLPanelObjectInventory() failed to delete callback" << llendl; + } +} + +BOOL LLPanelObjectInventory::postBuild() +{ + // clear contents and initialize menus, sets up mFolders + reset(); + + // Register an idle update callback + gIdleCallbacks.addFunction(idle, this); + + return TRUE; +} + +void LLPanelObjectInventory::doToSelected(const LLSD& userdata) +{ + mFolders->doToSelected(&gInventory, userdata); +} + +void LLPanelObjectInventory::clearContents() +{ + mHaveInventory = FALSE; + mIsInventoryEmpty = TRUE; + if (LLToolDragAndDrop::getInstance() && LLToolDragAndDrop::getInstance()->getSource() == LLToolDragAndDrop::SOURCE_WORLD) + { + LLToolDragAndDrop::getInstance()->endDrag(); + } + + if( mScroller ) + { + // removes mFolders + removeChild( mScroller ); //*TODO: Really shouldn't do this during draw()/refresh() + mScroller->die(); + mScroller = NULL; + mFolders = NULL; + } +} + + +void LLPanelObjectInventory::reset() +{ + clearContents(); + + setBorderVisible(FALSE); + + mCommitCallbackRegistrar.pushScope(); // push local callbacks + + LLRect dummy_rect(0, 1, 1, 0); + LLFolderView::Params p; + p.name = "task inventory"; + p.task_id = getTaskUUID(); + p.parent_panel = this; + mFolders = LLUICtrlFactory::create<LLFolderView>(p); + // this ensures that we never say "searching..." or "no items found" + mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); + + LLRect scroller_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + LLScrollContainer::Params scroll_p; + scroll_p.name("task inventory scroller"); + scroll_p.rect(scroller_rect); + scroll_p.follows.flags(FOLLOWS_ALL); + mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_p); + addChild(mScroller); + mScroller->addChild(mFolders); + + mFolders->setScrollContainer( mScroller ); + + mCommitCallbackRegistrar.popScope(); +} + +void LLPanelObjectInventory::inventoryChanged(LLViewerObject* object, + InventoryObjectList* inventory, + S32 serial_num, + void* data) +{ + if(!object) return; + + //llinfos << "invetnory arrived: \n" + // << " panel UUID: " << panel->mTaskUUID << "\n" + // << " task UUID: " << object->mID << llendl; + if(mTaskUUID == object->mID) + { + mInventoryNeedsUpdate = TRUE; + } + + // refresh any properties floaters that are hanging around. + if(inventory) + { + for (InventoryObjectList::const_iterator iter = inventory->begin(); + iter != inventory->end(); ) + { + LLInventoryObject* item = *iter++; + LLFloaterProperties* floater = LLFloaterReg::findTypedInstance<LLFloaterProperties>("properites", item->getUUID()); + if(floater) + { + floater->refresh(); + } + } + } +} + +void LLPanelObjectInventory::updateInventory() +{ + //llinfos << "inventory arrived: \n" + // << " panel UUID: " << panel->mTaskUUID << "\n" + // << " task UUID: " << object->mID << llendl; + // We're still interested in this task's inventory. + std::set<LLUUID> selected_items; + BOOL inventory_has_focus = FALSE; + if (mHaveInventory && mFolders->getNumSelectedDescendants()) + { + mFolders->getSelectionList(selected_items); + inventory_has_focus = gFocusMgr.childHasKeyboardFocus(mFolders); + } + + reset(); + + LLViewerObject* objectp = gObjectList.findObject(mTaskUUID); + if (objectp) + { + LLInventoryObject* inventory_root = objectp->getInventoryRoot(); + InventoryObjectList contents; + objectp->getInventoryContents(contents); + if (inventory_root) + { + createFolderViews(inventory_root, contents); + mHaveInventory = TRUE; + mIsInventoryEmpty = FALSE; + mFolders->setEnabled(TRUE); + } + else + { + // TODO: create an empty inventory + mIsInventoryEmpty = TRUE; + mHaveInventory = TRUE; + } + } + else + { + // TODO: create an empty inventory + mIsInventoryEmpty = TRUE; + mHaveInventory = TRUE; + } + + // restore previous selection + std::set<LLUUID>::iterator selection_it; + BOOL first_item = TRUE; + for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) + { + LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it); + if (selected_item) + { + //HACK: "set" first item then "change" each other one to get keyboard focus right + if (first_item) + { + mFolders->setSelection(selected_item, TRUE, inventory_has_focus); + first_item = FALSE; + } + else + { + mFolders->changeSelection(selected_item, TRUE); + } + } + } + + mFolders->requestArrange(); + mInventoryNeedsUpdate = FALSE; +} + +// *FIX: This is currently a very expensive operation, because we have +// to iterate through the inventory one time for each category. This +// leads to an N^2 based on the category count. This could be greatly +// speeded with an efficient multimap implementation, but we don't +// have that in our current arsenal. +void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root, InventoryObjectList& contents) +{ + if (!inventory_root) + { + return; + } + // Create a visible root category. + LLTaskInvFVBridge* bridge = NULL; + bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root); + if(bridge) + { + LLFolderViewFolder* new_folder = NULL; + LLFolderViewFolder::Params p; + p.name = inventory_root->getName(); + p.icon = LLUI::getUIImage("Inv_FolderClosed"); + p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); + p.root = mFolders; + p.listener = bridge; + new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); + new_folder->addToFolder(mFolders, mFolders); + new_folder->toggleOpen(); + + createViewsForCategory(&contents, inventory_root, new_folder); + } +} + +typedef std::pair<LLInventoryObject*, LLFolderViewFolder*> obj_folder_pair; + +void LLPanelObjectInventory::createViewsForCategory(InventoryObjectList* inventory, + LLInventoryObject* parent, + LLFolderViewFolder* folder) +{ + // Find all in the first pass + LLDynamicArray<obj_folder_pair*> child_categories; + LLTaskInvFVBridge* bridge; + LLFolderViewItem* view; + + InventoryObjectList::iterator it = inventory->begin(); + InventoryObjectList::iterator end = inventory->end(); + for( ; it != end; ++it) + { + LLInventoryObject* obj = *it; + + if(parent->getUUID() == obj->getParentUUID()) + { + bridge = LLTaskInvFVBridge::createObjectBridge(this, obj); + if(!bridge) + { + continue; + } + if(LLAssetType::AT_CATEGORY == obj->getType()) + { + LLFolderViewFolder::Params p; + p.name = obj->getName(); + p.icon = LLUI::getUIImage("Inv_FolderClosed"); + p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); + p.root = mFolders; + p.listener = bridge; + view = LLUICtrlFactory::create<LLFolderViewFolder>(p); + child_categories.put(new obj_folder_pair(obj, + (LLFolderViewFolder*)view)); + } + else + { + LLFolderViewItem::Params params; + params.name(obj->getName()); + params.icon(bridge->getIcon()); + params.creation_date(bridge->getCreationDate()); + params.root(mFolders); + params.listener(bridge); + params.rect(LLRect()); + view = LLUICtrlFactory::create<LLFolderViewItem> (params); + } + view->addToFolder(folder, mFolders); + } + } + + // now, for each category, do the second pass + for(S32 i = 0; i < child_categories.count(); i++) + { + createViewsForCategory(inventory, child_categories[i]->first, + child_categories[i]->second ); + delete child_categories[i]; + } +} + +void LLPanelObjectInventory::refresh() +{ + //llinfos << "LLPanelObjectInventory::refresh()" << llendl; + BOOL has_inventory = FALSE; + const BOOL non_root_ok = TRUE; + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(NULL, non_root_ok); + if(node) + { + LLViewerObject* object = node->getObject(); + if(object && ((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1) + || (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1))) + { + // determine if we need to make a request. Start with a + // default based on if we have inventory at all. + BOOL make_request = !mHaveInventory; + + // If the task id is different than what we've stored, + // then make the request. + if(mTaskUUID != object->mID) + { + mTaskUUID = object->mID; + make_request = TRUE; + + // This is a new object so pre-emptively clear the contents + // Otherwise we show the old stuff until the update comes in + clearContents(); + + // Register for updates from this object, + registerVOInventoryListener(object,NULL); + } + + // Based on the node information, we may need to dirty the + // object inventory and get it again. + if(node->mValid) + { + if(node->mInventorySerial != object->getInventorySerial() || object->isInventoryDirty()) + { + make_request = TRUE; + } + } + + // do the request if necessary. + if(make_request) + { + requestVOInventory(); + } + has_inventory = TRUE; + } + } + if(!has_inventory) + { + mTaskUUID = LLUUID::null; + removeVOInventoryListener(); + clearContents(); + } + //llinfos << "LLPanelObjectInventory::refresh() " << mTaskUUID << llendl; +} + +void LLPanelObjectInventory::removeSelectedItem() +{ + if(mFolders) + { + mFolders->removeSelectedItems(); + } +} + +void LLPanelObjectInventory::startRenamingSelectedItem() +{ + if(mFolders) + { + mFolders->startRenamingSelectedItem(); + } +} + +void LLPanelObjectInventory::draw() +{ + LLPanel::draw(); + + if(mIsInventoryEmpty) + { + if((LLUUID::null != mTaskUUID) && (!mHaveInventory)) + { + LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("LoadingContents"), 0, + (S32)(getRect().getWidth() * 0.5f), + 10, + LLColor4( 1, 1, 1, 1 ), + LLFontGL::HCENTER, + LLFontGL::BOTTOM); + } + else if(mHaveInventory) + { + LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("NoContents"), 0, + (S32)(getRect().getWidth() * 0.5f), + 10, + LLColor4( 1, 1, 1, 1 ), + LLFontGL::HCENTER, + LLFontGL::BOTTOM); + } + } +} + +void LLPanelObjectInventory::deleteAllChildren() +{ + mScroller = NULL; + mFolders = NULL; + LLView::deleteAllChildren(); +} + +BOOL LLPanelObjectInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg) +{ + if (mFolders && mHaveInventory) + { + LLFolderViewItem* folderp = mFolders->getNextFromChild(NULL); + if (!folderp) + { + return FALSE; + } + // Try to pass on unmodified mouse coordinates + S32 local_x = x - mFolders->getRect().mLeft; + S32 local_y = y - mFolders->getRect().mBottom; + + if (mFolders->pointInView(local_x, local_y)) + { + return mFolders->handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + else + { + //force mouse coordinates to be inside folder rectangle + return mFolders->handleDragAndDrop(5, 1, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + } + else + { + return FALSE; + } +} + +//static +void LLPanelObjectInventory::idle(void* user_data) +{ + LLPanelObjectInventory* self = (LLPanelObjectInventory*)user_data; + + + if (self->mInventoryNeedsUpdate) + { + self->updateInventory(); + } +} diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h new file mode 100644 index 0000000000..6722bb212e --- /dev/null +++ b/indra/newview/llpanelobjectinventory.h @@ -0,0 +1,102 @@ +/** + * @file llpanelobjectinventory.h + * @brief LLPanelObjectInventory class definition + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELOBJECTINVENTORY_H +#define LL_LLPANELOBJECTINVENTORY_H + +#include "llvoinventorylistener.h" +#include "llpanel.h" + +#include "llinventory.h" + +class LLScrollContainer; +class LLFolderView; +class LLFolderViewFolder; +class LLViewerObject; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLPanelObjectInventory +// +// This class represents the panel used to view and control a +// particular task's inventory. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener +{ +public: + // dummy param block for template registration purposes + struct Params : public LLPanel::Params {}; + + LLPanelObjectInventory(const Params&); + virtual ~LLPanelObjectInventory(); + + virtual BOOL postBuild(); + + void doToSelected(const LLSD& userdata); + + void refresh(); + const LLUUID& getTaskUUID() { return mTaskUUID;} + void removeSelectedItem(); + void startRenamingSelectedItem(); + + LLFolderView* getRootFolder() const { return mFolders; } + + virtual void draw(); + virtual void deleteAllChildren(); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg); + + static void idle(void* user_data); + +protected: + void reset(); + /*virtual*/ void inventoryChanged(LLViewerObject* object, + InventoryObjectList* inventory, + S32 serial_num, + void* user_data); + void updateInventory(); + void createFolderViews(LLInventoryObject* inventory_root, InventoryObjectList& contents); + void createViewsForCategory(InventoryObjectList* inventory, + LLInventoryObject* parent, + LLFolderViewFolder* folder); + void clearContents(); + +private: + LLScrollContainer* mScroller; + LLFolderView* mFolders; + + LLUUID mTaskUUID; + BOOL mHaveInventory; + BOOL mIsInventoryEmpty; + BOOL mInventoryNeedsUpdate; +}; + +#endif // LL_LLPANELOBJECTINVENTORY_H diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 2f8fae0f5d..b08eb27b9f 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -60,6 +60,7 @@ #include "llviewermenu.h" // for gMenuHolder #include "llvoiceclient.h" #include "llworld.h" +#include "llspeakers.h" #define FRIEND_LIST_UPDATE_TIMEOUT 0.5 #define NEARBY_LIST_UPDATE_INTERVAL 1 @@ -119,8 +120,84 @@ protected: } }; +/** Compares avatar items by distance between you and them */ +class LLAvatarItemDistanceComparator : public LLAvatarItemComparator +{ +public: + typedef std::map < LLUUID, LLVector3d > id_to_pos_map_t; + LLAvatarItemDistanceComparator() {}; + + void updateAvatarsPositions(std::vector<LLVector3d>& positions, std::vector<LLUUID>& uuids) + { + std::vector<LLVector3d>::const_iterator + pos_it = positions.begin(), + pos_end = positions.end(); + + std::vector<LLUUID>::const_iterator + id_it = uuids.begin(), + id_end = uuids.end(); + + LLAvatarItemDistanceComparator::id_to_pos_map_t pos_map; + + mAvatarsPositions.clear(); + + for (;pos_it != pos_end && id_it != id_end; ++pos_it, ++id_it ) + { + mAvatarsPositions[*id_it] = *pos_it; + } + }; + +protected: + virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const + { + const LLVector3d& me_pos = gAgent.getPositionGlobal(); + const LLVector3d& item1_pos = mAvatarsPositions.find(item1->getAvatarId())->second; + const LLVector3d& item2_pos = mAvatarsPositions.find(item2->getAvatarId())->second; + F32 dist1 = dist_vec(item1_pos, me_pos); + F32 dist2 = dist_vec(item2_pos, me_pos); + return dist1 < dist2; + } +private: + id_to_pos_map_t mAvatarsPositions; +}; + +/** Comparator for comparing nearby avatar items by last spoken time */ +class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator +{ +public: + LLAvatarItemRecentSpeakerComparator() {}; + virtual ~LLAvatarItemRecentSpeakerComparator() {}; + +protected: + virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const + { + LLPointer<LLSpeaker> lhs = LLLocalSpeakerMgr::instance().findSpeaker(item1->getAvatarId()); + LLPointer<LLSpeaker> rhs = LLLocalSpeakerMgr::instance().findSpeaker(item2->getAvatarId()); + if ( lhs.notNull() && rhs.notNull() ) + { + // Compare by last speaking time + if( lhs->mLastSpokeTime != rhs->mLastSpokeTime ) + return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime ); + } + else if ( lhs.notNull() ) + { + // True if only item1 speaker info available + return true; + } + else if ( rhs.notNull() ) + { + // False if only item2 speaker info available + return false; + } + // By default compare by name. + return LLAvatarItemNameComparator::doCompare(item1, item2); + } +}; + static const LLAvatarItemRecentComparator RECENT_COMPARATOR; static const LLAvatarItemStatusComparator STATUS_COMPARATOR; +static LLAvatarItemDistanceComparator DISTANCE_COMPARATOR; +static const LLAvatarItemRecentSpeakerComparator RECENT_SPEAKER_COMPARATOR; static LLRegisterPanelClassWrapper<LLPanelPeople> t_people("panel_people"); @@ -434,6 +511,7 @@ BOOL LLPanelPeople::postBuild() setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false); setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false); + setSortOrder(mNearbyList, (ESortOrder)gSavedSettings.getU32("NearbyPeopleSortOrder"), false); LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME); groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked, this)); @@ -454,7 +532,7 @@ BOOL LLPanelPeople::postBuild() mNearbyList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mNearbyList)); mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mRecentList)); - mGroupList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this)); + mGroupList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this)); mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this)); LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>("tab_all"); @@ -494,7 +572,8 @@ BOOL LLPanelPeople::postBuild() enable_registrar.add("People.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2)); enable_registrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2)); - + enable_registrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2)); + LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mGroupPlusMenuHandle = plus_menu->getHandle(); @@ -573,8 +652,13 @@ void LLPanelPeople::updateNearbyList() if (!mNearbyList) return; - LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); + std::vector<LLVector3d> positions; + + LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); mNearbyList->setDirty(); + + DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs()); + LLLocalSpeakerMgr::instance().update(TRUE); } void LLPanelPeople::updateRecentList() @@ -667,8 +751,10 @@ void LLPanelPeople::updateButtons() buttonSetEnabled("im_btn", (selected_uuids.size() >= 1)); // allow starting the friends conference for multiple selection buttonSetEnabled("call_btn", item_selected && false); // not implemented yet buttonSetEnabled("share_btn", item_selected && false); // not implemented yet - buttonSetEnabled("group_info_btn", item_selected); - buttonSetEnabled("chat_btn", item_selected); + + bool none_group_selected = item_selected && selected_id.isNull(); + buttonSetEnabled("group_info_btn", !none_group_selected); + buttonSetEnabled("chat_btn", !none_group_selected); } std::string LLPanelPeople::getActiveTabName() const @@ -758,6 +844,14 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save list->setComparator(&RECENT_COMPARATOR); list->sort(); break; + case E_SORT_BY_RECENT_SPEAKERS: + list->setComparator(&RECENT_SPEAKER_COMPARATOR); + list->sort(); + break; + case E_SORT_BY_DISTANCE: + list->setComparator(&DISTANCE_COMPARATOR); + list->sort(); + break; default: llwarns << "Unrecognized people sort order for " << list->getName() << llendl; return; @@ -772,7 +866,7 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save else if (list == mRecentList) setting = "RecentPeopleSortOrder"; else if (list == mNearbyList) - setting = "NearbyPeopleSortOrder"; // *TODO: unused by current implementation + setting = "NearbyPeopleSortOrder"; if (!setting.empty()) gSavedSettings.setU32(setting, order); @@ -992,9 +1086,6 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata) mAllFriendList->toggleIcons(); mOnlineFriendList->toggleIcons(); } - else if (chosen_item == "organize_offline") - { - } } void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata) @@ -1011,12 +1102,13 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata) { std::string chosen_item = userdata.asString(); - if (chosen_item == "sort_recent") + if (chosen_item == "sort_by_recent_speakers") { + setSortOrder(mNearbyList, E_SORT_BY_RECENT_SPEAKERS); } else if (chosen_item == "sort_name") { - mNearbyList->sortByName(); + setSortOrder(mNearbyList, E_SORT_BY_NAME); } else if (chosen_item == "view_icons") { @@ -1024,8 +1116,25 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata) } else if (chosen_item == "sort_distance") { + setSortOrder(mNearbyList, E_SORT_BY_DISTANCE); } } + +bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata) +{ + std::string item = userdata.asString(); + U32 sort_order = gSavedSettings.getU32("NearbyPeopleSortOrder"); + + if (item == "sort_by_recent_speakers") + return sort_order == E_SORT_BY_RECENT_SPEAKERS; + if (item == "sort_name") + return sort_order == E_SORT_BY_NAME; + if (item == "sort_distance") + return sort_order == E_SORT_BY_DISTANCE; + + return false; +} + void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata) { std::string chosen_item = userdata.asString(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 9bf9befe90..faed573eca 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -62,6 +62,8 @@ private: E_SORT_BY_NAME = 0, E_SORT_BY_STATUS = 1, E_SORT_BY_MOST_RECENT = 2, + E_SORT_BY_DISTANCE = 3, + E_SORT_BY_RECENT_SPEAKERS = 4, } ESortOrder; // methods indirectly called by the updaters @@ -115,6 +117,7 @@ private: bool onFriendsViewSortMenuItemCheck(const LLSD& userdata); bool onRecentViewSortMenuItemCheck(const LLSD& userdata); + bool onNearbyViewSortMenuItemCheck(const LLSD& userdata); // misc callbacks static void onAvatarPicked( diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 726c47b678..da0c8d5020 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -413,6 +413,8 @@ BOOL LLPanelPickEdit::postBuild() childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPickEdit::onClickSave, this)); childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPickEdit::onClickSetLocation, this)); + initTexturePickerMouseEvents(); + return TRUE; } diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index c600651015..906f8d084b 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -40,6 +40,7 @@ #include "llsdutil_math.h" +#include "lliconctrl.h" #include "llscrollcontainer.h" #include "lltextbox.h" @@ -81,6 +82,7 @@ BOOL LLPanelPlaceInfo::postBuild() mParcelName = getChild<LLTextBox>("parcel_title"); mDescEditor = getChild<LLExpandableTextBox>("description"); + mMaturityRatingIcon = getChild<LLIconCtrl>("maturity_icon"); mMaturityRatingText = getChild<LLTextBox>("maturity_value"); LLScrollContainer* scroll_container = getChild<LLScrollContainer>("place_scroll"); @@ -98,6 +100,7 @@ void LLPanelPlaceInfo::resetLocation() mPosRegion.clearVec(); std::string not_available = getString("not_available"); + mMaturityRatingIcon->setValue(not_available); mMaturityRatingText->setValue(not_available); mRegionName->setText(not_available); mParcelName->setText(not_available); @@ -204,20 +207,6 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) mDescEditor->setText(parcel_data.desc); } - // HACK: Flag 0x2 == adult region, - // Flag 0x1 == mature region, otherwise assume PG - std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG); - if (parcel_data.flags & 0x2) - { - rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT); - } - else if (parcel_data.flags & 0x1) - { - rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE); - } - - mMaturityRatingText->setValue(rating); - S32 region_x; S32 region_y; S32 region_z; diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index ec30397cff..ba32cc4c34 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -41,6 +41,7 @@ #include "llremoteparcelrequest.h" class LLExpandableTextBox; +class LLIconCtrl; class LLInventoryItem; class LLPanelPickEdit; class LLParcel; @@ -117,6 +118,7 @@ protected: LLTextBox* mRegionName; LLTextBox* mParcelName; LLExpandableTextBox* mDescEditor; + LLIconCtrl* mMaturityRatingIcon; LLTextBox* mMaturityRatingText; }; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index b2a9f6f251..61501cc1b1 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -55,6 +55,23 @@ static LLRegisterPanelClassWrapper<LLPanelPlaceProfile> t_place_profile("panel_place_profile"); +// Statics for textures filenames +static std::string icon_pg; +static std::string icon_m; +static std::string icon_r; +static std::string icon_voice; +static std::string icon_voice_no; +static std::string icon_fly; +static std::string icon_fly_no; +static std::string icon_push; +static std::string icon_push_no; +static std::string icon_build; +static std::string icon_build_no; +static std::string icon_scripts; +static std::string icon_scripts_no; +static std::string icon_damage; +static std::string icon_damage_no; + LLPanelPlaceProfile::LLPanelPlaceProfile() : LLPanelPlaceInfo(), mForSalePanel(NULL), @@ -80,7 +97,6 @@ BOOL LLPanelPlaceProfile::postBuild() setMouseDownCallback(boost::bind(&LLPanelPlaceProfile::onForSaleBannerClick, this)); mParcelOwner = getChild<LLTextBox>("owner_value"); - mLastVisited = getChild<LLTextBox>("last_visited_value"); mParcelRatingIcon = getChild<LLIconCtrl>("rating_icon"); mParcelRatingText = getChild<LLTextBox>("rating_value"); @@ -119,6 +135,22 @@ BOOL LLPanelPlaceProfile::postBuild() mResaleText = getChild<LLTextEditor>("resale"); mSaleToText = getChild<LLTextBox>("sale_to"); + icon_pg = getString("icon_PG"); + icon_m = getString("icon_M"); + icon_r = getString("icon_R"); + icon_voice = getString("icon_Voice"); + icon_voice_no = getString("icon_VoiceNo"); + icon_fly = getString("icon_Fly"); + icon_fly_no = getString("icon_FlyNo"); + icon_push = getString("icon_Push"); + icon_push_no = getString("icon_PushNo"); + icon_build = getString("icon_Build"); + icon_build_no = getString("icon_BuildNo"); + icon_scripts = getString("icon_Scripts"); + icon_scripts_no = getString("icon_ScriptsNo"); + icon_damage = getString("icon_Damage"); + icon_damage_no = getString("icon_DamageNo"); + return TRUE; } @@ -132,7 +164,6 @@ void LLPanelPlaceProfile::resetLocation() std::string not_available = getString("not_available"); mParcelOwner->setValue(not_available); - mLastVisited->setValue(not_available); mParcelRatingIcon->setValue(not_available); mParcelRatingText->setText(not_available); @@ -176,17 +207,13 @@ void LLPanelPlaceProfile::resetLocation() void LLPanelPlaceProfile::setInfoType(INFO_TYPE type) { bool is_info_type_agent = type == AGENT; - bool is_info_type_teleport_history = type == TELEPORT_HISTORY; - getChild<LLTextBox>("maturity_label")->setVisible(!is_info_type_agent); + mMaturityRatingIcon->setVisible(!is_info_type_agent); mMaturityRatingText->setVisible(!is_info_type_agent); getChild<LLTextBox>("owner_label")->setVisible(is_info_type_agent); mParcelOwner->setVisible(is_info_type_agent); - getChild<LLTextBox>("last_visited_label")->setVisible(is_info_type_teleport_history); - mLastVisited->setVisible(is_info_type_teleport_history); - getChild<LLAccordionCtrl>("advanced_info_accordion")->setVisible(is_info_type_agent); switch(type) @@ -205,6 +232,30 @@ void LLPanelPlaceProfile::setInfoType(INFO_TYPE type) LLPanelPlaceInfo::setInfoType(type); } +// virtual +void LLPanelPlaceProfile::processParcelInfo(const LLParcelData& parcel_data) +{ + LLPanelPlaceInfo::processParcelInfo(parcel_data); + + // HACK: Flag 0x2 == adult region, + // Flag 0x1 == mature region, otherwise assume PG + if (parcel_data.flags & 0x2) + { + mMaturityRatingIcon->setValue(icon_r); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_ADULT)); + } + else if (parcel_data.flags & 0x1) + { + mMaturityRatingIcon->setValue(icon_m); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_MATURE)); + } + else + { + mMaturityRatingIcon->setValue(icon_pg); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG)); + } +} + void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, LLViewerRegion* region, const LLVector3d& pos_global, @@ -231,22 +282,22 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, case SIM_ACCESS_MATURE: parcel_data.flags = 0x1; - mParcelRatingIcon->setValue("parcel_drk_M"); - mRegionRatingIcon->setValue("parcel_drk_M"); + mParcelRatingIcon->setValue(icon_m); + mRegionRatingIcon->setValue(icon_m); break; case SIM_ACCESS_ADULT: parcel_data.flags = 0x2; - mParcelRatingIcon->setValue("parcel_drk_R"); - mRegionRatingIcon->setValue("parcel_drk_R"); + mParcelRatingIcon->setValue(icon_r); + mRegionRatingIcon->setValue(icon_r); break; default: parcel_data.flags = 0; - mParcelRatingIcon->setValue("parcel_drk_PG"); - mRegionRatingIcon->setValue("parcel_drk_PG"); + mParcelRatingIcon->setValue(icon_pg); + mRegionRatingIcon->setValue(icon_pg); } std::string rating = LLViewerRegion::accessToString(sim_access); @@ -270,45 +321,45 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, // Processing parcel characteristics if (parcel->getParcelFlagAllowVoice()) { - mVoiceIcon->setValue("parcel_drk_Voice"); + mVoiceIcon->setValue(icon_voice); mVoiceText->setText(on); } else { - mVoiceIcon->setValue("parcel_drk_VoiceNo"); + mVoiceIcon->setValue(icon_voice_no); mVoiceText->setText(off); } if (!region->getBlockFly() && parcel->getAllowFly()) { - mFlyIcon->setValue("parcel_drk_Fly"); + mFlyIcon->setValue(icon_fly); mFlyText->setText(on); } else { - mFlyIcon->setValue("parcel_drk_FlyNo"); + mFlyIcon->setValue(icon_fly_no); mFlyText->setText(off); } if (region->getRestrictPushObject() || parcel->getRestrictPushObject()) { - mPushIcon->setValue("parcel_drk_PushNo"); + mPushIcon->setValue(icon_push_no); mPushText->setText(off); } else { - mPushIcon->setValue("parcel_drk_Push"); + mPushIcon->setValue(icon_push); mPushText->setText(on); } if (parcel->getAllowModify()) { - mBuildIcon->setValue("parcel_drk_Build"); + mBuildIcon->setValue(icon_build); mBuildText->setText(on); } else { - mBuildIcon->setValue("parcel_drk_BuildNo"); + mBuildIcon->setValue(icon_build_no); mBuildText->setText(off); } @@ -316,23 +367,23 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) || !parcel->getAllowOtherScripts()) { - mScriptsIcon->setValue("parcel_drk_ScriptsNo"); + mScriptsIcon->setValue(icon_scripts_no); mScriptsText->setText(off); } else { - mScriptsIcon->setValue("parcel_drk_Scripts"); + mScriptsIcon->setValue(icon_scripts); mScriptsText->setText(on); } if (region->getAllowDamage() || parcel->getAllowDamage()) { - mDamageIcon->setValue("parcel_drk_Damage"); + mDamageIcon->setValue(icon_damage); mDamageText->setText(on); } else { - mDamageIcon->setValue("parcel_drk_DamageNo"); + mDamageIcon->setValue(icon_damage_no); mDamageText->setText(off); } @@ -488,22 +539,6 @@ void LLPanelPlaceProfile::updateCovenantText(const std::string &text) mCovenantText->setText(text); } -void LLPanelPlaceProfile::updateLastVisitedText(const LLDate &date) -{ - if (date.isNull()) - { - mLastVisited->setText(getString("unknown")); - } - else - { - std::string timeStr = getString("acquired_date"); - LLSD substitution; - substitution["datetime"] = (S32) date.secondsSinceEpoch(); - LLStringUtil::format (timeStr, substitution); - mLastVisited->setText(timeStr); - } -} - void LLPanelPlaceProfile::onForSaleBannerClick() { LLViewerParcelMgr* mgr = LLViewerParcelMgr::getInstance(); @@ -541,7 +576,7 @@ void LLPanelPlaceProfile::updateYouAreHereBanner(void* userdata) if(!self->getVisible()) return; - if(!gDisconnected) + if(!gDisconnected && gAgent.getRegion()) { static F32 radius = gSavedSettings.getF32("YouAreHereDistance"); diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index b3ef4acf51..8c30ca92fb 100644 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -50,6 +50,8 @@ public: /*virtual*/ void setInfoType(INFO_TYPE type); + /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); + // Displays information about the currently selected parcel // without sending a request to the server. // If is_current_parcel true shows "You Are Here" banner. @@ -61,7 +63,6 @@ public: void updateEstateName(const std::string& name); void updateEstateOwnerName(const std::string& name); void updateCovenantText(const std::string &text); - void updateLastVisitedText(const LLDate &date); private: void onForSaleBannerClick(); @@ -78,7 +79,6 @@ private: LLPanel* mYouAreHerePanel; LLTextBox* mParcelOwner; - LLTextBox* mLastVisited; LLIconCtrl* mParcelRatingIcon; LLTextBox* mParcelRatingText; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 0784e4555f..3d0fba9426 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -293,7 +293,6 @@ void LLPanelPlaces::onOpen(const LLSD& key) mPosGlobal = hist_items[index].mGlobalPos; mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY); - mPlaceProfile->updateLastVisitedText(hist_items[index].mDate); mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal); } @@ -587,7 +586,7 @@ void LLPanelPlaces::onOverflowButtonClicked() if (mItem.notNull()) { const LLUUID& item_id = mItem->getUUID(); - const LLUUID& trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); is_landmark_removable = gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID()) && !gInventory.isObjectDescendentOf(item_id, trash_id); } @@ -669,7 +668,7 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param) { if ( mItem.notNull() ) { - LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + const LLUUID& favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); if ( favorites_id.notNull() ) { copy_inventory_item(gAgent.getID(), diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 58ca481b77..73e19b3b2a 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -228,6 +228,7 @@ void LLPanelPrimMediaControls::updateShape() bool can_navigate = parcel->getMediaAllowNavigate(); bool enabled = false; + bool is_zoomed = (mCurrentZoom != ZOOM_NONE); // There is no such thing as "has_focus" being different from normal controls set // anymore (as of user feedback from bri 10/09). So we cheat here and force 'has_focus' // to 'true' (or, actually, we use a setting) @@ -256,7 +257,7 @@ void LLPanelPrimMediaControls::updateShape() LLUICtrl* stop_ctrl = getChild<LLUICtrl>("stop"); LLUICtrl* media_stop_ctrl = getChild<LLUICtrl>("media_stop"); LLUICtrl* home_ctrl = getChild<LLUICtrl>("home"); - LLUICtrl* close_ctrl = getChild<LLUICtrl>("close"); + LLUICtrl* unzoom_ctrl = getChild<LLUICtrl>("close"); // This is actually "unzoom" LLUICtrl* open_ctrl = getChild<LLUICtrl>("new_window"); LLUICtrl* zoom_ctrl = getChild<LLUICtrl>("zoom_frame"); LLPanel* media_loading_panel = getChild<LLPanel>("media_progress_indicator"); @@ -283,7 +284,8 @@ void LLPanelPrimMediaControls::updateShape() reload_ctrl->setVisible(has_focus); stop_ctrl->setVisible(false); home_ctrl->setVisible(has_focus); - close_ctrl->setVisible(has_focus); + zoom_ctrl->setVisible(!is_zoomed); + unzoom_ctrl->setVisible(has_focus && is_zoomed); open_ctrl->setVisible(true); media_address_ctrl->setVisible(has_focus && !mini_controls); media_play_slider_panel->setVisible(has_focus && !mini_controls); @@ -294,6 +296,7 @@ void LLPanelPrimMediaControls::updateShape() whitelist_icon->setVisible(!mini_controls && (media_data)?media_data->getWhiteListEnable():false); // Disable zoom if HUD zoom_ctrl->setEnabled(!objectp->isHUDAttachment()); + unzoom_ctrl->setEnabled(!objectp->isHUDAttachment()); secure_lock_icon->setVisible(false); mCurrentURL = media_impl->getCurrentMediaURL(); @@ -691,24 +694,31 @@ bool LLPanelPrimMediaControls::isMouseOver() getWindow()->getCursorPosition(&cursor_pos_window); getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); - LLPanel* controls_panel = NULL; - controls_panel = getChild<LLPanel>("media_hover_controls"); - if(controls_panel && !controls_panel->getVisible()) - { - // The hover controls aren't visible -- use the focused controls instead. - controls_panel = getChild<LLPanel>("media_focused_controls"); - } + LLView* controls_view = NULL; + controls_view = getChild<LLView>("media_controls"); - if(controls_panel && controls_panel->getVisible()) + if(controls_view && controls_view->getVisible()) { - controls_panel->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &x, &y); + controls_view->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &x, &y); - LLView *hit_child = controls_panel->childFromPoint(x, y); - if(hit_child) + LLView *hit_child = controls_view->childFromPoint(x, y); + if(hit_child && hit_child->getVisible()) { // This was useful for debugging both coordinate translation and view hieararchy problems... -// llinfos << "mouse coords: " << x << ", " << y << " hit child " << hit_child->getName() << llendl; - result = true; + // llinfos << "mouse coords: " << x << ", " << y << " hit child " << hit_child->getName() << llendl; + + // This will be a direct child of the LLLayoutStack, which should be a layout_panel. + // These may not shown/hidden by the logic in updateShape(), so we need to do another hit test on the children of the layout panel, + // which are the actual controls. + hit_child->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &x, &y); + + LLView *hit_child_2 = hit_child->childFromPoint(x, y); + if(hit_child_2 && hit_child_2->getVisible()) + { + // This was useful for debugging both coordinate translation and view hieararchy problems... + // llinfos << " mouse coords: " << x << ", " << y << " hit child 2 " << hit_child_2->getName() << llendl; + result = true; + } } } } diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index b404c8db4c..b0a71f1ebe 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -59,17 +59,61 @@ public: return false; } - if (params[1].asString() == "about") + const std::string verb = params[1].asString(); + if (verb == "about") { LLAvatarActions::showProfile(avatar_id); return true; } - if (params[1].asString() == "inspect") + if (verb == "inspect") { LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", avatar_id)); return true; } + + if (verb == "im") + { + LLAvatarActions::startIM(avatar_id); + return true; + } + + if (verb == "pay") + { + LLAvatarActions::pay(avatar_id); + return true; + } + + if (verb == "offerteleport") + { + LLAvatarActions::offerTeleport(avatar_id); + return true; + } + + if (verb == "requestfriend") + { + LLAvatarActions::requestFriendshipDialog(avatar_id); + return true; + } + + if (verb == "mute") + { + if (! LLAvatarActions::isBlocked(avatar_id)) + { + LLAvatarActions::toggleBlock(avatar_id); + } + return true; + } + + if (verb == "unmute") + { + if (LLAvatarActions::isBlocked(avatar_id)) + { + LLAvatarActions::toggleBlock(avatar_id); + } + return true; + } + return false; } }; diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 437af1c4e7..72856d5b82 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -71,9 +71,10 @@ public: static void showPlaceInfoPanel(S32 index); private: - void onInfoBtnClick(); + void onProfileBtnClick(); - LLButton* mInfoBtn; + LLButton* mProfileBtn; + LLTeleportHistoryPanel::ContextMenu *mContextMenu; S32 mIndex; @@ -95,8 +96,9 @@ BOOL LLTeleportHistoryFlatItem::postBuild() LLTextBox *region = getChild<LLTextBox>("region"); region->setValue(mRegionName); - mInfoBtn = getChild<LLButton>("info_btn"); - mInfoBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onInfoBtnClick, this)); + mProfileBtn = getChild<LLButton>("profile_btn"); + + mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this)); return true; } @@ -111,7 +113,7 @@ void LLTeleportHistoryFlatItem::setValue(const LLSD& value) void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask) { childSetVisible("hovered_icon", true); - mInfoBtn->setVisible(true); + mProfileBtn->setVisible(true); LLPanel::onMouseEnter(x, y, mask); } @@ -119,7 +121,7 @@ void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask) void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask) { childSetVisible("hovered_icon", false); - mInfoBtn->setVisible(false); + mProfileBtn->setVisible(false); LLPanel::onMouseLeave(x, y, mask); } @@ -142,7 +144,7 @@ void LLTeleportHistoryFlatItem::showPlaceInfoPanel(S32 index) LLSideTray::getInstance()->showPanel("panel_places", params); } -void LLTeleportHistoryFlatItem::onInfoBtnClick() +void LLTeleportHistoryFlatItem::onProfileBtnClick() { LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex); } @@ -357,7 +359,7 @@ void LLTeleportHistoryPanel::onCopySLURL() U64 new_region_handle = to_region_handle(global_pos); - LLWorldMap::url_callback_t cb = boost::bind( + LLWorldMapMessage::url_callback_t cb = boost::bind( &LLPanelPlacesTab::onRegionResponse, this, global_pos, _1, _2, _3, _4); @@ -404,6 +406,7 @@ void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, L if (tab_idx <= tabs_cnt - 4) { + // All tabs, except last three, are tabs for one day, so just push tab_date back by one day tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day); } else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month @@ -440,6 +443,7 @@ void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, L } } +// Called to add items, no more, than ADD_LIMIT at time void LLTeleportHistoryPanel::refresh() { if (!mHistoryAccordion) @@ -450,12 +454,16 @@ void LLTeleportHistoryPanel::refresh() const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems(); + // Setting tab_boundary_date to "now", so date from any item would be earlier, than boundary. + // That leads to call to getNextTab to get right tab_idx in first pass LLDate tab_boundary_date = LLDate::now(); + LLFlatListView* curr_flat_view = NULL; U32 added_items = 0; while (mCurrentItem >= 0) { + // Filtering std::string landmark_title = items[mCurrentItem].mTitle; LLStringUtil::toUpper(landmark_title); @@ -468,10 +476,14 @@ void LLTeleportHistoryPanel::refresh() continue; } + // Checking whether date of item is earlier, than tab_boundary_date. + // In that case, item should be added to another tab const LLDate &date = items[mCurrentItem].mDate; if (date < tab_boundary_date) { + // Getting apropriate tab_idx for this and subsequent items, + // tab_boundary_date would be earliest possible date for this tab S32 tab_idx = 0; getNextTab(date, tab_idx, tab_boundary_date); @@ -578,6 +590,9 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index) void LLTeleportHistoryPanel::showTeleportHistory() { mDirty = true; + + // Starting to add items from last one, in reverse order, + // since TeleportHistory keeps most recent item at the end mCurrentItem = mTeleportHistory->getItems().size() - 1; for (S32 n = mItemContainers.size() - 1; n >= 0; --n) diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 4ac109bf3d..5a70842a73 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -57,7 +57,6 @@ #include "llfirstuse.h" #include "llfocusmgr.h" #include "llmanipscale.h" -#include "llpanelinventory.h" #include "llpreviewscript.h" #include "llresmgr.h" #include "llselectmgr.h" diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index 9d197aafa5..7bc935f986 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -45,7 +45,6 @@ class LLUICtrl; class LLButton; class LLViewerObject; class LLComboBox; -class LLPanelInventory; class LLColorSwatchCtrl; class LLPanelVolume : public LLPanel diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index edff706fee..2be0781487 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -42,6 +42,9 @@ #include "llspeakers.h" //LLParticipantList retrieves add, clear and remove events and updates view accordingly +#if LL_MSVC +#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally +#endif LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list): mSpeakerMgr(data_source), mAvatarList(avatar_list), @@ -50,13 +53,16 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av mSpeakerAddListener = new SpeakerAddListener(*this); mSpeakerRemoveListener = new SpeakerRemoveListener(*this); mSpeakerClearListener = new SpeakerClearListener(*this); + mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this); mSpeakerMgr->addListener(mSpeakerAddListener, "add"); mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove"); mSpeakerMgr->addListener(mSpeakerClearListener, "clear"); + mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); + mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); //Lets fill avatarList with existing speakers LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); @@ -65,7 +71,12 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av mSpeakerMgr->getSpeakerList(&speaker_list, true); for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) { - group_members.push_back((*it)->mID); + const LLPointer<LLSpeaker>& speakerp = *it; + group_members.push_back(speakerp->mID); + if ( speakerp->mIsModerator ) + { + mModeratorList.insert(speakerp->mID); + } } sort(); } @@ -84,6 +95,56 @@ void LLParticipantList::onAvatarListDoubleClicked(LLAvatarList* list) LLAvatarActions::startIM(clicked_id); } +void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) +{ + LLAvatarList* list = dynamic_cast<LLAvatarList*>(ctrl); + if (list) + { + const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); + const std::size_t moderator_indicator_len = moderator_indicator.length(); + + // Firstly remove moderators indicator + std::set<LLUUID>::const_iterator + moderator_list_it = mModeratorToRemoveList.begin(), + moderator_list_end = mModeratorToRemoveList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + { + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)); + if ( item ) + { + std::string name = item->getAvatarName(); + size_t found = name.find(moderator_indicator); + if (found == std::string::npos) + { + name.erase(found, moderator_indicator_len); + item->setName(name); + } + } + } + + mModeratorToRemoveList.clear(); + + // Add moderators indicator + moderator_list_it = mModeratorList.begin(); + moderator_list_end = mModeratorList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + { + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)); + if ( item ) + { + std::string name = item->getAvatarName(); + size_t found = name.find(moderator_indicator); + if (found == std::string::npos) + { + name += " "; + name += moderator_indicator; + item->setName(name); + } + } + } + } +} + void LLParticipantList::setSortOrder(EParticipantSortOrder order) { if ( mSortOrder != order ) @@ -106,6 +167,8 @@ bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, co } group_members.push_back(uu_id); + // Mark AvatarList as dirty one + mAvatarList->setDirty(); sort(); return true; } @@ -130,14 +193,36 @@ bool LLParticipantList::onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, return true; } +bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + const LLSD& evt_data = event->getValue(); + if ( evt_data.has("id") && evt_data.has("is_moderator") ) + { + LLUUID id = evt_data["id"]; + bool is_moderator = evt_data["is_moderator"]; + if ( id.notNull() ) + { + if ( is_moderator ) + mModeratorList.insert(id); + else + { + std::set<LLUUID>::iterator it = mModeratorList.find (id); + if ( it != mModeratorList.end () ) + { + mModeratorToRemoveList.insert(id); + mModeratorList.erase(id); + } + } + } + } + return true; +} + void LLParticipantList::sort() { if ( !mAvatarList ) return; - // Mark AvatarList as dirty one - mAvatarList->setDirty(); - // TODO: Implement more sorting orders after specs updating (EM) switch ( mSortOrder ) { case E_SORT_BY_NAME : @@ -172,3 +257,11 @@ bool LLParticipantList::SpeakerClearListener::handleEvent(LLPointer<LLOldEvents: { return mParent.onClearListEvent(event, userdata); } + +// +// LLParticipantList::SpeakerModeratorListener +// +bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + return mParent.onModeratorUpdateEvent(event, userdata); +} diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 8c209c0b20..fc34dd308b 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -35,6 +35,7 @@ class LLSpeakerMgr; class LLAvatarList; +class LLUICtrl; class LLParticipantList { @@ -59,6 +60,7 @@ class LLParticipantList bool onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); /** * Sorts the Avatarlist by stored order @@ -97,15 +99,27 @@ class LLParticipantList /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); }; + class SpeakerModeratorUpdateListener : public BaseSpeakerListner + { + public: + SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + }; + private: void onAvatarListDoubleClicked(LLAvatarList* list); + void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); LLSpeakerMgr* mSpeakerMgr; LLAvatarList* mAvatarList; - LLPointer<SpeakerAddListener> mSpeakerAddListener; - LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener; - LLPointer<SpeakerClearListener> mSpeakerClearListener; + std::set<LLUUID> mModeratorList; + std::set<LLUUID> mModeratorToRemoveList; + + LLPointer<SpeakerAddListener> mSpeakerAddListener; + LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener; + LLPointer<SpeakerClearListener> mSpeakerClearListener; + LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; EParticipantSortOrder mSortOrder; }; diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index b3b4857727..83443687c9 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -38,6 +38,7 @@ #include "llfloaterinventory.h" // for LLInventoryPanel #include "llfolderview.h" // for FIRST_SELECTED_ITEM +#include "llinventorypanel.h" static const std::string LANDMARKS_INVENTORY_LIST_NAME("landmarks_list"); @@ -83,7 +84,7 @@ void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601 } - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } @@ -116,7 +117,7 @@ void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // repeat parent functionality sSelf = this; // necessary for "New Folder" functionality - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } } diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index b06e70c00a..34e78b5c46 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -45,6 +45,7 @@ #include "lltooldraganddrop.h" #include "llradiogroup.h" #include "llassetstorage.h" +#include "llviewerassettype.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "lldbstrings.h" @@ -317,7 +318,7 @@ BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask) && LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) { EDragAndDropType type; - type = LLAssetType::lookupDragAndDropType(item->getType()); + type = LLViewerAssetType::lookupDragAndDropType(item->getType()); LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY; if(!mObjectUUID.isNull()) { @@ -406,7 +407,7 @@ void LLPreview::onDiscardBtn(void* data) */ // Move the item to the trash - LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if (item->getParentUUID() != trash_id) { LLInventoryModel::update_list_t update; diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index ab2afb8056..7b3a20d102 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -130,10 +130,10 @@ LLPreviewGesture* LLPreviewGesture::show(const LLUUID& item_id, const LLUUID& ob preview->setObjectID(object_id); // Start speculative download of sounds and animations - LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_ANIMATION); + const LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ANIMATION); gInventory.startBackgroundFetch(animation_folder_id); - LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_SOUND); + const LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SOUND); gInventory.startBackgroundFetch(sound_folder_id); // this will call refresh when we have everything. diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index b391c6ff1d..2382befcfa 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -89,7 +89,6 @@ #include "lltrans.h" #include "llviewercontrol.h" #include "llappviewer.h" -#include "llpanelinventory.h" const std::string HELLO_LSL = "default\n" diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 9c21faa3be..3eab13fc4a 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -48,6 +48,7 @@ #include "lltextbox.h" #include "lltextureview.h" #include "llui.h" +#include "llviewerinventory.h" #include "llviewertexture.h" #include "llviewertexturelist.h" #include "lluictrlfactory.h" @@ -63,7 +64,7 @@ const F32 PREVIEW_TEXTURE_MIN_ASPECT = 0.005f; LLPreviewTexture::LLPreviewTexture(const LLSD& key) - : LLPreview( key ), + : LLPreview(key), mLoadingFullImage( FALSE ), mShowKeepDiscard(FALSE), mCopyToInv(FALSE), @@ -71,7 +72,8 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key) mUpdateDimensions(TRUE), mLastHeight(0), mLastWidth(0), - mAspectRatio(0.f) + mAspectRatio(0.f), + mPreviewToSave(FALSE) { const LLInventoryItem *item = getItem(); if(item) @@ -104,6 +106,10 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key) mIsCopyable = TRUE; } + if (key.has("save_as")) + { + mPreviewToSave = TRUE; + } //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_texture.xml", FALSE); } @@ -181,6 +187,12 @@ void LLPreviewTexture::draw() if ( mImage.notNull() ) { + // Automatically bring up SaveAs dialog if we opened this to save the texture. + if (mPreviewToSave) + { + mPreviewToSave = FALSE; + saveAs(); + } // Draw the texture glColor3f( 1.f, 1.f, 1.f ); gl_draw_scaled_image(interior.mLeft, @@ -209,7 +221,7 @@ void LLPreviewTexture::draw() if( mLoadingFullImage ) { - LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("Receiving:"), 0, + LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("Receiving"), 0, interior.mLeft + 4, interior.mBottom + 4, LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM, @@ -304,6 +316,11 @@ void LLPreviewTexture::onFocusReceived() LLPreview::onFocusReceived(); } +void LLPreviewTexture::openToSave() +{ + mPreviewToSave = TRUE; +} + // static void LLPreviewTexture::onFileLoadedForSave(BOOL success, LLViewerFetchedTexture *src_vi, @@ -356,6 +373,7 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success, { LLNotifications::instance().add("CannotDownloadFile"); } + } @@ -552,8 +570,9 @@ void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata) void LLPreviewTexture::loadAsset() { - mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mImage->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + mImage->forceToSaveRawImage(0) ; mAssetStatus = PREVIEW_ASSET_LOADING; updateDimensions(); } diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index 520626b49f..9b3c91d831 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -67,8 +67,7 @@ public: S32 discard_level, BOOL final, void* userdata ); - - + void openToSave(); protected: void init(); /* virtual */ BOOL postBuild(); @@ -77,14 +76,17 @@ protected: private: void updateDimensions(); - LLUUID mImageID; + LLUUID mImageID; LLPointer<LLViewerFetchedTexture> mImage; BOOL mLoadingFullImage; std::string mSaveFileName; LLFrameTimer mSavedFileTimer; BOOL mShowKeepDiscard; BOOL mCopyToInv; - + + // Save the image once it's loaded. + BOOL mPreviewToSave; + // This is stored off in a member variable, because the save-as // button and drag and drop functionality need to know. BOOL mIsCopyable; @@ -94,6 +96,4 @@ private: F32 mAspectRatio; BOOL mUpdateDimensions; }; - - #endif // LL_LLPREVIEWTEXTURE_H diff --git a/indra/newview/llresourcedata.h b/indra/newview/llresourcedata.h index 46b79150bb..b4b9042689 100644 --- a/indra/newview/llresourcedata.h +++ b/indra/newview/llresourcedata.h @@ -39,11 +39,12 @@ struct LLResourceData { LLAssetInfo mAssetInfo; - LLAssetType::EType mPreferredLocation; + LLFolderType::EType mPreferredLocation; LLInventoryType::EType mInventoryType; U32 mNextOwnerPerm; S32 mExpectedUploadCost; void *mUserData; + static const S8 INVALID_LOCATION = -2; }; #endif diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 987bc4b596..fd31690622 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -204,8 +204,7 @@ public: // signal on rejecting of a toast event typedef boost::function<void (LLUUID id)> reject_tost_callback_t; typedef boost::signals2::signal<void (LLUUID id)> reject_tost_signal_t; - reject_tost_signal_t mRejectToastSignal; - boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); } + reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); } private: struct ToastElem diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp index 0a520ff65f..1fbaeb94f5 100644 --- a/indra/newview/llscrollingpanelparam.cpp +++ b/indra/newview/llscrollingpanelparam.cpp @@ -209,7 +209,7 @@ void LLScrollingPanelParam::onSliderMoved(LLUICtrl* ctrl, void* userdata) F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() ); if (current_weight != new_weight ) { - self->mWearable->setVisualParamWeight( param->getID(), new_weight, TRUE ); + self->mWearable->setVisualParamWeight( param->getID(), new_weight, FALSE ); gAgent.getAvatarObject()->updateVisualParams(); } } @@ -298,7 +298,7 @@ void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint ) if (slider->getMinValue() < new_percent && new_percent < slider->getMaxValue()) { - mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight, TRUE); + mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight, FALSE); gAgent.getAvatarObject()->updateVisualParams(); slider->setValue( weightToPercent( new_weight ) ); @@ -330,7 +330,7 @@ void LLScrollingPanelParam::onHintMinMouseUp( void* userdata ) if (slider->getMinValue() < new_percent && new_percent < slider->getMaxValue()) { - self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, TRUE); + self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE); slider->setValue( self->weightToPercent( new_weight ) ); } } @@ -364,7 +364,7 @@ void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata ) if (slider->getMinValue() < new_percent && new_percent < slider->getMaxValue()) { - self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, TRUE); + self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE); slider->setValue( self->weightToPercent( new_weight ) ); } } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 759c86f3a0..4cb561381d 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -67,6 +67,7 @@ #include "llinventorymodel.h" #include "llmenugl.h" #include "llmutelist.h" +#include "llsidepaneltaskinfo.h" #include "llslurl.h" #include "llstatusbar.h" #include "llsurface.h" @@ -1448,7 +1449,7 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) // Texture picker defaults aren't inventory items // * Don't need to worry about permissions for them // * Can just apply the texture and be done with it. - objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE)); + objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } return true; } @@ -1604,7 +1605,7 @@ BOOL LLSelectMgr::selectionRevertTextures() } else { - object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE)); + object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } } } @@ -2827,7 +2828,7 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, case 0: { // TODO: Make sure you have delete permissions on all of them. - LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); // attempt to derez into the trash. LLDeRezInfo* info = new LLDeRezInfo(DRD_TRASH, trash_id); LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", @@ -3406,7 +3407,7 @@ void LLSelectMgr::deselectAll() { return; } - + // Zap the angular velocity, as the sim will set it to zero for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); iter != mSelectedObjects->end(); iter++ ) @@ -3496,6 +3497,7 @@ void LLSelectMgr::deselectAllIfTooFar() LLVector3d selectionCenter = getSelectionCenterGlobal(); if (gSavedSettings.getBOOL("LimitSelectDistance") && (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar()) + && (mSelectedObjects->getPrimaryObject() != LLViewerMediaFocus::getInstance()->getFocusedObject()) && !mSelectedObjects->isAttachment() && !selectionCenter.isExactlyZero()) { @@ -4604,7 +4606,7 @@ void LLSelectMgr::updateSilhouettes() if (!mSilhouetteImagep) { - mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, TRUE); + mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, LLViewerTexture::BOOST_UI); } mHighlightedObjects->cleanupNodes(); @@ -4906,12 +4908,21 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) } if (mSelectedObjects->getNumNodes()) { - LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect"); LLUUID inspect_item_id= LLUUID::null; +#if 0 + LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect"); if(inspect_instance) { inspect_item_id = inspect_instance->getSelectedUUID(); } +#endif + LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel(); + if (panel_task_info) + { + inspect_item_id = panel_task_info->getSelectedUUID(); + } + + LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getFocusedObjectID(); for (S32 pass = 0; pass < 2; pass++) { for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); @@ -4925,7 +4936,11 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) { continue; } - if(objectp->getID() == inspect_item_id) + if (objectp->getID() == focus_item_id) + { + node->renderOneSilhouette(gFocusMgr.getFocusColor()); + } + else if(objectp->getID() == inspect_item_id) { node->renderOneSilhouette(sHighlightInspectColor); } @@ -4979,19 +4994,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) } } -#if 0 - // Hilight focused media object - { - LLViewerObject* objectp = LLViewerMediaFocus::getInstance()->getFocusedObject(); - if(objectp) - { - // FIXME: how do I construct a silhouette for an object that's not selected? - // Would we need to add another LLObjectSelectionHandle for this purpose? - node->renderOneSilhouette(gFocusMgr.getFocusColor()); - } - } -#endif - if (for_hud && avatar) { glMatrixMode(GL_PROJECTION); @@ -5494,12 +5496,19 @@ void dialog_refresh_all() } LLFloaterProperties::dirtyAll(); - + +#if 0 LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect"); if(inspect_instance) { inspect_instance->dirty(); } +#endif + LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel(); + if (panel_task_info) + { + panel_task_info->dirty(); + } } S32 get_family_count(LLViewerObject *parent) diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp new file mode 100644 index 0000000000..6aa5c53194 --- /dev/null +++ b/indra/newview/llsidepanelinventory.cpp @@ -0,0 +1,274 @@ +/**
+ * @file LLSidepanelInventory.cpp
+ * @brief Side Bar "Inventory" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepanelinventory.h"
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "llinventorybridge.h"
+#include "llinventorypanel.h"
+#include "llpanelmaininventory.h"
+#include "llsidepaneliteminfo.h"
+#include "llsidepaneltaskinfo.h"
+#include "lltabcontainer.h"
+#include "llselectmgr.h"
+
+static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_inventory");
+
+LLSidepanelInventory::LLSidepanelInventory()
+ : LLPanel(),
+ mItemPanel(NULL)
+{
+
+ //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
+}
+
+LLSidepanelInventory::~LLSidepanelInventory()
+{
+}
+
+BOOL LLSidepanelInventory::postBuild()
+{
+ // UI elements from inventory panel
+ {
+ mInventoryPanel = getChild<LLPanel>("sidepanel__inventory_panel");
+
+ mInfoBtn = mInventoryPanel->getChild<LLButton>("info_btn");
+ mInfoBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onInfoButtonClicked, this));
+
+ mShareBtn = mInventoryPanel->getChild<LLButton>("share_btn");
+ mShareBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onShareButtonClicked, this));
+
+ mWearBtn = mInventoryPanel->getChild<LLButton>("wear_btn");
+ mWearBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onWearButtonClicked, this));
+
+ mPlayBtn = mInventoryPanel->getChild<LLButton>("play_btn");
+ mPlayBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onPlayButtonClicked, this));
+
+ mTeleportBtn = mInventoryPanel->getChild<LLButton>("teleport_btn");
+ mTeleportBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onTeleportButtonClicked, this));
+
+ mOverflowBtn = mInventoryPanel->getChild<LLButton>("overflow_btn");
+ mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onOverflowButtonClicked, this));
+
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ panel_main_inventory->setSelectCallback(boost::bind(&LLSidepanelInventory::onSelectionChange, this, _1, _2));
+ }
+
+ // UI elements from item panel
+ {
+ mItemPanel = getChild<LLSidepanelItemInfo>("sidepanel__item_panel");
+
+ LLButton* back_btn = mItemPanel->getChild<LLButton>("back_btn");
+ back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this));
+ }
+
+ // UI elements from task panel
+ {
+ mTaskPanel = getChild<LLSidepanelTaskInfo>("sidepanel__task_panel");
+ if (mTaskPanel)
+ {
+ LLButton* back_btn = mTaskPanel->getChild<LLButton>("back_btn");
+ back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this));
+ }
+ }
+
+ return TRUE;
+}
+
+void LLSidepanelInventory::onOpen(const LLSD& key)
+{
+ if(key.size() == 0)
+ return;
+
+ mItemPanel->reset();
+
+ if (key.has("id"))
+ {
+ mItemPanel->setItemID(key["id"].asUUID());
+ if (key.has("object"))
+ {
+ mItemPanel->setObjectID(key["object"].asUUID());
+ }
+ showItemInfoPanel();
+ }
+ if (key.has("task"))
+ {
+ if (mTaskPanel)
+ mTaskPanel->setObjectSelection(LLSelectMgr::getInstance()->getSelection());
+ showTaskInfoPanel();
+ }
+}
+
+void LLSidepanelInventory::onInfoButtonClicked()
+{
+ LLInventoryItem *item = getSelectedItem();
+ if (item)
+ {
+ mItemPanel->reset();
+ mItemPanel->setItemID(item->getUUID());
+ showItemInfoPanel();
+ }
+}
+
+void LLSidepanelInventory::onShareButtonClicked()
+{
+}
+
+void LLSidepanelInventory::performActionOnSelection(const std::string &action)
+{
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+ current_item->getListener()->performAction(panel_main_inventory->getActivePanel()->getRootFolder(), panel_main_inventory->getActivePanel()->getModel(), action);
+}
+
+void LLSidepanelInventory::onWearButtonClicked()
+{
+ performActionOnSelection("wear");
+ performActionOnSelection("attach");
+}
+
+void LLSidepanelInventory::onPlayButtonClicked()
+{
+ performActionOnSelection("activate");
+}
+
+void LLSidepanelInventory::onTeleportButtonClicked()
+{
+ performActionOnSelection("teleport");
+}
+
+void LLSidepanelInventory::onOverflowButtonClicked()
+{
+}
+
+void LLSidepanelInventory::onBackButtonClicked()
+{
+ showInventoryPanel();
+}
+
+void LLSidepanelInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ updateVerbs();
+}
+
+void LLSidepanelInventory::showItemInfoPanel()
+{
+ mItemPanel->setVisible(TRUE);
+ if (mTaskPanel)
+ mTaskPanel->setVisible(FALSE);
+ mInventoryPanel->setVisible(FALSE);
+
+ mItemPanel->dirty();
+ mItemPanel->setIsEditing(FALSE);
+}
+
+void LLSidepanelInventory::showTaskInfoPanel()
+{
+ mItemPanel->setVisible(FALSE);
+ mInventoryPanel->setVisible(FALSE);
+
+ if (mTaskPanel)
+ {
+ mTaskPanel->setVisible(TRUE);
+ mTaskPanel->dirty();
+ mTaskPanel->setIsEditing(FALSE);
+ }
+}
+
+void LLSidepanelInventory::showInventoryPanel()
+{
+ mItemPanel->setVisible(FALSE);
+ if (mTaskPanel)
+ mTaskPanel->setVisible(FALSE);
+ mInventoryPanel->setVisible(TRUE);
+ updateVerbs();
+}
+
+void LLSidepanelInventory::updateVerbs()
+{
+ mInfoBtn->setEnabled(FALSE);
+ mShareBtn->setEnabled(FALSE);
+
+ mWearBtn->setVisible(FALSE);
+ mWearBtn->setEnabled(FALSE);
+ mPlayBtn->setVisible(FALSE);
+ mPlayBtn->setEnabled(FALSE);
+ mTeleportBtn->setVisible(FALSE);
+ mTeleportBtn->setEnabled(FALSE);
+
+ const LLInventoryItem *item = getSelectedItem();
+ if (!item)
+ return;
+
+ mInfoBtn->setEnabled(TRUE);
+ mShareBtn->setEnabled(TRUE);
+
+ switch(item->getInventoryType())
+ {
+ case LLInventoryType::IT_WEARABLE:
+ case LLInventoryType::IT_OBJECT:
+ case LLInventoryType::IT_ATTACHMENT:
+ mWearBtn->setVisible(TRUE);
+ mWearBtn->setEnabled(TRUE);
+ break;
+ case LLInventoryType::IT_SOUND:
+ case LLInventoryType::IT_GESTURE:
+ case LLInventoryType::IT_ANIMATION:
+ mPlayBtn->setVisible(TRUE);
+ mPlayBtn->setEnabled(TRUE);
+ break;
+ case LLInventoryType::IT_LANDMARK:
+ mTeleportBtn->setVisible(TRUE);
+ mTeleportBtn->setEnabled(TRUE);
+ break;
+ default:
+ break;
+ }
+}
+
+LLInventoryItem *LLSidepanelInventory::getSelectedItem()
+{
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return NULL;
+ }
+ const LLUUID &item_id = current_item->getListener()->getUUID();
+ LLInventoryItem *item = gInventory.getItem(item_id);
+ return item;
+}
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h new file mode 100644 index 0000000000..681af7fafa --- /dev/null +++ b/indra/newview/llsidepanelinventory.h @@ -0,0 +1,90 @@ +/**
+ * @file LLSidepanelInventory.h
+ * @brief Side Bar "Inventory" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELINVENTORY_H
+#define LL_LLSIDEPANELINVENTORY_H
+
+#include "llpanel.h"
+
+class LLFolderViewItem;
+class LLInventoryItem;
+class LLPanelMainInventory;
+class LLSidepanelItemInfo;
+class LLSidepanelTaskInfo;
+
+class LLSidepanelInventory : public LLPanel
+{
+public:
+ LLSidepanelInventory();
+ virtual ~LLSidepanelInventory();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+protected:
+ // Tracks highlighted (selected) item in inventory panel.
+ LLInventoryItem *getSelectedItem();
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ // "wear", "teleport", etc.
+ void performActionOnSelection(const std::string &action);
+
+ void showItemInfoPanel();
+ void showTaskInfoPanel();
+ void showInventoryPanel();
+ void updateVerbs();
+
+ //
+ // UI Elements
+ //
+private:
+ LLPanel* mInventoryPanel; // Main inventory view
+ LLSidepanelItemInfo* mItemPanel; // Individual item view
+ LLSidepanelTaskInfo* mTaskPanel; // Individual in-world object view
+
+protected:
+ void onInfoButtonClicked();
+ void onShareButtonClicked();
+ void onWearButtonClicked();
+ void onPlayButtonClicked();
+ void onTeleportButtonClicked();
+ void onOverflowButtonClicked();
+ void onBackButtonClicked();
+private:
+ LLButton* mInfoBtn;
+ LLButton* mShareBtn;
+ LLButton* mWearBtn;
+ LLButton* mPlayBtn;
+ LLButton* mTeleportBtn;
+ LLButton* mOverflowBtn;
+
+};
+
+#endif //LL_LLSIDEPANELINVENTORY_H
diff --git a/indra/newview/llsidepanelinventorysubpanel.cpp b/indra/newview/llsidepanelinventorysubpanel.cpp new file mode 100644 index 0000000000..162198f1c5 --- /dev/null +++ b/indra/newview/llsidepanelinventorysubpanel.cpp @@ -0,0 +1,155 @@ +/**
+ * @file llsidepanelinventorysubpanel.cpp
+ * @brief A floater which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepanelinventorysubpanel.h"
+
+#include "roles_constants.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llgroupactions.h"
+#include "llinventorymodel.h"
+#include "lllineeditor.h"
+#include "llradiogroup.h"
+#include "llviewercontrol.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+
+
+///----------------------------------------------------------------------------
+/// Class LLSidepanelInventorySubpanel
+///----------------------------------------------------------------------------
+
+// Default constructor
+LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel()
+ : LLPanel(),
+ mIsDirty(TRUE),
+ mIsEditing(FALSE),
+ mEditBtn(NULL),
+ mCancelBtn(NULL),
+ mSaveBtn(NULL)
+{
+}
+
+// Destroys the object
+LLSidepanelInventorySubpanel::~LLSidepanelInventorySubpanel()
+{
+}
+
+// virtual
+BOOL LLSidepanelInventorySubpanel::postBuild()
+{
+ mEditBtn = getChild<LLButton>("edit_btn");
+ mEditBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onEditButtonClicked, this));
+
+ mSaveBtn = getChild<LLButton>("save_btn");
+ mSaveBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onSaveButtonClicked, this));
+
+ mCancelBtn = getChild<LLButton>("cancel_btn");
+ mCancelBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onCancelButtonClicked, this));
+ return TRUE;
+}
+
+void LLSidepanelInventorySubpanel::setVisible(BOOL visible)
+{
+ if (visible)
+ {
+ dirty();
+ }
+ LLPanel::setVisible(visible);
+}
+
+void LLSidepanelInventorySubpanel::setIsEditing(BOOL edit)
+{
+ mIsEditing = edit;
+ mIsDirty = TRUE;
+}
+
+BOOL LLSidepanelInventorySubpanel::getIsEditing() const
+{
+ return mIsEditing;
+}
+
+void LLSidepanelInventorySubpanel::reset()
+{
+ mIsDirty = TRUE;
+}
+
+void LLSidepanelInventorySubpanel::draw()
+{
+ if (mIsDirty)
+ {
+ mIsDirty = FALSE;
+ refresh();
+ updateVerbs();
+ }
+
+ LLPanel::draw();
+}
+
+void LLSidepanelInventorySubpanel::dirty()
+{
+ mIsDirty = TRUE;
+ setIsEditing(FALSE);
+}
+
+void LLSidepanelInventorySubpanel::updateVerbs()
+{
+ mEditBtn->setVisible(!mIsEditing);
+ mSaveBtn->setVisible(mIsEditing);
+ mCancelBtn->setVisible(mIsEditing);
+}
+
+void LLSidepanelInventorySubpanel::onEditButtonClicked()
+{
+ setIsEditing(TRUE);
+ refresh();
+ updateVerbs();
+}
+
+void LLSidepanelInventorySubpanel::onSaveButtonClicked()
+{
+ save();
+ setIsEditing(FALSE);
+ refresh();
+ updateVerbs();
+}
+
+void LLSidepanelInventorySubpanel::onCancelButtonClicked()
+{
+ setIsEditing(FALSE);
+ refresh();
+ updateVerbs();
+}
diff --git a/indra/newview/llsidepanelinventorysubpanel.h b/indra/newview/llsidepanelinventorysubpanel.h new file mode 100644 index 0000000000..6503887cd1 --- /dev/null +++ b/indra/newview/llsidepanelinventorysubpanel.h @@ -0,0 +1,82 @@ +/**
+ * @file llsidepanelinventorysubpanel.h
+ * @brief A panel which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELINVENTORYSUBPANEL_H
+#define LL_LLSIDEPANELINVENTORYSUBPANEL_H
+
+#include "llpanel.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLSidepanelInventorySubpanel
+// Base class for inventory sidepanel panels (e.g. item info, task info).
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLButton;
+class LLInventoryItem;
+
+class LLSidepanelInventorySubpanel : public LLPanel
+{
+public:
+ LLSidepanelInventorySubpanel();
+ virtual ~LLSidepanelInventorySubpanel();
+
+ /*virtual*/ void setVisible(BOOL visible);
+ virtual BOOL postBuild();
+ virtual void draw();
+ virtual void reset();
+
+ void dirty();
+ void setIsEditing(BOOL edit);
+protected:
+ virtual void refresh() = 0;
+ virtual void save() = 0;
+ virtual void updateVerbs();
+
+ BOOL getIsEditing() const;
+
+ //
+ // UI Elements
+ //
+protected:
+ void onEditButtonClicked();
+ void onSaveButtonClicked();
+ void onCancelButtonClicked();
+ LLButton* mEditBtn;
+ LLButton* mSaveBtn;
+ LLButton* mCancelBtn;
+
+private:
+ BOOL mIsDirty; // item properties need to be updated
+ BOOL mIsEditing; // if we're in edit mode
+};
+
+#endif // LL_LLSIDEPANELINVENTORYSUBPANEL_H
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp new file mode 100644 index 0000000000..9d2960fbed --- /dev/null +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -0,0 +1,882 @@ +/**
+ * @file llsidepaneliteminfo.cpp
+ * @brief A floater which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepaneliteminfo.h"
+
+#include "roles_constants.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llgroupactions.h"
+#include "llinventorymodel.h"
+#include "lllineeditor.h"
+#include "llradiogroup.h"
+#include "llviewercontrol.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLItemPropertiesObserver
+//
+// Helper class to watch for changes to the item.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLItemPropertiesObserver : public LLInventoryObserver
+{
+public:
+ LLItemPropertiesObserver(LLSidepanelItemInfo* floater)
+ : mFloater(floater)
+ {
+ gInventory.addObserver(this);
+ }
+ virtual ~LLItemPropertiesObserver()
+ {
+ gInventory.removeObserver(this);
+ }
+ virtual void changed(U32 mask);
+private:
+ LLSidepanelItemInfo* mFloater;
+};
+
+void LLItemPropertiesObserver::changed(U32 mask)
+{
+ // if there's a change we're interested in.
+ if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
+ {
+ mFloater->dirty();
+ }
+}
+
+
+
+///----------------------------------------------------------------------------
+/// Class LLSidepanelItemInfo
+///----------------------------------------------------------------------------
+
+static LLRegisterPanelClassWrapper<LLSidepanelItemInfo> t_item_info("sidepanel_item_info");
+
+// Default constructor
+LLSidepanelItemInfo::LLSidepanelItemInfo()
+ : mItemID(LLUUID::null)
+{
+ mPropertiesObserver = new LLItemPropertiesObserver(this);
+
+ //LLUICtrlFactory::getInstance()->buildFloater(this,"floater_inventory_item_properties.xml");
+}
+
+// Destroys the object
+LLSidepanelItemInfo::~LLSidepanelItemInfo()
+{
+ delete mPropertiesObserver;
+ mPropertiesObserver = NULL;
+}
+
+// virtual
+BOOL LLSidepanelItemInfo::postBuild()
+{
+ LLSidepanelInventorySubpanel::postBuild();
+
+ // build the UI
+ // item name & description
+ childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidatePrintableNotPipe);
+ //getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitName,this));
+ childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidatePrintableNotPipe);
+ //getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLSidepanelItemInfo:: onCommitDescription, this));
+
+ // Creator information
+ getChild<LLUICtrl>("BtnCreator")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickCreator,this));
+
+ // owner information
+ getChild<LLUICtrl>("BtnOwner")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickOwner,this));
+
+ refresh();
+ return TRUE;
+}
+
+void LLSidepanelItemInfo::setObjectID(const LLUUID& object_id)
+{
+ mObjectID = object_id;
+}
+
+void LLSidepanelItemInfo::setItemID(const LLUUID& item_id)
+{
+ mItemID = item_id;
+}
+
+void LLSidepanelItemInfo::reset()
+{
+ LLSidepanelInventorySubpanel::reset();
+
+ mObjectID = LLUUID::null;
+ mItemID = LLUUID::null;
+}
+
+void LLSidepanelItemInfo::refresh()
+{
+ LLInventoryItem* item = findItem();
+ if(item)
+ {
+ refreshFromItem(item);
+ updateVerbs();
+ }
+ else
+ {
+ if (getIsEditing())
+ {
+ setIsEditing(FALSE);
+ return;
+ }
+ }
+
+ if (!getIsEditing())
+ {
+ const std::string no_item_names[]={
+ "LabelItemName",
+ "LabelItemDesc",
+ "LabelCreatorName",
+ "LabelOwnerName",
+ "CheckOwnerModify",
+ "CheckOwnerCopy",
+ "CheckOwnerTransfer",
+ "CheckShareWithGroup",
+ "CheckEveryoneCopy",
+ "CheckNextOwnerModify",
+ "CheckNextOwnerCopy",
+ "CheckNextOwnerTransfer",
+ "CheckPurchase",
+ "RadioSaleType",
+ "Edit Cost"
+ };
+
+ for(size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t)
+ {
+ childSetEnabled(no_item_names[t],false);
+ }
+
+ const std::string hide_names[]={
+ "BaseMaskDebug",
+ "OwnerMaskDebug",
+ "GroupMaskDebug",
+ "EveryoneMaskDebug",
+ "NextMaskDebug"
+ };
+ for(size_t t=0; t<LL_ARRAY_SIZE(hide_names); ++t)
+ {
+ childSetVisible(hide_names[t],false);
+ }
+ }
+
+ if (!item)
+ {
+ const std::string no_edit_mode_names[]={
+ "BtnCreator",
+ "BtnOwner",
+ };
+ for(size_t t=0; t<LL_ARRAY_SIZE(no_edit_mode_names); ++t)
+ {
+ childSetEnabled(no_edit_mode_names[t],false);
+ }
+ }
+
+ updateVerbs();
+}
+
+void LLSidepanelItemInfo::refreshFromItem(LLInventoryItem* item)
+{
+ ////////////////////////
+ // PERMISSIONS LOOKUP //
+ ////////////////////////
+
+ // do not enable the UI for incomplete items.
+ LLViewerInventoryItem* i = (LLViewerInventoryItem*)item;
+ BOOL is_complete = i->isComplete();
+ const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(i->getInventoryType());
+ const BOOL is_calling_card = (i->getInventoryType() == LLInventoryType::IT_CALLINGCARD);
+ const LLPermissions& perm = item->getPermissions();
+ const BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm,
+ GP_OBJECT_MANIPULATE);
+ const BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm,
+ GP_OBJECT_SET_SALE) &&
+ !cannot_restrict_permissions;
+ const BOOL is_link = i->getIsLinkType();
+
+ // You need permission to modify the object to modify an inventory
+ // item in it.
+ LLViewerObject* object = NULL;
+ if(!mObjectID.isNull()) object = gObjectList.findObject(mObjectID);
+ BOOL is_obj_modify = TRUE;
+ if(object)
+ {
+ is_obj_modify = object->permOwnerModify();
+ }
+
+ //////////////////////
+ // ITEM NAME & DESC //
+ //////////////////////
+ BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm,
+ GP_OBJECT_MANIPULATE)
+ && is_obj_modify && is_complete;
+
+ childSetEnabled("LabelItemNameTitle",TRUE);
+ childSetEnabled("LabelItemName",is_modifiable && !is_calling_card); // for now, don't allow rename of calling cards
+ childSetText("LabelItemName",item->getName());
+ childSetEnabled("LabelItemDescTitle",TRUE);
+ childSetEnabled("LabelItemDesc",is_modifiable);
+ childSetVisible("IconLocked",!is_modifiable);
+ childSetText("LabelItemDesc",item->getDescription());
+
+ //////////////////
+ // CREATOR NAME //
+ //////////////////
+ if(!gCacheName) return;
+ if(!gAgent.getRegion()) return;
+
+ if (item->getCreatorUUID().notNull())
+ {
+ std::string name;
+ gCacheName->getFullName(item->getCreatorUUID(), name);
+ childSetEnabled("BtnCreator",TRUE);
+ childSetEnabled("LabelCreatorTitle",TRUE);
+ childSetEnabled("LabelCreatorName",TRUE);
+ childSetText("LabelCreatorName",name);
+ }
+ else
+ {
+ childSetEnabled("BtnCreator",FALSE);
+ childSetEnabled("LabelCreatorTitle",FALSE);
+ childSetEnabled("LabelCreatorName",FALSE);
+ childSetText("LabelCreatorName",getString("unknown"));
+ }
+
+ ////////////////
+ // OWNER NAME //
+ ////////////////
+ if(perm.isOwned())
+ {
+ std::string name;
+ if (perm.isGroupOwned())
+ {
+ gCacheName->getGroupName(perm.getGroup(), name);
+ }
+ else
+ {
+ gCacheName->getFullName(perm.getOwner(), name);
+ }
+ childSetEnabled("BtnOwner",TRUE);
+ childSetEnabled("LabelOwnerTitle",TRUE);
+ childSetEnabled("LabelOwnerName",TRUE);
+ childSetText("LabelOwnerName",name);
+ }
+ else
+ {
+ childSetEnabled("BtnOwner",FALSE);
+ childSetEnabled("LabelOwnerTitle",FALSE);
+ childSetEnabled("LabelOwnerName",FALSE);
+ childSetText("LabelOwnerName",getString("public"));
+ }
+
+ //////////////////
+ // ACQUIRE DATE //
+ //////////////////
+
+ time_t time_utc = item->getCreationDate();
+ if (0 == time_utc)
+ {
+ childSetText("LabelAcquiredDate",getString("unknown"));
+ }
+ else
+ {
+ std::string timeStr = getString("acquiredDate");
+ LLSD substitution;
+ substitution["datetime"] = (S32) time_utc;
+ LLStringUtil::format (timeStr, substitution);
+ childSetText ("LabelAcquiredDate", timeStr);
+ }
+
+ ///////////////////////
+ // OWNER PERMISSIONS //
+ ///////////////////////
+ if(can_agent_manipulate)
+ {
+ childSetText("OwnerLabel",getString("you_can"));
+ }
+ else
+ {
+ childSetText("OwnerLabel",getString("owner_can"));
+ }
+
+ U32 base_mask = perm.getMaskBase();
+ U32 owner_mask = perm.getMaskOwner();
+ U32 group_mask = perm.getMaskGroup();
+ U32 everyone_mask = perm.getMaskEveryone();
+ U32 next_owner_mask = perm.getMaskNextOwner();
+
+ childSetEnabled("OwnerLabel",TRUE);
+ childSetEnabled("CheckOwnerModify",FALSE);
+ childSetValue("CheckOwnerModify",LLSD((BOOL)(owner_mask & PERM_MODIFY)));
+ childSetEnabled("CheckOwnerCopy",FALSE);
+ childSetValue("CheckOwnerCopy",LLSD((BOOL)(owner_mask & PERM_COPY)));
+ childSetEnabled("CheckOwnerTransfer",FALSE);
+ childSetValue("CheckOwnerTransfer",LLSD((BOOL)(owner_mask & PERM_TRANSFER)));
+
+ ///////////////////////
+ // DEBUG PERMISSIONS //
+ ///////////////////////
+
+ if( gSavedSettings.getBOOL("DebugPermissions") )
+ {
+ BOOL slam_perm = FALSE;
+ BOOL overwrite_group = FALSE;
+ BOOL overwrite_everyone = FALSE;
+
+ if (item->getType() == LLAssetType::AT_OBJECT)
+ {
+ U32 flags = item->getFlags();
+ slam_perm = flags & LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+ overwrite_everyone = flags & LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+ overwrite_group = flags & LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+ }
+
+ std::string perm_string;
+
+ perm_string = "B: ";
+ perm_string += mask_to_string(base_mask);
+ childSetText("BaseMaskDebug",perm_string);
+ childSetVisible("BaseMaskDebug",TRUE);
+
+ perm_string = "O: ";
+ perm_string += mask_to_string(owner_mask);
+ childSetText("OwnerMaskDebug",perm_string);
+ childSetVisible("OwnerMaskDebug",TRUE);
+
+ perm_string = "G";
+ perm_string += overwrite_group ? "*: " : ": ";
+ perm_string += mask_to_string(group_mask);
+ childSetText("GroupMaskDebug",perm_string);
+ childSetVisible("GroupMaskDebug",TRUE);
+
+ perm_string = "E";
+ perm_string += overwrite_everyone ? "*: " : ": ";
+ perm_string += mask_to_string(everyone_mask);
+ childSetText("EveryoneMaskDebug",perm_string);
+ childSetVisible("EveryoneMaskDebug",TRUE);
+
+ perm_string = "N";
+ perm_string += slam_perm ? "*: " : ": ";
+ perm_string += mask_to_string(next_owner_mask);
+ childSetText("NextMaskDebug",perm_string);
+ childSetVisible("NextMaskDebug",TRUE);
+ }
+ else
+ {
+ childSetVisible("BaseMaskDebug",FALSE);
+ childSetVisible("OwnerMaskDebug",FALSE);
+ childSetVisible("GroupMaskDebug",FALSE);
+ childSetVisible("EveryoneMaskDebug",FALSE);
+ childSetVisible("NextMaskDebug",FALSE);
+ }
+
+ /////////////
+ // SHARING //
+ /////////////
+
+ // Check for ability to change values.
+ if (is_link || cannot_restrict_permissions)
+ {
+ childSetEnabled("CheckShareWithGroup",FALSE);
+ childSetEnabled("CheckEveryoneCopy",FALSE);
+ }
+ else if (is_obj_modify && can_agent_manipulate)
+ {
+ childSetEnabled("CheckShareWithGroup",TRUE);
+ childSetEnabled("CheckEveryoneCopy",(owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER));
+ }
+ else
+ {
+ childSetEnabled("CheckShareWithGroup",FALSE);
+ childSetEnabled("CheckEveryoneCopy",FALSE);
+ }
+
+ // Set values.
+ BOOL is_group_copy = (group_mask & PERM_COPY) ? TRUE : FALSE;
+ BOOL is_group_modify = (group_mask & PERM_MODIFY) ? TRUE : FALSE;
+ BOOL is_group_move = (group_mask & PERM_MOVE) ? TRUE : FALSE;
+
+ if (is_group_copy && is_group_modify && is_group_move)
+ {
+ childSetValue("CheckShareWithGroup",LLSD((BOOL)TRUE));
+
+ LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ if(ctl)
+ {
+ ctl->setTentative(FALSE);
+ }
+ }
+ else if (!is_group_copy && !is_group_modify && !is_group_move)
+ {
+ childSetValue("CheckShareWithGroup",LLSD((BOOL)FALSE));
+ LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ if(ctl)
+ {
+ ctl->setTentative(FALSE);
+ }
+ }
+ else
+ {
+ LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ if(ctl)
+ {
+ ctl->setTentative(TRUE);
+ ctl->set(TRUE);
+ }
+ }
+
+ childSetValue("CheckEveryoneCopy",LLSD((BOOL)(everyone_mask & PERM_COPY)));
+
+ ///////////////
+ // SALE INFO //
+ ///////////////
+
+ const LLSaleInfo& sale_info = item->getSaleInfo();
+ BOOL is_for_sale = sale_info.isForSale();
+ // Check for ability to change values.
+ if (is_obj_modify && can_agent_sell
+ && gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE))
+ {
+ childSetEnabled("SaleLabel",is_complete);
+ childSetEnabled("CheckPurchase",is_complete);
+
+ childSetEnabled("NextOwnerLabel",TRUE);
+ childSetEnabled("CheckNextOwnerModify",(base_mask & PERM_MODIFY) && !cannot_restrict_permissions);
+ childSetEnabled("CheckNextOwnerCopy",(base_mask & PERM_COPY) && !cannot_restrict_permissions);
+ childSetEnabled("CheckNextOwnerTransfer",(next_owner_mask & PERM_COPY) && !cannot_restrict_permissions);
+
+ childSetEnabled("RadioSaleType",is_complete && is_for_sale);
+ childSetEnabled("TextPrice",is_complete && is_for_sale);
+ childSetEnabled("Edit Cost",is_complete && is_for_sale);
+ }
+ else
+ {
+ childSetEnabled("SaleLabel",FALSE);
+ childSetEnabled("CheckPurchase",FALSE);
+
+ childSetEnabled("NextOwnerLabel",FALSE);
+ childSetEnabled("CheckNextOwnerModify",FALSE);
+ childSetEnabled("CheckNextOwnerCopy",FALSE);
+ childSetEnabled("CheckNextOwnerTransfer",FALSE);
+
+ childSetEnabled("RadioSaleType",FALSE);
+ childSetEnabled("TextPrice",FALSE);
+ childSetEnabled("Edit Cost",FALSE);
+ }
+
+ // Set values.
+ childSetValue("CheckPurchase", is_for_sale);
+ childSetEnabled("combobox sale copy", is_for_sale);
+ childSetEnabled("Edit Cost", is_for_sale);
+ childSetValue("CheckNextOwnerModify",LLSD(BOOL(next_owner_mask & PERM_MODIFY)));
+ childSetValue("CheckNextOwnerCopy",LLSD(BOOL(next_owner_mask & PERM_COPY)));
+ childSetValue("CheckNextOwnerTransfer",LLSD(BOOL(next_owner_mask & PERM_TRANSFER)));
+
+ LLRadioGroup* radioSaleType = getChild<LLRadioGroup>("RadioSaleType");
+ if (is_for_sale)
+ {
+ radioSaleType->setSelectedIndex((S32)sale_info.getSaleType() - 1);
+ S32 numerical_price;
+ numerical_price = sale_info.getSalePrice();
+ childSetText("Edit Cost",llformat("%d",numerical_price));
+ }
+ else
+ {
+ radioSaleType->setSelectedIndex(-1);
+ childSetText("Edit Cost",llformat("%d",0));
+ }
+}
+
+void LLSidepanelItemInfo::onClickCreator()
+{
+ LLInventoryItem* item = findItem();
+ if(!item) return;
+ if(!item->getCreatorUUID().isNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onClickOwner()
+{
+ LLInventoryItem* item = findItem();
+ if(!item) return;
+ if(item->getPermissions().isGroupOwned())
+ {
+ LLGroupActions::show(item->getPermissions().getGroup());
+ }
+ else
+ {
+ LLAvatarActions::showProfile(item->getPermissions().getOwner());
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onCommitName()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitName()" << llendl;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if(!item)
+ {
+ return;
+ }
+ LLLineEditor* labelItemName = getChild<LLLineEditor>("LabelItemName");
+
+ if(labelItemName&&
+ (item->getName() != labelItemName->getText()) &&
+ (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) )
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(labelItemName->getText());
+ if(mObjectID.isNull())
+ {
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+}
+
+void LLSidepanelItemInfo::onCommitDescription()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitDescription()" << llendl;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if(!item) return;
+
+ LLLineEditor* labelItemDesc = getChild<LLLineEditor>("LabelItemDesc");
+ if(!labelItemDesc)
+ {
+ return;
+ }
+ if((item->getDescription() != labelItemDesc->getText()) &&
+ (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+
+ new_item->setDescription(labelItemDesc->getText());
+ if(mObjectID.isNull())
+ {
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onCommitPermissions()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitPermissions()" << llendl;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if(!item) return;
+ LLPermissions perm(item->getPermissions());
+
+
+ LLCheckBoxCtrl* CheckShareWithGroup = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+
+ if(CheckShareWithGroup)
+ {
+ perm.setGroupBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckShareWithGroup->get(),
+ PERM_MODIFY | PERM_MOVE | PERM_COPY);
+ }
+ LLCheckBoxCtrl* CheckEveryoneCopy = getChild<LLCheckBoxCtrl>("CheckEveryoneCopy");
+ if(CheckEveryoneCopy)
+ {
+ perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckEveryoneCopy->get(), PERM_COPY);
+ }
+
+ LLCheckBoxCtrl* CheckNextOwnerModify = getChild<LLCheckBoxCtrl>("CheckNextOwnerModify");
+ if(CheckNextOwnerModify)
+ {
+ perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckNextOwnerModify->get(), PERM_MODIFY);
+ }
+ LLCheckBoxCtrl* CheckNextOwnerCopy = getChild<LLCheckBoxCtrl>("CheckNextOwnerCopy");
+ if(CheckNextOwnerCopy)
+ {
+ perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckNextOwnerCopy->get(), PERM_COPY);
+ }
+ LLCheckBoxCtrl* CheckNextOwnerTransfer = getChild<LLCheckBoxCtrl>("CheckNextOwnerTransfer");
+ if(CheckNextOwnerTransfer)
+ {
+ perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckNextOwnerTransfer->get(), PERM_TRANSFER);
+ }
+ if(perm != item->getPermissions()
+ && item->isComplete())
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->setPermissions(perm);
+ U32 flags = new_item->getFlags();
+ // If next owner permissions have changed (and this is an object)
+ // then set the slam permissions flag so that they are applied on rez.
+ if((perm.getMaskNextOwner()!=item->getPermissions().getMaskNextOwner())
+ && (item->getType() == LLAssetType::AT_OBJECT))
+ {
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+ }
+ // If everyone permissions have changed (and this is an object)
+ // then set the overwrite everyone permissions flag so they
+ // are applied on rez.
+ if ((perm.getMaskEveryone()!=item->getPermissions().getMaskEveryone())
+ && (item->getType() == LLAssetType::AT_OBJECT))
+ {
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+ }
+ // If group permissions have changed (and this is an object)
+ // then set the overwrite group permissions flag so they
+ // are applied on rez.
+ if ((perm.getMaskGroup()!=item->getPermissions().getMaskGroup())
+ && (item->getType() == LLAssetType::AT_OBJECT))
+ {
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+ }
+ new_item->setFlags(flags);
+ if(mObjectID.isNull())
+ {
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+ else
+ {
+ // need to make sure we don't just follow the click
+ refresh();
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onCommitSaleInfo()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitSaleInfo()" << llendl;
+ updateSaleInfo();
+}
+
+// static
+void LLSidepanelItemInfo::onCommitSaleType()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitSaleType()" << llendl;
+ updateSaleInfo();
+}
+
+void LLSidepanelItemInfo::updateSaleInfo()
+{
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if(!item) return;
+ LLSaleInfo sale_info(item->getSaleInfo());
+ if(!gAgent.allowOperation(PERM_TRANSFER, item->getPermissions(), GP_OBJECT_SET_SALE))
+ {
+ childSetValue("CheckPurchase",LLSD((BOOL)FALSE));
+ }
+
+ if((BOOL)childGetValue("CheckPurchase"))
+ {
+ // turn on sale info
+ LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_COPY;
+
+ LLRadioGroup* RadioSaleType = getChild<LLRadioGroup>("RadioSaleType");
+ if(RadioSaleType)
+ {
+ switch (RadioSaleType->getSelectedIndex())
+ {
+ case 0:
+ sale_type = LLSaleInfo::FS_ORIGINAL;
+ break;
+ case 1:
+ sale_type = LLSaleInfo::FS_COPY;
+ break;
+ case 2:
+ sale_type = LLSaleInfo::FS_CONTENTS;
+ break;
+ default:
+ sale_type = LLSaleInfo::FS_COPY;
+ break;
+ }
+ }
+
+ if (sale_type == LLSaleInfo::FS_COPY
+ && !gAgent.allowOperation(PERM_COPY, item->getPermissions(),
+ GP_OBJECT_SET_SALE))
+ {
+ sale_type = LLSaleInfo::FS_ORIGINAL;
+ }
+
+
+
+ S32 price = -1;
+ price = getChild<LLUICtrl>("Edit Cost")->getValue().asInteger();;
+
+ // Invalid data - turn off the sale
+ if (price < 0)
+ {
+ sale_type = LLSaleInfo::FS_NOT;
+ price = 0;
+ }
+
+ sale_info.setSaleType(sale_type);
+ sale_info.setSalePrice(price);
+ }
+ else
+ {
+ sale_info.setSaleType(LLSaleInfo::FS_NOT);
+ }
+ if(sale_info != item->getSaleInfo()
+ && item->isComplete())
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+
+ // Force an update on the sale price at rez
+ if (item->getType() == LLAssetType::AT_OBJECT)
+ {
+ U32 flags = new_item->getFlags();
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
+ new_item->setFlags(flags);
+ }
+
+ new_item->setSaleInfo(sale_info);
+ if(mObjectID.isNull())
+ {
+ // This is in the agent's inventory.
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ // This is in an object's contents.
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+ else
+ {
+ // need to make sure we don't just follow the click
+ refresh();
+ }
+}
+
+LLInventoryItem* LLSidepanelItemInfo::findItem() const
+{
+ LLInventoryItem* item = NULL;
+ if(mObjectID.isNull())
+ {
+ // it is in agent inventory
+ item = gInventory.getItem(mItemID);
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ item = (LLInventoryItem*)object->getInventoryObject(mItemID);
+ }
+ }
+ return item;
+}
+
+// virtual
+void LLSidepanelItemInfo::updateVerbs()
+{
+ LLSidepanelInventorySubpanel::updateVerbs();
+
+ const LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if (item)
+ {
+ const LLPermissions& perm = item->getPermissions();
+ BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm,
+ GP_OBJECT_MANIPULATE);
+ mEditBtn->setEnabled(is_modifiable);
+ }
+}
+
+// virtual
+void LLSidepanelItemInfo::save()
+{
+ onCommitName();
+ onCommitDescription();
+ onCommitPermissions();
+ onCommitSaleInfo();
+ onCommitSaleType();
+}
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h new file mode 100644 index 0000000000..b348b5cceb --- /dev/null +++ b/indra/newview/llsidepaneliteminfo.h @@ -0,0 +1,91 @@ +/**
+ * @file llsidepaneliteminfo.h
+ * @brief A panel which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELITEMINFO_H
+#define LL_LLSIDEPANELITEMINFO_H
+
+#include "llsidepanelinventorysubpanel.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLSidepanelItemInfo
+// Object properties for inventory side panel.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLButton;
+class LLInventoryItem;
+class LLItemPropertiesObserver;
+class LLViewerObject;
+class LLPermissions;
+
+class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
+{
+public:
+ LLSidepanelItemInfo();
+ virtual ~LLSidepanelItemInfo();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void reset();
+
+ void setObjectID(const LLUUID& object_id);
+ void setItemID(const LLUUID& item_id);
+ void setEditMode(BOOL edit);
+
+protected:
+ /*virtual*/ void refresh();
+ /*virtual*/ void save();
+ /*virtual*/ void updateVerbs();
+
+ LLInventoryItem* findItem() const;
+ LLViewerObject* findObject() const;
+
+ void refreshFromItem(LLInventoryItem* item);
+
+private:
+ LLUUID mItemID; // inventory UUID for the inventory item.
+ LLUUID mObjectID; // in-world task UUID, or null if in agent inventory.
+ LLItemPropertiesObserver* mPropertiesObserver; // for syncing changes to item
+
+ //
+ // UI Elements
+ //
+protected:
+ void onClickCreator();
+ void onClickOwner();
+ void onCommitName();
+ void onCommitDescription();
+ void onCommitPermissions();
+ void onCommitSaleInfo();
+ void onCommitSaleType();
+ void updateSaleInfo();
+};
+
+#endif // LL_LLSIDEPANELITEMINFO_H
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp new file mode 100644 index 0000000000..01c832d7d5 --- /dev/null +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -0,0 +1,1124 @@ +/** + * @file llsidepaneltaskinfo.cpp + * @brief LLSidepanelTaskInfo class implementation + * This class represents the panel in the build view for + * viewing/editing object names, owners, permissions, etc. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llsidepaneltaskinfo.h" + +#include "lluuid.h" +#include "llpermissions.h" +#include "llcategory.h" +#include "llclickaction.h" +#include "llfocusmgr.h" +#include "llstring.h" + +#include "llviewerwindow.h" +#include "llresmgr.h" +#include "lltextbox.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llviewerobject.h" +#include "llselectmgr.h" +#include "llagent.h" +#include "llstatusbar.h" // for getBalance() +#include "lllineeditor.h" +#include "llcombobox.h" +#include "lluiconstants.h" +#include "lldbstrings.h" +#include "llfloatergroups.h" +#include "llfloaterreg.h" +#include "llavataractions.h" +#include "llnamebox.h" +#include "llviewercontrol.h" +#include "llviewermenu.h" +#include "lluictrlfactory.h" +#include "llspinctrl.h" +#include "roles_constants.h" +#include "llgroupactions.h" + +///---------------------------------------------------------------------------- +/// Class llsidepaneltaskinfo +///---------------------------------------------------------------------------- + +LLSidepanelTaskInfo* LLSidepanelTaskInfo::sActivePanel = NULL; + +static LLRegisterPanelClassWrapper<LLSidepanelTaskInfo> t_task_info("sidepanel_task_info"); + +// Default constructor +LLSidepanelTaskInfo::LLSidepanelTaskInfo() +{ + setMouseOpaque(FALSE); +} + + +LLSidepanelTaskInfo::~LLSidepanelTaskInfo() +{ + if (sActivePanel == this) + sActivePanel = NULL; +} + +// virtual +BOOL LLSidepanelTaskInfo::postBuild() +{ + LLSidepanelInventorySubpanel::postBuild(); + + mOpenBtn = getChild<LLButton>("open_btn"); + mOpenBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onOpenButtonClicked, this)); + mPayBtn = getChild<LLButton>("pay_btn"); + mPayBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onPayButtonClicked, this)); + mBuyBtn = getChild<LLButton>("buy_btn"); + mBuyBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onBuyButtonClicked, this)); + + childSetPrevalidate("Object Name",LLLineEditor::prevalidatePrintableNotPipe); + childSetPrevalidate("Object Description",LLLineEditor::prevalidatePrintableNotPipe); + +// getChild<LLUICtrl>("button set group")->setCommitCallback(boost::bind(&LLSidepanelTaskInfo::onClickGroup,this)); +// childSetAction("button deed",LLSidepanelTaskInfo::onClickDeedToGroup,this); + + mLabelGroupName = getChild<LLNameBox>("Group Name Proxy"); + + return TRUE; +} + +// virtual +void LLSidepanelTaskInfo::setVisible(BOOL visible) +{ + LLPanel::setVisible(visible); + if (visible) + { + sActivePanel = this; + } + else + { + sActivePanel = NULL; + } +} + +void LLSidepanelTaskInfo::refresh() +{ + LLButton* BtnDeedToGroup = getChild<LLButton>("button deed"); + if(BtnDeedToGroup) + { + std::string deedText; + if (gWarningSettings.getBOOL("DeedObject")) + { + deedText = getString("text deed continued"); + } + else + { + deedText = getString("text deed"); + } + BtnDeedToGroup->setLabelSelected(deedText); + BtnDeedToGroup->setLabelUnselected(deedText); + } + BOOL root_selected = TRUE; + LLSelectNode* nodep = mObjectSelection->getFirstRootNode(); + S32 object_count = mObjectSelection->getRootObjectCount(); + if(!nodep || 0 == object_count) + { + nodep = mObjectSelection->getFirstNode(); + object_count = mObjectSelection->getObjectCount(); + root_selected = FALSE; + } + + //BOOL attachment_selected = mObjectSelection->isAttachment(); + //attachment_selected = false; + LLViewerObject* objectp = NULL; + if(nodep) objectp = nodep->getObject(); + if(!nodep || !objectp)// || attachment_selected) + { + // ...nothing selected + childSetEnabled("perm_modify",false); + childSetText("perm_modify",LLStringUtil::null); + + childSetEnabled("Creator:",false); + childSetText("Creator Name",LLStringUtil::null); + childSetEnabled("Creator Name",false); + + childSetEnabled("Owner:",false); + childSetText("Owner Name",LLStringUtil::null); + childSetEnabled("Owner Name",false); + + childSetEnabled("Group:",false); + childSetText("Group Name",LLStringUtil::null); + childSetEnabled("Group Name",false); + childSetEnabled("button set group",false); + + childSetText("Object Name",LLStringUtil::null); + childSetEnabled("Object Name",false); + childSetEnabled("Name:",false); + childSetText("Group Name",LLStringUtil::null); + childSetEnabled("Group Name",false); + childSetEnabled("Description:",false); + childSetText("Object Description",LLStringUtil::null); + childSetEnabled("Object Description",false); + + childSetEnabled("Permissions:",false); + + childSetValue("checkbox share with group",FALSE); + childSetEnabled("checkbox share with group",false); + childSetEnabled("button deed",false); + + childSetValue("checkbox allow everyone move",FALSE); + childSetEnabled("checkbox allow everyone move",false); + childSetValue("checkbox allow everyone copy",FALSE); + childSetEnabled("checkbox allow everyone copy",false); + + //Next owner can: + childSetEnabled("Next owner can:",false); + childSetValue("checkbox next owner can modify",FALSE); + childSetEnabled("checkbox next owner can modify",false); + childSetValue("checkbox next owner can copy",FALSE); + childSetEnabled("checkbox next owner can copy",false); + childSetValue("checkbox next owner can transfer",FALSE); + childSetEnabled("checkbox next owner can transfer",false); + + //checkbox for sale + childSetValue("checkbox for sale",FALSE); + childSetEnabled("checkbox for sale",false); + + //checkbox include in search + childSetValue("search_check", FALSE); + childSetEnabled("search_check", false); + + LLComboBox* combo_sale_type = getChild<LLComboBox>("sale type"); + combo_sale_type->setValue(LLSaleInfo::FS_COPY); + combo_sale_type->setEnabled(FALSE); + + childSetEnabled("Cost",false); + childSetText("Cost",getString("Cost Default")); + childSetText("Edit Cost",LLStringUtil::null); + childSetEnabled("Edit Cost",false); + + childSetEnabled("label click action",false); + LLComboBox* ComboClickAction = getChild<LLComboBox>("clickaction"); + if(ComboClickAction) + { + ComboClickAction->setEnabled(FALSE); + ComboClickAction->clear(); + } + childSetVisible("B:",false); + childSetVisible("O:",false); + childSetVisible("G:",false); + childSetVisible("E:",false); + childSetVisible("N:",false); + childSetVisible("F:",false); + + return; + } + + // figure out a few variables + BOOL is_one_object = (object_count == 1); + + // BUG: fails if a root and non-root are both single-selected. + BOOL is_perm_modify = (mObjectSelection->getFirstRootNode() + && LLSelectMgr::getInstance()->selectGetRootsModify()) + || LLSelectMgr::getInstance()->selectGetModify(); + const LLFocusableElement* keyboard_focus_view = gFocusMgr.getKeyboardFocus(); + S32 string_index = 0; + std::string MODIFY_INFO_STRINGS[] = + { + getString("text modify info 1"), + getString("text modify info 2"), + getString("text modify info 3"), + getString("text modify info 4") + }; + if(!is_perm_modify) + { + string_index += 2; + } + if(!is_one_object) + { + ++string_index; + } + childSetEnabled("perm_modify",true); + childSetText("perm_modify",MODIFY_INFO_STRINGS[string_index]); + + childSetEnabled("Permissions:",true); + + // Update creator text field + childSetEnabled("Creator:",true); + BOOL creators_identical; + std::string creator_name; + creators_identical = LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, + creator_name); + + childSetText("Creator Name",creator_name); + childSetEnabled("Creator Name",TRUE); + + // Update owner text field + childSetEnabled("Owner:",true); + + BOOL owners_identical; + std::string owner_name; + owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name); + +// llinfos << "owners_identical " << (owners_identical ? "TRUE": "FALSE") << llendl; + + if (mOwnerID.isNull()) + { + if(LLSelectMgr::getInstance()->selectIsGroupOwned()) + { + // Group owned already displayed by selectGetOwner + } + else + { + // Display last owner if public + std::string last_owner_name; + LLSelectMgr::getInstance()->selectGetLastOwner(mLastOwnerID, last_owner_name); + + // It should never happen that the last owner is null and the owner + // is null, but it seems to be a bug in the simulator right now. JC + if (!mLastOwnerID.isNull() && !last_owner_name.empty()) + { + owner_name.append(", last "); + owner_name.append( last_owner_name ); + } + } + } + + childSetText("Owner Name",owner_name); + childSetEnabled("Owner Name",TRUE); + + // update group text field + childSetEnabled("Group:",true); + childSetText("Group Name",LLStringUtil::null); + LLUUID group_id; + BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id); + if (groups_identical) + { + if(mLabelGroupName) + { + mLabelGroupName->setNameID(group_id, TRUE); + mLabelGroupName->setEnabled(TRUE); + } + } + else + { + if(mLabelGroupName) + { + mLabelGroupName->setNameID(LLUUID::null, TRUE); + mLabelGroupName->refresh(LLUUID::null, LLStringUtil::null, LLStringUtil::null, TRUE); + mLabelGroupName->setEnabled(FALSE); + } + } + + childSetEnabled("button set group",owners_identical && (mOwnerID == gAgent.getID())); + + // figure out the contents of the name, description, & category + BOOL edit_name_desc = FALSE; + if(is_one_object && objectp->permModify()) + { + edit_name_desc = TRUE; + } + + childSetEnabled("Name:",true); + LLLineEditor* LineEditorObjectName = getChild<LLLineEditor>("Object Name"); + childSetEnabled("Description:",true); + LLLineEditor* LineEditorObjectDesc = getChild<LLLineEditor>("Object Description"); + + if(is_one_object) + { + if(keyboard_focus_view != LineEditorObjectName) + { + childSetText("Object Name",nodep->mName); + } + + if(LineEditorObjectDesc) + { + if(keyboard_focus_view != LineEditorObjectDesc) + { + LineEditorObjectDesc->setText(nodep->mDescription); + } + } + } + else + { + childSetText("Object Name",LLStringUtil::null); + LineEditorObjectDesc->setText(LLStringUtil::null); + } + + if(edit_name_desc) + { + childSetEnabled("Object Name",true); + childSetEnabled("Object Description",true); + } + else + { + childSetEnabled("Object Name",false); + childSetEnabled("Object Description",false); + } + + S32 total_sale_price = 0; + S32 individual_sale_price = 0; + BOOL is_for_sale_mixed = FALSE; + BOOL is_sale_price_mixed = FALSE; + U32 num_for_sale = FALSE; + LLSelectMgr::getInstance()->selectGetAggregateSaleInfo(num_for_sale, + is_for_sale_mixed, + is_sale_price_mixed, + total_sale_price, + individual_sale_price); + + const BOOL self_owned = (gAgent.getID() == mOwnerID); + const BOOL group_owned = LLSelectMgr::getInstance()->selectIsGroupOwned() ; + const BOOL public_owned = (mOwnerID.isNull() && !LLSelectMgr::getInstance()->selectIsGroupOwned()); + const BOOL can_transfer = LLSelectMgr::getInstance()->selectGetRootsTransfer(); + const BOOL can_copy = LLSelectMgr::getInstance()->selectGetRootsCopy(); + + if(!owners_identical) + { + childSetEnabled("Cost",false); + childSetText("Edit Cost",LLStringUtil::null); + childSetEnabled("Edit Cost",false); + } + // You own these objects. + else if(self_owned || (group_owned && gAgent.hasPowerInGroup(group_id,GP_OBJECT_SET_SALE))) + { + // If there are multiple items for sale then set text to PRICE PER UNIT. + if (num_for_sale > 1) + { + childSetText("Cost",getString("Cost Per Unit")); + } + else + { + childSetText("Cost",getString("Cost Default")); + } + + LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost"); + if(!edit_price->hasFocus()) + { + // If the sale price is mixed then set the cost to MIXED, otherwise + // set to the actual cost. + if (num_for_sale > 0 && is_for_sale_mixed) + { + edit_price->setTentative(TRUE); + } + else if (num_for_sale > 0 && is_sale_price_mixed) + { + edit_price->setTentative(TRUE); + } + else + { + edit_price->setValue(individual_sale_price); + } + } + // The edit fields are only enabled if you can sell this object + // and the sale price is not mixed. + bool enable_edit = (num_for_sale && can_transfer) ? !is_for_sale_mixed : false; + childSetEnabled("Cost",enable_edit); + childSetEnabled("Edit Cost",enable_edit); + } + // Someone, not you, owns these objects. + else if(!public_owned) + { + childSetEnabled("Cost",false); + childSetEnabled("Edit Cost",false); + + // Don't show a price if none of the items are for sale. + if (num_for_sale) + childSetText("Edit Cost",llformat("%d",total_sale_price)); + else + childSetText("Edit Cost",LLStringUtil::null); + + // If multiple items are for sale, set text to TOTAL PRICE. + if (num_for_sale > 1) + childSetText("Cost",getString("Cost Total")); + else + childSetText("Cost",getString("Cost Default")); + } + // This is a public object. + else + { + childSetEnabled("Cost",false); + childSetText("Cost",getString("Cost Default")); + + childSetText("Edit Cost",LLStringUtil::null); + childSetEnabled("Edit Cost",false); + } + + // Enable and disable the permissions checkboxes + // based on who owns the object. + // TODO: Creator permissions + + BOOL valid_base_perms = FALSE; + BOOL valid_owner_perms = FALSE; + BOOL valid_group_perms = FALSE; + BOOL valid_everyone_perms = FALSE; + BOOL valid_next_perms = FALSE; + + U32 base_mask_on; + U32 base_mask_off; + U32 owner_mask_on; + U32 owner_mask_off; + U32 group_mask_on; + U32 group_mask_off; + U32 everyone_mask_on; + U32 everyone_mask_off; + U32 next_owner_mask_on = 0; + U32 next_owner_mask_off = 0; + + valid_base_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_BASE, + &base_mask_on, + &base_mask_off); + + valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER, + &owner_mask_on, + &owner_mask_off); + + valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_GROUP, + &group_mask_on, + &group_mask_off); + + valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_EVERYONE, + &everyone_mask_on, + &everyone_mask_off); + + valid_next_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_NEXT_OWNER, + &next_owner_mask_on, + &next_owner_mask_off); + + + if( gSavedSettings.getBOOL("DebugPermissions") ) + { + std::string perm_string; + if (valid_base_perms) + { + perm_string = "B: "; + perm_string += mask_to_string(base_mask_on); + childSetText("B:",perm_string); + childSetVisible("B:",true); + + perm_string = "O: "; + perm_string += mask_to_string(owner_mask_on); + childSetText("O:",perm_string); + childSetVisible("O:",true); + + perm_string = "G: "; + perm_string += mask_to_string(group_mask_on); + childSetText("G:",perm_string); + childSetVisible("G:",true); + + perm_string = "E: "; + perm_string += mask_to_string(everyone_mask_on); + childSetText("E:",perm_string); + childSetVisible("E:",true); + + perm_string = "N: "; + perm_string += mask_to_string(next_owner_mask_on); + childSetText("N:",perm_string); + childSetVisible("N:",true); + } + perm_string = "F: "; + U32 flag_mask = 0x0; + if (objectp->permMove()) + flag_mask |= PERM_MOVE; + if (objectp->permModify()) + flag_mask |= PERM_MODIFY; + if (objectp->permCopy()) + flag_mask |= PERM_COPY; + if (objectp->permTransfer()) + flag_mask |= PERM_TRANSFER; + perm_string += mask_to_string(flag_mask); + childSetText("F:",perm_string); + childSetVisible("F:",true); + } + else + { + childSetVisible("B:",false); + childSetVisible("O:",false); + childSetVisible("G:",false); + childSetVisible("E:",false); + childSetVisible("N:",false); + childSetVisible("F:",false); + } + + bool has_change_perm_ability = false; + bool has_change_sale_ability = false; + + if(valid_base_perms + && (self_owned + || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_MANIPULATE)))) + { + has_change_perm_ability = true; + } + if(valid_base_perms + && (self_owned + || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_SET_SALE)))) + { + has_change_sale_ability = true; + } + + if (!has_change_perm_ability && !has_change_sale_ability && !root_selected) + { + // ...must select root to choose permissions + childSetValue("perm_modify", getString("text modify warning")); + } + + if (has_change_perm_ability) + { + childSetEnabled("checkbox share with group",true); + childSetEnabled("checkbox allow everyone move",owner_mask_on & PERM_MOVE); + childSetEnabled("checkbox allow everyone copy",owner_mask_on & PERM_COPY && owner_mask_on & PERM_TRANSFER); + } + else + { + childSetEnabled("checkbox share with group", FALSE); + childSetEnabled("checkbox allow everyone move", FALSE); + childSetEnabled("checkbox allow everyone copy", FALSE); + } + + if (has_change_sale_ability && (owner_mask_on & PERM_TRANSFER)) + { + childSetEnabled("checkbox for sale", can_transfer || (!can_transfer && num_for_sale)); + // Set the checkbox to tentative if the prices of each object selected + // are not the same. + childSetTentative("checkbox for sale", is_for_sale_mixed); + childSetEnabled("sale type",num_for_sale && can_transfer && !is_sale_price_mixed); + + childSetEnabled("Next owner can:", TRUE); + childSetEnabled("checkbox next owner can modify",base_mask_on & PERM_MODIFY); + childSetEnabled("checkbox next owner can copy",base_mask_on & PERM_COPY); + childSetEnabled("checkbox next owner can transfer",next_owner_mask_on & PERM_COPY); + } + else + { + childSetEnabled("checkbox for sale",FALSE); + childSetEnabled("sale type",FALSE); + + childSetEnabled("Next owner can:",FALSE); + childSetEnabled("checkbox next owner can modify",FALSE); + childSetEnabled("checkbox next owner can copy",FALSE); + childSetEnabled("checkbox next owner can transfer",FALSE); + } + + if(valid_group_perms) + { + if((group_mask_on & PERM_COPY) && (group_mask_on & PERM_MODIFY) && (group_mask_on & PERM_MOVE)) + { + childSetValue("checkbox share with group",TRUE); + childSetTentative("checkbox share with group",FALSE); + childSetEnabled("button deed",gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer); + } + else if((group_mask_off & PERM_COPY) && (group_mask_off & PERM_MODIFY) && (group_mask_off & PERM_MOVE)) + { + childSetValue("checkbox share with group",FALSE); + childSetTentative("checkbox share with group",false); + childSetEnabled("button deed",false); + } + else + { + childSetValue("checkbox share with group",TRUE); + childSetTentative("checkbox share with group",true); + childSetEnabled("button deed",gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (group_mask_on & PERM_MOVE) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer); + } + } + + if(valid_everyone_perms) + { + // Move + if(everyone_mask_on & PERM_MOVE) + { + childSetValue("checkbox allow everyone move",TRUE); + childSetTentative("checkbox allow everyone move",false); + } + else if(everyone_mask_off & PERM_MOVE) + { + childSetValue("checkbox allow everyone move",FALSE); + childSetTentative("checkbox allow everyone move",false); + } + else + { + childSetValue("checkbox allow everyone move",TRUE); + childSetTentative("checkbox allow everyone move",true); + } + + // Copy == everyone can't copy + if(everyone_mask_on & PERM_COPY) + { + childSetValue("checkbox allow everyone copy",TRUE); + childSetTentative("checkbox allow everyone copy",!can_copy || !can_transfer); + } + else if(everyone_mask_off & PERM_COPY) + { + childSetValue("checkbox allow everyone copy",FALSE); + childSetTentative("checkbox allow everyone copy",false); + } + else + { + childSetValue("checkbox allow everyone copy",TRUE); + childSetTentative("checkbox allow everyone copy",true); + } + } + + if(valid_next_perms) + { + // Modify == next owner canot modify + if(next_owner_mask_on & PERM_MODIFY) + { + childSetValue("checkbox next owner can modify",TRUE); + childSetTentative("checkbox next owner can modify",false); + } + else if(next_owner_mask_off & PERM_MODIFY) + { + childSetValue("checkbox next owner can modify",FALSE); + childSetTentative("checkbox next owner can modify",false); + } + else + { + childSetValue("checkbox next owner can modify",TRUE); + childSetTentative("checkbox next owner can modify",true); + } + + // Copy == next owner cannot copy + if(next_owner_mask_on & PERM_COPY) + { + childSetValue("checkbox next owner can copy",TRUE); + childSetTentative("checkbox next owner can copy",!can_copy); + } + else if(next_owner_mask_off & PERM_COPY) + { + childSetValue("checkbox next owner can copy",FALSE); + childSetTentative("checkbox next owner can copy",FALSE); + } + else + { + childSetValue("checkbox next owner can copy",TRUE); + childSetTentative("checkbox next owner can copy",TRUE); + } + + // Transfer == next owner cannot transfer + if(next_owner_mask_on & PERM_TRANSFER) + { + childSetValue("checkbox next owner can transfer",TRUE); + childSetTentative("checkbox next owner can transfer",!can_transfer); + } + else if(next_owner_mask_off & PERM_TRANSFER) + { + childSetValue("checkbox next owner can transfer",FALSE); + childSetTentative("checkbox next owner can transfer",FALSE); + } + else + { + childSetValue("checkbox next owner can transfer",TRUE); + childSetTentative("checkbox next owner can transfer",TRUE); + } + } + + // reflect sale information + LLSaleInfo sale_info; + BOOL valid_sale_info = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info); + LLSaleInfo::EForSale sale_type = sale_info.getSaleType(); + + LLComboBox* combo_sale_type = getChild<LLComboBox>("sale type"); + if (valid_sale_info) + { + combo_sale_type->setValue(sale_type == LLSaleInfo::FS_NOT ? LLSaleInfo::FS_COPY : sale_type); + combo_sale_type->setTentative(FALSE); // unfortunately this doesn't do anything at the moment. + } + else + { + // default option is sell copy, determined to be safest + combo_sale_type->setValue(LLSaleInfo::FS_COPY); + combo_sale_type->setTentative(TRUE); // unfortunately this doesn't do anything at the moment. + } + + childSetValue("checkbox for sale", num_for_sale != 0); + + // HACK: There are some old objects in world that are set for sale, + // but are no-transfer. We need to let users turn for-sale off, but only + // if for-sale is set. + bool cannot_actually_sell = !can_transfer || (!can_copy && sale_type == LLSaleInfo::FS_COPY); + if (num_for_sale && has_change_sale_ability && cannot_actually_sell) + { + childSetEnabled("checkbox for sale", true); + } + + // Check search status of objects + BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); + bool include_in_search; + bool all_include_in_search = LLSelectMgr::getInstance()->selectionGetIncludeInSearch(&include_in_search); + childSetEnabled("search_check", has_change_sale_ability && all_volume); + childSetValue("search_check", include_in_search); + childSetTentative("search_check", ! all_include_in_search); + + // Click action (touch, sit, buy) + U8 click_action = 0; + if (LLSelectMgr::getInstance()->selectionGetClickAction(&click_action)) + { + LLComboBox* ComboClickAction = getChild<LLComboBox>("clickaction"); + if(ComboClickAction) + { + ComboClickAction->setCurrentByIndex((S32)click_action); + } + } + childSetEnabled("label click action",is_perm_modify && all_volume); + childSetEnabled("clickaction",is_perm_modify && all_volume); + + if (!getIsEditing()) + { + const std::string no_item_names[]={ + "Object Name", + "Object Description", + "button set group", + "checkbox share with group", + "button deed", + "checkbox allow everyone move", + "checkbox allow everyone copy", + "checkbox for sale", + "sale type", + "Edit Cost", + "checkbox next owner can modify", + "checkbox next owner can copy", + "checkbox next owner can transfer", + "clickaction", + "search_check", + "perm_modify", + "Group Name", + }; + for(size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t) + { + childSetEnabled(no_item_names[t],false); + } + } + updateVerbs(); +} + + +// static +void LLSidepanelTaskInfo::onClickClaim(void*) +{ + // try to claim ownership + LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID()); +} + +// static +void LLSidepanelTaskInfo::onClickRelease(void*) +{ + // try to release ownership + LLSelectMgr::getInstance()->sendOwner(LLUUID::null, LLUUID::null); +} + +void LLSidepanelTaskInfo::onClickGroup() +{ + LLUUID owner_id; + std::string name; + BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, name); + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + + if(owners_identical && (owner_id == gAgent.getID())) + { + LLFloaterGroupPicker* fg = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(gAgent.getID())); + if (fg) + { + fg->setSelectGroupCallback( boost::bind(&LLSidepanelTaskInfo::cbGroupID, this, _1) ); + + if (parent_floater) + { + LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, fg); + fg->setOrigin(new_rect.mLeft, new_rect.mBottom); + parent_floater->addDependentFloater(fg); + } + } + } +} + +void LLSidepanelTaskInfo::cbGroupID(LLUUID group_id) +{ + if(mLabelGroupName) + { + mLabelGroupName->setNameID(group_id, TRUE); + } + LLSelectMgr::getInstance()->sendGroup(group_id); +} + +static bool callback_deed_to_group(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if (0 == option) + { + LLUUID group_id; + BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id); + if(group_id.notNull() && groups_identical && (gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED))) + { + LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE); +// LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT); + } + } + return false; +} + +void LLSidepanelTaskInfo::onClickDeedToGroup() +{ + LLNotifications::instance().add( "DeedObjectToGroup", LLSD(), LLSD(), callback_deed_to_group); +} + +///---------------------------------------------------------------------------- +/// Permissions checkboxes +///---------------------------------------------------------------------------- + +void LLSidepanelTaskInfo::onCommitPerm(LLCheckBoxCtrl *ctrl, U8 field, U32 perm) +{ + LLViewerObject* object = mObjectSelection->getFirstRootObject(); + if(!object) return; + + BOOL new_state = ctrl->get(); + LLSelectMgr::getInstance()->selectionSetObjectPermissions(field, new_state, perm); +} + +void LLSidepanelTaskInfo::onCommitGroupShare() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox share with group"); + onCommitPerm(ctrl, PERM_GROUP, PERM_MODIFY | PERM_MOVE | PERM_COPY); +} + +void LLSidepanelTaskInfo::onCommitEveryoneMove() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox allow everyone move"); + onCommitPerm(ctrl, PERM_EVERYONE, PERM_MOVE); +} + + +void LLSidepanelTaskInfo::onCommitEveryoneCopy() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox allow everyone copy"); + onCommitPerm(ctrl, PERM_EVERYONE, PERM_COPY); +} + +void LLSidepanelTaskInfo::onCommitNextOwnerModify() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox next owner can modify"); + onCommitPerm(ctrl, PERM_NEXT_OWNER, PERM_MODIFY); +} + +void LLSidepanelTaskInfo::onCommitNextOwnerCopy() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox next owner can copy"); + onCommitPerm(ctrl, PERM_NEXT_OWNER, PERM_COPY); +} + +void LLSidepanelTaskInfo::onCommitNextOwnerTransfer() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox next owner can transfer"); + onCommitPerm(ctrl, PERM_NEXT_OWNER, PERM_TRANSFER); +} + +void LLSidepanelTaskInfo::onCommitName() +{ + LLLineEditor* tb = getChild<LLLineEditor>("Object Name"); + LLSelectMgr::getInstance()->selectionSetObjectName(tb->getText()); +} + +void LLSidepanelTaskInfo::onCommitDesc() +{ + LLLineEditor* le = getChild<LLLineEditor>("Object Description"); + LLSelectMgr::getInstance()->selectionSetObjectDescription(le->getText()); +} + +void LLSidepanelTaskInfo::onCommitSaleInfo() +{ + setAllSaleInfo(); +} + +void LLSidepanelTaskInfo::onCommitSaleType() +{ + setAllSaleInfo(); +} + +void LLSidepanelTaskInfo::setAllSaleInfo() +{ + llinfos << "LLSidepanelTaskInfo::setAllSaleInfo()" << llendl; + LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_NOT; + + LLCheckBoxCtrl *checkPurchase = getChild<LLCheckBoxCtrl>("checkbox for sale"); + + // Set the sale type if the object(s) are for sale. + if(checkPurchase && checkPurchase->get()) + { + sale_type = static_cast<LLSaleInfo::EForSale>(getChild<LLComboBox>("sale type")->getValue().asInteger()); + } + + S32 price = -1; + + LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost"); + price = (edit_price->getTentative()) ? DEFAULT_PRICE : edit_price->getValue().asInteger(); + + // If somehow an invalid price, turn the sale off. + if (price < 0) + sale_type = LLSaleInfo::FS_NOT; + + LLSaleInfo sale_info(sale_type, price); + LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(sale_info); + + // If turned off for-sale, make sure click-action buy is turned + // off as well + if (sale_type == LLSaleInfo::FS_NOT) + { + U8 click_action = 0; + LLSelectMgr::getInstance()->selectionGetClickAction(&click_action); + if (click_action == CLICK_ACTION_BUY) + { + LLSelectMgr::getInstance()->selectionSetClickAction(CLICK_ACTION_TOUCH); + } + } +} + +struct LLSelectionPayable : public LLSelectedObjectFunctor +{ + virtual bool apply(LLViewerObject* obj) + { + // can pay if you or your parent has money() event in script + LLViewerObject* parent = (LLViewerObject*)obj->getParent(); + return (obj->flagTakesMoney() + || (parent && parent->flagTakesMoney())); + } +}; + +// static +void LLSidepanelTaskInfo::onCommitClickAction(U8 click_action) +{ + if (click_action == CLICK_ACTION_BUY) + { + LLSaleInfo sale_info; + LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info); + if (!sale_info.isForSale()) + { + LLNotifications::instance().add("CantSetBuyObject"); + + // Set click action back to its old value + U8 click_action = 0; + LLSelectMgr::getInstance()->selectionGetClickAction(&click_action); +// box->setCurrentByIndex((S32)click_action); + + return; + } + } + else if (click_action == CLICK_ACTION_PAY) + { + // Verify object has script with money() handler + LLSelectionPayable payable; + bool can_pay = mObjectSelection->applyToObjects(&payable); + if (!can_pay) + { + // Warn, but do it anyway. + LLNotifications::instance().add("ClickActionNotPayable"); + } + } + LLSelectMgr::getInstance()->selectionSetClickAction(click_action); +} + +// static +void LLSidepanelTaskInfo::onCommitIncludeInSearch() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("search_check"); + LLSelectMgr::getInstance()->selectionSetIncludeInSearch(ctrl->get()); +} + +// virtual +void LLSidepanelTaskInfo::updateVerbs() +{ + LLSidepanelInventorySubpanel::updateVerbs(); + + mOpenBtn->setVisible(!getIsEditing()); + mPayBtn->setVisible(!getIsEditing()); + mBuyBtn->setVisible(!getIsEditing()); + + mOpenBtn->setEnabled(enable_object_open()); + const LLViewerObject *obj = getFirstSelectedObject(); + mEditBtn->setEnabled(obj && obj->permModify()); +} + +void LLSidepanelTaskInfo::onOpenButtonClicked() +{ + if (enable_object_open()) + { + handle_object_open(); + } +} + +void LLSidepanelTaskInfo::onPayButtonClicked() +{ + onCommitClickAction(CLICK_ACTION_PAY); +} + +void LLSidepanelTaskInfo::onBuyButtonClicked() +{ + onCommitClickAction(CLICK_ACTION_BUY); +} + +// virtual +void LLSidepanelTaskInfo::save() +{ + onCommitGroupShare(); + onCommitEveryoneMove(); + onCommitEveryoneCopy(); + onCommitNextOwnerModify(); + onCommitNextOwnerCopy(); + onCommitNextOwnerTransfer(); + onCommitName(); + onCommitDesc(); + onCommitSaleInfo(); + onCommitSaleType(); + onCommitIncludeInSearch(); +} + +void LLSidepanelTaskInfo::setObjectSelection(LLObjectSelectionHandle selection) +{ + mObjectSelection = selection; +} + +LLSidepanelTaskInfo* LLSidepanelTaskInfo::getActivePanel() +{ + return sActivePanel; +} + +LLViewerObject* LLSidepanelTaskInfo::getFirstSelectedObject() +{ + LLSelectNode *node = mObjectSelection->getFirstRootNode(); + if (node) + { + return node->getObject(); + } + return NULL; +} + +const LLUUID& LLSidepanelTaskInfo::getSelectedUUID() +{ + const LLViewerObject* obj = getFirstSelectedObject(); + if (obj) + { + return obj->getID(); + } + return LLUUID::null; +} diff --git a/indra/newview/llsidepaneltaskinfo.h b/indra/newview/llsidepaneltaskinfo.h new file mode 100644 index 0000000000..b6dd4dfb2c --- /dev/null +++ b/indra/newview/llsidepaneltaskinfo.h @@ -0,0 +1,115 @@ +/** + * @file llsidepaneltaskinfo.h + * @brief LLSidepanelTaskInfo class header file + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLSIDEPANELTASKINFO_H +#define LL_LLSIDEPANELTASKINFO_H + +#include "llsidepanelinventorysubpanel.h" +#include "lluuid.h" +#include "llselectmgr.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLSidepanelTaskInfo +// +// Panel for permissions of an object. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLNameBox; +class LLCheckBoxCtrl; +class LLViewerObject; + +class LLSidepanelTaskInfo : public LLSidepanelInventorySubpanel +{ +public: + LLSidepanelTaskInfo(); + virtual ~LLSidepanelTaskInfo(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void setVisible(BOOL visible); + + void setObjectSelection(LLObjectSelectionHandle selection); + + const LLUUID& getSelectedUUID(); + LLViewerObject* getFirstSelectedObject(); + + static LLSidepanelTaskInfo *getActivePanel(); +protected: + /*virtual*/ void refresh(); // refresh all labels as needed + /*virtual*/ void save(); + /*virtual*/ void updateVerbs(); + + // statics + static void onClickClaim(void*); + static void onClickRelease(void*); + void onClickGroup(); + void cbGroupID(LLUUID group_id); + + void onClickDeedToGroup(); + void onCommitPerm(LLCheckBoxCtrl* ctrl, U8 field, U32 perm); + void onCommitGroupShare(); + void onCommitEveryoneMove(); + void onCommitEveryoneCopy(); + void onCommitNextOwnerModify(); + void onCommitNextOwnerCopy(); + void onCommitNextOwnerTransfer(); + void onCommitName(); + void onCommitDesc(); + void onCommitSaleInfo(); + void onCommitSaleType(); + + void onCommitClickAction(U8 click_action); + void onCommitIncludeInSearch(); + + void setAllSaleInfo(); + +private: + LLNameBox* mLabelGroupName; // group name + + LLUUID mCreatorID; + LLUUID mOwnerID; + LLUUID mLastOwnerID; + +protected: + void onOpenButtonClicked(); + void onPayButtonClicked(); + void onBuyButtonClicked(); +private: + LLButton* mOpenBtn; + LLButton* mPayBtn; + LLButton* mBuyBtn; + + LLObjectSelectionHandle mObjectSelection; + static LLSidepanelTaskInfo* sActivePanel; +}; + + +#endif // LL_LLSIDEPANELTASKINFO_H diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 9f317803ce..8c5439d47e 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2679,8 +2679,7 @@ void renderTexturePriority(LLDrawable* drawable) //LLViewerTexture* imagep = facep->getTexture(); //if (imagep) { - - //F32 vsize = LLVOVolume::getTextureVirtualSize(facep); + //F32 vsize = imagep->mMaxVirtualSize; F32 vsize = facep->getPixelArea(); @@ -2704,7 +2703,7 @@ void renderTexturePriority(LLDrawable* drawable) drawBox(center, size); /*S32 boost = imagep->getBoostLevel(); - if (boost) + if (boost>LLViewerTexture::BOOST_NONE) { F32 t = (F32) boost / (F32) (LLViewerTexture::BOOST_MAX_LEVEL-1); LLVector4 col = lerp(boost_cold, boost_hot, t); diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp new file mode 100644 index 0000000000..cd765b0338 --- /dev/null +++ b/indra/newview/llspeakbutton.cpp @@ -0,0 +1,174 @@ +/** +* @file llspeakbutton.cpp +* @brief LLSpeakButton class implementation +* +* $LicenseInfo:firstyear=2002&license=viewergpl$ +* +* Copyright (c) 2002-2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" // must be first include + +#include "llagent.h" +#include "llbottomtray.h" +#include "llfloaterreg.h" +#include "llvoiceclient.h" +#include "llvoicecontrolpanel.h" +#include "lltransientfloatermgr.h" + +#include "llavatariconctrl.h" +#include "llbutton.h" +#include "llpanel.h" +#include "lltextbox.h" +#include "lloutputmonitorctrl.h" +#include "llgroupmgr.h" + +#include "llspeakbutton.h" + +static LLDefaultChildRegistry::Register<LLSpeakButton> t1("talk_button"); + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLSpeakButton::Params::Params() + : speak_button("speak_button") + , show_button("show_button") + , monitor("monitor") +{ + // See widgets/talk_button.xml +} + +LLSpeakButton::LLSpeakButton(const Params& p) +: LLUICtrl(p) +, mPrivateCallPanel(NULL) +, mOutputMonitor(NULL) +, mSpeakBtn(NULL) +, mShowBtn(NULL) +{ + LLRect rect = p.rect(); + LLRect speak_rect(0, rect.getHeight(), rect.getWidth(), 0); + LLRect show_rect = p.show_button.rect(); + show_rect.set(0, rect.getHeight(), show_rect.getWidth(), 0); + + speak_rect.mRight -= show_rect.getWidth(); + show_rect.mLeft = speak_rect.getWidth(); + show_rect.mRight = rect.getWidth(); + + LLButton::Params speak_params = p.speak_button; + speak_params.rect(speak_rect); + mSpeakBtn = LLUICtrlFactory::create<LLButton>(speak_params); + addChild(mSpeakBtn); + LLTransientFloaterMgr::getInstance()->addControlView(mSpeakBtn); + + mSpeakBtn->setClickedCallback(boost::bind(&LLSpeakButton::onClick_SpeakBtn, this)); + mSpeakBtn->setToggleState(FALSE); + + LLButton::Params show_params = p.show_button; + show_params.rect(show_rect); + mShowBtn = LLUICtrlFactory::create<LLButton>(show_params); + addChild(mShowBtn); + LLTransientFloaterMgr::getInstance()->addControlView(mShowBtn); + + mShowBtn->setClickedCallback(boost::bind(&LLSpeakButton::onClick_ShowBtn, this)); + mShowBtn->setToggleState(FALSE); + + static const S32 MONITOR_RIGHT_PAD = 2; + + LLRect monitor_rect = p.monitor.rect(); + S32 monitor_height = monitor_rect.getHeight(); + monitor_rect.mLeft = speak_rect.getWidth() - monitor_rect.getWidth() - MONITOR_RIGHT_PAD; + monitor_rect.mRight = speak_rect.getWidth() - MONITOR_RIGHT_PAD; + monitor_rect.mBottom = (rect.getHeight() / 2) - (monitor_height / 2); + monitor_rect.mTop = monitor_rect.mBottom + monitor_height; + + LLOutputMonitorCtrl::Params monitor_params = p.monitor; + monitor_params.draw_border(false); + monitor_params.rect(monitor_rect); + monitor_params.auto_update(true); + monitor_params.speaker_id(gAgentID); + mOutputMonitor = LLUICtrlFactory::create<LLOutputMonitorCtrl>(monitor_params); + mSpeakBtn->addChild(mOutputMonitor); + + // never show "muted" because you can't mute yourself + mOutputMonitor->setIsMuted(false); + mOutputMonitor->setIsAgentControl(true); +} + +LLSpeakButton::~LLSpeakButton() +{ +} + +void LLSpeakButton::setSpeakBtnToggleState(bool state) +{ + mSpeakBtn->setToggleState(state); +} + +void LLSpeakButton::onClick_SpeakBtn() +{ + bool speaking = mSpeakBtn->getToggleState(); + gVoiceClient->setUserPTTState(speaking); +} + +void LLSpeakButton::onClick_ShowBtn() +{ + if(!mShowBtn->getToggleState()) + { + mPrivateCallPanel->onClickClose(mPrivateCallPanel); + delete mPrivateCallPanel; + mPrivateCallPanel = NULL; + mShowBtn->setToggleState(FALSE); + return; + } + + S32 x = mSpeakBtn->getRect().mLeft; + S32 y = 0; + + localPointToScreen(x, y, &x, &y); + + mPrivateCallPanel = new LLVoiceControlPanel; + getRootView()->addChild(mPrivateCallPanel); + + y = LLBottomTray::getInstance()->getRect().getHeight() + mPrivateCallPanel->getRect().getHeight(); + + LLRect rect; + rect.setLeftTopAndSize(x, y, mPrivateCallPanel->getRect().getWidth(), mPrivateCallPanel->getRect().getHeight()); + mPrivateCallPanel->setRect(rect); + + + LLAvatarListItem* item = new LLAvatarListItem(); + item->showLastInteractionTime(false); + item->showInfoBtn(true); + item->showSpeakingIndicator(true); + item->reshape(mPrivateCallPanel->getRect().getWidth(), item->getRect().getHeight(), FALSE); + + mPrivateCallPanel->addItem(item); + mPrivateCallPanel->setVisible(TRUE); + mPrivateCallPanel->setFrontmost(TRUE); + + mShowBtn->setToggleState(TRUE); +} + diff --git a/indra/newview/llspeakbutton.h b/indra/newview/llspeakbutton.h new file mode 100644 index 0000000000..f59ded2133 --- /dev/null +++ b/indra/newview/llspeakbutton.h @@ -0,0 +1,82 @@ +/** +* @file llspeakbutton.h +* @brief LLSpeakButton class header file +* +* $LicenseInfo:firstyear=2002&license=viewergpl$ +* +* Copyright (c) 2002-2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ + +#ifndef LL_LLSPEAKBUTTON_H +#define LL_LLSPEAKBUTTON_H + +#include "llinitparam.h" +#include "lluictrl.h" + +class LLVoiceControlPanel; +class LLButton; +class LLOutputMonitorCtrl; + +/* + * Button displaying voice chat status. Displays voice chat options when + * clicked. +*/ +class LLSpeakButton : public LLUICtrl + +{ +public: + + struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> + { + Optional<LLButton::Params> + speak_button, + show_button; + + Optional<LLOutputMonitorCtrl::Params> monitor; + + Params(); + }; + + /*virtual*/ ~LLSpeakButton(); + + void setSpeakBtnToggleState(bool state); + +protected: + friend class LLUICtrlFactory; + LLSpeakButton(const Params& p); + + void onClick_SpeakBtn(); + + void onClick_ShowBtn(); + +private: + LLButton* mSpeakBtn; + LLButton* mShowBtn; + LLVoiceControlPanel* mPrivateCallPanel; + LLOutputMonitorCtrl* mOutputMonitor; +}; + +#endif // LL_LLSPEAKBUTTON_H diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 2341fcfc6d..2ed82b7d62 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -87,6 +87,21 @@ void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, c mDisplayName = first + " " + last; } +LLSpeakerUpdateModeratorEvent::LLSpeakerUpdateModeratorEvent(LLSpeaker* source) +: LLEvent(source, "Speaker add moderator event"), + mSpeakerID (source->mID), + mIsModerator (source->mIsModerator) +{ +} + +LLSD LLSpeakerUpdateModeratorEvent::getValue() +{ + LLSD ret; + ret["id"] = mSpeakerID; + ret["is_moderator"] = mIsModerator; + return ret; +} + LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source) : LLEvent(source, "Speaker text moderation event") { @@ -437,9 +452,13 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers) if ( speaker_it->second.isMap() ) { + BOOL is_moderator = speakerp->mIsModerator; speakerp->mIsModerator = speaker_it->second["is_moderator"]; speakerp->mModeratorMutedText = speaker_it->second["mutes"]["text"]; + // Fire event only if moderator changed + if ( is_moderator != speakerp->mIsModerator ) + fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); } } } @@ -507,7 +526,11 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) if (agent_info.has("is_moderator")) { + BOOL is_moderator = speakerp->mIsModerator; speakerp->mIsModerator = agent_info["is_moderator"]; + // Fire event only if moderator changed + if ( is_moderator != speakerp->mIsModerator ) + fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); } if (agent_info.has("mutes")) diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index e0f22bff4f..04046a8587 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -84,6 +84,16 @@ public: BOOL mModeratorMutedText; }; +class LLSpeakerUpdateModeratorEvent : public LLOldEvents::LLEvent +{ +public: + LLSpeakerUpdateModeratorEvent(LLSpeaker* source); + /*virtual*/ LLSD getValue(); +private: + const LLUUID& mSpeakerID; + BOOL mIsModerator; +}; + class LLSpeakerTextModerationEvent : public LLOldEvents::LLEvent { public: diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0ffea6d600..0a6eefc41d 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -60,6 +60,7 @@ #include "llfocusmgr.h" #include "llhttpsender.h" #include "lllocationhistory.h" +#include "llimageworker.h" #include "llloginflags.h" #include "llmd5.h" #include "llmemorystream.h" @@ -168,7 +169,7 @@ #include "llvoclouds.h" #include "llweb.h" #include "llworld.h" -#include "llworldmap.h" +#include "llworldmapmessage.h" #include "llxfermanager.h" #include "pipeline.h" #include "llappviewer.h" @@ -334,7 +335,7 @@ void populate_favorites_bar() S32 count = lib_cats->count(); for(S32 i = 0; i < count; ++i) { - if(lib_cats->get(i)->getPreferredType() == LLAssetType::AT_LANDMARK) + if(lib_cats->get(i)->getPreferredType() == LLFolderType::FT_LANDMARK) { lib_landmarks = lib_cats->get(i)->getUUID(); break; @@ -351,7 +352,7 @@ void populate_favorites_bar() gInventory.getDirectDescendentsOf(lib_landmarks, lm_cats, lm_items); if (!lm_items) return; - LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + const LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); if (favorites_id.isNull()) { llerror("My Inventory is missing My Favorites", 0); @@ -738,11 +739,12 @@ bool idle_startup() } if (!gLoginHandler.getFirstName().empty() || !gLoginHandler.getLastName().empty() - || !gLoginHandler.getWebLoginKey().isNull() ) + /*|| !gLoginHandler.getWebLoginKey().isNull()*/ ) { // We have at least some login information on a SLURL gFirstname = gLoginHandler.getFirstName(); gLastname = gLoginHandler.getLastName(); + LL_DEBUGS("LLStartup") << "STATE_FIRST: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; // Show the login screen if we don't have everything show_connect_box = @@ -753,6 +755,7 @@ bool idle_startup() LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); gFirstname = cmd_line_login[0].asString(); gLastname = cmd_line_login[1].asString(); + LL_DEBUGS("LLStartup") << "Setting gFirstname, gLastname from gSavedSettings(\"UserLoginInfo\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str()); char md5pass[33]; /* Flawfinder: ignore */ @@ -770,6 +773,7 @@ bool idle_startup() { gFirstname = gSavedSettings.getString("FirstName"); gLastname = gSavedSettings.getString("LastName"); + LL_DEBUGS("LLStartup") << "AutoLogin: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; gPassword = LLStartUp::loadPasswordFromDisk(); gSavedSettings.setBOOL("RememberPassword", TRUE); @@ -785,6 +789,7 @@ bool idle_startup() // a valid grid is selected gFirstname = gSavedSettings.getString("FirstName"); gLastname = gSavedSettings.getString("LastName"); + LL_DEBUGS("LLStartup") << "normal login: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; gPassword = LLStartUp::loadPasswordFromDisk(); show_connect_box = true; } @@ -895,13 +900,16 @@ bool idle_startup() gViewerWindow->moveProgressViewToFront(); //reset the values that could have come in from a slurl - if (!gLoginHandler.getWebLoginKey().isNull()) + // DEV-42215: Make sure they're not empty -- gFirstname and gLastname + // might already have been set from gSavedSettings, and it's too bad + // to overwrite valid values with empty strings. + if (! gLoginHandler.getFirstName().empty() && ! gLoginHandler.getLastName().empty()) { gFirstname = gLoginHandler.getFirstName(); gLastname = gLoginHandler.getLastName(); -// gWebLoginKey = gLoginHandler.getWebLoginKey(); + LL_DEBUGS("LLStartup") << "STATE_LOGIN_CLEANUP: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; } - + if (show_connect_box) { // TODO if not use viewer auth @@ -1314,6 +1322,7 @@ bool idle_startup() gViewerWindow->moveProgressViewToFront(); LLError::logToFixedBuffer(gDebugView->mDebugConsolep); + // set initial visibility of debug console gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole")); } @@ -1677,7 +1686,7 @@ bool idle_startup() gInventory.buildParentChildMap(); //all categories loaded. lets create "My Favorites" category - gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE,true); + gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true); // lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" and fill it with buddies LLFriendCardsManager::instance().syncFriendsFolder(); @@ -2529,9 +2538,8 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); - msg->setHandlerFunc("MapLayerReply", LLWorldMap::processMapLayerReply); - msg->setHandlerFunc("MapBlockReply", LLWorldMap::processMapBlockReply); - msg->setHandlerFunc("MapItemReply", LLWorldMap::processMapItemReply); + msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply); + msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply); msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply); msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index 5440b2c9ad..1d479bac8c 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -234,12 +234,7 @@ void LLSurface::createSTexture() { if (!mSTexturep) { - // Fill with dummy gray data. - - //mSTexturep = LLViewerTextureManager::getLocalTexture(sTextureSize, sTextureSize, 3, FALSE); - //mSTexturep->dontDiscard(); - //mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - + // Fill with dummy gray data. // GL NOT ACTIVE HERE LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3); U8 *default_texture = raw->getData(); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index c255418429..723ac0fc33 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -66,6 +66,7 @@ BOOL LLSysWellWindow::postBuild() // init connections to the list's update events connectListUpdaterToSignal("notify"); connectListUpdaterToSignal("groupnotify"); + connectListUpdaterToSignal("offer"); // get a corresponding channel initChannel(); diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 5d9046ac90..5d682cad3c 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -670,8 +670,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); gGL.setColorMask(true, true); - BOOL render_morph = mAvatar->morphMaskNeedsUpdate(mBakedTexIndex); - // clear buffer area to ensure we don't pick up UI elements { gGL.flush(); @@ -691,12 +689,8 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) if (layer->getRenderPass() == LLTexLayer::RP_COLOR) { gGL.flush(); - success &= layer->render(x, y, width, height, render_morph); + success &= layer->render(x, y, width, height); gGL.flush(); - if (layer->isMorphValid()) - { - mAvatar->setMorphMasksValid(TRUE, mBakedTexIndex); - } } } @@ -786,12 +780,10 @@ void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height) { memset(data, 255, width * height); - BOOL render_morph = mAvatar->morphMaskNeedsUpdate(mBakedTexIndex); - for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayerInterface* layer = *iter; - layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height, render_morph); + layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height); } // Set alpha back to that of our alpha masks. @@ -863,6 +855,31 @@ void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_ mAvatar->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); } +BOOL LLTexLayerSet::isMorphValid() +{ + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + if (layer && !layer->isMorphValid()) + { + return FALSE; + } + } + return TRUE; +} + +void LLTexLayerSet::invalidateMorphMasks() +{ + for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) + { + LLTexLayerInterface* layer = *iter; + if (layer) + { + layer->invalidateMorphMasks(); + } + } +} + //----------------------------------------------------------------------------- // LLTexLayerInfo @@ -1282,7 +1299,7 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL } } -BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) +BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) { LLGLEnable color_mat(GL_COLOR_MATERIAL); gPipeline.disableLights(); @@ -1333,7 +1350,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) } }//*/ - renderMorphMasks(x, y, width, height, net_color, render_morph); + renderMorphMasks(x, y, width, height, net_color); alpha_mask_specified = TRUE; gGL.flush(); gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); @@ -1371,7 +1388,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); - gGL.getTexUnit(0)->bind(tex); + gGL.getTexUnit(0)->bind(tex, TRUE); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gl_rect_2d_simple_tex( width, height ); @@ -1393,7 +1410,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { - gGL.getTexUnit(0)->bind(tex); + gGL.getTexUnit(0)->bind(tex, TRUE); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } @@ -1506,7 +1523,7 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) if( tex ) { LLGLSNoAlphaTest gls_no_alpha_test; - gGL.getTexUnit(0)->bind(tex); + gGL.getTexUnit(0)->bind(tex, TRUE); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } @@ -1534,12 +1551,12 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) return success; } -/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph) +/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { - addAlphaMask(data, originX, originY, width, height, render_morph); + addAlphaMask(data, originX, originY, width, height); } -BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, BOOL render_morph) +BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color) { BOOL success = TRUE; @@ -1578,46 +1595,38 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // Accumulate the alpha component of the texture if( getInfo()->mLocalTexture != -1 ) { - LLViewerTexture* tex = mLocalTextureObject->getImage(); - if( tex && (tex->getComponents() == 4) ) - { - LLGLSNoAlphaTest gls_no_alpha_test; + LLViewerTexture* tex = mLocalTextureObject->getImage(); + if( tex && (tex->getComponents() == 4) ) + { + LLGLSNoAlphaTest gls_no_alpha_test; - LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); - - gGL.getTexUnit(0)->bind(tex); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); + + gGL.getTexUnit(0)->bind(tex, TRUE); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - gl_rect_2d_simple_tex( width, height ); + gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->setTextureAddressMode(old_mode); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - else - { - success = FALSE; - } + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } + } if( !getInfo()->mStaticImageFileName.empty() ) { - LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); - if( tex ) - { - if( (tex->getComponents() == 4) || - ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) - { - LLGLSNoAlphaTest gls_no_alpha_test; - gGL.getTexUnit(0)->bind(tex); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - } - else + LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + if( tex ) + { + if( (tex->getComponents() == 4) || + ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) { - success = FALSE; + LLGLSNoAlphaTest gls_no_alpha_test; + gGL.getTexUnit(0)->bind(tex, TRUE); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } + } // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); @@ -1634,7 +1643,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC gGL.setColorMask(true, true); - if (render_morph && mHasMorph && success) + if (hasMorph() && success) { LLCRC alpha_mask_crc; const LLUUID& uuid = getUUID(); @@ -1674,7 +1683,7 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC return success; } -void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph) +void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { S32 size = width * height; U8* alphaData = getAlphaData(); @@ -1684,7 +1693,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 findNetColor( &net_color ); // TODO: eliminate need for layer morph mask valid flag invalidateMorphMasks(); - renderMorphMasks(originX, originY, width, height, net_color, render_morph); + renderMorphMasks(originX, originY, width, height, net_color); alphaData = getAlphaData(); } if (alphaData) @@ -1805,7 +1814,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) return layer; } -/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) +/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height) { BOOL success = TRUE; updateWearableCache(); @@ -1827,7 +1836,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) { wearable->writeToAvatar(FALSE, FALSE); layer->setLTO(lto); - success &= layer->render(x,y,width,height,render_morph); + success &= layer->render(x,y,width,height); } } @@ -1849,7 +1858,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) return success; } -/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph) +/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { U32 num_wearables = updateWearableCache(); for (U32 i = 0; i < num_wearables; i++) @@ -1857,7 +1866,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) LLTexLayer *layer = getLayer(i); if (layer) { - layer->addAlphaMask(data, originX, originY, width, height, render_morph); + layer->addAlphaMask(data, originX, originY, width, height); } } } @@ -2034,7 +2043,7 @@ LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_n // that once an image is a mask it's always a mask. tex->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); } - tex->createGLTexture(0, image_raw); + tex->createGLTexture(0, image_raw, 0, TRUE, LLViewerTexture::LOCAL); gGL.getTexUnit(0)->bind(tex); tex->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index e4a6e82ba5..cd8f27a96b 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -81,13 +81,14 @@ public: const LLTexLayerInfo* getInfo() const { return mInfo; } virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions - virtual BOOL render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph) = 0; + virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0; void requestUpdate(); LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; } virtual void deleteCaches() = 0; void invalidateMorphMasks(); virtual void setHasMorph(BOOL newval) { mHasMorph = newval; } + BOOL hasMorph() { return mHasMorph; } BOOL isMorphValid() { return mMorphMasksValid; } const std::string& getName() const; @@ -95,7 +96,7 @@ public: const std::string& getGlobalColor() const; virtual BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) = 0; - virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph) = 0; + virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0; BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); } BOOL isVisibilityMask() const; @@ -134,10 +135,10 @@ public: LLTexLayerTemplate(const LLTexLayerTemplate &layer); /*virtual*/ ~LLTexLayerTemplate(); - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph); + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions /*virtual*/ BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph); + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); /*virtual*/ void setHasMorph(BOOL newval); /*virtual*/ void deleteCaches(); private: @@ -162,16 +163,16 @@ public: /*virtual*/ ~LLTexLayer(); /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph); + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); /*virtual*/ void deleteCaches(); U8* getAlphaData(); BOOL findNetColor(LLColor4* color) const; /*virtual*/ BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph); - BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, BOOL render_morph); - void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, BOOL render_morph); + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color); + void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height); void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } LLLocalTextureObject* getLTO() { return mLocalTextureObject; } @@ -261,6 +262,8 @@ public: void deleteCaches(); void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height); void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); + BOOL isMorphValid(); + void invalidateMorphMasks(); LLTexLayerInterface* findLayerByName(const std::string& name); void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 1b249d75d1..69a2d1d7a6 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -43,11 +43,17 @@ // Included to allow LLTextureCache::purgeTextures() to pause watchdog timeout #include "llappviewer.h" -#define USE_LFS_READ 0 -#define USE_LFS_WRITE 0 - -// Note: first 4 bytes store file size, rest is j2c data -const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE; //1024; +// Cache organization: +// cache/texture.entries +// Unordered array of Entry structs +// cache/texture.cache +// First TEXTURE_CACHE_ENTRY_SIZE bytes of each texture in texture.entries in same order +// cache/textures/[0-F]/UUID.texture +// Actual texture body files + +const S32 TEXTURE_CACHE_ENTRY_SIZE = 1024; +const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by when it exceeds its limit +const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate) class LLTextureCacheWorker : public LLWorkerClass { @@ -309,94 +315,75 @@ void LLTextureCacheWorker::startWork(S32 param) { } +// This is where a texture is read from the cache system (header and body) +// Current assumption are: +// - the whole data are in a raw form, will be stored at mReadData +// - the size of this raw data is mDataSize and can be smaller than TEXTURE_CACHE_ENTRY_SIZE (the size of a record in the header cache) +// - the code supports offset reading but this is actually never exercised in the viewer bool LLTextureCacheRemoteWorker::doRead() { + bool done = false; + S32 idx = -1; + S32 local_size = 0; std::string local_filename; + // First state / stage : find out if the file is local if (mState == INIT) { std::string filename = mCache->getLocalFileName(mID); - local_filename = filename + ".j2c"; - local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); - if (local_size == 0) + // Is it a JPEG2000 file? { - local_filename = filename + ".tga"; + local_filename = filename + ".j2c"; local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); if (local_size > 0) { - mImageFormat = IMG_CODEC_TGA; - mDataSize = local_size; // Only a complete .tga file is valid + mImageFormat = IMG_CODEC_J2C; } } - if (local_size > 0) - { - mState = LOCAL; - } - else - { - mState = CACHE; - } - } - - if (mState == LOCAL) - { -#if USE_LFS_READ - if (mFileHandle == LLLFSThread::nullHandle()) + // If not, is it a jpeg file? + if (local_size == 0) { - mImageLocal = TRUE; - mImageSize = local_size; - if (!mDataSize || mDataSize + mOffset > local_size) + local_filename = filename + ".jpg"; + local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); + if (local_size > 0) { - mDataSize = local_size - mOffset; + mImageFormat = IMG_CODEC_JPEG; + mDataSize = local_size; // Only a complete .jpg file is valid } - if (mDataSize <= 0) - { - // no more data to read - mDataSize = 0; - return true; - } - mReadData = new U8[mDataSize]; - mBytesRead = -1; - mBytesToRead = mDataSize; - setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); - mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize, - new ReadResponder(mCache, mRequestHandle)); - return false; } - else + // Hmm... What about a targa file? (used for UI texture mostly) + if (local_size == 0) { - if (mBytesRead >= 0) - { - if (mBytesRead != mBytesToRead) - { -// llwarns << "Error reading file from local cache: " << local_filename -// << " Bytes: " << mDataSize << " Offset: " << mOffset -// << " / " << mDataSize << llendl; - mDataSize = 0; // failed - delete[] mReadData; - mReadData = NULL; - } - return true; - } - else + local_filename = filename + ".tga"; + local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); + if (local_size > 0) { - return false; + mImageFormat = IMG_CODEC_TGA; + mDataSize = local_size; // Only a complete .tga file is valid } } -#else + // Determine the next stage: if we found a file, then LOCAL else CACHE + mState = (local_size > 0 ? LOCAL : CACHE); + } + + // Second state / stage : if the file is local, load it and leave + if (!done && (mState == LOCAL)) + { + llassert(local_size != 0); // we're assuming there is a non empty local file here... if (!mDataSize || mDataSize > local_size) { mDataSize = local_size; } + // Allocate read buffer mReadData = new U8[mDataSize]; S32 bytes_read = LLAPRFile::readEx(local_filename, mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); if (bytes_read != mDataSize) { -// llwarns << "Error reading file from local cache: " << local_filename -// << " Bytes: " << mDataSize << " Offset: " << mOffset -// << " / " << mDataSize << llendl; + llwarns << "Error reading file from local cache: " << local_filename + << " Bytes: " << mDataSize << " Offset: " << mOffset + << " / " << mDataSize << llendl; mDataSize = 0; delete[] mReadData; mReadData = NULL; @@ -406,405 +393,275 @@ bool LLTextureCacheRemoteWorker::doRead() mImageSize = local_size; mImageLocal = TRUE; } - return true; -#endif + // We're done... + done = true; } - S32 idx = -1; - - if (mState == CACHE) + // Second state / stage : identify the cache or not... + if (!done && (mState == CACHE)) { - llassert_always(mImageSize == 0); - idx = mCache->getHeaderCacheEntry(mID, false, &mImageSize); - if (idx >= 0 && mImageSize > mOffset) + idx = mCache->getHeaderCacheEntry(mID, mImageSize); + if (idx < 0) { - llassert_always(mImageSize > 0); - if (!mDataSize || mDataSize > mImageSize) - { - mDataSize = mImageSize; - } - mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; + // The texture is *not* cached. We're done here... + mDataSize = 0; // no data + done = true; } else { - mDataSize = 0; // no data - return true; + // If the read offset is bigger than the header cache, we read directly from the body + // Note that currently, we *never* read with offset from the cache, so the result is *always* HEADER + mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; } } - if (mState == HEADER) + // Third state / stage : read data from the header cache (texture.entries) file + if (!done && (mState == HEADER)) { -#if USE_LFS_READ - if (mFileHandle == LLLFSThread::nullHandle()) - { - llassert_always(idx >= 0); - llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); - S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; - S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; - llassert_always(mReadData == NULL); - mReadData = new U8[size]; - mBytesRead = -1; - mBytesToRead = size; - setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); - mFileHandle = LLLFSThread::sLocal->read(mCache->mHeaderDataFileName, - mReadData, offset, mBytesToRead, - new ReadResponder(mCache, mRequestHandle)); - return false; - } - else - { - if (mBytesRead >= 0) - { - if (mBytesRead != mBytesToRead) - { -// llwarns << "LLTextureCacheWorker: " << mID -// << " incorrect number of bytes read from header: " << mBytesRead -// << " != " << mBytesToRead << llendl; - mDataSize = -1; // failed - return true; - } - if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE) - { - return true; // done - } - else - { - mFileHandle = LLLFSThread::nullHandle(); - mState = BODY; - } - } - else - { - return false; - } - } -#else - llassert_always(idx >= 0); + llassert_always(idx >= 0); // we need an entry here or reading the header makes no sense llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; + // Compute the size we need to read (in bytes) S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; + size = llmin(size, mDataSize); + // Allocate the read buffer mReadData = new U8[size]; S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, mReadData, offset, size, mCache->getLocalAPRFilePool()); if (bytes_read != size) { -// llwarns << "LLTextureCacheWorker: " << mID -// << " incorrect number of bytes read from header: " << bytes_read -// << " / " << size << llendl; + llwarns << "LLTextureCacheWorker: " << mID + << " incorrect number of bytes read from header: " << bytes_read + << " / " << size << llendl; + delete[] mReadData; + mReadData = NULL; mDataSize = -1; // failed - return true; + done = true; } - if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE) + // If we already read all we expected, we're actually done + if (mDataSize <= bytes_read) { - return true; // done + done = true; } else { mState = BODY; } -#endif } - if (mState == BODY) + // Fourth state / stage : read the rest of the data from the UUID based cached file + if (!done && (mState == BODY)) { -#if USE_LFS_READ - if (mFileHandle == LLLFSThread::nullHandle()) - { - std::string filename = mCache->getTextureFileName(mID); - S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool()); - if (filesize > mOffset) - { - S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize; - mDataSize = llmin(datasize, mDataSize); - S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; - data_offset = llmax(data_offset, 0); - S32 file_size = mDataSize - data_offset; - S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; - file_offset = llmax(file_offset, 0); - - llassert_always(mDataSize > 0); - U8* data = new U8[mDataSize]; - if (data_offset > 0) - { - llassert_always(mReadData); - llassert_always(data_offset <= mDataSize); - memcpy(data, mReadData, data_offset); - delete[] mReadData; - mReadData = NULL; - } - llassert_always(mReadData == NULL); - mReadData = data; - - mBytesRead = -1; - mBytesToRead = file_size; - setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); - llassert_always(data_offset + mBytesToRead <= mDataSize); - mFileHandle = LLLFSThread::sLocal->read(filename, - mReadData + data_offset, file_offset, mBytesToRead, - new ReadResponder(mCache, mRequestHandle)); - return false; - } - else - { - mDataSize = TEXTURE_CACHE_ENTRY_SIZE; - return true; // done - } - } - else - { - if (mBytesRead >= 0) - { - if (mBytesRead != mBytesToRead) - { -// llwarns << "LLTextureCacheWorker: " << mID -// << " incorrect number of bytes read from body: " << mBytesRead -// << " != " << mBytesToRead << llendl; - mDataSize = -1; // failed - } - return true; - } - else - { - return false; - } - } -#else std::string filename = mCache->getTextureFileName(mID); S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool()); - S32 bytes_read = 0; - if (filesize > mOffset) + + if (filesize && (filesize + TEXTURE_CACHE_ENTRY_SIZE) > mOffset) { - S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize; - mDataSize = llmin(datasize, mDataSize); - S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; - data_offset = llmax(data_offset, 0); - S32 file_size = mDataSize - data_offset; - S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; - file_offset = llmax(file_offset, 0); + S32 max_datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize - mOffset; + mDataSize = llmin(max_datasize, mDataSize); + + S32 data_offset, file_size, file_offset; + // Reserve the whole data buffer first U8* data = new U8[mDataSize]; - if (data_offset > 0) + + // Set the data file pointers taking the read offset into account. 2 cases: + if (mOffset < TEXTURE_CACHE_ENTRY_SIZE) { + // Offset within the header record. That means we read something from the header cache. + // Note: most common case is (mOffset = 0), so this is the "normal" code path. + data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; // i.e. TEXTURE_CACHE_ENTRY_SIZE if mOffset nul (common case) + file_offset = 0; + file_size = mDataSize - data_offset; + // Copy the raw data we've been holding from the header cache into the new sized buffer llassert_always(mReadData); memcpy(data, mReadData, data_offset); delete[] mReadData; + mReadData = NULL; + } + else + { + // Offset bigger than the header record. That means we haven't read anything yet. + data_offset = 0; + file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; + file_size = mDataSize; + // No data from header cache to copy in that case, we skipped it all } + + // Now use that buffer as the object read buffer + llassert_always(mReadData == NULL); mReadData = data; - bytes_read = LLAPRFile::readEx(filename, + + // Read the data at last + S32 bytes_read = LLAPRFile::readEx(filename, mReadData + data_offset, file_offset, file_size, mCache->getLocalAPRFilePool()); if (bytes_read != file_size) { -// llwarns << "LLTextureCacheWorker: " << mID -// << " incorrect number of bytes read from body: " << bytes_read -// << " / " << file_size << llendl; + llwarns << "LLTextureCacheWorker: " << mID + << " incorrect number of bytes read from body: " << bytes_read + << " / " << file_size << llendl; + delete[] mReadData; + mReadData = NULL; mDataSize = -1; // failed - return true; + done = true; } } else { - mDataSize = TEXTURE_CACHE_ENTRY_SIZE; - } - - return true; -#endif + // No body, we're done. + mDataSize = llmax(TEXTURE_CACHE_ENTRY_SIZE - mOffset, 0); + lldebugs << "No body file for: " << filename << llendl; + } + // Nothing else to do at that point... + done = true; } - - return false; + + // Clean up and exit + return done; } +// This is where *everything* about a texture is written down in the cache system (entry map, header and body) +// Current assumption are: +// - the whole data are in a raw form, starting at mWriteData +// - the size of this raw data is mDataSize and can be smaller than TEXTURE_CACHE_ENTRY_SIZE (the size of a record in the header cache) +// - the code *does not* support offset writing so there are no difference between buffer addresses and start of data bool LLTextureCacheRemoteWorker::doWrite() { + bool done = false; S32 idx = -1; - // No LOCAL state for write() - + // First state / stage : check that what we're trying to cache is in an OK shape if (mState == INIT) { + llassert_always(mOffset == 0); // We currently do not support write offsets + llassert_always(mDataSize > 0); // Things will go badly wrong if mDataSize is nul or negative... + mState = CACHE; + } + + // No LOCAL state for write(): because it doesn't make much sense to cache a local file... + + // Second state / stage : set an entry in the headers entry (texture.entries) file + if (!done && (mState == CACHE)) + { + bool alreadyCached = false; S32 cur_imagesize = 0; - S32 offset = mOffset; - idx = mCache->getHeaderCacheEntry(mID, false, &cur_imagesize); - if (idx >= 0 && cur_imagesize > 0) + // Checks if this image is already in the entry list + idx = mCache->getHeaderCacheEntry(mID, cur_imagesize); + if (idx >= 0 && (cur_imagesize >= 0)) { - offset = TEXTURE_CACHE_ENTRY_SIZE; // don't re-write header + alreadyCached = true; // already there and non empty } - idx = mCache->getHeaderCacheEntry(mID, true, &mImageSize); // touch entry - if (idx >= 0) + idx = mCache->setHeaderCacheEntry(mID, mImageSize); // create or touch the entry + if (idx < 0) { - if(cur_imagesize > 0 && mImageSize != cur_imagesize) - { -// llwarns << "Header cache entry size: " << cur_imagesize << " != mImageSize: " << mImageSize << llendl; - offset = 0; // re-write header - } - mState = offset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; + llwarns << "LLTextureCacheWorker: " << mID + << " Unable to create header entry for writing!" << llendl; + mDataSize = -1; // failed + done = true; } else { - mDataSize = -1; // failed - return true; + if (cur_imagesize > 0 && (mImageSize != cur_imagesize)) + { + alreadyCached = false; // re-write the header if the size changed in all cases + } + if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)) + { + // Small texture already cached case: we're done with writing + done = true; + } + else + { + // If the texture has already been cached, we don't resave the header and go directly to the body part + mState = alreadyCached ? BODY : HEADER; + } } } - - if (mState == HEADER) + + // Third stage / state : write the header record in the header file (texture.cache) + if (!done && (mState == HEADER)) { -#if USE_LFS_WRITE - if (mFileHandle == LLLFSThread::nullHandle()) + llassert_always(idx >= 0); // we need an entry here or storing the header makes no sense + S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE; // skip to the correct spot in the header file + S32 size = TEXTURE_CACHE_ENTRY_SIZE; // record size is fixed for the header + S32 bytes_written; + + if (mDataSize < TEXTURE_CACHE_ENTRY_SIZE) { - llassert_always(idx >= 0); - llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); - S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; - S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; - mBytesRead = -1; - mBytesToRead = size; - setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); - mFileHandle = LLLFSThread::sLocal->write(mCache->mHeaderDataFileName, - mWriteData, offset, mBytesToRead, - new WriteResponder(mCache, mRequestHandle)); - return false; + // We need to write a full record in the header cache so, if the amount of data is smaller + // than a record, we need to transfer the data to a buffer padded with 0 and write that + U8* padBuffer = new U8[TEXTURE_CACHE_ENTRY_SIZE]; + memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros + memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer + bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool()); + delete [] padBuffer; } else { - if (mBytesRead >= 0) - { - if (mBytesRead != mBytesToRead) - { -// llwarns << "LLTextureCacheWorker: " << mID -// << " incorrect number of bytes written to header: " << mBytesRead -// << " != " << mBytesToRead << llendl; - mDataSize = -1; // failed - return true; - } - if (mDataSize <= mBytesToRead) - { - return true; // done - } - else - { - mFileHandle = LLLFSThread::nullHandle(); - mState = BODY; - } - } - else - { - return false; - } + // Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file + bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); } -#else - llassert_always(idx >= 0); - llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); - S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; - S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; - S32 bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); if (bytes_written <= 0) { -// llwarns << "LLTextureCacheWorker: missing entry: " << mID << llendl; + llwarns << "LLTextureCacheWorker: " << mID + << " Unable to write header entry!" << llendl; mDataSize = -1; // failed - return true; + done = true; } - if (mDataSize <= size) + // If we wrote everything (may be more with padding) in the header cache, + // we're done so we don't have a body to store + if (mDataSize <= bytes_written) { - return true; // done + done = true; } else { mState = BODY; } -#endif } - if (mState == BODY) + // Fourth stage / state : write the body file, i.e. the rest of the texture in a "UUID" file name + if (!done && (mState == BODY)) { -#if USE_LFS_WRITE - if (mFileHandle == LLLFSThread::nullHandle()) + llassert(mDataSize > TEXTURE_CACHE_ENTRY_SIZE); // wouldn't make sense to be here otherwise... + S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE; + if ((file_size > 0) && mCache->updateTextureEntryList(mID, file_size)) { - S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; - data_offset = llmax(data_offset, 0); - S32 file_size = mDataSize - data_offset; - S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; - file_offset = llmax(file_offset, 0); - if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size)) - { - std::string filename = mCache->getTextureFileName(mID); - mBytesRead = -1; - mBytesToRead = file_size; - setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); - mFileHandle = LLLFSThread::sLocal->write(filename, - mWriteData + data_offset, file_offset, mBytesToRead, - new WriteResponder(mCache, mRequestHandle)); - return false; - } - else - { - mDataSize = 0; // no data written - return true; // done - } - } - else - { - if (mBytesRead >= 0) - { - if (mBytesRead != mBytesToRead) - { -// llwarns << "LLTextureCacheWorker: " << mID -// << " incorrect number of bytes written to body: " << mBytesRead -// << " != " << mBytesToRead << llendl; - mDataSize = -1; // failed - } - return true; - } - else - { - return false; - } - } -#else - S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; - data_offset = llmax(data_offset, 0); - S32 file_size = mDataSize - data_offset; - S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; - file_offset = llmax(file_offset, 0); - S32 bytes_written = 0; - if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size)) - { - std::string filename = mCache->getTextureFileName(mID); - - bytes_written = LLAPRFile::writeEx(filename, - mWriteData + data_offset, - file_offset, file_size, - mCache->getLocalAPRFilePool()); + // build the cache file name from the UUID + std::string filename = mCache->getTextureFileName(mID); +// llinfos << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << llendl; + S32 bytes_written = LLAPRFile::writeEx( filename, + mWriteData + TEXTURE_CACHE_ENTRY_SIZE, + 0, file_size, + mCache->getLocalAPRFilePool()); if (bytes_written <= 0) { + llwarns << "LLTextureCacheWorker: " << mID + << " incorrect number of bytes written to body: " << bytes_written + << " / " << file_size << llendl; mDataSize = -1; // failed + done = true; } } else { mDataSize = 0; // no data written } - - return true; -#endif + // Nothing else to do at that point... + done = true; } - - return false; + + // Clean up and exit + return done; } //virtual bool LLTextureCacheWorker::doWork(S32 param) { -// *TODO reenable disabled apr_pool usage disabled due to maint-render-9 merge breakage -brad - //allocate a new local apr_pool -// LLAPRPool pool ; - - //save the current mFileAPRPool to avoid breaking anything. -// apr_pool_t* old_pool = mCache->getFileAPRPool() ; - //make mFileAPRPool to point to the local one -// mCache->setFileAPRPool(pool.getAPRPool()) ; - bool res = false; if (param == 0) // read { @@ -818,10 +675,6 @@ bool LLTextureCacheWorker::doWork(S32 param) { llassert_always(0); } - - //set mFileAPRPool back, the local one will be released automatically. -// mCache->setFileAPRPool(old_pool) ; - return res; } @@ -887,6 +740,7 @@ LLTextureCache::LLTextureCache(bool threaded) mWorkersMutex(NULL), mHeaderMutex(NULL), mListMutex(NULL), + mHeaderAPRFile(NULL), mReadOnly(FALSE), mTexturesSizeTotal(0), mDoPurge(FALSE) @@ -926,6 +780,9 @@ S32 LLTextureCache::update(U32 max_time_ms) } } + unlockWorkers(); + + // call 'completed' with workers list unlocked (may call readComplete() or writeComplete() for (responder_list_t::iterator iter1 = completed_list.begin(); iter1 != completed_list.end(); ++iter1) { @@ -934,8 +791,6 @@ S32 LLTextureCache::update(U32 max_time_ms) responder->completed(success); } - unlockWorkers(); - return res; } @@ -954,33 +809,48 @@ std::string LLTextureCache::getTextureFileName(const LLUUID& id) { std::string idstr = id.asString(); std::string delem = gDirUtilp->getDirDelimiter(); - std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr; + std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr + ".texture"; return filename; } -bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize) +bool LLTextureCache::updateTextureEntryList(const LLUUID& id, S32 bodysize) { bool res = false; bool purge = false; - // Append UUID to end of texture entries { LLMutexLock lock(&mHeaderMutex); - size_map_t::iterator iter = mTexturesSizeMap.find(id); - if (iter == mTexturesSizeMap.end() || iter->second < bodysize) + size_map_t::iterator iter1 = mTexturesSizeMap.find(id); + if (iter1 == mTexturesSizeMap.end() || iter1->second < bodysize) { llassert_always(bodysize > 0); - Entry* entry = new Entry(id, bodysize, time(NULL)); - LLAPRFile::writeEx(mTexturesDirEntriesFileName, - (U8*)entry, -1, 1*sizeof(Entry), - getLocalAPRFilePool()); - delete entry; - if (iter != mTexturesSizeMap.end()) + S32 oldbodysize = 0; + if (iter1 != mTexturesSizeMap.end()) + { + oldbodysize = iter1->second; + } + + Entry entry; + S32 idx = openAndReadEntry(id, entry, false); + if (idx < 0) + { + // TODO: change to llwarns + llerrs << "Failed to open entry: " << id << llendl; + removeFromCache(id); + return false; + } + else if (oldbodysize != entry.mBodySize) { - mTexturesSizeTotal -= iter->second; + // TODO: change to llwarns + llerrs << "Entry mismatch in mTextureSizeMap / mHeaderIDMap" + << " idx=" << idx << " oldsize=" << oldbodysize << " entrysize=" << entry.mBodySize << llendl; } + entry.mBodySize = bodysize; + writeEntryAndClose(idx, entry); + + mTexturesSizeTotal -= oldbodysize; mTexturesSizeTotal += bodysize; - mTexturesSizeMap[id] = bodysize; + if (mTexturesSizeTotal > sCacheMaxTexturesSize) { purge = true; @@ -995,11 +865,59 @@ bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize) return res; } +//debug +BOOL LLTextureCache::isInCache(const LLUUID& id) +{ + LLMutexLock lock(&mHeaderMutex); + id_map_t::const_iterator iter = mHeaderIDMap.find(id); + + return (iter != mHeaderIDMap.end()) ; +} + +//debug +BOOL LLTextureCache::isInLocal(const LLUUID& id) +{ + S32 local_size = 0; + std::string local_filename; + + std::string filename = getLocalFileName(id); + // Is it a JPEG2000 file? + { + local_filename = filename + ".j2c"; + local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool()); + if (local_size > 0) + { + return TRUE ; + } + } + + // If not, is it a jpeg file? + { + local_filename = filename + ".jpg"; + local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool()); + if (local_size > 0) + { + return TRUE ; + } + } + + // Hmm... What about a targa file? (used for UI texture mostly) + { + local_filename = filename + ".tga"; + local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool()); + if (local_size > 0) + { + return TRUE ; + } + } + + return FALSE ; +} ////////////////////////////////////////////////////////////////////////////// //static const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB -F32 LLTextureCache::sHeaderCacheVersion = 1.0f; +F32 LLTextureCache::sHeaderCacheVersion = 1.3f; U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE; S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit const char* entries_filename = "texture.entries"; @@ -1012,7 +930,6 @@ void LLTextureCache::setDirNames(ELLPath location) mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, entries_filename); mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, cache_filename); mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname); - mTexturesDirEntriesFileName = mTexturesDirName + delem + entries_filename; } void LLTextureCache::purgeCache(ELLPath location) @@ -1020,7 +937,7 @@ void LLTextureCache::purgeCache(ELLPath location) if (!mReadOnly) { setDirNames(location); - + llassert_always(mHeaderAPRFile == NULL); LLAPRFile::remove(mHeaderEntriesFileName, getLocalAPRFilePool()); LLAPRFile::remove(mHeaderDataFileName, getLocalAPRFilePool()); } @@ -1063,83 +980,317 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only) return max_size; // unused cache space } -struct lru_data +//---------------------------------------------------------------------------- +// mHeaderMutex must be locked for the following functions! + +LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset) +{ + llassert_always(mHeaderAPRFile == NULL); + apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY; + mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, getLocalAPRFilePool()); + mHeaderAPRFile->seek(APR_SET, offset); + return mHeaderAPRFile; +} + +void LLTextureCache::closeHeaderEntriesFile() +{ + llassert_always(mHeaderAPRFile != NULL); + delete mHeaderAPRFile; + mHeaderAPRFile = NULL; +} + +void LLTextureCache::readEntriesHeader() +{ + // mHeaderEntriesInfo initializes to default values so safe not to read it + llassert_always(mHeaderAPRFile == NULL); + if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool())) + { + LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); + } +} + +void LLTextureCache::writeEntriesHeader() { - lru_data(U32 t, S32 i, const LLUUID& id) { time=t; index=i; uuid=id; } - U32 time; - S32 index; - LLUUID uuid; - struct Compare - { - // lhs < rhs - typedef const lru_data* lru_data_ptr; - bool operator()(const lru_data_ptr& a, const lru_data_ptr& b) const + llassert_always(mHeaderAPRFile == NULL); + if (!mReadOnly) + { + LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); + } +} + +static S32 mHeaderEntriesMaxWriteIdx = 0; + +S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create) +{ + S32 idx = -1; + + id_map_t::iterator iter1 = mHeaderIDMap.find(id); + if (iter1 != mHeaderIDMap.end()) + { + idx = iter1->second; + } + + if (idx < 0) + { + if (create && !mReadOnly) { - if(a->time == b->time) - return (a->index < b->index); + if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries) + { + // Add an entry to the end of the list + idx = mHeaderEntriesInfo.mEntries++; + + } + else if (!mFreeList.empty()) + { + idx = *(mFreeList.begin()); + mFreeList.erase(mFreeList.begin()); + } else - return (a->time >= b->time); + { + // Look for a still valid entry in the LRU + for (std::set<LLUUID>::iterator iter2 = mLRU.begin(); iter2 != mLRU.end();) + { + std::set<LLUUID>::iterator curiter2 = iter2++; + LLUUID oldid = *curiter2; + // Erase entry from LRU regardless + mLRU.erase(curiter2); + // Look up entry and use it if it is valid + id_map_t::iterator iter3 = mHeaderIDMap.find(oldid); + if (iter3 != mHeaderIDMap.end() && iter3->second >= 0) + { + idx = iter3->second; + mHeaderIDMap.erase(oldid); + mTexturesSizeMap.erase(oldid); + break; + } + } + // if (idx < 0) at this point, we will rebuild the LRU + // and retry if called from setHeaderCacheEntry(), + // otherwise this shouldn't happen and will trigger an error + } + if (idx >= 0) + { + // Set the header index + mHeaderIDMap[id] = idx; + llassert_always(mTexturesSizeMap.erase(id) == 0); + // Initialize the entry (will get written later) + entry.init(id, time(NULL)); + // Update Header + writeEntriesHeader(); + // Write Entry + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + LLAPRFile* aprfile = openHeaderEntriesFile(false, offset); + S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry)); + llassert_always(bytes_written == sizeof(Entry)); + mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx); + closeHeaderEntriesFile(); + } } - }; -}; + } + else + { + // Remove this entry from the LRU if it exists + mLRU.erase(id); + // Read the entry + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + LLAPRFile* aprfile = openHeaderEntriesFile(true, offset); + S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry)); + llassert_always(bytes_read == sizeof(Entry)); + llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); + closeHeaderEntriesFile(); + } + return idx; +} + +void LLTextureCache::writeEntryAndClose(S32 idx, Entry& entry) +{ + if (idx >= 0) + { + if (!mReadOnly) + { + entry.mTime = time(NULL); + llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize); + if (entry.mBodySize > 0) + { + mTexturesSizeMap[entry.mID] = entry.mBodySize; + } +// llinfos << "Updating TE: " << idx << ": " << id << " Size: " << entry.mBodySize << " Time: " << entry.mTime << llendl; + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + LLAPRFile* aprfile = openHeaderEntriesFile(false, offset); + S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry)); + llassert_always(bytes_written == sizeof(Entry)); + mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx); + closeHeaderEntriesFile(); + } + } +} + +U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries) +{ + U32 num_entries = mHeaderEntriesInfo.mEntries; + + mHeaderIDMap.clear(); + mTexturesSizeMap.clear(); + mFreeList.clear(); + mTexturesSizeTotal = 0; + + LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo)); + for (U32 idx=0; idx<num_entries; idx++) + { + Entry entry; + S32 bytes_read = aprfile->read((void*)(&entry), (S32)sizeof(Entry)); + if (bytes_read < sizeof(Entry)) + { + llwarns << "Corrupted header entries, failed at " << idx << " / " << num_entries << llendl; + closeHeaderEntriesFile(); + purgeAllTextures(false); + return 0; + } + entries.push_back(entry); +// llinfos << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << llendl; + if (entry.mImageSize < 0) + { + mFreeList.insert(idx); + } + else + { + mHeaderIDMap[entry.mID] = idx; + if (entry.mBodySize > 0) + { + mTexturesSizeMap[entry.mID] = entry.mBodySize; + mTexturesSizeTotal += entry.mBodySize; + } + llassert_always(entry.mImageSize == 0 || entry.mImageSize > entry.mBodySize); + } + } + closeHeaderEntriesFile(); + return num_entries; +} + +void LLTextureCache::writeEntriesAndClose(const std::vector<Entry>& entries) +{ + S32 num_entries = entries.size(); + llassert_always(num_entries == mHeaderEntriesInfo.mEntries); + + if (!mReadOnly) + { + LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo)); + for (S32 idx=0; idx<num_entries; idx++) + { + S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry)); + llassert_always(bytes_written == sizeof(Entry)); + } + mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, num_entries-1); + closeHeaderEntriesFile(); + } +} + +//---------------------------------------------------------------------------- // Called from either the main thread or the worker thread void LLTextureCache::readHeaderCache() { LLMutexLock lock(&mHeaderMutex); - mHeaderEntriesInfo.mVersion = 0.f; - mHeaderEntriesInfo.mEntries = 0; - if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool())) - { - LLAPRFile::readEx(mHeaderEntriesFileName, - (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), - getLocalAPRFilePool()); - } + + mLRU.clear(); // always clear the LRU + + readEntriesHeader(); + if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion) { if (!mReadOnly) { - // Info with 0 entries - mHeaderEntriesInfo.mVersion = sHeaderCacheVersion; - - LLAPRFile::writeEx(mHeaderEntriesFileName, - (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), - getLocalAPRFilePool()); + purgeAllTextures(false); } } else { - S32 num_entries = mHeaderEntriesInfo.mEntries; + std::vector<Entry> entries; + U32 num_entries = openAndReadEntries(entries); if (num_entries) { - Entry* entries = new Entry[num_entries]; + U32 empty_entries = 0; + typedef std::pair<U32, LLUUID> lru_data_t; + std::set<lru_data_t> lru; + std::vector<LLUUID> purge_list; + for (U32 i=0; i<num_entries; i++) + { + Entry& entry = entries[i]; + const LLUUID& id = entry.mID; + if (entry.mImageSize < 0) + { + // This will be in the Free List, don't put it in the LRY + ++empty_entries; + } + else + { + lru.insert(std::make_pair(entry.mTime, id)); + if (entry.mBodySize > 0) + { + if (entry.mBodySize > entry.mImageSize) + { + // Shouldn't happen, failsafe only + llwarns << "Bad entry: " << i << ": " << id << ": BodySize: " << entry.mBodySize << llendl; + purge_list.push_back(id); + } + } + } + } + if (num_entries > sCacheMaxEntries) + { + // Special case: cache size was reduced, need to remove entries + // Note: After we prune entries, we will call this again and create the LRU + U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries; + if (entries_to_purge > 0) + { + for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter) + { + purge_list.push_back(iter->second); + if (--entries_to_purge <= 0) + break; + } + } + } + else { - LLAPRFile::readEx(mHeaderEntriesFileName, - (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry), - getLocalAPRFilePool()); + S32 lru_entries = (S32)((F32)sCacheMaxEntries * TEXTURE_CACHE_LRU_SIZE); + for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter) + { + mLRU.insert(iter->second); +// llinfos << "LRU: " << iter->first << " : " << iter->second << llendl; + if (--lru_entries <= 0) + break; + } } - typedef std::set<lru_data*, lru_data::Compare> lru_set_t; - lru_set_t lru; - for (S32 i=0; i<num_entries; i++) + + if (purge_list.size() > 0) { - if (entries[i].mSize >= 0) // -1 indicates erased entry, skip + for (std::vector<LLUUID>::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) { - const LLUUID& id = entries[i].mID; - lru.insert(new lru_data(entries[i].mTime, i, id)); - mHeaderIDMap[id] = i; + removeFromCache(*iter); } + // If we removed any entries, we need to rebuild the entries list, + // write the header, and call this again + std::vector<Entry> new_entries; + for (U32 i=0; i<num_entries; i++) + { + const Entry& entry = entries[i]; + if (entry.mImageSize >=0) + { + new_entries.push_back(entry); + } + } + llassert_always(new_entries.size() <= sCacheMaxEntries); + mHeaderEntriesInfo.mEntries = new_entries.size(); + writeEntriesAndClose(new_entries); + readHeaderCache(); // repeat with new entries file } - mLRU.clear(); - S32 lru_entries = sCacheMaxEntries / 10; - for (lru_set_t::iterator iter = lru.begin(); iter != lru.end(); ++iter) + else { - lru_data* data = *iter; - mLRU[data->index] = data->uuid; - if (--lru_entries <= 0) - break; + writeEntriesAndClose(entries); } - for_each(lru.begin(), lru.end(), DeletePointer()); - delete[] entries; } } } @@ -1162,13 +1313,21 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) LLFile::rmdir(dirname); } } - LLAPRFile::remove(mTexturesDirEntriesFileName, getLocalAPRFilePool()); if (purge_directories) { LLFile::rmdir(mTexturesDirName); } } + mHeaderIDMap.clear(); mTexturesSizeMap.clear(); + mTexturesSizeTotal = 0; + mFreeList.clear(); + mTexturesSizeTotal = 0; + + // Info with 0 entries + mHeaderEntriesInfo.mVersion = sHeaderCacheVersion; + mHeaderEntriesInfo.mEntries = 0; + writeEntriesHeader(); } void LLTextureCache::purgeTextures(bool validate) @@ -1182,51 +1341,37 @@ void LLTextureCache::purgeTextures(bool validate) LLAppViewer::instance()->pauseMainloopTimeout(); LLMutexLock lock(&mHeaderMutex); - - S32 filesize = LLAPRFile::size(mTexturesDirEntriesFileName, getLocalAPRFilePool()); - S32 num_entries = filesize / sizeof(Entry); - if (num_entries * (S32)sizeof(Entry) != filesize) - { - LL_WARNS("TextureCache") << "Bad cache file: " << mTexturesDirEntriesFileName << " Purging." << LL_ENDL; - purgeAllTextures(false); - return; - } - if (num_entries == 0) + + llinfos << "TEXTURE CACHE: Purging." << llendl; + + // Read the entries list + std::vector<Entry> entries; + U32 num_entries = openAndReadEntries(entries); + if (!num_entries) { - return; // nothing to do + writeEntriesAndClose(entries); + return; // nothing to purge } - Entry* entries = new Entry[num_entries]; - S32 bytes_read = LLAPRFile::readEx(mTexturesDirEntriesFileName, - (U8*)entries, 0, num_entries*sizeof(Entry), - getLocalAPRFilePool()); - if (bytes_read != filesize) - { - LL_WARNS("TextureCache") << "Bad cache file (2): " << mTexturesDirEntriesFileName << " Purging." << LL_ENDL; - purgeAllTextures(false); - return; - } - - LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Reading Entries..." << LL_ENDL; - - std::map<LLUUID, S32> entry_idx_map; - S64 total_size = 0; - for (S32 idx=0; idx<num_entries; idx++) - { - const LLUUID& id = entries[idx].mID; - LL_DEBUGS("TextureCache") << "Entry: " << id << " Size: " << entries[idx].mSize << " Time: " << entries[idx].mTime << LL_ENDL; - std::map<LLUUID, S32>::iterator iter = entry_idx_map.find(id); - if (iter != entry_idx_map.end()) + // Use mTexturesSizeMap to collect UUIDs of textures with bodies + typedef std::set<std::pair<U32,S32> > time_idx_set_t; + std::set<std::pair<U32,S32> > time_idx_set; + for (size_map_t::iterator iter1 = mTexturesSizeMap.begin(); + iter1 != mTexturesSizeMap.end(); ++iter1) + { + if (iter1->second > 0) { - // Newer entry replacing older entry - S32 pidx = iter->second; - total_size -= entries[pidx].mSize; - entries[pidx].mSize = 0; // flag: skip older entry + id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first); + if (iter2 != mHeaderIDMap.end()) + { + S32 idx = iter2->second; + time_idx_set.insert(std::make_pair(entries[idx].mTime, idx)); +// llinfos << "TIME: " << entries[idx].mTime << " TEX: " << entries[idx].mID << " IDX: " << idx << " Size: " << entries[idx].mImageSize << llendl; + } } - entry_idx_map[id] = idx; - total_size += entries[idx].mSize; } - + + // Validate 1/256th of the files on startup U32 validate_idx = 0; if (validate) { @@ -1235,19 +1380,17 @@ void LLTextureCache::purgeTextures(bool validate) gSavedSettings.setU32("CacheValidateCounter", next_idx); LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Validating: " << validate_idx << LL_ENDL; } - - S64 min_cache_size = (sCacheMaxTexturesSize * 9) / 10; + + S64 cache_size = mTexturesSizeTotal; + S64 purged_cache_size = (sCacheMaxTexturesSize * (S64)((1.f-TEXTURE_CACHE_PURGE_AMOUNT)*100)) / 100; S32 purge_count = 0; - S32 next_idx = 0; - for (S32 idx=0; idx<num_entries; idx++) + for (time_idx_set_t::iterator iter = time_idx_set.begin(); + iter != time_idx_set.end(); ++iter) { - if (entries[idx].mSize == 0) - { - continue; - } + S32 idx = iter->second; bool purge_entry = false; std::string filename = getTextureFileName(entries[idx].mID); - if (total_size >= min_cache_size) + if (cache_size >= purged_cache_size) { purge_entry = true; } @@ -1257,60 +1400,44 @@ void LLTextureCache::purgeTextures(bool validate) U32 uuididx = entries[idx].mID.mData[0]; if (uuididx == validate_idx) { - LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mSize << LL_ENDL; + LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mBodySize << LL_ENDL; S32 bodysize = LLAPRFile::size(filename, getLocalAPRFilePool()); - if (bodysize != entries[idx].mSize) + if (bodysize != entries[idx].mBodySize) { - LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mSize + LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize << filename << LL_ENDL; purge_entry = true; } } } + else + { + break; + } + if (purge_entry) { purge_count++; LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; LLAPRFile::remove(filename, getLocalAPRFilePool()); - total_size -= entries[idx].mSize; - entries[idx].mSize = 0; - } - else - { - if (next_idx != idx) - { - entries[next_idx] = entries[idx]; - } - ++next_idx; + cache_size -= entries[idx].mBodySize; + mTexturesSizeTotal -= entries[idx].mBodySize; + entries[idx].mBodySize = 0; + mTexturesSizeMap.erase(entries[idx].mID); } } - num_entries = next_idx; LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Writing Entries: " << num_entries << LL_ENDL; - - LLAPRFile::remove(mTexturesDirEntriesFileName, getLocalAPRFilePool()); - LLAPRFile::writeEx(mTexturesDirEntriesFileName, - (U8*)&entries[0], 0, num_entries*sizeof(Entry), - getLocalAPRFilePool()); - - mTexturesSizeTotal = 0; - mTexturesSizeMap.clear(); - for (S32 idx=0; idx<num_entries; idx++) - { - mTexturesSizeMap[entries[idx].mID] = entries[idx].mSize; - mTexturesSizeTotal += entries[idx].mSize; - } - llassert(mTexturesSizeTotal == total_size); - - delete[] entries; + writeEntriesAndClose(entries); + // *FIX:Mani - watchdog back on. LLAppViewer::instance()->resumeMainloopTimeout(); LL_INFOS("TextureCache") << "TEXTURE CACHE:" << " PURGED: " << purge_count << " ENTRIES: " << num_entries - << " CACHE SIZE: " << total_size / 1024*1024 << " MB" + << " CACHE SIZE: " << mTexturesSizeTotal / 1024*1024 << " MB" << llendl; } @@ -1340,78 +1467,39 @@ LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle) } ////////////////////////////////////////////////////////////////////////////// - // Called from work thread -S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize) -{ - bool retry = false; - S32 idx = -1; +// Reads imagesize from the header, updates timestamp +S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, S32& imagesize) +{ + LLMutexLock lock(&mHeaderMutex); + Entry entry; + S32 idx = openAndReadEntry(id, entry, false); + if (idx >= 0) { - LLMutexLock lock(&mHeaderMutex); - id_map_t::iterator iter = mHeaderIDMap.find(id); - if (iter != mHeaderIDMap.end()) - { - idx = iter->second; - } - else if (touch && !mReadOnly) - { - if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries) - { - // Add an entry - idx = mHeaderEntriesInfo.mEntries++; - mHeaderIDMap[id] = idx; - // Update Info - LLAPRFile::writeEx(mHeaderEntriesFileName, - (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), - getLocalAPRFilePool()); - } - else if (!mLRU.empty()) - { - idx = mLRU.begin()->first; // will be erased below - const LLUUID& oldid = mLRU.begin()->second; - mHeaderIDMap.erase(oldid); - mTexturesSizeMap.erase(oldid); - mHeaderIDMap[id] = idx; - } - else - { - idx = -1; - retry = true; - } - } - if (idx >= 0) - { - if (touch && !mReadOnly) - { - // Update the lru entry - mLRU.erase(idx); - llassert_always(imagesize && *imagesize > 0); - Entry* entry = new Entry(id, *imagesize, time(NULL)); - S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - LLAPRFile::writeEx(mHeaderEntriesFileName, - (U8*)entry, offset, sizeof(Entry), - getLocalAPRFilePool()); - delete entry; - } - else if (imagesize) - { - // Get the image size - Entry entry; - S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + imagesize = entry.mImageSize; + writeEntryAndClose(idx, entry); // updates time + } + return idx; +} - LLAPRFile::readEx(mHeaderEntriesFileName, - (U8*)&entry, offset, sizeof(Entry), - getLocalAPRFilePool()); - *imagesize = entry.mSize; - } - } +// Writes imagesize to the header, updates timestamp +S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, S32 imagesize) +{ + LLMutexLock lock(&mHeaderMutex); + llassert_always(imagesize >= 0); + Entry entry; + S32 idx = openAndReadEntry(id, entry, true); + if (idx >= 0) + { + entry.mImageSize = imagesize; + writeEntryAndClose(idx, entry); } - if (retry) + else // retry { - readHeaderCache(); // updates the lru + readHeaderCache(); // We couldn't write an entry, so refresh the LRU llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries); - idx = getHeaderCacheEntry(id, touch, imagesize); // assert above ensures no inf. recursion + idx = setHeaderCacheEntry(id, imagesize); // assert above ensures no inf. recursion } return idx; } @@ -1427,8 +1515,8 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filena // so let the thread handle it LLMutexLock lock(&mWorkersMutex); LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, priority, filename, id, - NULL, size, offset, 0, - responder); + NULL, size, offset, 0, + responder); handle_t handle = worker->read(); mReaders[handle] = worker; return handle; @@ -1441,8 +1529,8 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri // so let the thread handle it LLMutexLock lock(&mWorkersMutex); LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, - NULL, size, offset, 0, - responder); + NULL, size, offset, + 0, responder); handle_t handle = worker->read(); mReaders[handle] = worker; return handle; @@ -1453,7 +1541,7 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort) { lockWorkers(); handle_map_t::iterator iter = mReaders.find(handle); - llassert_always(iter != mReaders.end()); + llassert_always(iter != mReaders.end() || abort); LLTextureCacheWorker* worker = iter->second; bool res = worker->complete(); if (res || abort) @@ -1487,19 +1575,13 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio purgeTextures(false); mDoPurge = FALSE; } - if (datasize >= TEXTURE_CACHE_ENTRY_SIZE) - { - LLMutexLock lock(&mWorkersMutex); - llassert_always(imagesize > 0); - LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, - data, datasize, 0, - imagesize, responder); - handle_t handle = worker->write(); - mWriters[handle] = worker; - return handle; - } - delete responder; - return LLWorkerThread::nullHandle(); + LLMutexLock lock(&mWorkersMutex); + LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, + data, datasize, 0, + imagesize, responder); + handle_t handle = worker->write(); + mWriters[handle] = worker; + return handle; } bool LLTextureCache::writeComplete(handle_t handle, bool abort) @@ -1542,25 +1624,17 @@ void LLTextureCache::addCompleted(Responder* responder, bool success) bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id) { - if (mReadOnly) - { - return false; - } - LLMutexLock lock(&mHeaderMutex); - id_map_t::iterator iter = mHeaderIDMap.find(id); - if (iter != mHeaderIDMap.end()) + if (!mReadOnly) { - S32 idx = iter->second; + LLMutexLock lock(&mHeaderMutex); + Entry entry; + S32 idx = openAndReadEntry(id, entry, false); if (idx >= 0) { - Entry* entry = new Entry(id, -1, time(NULL)); - S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - - LLAPRFile::writeEx(mHeaderEntriesFileName, - (U8*)entry, offset, sizeof(Entry), - getLocalAPRFilePool()); - delete entry; - mLRU[idx] = id; + entry.mImageSize = -1; + entry.mBodySize = 0; + writeEntryAndClose(idx, entry); + mFreeList.insert(idx); mHeaderIDMap.erase(id); mTexturesSizeMap.erase(id); return true; diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index 68b1458e9a..bc9c988648 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -48,6 +48,27 @@ class LLTextureCache : public LLWorkerThread friend class LLTextureCacheRemoteWorker; friend class LLTextureCacheLocalFileWorker; +private: + // Entries + struct EntriesInfo + { + EntriesInfo() : mVersion(0.f), mEntries(0) {} + F32 mVersion; + U32 mEntries; + }; + struct Entry + { + Entry() {} + Entry(const LLUUID& id, S32 imagesize, S32 bodysize, U32 time) : + mID(id), mImageSize(imagesize), mBodySize(bodysize), mTime(time) {} + void init(const LLUUID& id, U32 time) { mID = id, mImageSize = 0; mBodySize = 0; mTime = time; } + LLUUID mID; // 16 bytes + S32 mImageSize; // total size of image if known + S32 mBodySize; // size of body file in body cache + U32 mTime; // seconds since 1/1/1970 + }; + + public: class Responder : public LLResponder @@ -106,10 +127,16 @@ public: // debug S32 getNumReads() { return mReaders.size(); } S32 getNumWrites() { return mWriters.size(); } + S64 getUsage() { return mTexturesSizeTotal; } + S64 getMaxUsage() { return sCacheMaxTexturesSize; } + U32 getEntries() { return mHeaderEntriesInfo.mEntries; } + U32 getMaxEntries() { return sCacheMaxEntries; }; + BOOL isInCache(const LLUUID& id) ; + BOOL isInLocal(const LLUUID& id) ; protected: // Accessed by LLTextureCacheWorker - bool appendToTextureEntryList(const LLUUID& id, S32 size); + bool updateTextureEntryList(const LLUUID& id, S32 size); std::string getLocalFileName(const LLUUID& id); std::string getTextureFileName(const LLUUID& id); void addCompleted(Responder* responder, bool success); @@ -122,7 +149,16 @@ private: void readHeaderCache(); void purgeAllTextures(bool purge_directories); void purgeTextures(bool validate); - S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL); + LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset); + void closeHeaderEntriesFile(); + void readEntriesHeader(); + void writeEntriesHeader(); + S32 openAndReadEntry(const LLUUID& id, Entry& entry, bool create); + void writeEntryAndClose(S32 idx, Entry& entry); + U32 openAndReadEntries(std::vector<Entry>& entries); + void writeEntriesAndClose(const std::vector<Entry>& entries); + S32 getHeaderCacheEntry(const LLUUID& id, S32& imagesize); + S32 setHeaderCacheEntry(const LLUUID& id, S32 imagesize); bool removeHeaderCacheEntry(const LLUUID& id); void lockHeaders() { mHeaderMutex.lock(); } void unlockHeaders() { mHeaderMutex.unlock(); } @@ -132,6 +168,7 @@ private: LLMutex mWorkersMutex; LLMutex mHeaderMutex; LLMutex mListMutex; + LLAPRFile* mHeaderAPRFile; typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t; handle_map_t mReaders; @@ -145,42 +182,28 @@ private: BOOL mReadOnly; - // Entries - struct EntriesInfo - { - F32 mVersion; - U32 mEntries; - }; - struct Entry - { - Entry() {} - Entry(const LLUUID& id, S32 size, U32 time) : mID(id), mSize(size), mTime(time) {} - LLUUID mID; // 128 bits - S32 mSize; // total size of image if known (NOT size cached) - U32 mTime; // seconds since 1/1/1970 - }; - // HEADERS (Include first mip) std::string mHeaderEntriesFileName; std::string mHeaderDataFileName; EntriesInfo mHeaderEntriesInfo; - typedef std::map<S32,LLUUID> index_map_t; - index_map_t mLRU; // index, id; stored as a map for fast removal + std::set<S32> mFreeList; // deleted entries + std::set<LLUUID> mLRU; typedef std::map<LLUUID,S32> id_map_t; id_map_t mHeaderIDMap; // BODIES (TEXTURES minus headers) std::string mTexturesDirName; - std::string mTexturesDirEntriesFileName; typedef std::map<LLUUID,S32> size_map_t; size_map_t mTexturesSizeMap; S64 mTexturesSizeTotal; LLAtomic32<BOOL> mDoPurge; - + // Statics static F32 sHeaderCacheVersion; static U32 sCacheMaxEntries; static S64 sCacheMaxTexturesSize; }; +extern const S32 TEXTURE_CACHE_ENTRY_SIZE; + #endif // LL_LLTEXTURECACHE_H diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 4940d9b5bb..de00ca8420 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -47,7 +47,9 @@ #include "llfolderview.h" #include "llfoldervieweventlistener.h" #include "llinventory.h" +#include "llinventoryfunctions.h" #include "llinventorymodel.h" +#include "llinventorypanel.h" #include "llfloaterinventory.h" #include "lllineeditor.h" #include "llui.h" @@ -424,7 +426,7 @@ BOOL LLFloaterTexturePicker::postBuild() mInventoryPanel->getRootFolder()->getFilter()->markDefault(); // Commented out to stop opening all folders with textures - // mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_TEXTURE); + // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE); // don't put keyboard focus on selected item, because the selection callback // will assume that this was user input @@ -527,7 +529,7 @@ void LLFloaterTexturePicker::draw() mTexturep = NULL; if(mImageAssetID.notNull()) { - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES); mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); } else if (!mFallbackImageName.empty()) @@ -1071,7 +1073,7 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask) { showPicker(FALSE); //grab textures first... - gInventory.startBackgroundFetch(gInventory.findCategoryUUIDForType(LLAssetType::AT_TEXTURE)); + gInventory.startBackgroundFetch(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE)); //...then start full inventory fetch. gInventory.startBackgroundFetch(); handled = TRUE; @@ -1188,7 +1190,7 @@ void LLTextureCtrl::draw() } else if (!mImageAssetID.isNull()) { - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES); mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); } else if (!mFallbackImageName.empty()) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 88fc7f98c0..c918f98895 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -32,108 +32,35 @@ #include "llviewerprecompiledheaders.h" +#include <iostream> + #include "llstl.h" #include "lltexturefetch.h" #include "llcurl.h" +#include "lldir.h" #include "llhttpclient.h" +#include "llhttpstatuscodes.h" #include "llimage.h" #include "llimageworker.h" #include "llworkerthread.h" #include "llagent.h" #include "lltexturecache.h" +#include "llviewercontrol.h" #include "llviewertexturelist.h" #include "llviewertexture.h" #include "llviewerregion.h" +#include "llworld.h" ////////////////////////////////////////////////////////////////////////////// -//static class LLTextureFetchWorker : public LLWorkerClass { -friend class LLTextureFetch; - -private: -#if 0 - class URLResponder : public LLHTTPClient::Responder - { - public: - URLResponder(LLTextureFetch* fetcher, const LLUUID& id) - : mFetcher(fetcher), mID(id) - { - } - ~URLResponder() - { - } - virtual void error(U32 status, const std::string& reason) - { - mFetcher->lockQueue(); - LLTextureFetchWorker* worker = mFetcher->getWorker(mID); - if (worker) - { -// llwarns << "LLTextureFetchWorker::URLResponder::error " << status << ": " << reason << llendl; - worker->callbackURLReceived(LLSD(), false); - } - mFetcher->unlockQueue(); - } - virtual void result(const LLSD& content) - { - mFetcher->lockQueue(); - LLTextureFetchWorker* worker = mFetcher->getWorker(mID); - if (worker) - { - worker->callbackURLReceived(content, true); - } - mFetcher->unlockQueue(); - } - private: - LLTextureFetch* mFetcher; - LLUUID mID; - }; - - class HTTPGetResponder : public LLHTTPClient::Responder - { - public: - HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id) - : mFetcher(fetcher), mID(id) - { - } - ~HTTPGetResponder() - { - } - virtual void completed(U32 status, const std::stringstream& content) - { - mFetcher->lockQueue(); - LLTextureFetchWorker* worker = mFetcher->getWorker(mID); - if (worker) - { - const std::string& cstr = content.str(); - if (200 <= status && status < 300) - { - if (203 == status) // partial information (i.e. last block) - { - worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), true); - } - else - { - worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), false); - } - } - else - { -// llinfos << "LLTextureFetchWorker::HTTPGetResponder::error " << status << ": " << cstr << llendl; - worker->callbackHttpGet(NULL, -1, true); - } - } - mFetcher->unlockQueue(); - } - private: - LLTextureFetch* mFetcher; - LLUUID mID; - }; -#endif + friend class LLTextureFetch; + friend class HTTPGetResponder; +private: class CacheReadResponder : public LLTextureCache::ReadResponder { public: @@ -179,20 +106,20 @@ private: LLUUID mID; }; - class DecodeResponder : public LLResponder + class DecodeResponder : public LLImageDecodeThread::Responder { public: DecodeResponder(LLTextureFetch* fetcher, const LLUUID& id, LLTextureFetchWorker* worker) : mFetcher(fetcher), mID(id), mWorker(worker) { } - virtual void completed(bool success) + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) { mFetcher->lockQueue(); LLTextureFetchWorker* worker = mFetcher->getWorker(mID); if (worker) { - worker->callbackDecoded(success); + worker->callbackDecoded(success, raw, aux); } mFetcher->unlockQueue(); } @@ -227,37 +154,45 @@ public: ~LLTextureFetchWorker(); void relese() { --mActiveCount; } + void callbackHttpGet(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer, + bool last_block, bool success); + void callbackCacheRead(bool success, LLImageFormatted* image, + S32 imagesize, BOOL islocal); + void callbackCacheWrite(bool success); + void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux); + + void setGetStatus(U32 status, const std::string& reason) + { + mGetStatus = status; + mGetReason = reason; + } + protected: LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host, F32 priority, S32 discard, S32 size); + LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host, + F32 priority, S32 discard, S32 size); private: /*virtual*/ void startWork(S32 param); // called from addWork() (MAIN THREAD) /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) - virtual std::string getName() { return LLStringUtil::null; } void resetFormattedData(); void setImagePriority(F32 priority); void setDesiredDiscard(S32 discard, S32 size); bool insertPacket(S32 index, U8* data, S32 size); void clearPackets(); + void setupPacketData(); U32 calcWorkPriority(); void removeFromCache(); bool processSimulatorPackets(); - bool decodeImage(); bool writeToCacheComplete(); - void lockWorkData() { mWorkMutex.lock(); } - void unlockWorkData() { mWorkMutex.unlock(); } + void lockWorkMutex() { mWorkMutex.lock(); } + void unlockWorkMutex() { mWorkMutex.unlock(); } - void callbackURLReceived(const LLSD& data, bool success); - void callbackHttpGet(U8* data, S32 data_size, bool last_block); - void callbackCacheRead(bool success, LLImageFormatted* image, - S32 imagesize, BOOL islocal); - void callbackCacheWrite(bool success); - void callbackDecoded(bool success); - private: enum e_state // mState { @@ -268,8 +203,8 @@ private: CACHE_POST, LOAD_FROM_NETWORK, LOAD_FROM_SIMULATOR, - LOAD_FROM_HTTP_GET_URL, - LOAD_FROM_HTTP_GET_DATA, + SEND_HTTP_REQ, + WAIT_HTTP_REQ, DECODE_IMAGE, DECODE_IMAGE_UPDATE, WRITE_TO_CACHE, @@ -280,19 +215,17 @@ private: { UNSENT = 0, QUEUED = 1, - SENT_SIM = 2, - SENT_URL = 3, - SENT_HTTP = 4 + SENT_SIM = 2 }; static const char* sStateDescs[]; e_state mState; LLTextureFetch* mFetcher; - LLImageWorker* mImageWorker; LLPointer<LLImageFormatted> mFormattedImage; LLPointer<LLImageRaw> mRawImage; LLPointer<LLImageRaw> mAuxImage; LLUUID mID; LLHost mHost; + std::string mUrl; U8 mType; F32 mImagePriority; U32 mWorkPriority; @@ -314,15 +247,18 @@ private: S32 mCachedSize; BOOL mLoaded; e_request_state mSentRequest; + handle_t mDecodeHandle; BOOL mDecoded; BOOL mWritten; BOOL mNeedsAux; BOOL mHaveAllData; BOOL mInLocalCache; + S32 mHTTPFailCount; S32 mRetryAttempt; - std::string mURL; S32 mActiveCount; - + U32 mGetStatus; + std::string mGetReason; + // Work Data LLMutex mWorkMutex; struct PacketData @@ -340,25 +276,79 @@ private: U8 mImageCodec; }; -class LLTextureFetchLocalFileWorker : public LLTextureFetchWorker -{ -friend class LLTextureFetch; - -protected: - LLTextureFetchLocalFileWorker(LLTextureFetch* fetcher, const std::string& filename, const LLUUID& id, const LLHost& host, - F32 priority, S32 discard, S32 size) - : LLTextureFetchWorker(fetcher, id, host, priority, discard, size), - mFileName(filename) - {} +////////////////////////////////////////////////////////////////////////////// -private: - /*virtual*/ std::string getName() { return mFileName; } +class HTTPGetResponder : public LLCurl::Responder +{ + LOG_CLASS(HTTPGetResponder); +public: + HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset) + : mFetcher(fetcher), mID(id), mStartTime(startTime), mRequestedSize(requestedSize), mOffset(offset) + { + } + ~HTTPGetResponder() + { + } + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"))) + { + mFetcher->mTextureInfo.setRequestStartTime(mID, mStartTime); + U64 timeNow = LLTimer::getTotalTime(); + mFetcher->mTextureInfo.setRequestType(mID, LLTextureInfoDetails::REQUEST_TYPE_HTTP); + mFetcher->mTextureInfo.setRequestSize(mID, mRequestedSize); + mFetcher->mTextureInfo.setRequestOffset(mID, mOffset); + mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); + } + lldebugs << "HTTP COMPLETE: " << mID << llendl; + mFetcher->lockQueue(); + LLTextureFetchWorker* worker = mFetcher->getWorker(mID); + if (worker) + { + bool success = false; + bool partial = false; + if (200 <= status && status < 300) + { + success = true; + if (203 == status) // partial information (i.e. last block) + { + partial = true; + } + } + else + { + worker->setGetStatus(status, reason); +// llwarns << status << ": " << reason << llendl; + } + if (!success) + { + worker->setGetStatus(status, reason); +// llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl; + } + mFetcher->removeFromHTTPQueue(mID); + worker->callbackHttpGet(channels, buffer, partial, success); + } + else + { + mFetcher->removeFromHTTPQueue(mID); + llwarns << "Worker not found: " << mID << llendl; + } + mFetcher->unlockQueue(); + } + private: - std::string mFileName; + LLTextureFetch* mFetcher; + LLUUID mID; + U64 mStartTime; + S32 mRequestedSize; + U32 mOffset; }; +////////////////////////////////////////////////////////////////////////////// //static const char* LLTextureFetchWorker::sStateDescs[] = { @@ -368,8 +358,8 @@ const char* LLTextureFetchWorker::sStateDescs[] = { "CACHE_POST", "LOAD_FROM_NETWORK", "LOAD_FROM_SIMULATOR", - "LOAD_FROM_HTTP_URL", - "LOAD_FROM_HTTP_DATA", + "SEND_HTTP_REQ", + "WAIT_HTTP_REQ", "DECODE_IMAGE", "DECODE_IMAGE_UPDATE", "WRITE_TO_CACHE", @@ -380,6 +370,7 @@ const char* LLTextureFetchWorker::sStateDescs[] = { // called from MAIN THREAD LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, + const std::string& url, // Optional URL const LLUUID& id, // Image UUID const LLHost& host, // Simulator host F32 priority, // Priority @@ -388,9 +379,9 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, : LLWorkerClass(fetcher, "TextureFetch"), mState(INIT), mFetcher(fetcher), - mImageWorker(NULL), mID(id), mHost(host), + mUrl(url), mImagePriority(priority), mWorkPriority(0), mRequestedPriority(0.f), @@ -404,18 +395,21 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mBuffer(NULL), mBufferSize(0), mRequestedSize(0), - mDesiredSize(FIRST_PACKET_SIZE), + mDesiredSize(TEXTURE_CACHE_ENTRY_SIZE), mFileSize(0), mCachedSize(0), mLoaded(FALSE), mSentRequest(UNSENT), + mDecodeHandle(0), mDecoded(FALSE), mWritten(FALSE), mNeedsAux(FALSE), mHaveAllData(FALSE), mInLocalCache(FALSE), + mHTTPFailCount(0), mRetryAttempt(0), mActiveCount(0), + mGetStatus(0), mWorkMutex(NULL), mFirstPacket(0), mLastPacket(-1), @@ -440,7 +434,7 @@ LLTextureFetchWorker::~LLTextureFetchWorker() // << " Requested=" << mRequestedDiscard // << " Desired=" << mDesiredDiscard << llendl; llassert_always(!haveWork()); - lockWorkData(); + lockWorkMutex(); if (mCacheReadHandle != LLTextureCache::nullHandle()) { mFetcher->mTextureCache->readComplete(mCacheReadHandle, true); @@ -449,13 +443,9 @@ LLTextureFetchWorker::~LLTextureFetchWorker() { mFetcher->mTextureCache->writeComplete(mCacheWriteHandle, true); } - if (mImageWorker) - { - mImageWorker->scheduleDelete(); - } mFormattedImage = NULL; clearPackets(); - unlockWorkData(); + unlockWorkMutex(); } void LLTextureFetchWorker::clearPackets() @@ -467,6 +457,38 @@ void LLTextureFetchWorker::clearPackets() mFirstPacket = 0; } +void LLTextureFetchWorker::setupPacketData() +{ + S32 data_size = 0; + if (mFormattedImage.notNull()) + { + data_size = mFormattedImage->getDataSize(); + } + if (data_size > 0) + { + // Only used for simulator requests + mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1; + if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size) + { + llwarns << "Bad CACHED TEXTURE size: " << data_size << " removing." << llendl; + removeFromCache(); + resetFormattedData(); + clearPackets(); + } + else if (mFileSize > 0) + { + mLastPacket = mFirstPacket-1; + mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1; + } + else + { + // This file was cached using HTTP so we have to refetch the first packet + resetFormattedData(); + clearPackets(); + } + } +} + U32 LLTextureFetchWorker::calcWorkPriority() { // llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerTexture::maxDecodePriority()); @@ -538,7 +560,6 @@ void LLTextureFetchWorker::resetFormattedData() // Called from MAIN thread void LLTextureFetchWorker::startWork(S32 param) { - llassert(mImageWorker == NULL); llassert(mFormattedImage.isNull()); } @@ -549,6 +570,14 @@ bool LLTextureFetchWorker::doWork(S32 param) { LLMutexLock lock(&mWorkMutex); + if ((mFetcher->isQuitting() || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) + { + if (mState < WRITE_TO_CACHE) + { + return true; // abort + } + } + if (mFetcher->mDebugPause) { return false; // debug: don't do any work @@ -563,16 +592,9 @@ bool LLTextureFetchWorker::doWork(S32 param) mFetchTimer.reset(); } - if (mImagePriority <= 0.0f) - { - if (mState < WRITE_TO_CACHE) - { - return true; // cancel request - } - } - if (mState == INIT) { + mRawImage = NULL ; mRequestedDiscard = -1; mLoadedDiscard = -1; mDecodedDiscard = -1; @@ -590,8 +612,9 @@ bool LLTextureFetchWorker::doWork(S32 param) clearPackets(); // TODO: Shouldn't be necessary mCacheReadHandle = LLTextureCache::nullHandle(); mCacheWriteHandle = LLTextureCache::nullHandle(); - mURL.clear(); mState = LOAD_FROM_TEXTURE_CACHE; + LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority) + << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; // fall through } @@ -612,16 +635,27 @@ bool LLTextureFetchWorker::doWork(S32 param) setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); - if (getName().empty()) + if (mUrl.compare(0, 7, "file://") == 0) + { + // read file from local disk + std::string filename = mUrl.substr(7, std::string::npos); + mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority, + offset, size, responder); + } + else if (mUrl.empty()) { mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, offset, size, responder); } else { - // read file from local disk - mCacheReadHandle = mFetcher->mTextureCache->readFromCache(getName(), mID, cache_priority, - offset, size, responder); + if (!(mUrl.compare(0, 7, "http://") == 0)) + { + // *TODO:?remove this warning + llwarns << "Unknown URL Type: " << mUrl << llendl; + } + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + mState = SEND_HTTP_REQ; } } @@ -647,75 +681,101 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == CACHE_POST) { - mDesiredSize = llmax(mDesiredSize, FIRST_PACKET_SIZE); + mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); mCachedSize = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0; // Successfully loaded if ((mCachedSize >= mDesiredSize) || mHaveAllData) { // we have enough data, decode it llassert_always(mFormattedImage->getDataSize() > 0); + mLoadedDiscard = mDesiredDiscard; mState = DECODE_IMAGE; + LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() + << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight()) + << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; // fall through } else { - if (!getName().empty()) + if (mUrl.compare(0, 7, "file://") == 0) { // failed to load local file, we're done. return true; } // need more data - mState = LOAD_FROM_NETWORK; + else + { + LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL; + mState = LOAD_FROM_NETWORK; + } // fall through } } if (mState == LOAD_FROM_NETWORK) { - if (mSentRequest == UNSENT) + bool get_url = gSavedSettings.getBOOL("ImagePipelineUseHTTP"); + if (!mUrl.empty()) get_url = false; +// if (mHost != LLHost::invalid) get_url = false; + if ( get_url ) { - if (mFormattedImage.isNull()) - { - mFormattedImage = new LLImageJ2C; - } - // Add this to the network queue and sit here. - // LLTextureFetch::update() will send off a request which will change our state - S32 data_size = mFormattedImage->getDataSize(); - if (data_size > 0) + LLViewerRegion* region = NULL; + if (mHost == LLHost::invalid) + region = gAgent.getRegion(); + else + region = LLWorld::getInstance()->getRegion(mHost); + + if (region) { - // Only used for simulator requests - mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1; - if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size) - { -// llwarns << "Bad CACHED TEXTURE size: " << data_size << " removing." << llendl; - removeFromCache(); - resetFormattedData(); - clearPackets(); - } - else + std::string http_url = region->getCapability("GetTexture"); + if (!http_url.empty()) { - mLastPacket = mFirstPacket-1; - mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1; + mUrl = http_url + "/?texture_id=" + mID.asString().c_str(); } } + else + { + llwarns << "Region not found for host: " << mHost << llendl; + } + } + if (!mUrl.empty()) + { + mState = LLTextureFetchWorker::SEND_HTTP_REQ; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + // don't return, fall through to next state + } + else if (mSentRequest == UNSENT) + { + // Add this to the network queue and sit here. + // LLTextureFetch::update() will send off a request which will change our state mRequestedSize = mDesiredSize; mRequestedDiscard = mDesiredDiscard; mSentRequest = QUEUED; - mFetcher->lockQueue(); mFetcher->addToNetworkQueue(this); - mFetcher->unlockQueue(); setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + return false; + } + else + { + // Shouldn't need to do anything here + //llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end()); + // Make certain this is in the network queue + //mFetcher->addToNetworkQueue(this); + //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + return false; } - return false; } if (mState == LOAD_FROM_SIMULATOR) { + if (mFormattedImage.isNull()) + { + mFormattedImage = new LLImageJ2C; + } if (processSimulatorPackets()) { - mFetcher->lockQueue(); - mFetcher->removeFromNetworkQueue(this); - mFetcher->unlockQueue(); + LL_DEBUGS("Texture") << mID << ": Loaded from Sim. Bytes: " << mFormattedImage->getDataSize() << LL_ENDL; + mFetcher->removeFromNetworkQueue(this, false); if (mFormattedImage.isNull() || !mFormattedImage->getDataSize()) { // processSimulatorPackets() failed @@ -727,108 +787,99 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { + mFetcher->addToNetworkQueue(this); // failsafe setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); } return false; } -#if 0 - if (mState == LOAD_FROM_HTTP_GET_URL) - { - if (!mSentRequest) - { - mSentRequest = TRUE; - mLoaded = FALSE; - std::string url; - LLViewerRegion* region = gAgent.getRegion(); - if (region) + if (mState == SEND_HTTP_REQ) + { + { + const S32 HTTP_QUEUE_MAX_SIZE = 32; + // *TODO: Integrate this with llviewerthrottle + // Note: LLViewerThrottle uses dynamic throttling which makes sense for UDP, + // but probably not for Textures. + // Set the throttle to the entire bandwidth, assuming UDP packets will get priority + // when they are needed + F32 max_bandwidth = mFetcher->mMaxBandwidth; + if ((mFetcher->getHTTPQueueSize() >= HTTP_QUEUE_MAX_SIZE) || + (mFetcher->getTextureBandwidth() > max_bandwidth)) { - url = region->getCapability("RequestTextureDownload"); - } - if (!url.empty()) - { - LLSD sd; - sd = mID.asString(); - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - LLHTTPClient::post(url, sd, new URLResponder(mFetcher, mID)); + // Make normal priority and return (i.e. wait until there is room in the queue) + setPriority(LLWorkerThread::PRIORITY_NORMAL | mWorkPriority); return false; } - else - { -// llwarns << mID << ": HTTP get url failed, requesting from simulator" << llendl; - mSentRequest = FALSE; - mState = LOAD_FROM_SIMULATOR; - return false; - } - } - else - { - if (mLoaded) + + mFetcher->removeFromNetworkQueue(this, false); + + S32 cur_size = 0; + if (mFormattedImage.notNull()) { - if (!mURL.empty()) - { - mState = LOAD_FROM_HTTP_GET_DATA; - mSentRequest = FALSE; // reset - mLoaded = FALSE; // reset - } - else - { -// llwarns << mID << ": HTTP get url is empty, requesting from simulator" << llendl; - mSentRequest = FALSE; - mState = LOAD_FROM_SIMULATOR; - return false; - } + cur_size = mFormattedImage->getDataSize(); // amount of data we already have } - } - // fall through - } - - if (mState == LOAD_FROM_HTTP_GET_DATA) - { - if (!mSentRequest) - { - mSentRequest = TRUE; - S32 cur_size = mFormattedImage->getDataSize(); // amount of data we already have mRequestedSize = mDesiredSize; mRequestedDiscard = mDesiredDiscard; -#if 1 // *TODO: LLCurl::getByteRange is broken (ignores range) - cur_size = 0; - mFormattedImage->deleteData(); -#endif mRequestedSize -= cur_size; - // F32 priority = mImagePriority / (F32)LLViewerTexture::maxDecodePriority(); // 0-1 S32 offset = cur_size; mBufferSize = cur_size; // This will get modified by callbackHttpGet() - std::string url; - if (mURL.empty()) + + bool res = false; + if (!mUrl.empty()) { - //url = "http://asset.agni/0000002f-38ae-0e17-8e72-712e58964e9c.texture"; - std::stringstream urlstr; - urlstr << "http://asset.agni/" << mID.asString() << ".texture"; - url = urlstr.str(); + mLoaded = FALSE; + mGetStatus = 0; + mGetReason.clear(); + lldebugs << "HTTP GET: " << mID << " Offset: " << offset + << " Bytes: " << mRequestedSize + << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth + << llendl; + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + mState = WAIT_HTTP_REQ; + + mFetcher->addToHTTPQueue(mID); + // Will call callbackHttpGet when curl request completes + std::vector<std::string> headers; + headers.push_back("Accept: image/x-j2c"); + res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize, + new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset)); } - else + if (!res) { - url = mURL; + llwarns << "HTTP GET request failed for " << mID << llendl; + resetFormattedData(); + ++mHTTPFailCount; + return true; // failed } - mLoaded = FALSE; -// llinfos << "HTTP GET: " << mID << " Offset: " << offset << " Bytes: " << mRequestedSize << llendl; - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - LLCurl::getByteRange(url, offset, mRequestedSize, - new HTTPGetResponder(mFetcher, mID)); // *TODO: use mWorkPriority - return false; // not done + // fall through } - + } + + if (mState == WAIT_HTTP_REQ) + { if (mLoaded) { - S32 cur_size = mFormattedImage->getDataSize(); + S32 cur_size = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0; if (mRequestedSize < 0) { -// llwarns << "http get failed for: " << mID << llendl; + const S32 HTTP_MAX_RETRY_COUNT = 3; + S32 max_attempts = (mGetStatus == HTTP_NOT_FOUND) ? 1 : HTTP_MAX_RETRY_COUNT + 1; + llinfos << "HTTP GET failed for: " << mUrl + << " Status: " << mGetStatus << " Reason: '" << mGetReason << "'" + << " Attempt:" << mHTTPFailCount+1 << "/" << max_attempts << llendl; if (cur_size == 0) { - resetFormattedData(); - return true; // failed + ++mHTTPFailCount; + if (mHTTPFailCount >= max_attempts) + { + resetFormattedData(); + return true; // failed + } + else + { + mState = SEND_HTTP_REQ; + return false; // retry + } } else { @@ -836,6 +887,18 @@ bool LLTextureFetchWorker::doWork(S32 param) return false; // use what we have } } + + if (mFormattedImage.isNull()) + { + // For now, create formatted image based on extension + std::string extension = gDirUtilp->getExtension(mUrl); + mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension)); + if (mFormattedImage.isNull()) + { + mFormattedImage = new LLImageJ2C; // default + } + } + llassert_always(mBufferSize == cur_size + mRequestedSize); if (mHaveAllData) { @@ -854,43 +917,51 @@ bool LLTextureFetchWorker::doWork(S32 param) mBuffer = NULL; mBufferSize = 0; mLoadedDiscard = mRequestedDiscard; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); mState = DECODE_IMAGE; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + return false; + } + else + { + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return false; } - - // NOTE: Priority gets updated when the http get completes (in callbackHTTPGet()) - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - return false; } -#endif if (mState == DECODE_IMAGE) { - llassert_always(mFormattedImage->getDataSize() > 0); + if (mFormattedImage->getDataSize() <= 0) + { + llerrs << "Decode entered with invalid mFormattedImage. ID = " << mID << llendl; + } setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it mRawImage = NULL; mAuxImage = NULL; - llassert_always(mImageWorker == NULL); llassert_always(mFormattedImage.notNull()); + llassert_always(mLoadedDiscard >= 0); S32 discard = mHaveAllData ? 0 : mLoadedDiscard; U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority; mDecoded = FALSE; mState = DECODE_IMAGE_UPDATE; - mImageWorker = new LLImageWorker(mFormattedImage, image_priority, discard, new DecodeResponder(mFetcher, mID, this)); - // fall though (need to call requestDecodedData() to start work) + LL_DEBUGS("Texture") << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard + << " All Data: " << mHaveAllData << LL_ENDL; + mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux, + new DecodeResponder(mFetcher, mID, this)); + // fall though } if (mState == DECODE_IMAGE_UPDATE) { - if (decodeImage()) + if (mDecoded) { if (mDecodedDiscard < 0) { + LL_DEBUGS("Texture") << mID << ": Failed to Decode." << LL_ENDL; if (mCachedSize > 0 && !mInLocalCache && mRetryAttempt == 0) { // Cache file should be deleted, try again // llwarns << mID << ": Decode of cached file failed (removed), retrying" << llendl; + llassert_always(mDecodeHandle == 0); mFormattedImage = NULL; ++mRetryAttempt; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); @@ -905,6 +976,9 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { + llassert_always(mRawImage.notNull()); + LL_DEBUGS("Texture") << mID << ": Decoded. Discard: " << mDecodedDiscard + << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); mState = WRITE_TO_CACHE; } @@ -918,9 +992,10 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == WRITE_TO_CACHE) { - if (mInLocalCache || !mFileSize || mSentRequest == UNSENT) + if (mInLocalCache || mSentRequest == UNSENT || mFormattedImage.isNull()) { - // If we're in a local cache or we didn't actually receive any new data, skip + // If we're in a local cache or we didn't actually receive any new data, + // or we failed to load anything, skip mState = DONE; return false; } @@ -979,10 +1054,10 @@ bool LLTextureFetchWorker::doWork(S32 param) // Called from MAIN thread void LLTextureFetchWorker::endWork(S32 param, bool aborted) { - if (mImageWorker) + if (mDecodeHandle != 0) { - mImageWorker->scheduleDelete(); - mImageWorker = NULL; + mFetcher->mImageDecodeThread->abortRequest(mDecodeHandle, false); + mDecodeHandle = 0; } mFormattedImage = NULL; } @@ -1035,7 +1110,7 @@ bool LLTextureFetchWorker::deleteOK() if ((haveWork() && // not ok to delete from these states - ((mState >= LOAD_FROM_HTTP_GET_URL && mState <= LOAD_FROM_HTTP_GET_DATA) || + ((mState >= SEND_HTTP_REQ && mState <= WAIT_HTTP_REQ) || (mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE)))) { delete_ok = false; @@ -1044,7 +1119,6 @@ bool LLTextureFetchWorker::deleteOK() return delete_ok; } - void LLTextureFetchWorker::removeFromCache() { if (!mInLocalCache) @@ -1061,6 +1135,7 @@ bool LLTextureFetchWorker::processSimulatorPackets() if (mFormattedImage.isNull() || mRequestedSize < 0) { // not sure how we got here, but not a valid state, abort! + llassert_always(mDecodeHandle == 0); mFormattedImage = NULL; return true; } @@ -1074,6 +1149,12 @@ bool LLTextureFetchWorker::processSimulatorPackets() buffer_size += mPackets[i]->mSize; } bool have_all_data = mLastPacket >= mTotalPackets-1; + if (mRequestedSize <= 0) + { + // We received a packed but haven't requested anything yet (edge case) + // Return true (we're "done") since we didn't request anything + return true; + } if (buffer_size >= mRequestedSize || have_all_data) { /// We have enough (or all) data @@ -1109,50 +1190,36 @@ bool LLTextureFetchWorker::processSimulatorPackets() ////////////////////////////////////////////////////////////////////////////// -void LLTextureFetchWorker::callbackURLReceived(const LLSD& data, bool success) +void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer, + bool last_block, bool success) { -#if 0 LLMutexLock lock(&mWorkMutex); - if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_URL) - { - llwarns << "callbackURLReceived for unrequested fetch worker, req=" - << mSentRequest << " state= " << mState << llendl; - return; - } - if (success) - { - mURL = data.asString(); - } - mLoaded = TRUE; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); -#endif -} - -////////////////////////////////////////////////////////////////////////////// -void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_block) -{ -#if 0 - LLMutexLock lock(&mWorkMutex); - if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_DATA) + if (mState != WAIT_HTTP_REQ) { - llwarns << "callbackHttpGet for unrequested fetch worker, req=" - << mSentRequest << " state= " << mState << llendl; + llwarns << "callbackHttpGet for unrequested fetch worker: " << mID + << " req=" << mSentRequest << " state= " << mState << llendl; return; } -// llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl; if (mLoaded) { llwarns << "Duplicate callback for " << mID.asString() << llendl; return; // ignore duplicate callback } - if (data_size >= 0) + if (success) { + // get length of stream: + S32 data_size = buffer->countAfter(channels.in(), NULL); + + gTextureList.sTextureBits += data_size * 8; // Approximate - does not include header bits + + //llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl; if (data_size > 0) { + // *TODO: set the formatted image data here directly to avoid the copy mBuffer = new U8[data_size]; - // *TODO: set the formatted image data here - memcpy(mBuffer, data, data_size); + buffer->readAfter(channels.in(), NULL, mBuffer, data_size); mBufferSize += data_size; if (data_size < mRequestedSize || last_block == true) { @@ -1160,10 +1227,11 @@ void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_bl } else if (data_size > mRequestedSize) { - // *TODO: This will happen until we fix LLCurl::getByteRange() -// llinfos << "HUH?" << llendl; + // *TODO: This shouldn't be happening any more + llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl; mHaveAllData = TRUE; - mFormattedImage->deleteData(); + llassert_always(mDecodeHandle == 0); + mFormattedImage = NULL; // discard any previous data we had mBufferSize = data_size; } } @@ -1181,7 +1249,6 @@ void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_bl } mLoaded = TRUE; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); -#endif } ////////////////////////////////////////////////////////////////////////////// @@ -1197,7 +1264,7 @@ void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* ima } if (success) { - llassert_always(imagesize > 0); + llassert_always(imagesize >= 0); mFileSize = imagesize; mFormattedImage = image; mImageCodec = image->getCodec(); @@ -1225,65 +1292,40 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success) ////////////////////////////////////////////////////////////////////////////// -void LLTextureFetchWorker::callbackDecoded(bool success) +void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux) { + LLMutexLock lock(&mWorkMutex); + if (mDecodeHandle == 0) + { + return; // aborted, ignore + } if (mState != DECODE_IMAGE_UPDATE) { // llwarns << "Decode callback for " << mID << " with state = " << mState << llendl; + mDecodeHandle = 0; return; } -// llinfos << mID << " : DECODE COMPLETE " << llendl; - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); -} - -////////////////////////////////////////////////////////////////////////////// - -bool LLTextureFetchWorker::decodeImage() -{ - if(!mImageWorker) - { - //LLTextureFetchWorker is aborted, skip image decoding. - return true ; - } - - bool res = true; - if (mRawImage.isNull()) - { - res = false; - if (mImageWorker->requestDecodedData(mRawImage, -1)) - { - res = true; -// llinfos << mID << " : BASE DECODE FINISHED" << llendl; - } - } - if (res && - (mRawImage.notNull() && mRawImage->getDataSize() > 0) && - (mNeedsAux && mAuxImage.isNull())) + llassert_always(mFormattedImage.notNull()); + + mDecodeHandle = 0; + if (success) { - res = false; - if (mImageWorker->requestDecodedAuxData(mAuxImage, 4, -1)) - { - res = true; -// llinfos << mID << " : AUX DECODE FINISHED" << llendl; - } + llassert_always(raw); + mRawImage = raw; + mAuxImage = aux; + mDecodedDiscard = mFormattedImage->getDiscardLevel(); + LL_DEBUGS("Texture") << mID << ": Decode Finished. Discard: " << mDecodedDiscard + << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL; } - if (res) + else { - if ((mRawImage.notNull() && mRawImage->getDataSize() > 0) && - (!mNeedsAux || (mAuxImage.notNull() && mAuxImage->getDataSize() > 0))) - { - mDecodedDiscard = mFormattedImage->getDiscardLevel(); -// llinfos << mID << " : DECODE FINISHED. DISCARD: " << mDecodedDiscard << llendl; - } - else - { -// llwarns << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << llendl; - removeFromCache(); - } - mImageWorker->scheduleDelete(); - mImageWorker = NULL; + llwarns << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << llendl; + removeFromCache(); + mDecodedDiscard = -1; // Redundant, here for clarity and paranoia } - return res; + mDecoded = TRUE; +// llinfos << mID << " : DECODE COMPLETE " << llendl; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); } ////////////////////////////////////////////////////////////////////////////// @@ -1314,15 +1356,21 @@ bool LLTextureFetchWorker::writeToCacheComplete() ////////////////////////////////////////////////////////////////////////////// // public -LLTextureFetch::LLTextureFetch(LLTextureCache* cache, bool threaded) +LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded) : LLWorkerThread("TextureFetch", threaded), mDebugCount(0), mDebugPause(FALSE), mPacketCount(0), mBadPacketCount(0), mQueueMutex(getAPRPool()), - mTextureCache(cache) + mNetworkQueueMutex(getAPRPool()), + mTextureCache(cache), + mImageDecodeThread(imagedecodethread), + mTextureBandwidth(0), + mCurlGetRequest(NULL) { + mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); + mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); } LLTextureFetch::~LLTextureFetch() @@ -1330,13 +1378,7 @@ LLTextureFetch::~LLTextureFetch() // ~LLQueuedThread() called here } -bool LLTextureFetch::createRequest(const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux) -{ - return createRequest(LLStringUtil::null, id, host, priority, w, h, c, desired_discard, needs_aux); -} - -bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id, const LLHost& host, F32 priority, +bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux) { if (mDebugPause) @@ -1361,7 +1403,14 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id } S32 desired_size; - if (desired_discard == 0) + std::string exten = gDirUtilp->getExtension(url); + if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) + { + // Only do partial requests for J2C at the moment + //llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl; + desired_size = MAX_IMAGE_DATA_SIZE; + } + else if (desired_discard == 0) { // if we want the entire image, and we know its size, then get it all // (calcDataSizeJ2C() below makes assumptions about how the image @@ -1378,7 +1427,7 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id } else { - desired_size = FIRST_PACKET_SIZE; + desired_size = TEXTURE_CACHE_ENTRY_SIZE; desired_discard = MAX_DISCARD_LEVEL; } @@ -1389,10 +1438,10 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id { return false; // need to wait for previous aborted request to complete } - worker->lockWorkData(); + worker->lockWorkMutex(); worker->setImagePriority(priority); worker->setDesiredDiscard(desired_discard, desired_size); - worker->unlockWorkData(); + worker->unlockWorkMutex(); if (!worker->haveWork()) { worker->mState = LLTextureFetchWorker::INIT; @@ -1401,16 +1450,7 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id } else { - if (filename.empty()) - { - // do remote fetch - worker = new LLTextureFetchWorker(this, id, host, priority, desired_discard, desired_size); - } - else - { - // do local file fetch - worker = new LLTextureFetchLocalFileWorker(this, filename, id, host, priority, desired_discard, desired_size); - } + worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size); mRequestMap[id] = worker; } worker->mActiveCount++; @@ -1430,10 +1470,9 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) } // protected - -// call lockQueue() first! void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) { + LLMutexLock lock(&mNetworkQueueMutex); if (mRequestMap.find(worker->mID) != mRequestMap.end()) { // only add to the queue if in the request map @@ -1447,10 +1486,27 @@ void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) } } -// call lockQueue() first! -void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker) +void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel) { - mNetworkQueue.erase(worker->mID); + LLMutexLock lock(&mNetworkQueueMutex); + size_t erased = mNetworkQueue.erase(worker->mID); + if (cancel && erased > 0) + { + mCancelQueue[worker->mHost].insert(worker->mID); + } +} + +// protected +void LLTextureFetch::addToHTTPQueue(const LLUUID& id) +{ + LLMutexLock lock(&mNetworkQueueMutex); + mHTTPTextureQueue.insert(id); +} + +void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id) +{ + LLMutexLock lock(&mNetworkQueueMutex); + mHTTPTextureQueue.erase(id); } // call lockQueue() first! @@ -1458,11 +1514,7 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel) { size_t erased_1 = mRequestMap.erase(worker->mID); llassert_always(erased_1 > 0) ; - size_t erased = mNetworkQueue.erase(worker->mID); - if (cancel && erased > 0) - { - mCancelQueue[worker->mHost].insert(worker->mID); - } + removeFromNetworkQueue(worker, cancel); llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ; worker->scheduleDelete(); @@ -1504,24 +1556,27 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, } else if (worker->checkWork()) { + worker->lockWorkMutex(); discard_level = worker->mDecodedDiscard; - raw = worker->mRawImage; worker->mRawImage = NULL; - aux = worker->mAuxImage; worker->mAuxImage = NULL; + raw = worker->mRawImage; + aux = worker->mAuxImage; res = true; + LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL; + worker->unlockWorkMutex(); } else { - worker->lockWorkData(); + worker->lockWorkMutex(); if ((worker->mDecodedDiscard >= 0) && (worker->mDecodedDiscard < discard_level || discard_level < 0) && (worker->mState >= LLTextureFetchWorker::WAIT_ON_WRITE)) { // Not finished, but data is ready discard_level = worker->mDecodedDiscard; - if (worker->mRawImage) raw = worker->mRawImage; - if (worker->mAuxImage) aux = worker->mAuxImage; + raw = worker->mRawImage; + aux = worker->mAuxImage; } - worker->unlockWorkData(); + worker->unlockWorkMutex(); } } else @@ -1538,9 +1593,9 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) LLTextureFetchWorker* worker = getWorker(id); if (worker) { - worker->lockWorkData(); + worker->lockWorkMutex(); worker->setImagePriority(priority); - worker->unlockWorkData(); + worker->unlockWorkMutex(); res = true; } return res; @@ -1548,40 +1603,106 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) ////////////////////////////////////////////////////////////////////////////// +// MAIN THREAD //virtual S32 LLTextureFetch::update(U32 max_time_ms) { S32 res; + + mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); + res = LLWorkerThread::update(max_time_ms); - const F32 REQUEST_TIME = 1.f; - - // Periodically, gather the list of textures that need data from the network - // And send the requests out to the simulators - if (mNetworkTimer.getElapsedTimeF32() >= REQUEST_TIME) + if (!mDebugPause) { - mNetworkTimer.reset(); sendRequestListToSimulators(); } return res; } +// WORKER THREAD +void LLTextureFetch::startThread() +{ + // Construct mCurlGetRequest from Worker Thread + mCurlGetRequest = new LLCurlRequest(); +} + +// WORKER THREAD +void LLTextureFetch::endThread() +{ + // Destroy mCurlGetRequest from Worker Thread + delete mCurlGetRequest; + mCurlGetRequest = NULL; +} + +// WORKER THREAD +void LLTextureFetch::threadedUpdate() +{ + llassert_always(mCurlGetRequest); + + // Limit update frequency + const F32 PROCESS_TIME = 0.05f; + static LLFrameTimer process_timer; + if (process_timer.getElapsedTimeF32() < PROCESS_TIME) + { + return; + } + process_timer.reset(); + + // Update Curl on same thread as mCurlGetRequest was constructed + S32 processed = mCurlGetRequest->process(); + if (processed > 0) + { + lldebugs << "processed: " << processed << " messages." << llendl; + } + +#if 0 + const F32 INFO_TIME = 1.0f; + static LLFrameTimer info_timer; + if (info_timer.getElapsedTimeF32() >= INFO_TIME) + { + S32 q = mCurlGetRequest->getQueued(); + if (q > 0) + { + llinfos << "Queued gets: " << q << llendl; + info_timer.reset(); + } + } +#endif + +} + ////////////////////////////////////////////////////////////////////////////// void LLTextureFetch::sendRequestListToSimulators() { + // All requests + const F32 REQUEST_DELTA_TIME = 0.10f; // 10 fps + + // Sim requests const S32 IMAGES_PER_REQUEST = 50; - const F32 LAZY_FLUSH_TIMEOUT = 15.f; // 10.0f // temp + const F32 SIM_LAZY_FLUSH_TIMEOUT = 10.0f; // temp const F32 MIN_REQUEST_TIME = 1.0f; const F32 MIN_DELTA_PRIORITY = 1000.f; - LLMutexLock lock(&mQueueMutex); + // Periodically, gather the list of textures that need data from the network + // And send the requests out to the simulators + static LLFrameTimer timer; + if (timer.getElapsedTimeF32() < REQUEST_DELTA_TIME) + { + return; + } + timer.reset(); + LLMutexLock lock(&mQueueMutex); + // Send requests typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t; typedef std::map< LLHost, request_list_t > work_request_map_t; work_request_map_t requests; + { + LLMutexLock lock2(&mNetworkQueueMutex); for (queue_t::iterator iter = mNetworkQueue.begin(); iter != mNetworkQueue.end(); ) { queue_t::iterator curiter = iter++; @@ -1591,65 +1712,65 @@ void LLTextureFetch::sendRequestListToSimulators() mNetworkQueue.erase(curiter); continue; // paranoia } + if ((req->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK) && + (req->mState != LLTextureFetchWorker::LOAD_FROM_SIMULATOR)) + { + // We already received our URL, remove from the queue + llwarns << "Worker: " << req->mID << " in mNetworkQueue but in wrong state: " << req->mState << llendl; + mNetworkQueue.erase(curiter); + continue; + } if (req->mID == mDebugID) { mDebugCount++; // for setting breakpoints } - if (req->mTotalPackets > 0 && req->mLastPacket >= req->mTotalPackets-1) + if (req->mSentRequest == LLTextureFetchWorker::SENT_SIM && + req->mTotalPackets > 0 && + req->mLastPacket >= req->mTotalPackets-1) { // We have all the packets... make sure this is high priority // req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority); continue; } F32 elapsed = req->mRequestedTimer.getElapsedTimeF32(); - F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority); - if ((req->mSimRequestedDiscard != req->mDesiredDiscard) || - (delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) || - (elapsed >= LAZY_FLUSH_TIMEOUT)) { - requests[req->mHost].insert(req); + F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority); + if ((req->mSimRequestedDiscard != req->mDesiredDiscard) || + (delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) || + (elapsed >= SIM_LAZY_FLUSH_TIMEOUT)) + { + requests[req->mHost].insert(req); + } } } - - std::string http_url; -#if 0 - if (gSavedSettings.getBOOL("ImagePipelineUseHTTP")) - { - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - http_url = region->getCapability("RequestTextureDownload"); - } } -#endif - + for (work_request_map_t::iterator iter1 = requests.begin(); iter1 != requests.end(); ++iter1) { - bool use_http = http_url.empty() ? false : true; LLHost host = iter1->first; // invalid host = use agent host if (host == LLHost::invalid) { host = gAgent.getRegionHost(); } - else - { - use_http = false; - } - if (use_http) + S32 sim_request_count = 0; + + for (request_list_t::iterator iter2 = iter1->second.begin(); + iter2 != iter1->second.end(); ++iter2) { - } - else - { - S32 request_count = 0; - for (request_list_t::iterator iter2 = iter1->second.begin(); - iter2 != iter1->second.end(); ++iter2) + LLTextureFetchWorker* req = *iter2; + if (gMessageSystem) { - LLTextureFetchWorker* req = *iter2; - req->mSentRequest = LLTextureFetchWorker::SENT_SIM; - if (0 == request_count) + if (req->mSentRequest != LLTextureFetchWorker::SENT_SIM) + { + // Initialize packet data based on data read from cache + req->lockWorkMutex(); + req->setupPacketData(); + req->unlockWorkMutex(); + } + if (0 == sim_request_count) { gMessageSystem->newMessageFast(_PREHASH_RequestImage); gMessageSystem->nextBlockFast(_PREHASH_AgentData); @@ -1666,30 +1787,42 @@ void LLTextureFetch::sendRequestListToSimulators() // llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard // << " Packet: " << packet << " Priority: " << req->mImagePriority << llendl; - req->lockWorkData(); + if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"))) + { + mTextureInfo.setRequestStartTime(req->mID, LLTimer::getTotalTime()); + mTextureInfo.setRequestOffset(req->mID, 0); + mTextureInfo.setRequestSize(req->mID, 0); + mTextureInfo.setRequestType(req->mID, LLTextureInfoDetails::REQUEST_TYPE_UDP); + } + + req->lockWorkMutex(); + req->mSentRequest = LLTextureFetchWorker::SENT_SIM; req->mSimRequestedDiscard = req->mDesiredDiscard; req->mRequestedPriority = req->mImagePriority; req->mRequestedTimer.reset(); - req->unlockWorkData(); - request_count++; - if (request_count >= IMAGES_PER_REQUEST) + req->unlockWorkMutex(); + sim_request_count++; + if (sim_request_count >= IMAGES_PER_REQUEST) { -// llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; +// llinfos << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; + gMessageSystem->sendSemiReliable(host, NULL, NULL); - request_count = 0; + sim_request_count = 0; } } - if (request_count > 0 && request_count < IMAGES_PER_REQUEST) - { -// llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; - gMessageSystem->sendSemiReliable(host, NULL, NULL); - request_count = 0; - } + } + if (gMessageSystem && sim_request_count > 0 && sim_request_count < IMAGES_PER_REQUEST) + { +// llinfos << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; + gMessageSystem->sendSemiReliable(host, NULL, NULL); + sim_request_count = 0; } } // Send cancelations - if (!mCancelQueue.empty()) + { + LLMutexLock lock2(&mNetworkQueueMutex); + if (gMessageSystem && !mCancelQueue.empty()) { for (cancel_queue_t::iterator iter1 = mCancelQueue.begin(); iter1 != mCancelQueue.end(); ++iter1) @@ -1732,6 +1865,7 @@ void LLTextureFetch::sendRequestListToSimulators() } mCancelQueue.clear(); } + } } ////////////////////////////////////////////////////////////////////////////// @@ -1808,7 +1942,7 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 return false; } - worker->lockWorkData(); + worker->lockWorkMutex(); // Copy header data into image object worker->mImageCodec = codec; @@ -1819,7 +1953,7 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 res = worker->insertPacket(0, data, data_size); worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR; - worker->unlockWorkData(); + worker->unlockWorkMutex(); return res; } @@ -1853,7 +1987,7 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 return false; } - worker->lockWorkData(); + worker->lockWorkMutex(); res = worker->insertPacket(packet_num, data, data_size); @@ -1866,12 +2000,20 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 else { // llwarns << "receiveImagePacket " << packet_num << "/" << worker->mLastPacket << " for worker: " << id -// << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << llendl; - removeFromNetworkQueue(worker); // failsafe - mCancelQueue[host].insert(id); +// << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << llendl; + removeFromNetworkQueue(worker, true); // failsafe } - - worker->unlockWorkData(); + + if(packet_num >= (worker->mTotalPackets - 1)) + { + if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"))) + { + U64 timeNow = LLTimer::getTotalTime(); + mTextureInfo.setRequestSize(id, worker->mFileSize); + mTextureInfo.setRequestCompleteTimeAndLog(id, timeNow); + } + } + worker->unlockWorkMutex(); return res; } @@ -1885,9 +2027,9 @@ BOOL LLTextureFetch::isFromLocalCache(const LLUUID& id) LLTextureFetchWorker* worker = getWorker(id); if (worker) { - worker->lockWorkData(); + worker->lockWorkMutex() ; from_cache = worker->mInLocalCache ; - worker->unlockWorkData(); + worker->unlockWorkMutex() ; } return from_cache ; @@ -1907,7 +2049,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r LLTextureFetchWorker* worker = getWorker(id); if (worker && worker->haveWork()) { - worker->lockWorkData(); + worker->lockWorkMutex(); state = worker->mState; fetch_dtime = worker->mFetchTimer.getElapsedTimeF32(); request_dtime = worker->mRequestedTimer.getElapsedTimeF32(); @@ -1924,7 +2066,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r data_progress = (F32)worker->mFormattedImage->getDataSize() / (F32)worker->mFileSize; } } - if (state >= LLTextureFetchWorker::LOAD_FROM_NETWORK && state <= LLTextureFetchWorker::LOAD_FROM_HTTP_GET_DATA) + if (state >= LLTextureFetchWorker::LOAD_FROM_NETWORK && state <= LLTextureFetchWorker::WAIT_HTTP_REQ) { requested_priority = worker->mRequestedPriority; } @@ -1933,7 +2075,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r requested_priority = worker->mImagePriority; } fetch_priority = worker->getPriority(); - worker->unlockWorkData(); + worker->unlockWorkMutex(); } data_progress_p = data_progress; requested_priority_p = requested_priority; @@ -1959,5 +2101,3 @@ void LLTextureFetch::dump() } } - -////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 97719a9468..373e38a83c 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -37,26 +37,29 @@ #include "llimage.h" #include "lluuid.h" #include "llworkerthread.h" +#include "llcurl.h" +#include "lltextureinfo.h" class LLViewerTexture; class LLTextureFetchWorker; +class HTTPGetResponder; class LLTextureCache; +class LLImageDecodeThread; class LLHost; // Interface class class LLTextureFetch : public LLWorkerThread { friend class LLTextureFetchWorker; + friend class HTTPGetResponder; public: - LLTextureFetch(LLTextureCache* cache, bool threaded); + LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded); ~LLTextureFetch(); /*virtual*/ S32 update(U32 max_time_ms); - bool createRequest(const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 discard, bool needs_aux); - bool createRequest(const std::string& filename, const LLUUID& id, const LLHost& host, F32 priority, + bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 discard, bool needs_aux); void deleteRequest(const LLUUID& id, bool cancel); bool getRequestFinished(const LLUUID& id, S32& discard_level, @@ -66,25 +69,39 @@ public: bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data); bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data); + void setTextureBandwidth(F32 bandwidth) { mTextureBandwidth = bandwidth; } + F32 getTextureBandwidth() { return mTextureBandwidth; } + // Debug BOOL isFromLocalCache(const LLUUID& id); S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p, U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p); void dump(); S32 getNumRequests() { return mRequestMap.size(); } + S32 getNumHTTPRequests() { return mHTTPTextureQueue.size(); } // Public for access by callbacks void lockQueue() { mQueueMutex.lock(); } void unlockQueue() { mQueueMutex.unlock(); } LLTextureFetchWorker* getWorker(const LLUUID& id); + + LLTextureInfo* getTextureInfo() { return &mTextureInfo; } protected: void addToNetworkQueue(LLTextureFetchWorker* worker); - void removeFromNetworkQueue(LLTextureFetchWorker* worker); + void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); + void addToHTTPQueue(const LLUUID& id); + void removeFromHTTPQueue(const LLUUID& id); + S32 getHTTPQueueSize() { return (S32)mHTTPTextureQueue.size(); } void removeRequest(LLTextureFetchWorker* worker, bool cancel); + // Called from worker thread (during doWork) + void processCurlRequests(); private: void sendRequestListToSimulators(); + /*virtual*/ void startThread(void); + /*virtual*/ void endThread(void); + /*virtual*/ void threadedUpdate(void); public: LLUUID mDebugID; @@ -95,8 +112,11 @@ public: private: LLMutex mQueueMutex; + LLMutex mNetworkQueueMutex; LLTextureCache* mTextureCache; + LLImageDecodeThread* mImageDecodeThread; + LLCurlRequest* mCurlGetRequest; // Map of all requests by UUID typedef std::map<LLUUID,LLTextureFetchWorker*> map_t; @@ -105,10 +125,13 @@ private: // Set of requests that require network data typedef std::set<LLUUID> queue_t; queue_t mNetworkQueue; + queue_t mHTTPTextureQueue; typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t; cancel_queue_t mCancelQueue; - - LLFrameTimer mNetworkTimer; + F32 mTextureBandwidth; + F32 mMaxBandwidth; + LLTextureInfo mTextureInfo; }; #endif // LL_LLTEXTUREFETCH_H + diff --git a/indra/newview/lltextureinfo.cpp b/indra/newview/lltextureinfo.cpp new file mode 100644 index 0000000000..672a36a8bd --- /dev/null +++ b/indra/newview/lltextureinfo.cpp @@ -0,0 +1,290 @@ +/** + * @file lltextureinfo.cpp + * @brief Object which handles local texture info + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lltextureinfo.h" +#include "lltexturestats.h" +#include "llviewercontrol.h" + +LLTextureInfo::LLTextureInfo() : + mLogTextureDownloadsToViewerLog(false), + mLogTextureDownloadsToSimulator(false), + mTotalBytes(0), + mTotalMilliseconds(0), + mTextureDownloadsStarted(0), + mTextureDownloadsCompleted(0), + mTextureDownloadProtocol("NONE"), + mTextureLogThreshold(100 * 1024), + mCurrentStatsBundleStartTime(0) +{ + mTextures.clear(); +} + +void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold) +{ + mLogTextureDownloadsToViewerLog = writeToViewerLog; + mLogTextureDownloadsToSimulator = sendToSim; + mTextureLogThreshold = textureLogThreshold; +} + +LLTextureInfo::~LLTextureInfo() +{ + std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator; + for (iterator = mTextures.begin(); iterator != mTextures.end(); iterator++) + { + LLTextureInfoDetails *info = (*iterator).second; + delete info; + } + + mTextures.clear(); +} + +void LLTextureInfo::addRequest(const LLUUID& id) +{ + LLTextureInfoDetails *info = new LLTextureInfoDetails(); + mTextures[id] = info; +} + +U32 LLTextureInfo::getTextureInfoMapSize() +{ + return mTextures.size(); +} + +bool LLTextureInfo::has(const LLUUID& id) +{ + std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); + if (iterator == mTextures.end()) + { + return false; + } + else + { + return true; + } +} + +void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime) +{ + if (!has(id)) + { + addRequest(id); + } + mTextures[id]->mStartTime = startTime; + mTextureDownloadsStarted++; +} + +void LLTextureInfo::setRequestSize(const LLUUID& id, U32 size) +{ + if (!has(id)) + { + addRequest(id); + } + mTextures[id]->mSize = size; +} + +void LLTextureInfo::setRequestOffset(const LLUUID& id, U32 offset) +{ + if (!has(id)) + { + addRequest(id); + } + mTextures[id]->mOffset = offset; +} + +void LLTextureInfo::setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type) +{ + if (!has(id)) + { + addRequest(id); + } + mTextures[id]->mType = type; +} + +void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime) +{ + if (!has(id)) + { + addRequest(id); + } + mTextures[id]->mCompleteTime = completeTime; + + std::string protocol = "NONE"; + switch(mTextures[id]->mType) + { + case LLTextureInfoDetails::REQUEST_TYPE_HTTP: + protocol = "HTTP"; + break; + + case LLTextureInfoDetails::REQUEST_TYPE_UDP: + protocol = "UDP"; + break; + + case LLTextureInfoDetails::REQUEST_TYPE_NONE: + default: + break; + } + + if (mLogTextureDownloadsToViewerLog) + { + llinfos << "texture=" << id + << " start=" << mTextures[id]->mStartTime + << " end=" << mTextures[id]->mCompleteTime + << " size=" << mTextures[id]->mSize + << " offset=" << mTextures[id]->mOffset + << " length_in_ms=" << (mTextures[id]->mCompleteTime - mTextures[id]->mStartTime) / 1000 + << " protocol=" << protocol + << llendl; + } + + if(mLogTextureDownloadsToSimulator) + { + S32 texture_stats_upload_threshold = mTextureLogThreshold; + mTotalBytes += mTextures[id]->mSize; + mTotalMilliseconds += mTextures[id]->mCompleteTime - mTextures[id]->mStartTime; + mTextureDownloadsCompleted++; + mTextureDownloadProtocol = protocol; + if (mTotalBytes >= texture_stats_upload_threshold) + { + LLSD texture_data; + std::stringstream startTime; + startTime << mCurrentStatsBundleStartTime; + texture_data["start_time"] = startTime.str(); + std::stringstream endTime; + endTime << completeTime; + texture_data["end_time"] = endTime.str(); + texture_data["averages"] = getAverages(); + send_texture_stats_to_sim(texture_data); + resetTextureStatistics(); + } + } + + mTextures.erase(id); +} + +LLSD LLTextureInfo::getAverages() +{ + LLSD averagedTextureData; + S32 averageDownloadRate; + if(mTotalMilliseconds == 0) + { + averageDownloadRate = 0; + } + else + { + averageDownloadRate = (mTotalBytes * 8) / mTotalMilliseconds; + } + + averagedTextureData["bits_per_second"] = averageDownloadRate; + averagedTextureData["bytes_downloaded"] = mTotalBytes; + averagedTextureData["texture_downloads_started"] = mTextureDownloadsStarted; + averagedTextureData["texture_downloads_completed"] = mTextureDownloadsCompleted; + averagedTextureData["transport"] = mTextureDownloadProtocol; + + return averagedTextureData; +} + +void LLTextureInfo::resetTextureStatistics() +{ + mTotalMilliseconds = 0; + mTotalBytes = 0; + mTextureDownloadsStarted = 0; + mTextureDownloadsCompleted = 0; + mTextureDownloadProtocol = "NONE"; + mCurrentStatsBundleStartTime = LLTimer::getTotalTime(); +} + +U32 LLTextureInfo::getRequestStartTime(const LLUUID& id) +{ + if (!has(id)) + { + return 0; + } + else + { + std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); + return (*iterator).second->mStartTime; + } +} + +U32 LLTextureInfo::getRequestSize(const LLUUID& id) +{ + if (!has(id)) + { + return 0; + } + else + { + std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); + return (*iterator).second->mSize; + } +} + +U32 LLTextureInfo::getRequestOffset(const LLUUID& id) +{ + if (!has(id)) + { + return 0; + } + else + { + std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); + return (*iterator).second->mOffset; + } +} + +LLTextureInfoDetails::LLRequestType LLTextureInfo::getRequestType(const LLUUID& id) +{ + if (!has(id)) + { + return LLTextureInfoDetails::REQUEST_TYPE_NONE; + } + else + { + std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); + return (*iterator).second->mType; + } +} + +U32 LLTextureInfo::getRequestCompleteTime(const LLUUID& id) +{ + if (!has(id)) + { + return 0; + } + else + { + std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id); + return (*iterator).second->mCompleteTime; + } +} + diff --git a/indra/newview/lltextureinfo.h b/indra/newview/lltextureinfo.h new file mode 100644 index 0000000000..71b0ea431f --- /dev/null +++ b/indra/newview/lltextureinfo.h @@ -0,0 +1,80 @@ +/** + * @file lltextureinfo.h + * @brief Object for managing texture information. + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXTUREINFO_H +#define LL_LLTEXTUREINFO_H + +#include "lluuid.h" +#include "lltextureinfodetails.h" +#include <map> + +class LLTextureInfo +{ +public: + LLTextureInfo(); + ~LLTextureInfo(); + + void setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold); + bool has(const LLUUID& id); + void setRequestStartTime(const LLUUID& id, U64 startTime); + void setRequestSize(const LLUUID& id, U32 size); + void setRequestOffset(const LLUUID& id, U32 offset); + void setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type); + void setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime); + U32 getRequestStartTime(const LLUUID& id); + U32 getRequestSize(const LLUUID& id); + U32 getRequestOffset(const LLUUID& id); + LLTextureInfoDetails::LLRequestType getRequestType(const LLUUID& id); + U32 getRequestCompleteTime(const LLUUID& id); + void resetTextureStatistics(); + U32 getTextureInfoMapSize(); + LLSD getAverages(); + +private: + void addRequest(const LLUUID& id); + + std::map<LLUUID, LLTextureInfoDetails *> mTextures; + + LLSD mAverages; + + bool mLogTextureDownloadsToViewerLog; + bool mLogTextureDownloadsToSimulator; + S32 mTotalBytes; + S32 mTotalMilliseconds; + S32 mTextureDownloadsStarted; + S32 mTextureDownloadsCompleted; + std::string mTextureDownloadProtocol; + U32 mTextureLogThreshold; // in bytes + U64 mCurrentStatsBundleStartTime; +}; + +#endif // LL_LLTEXTUREINFO_H diff --git a/indra/newview/lltextureinfodetails.cpp b/indra/newview/lltextureinfodetails.cpp new file mode 100644 index 0000000000..f6ef47a2ee --- /dev/null +++ b/indra/newview/lltextureinfodetails.cpp @@ -0,0 +1,40 @@ +/** + * @file lltextureinfodetails.cpp + * @brief Object which handles details of any individual texture + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lltextureinfodetails.h" + +LLTextureInfoDetails::LLTextureInfoDetails() : mStartTime(0), mCompleteTime(0), mSize(0), mType(REQUEST_TYPE_NONE), mOffset(0) +{ +} + diff --git a/indra/newview/lltextureinfodetails.h b/indra/newview/lltextureinfodetails.h new file mode 100644 index 0000000000..091fa01a3d --- /dev/null +++ b/indra/newview/lltextureinfodetails.h @@ -0,0 +1,58 @@ +/** + * @file lltextureinfo.h + * @brief Object for managing texture information. + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXTUREINFODETAILS_H +#define LL_LLTEXTUREINFODETAILS_H + +#include "lluuid.h" + +class LLTextureInfoDetails +{ +public: + enum LLRequestType + { + REQUEST_TYPE_NONE, + REQUEST_TYPE_HTTP, + REQUEST_TYPE_UDP + }; + + U32 mStartTime; + U32 mCompleteTime; + U32 mOffset; + U32 mSize; + LLRequestType mType; + + LLTextureInfoDetails(); +}; + +#endif // LL_LLTEXTUREINFODETAILS_H + diff --git a/indra/newview/lltexturestats.cpp b/indra/newview/lltexturestats.cpp new file mode 100644 index 0000000000..c91bfd4df2 --- /dev/null +++ b/indra/newview/lltexturestats.cpp @@ -0,0 +1,61 @@ +/** + * @file lltexturerstats.cpp + * @brief texture stats helper methods + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "pipeline.h" +#include "llagent.h" +#include "lltexturefetch.h" +#include "lltexturestats.h" +#include "lltexturestatsuploader.h" +#include "llviewerregion.h" + +void send_texture_stats_to_sim(const LLSD &texture_stats) +{ + LLSD texture_stats_report; + // Only send stats if the agent is connected to a region. + if (!gAgent.getRegion() || gNoRender) + { + return; + } + + LLUUID agent_id = gAgent.getID(); + texture_stats_report["agent_id"] = agent_id; + texture_stats_report["region_id"] = gAgent.getRegion()->getRegionID(); + texture_stats_report["stats_data"] = texture_stats; + + std::string texture_cap_url = gAgent.getRegion()->getCapability("TextureStats"); + LLTextureStatsUploader tsu; + llinfos << "uploading texture stats data to simulator" << llendl; + tsu.uploadStatsToSimulator(texture_cap_url, texture_stats); +} + diff --git a/indra/newview/lltexturestats.h b/indra/newview/lltexturestats.h new file mode 100644 index 0000000000..2deb377dfd --- /dev/null +++ b/indra/newview/lltexturestats.h @@ -0,0 +1,41 @@ +/** + * @file lltexturestats.h + * @brief texture stats utilities + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXTURESTATS_H +#define LL_LLTEXTURESTATS_H + +#include "llappviewer.h" + +// utility functions to capture data on texture download speeds and send to simulator periodically +void send_texture_stats_to_sim(const LLSD &texture_stats); + +#endif // LL_LLTEXTURESTATS_H diff --git a/indra/newview/lltexturestatsuploader.cpp b/indra/newview/lltexturestatsuploader.cpp new file mode 100644 index 0000000000..e0358e1fca --- /dev/null +++ b/indra/newview/lltexturestatsuploader.cpp @@ -0,0 +1,59 @@ +/** + * @file lltexturerstats.cpp + * @brief texture stats upload class + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lltexturestatsuploader.h" + +LLTextureStatsUploader::LLTextureStatsUploader() +{ +} + +LLTextureStatsUploader::~LLTextureStatsUploader() +{ +} + +void LLTextureStatsUploader::uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats) +{ + if ( texture_cap_url != "" ) + { + LLHTTPClient::post(texture_cap_url, texture_stats, NULL); + } + else + { + llinfos << "Not sending texture stats: " + << texture_stats + << " as there is no cap url." + << llendl; + } +} + diff --git a/indra/newview/lltexturestatsuploader.h b/indra/newview/lltexturestatsuploader.h new file mode 100644 index 0000000000..f6cc8be8fe --- /dev/null +++ b/indra/newview/lltexturestatsuploader.h @@ -0,0 +1,48 @@ +/** + * @file lltexturestatsuploader.h + * @brief Class to send the texture stats to the simulatore + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXTURESTATSUPLOADER_H +#define LL_LLTEXTURESTATSUPLOADER_H + +#include "llappviewer.h" + +// utility functions to capture data on texture download speeds and send to simulator periodically + +class LLTextureStatsUploader +{ +public: + LLTextureStatsUploader(); + ~LLTextureStatsUploader(); + void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats); +}; + +#endif // LL_LLTEXTURESTATSUPLOADER_H diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index ea675c5a6e..b6e20608eb 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -44,19 +44,21 @@ #include "llrender.h" #include "lltooltip.h" +#include "llappviewer.h" #include "llselectmgr.h" #include "lltexlayer.h" #include "lltexturecache.h" #include "lltexturefetch.h" +#include "llviewercontrol.h" #include "llviewerobject.h" #include "llviewertexture.h" #include "llviewertexturelist.h" -#include "llappviewer.h" - +#include "llvovolume.h" extern F32 texmem_lower_bound_scale; LLTextureView *gTextureView = NULL; LLTextureSizeView *gTextureSizeView = NULL; +LLTextureSizeView *gTextureCategoryView = NULL; //static std::set<LLViewerFetchedTexture*> LLTextureView::sDebugImages; @@ -168,7 +170,7 @@ void LLTextureBar::draw() { color = LLColor4::green4; } - else if (mImagep->getBoostLevel()) + else if (mImagep->getBoostLevel() > LLViewerTexture::BOOST_NONE) { color = LLColor4::magenta; } @@ -230,10 +232,10 @@ void LLTextureBar::draw() { "DSK", LLColor4::blue }, // CACHE_POST { "NET", LLColor4::green }, // LOAD_FROM_NETWORK { "SIM", LLColor4::green }, // LOAD_FROM_SIMULATOR - { "URL", LLColor4::green2 },// LOAD_FROM_HTTP_GET_URL - { "HTP", LLColor4::green }, // LOAD_FROM_HTTP_GET_DATA + { "REQ", LLColor4::yellow },// SEND_HTTP_REQ + { "HTP", LLColor4::green }, // WAIT_HTTP_REQ { "DEC", LLColor4::yellow },// DECODE_IMAGE - { "DEC", LLColor4::yellow },// DECODE_IMAGE_UPDATE + { "DEC", LLColor4::green }, // DECODE_IMAGE_UPDATE { "WRT", LLColor4::purple },// WRITE_TO_CACHE { "WRT", LLColor4::orange },// WAIT_ON_WRITE { "END", LLColor4::red }, // DONE @@ -261,7 +263,7 @@ void LLTextureBar::draw() // Draw the progress bar. S32 bar_width = 100; - S32 bar_left = 280; + S32 bar_left = 260; left = bar_left; right = left + bar_width; @@ -286,30 +288,31 @@ void LLTextureBar::draw() S32 pip_x = title_x3 + pip_space/2; // Draw the packet pip + const F32 pip_max_time = 5.f; F32 last_event = mImagep->mLastPacketTimer.getElapsedTimeF32(); - if (last_event < 1.f) + if (last_event < pip_max_time) { clr = LLColor4::white; } else { last_event = mImagep->mRequestDeltaTime; - if (last_event < 1.f) + if (last_event < pip_max_time) { clr = LLColor4::green; } else { last_event = mImagep->mFetchDeltaTime; - if (last_event < 1.f) + if (last_event < pip_max_time) { clr = LLColor4::yellow; } } } - if (last_event < 1.f) + if (last_event < pip_max_time) { - clr.setAlpha(1.f - last_event); + clr.setAlpha(1.f - last_event/pip_max_time); gGL.color4fv(clr.mV); gl_rect_2d(pip_x, top, pip_x + pip_width, bottom); } @@ -406,89 +409,113 @@ void LLGLTexMemBar::draw() S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sTotalTextureMemoryInBytes); S32 max_total_mem = LLViewerTexture::sMaxTotalTextureMemInMegaBytes; F32 discard_bias = LLViewerTexture::sDesiredDiscardBias; + F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ; + F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); S32 h_offset = (S32)((texture_bar_height + 2.5f) * mTextureView->mNumTextureBars + 2.5f); //---------------------------------------------------------------------------- LLGLSUIDefault gls_ui; - F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; + LLColor4 text_color(1.f, 1.f, 1.f, 0.75f); + LLColor4 color; std::string text; - text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Discard Bias: %.2f", + text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB", total_mem, max_total_mem, bound_mem, max_bound_mem, - discard_bias); + LLImageRaw::sGlobalRawMemory >> 20, discard_bias, + cache_usage, cache_max_usage); + //, cache_entries, cache_max_entries LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, h_offset + line_height*3, - text_color, LLFontGL::LEFT, LLFontGL::TOP); + text_color, LLFontGL::LEFT, LLFontGL::TOP); //---------------------------------------------------------------------------- - S32 bar_left = 380; +#if 0 + S32 bar_left = 400; S32 bar_width = 200; S32 top = line_height*3 - 2 + h_offset; S32 bottom = top - 6; S32 left = bar_left; S32 right = left + bar_width; - - F32 bar_scale = (F32)bar_width / (max_bound_mem * 1.5f); + F32 bar_scale; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); - gl_rect_2d(left, top, right, bottom); - + // GL Mem Bar + left = bar_left; - right = left + llfloor(bound_mem * bar_scale); - if (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) - { - gGL.color4f(0.f, 1.f, 0.f, 0.75f); - } - else if (bound_mem < max_bound_mem) - { - gGL.color4f(1.f, 1.f, 0.f, 0.75f); - } - else - { - gGL.color4f(1.f, 0.f, 0.f, 0.75f); - } + text = "GL"; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + + left = bar_left+20; + right = left + bar_width; + + gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); // grey gl_rect_2d(left, top, right, bottom); bar_scale = (F32)bar_width / (max_total_mem * 1.5f); + right = left + llfloor(total_mem * bar_scale); + right = llclamp(right, bar_left, bar_left + bar_width); - top = bottom - 2; - bottom = top - 6; + color = (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) ? LLColor4::green : + (total_mem < max_total_mem) ? LLColor4::yellow : LLColor4::red; + color[VALPHA] = .75f; + glColor4fv(color.mV); + + gl_rect_2d(left, top, right, bottom); // red/yellow/green + + // + bar_left += bar_width + bar_space; + //top = bottom - 2; bottom = top - 6; + + // Bound Mem Bar + left = bar_left; - right = left + llfloor(total_mem * bar_scale); - if (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) - { - gGL.color4f(0.f, 1.f, 0.f, 0.75f); - } - else if (total_mem < max_total_mem) - { - gGL.color4f(1.f, 1.f, 0.f, 0.75f); - } - else - { - gGL.color4f(1.f, 0.f, 0.f, 0.75f); - } + text = "GL"; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + left = bar_left + 20; + right = left + bar_width; + + gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); gl_rect_2d(left, top, right, bottom); + color = (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) ? LLColor4::green : + (bound_mem < max_bound_mem) ? LLColor4::yellow : LLColor4::red; + color[VALPHA] = .75f; + glColor4fv(color.mV); + + gl_rect_2d(left, top, right, bottom); +#else + S32 left = 0 ; +#endif //---------------------------------------------------------------------------- - text = llformat("Textures: Count: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d(%d) RAW:%d mRaw:%d mAux:%d CB:%d", + text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d HTP:%d", gTextureList.getNumImages(), LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(), LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount, LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(), LLLFSThread::sLocal->getPending(), - LLImageWorker::sCount, LLImageWorker::getWorkerThread()->getNumDeletes(), - LLImageRaw::sRawImageCount, LLViewerFetchedTexture::sRawCount, LLViewerFetchedTexture::sAuxCount, - gTextureList.mCallbackList.size()); + LLAppViewer::getImageDecodeThread()->getPending(), + LLImageRaw::sRawImageCount, + LLAppViewer::getTextureFetch()->getNumHTTPRequests()); LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, h_offset + line_height*2, text_color, LLFontGL::LEFT, LLFontGL::TOP); + + + left = 550; + F32 bandwidth = LLAppViewer::getTextureFetch()->getTextureBandwidth(); + F32 max_bandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); + color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color; + color[VALPHA] = text_color[VALPHA]; + text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth); + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*2, + color, LLFontGL::LEFT, LLFontGL::TOP); S32 dx1 = 0; if (LLAppViewer::getTextureFetch()->mDebugPause) @@ -555,7 +582,7 @@ public: void setTop(S32 loaded, S32 bound, F32 scale) {mTopLoaded = loaded ; mTopBound = bound; mScale = scale ;} void draw(); - BOOL handleHover(S32 x, S32 y, MASK mask) ; + BOOL handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) ; private: S32 mIndex ; @@ -568,19 +595,16 @@ private: F32 mScale ; }; -BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask) +BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) { -#if !LL_RELEASE_FOR_DOWNLOAD if(y > mBottom && (y < mBottom + (S32)(mTopLoaded * mScale) || y < mBottom + (S32)(mTopBound * mScale))) { - LLImageGL::setCurTexSizebar(mIndex); + LLImageGL::setCurTexSizebar(mIndex, set_pick_size); } -#endif return TRUE ; } void LLGLTexSizeBar::draw() { -#if !LL_RELEASE_FOR_DOWNLOAD LLGLSUIDefault gls_ui; if(LLImageGL::sCurTexSizeBar == mIndex) @@ -601,7 +625,6 @@ void LLGLTexSizeBar::draw() F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; gl_rect_2d(mLeft, mBottom + (S32)(mTopLoaded * mScale), (mLeft + mRight) / 2, mBottom, loaded_color) ; gl_rect_2d((mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale), mRight, mBottom, bound_color) ; -#endif } //////////////////////////////////////////////////////////////////////////// @@ -675,7 +698,13 @@ void LLTextureView::draw() << "\t" << cur_discard << llendl; } - + + if (imagep->getID() == LLAppViewer::getTextureFetch()->mDebugID) + { + static S32 debug_count = 0; + ++debug_count; // for breakpoints + } + #if 0 if (imagep->getDontDiscard()) { @@ -889,8 +918,7 @@ BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent) } //----------------------------------------------------------------- -LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p) - : LLView(p) +LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p) : LLContainerView(p) { setVisible(FALSE) ; @@ -910,7 +938,31 @@ LLTextureSizeView::~LLTextureSizeView() } void LLTextureSizeView::draw() { -#if !LL_RELEASE_FOR_DOWNLOAD + if(mType == TEXTURE_MEM_OVER_SIZE) + { + drawTextureSizeGraph(); + } + else + { + drawTextureCategoryGraph() ; + } + + LLView::draw(); +} + +BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) +{ + if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight) + { + mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask, (mType == TEXTURE_MEM_OVER_SIZE)) ; + } + + return TRUE ; +} + +//draw real-time texture mem bar over size +void LLTextureSizeView::drawTextureSizeGraph() +{ if(mTextureSizeBar.size() == 0) { S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); @@ -931,29 +983,16 @@ void LLTextureSizeView::draw() mTextureSizeBar[i]->draw() ; } LLImageGL::resetCurTexSizebar(); - - LLView::draw(); -#endif -} - -BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) -{ - if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight) - { - mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask) ; - } - - return TRUE ; } //draw background of texture size bar graph F32 LLTextureSizeView::drawTextureSizeDistributionGraph() { + //scale F32 scale = 1.0f ; -#if !LL_RELEASE_FOR_DOWNLOAD + LLGLSUIDefault gls_ui; - //scale { S32 count = 0 ; for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++) @@ -1043,8 +1082,137 @@ F32 LLTextureSizeView::drawTextureSizeDistributionGraph() text = llformat("Texture Size Distribution") ; LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, text_color, LLFontGL::LEFT, LLFontGL::TOP); - -#endif return scale ; } +//draw real-time texture mem bar over category +void LLTextureSizeView::drawTextureCategoryGraph() +{ + if(mTextureSizeBar.size() == 0) + { + S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); + mTextureSizeBar.resize(LLViewerTexture::getTotalNumOfCategories()) ; + mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ; + + for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) + { + mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , + line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ; + } + } + + F32 size_bar_scale = drawTextureCategoryDistributionGraph() ; + for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) + { + U32 k = LLViewerTexture::getIndexFromCategory(i) ; + mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ; + mTextureSizeBar[i]->draw() ; + } + LLImageGL::resetCurTexSizebar(); +} + +//draw background for TEXTURE_MEM_OVER_CATEGORY +F32 LLTextureSizeView::drawTextureCategoryDistributionGraph() +{ + //scale + F32 scale = 4.0f ; + + LLGLSUIDefault gls_ui; + + { + S32 count = 0 ; + for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++) + { + S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ; + if(tmp > count) + { + count = tmp ; + } + } + if(count > mTextureSizeBarRect.getHeight() * 0.25f) + { + scale = (F32)mTextureSizeBarRect.getHeight() * 0.25f / count ; + } + } + + S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); + S32 left = mTextureSizeBarRect.mLeft ; + S32 bottom = mTextureSizeBarRect.mBottom ; + S32 right = mTextureSizeBarRect.mRight ; + S32 top = mTextureSizeBarRect.mTop ; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + //background rect + gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ; + + //-------------------------------------------------- + gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f); + gl_line_2d(left, bottom, right, bottom) ; //x axis + gl_line_2d(left, bottom, left, top) ; //y axis + + //ruler + //-------------------------------------------------- + gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f); + for(S32 i = bottom + 50 ; i <= top ; i += 50) + { + gl_line_2d(left, i, right, i) ; + } + + //texts + //-------------------------------------------------- + F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; + std::string text; + + //------- + //x axis: size label + static char category[LLViewerTexture::MAX_GL_IMAGE_CATEGORY][4] = + {"Non", "Bak", "Av", "Cld", "Scp", "Hi", "Trn", "Slt", "Hud", "Bsf", "UI", "Pvw", "Map", "Mvs", "Slf", "Loc", "Scr", "Dyn", "Mdi", "ALT", "Oth" } ; + + text = llformat("%s", category[0]) ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++) + { + text = llformat("%s", category[i]) ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + } + //------- + + //y axis: number label + for(S32 i = bottom + 50 ; i <= top ; i += 50) + { + text = llformat("%d", (S32)((i - bottom) / scale)) ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 , + text_color, LLFontGL::LEFT, LLFontGL::TOP); + LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 , + text_color, LLFontGL::LEFT, LLFontGL::TOP); + } + + text = llformat("MB") ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, top + line_height * 2 , + text_color, LLFontGL::LEFT, LLFontGL::TOP); + //-------------------------------------------------- + F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f}; + gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ; + text = llformat("Loaded") ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2, + loaded_color, + LLFontGL::LEFT, LLFontGL::TOP); + + F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; + gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ; + text = llformat("Bound") ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2, + bound_color, LLFontGL::LEFT, LLFontGL::TOP); + + //-------------------------------------------------- + + //title + text = llformat("Texture Category Distribution") ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + + return scale ; +} diff --git a/indra/newview/lltextureview.h b/indra/newview/lltextureview.h index e917c0235e..435a55df83 100644 --- a/indra/newview/lltextureview.h +++ b/indra/newview/lltextureview.h @@ -79,24 +79,41 @@ public: }; class LLGLTexSizeBar; - -class LLTextureSizeView : public LLView +class LLTextureSizeView : public LLContainerView { -public: +protected: LLTextureSizeView(const Params&); + friend class LLUICtrlFactory; +public: ~LLTextureSizeView(); /*virtual*/ void draw(); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) ; + void setType(S32 type) {mType = type ;} + enum + { + TEXTURE_MEM_OVER_SIZE, + TEXTURE_MEM_OVER_CATEGORY + }; private: + //draw background for TEXTURE_MEM_OVER_SIZE F32 drawTextureSizeDistributionGraph() ; - + //draw real-time texture mem bar over size + void drawTextureSizeGraph(); + + //draw background for TEXTURE_MEM_OVER_CATEGORY + F32 drawTextureCategoryDistributionGraph() ; + //draw real-time texture mem bar over category + void drawTextureCategoryGraph(); + private: std::vector<LLGLTexSizeBar*> mTextureSizeBar ; LLRect mTextureSizeBarRect ; - S32 mTextureSizeBarWidth ; + S32 mTextureSizeBarWidth ; + S32 mType ; }; extern LLTextureView *gTextureView; extern LLTextureSizeView *gTextureSizeView; +extern LLTextureSizeView *gTextureCategoryView; #endif // LL_TEXTURE_VIEW_H diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index e4a3f8603b..beb31bc833 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -30,6 +30,9 @@ * $/LicenseInfo$ */ +// *NOTE: this module is a copy-paste of llui/llalertdialog.h +// Can we re-implement this as a subclass of LLAlertDialog and +// avoid all this code duplication? It already caused EXT-2232. #include "llviewerprecompiledheaders.h" // must be first include @@ -56,7 +59,7 @@ const F32 DEFAULT_BUTTON_DELAY = 0.5f; const S32 MSG_PAD = 8; /*static*/ LLControlGroup* LLToastAlertPanel::sSettings = NULL; -/*static*/ LLToastAlertPanel::URLLoader* LLToastAlertPanel::sURLLoader; +/*static*/ LLAlertURLLoader* LLToastAlertPanel::sURLLoader; //----------------------------------------------------------------------------- // Private methods diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index af0c9a9ddd..840143a2a9 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -30,6 +30,10 @@ * $/LicenseInfo$ */ +// *NOTE: this module is a copy-paste of llui/llalertdialog.h +// Can we re-implement this as a subclass of LLAlertDialog and +// avoid all this code duplication? It already caused EXT-2232. + #ifndef LL_TOASTALERTPANEL_H #define LL_TOASTALERTPANEL_H @@ -37,6 +41,7 @@ #include "llfloater.h" #include "llui.h" #include "llnotifications.h" +#include "llalertdialog.h" class LLButton; class LLCheckBoxCtrl; @@ -57,14 +62,7 @@ class LLToastAlertPanel public: typedef bool (*display_callback_t)(S32 modal); - class URLLoader - { - public: - virtual void load(const std::string& url, bool force_open_externally = 0 ) = 0; - virtual ~URLLoader() {} - }; - - static void setURLLoader(URLLoader* loader) + static void setURLLoader(LLAlertURLLoader* loader) { sURLLoader = loader; } @@ -97,7 +95,7 @@ private: BOOL hasTitleBar() const; private: - static URLLoader* sURLLoader; + static LLAlertURLLoader* sURLLoader; static LLControlGroup* sSettings; struct ButtonData diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index e26a0776ff..f82573f46c 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -38,6 +38,7 @@ #include "llbutton.h" #include "lliconctrl.h" +#include "llinventoryfunctions.h" #include "llnotify.h" #include "lltextbox.h" @@ -219,7 +220,6 @@ bool LLToastGroupNotifyPanel::isAttachmentOpenable(LLAssetType::EType type) switch(type) { case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_FAVORITE: case LLAssetType::AT_NOTECARD: case LLAssetType::AT_IMAGE_JPEG: case LLAssetType::AT_IMAGE_TGA: diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 9a63f07a7e..959cb3f182 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -92,7 +92,7 @@ public: virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) { - if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE)) + if(cat && (cat->getPreferredType() == LLFolderType::FT_NONE)) { return true; } @@ -109,7 +109,7 @@ public: LLInventoryItem* item) { if(item) return true; - if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE)) + if(cat && (cat->getPreferredType() == LLFolderType::FT_NONE)) { return true; } @@ -1317,8 +1317,7 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, // Check if it's in the trash. bool is_in_trash = false; - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) { is_in_trash = true; @@ -2088,7 +2087,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv( if(!item || !item->isComplete()) return ACCEPT_NO; // must not be in the trash - LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH)); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) { return ACCEPT_NO; @@ -2170,8 +2169,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( } // Check if it's in the trash. - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) { accept = ACCEPT_YES_SINGLE; @@ -2249,8 +2247,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject( } // Check if it's in the trash. - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) { accept = ACCEPT_YES_SINGLE; @@ -2388,7 +2385,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem( if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) { // it's in the agent inventory - LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) { return ACCEPT_NO; @@ -2443,7 +2440,7 @@ EAcceptance LLToolDragAndDrop::dad3dActivateGesture( if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) { // it's in the agent inventory - LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) { return ACCEPT_NO; @@ -2502,7 +2499,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory( if(mSource == SOURCE_AGENT) { - LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH)); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if( gInventory.isObjectDescendentOf( category->getUUID(), trash_id ) ) { return ACCEPT_NO; diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 0a9e72506b..93da32b115 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -494,6 +494,8 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) } else if (handleMediaHover(mHoverPick)) { + // *NOTE: If you think the hover glow conflicts with the media outline, you + // could disable it here. show_highlight = true; // cursor set by media object lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl; @@ -761,14 +763,14 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask) { is_time_based_media = true; is_web_based_media = false; - args["[CurrentURL]"] = media_impl->getMediaURL(); + //args["[CurrentURL]"] = media_impl->getMediaURL(); is_media_playing = media_impl->isMediaPlaying(); } else { is_time_based_media = false; is_web_based_media = true; - args["[CurrentURL]"] = media_plugin->getLocation(); + //args["[CurrentURL]"] = media_plugin->getLocation(); } //tooltip_msg.append(LLTrans::getString("CurrentURL", args)); } @@ -1039,31 +1041,28 @@ void LLToolPie::playCurrentMedia(const LLPickInfo& info) if(!mep) return; + //TODO: Can you Use it? + LLPluginClassMedia* media_plugin = NULL; -// if (gSavedSettings.getBOOL("MediaOnAPrimUI")) -// { - viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); - if(media_impl.notNull() && media_impl->hasMedia()) + if(media_impl.notNull() && media_impl->hasMedia()) + { + media_plugin = media_impl->getMediaPlugin(); + if (media_plugin && media_plugin->pluginSupportsMediaTime()) { - media_plugin = media_impl->getMediaPlugin(); - - if (media_plugin && media_plugin->pluginSupportsMediaTime()) + if(media_impl->isMediaPlaying()) { - if(media_impl->isMediaPlaying()) - { - media_impl->pause(); - } - else //if(media_impl->isMediaPaused()) - { - media_impl->play(); - } - + media_impl->pause(); + } + else + { + media_impl->play(); } - } -// } + } + } @@ -1094,6 +1093,8 @@ void LLToolPie::VisitHomePage(const LLPickInfo& info) if(!mep) return; + //TODO: Can you Use it? + LLPluginClassMedia* media_plugin = NULL; viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index 5929ecd928..1a61717658 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -416,10 +416,10 @@ F32 pulse_func(F32 t, F32 z) return 0.f; } - t *= 3.14159f; + t *= F_PI; z -= t*64.f - 256.f; - F32 a = cosf(z*3.14159/512.f)*10.0f; + F32 a = cosf(z*F_PI/512.f)*10.0f; a = llmax(a, 9.9f); a -= 9.9f; a *= 10.f; @@ -433,7 +433,7 @@ void draw_shockwave(F32 center_z, F32 t, S32 steps, LLColor4 color) return; } - t *= 0.6284f/3.14159f; + t *= 0.6284f/F_PI; t -= (F32) (S32) t; diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 841902f683..a3daca6fa4 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -46,7 +46,7 @@ #include "llstartup.h" // gStartupState #include "llurlsimstring.h" #include "llweb.h" -#include "llworldmap.h" +#include "llworldmapmessage.h" // library includes #include "llsd.h" @@ -201,7 +201,7 @@ bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mous //if(url_displayp) url_displayp->setName(region_name); // Request a region handle by name - LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, LLURLDispatcherImpl::regionNameCallback, url, false); // don't teleport @@ -240,7 +240,7 @@ void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const std::strin LLVector3d global_pos = from_region_handle(region_handle) + LLVector3d(local_pos); U64 new_region_handle = to_region_handle(global_pos); - LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, + LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, LLURLDispatcherImpl::regionHandleCallback, url, teleport); } @@ -335,7 +335,7 @@ public: { url += tokens[i].asString() + "/"; } - LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, LLURLDispatcherImpl::regionHandleCallback, url, true); // teleport diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp new file mode 100644 index 0000000000..c974171c2c --- /dev/null +++ b/indra/newview/llviewerassettype.cpp @@ -0,0 +1,114 @@ +/** + * @file llassettype.cpp + * @brief Implementatino of LLViewerAssetType functionality. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewerassettype.h" +#include "lldictionary.h" +#include "llmemory.h" +#include "llsingleton.h" + +static const std::string empty_string; + +struct ViewerAssetEntry : public LLDictionaryEntry +{ + ViewerAssetEntry(EDragAndDropType dad_type // drag and drop type + ) + : + LLDictionaryEntry(empty_string), // no reverse lookup needed for now, so just leave this blank + mDadType(dad_type) + { + } + EDragAndDropType mDadType; +}; + +class LLViewerAssetDictionary : public LLSingleton<LLViewerAssetDictionary>, + public LLDictionary<LLViewerAssetType::EType, ViewerAssetEntry> +{ +public: + LLViewerAssetDictionary(); +}; + +LLViewerAssetDictionary::LLViewerAssetDictionary() +{ + // DRAG&DROP TYPE + // |--------------------| + addEntry(LLViewerAssetType::AT_TEXTURE, new ViewerAssetEntry(DAD_TEXTURE)); + addEntry(LLViewerAssetType::AT_SOUND, new ViewerAssetEntry(DAD_SOUND)); + addEntry(LLViewerAssetType::AT_CALLINGCARD, new ViewerAssetEntry(DAD_CALLINGCARD)); + addEntry(LLViewerAssetType::AT_LANDMARK, new ViewerAssetEntry(DAD_LANDMARK)); + addEntry(LLViewerAssetType::AT_SCRIPT, new ViewerAssetEntry(DAD_NONE)); + addEntry(LLViewerAssetType::AT_CLOTHING, new ViewerAssetEntry(DAD_CLOTHING)); + addEntry(LLViewerAssetType::AT_OBJECT, new ViewerAssetEntry(DAD_OBJECT)); + addEntry(LLViewerAssetType::AT_NOTECARD, new ViewerAssetEntry(DAD_NOTECARD)); + addEntry(LLViewerAssetType::AT_CATEGORY, new ViewerAssetEntry(DAD_CATEGORY)); + addEntry(LLViewerAssetType::AT_ROOT_CATEGORY, new ViewerAssetEntry(DAD_ROOT_CATEGORY)); + addEntry(LLViewerAssetType::AT_LSL_TEXT, new ViewerAssetEntry(DAD_SCRIPT)); + addEntry(LLViewerAssetType::AT_LSL_BYTECODE, new ViewerAssetEntry(DAD_NONE)); + addEntry(LLViewerAssetType::AT_TEXTURE_TGA, new ViewerAssetEntry(DAD_NONE)); + addEntry(LLViewerAssetType::AT_BODYPART, new ViewerAssetEntry(DAD_BODYPART)); + addEntry(LLViewerAssetType::AT_SOUND_WAV, new ViewerAssetEntry(DAD_NONE)); + addEntry(LLViewerAssetType::AT_IMAGE_TGA, new ViewerAssetEntry(DAD_NONE)); + addEntry(LLViewerAssetType::AT_IMAGE_JPEG, new ViewerAssetEntry(DAD_NONE)); + addEntry(LLViewerAssetType::AT_ANIMATION, new ViewerAssetEntry(DAD_ANIMATION)); + addEntry(LLViewerAssetType::AT_GESTURE, new ViewerAssetEntry(DAD_GESTURE)); + addEntry(LLViewerAssetType::AT_SIMSTATE, new ViewerAssetEntry(DAD_NONE)); + + addEntry(LLViewerAssetType::AT_LINK, new ViewerAssetEntry(DAD_LINK)); + addEntry(LLViewerAssetType::AT_LINK_FOLDER, new ViewerAssetEntry(DAD_LINK)); + + addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE)); +}; + +EDragAndDropType LLViewerAssetType::lookupDragAndDropType(EType asset_type) +{ + const LLViewerAssetDictionary *dict = LLViewerAssetDictionary::getInstance(); + const ViewerAssetEntry *entry = dict->lookup(asset_type); + if (entry) + return entry->mDadType; + else + return DAD_NONE; +} + +// Generate a good default description +void LLViewerAssetType::generateDescriptionFor(LLViewerAssetType::EType asset_type, + std::string& description) +{ + const S32 BUF_SIZE = 30; + char time_str[BUF_SIZE]; /* Flawfinder: ignore */ + time_t now; + time(&now); + memset(time_str, '\0', BUF_SIZE); + strftime(time_str, BUF_SIZE - 1, "%Y-%m-%d %H:%M:%S ", localtime(&now)); + description.assign(time_str); + description.append(LLAssetType::lookupHumanReadable(asset_type)); +} diff --git a/indra/newview/llviewerassettype.h b/indra/newview/llviewerassettype.h new file mode 100644 index 0000000000..01158885ce --- /dev/null +++ b/indra/newview/llviewerassettype.h @@ -0,0 +1,54 @@ +/** + * @file llviewerassettype.h + * @brief Declaration of LLViewerViewerAssetType. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLVIEWERASSETTYPE_H +#define LL_LLVIEWERASSETTYPE_H + +#include <string> +#include "llassettype.h" + +// This class is similar to llassettype, but contains methods +// only used by the viewer. +class LLViewerAssetType : public LLAssetType +{ +public: + // Generate a good default description. You may want to add a verb + // or agent name after this depending on your application. + static void generateDescriptionFor(LLViewerAssetType::EType asset_type, + std::string& description); + static EDragAndDropType lookupDragAndDropType(EType asset_type); +protected: + LLViewerAssetType() {} + ~LLViewerAssetType() {} +}; + +#endif // LL_LLVIEWERASSETTYPE_H diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index f65baea6ca..b5709fa102 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -109,10 +109,13 @@ LLViewerCamera::LLViewerCamera() : LLCamera() { calcProjection(getFar()); mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; + mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f); mPixelMeterRatio = 0.f; mScreenPixelArea = 0; mZoomFactor = 1.f; mZoomSubregion = 1; + mAverageSpeed = 0.f; + mAverageAngularSpeed = 0.f; gSavedSettings.getControl("CameraAngle")->getCommitSignal()->connect(boost::bind(&LLViewerCamera::updateCameraAngle, this, _2)); } @@ -151,15 +154,22 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, setOriginAndLookAt(origin, up_direction, point_of_interest); - F32 dpos = (center - last_position).magVec(); + mVelocityDir = center - last_position ; + F32 dpos = mVelocityDir.normVec() ; LLQuaternion rotation; rotation.shortestArc(last_axis, getAtAxis()); F32 x, y, z; F32 drot; rotation.getAngleAxis(&drot, &x, &y, &z); + mVelocityStat.addValue(dpos); mAngularVelocityStat.addValue(drot); + + mAverageSpeed = mVelocityStat.getMeanPerSec() ; + mAverageAngularSpeed = mAngularVelocityStat.getMeanPerSec() ; + mCosHalfCameraFOV = cosf(0.5f * getView() * llmax(1.0f, getAspect())); + // update pixel meter ratio using default fov, not modified one mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5)); // update screen pixel area @@ -818,10 +828,12 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) LLCamera::setView(vertical_fov_rads); // call base implementation } -void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) { +void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) +{ vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView()); setView(vertical_fov_rads); mCameraFOVDefault = vertical_fov_rads; + mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f); } diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 90b77f771f..2b8a0892bf 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -91,17 +91,20 @@ public: BOOL projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp = TRUE) const; BOOL projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const; - + const LLVector3* getVelocityDir() const {return &mVelocityDir;} LLStat *getVelocityStat() { return &mVelocityStat; } LLStat *getAngularVelocityStat() { return &mAngularVelocityStat; } + F32 getCosHalfFov() {return mCosHalfCameraFOV;} + F32 getAverageSpeed() {return mAverageSpeed ;} + F32 getAverageAngularSpeed() {return mAverageAngularSpeed;} void getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right); LLVector3 roundToPixel(const LLVector3 &pos_agent); // Sets the current matrix /* virtual */ void setView(F32 vertical_fov_rads); - // Sets the current matrix AND remembers result as default view - void setDefaultFOV(F32 vertical_fov_rads); + + void setDefaultFOV(F32 fov) ; F32 getDefaultFOV() { return mCameraFOVDefault; } BOOL cameraUnderWater() const; @@ -120,9 +123,14 @@ protected: LLStat mVelocityStat; LLStat mAngularVelocityStat; + LLVector3 mVelocityDir ; + F32 mAverageSpeed ; + F32 mAverageAngularSpeed ; + mutable LLMatrix4 mProjectionMatrix; // Cache of perspective matrix mutable LLMatrix4 mModelviewMatrix; F32 mCameraFOVDefault; + F32 mCosHalfCameraFOV; LLVector3 mLastPointOfInterest; F32 mPixelMeterRatio; // Divide by distance from camera to get pixels per meter at that distance. S32 mScreenPixelArea; // Pixel area of entire window diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 35226a1632..5e23a7e114 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -90,7 +90,7 @@ std::string gCurrentVersion; extern BOOL gResizeScreenTexture; extern BOOL gDebugGL; - +extern BOOL gAuditTexture; //////////////////////////////////////////////////////////////////////////// // Listeners @@ -378,6 +378,12 @@ static bool handleRenderUseImpostorsChanged(const LLSD& newvalue) return true; } +static bool handleAuditTextureChanged(const LLSD& newvalue) +{ + gAuditTexture = newvalue.asBoolean(); + return true; +} + static bool handleRenderDebugGLChanged(const LLSD& newvalue) { gDebugGL = newvalue.asBoolean() || gDebugSession; @@ -587,6 +593,7 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderDeferredShadow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderDeferredGI")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2)); + gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _2)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _2)); gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _2)); gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index a6a72e9666..e0bb8fedeb 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -712,7 +712,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. - const F32 max_image_decode_time = llmin(0.005f, 0.005f*10.f*gFrameIntervalSeconds); // 50 ms/second decode time (no more than 5ms/frame) + F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time + max_image_decode_time = llclamp(max_image_decode_time, 0.001f, 0.005f ); // min 1ms/frame, max 5ms/frame) gTextureList.updateImages(max_image_decode_time); //remove dead textures from GL diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 9ca2d3f61d..edbac69e1b 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -170,6 +170,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>); LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>); + LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>); LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInventory>); LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>); LLInspectAvatarUtil::registerFloater(); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp new file mode 100644 index 0000000000..384538364f --- /dev/null +++ b/indra/newview/llviewerfoldertype.cpp @@ -0,0 +1,263 @@ +/** + * @file llfoldertype.cpp + * @brief Implementation of LLViewerFolderType functionality. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewerfoldertype.h" +#include "lldictionary.h" +#include "llmemory.h" +#include "llvisualparam.h" + +static const std::string empty_string; + +struct ViewerFolderEntry : public LLDictionaryEntry +{ + // Constructor for non-ensembles + ViewerFolderEntry(const std::string &new_category_name, // default name when creating a new category of this type + const std::string &icon_name // name of the folder icon + ) + : + LLDictionaryEntry(empty_string), // no reverse lookup needed on non-ensembles, so just leave this blank + mIconName(icon_name), + mNewCategoryName(new_category_name) + { + mAllowedNames.clear(); + } + + // Constructor for ensembles + ViewerFolderEntry(const std::string &xui_name, // name of the xui menu item + const std::string &new_category_name, // default name when creating a new category of this type + const std::string &icon_name, // name of the folder icon + const std::string allowed_names // allowed item typenames for this folder type + ) + : + LLDictionaryEntry(xui_name), + mIconName(icon_name), + mNewCategoryName(new_category_name) + { + const std::string delims (","); + LLStringUtilBase<char>::getTokens(allowed_names, mAllowedNames, delims); + } + + bool getIsAllowedName(const std::string &name) const + { + if (mAllowedNames.empty()) + return false; + for (name_vec_t::const_iterator iter = mAllowedNames.begin(); + iter != mAllowedNames.end(); + iter++) + { + if (name == (*iter)) + return true; + } + return false; + } + const std::string mIconName; + const std::string mNewCategoryName; + typedef std::vector<std::string> name_vec_t; + name_vec_t mAllowedNames; +}; + +class LLViewerFolderDictionary : public LLSingleton<LLViewerFolderDictionary>, + public LLDictionary<LLFolderType::EType, ViewerFolderEntry> +{ +public: + LLViewerFolderDictionary(); +protected: + bool initEnsemblesFromFile(); // Reads in ensemble information from foldertypes.xml +}; + +LLViewerFolderDictionary::LLViewerFolderDictionary() +{ + initEnsemblesFromFile(); + + // NEW CATEGORY NAME FOLDER ICON NAME + // |-------------------------|---------------------------| + addEntry(LLFolderType::FT_TEXTURE, new ViewerFolderEntry("Textures", "inv_folder_texture.tga")); + addEntry(LLFolderType::FT_SOUND, new ViewerFolderEntry("Sounds", "inv_folder_sound.tga")); + addEntry(LLFolderType::FT_CALLINGCARD, new ViewerFolderEntry("Calling Cards", "inv_folder_callingcard.tga")); + addEntry(LLFolderType::FT_LANDMARK, new ViewerFolderEntry("Landmarks", "inv_folder_landmark.tga")); + addEntry(LLFolderType::FT_CLOTHING, new ViewerFolderEntry("Clothing", "inv_folder_clothing.tga")); + addEntry(LLFolderType::FT_OBJECT, new ViewerFolderEntry("Objects", "inv_folder_object.tga")); + addEntry(LLFolderType::FT_NOTECARD, new ViewerFolderEntry("Notecards", "inv_folder_notecard.tga")); + addEntry(LLFolderType::FT_CATEGORY, new ViewerFolderEntry("New Folder", "inv_folder_plain_closed.tga")); + addEntry(LLFolderType::FT_ROOT_CATEGORY, new ViewerFolderEntry("Inventory", "")); + addEntry(LLFolderType::FT_LSL_TEXT, new ViewerFolderEntry("Scripts", "inv_folder_script.tga")); + addEntry(LLFolderType::FT_BODYPART, new ViewerFolderEntry("Body Parts", "inv_folder_bodypart.tga")); + addEntry(LLFolderType::FT_TRASH, new ViewerFolderEntry("Trash", "inv_folder_trash.tga")); + addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new ViewerFolderEntry("Photo Album", "inv_folder_snapshot.tga")); + addEntry(LLFolderType::FT_LOST_AND_FOUND, new ViewerFolderEntry("Lost And Found", "inv_folder_lostandfound.tga")); + addEntry(LLFolderType::FT_ANIMATION, new ViewerFolderEntry("Animations", "inv_folder_animation.tga")); + addEntry(LLFolderType::FT_GESTURE, new ViewerFolderEntry("Gestures", "inv_folder_gesture.tga")); + addEntry(LLFolderType::FT_FAVORITE, new ViewerFolderEntry("Favorite", "inv_folder_plain_closed.tga")); + + addEntry(LLFolderType::FT_CURRENT_OUTFIT, new ViewerFolderEntry("Current Outfit", "inv_folder_current_outfit.tga")); + addEntry(LLFolderType::FT_OUTFIT, new ViewerFolderEntry("New Outfit", "inv_folder_outfit.tga")); + addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "inv_folder_my_outfits.tga")); + addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "inv_folder_inbox.tga")); + + addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "inv_folder_plain_closed.tga")); +} + +bool LLViewerFolderDictionary::initEnsemblesFromFile() +{ + std::string xml_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"foldertypes.xml"); + LLXmlTree folder_def; + if (!folder_def.parseFile(xml_filename)) + { + llerrs << "Failed to parse folders file " << xml_filename << llendl; + return false; + } + + LLXmlTreeNode* rootp = folder_def.getRoot(); + for (LLXmlTreeNode* ensemble = rootp->getFirstChild(); + ensemble; + ensemble = rootp->getNextChild()) + { + if (!ensemble->hasName("ensemble")) + { + llwarns << "Invalid ensemble definition node " << ensemble->getName() << llendl; + continue; + } + + S32 ensemble_type; + static LLStdStringHandle ensemble_num_string = LLXmlTree::addAttributeString("foldertype_num"); + if (!ensemble->getFastAttributeS32(ensemble_num_string, ensemble_type)) + { + llwarns << "No ensemble type defined" << llendl; + continue; + } + + + if (ensemble_type < S32(LLFolderType::FT_ENSEMBLE_START) || ensemble_type > S32(LLFolderType::FT_ENSEMBLE_END)) + { + llwarns << "Exceeded maximum ensemble index" << LLFolderType::FT_ENSEMBLE_END << llendl; + break; + } + + std::string xui_name; + static LLStdStringHandle xui_name_string = LLXmlTree::addAttributeString("xui_name"); + if (!ensemble->getFastAttributeString(xui_name_string, xui_name)) + { + llwarns << "No xui name defined" << llendl; + continue; + } + + std::string icon_name; + static LLStdStringHandle icon_name_string = LLXmlTree::addAttributeString("icon_name"); + if (!ensemble->getFastAttributeString(icon_name_string, icon_name)) + { + llwarns << "No ensemble icon name defined" << llendl; + continue; + } + + std::string allowed_names; + static LLStdStringHandle allowed_names_string = LLXmlTree::addAttributeString("allowed"); + if (!ensemble->getFastAttributeString(allowed_names_string, allowed_names)) + { + } + + // Add the entry and increment the asset number. + const static std::string new_ensemble_name = "New Ensemble"; + addEntry(LLFolderType::EType(ensemble_type), new ViewerFolderEntry(xui_name, new_ensemble_name, icon_name, allowed_names)); + } + + return true; +} + + +const std::string &LLViewerFolderType::lookupXUIName(LLFolderType::EType folder_type) +{ + const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type); + if (entry) + { + return entry->mName; + } + return badLookup(); +} + +LLFolderType::EType LLViewerFolderType::lookupTypeFromXUIName(const std::string &name) +{ + return LLViewerFolderDictionary::getInstance()->lookup(name); +} + +const std::string &LLViewerFolderType::lookupIconName(LLFolderType::EType folder_type) +{ + const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type); + if (entry) + { + return entry->mIconName; + } + return badLookup(); +} + +const std::string &LLViewerFolderType::lookupNewCategoryName(LLFolderType::EType folder_type) +{ + const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type); + if (entry) + { + return entry->mNewCategoryName; + } + return badLookup(); +} + +LLFolderType::EType LLViewerFolderType::lookupTypeFromNewCategoryName(const std::string& name) +{ + for (LLViewerFolderDictionary::const_iterator iter = LLViewerFolderDictionary::getInstance()->begin(); + iter != LLViewerFolderDictionary::getInstance()->end(); + iter++) + { + const ViewerFolderEntry *entry = iter->second; + if (entry->mNewCategoryName == name) + { + return iter->first; + } + } + return FT_NONE; +} + + +U64 LLViewerFolderType::lookupValidFolderTypes(const std::string& item_name) +{ + U64 matching_folders = 0; + for (LLViewerFolderDictionary::const_iterator iter = LLViewerFolderDictionary::getInstance()->begin(); + iter != LLViewerFolderDictionary::getInstance()->end(); + iter++) + { + const ViewerFolderEntry *entry = iter->second; + if (entry->getIsAllowedName(item_name)) + { + matching_folders |= 1LL << iter->first; + } + } + return matching_folders; +} diff --git a/indra/newview/llviewerfoldertype.h b/indra/newview/llviewerfoldertype.h new file mode 100644 index 0000000000..a6aea62b2a --- /dev/null +++ b/indra/newview/llviewerfoldertype.h @@ -0,0 +1,57 @@ +/** + * @file llviewerfoldertype.h + * @brief Declaration of LLAssetType. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLVIEWERFOLDERTYPE_H +#define LL_LLVIEWERFOLDERTYPE_H + +#include <string> +#include "llfoldertype.h" + +// This class is similar to llfoldertype, but contains methods +// only used by the viewer. This also handles ensembles. +class LLViewerFolderType : public LLFolderType +{ +public: + static const std::string& lookupXUIName(EType folder_type); // name used by the UI + static LLFolderType::EType lookupTypeFromXUIName(const std::string& name); + + static const std::string& lookupIconName(EType asset_type); // folder icon name + static const std::string& lookupNewCategoryName(EType folder_type); // default name when creating new category + static LLFolderType::EType lookupTypeFromNewCategoryName(const std::string& name); // default name when creating new category + + static U64 lookupValidFolderTypes(const std::string& item_name); // which folders allow an item of this type? +protected: + LLViewerFolderType() {} + ~LLViewerFolderType() {} +}; + +#endif // LL_LLVIEWERFOLDERTYPE_H diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 366e5602bd..1d62ead843 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -37,7 +37,8 @@ #include "indra_constants.h" #include "llagent.h" -#include "llfoldertype.h" +#include "llviewerfoldertype.h" +#include "llfolderview.h" #include "llviewercontrol.h" #include "llconsole.h" #include "llinventorymodel.h" @@ -47,6 +48,7 @@ #include "llinventorybridge.h" #include "llfloaterinventory.h" +#include "llviewerassettype.h" #include "llviewerregion.h" #include "llviewerobjectlist.h" #include "llpreviewgesture.h" @@ -358,7 +360,7 @@ void LLViewerInventoryItem::updateParentOnServer(BOOL restamp) const LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& uuid, const LLUUID& parent_uuid, - LLAssetType::EType pref, + LLFolderType::EType pref, const std::string& name, const LLUUID& owner_id) : LLInventoryCategory(uuid, parent_uuid, pref, name), @@ -415,7 +417,7 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const { // communicate that change with the server. - if (LLAssetType::lookupIsProtectedCategoryType(mPreferredType)) + if (LLFolderType::lookupIsProtectedType(mPreferredType)) { LLNotifications::instance().add("CannotModifyProtectedCategories"); return; @@ -439,7 +441,7 @@ void LLViewerInventoryCategory::removeFromServer( void ) llinfos << "Removing inventory category " << mUUID << " from server." << llendl; // communicate that change with the server. - if(LLAssetType::lookupIsProtectedCategoryType(mPreferredType)) + if(LLFolderType::lookupIsProtectedType(mPreferredType)) { LLNotifications::instance().add("CannotRemoveProtectedCategories"); return; @@ -542,7 +544,7 @@ bool LLViewerInventoryCategory::importFileLocal(LLFILE* fp) } else if(0 == strcmp("pref_type", keyword)) { - mPreferredType = LLAssetType::lookup(valuestr); + mPreferredType = LLFolderType::lookup(valuestr); } else if(0 == strcmp("name", keyword)) { @@ -580,7 +582,7 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const mParentUUID.toString(uuid_str); fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str()); fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - fprintf(fp, "\t\tpref_type\t%s\n", LLAssetType::lookup(mPreferredType)); + fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str()); fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); mOwnerID.toString(uuid_str); fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str()); @@ -591,8 +593,8 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const void LLViewerInventoryCategory::determineFolderType() { - LLAssetType::EType original_type = getPreferredType(); - if (LLAssetType::lookupIsProtectedCategoryType(original_type)) + LLFolderType::EType original_type = getPreferredType(); + if (LLFolderType::lookupIsProtectedType(original_type)) return; U64 folder_valid = 0; @@ -615,28 +617,28 @@ void LLViewerInventoryCategory::determineFolderType() { const EWearableType wearable_type = item->getWearableType(); const std::string& wearable_name = LLWearableDictionary::getTypeName(wearable_type); - U64 valid_folder_types = LLFolderType::lookupValidFolderTypes(wearable_name); + U64 valid_folder_types = LLViewerFolderType::lookupValidFolderTypes(wearable_name); folder_valid |= valid_folder_types; folder_invalid |= ~valid_folder_types; } } - for (U8 i = LLAssetType::AT_FOLDER_ENSEMBLE_START; i <= LLAssetType::AT_FOLDER_ENSEMBLE_END; i++) + for (U8 i = LLFolderType::FT_ENSEMBLE_START; i <= LLFolderType::FT_ENSEMBLE_END; i++) { if ((folder_valid & (1LL << i)) && !(folder_invalid & (1LL << i))) { - changeType((LLAssetType::EType)i); + changeType((LLFolderType::EType)i); return; } } } - if (LLAssetType::lookupIsEnsembleCategoryType(original_type)) + if (LLFolderType::lookupIsEnsembleType(original_type)) { - changeType(LLAssetType::AT_NONE); + changeType(LLFolderType::FT_NONE); } } -void LLViewerInventoryCategory::changeType(LLAssetType::EType new_folder_type) +void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type) { const LLUUID &folder_id = getUUID(); const LLUUID &parent_id = getParentUUID(); @@ -947,7 +949,7 @@ void copy_inventory_from_notecard(const LLUUID& object_id, const LLUUID& notecar body["notecard-id"] = notecard_inv_id; body["object-id"] = object_id; body["item-id"] = src->getUUID(); - body["folder-id"] = gInventory.findCategoryUUIDForType(src->getType()); + body["folder-id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(src->getType())); body["callback-id"] = (LLSD::Integer)callback_id; request["message"] = "CopyInventoryFromNotecard"; @@ -963,7 +965,7 @@ void create_new_item(const std::string& name, U32 next_owner_perm) { std::string desc; - LLAssetType::generateDescriptionFor(asset_type, desc); + LLViewerAssetType::generateDescriptionFor(asset_type, desc); next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER; @@ -988,19 +990,14 @@ const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not) const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) +// ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) { - std::string type = userdata.asString(); + std::string type_name = userdata.asString(); - if (("category" == type) || ("current" == type) || ("outfit" == type) || ("my_otfts" == type) ) + if (("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name)) { - LLAssetType::EType a_type = LLAssetType::AT_NONE; - if ("current" == type) - a_type = LLAssetType::AT_CURRENT_OUTFIT; - if ("outfit" == type) - a_type = LLAssetType::AT_OUTFIT; - if ("my_otfts" == type) - a_type = LLAssetType::AT_MY_OUTFITS; + LLFolderType::EType preferred_type = LLFolderType::lookup(type_name); LLUUID parent_id; if (bridge) @@ -1016,100 +1013,100 @@ void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, co parent_id = gInventory.getRootFolderID(); } - LLUUID category = gInventory.createNewCategory(parent_id, a_type, LLStringUtil::null); + LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null); gInventory.notifyObservers(); folder->setSelectionByID(category, TRUE); } - else if ("lsl" == type) + else if ("lsl" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_LSL_TEXT); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_LSL_TEXT); create_new_item(NEW_LSL_NAME, parent_id, LLAssetType::AT_LSL_TEXT, LLInventoryType::IT_LSL, PERM_MOVE | PERM_TRANSFER); } - else if ("notecard" == type) + else if ("notecard" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_NOTECARD); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_NOTECARD); create_new_item(NEW_NOTECARD_NAME, parent_id, LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, PERM_ALL); } - else if ("gesture" == type) + else if ("gesture" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); create_new_item(NEW_GESTURE_NAME, parent_id, LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, PERM_ALL); } - else if ("shirt" == type) + else if ("shirt" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); LLFolderBridge::createWearable(parent_id, WT_SHIRT); } - else if ("pants" == type) + else if ("pants" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); LLFolderBridge::createWearable(parent_id, WT_PANTS); } - else if ("shoes" == type) + else if ("shoes" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); LLFolderBridge::createWearable(parent_id, WT_SHOES); } - else if ("socks" == type) + else if ("socks" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); LLFolderBridge::createWearable(parent_id, WT_SOCKS); } - else if ("jacket" == type) + else if ("jacket" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); LLFolderBridge::createWearable(parent_id, WT_JACKET); } - else if ("skirt" == type) + else if ("skirt" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); LLFolderBridge::createWearable(parent_id, WT_SKIRT); } - else if ("gloves" == type) + else if ("gloves" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); LLFolderBridge::createWearable(parent_id, WT_GLOVES); } - else if ("undershirt" == type) + else if ("undershirt" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); LLFolderBridge::createWearable(parent_id, WT_UNDERSHIRT); } - else if ("underpants" == type) + else if ("underpants" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); LLFolderBridge::createWearable(parent_id, WT_UNDERPANTS); } - else if ("shape" == type) + else if ("shape" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_BODYPART); LLFolderBridge::createWearable(parent_id, WT_SHAPE); } - else if ("skin" == type) + else if ("skin" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_BODYPART); LLFolderBridge::createWearable(parent_id, WT_SKIN); } - else if ("hair" == type) + else if ("hair" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_BODYPART); LLFolderBridge::createWearable(parent_id, WT_HAIR); } - else if ("eyes" == type) + else if ("eyes" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_BODYPART); LLFolderBridge::createWearable(parent_id, WT_EYES); } diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index d523bf2859..529425aa25 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -185,7 +185,7 @@ protected: public: LLViewerInventoryCategory(const LLUUID& uuid, const LLUUID& parent_uuid, - LLAssetType::EType preferred_type, + LLFolderType::EType preferred_type, const std::string& name, const LLUUID& owner_id); LLViewerInventoryCategory(const LLUUID& owner_id); @@ -221,7 +221,7 @@ public: bool exportFileLocal(LLFILE* fp) const; bool importFileLocal(LLFILE* fp); void determineFolderType(); - void changeType(LLAssetType::EType new_folder_type); + void changeType(LLFolderType::EType new_folder_type); protected: LLUUID mOwnerID; S32 mVersion; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 55e4f28e75..40bf9fb1fe 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -658,6 +658,8 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mMediaAutoScale(media_auto_scale), mMediaLoop(media_loop), mNeedsNewTexture(true), + mTextureUsedWidth(0), + mTextureUsedHeight(0), mSuspendUpdates(false), mVisible(true), mLastSetCursor( UI_CURSOR_ARROW ), @@ -1568,8 +1570,11 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() if (mNeedsNewTexture || placeholder_image->getUseMipMaps() - || placeholder_image->getWidth() != mMediaSource->getTextureWidth() - || placeholder_image->getHeight() != mMediaSource->getTextureHeight()) + || (placeholder_image->getWidth() != mMediaSource->getTextureWidth()) + || (placeholder_image->getHeight() != mMediaSource->getTextureHeight()) + || (mTextureUsedWidth > mMediaSource->getWidth()) + || (mTextureUsedHeight > mMediaSource->getHeight()) + ) { LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL; LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL; @@ -1601,6 +1606,11 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() // FIXME // placeholder_image->mIsMediaTexture = true; mNeedsNewTexture = false; + + // If the amount of the texture being drawn by the media goes down in either width or height, + // recreate the texture to avoid leaving parts of the old image behind. + mTextureUsedWidth = mMediaSource->getWidth(); + mTextureUsedHeight = mMediaSource->getHeight(); } return placeholder_image; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index d6dde0c93e..4cb0817735 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -306,6 +306,8 @@ public: bool mMediaAutoScale; bool mMediaLoop; bool mNeedsNewTexture; + S32 mTextureUsedWidth; + S32 mTextureUsedHeight; bool mSuspendUpdates; bool mVisible; ECursorType mLastSetCursor; diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index 657c58364f..70a7d835a3 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -77,6 +77,10 @@ void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 fac { old_media_impl->focus(false); } + + // Always clear the current selection. If we're setting focus on a face, we'll reselect the correct object below. + LLSelectMgr::getInstance()->deselectAll(); + mSelection = NULL; if (media_impl.notNull() && objectp.notNull()) { @@ -87,6 +91,9 @@ void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 fac mFocusedObjectFace = face; mFocusedObjectNormal = pick_normal; + // Set the selection in the selection manager so we can draw the focus ring. + mSelection = LLSelectMgr::getInstance()->selectObjectOnly(objectp, face); + // Focusing on a media face clears its disable flag. media_impl->setDisabled(false); @@ -492,8 +499,14 @@ void LLViewerMediaFocus::focusZoomOnMedia(LLUUID media_id) S32 face = obj->getFaceIndexWithMediaImpl(impl, -1); // We don't have a proper pick normal here, and finding a face's real normal is... complicated. - // For now, use +z to look at the top of the object. - LLVector3 normal(0.0f, 0.0f, 1.0f); + LLVector3 normal = obj->getApproximateFaceNormal(face); + if(normal.isNull()) + { + // If that didn't work, use the inverse of the camera "look at" axis, which should keep the camera pointed in the same direction. +// llinfos << "approximate face normal invalid, using camera direction." << llendl; + normal = LLViewerCamera::getInstance()->getAtAxis(); + normal *= (F32)-1.0f; + } // Attempt to focus/zoom on that face. setFocusFace(obj, face, impl, normal); diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index e5f36d341c..89ee0ae283 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -76,6 +76,7 @@ public: LLViewerMediaImpl* getFocusedMediaImpl(); LLViewerObject* getFocusedObject(); S32 getFocusedFace() { return mFocusedObjectFace; } + LLUUID getFocusedObjectID() { return mFocusedObjectID; } // These look up (by uuid) and return the values that were set with setHoverFace. They will return null if the objects have been destroyed. LLViewerMediaImpl* getHoverMediaImpl(); @@ -95,6 +96,7 @@ protected: private: LLHandle<LLPanelPrimMediaControls> mMediaControls; + LLObjectSelectionHandle mSelection; LLUUID mFocusedObjectID; S32 mFocusedObjectFace; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9da9ff5ce7..07d073c3a9 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -50,6 +50,7 @@ #include "llfocusmgr.h" #include "llfontgl.h" #include "llinstantmessage.h" +#include "llinventorypanel.h" #include "llpermissionsflags.h" #include "llrect.h" #include "llsecondlifeurls.h" @@ -145,7 +146,6 @@ #include "llmenucommands.h" #include "llmenugl.h" #include "llmimetypes.h" -#include "llmorphview.h" #include "llmoveview.h" #include "llmutelist.h" #include "llnotify.h" @@ -210,6 +210,7 @@ #include "lltexlayer.h" #include "llappearancemgr.h" +#include "llimfloater.h" using namespace LLVOAvatarDefines; @@ -609,6 +610,14 @@ class LLAdvancedToggleConsole : public view_listener_t { toggle_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) ); } + else if (gTextureSizeView && "texture size" == console_type) + { + toggle_visibility( (void*)gTextureSizeView ); + } + else if (gTextureCategoryView && "texture category" == console_type) + { + toggle_visibility( (void*)gTextureCategoryView ); + } else if ("fast timers" == console_type) { toggle_visibility( (void*)gDebugView->mFastTimerView ); @@ -636,6 +645,14 @@ class LLAdvancedCheckConsole : public view_listener_t { new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) ); } + else if (gTextureSizeView && "texture size" == console_type) + { + new_value = get_visibility( (void*)gTextureSizeView ); + } + else if (gTextureCategoryView && "texture category" == console_type) + { + new_value = get_visibility( (void*)gTextureCategoryView ); + } else if ("fast timers" == console_type) { new_value = get_visibility( (void*)gDebugView->mFastTimerView ); @@ -1160,28 +1177,6 @@ class LLAdvancedCheckWireframe : public view_listener_t }; ////////////////////// -// DISABLE TEXTURES // -////////////////////// - -class LLAdvancedToggleDisableTextures : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLViewerTexture::sDontLoadVolumeTextures = !LLViewerTexture::sDontLoadVolumeTextures; - return true; - } -}; - -class LLAdvancedCheckDisableTextures : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLViewerTexture::sDontLoadVolumeTextures; // <-- make this using LLCacheControl - return new_value; - } -}; - -////////////////////// // TEXTURE ATLAS // ////////////////////// @@ -1884,7 +1879,7 @@ class LLAdvancedRebakeTextures : public view_listener_t }; -#ifndef LL_RELEASE_FOR_DOWNLOAD +#if 1 //ndef LL_RELEASE_FOR_DOWNLOAD /////////////////////////// // DEBUG AVATAR TEXTURES // /////////////////////////// @@ -2522,24 +2517,12 @@ class LLObjectEnableTouch : public view_listener_t // label.assign("Touch"); // } //} -/* -bool handle_object_open() -{ - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if(!obj) return true; - LLFloaterOpenObject::show(); - return true; +void handle_object_open() +{ + LLFloaterReg::showInstance("openobject"); } -class LLObjectOpen : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - return handle_object_open(); - } -}; -*/ bool enable_object_open() { // Look for contents in root object, which is all the LLFloaterOpenObject @@ -2647,8 +2630,22 @@ void handle_object_edit() // Could be first use LLFirstUse::useBuild(); return; - } + +void handle_object_inspect() +{ + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + LLViewerObject* selected_objectp = selection->getFirstRootObject(); + if (selected_objectp) + { + LLSD key; + key["task"] = "task"; + LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); + } + + LLFloaterReg::showInstance("inspect", LLSD()); +} + //--------------------------------------------------------------------------- // Land pie menu //--------------------------------------------------------------------------- @@ -3442,26 +3439,13 @@ void handle_show_side_tray() root->addChild(side_tray); } -class LLSelfFriends : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - // Open "Friends" tab of the "People" panel in side tray. - LLSD param; - param["people_panel_tab_name"] = "friends_panel"; - - LLSideTray::getInstance()->showPanel("panel_people", param); - return true; - } -}; - -class LLSelfGroups : public view_listener_t +class LLShowPanelPeopleTab : public view_listener_t { bool handleEvent(const LLSD& userdata) { - // Open "Groups" tab of the "People" panel in side tray. + // Open tab of the "People" panel in side tray. LLSD param; - param["people_panel_tab_name"] = "groups_panel"; + param["people_panel_tab_name"] = userdata.asString(); LLSideTray::getInstance()->showPanel("panel_people", param); return true; } @@ -3496,9 +3480,8 @@ void set_god_level(U8 god_level) gAgent.setGodLevel( god_level ); LLViewerParcelMgr::getInstance()->notifyObservers(); - // God mode changes sim visibility - LLWorldMap::getInstance()->reset(); - LLWorldMap::getInstance()->setCurrentLayer(0); + // God mode changes region visibility + LLWorldMap::getInstance()->reloadItems(true); // inventory in items may change in god mode gObjectList.dirtyAllObjectInventory(); @@ -4175,12 +4158,10 @@ void handle_take_copy() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; - LLUUID category_id = - gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); + const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); } - // You can return an object to its owner if it is on your land. class LLObjectReturn : public view_listener_t { @@ -4261,7 +4242,7 @@ class LLObjectEnableReturn : public view_listener_t void force_take_copy(void*) { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; - const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); + const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id); } @@ -4322,8 +4303,7 @@ void handle_take() if(category_id.notNull()) { // check trash - LLUUID trash; - trash = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash)) { category_id.setNull(); @@ -4339,7 +4319,7 @@ void handle_take() } if(category_id.isNull()) { - category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); + category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); } LLSD payload; payload["folder_id"] = category_id; @@ -5213,7 +5193,7 @@ void show_debug_menus() gMenuBarView->setItemEnabled("Develop", qamode); // Server ('Admin') menu hidden when not in godmode. - const bool show_server_menu = debug && (gAgent.getGodLevel() > GOD_NOT); + const bool show_server_menu = debug && (gAgent.getGodLevel() > GOD_NOT || gAgent.getAdminOverride()); gMenuBarView->setItemVisible("Admin", show_server_menu); gMenuBarView->setItemEnabled("Admin", show_server_menu); } @@ -6281,9 +6261,13 @@ class LLAvatarSendIM : public view_listener_t //EInstantMessage type = have_agent_callingcard(gLastHitObjectID) // ? IM_SESSION_ADD : IM_SESSION_CARDLESS_START; - gIMMgr->addSession(name, + LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, avatar->getID()); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } } return true; } @@ -6918,7 +6902,7 @@ void handle_grab_texture(void* data) LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << llendl; LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE; LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE; - LLUUID folder_id(gInventory.findCategoryUUIDForType(asset_type)); + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type)); if(folder_id.notNull()) { std::string name = "Unknown"; @@ -7460,52 +7444,10 @@ class LLEditEnableTakeOff : public view_listener_t bool handleEvent(const LLSD& userdata) { std::string clothing = userdata.asString(); - bool new_value = false; - if (clothing == "shirt") - { - new_value = LLAgentWearables::selfHasWearable(WT_SHIRT); - } - if (clothing == "pants") - { - new_value = LLAgentWearables::selfHasWearable(WT_PANTS); - } - if (clothing == "shoes") - { - new_value = LLAgentWearables::selfHasWearable(WT_SHOES); - } - if (clothing == "socks") - { - new_value = LLAgentWearables::selfHasWearable(WT_SOCKS); - } - if (clothing == "jacket") - { - new_value = LLAgentWearables::selfHasWearable(WT_JACKET); - } - if (clothing == "gloves") - { - new_value = LLAgentWearables::selfHasWearable(WT_GLOVES); - } - if (clothing == "undershirt") - { - new_value = LLAgentWearables::selfHasWearable(WT_UNDERSHIRT); - } - if (clothing == "underpants") - { - new_value = LLAgentWearables::selfHasWearable(WT_UNDERPANTS); - } - if (clothing == "skirt") - { - new_value = LLAgentWearables::selfHasWearable(WT_SKIRT); - } - if (clothing == "alpha") - { - new_value = LLAgentWearables::selfHasWearable(WT_ALPHA); - } - if (clothing == "tattoo") - { - new_value = LLAgentWearables::selfHasWearable(WT_TATTOO); - } - return new_value; + EWearableType type = LLWearableDictionary::typeNameToType(clothing); + if (type >= WT_SHAPE && type < WT_COUNT) + return LLAgentWearables::selfHasWearable(type); + return false; } }; @@ -7514,53 +7456,13 @@ class LLEditTakeOff : public view_listener_t bool handleEvent(const LLSD& userdata) { std::string clothing = userdata.asString(); - if (clothing == "shirt") - { - LLAgentWearables::userRemoveWearable((void*)WT_SHIRT); - } - else if (clothing == "pants") - { - LLAgentWearables::userRemoveWearable((void*)WT_PANTS); - } - else if (clothing == "shoes") - { - LLAgentWearables::userRemoveWearable((void*)WT_SHOES); - } - else if (clothing == "socks") - { - LLAgentWearables::userRemoveWearable((void*)WT_SOCKS); - } - else if (clothing == "jacket") - { - LLAgentWearables::userRemoveWearable((void*)WT_JACKET); - } - else if (clothing == "gloves") - { - LLAgentWearables::userRemoveWearable((void*)WT_GLOVES); - } - else if (clothing == "undershirt") - { - LLAgentWearables::userRemoveWearable((void*)WT_UNDERSHIRT); - } - else if (clothing == "underpants") - { - LLAgentWearables::userRemoveWearable((void*)WT_UNDERPANTS); - } - else if (clothing == "skirt") - { - LLAgentWearables::userRemoveWearable((void*)WT_SKIRT); - } - else if (clothing == "alpha") - { - LLAgentWearables::userRemoveWearable((void*)WT_ALPHA); - } - else if (clothing == "tattoo") - { - LLAgentWearables::userRemoveWearable((void*)WT_TATTOO); - } - else if (clothing == "all") + if (clothing == "all") + LLAgentWearables::userRemoveAllClothes(); + else { - LLAgentWearables::userRemoveAllClothes(NULL); + EWearableType type = LLWearableDictionary::typeNameToType(clothing); + if (type >= WT_SHAPE && type < WT_COUNT) + LLAgentWearables::userRemoveWearable(type); } return true; } @@ -7875,8 +7777,6 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo"); view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe"); view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe"); - view_listener_t::addMenu(new LLAdvancedToggleDisableTextures(), "Advanced.ToggleDisableTextures"); - view_listener_t::addMenu(new LLAdvancedCheckDisableTextures(), "Advanced.CheckDisableTextures"); view_listener_t::addMenu(new LLAdvancedToggleTextureAtlas(), "Advanced.ToggleTextureAtlas"); view_listener_t::addMenu(new LLAdvancedCheckTextureAtlas(), "Advanced.CheckTextureAtlas"); view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion"); @@ -8025,8 +7925,7 @@ void initialize_menus() 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 LLSelfFriends(), "Self.Friends"); - view_listener_t::addMenu(new LLSelfGroups(), "Self.Groups"); + view_listener_t::addMenu( new LLShowPanelPeopleTab(), "SideTray.PanelPeopleTab"); // Avatar pie menu view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute"); @@ -8061,6 +7960,8 @@ void initialize_menus() commit.add("Object.Buy", boost::bind(&handle_buy)); commit.add("Object.Edit", boost::bind(&handle_object_edit)); + 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)); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index b65878b5e6..db4eb3be9d 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -94,6 +94,7 @@ void handle_sit_down(void*); void handle_object_build(void*); void handle_object_touch(); bool enable_object_open(); +void handle_object_open(); // Buy either contents or object itself void handle_buy(); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index d3a9e1cef8..d17c7e486f 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -319,7 +319,7 @@ class LLFileUploadBulk : public view_listener_t LLAssetStorage::LLStoreAssetCallback callback = NULL; S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); void *userdata = NULL; - upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, + upload_new_resource(filename, asset_name, asset_name, 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), display_name, callback, expected_upload_cost, userdata); @@ -493,7 +493,7 @@ void handle_compress_image(void*) void upload_new_resource(const std::string& src_filename, std::string name, std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, + LLFolderType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, @@ -810,7 +810,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt if(result >= 0) { - LLAssetType::EType dest_loc = (data->mPreferredLocation == LLAssetType::AT_NONE) ? data->mAssetInfo.mType : data->mPreferredLocation; + 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 || @@ -856,7 +856,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt { // Actually add the upload to inventory llinfos << "Adding " << uuid << " to inventory." << llendl; - LLUUID folder_id(gInventory.findCategoryUUIDForType(dest_loc)); + const LLUUID folder_id = gInventory.findCategoryUUIDForType(dest_loc); if(folder_id.notNull()) { U32 next_owner_perms = data->mNextOwnerPerm; @@ -903,7 +903,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt LLAssetStorage::LLStoreAssetCallback callback = NULL; void *userdata = NULL; upload_new_resource(next_file, asset_name, asset_name, // file - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, PERM_NONE, PERM_NONE, PERM_NONE, display_name, callback, @@ -915,7 +915,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, std::string name, std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, + LLFolderType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, @@ -973,14 +973,14 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty llinfos << "Name: " << name << llendl; llinfos << "Desc: " << desc << llendl; llinfos << "Expected Upload Cost: " << expected_upload_cost << llendl; - lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type) << llendl; + lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type) << llendl; lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); if (!url.empty()) { llinfos << "New Agent Inventory via capability" << llendl; LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type); + body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type); body["asset_type"] = LLAssetType::lookup(asset_type); body["inventory_type"] = LLInventoryType::lookup(inv_type); body["name"] = name; diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index bf21292082..da78537a29 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -33,7 +33,7 @@ #ifndef LLVIEWERMENUFILE_H #define LLVIEWERMENUFILE_H -#include "llassettype.h" +#include "llfoldertype.h" #include "llinventorytype.h" class LLTransactionID; @@ -45,7 +45,7 @@ void upload_new_resource(const std::string& src_filename, std::string name, std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, + LLFolderType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, @@ -60,7 +60,7 @@ void upload_new_resource(const LLTransactionID &tid, std::string name, std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, + LLFolderType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index caa668836d..ea1097c477 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -89,6 +89,7 @@ #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llinventorymodel.h" +#include "llinventorypanel.h" #include "llfloaterinventory.h" #include "llmenugl.h" #include "llmoveview.h" @@ -208,7 +209,6 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = bool friendship_offer_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotification::getSelectedOption(notification, response); - LLUUID fid; LLMessageSystem* msg = gMessageSystem; const LLSD& payload = notification["payload"]; @@ -218,10 +218,11 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) switch(option) { case 0: + { // accept LLAvatarTracker::formFriendship(payload["from_id"]); - fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + const LLUUID fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); // This will also trigger an onlinenotification if the user is online msg->newMessageFast(_PREHASH_AcceptFriendship); @@ -234,7 +235,9 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) msg->addUUIDFast(_PREHASH_FolderID, fid); msg->sendReliable(LLHost(payload["sender"].asString())); break; + } case 1: + { // decline // We no longer notify other viewers, but we DO still send // the rejection to the simulator to delete the pending userop. @@ -246,6 +249,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); msg->sendReliable(LLHost(payload["sender"].asString())); break; + } default: // close button probably, possibly timed out break; @@ -766,8 +770,7 @@ public: virtual void done() { LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL; - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); bool notify = false; if(trash_id.notNull() && mObjectID.notNull()) { @@ -874,7 +877,7 @@ void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) { std::vector<LLUUID>::const_iterator it = items.begin(); std::vector<LLUUID>::const_iterator end = items.end(); - LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH)); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); LLInventoryItem* item; for(; it != end; ++it) { @@ -945,13 +948,12 @@ void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) } //Trash Check - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) { return; } - LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); //BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view); BOOL user_is_away = gAwayTimer.getStarted(); @@ -1715,7 +1717,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) info->mFromGroup = from_group; info->mTransactionID = session_id; info->mType = (LLAssetType::EType) asset_type; - info->mFolderID = gInventory.findCategoryUUIDForType(info->mType); + info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType)); std::string from_name; from_name += "A group member named "; @@ -1849,7 +1851,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) info->mFromID = from_id; info->mFromGroup = from_group; info->mTransactionID = session_id; - info->mFolderID = gInventory.findCategoryUUIDForType(info->mType); + info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType)); if (dialog == IM_TASK_INVENTORY_OFFERED) { @@ -2143,7 +2145,7 @@ bool callingcard_offer_callback(const LLSD& notification, const LLSD& response) msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_TransactionBlock); msg->addUUIDFast(_PREHASH_TransactionID, notification["payload"]["transaction_id"].asUUID()); - fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); msg->nextBlockFast(_PREHASH_FolderData); msg->addUUIDFast(_PREHASH_FolderID, fid); msg->sendReliable(LLHost(notification["payload"]["sender"].asString())); @@ -2596,11 +2598,10 @@ BOOL LLPostTeleportNotifiers::tick() { // get callingcards and landmarks available to the user arriving. LLInventoryFetchDescendentsObserver::folder_ref_t folders; - LLUUID folder_id; - folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); - if(folder_id.notNull()) - folders.push_back(folder_id); - folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + const LLUUID callingcard_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); + if(callingcard_id.notNull()) + folders.push_back(callingcard_id); + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); if(folder_id.notNull()) folders.push_back(folder_id); if(!folders.empty()) @@ -2913,46 +2914,37 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) if (!gLastVersionChannel.empty()) { - LLSD payload; - payload["message"] = version_channel; - LLNotifications::instance().add("ServerVersionChanged", LLSD(), payload, server_version_changed_callback); - } - - gLastVersionChannel = version_channel; -} - -bool server_version_changed_callback(const LLSD& notification, const LLSD& response) -{ - if(notification["payload"]["message"].asString() =="") - return false; - std::string url ="http://wiki.secondlife.com/wiki/Release_Notes/"; - //parse the msg string - std::string server_version = notification["payload"]["message"].asString(); - std::vector<std::string> s_vect; - boost::algorithm::split(s_vect, server_version, isspace); - for(U32 i = 0; i < s_vect.size(); i++) - { - if (i != (s_vect.size() - 1)) + // work out the URL for this server's Release Notes + std::string url ="http://wiki.secondlife.com/wiki/Release_Notes/"; + std::string server_version = version_channel; + std::vector<std::string> s_vect; + boost::algorithm::split(s_vect, server_version, isspace); + for(U32 i = 0; i < s_vect.size(); i++) { - if(i != (s_vect.size() - 2)) + if (i != (s_vect.size() - 1)) { - url += s_vect[i] + "_"; + if(i != (s_vect.size() - 2)) + { + url += s_vect[i] + "_"; + } + else + { + url += s_vect[i] + "/"; + } } else { - url += s_vect[i] + "/"; + url += s_vect[i].substr(0,4); } } - else - { - url += s_vect[i].substr(0,4); - } + + LLSD args; + args["URL"] = url; + LLNotifications::instance().add("ServerVersionChanged", args); } - - LLWeb::loadURL(url); - return false; -} + gLastVersionChannel = version_channel; +} void process_crossed_region(LLMessageSystem* msg, void**) { @@ -4818,7 +4810,7 @@ void container_inventory_arrived(LLViewerObject* object, // create a new inventory category to put this in LLUUID cat_id; cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(), - LLAssetType::AT_NONE, + LLFolderType::FT_NONE, LLTrans::getString("AcquiredItems")); InventoryObjectList::const_iterator it = inventory->begin(); @@ -4868,7 +4860,7 @@ void container_inventory_arrived(LLViewerObject* object, } LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); - LLUUID category = gInventory.findCategoryUUIDForType(item->getType()); + const LLUUID category = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType())); LLUUID item_id; item_id.generate(); diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index c15e5df675..e24da2013d 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -132,7 +132,6 @@ void container_inventory_arrived(LLViewerObject* object, // agent movement void send_complete_agent_movement(const LLHost& sim_host); void process_agent_movement_complete(LLMessageSystem* msg, void**); -bool server_version_changed_callback(const LLSD& notification, const LLSD& response); void process_crossed_region(LLMessageSystem* msg, void**); void process_teleport_start(LLMessageSystem* msg, void**); void process_teleport_progress(LLMessageSystem* msg, void**); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 20cd516fa0..e491e11960 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2906,7 +2906,7 @@ F32 LLViewerObject::getMidScale() const } -void LLViewerObject::updateTextures(LLAgent &agent) +void LLViewerObject::updateTextures() { } @@ -2928,7 +2928,7 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); LLUUID sculpt_id = sculpt_params->getSculptTexture(); - LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); + LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); } if (boost_children) @@ -3691,7 +3691,7 @@ void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) // if (mDrawable.notNull() && mDrawable->isVisible()) // { const LLUUID& image_id = getTE(te)->getID(); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); // } } @@ -3717,7 +3717,7 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos uuid == LLUUID::null) { retval = LLPrimitive::setTETexture(te, uuid); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); + mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); setChanged(TEXTURE); if (mDrawable.notNull()) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index b8ae31118c..01b213a87d 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -199,7 +199,7 @@ public: S32 getNumFaces() const { return mNumFaces; } // Graphical stuff for objects - maybe broken out into render class later? - virtual void updateTextures(LLAgent &agent); + virtual void updateTextures(); virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object virtual LLDrawable* createDrawable(LLPipeline *pipeline); diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 2927ca5292..96828ee1b6 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -642,7 +642,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) // Update distance & gpw objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area - objectp->updateTextures(agent); // Update the image levels of textures for this object. + objectp->updateTextures(); // Update the image levels of textures for this object. } } @@ -1074,6 +1074,7 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap) LLColor4 group_own_below_water_color = LLUIColorTable::instance().getColor( "NetMapGroupOwnBelowWater" ); + F32 max_radius = gSavedSettings.getF32("MiniMapPrimMaxRadius"); for (S32 i = 0; i < mMapObjects.count(); i++) { @@ -1089,6 +1090,11 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap) F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f; // 1.3 is a fudge + // Limit the size of megaprims so they don't blot out everything on the minimap. + // Attempting to draw very large megaprims also causes client lag. + // See DEV-17370 and DEV-29869/SNOW-79 for details. + approx_radius = llmin(approx_radius, max_radius); + LLColor4U color = above_water_color; if( objectp->permYouOwner() ) { diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 7ea55b49e8..d1c9840a97 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1427,11 +1427,11 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); capabilityNames.append("FetchInventory"); - capabilityNames.append("WebFetchInventoryDescendents"); capabilityNames.append("ObjectMedia"); capabilityNames.append("ObjectMediaNavigate"); capabilityNames.append("FetchLib"); capabilityNames.append("FetchLibDescendents"); + capabilityNames.append("GetTexture"); capabilityNames.append("GroupProposalBallot"); capabilityNames.append("HomeLocation"); capabilityNames.append("MapLayer"); @@ -1452,6 +1452,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("SendUserReportWithScreenshot"); capabilityNames.append("ServerReleaseNotes"); capabilityNames.append("StartGroupProposal"); + capabilityNames.append("TextureStats"); capabilityNames.append("UntrustedSimulatorMessage"); capabilityNames.append("UpdateAgentInformation"); capabilityNames.append("UpdateAgentLanguage"); @@ -1464,6 +1465,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("UploadBakedTexture"); capabilityNames.append("ViewerStartAuction"); capabilityNames.append("ViewerStats"); + capabilityNames.append("WebFetchInventoryDescendents"); // Please add new capabilities alphabetically to reduce // merge conflicts. diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 6e07d8f246..caa94dba38 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -560,12 +560,18 @@ extern U32 gVisCompared; extern U32 gVisTested; std::map<S32,LLFrameTimer> gDebugTimers; +std::map<S32,std::string> gDebugTimerLabel; + +void init_statistics() +{ + // Label debug timers + gDebugTimerLabel[0] = "Texture"; +} void update_statistics(U32 frame_count) { gTotalWorldBytes += gVLManager.getTotalBytes(); gTotalObjectBytes += gObjectBits / 8; - gTotalTextureBytes += gTextureList.mTextureBits / 8; // make sure we have a valid time delta for this frame if (gFrameIntervalSeconds > 0.f) @@ -617,7 +623,6 @@ void update_statistics(U32 frame_count) F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits()); LLViewerStats::getInstance()->mLayersKBitStat.addValue(layer_bits/1024.f); LLViewerStats::getInstance()->mObjectKBitStat.addValue(gObjectBits/1024.f); - LLViewerStats::getInstance()->mTextureKBitStat.addValue(gTextureList.mTextureBits/1024.f); LLViewerStats::getInstance()->mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending()); LLViewerStats::getInstance()->mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f); gTransferManager.resetTransferBitsIn(LLTCT_ASSET); @@ -631,8 +636,6 @@ void update_statistics(U32 frame_count) gDebugTimers[0].unpause(); } - LLViewerStats::getInstance()->mTexturePacketsStat.addValue(gTextureList.mTexturePackets); - { static F32 visible_avatar_frames = 0.f; static F32 avg_visible_avatars = 0; @@ -652,8 +655,20 @@ void update_statistics(U32 frame_count) gObjectBits = 0; // gDecodedBits = 0; - gTextureList.mTextureBits = 0; - gTextureList.mTexturePackets = 0; + // Only update texture stats ones per second so that they are less noisy + { + static const F32 texture_stats_freq = 1.f; + static LLFrameTimer texture_stats_timer; + if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) + { + LLViewerStats::getInstance()->mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); + LLViewerStats::getInstance()->mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets); + gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8; + LLViewerTextureList::sTextureBits = 0; + LLViewerTextureList::sTexturePackets = 0; + texture_stats_timer.reset(); + } + } } @@ -826,3 +841,4 @@ void send_stats() LLViewerStats::getInstance()->addToMessage(body); LLHTTPClient::post(url, body, new ViewerStatsResponder()); } + diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index ba89fbf02a..13d73000d2 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -34,6 +34,7 @@ #define LL_LLVIEWERSTATS_H #include "llstat.h" +#include "lltextureinfo.h" class LLViewerStats : public LLSingleton<LLViewerStats> { @@ -205,10 +206,13 @@ private: static const F32 SEND_STATS_PERIOD = 300.0f; // The following are from (older?) statistics code found in appviewer. +void init_statistics(); void reset_statistics(); void output_statistics(void*); void update_statistics(U32 frame_count); void send_stats(); extern std::map<S32,LLFrameTimer> gDebugTimers; +extern std::map<S32,std::string> gDebugTimerLabel; + #endif // LL_LLVIEWERSTATS_H diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 5c40f2a540..6f8818be6e 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -62,6 +62,7 @@ #include "lltooltip.h" #include "lltrans.h" #include "lluictrlfactory.h" +#include "llviewerassettype.h" #include "llviewercontrol.h" #include "llviewerinventory.h" #include "llviewertexturelist.h" @@ -170,7 +171,7 @@ public: mToolTip = inv_item->getName() + '\n' + inv_item->getDescription(); } - /*virtual*/ void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const + /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { if (num_chars == 0) { @@ -182,12 +183,29 @@ public: width = EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidth(mLabel.c_str()); height = llmax(mImage->getHeight(), llceil(mStyle->getFont()->getLineHeight())); } - + return false; } /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { - return 1; + // always draw at beginning of line + if (line_offset == 0) + { + return 1; + } + else + { + S32 width, height; + getDimensions(mStart, 1, width, height); + if (width > num_pixels) + { + return 0; + } + else + { + return 1; + } + } } /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { @@ -207,7 +225,7 @@ public: } F32 right_x; - mStyle->getFont()->render(mLabel, 0, image_rect.mRight + EMBEDDED_ITEM_LABEL_PADDING, draw_rect.mBottom, color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::UNDERLINE, LLFontGL::NO_SHADOW, mLabel.length(), S32_MAX, &right_x); + mStyle->getFont()->render(mLabel, 0, image_rect.mRight + EMBEDDED_ITEM_LABEL_PADDING, draw_rect.mTop, color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::UNDERLINE, LLFontGL::NO_SHADOW, mLabel.length(), S32_MAX, &right_x); return right_x; } @@ -505,19 +523,17 @@ LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const } break; - case LLAssetType::AT_SOUND: img_name = "Inv_Sound"; break; + case LLAssetType::AT_SOUND: img_name = "Inv_Sound"; break; case LLAssetType::AT_CLOTHING: img_name = "Inv_Clothing"; break; - case LLAssetType::AT_OBJECT: img_name = "Inv_Object"; break; + case LLAssetType::AT_OBJECT: img_name = "Inv_Object"; break; case LLAssetType::AT_CALLINGCARD: img_name = "Inv_CallingCard"; break; - case LLAssetType::AT_LANDMARK: img_name = "Inv_Landmark"; break; + case LLAssetType::AT_LANDMARK: img_name = "Inv_Landmark"; break; case LLAssetType::AT_NOTECARD: img_name = "Inv_Notecard"; break; case LLAssetType::AT_LSL_TEXT: img_name = "Inv_Script"; break; - case LLAssetType::AT_BODYPART: img_name = "Inv_Skin"; break; - case LLAssetType::AT_ANIMATION: img_name = "Inv_Animation";break; - case LLAssetType::AT_GESTURE: img_name = "Inv_Gesture"; break; - //TODO need img_name - case LLAssetType::AT_FAVORITE: img_name = "Inv_Landmark"; break; - default: llassert(0); + case LLAssetType::AT_BODYPART: img_name = "Inv_Skin"; break; + case LLAssetType::AT_ANIMATION: img_name = "Inv_Animation"; break; + case LLAssetType::AT_GESTURE: img_name = "Inv_Gesture"; break; + default: llassert(0); } return LLUI::getUIImage(img_name); @@ -732,11 +748,10 @@ BOOL LLViewerTextEditor::handleHover(S32 x, S32 y, MASK mask) if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) { LLToolDragAndDrop::getInstance()->beginDrag( - LLAssetType::lookupDragAndDropType( mDragItem->getType() ), + LLViewerAssetType::lookupDragAndDropType( mDragItem->getType() ), mDragItem->getUUID(), LLToolDragAndDrop::SOURCE_NOTECARD, mPreviewID, mObjectID); - return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); } getWindow()->setCursor(UI_CURSOR_HAND); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 758bf8c1aa..9923c9ac74 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -60,6 +60,8 @@ #include "llviewercontrol.h" #include "pipeline.h" #include "llappviewer.h" +#include "llface.h" +#include "llviewercamera.h" #include "lltextureatlas.h" #include "lltextureatlasmanager.h" #include "lltextureentry.h" @@ -88,7 +90,15 @@ S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0; S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0; S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0; S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ; -BOOL LLViewerTexture::sDontLoadVolumeTextures = FALSE; +S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ; +S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size +const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ; +const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ; +const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128 ; +S32 LLViewerTexture::sMinLargeImageSize = 65536 ; //256 * 256. +S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ; +BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ; +F32 LLViewerTexture::sCurrentTime = 0.0f ; BOOL LLViewerTexture::sUseTextureAtlas = FALSE ; const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by @@ -162,6 +172,7 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(BOOL usemipma if(generate_gl_tex) { tex->generateGLTexture() ; + tex->setCategory(LLViewerTexture::LOCAL) ; } return tex ; } @@ -171,12 +182,14 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLUUID& if(generate_gl_tex) { tex->generateGLTexture() ; + tex->setCategory(LLViewerTexture::LOCAL) ; } return tex ; } LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) { LLPointer<LLViewerTexture> tex = new LLViewerTexture(raw, usemipmaps) ; + tex->setCategory(LLViewerTexture::LOCAL) ; return tex ; } LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex) @@ -185,6 +198,7 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid if(generate_gl_tex) { tex->generateGLTexture() ; + tex->setCategory(LLViewerTexture::LOCAL) ; } return tex ; } @@ -198,6 +212,7 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( LLGLenum primary_format, LLHost request_from_host) { + llassert_always(boost_priority >= LLViewerTexture::BOOST_NONE) ; return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; } @@ -210,9 +225,23 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( LLGLenum primary_format, const LLUUID& force_id) { + llassert_always(boost_priority >= LLViewerTexture::BOOST_NONE) ; return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; } +//static +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url, + BOOL usemipmaps, + S32 boost_priority, + S8 texture_type, + LLGLint internal_format, + LLGLenum primary_format, + const LLUUID& force_id + ) +{ + return gTextureList.getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; +} + LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) { return gTextureList.getImageFromHost(image_id, host) ; @@ -254,12 +283,13 @@ void LLViewerTextureManager::init() } imagep->createGLTexture(0, image_raw); image_raw = NULL; - LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); #else - LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE); + LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI); #endif - - LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, TRUE); + LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); + LLViewerFetchedTexture::sDefaultImagep->setCategory(LLViewerTexture::OTHER) ; + + LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI); LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ; LLViewerTexture::initClass() ; @@ -282,6 +312,8 @@ void LLViewerTextureManager::cleanup() LLViewerFetchedTexture::sWhiteImagep = NULL; LLViewerMediaTexture::cleanup() ; + + LLViewerTexture::cleanupClass() ; } //---------------------------------------------------------------------------------------------- @@ -292,6 +324,11 @@ void LLViewerTextureManager::cleanup() void LLViewerTexture::initClass() { LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ; + + if(gAuditTexture) + { + LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ; + } } // static @@ -299,6 +336,25 @@ void LLViewerTexture::cleanupClass() { } +// static +S32 LLViewerTexture::getTotalNumOfCategories() +{ + return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ; +} + +// static +//index starts from zero. +S32 LLViewerTexture::getIndexFromCategory(S32 category) +{ + return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ; +} + +//static +S32 LLViewerTexture::getCategoryFromIndex(S32 index) +{ + return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ; +} + // tuning params const F32 discard_bias_delta = .05f; const F32 discard_delta_time = 0.5f; @@ -310,6 +366,8 @@ F32 texmem_middle_bound_scale = 0.925f; //static void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity) { + sCurrentTime = gFrameTimeSeconds ; + if(LLViewerTextureManager::sTesterp) { LLViewerTextureManager::sTesterp->update() ; @@ -350,6 +408,13 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max); LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ; + + F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; + F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); + sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ; + + LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && + (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ; } //end of static functions @@ -415,7 +480,9 @@ void LLViewerTexture::init(bool firstinit) mTextureState = NO_DELETE ; mDontDiscard = FALSE; mMaxVirtualSize = 0.f; + mNeedsGLTexture = FALSE ; mNeedsResetMaxVirtualSize = FALSE ; + mAdditionalDecodePriority = 0.f ; mParcelMedia = NULL ; } @@ -457,11 +524,15 @@ void LLViewerTexture::setBoostLevel(S32 level) { setNoDelete() ; } + if(gAuditTexture) + { + setCategory(mBoostLevel); + } } } -bool LLViewerTexture::bindDefaultImage(S32 stage) const +bool LLViewerTexture::bindDefaultImage(S32 stage) { if (stage < 0) return false; @@ -480,6 +551,10 @@ bool LLViewerTexture::bindDefaultImage(S32 stage) const llwarns << "LLViewerTexture::bindDefaultImage failed." << llendl; } stop_glerror(); + + //check if there is cached raw image and switch to it if possible + switchToCachedImage() ; + if(LLViewerTextureManager::sTesterp) { LLViewerTextureManager::sTesterp->updateGrayTextureBinding() ; @@ -498,24 +573,32 @@ void LLViewerTexture::forceImmediateUpdate() { } -void LLViewerTexture::addTextureStats(F32 virtual_size) const +void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const { - if (virtual_size > mMaxVirtualSize) + if(needs_gltexture) { - mMaxVirtualSize = virtual_size; + mNeedsGLTexture = TRUE ; } -} -void LLViewerTexture::resetTextureStats(BOOL zero) -{ - if (zero) + if(mNeedsResetMaxVirtualSize) { - mMaxVirtualSize = 0.0f; + //flag to reset the values because the old values are used. + mNeedsResetMaxVirtualSize = FALSE ; + mMaxVirtualSize = virtual_size; + mAdditionalDecodePriority = 0.f ; + mNeedsGLTexture = needs_gltexture ; } - else + else if (virtual_size > mMaxVirtualSize) { - mMaxVirtualSize -= mMaxVirtualSize * .10f; // decay by 5%/update - } + mMaxVirtualSize = virtual_size; + } +} + +void LLViewerTexture::resetTextureStats() +{ + mMaxVirtualSize = 0.0f; + mAdditionalDecodePriority = 0.f ; + mNeedsResetMaxVirtualSize = FALSE ; } //virtual @@ -542,6 +625,12 @@ void LLViewerTexture::removeFace(LLFace* facep) mFaceList.remove(facep) ; } +//virtual +void LLViewerTexture::switchToCachedImage() +{ + //nothing here. +} + void LLViewerTexture::forceActive() { mTextureState = ACTIVE ; @@ -586,11 +675,11 @@ BOOL LLViewerTexture::createGLTexture() return mGLTexturep->createGLTexture() ; } -BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename) +BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category) { llassert_always(mGLTexturep.notNull()) ; - BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename) ; + BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ; if(ret) { @@ -702,6 +791,13 @@ void LLViewerTexture::setGLTextureCreated (bool initialized) mGLTexturep->setGLTextureCreated (initialized) ; } +void LLViewerTexture::setCategory(S32 category) +{ + llassert_always(mGLTexturep.notNull()) ; + + mGLTexturep->setCategory(category) ; +} + LLTexUnit::eTextureAddressMode LLViewerTexture::getAddressMode(void) const { llassert_always(mGLTexturep.notNull()) ; @@ -750,18 +846,18 @@ BOOL LLViewerTexture::getMissed() const return mGLTexturep->getMissed() ; } -BOOL LLViewerTexture::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) +BOOL LLViewerTexture::isJustBound() const { llassert_always(mGLTexturep.notNull()) ; - return mGLTexturep->isValidForSculpt(discard_level, image_width, image_height, ncomponents) ; + return mGLTexturep->isJustBound() ; } -BOOL LLViewerTexture::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const +void LLViewerTexture::forceUpdateBindStats(void) const { llassert_always(mGLTexturep.notNull()) ; - return mGLTexturep->readBackRaw(discard_level, imageraw, compressed_ok) ; + return mGLTexturep->forceUpdateBindStats() ; } U32 LLViewerTexture::getTexelsInAtlas() const @@ -801,6 +897,11 @@ void LLViewerTexture::destroyGLTexture() } } +BOOL LLViewerTexture::isLargeImage() +{ + return mFullWidth * mFullHeight > LLViewerTexture::sMinLargeImageSize ; +} + //virtual void LLViewerTexture::updateBindStatsForTester() { @@ -821,11 +922,12 @@ void LLViewerTexture::updateBindStatsForTester() //static F32 LLViewerFetchedTexture::maxDecodePriority() { - return 2000000.f; + return 6000000.f; } -LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, BOOL usemipmaps) - : LLViewerTexture(id, usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) + : LLViewerTexture(id, usemipmaps), + mTargetHost(host) { init(TRUE) ; generateGLTexture() ; @@ -837,9 +939,9 @@ LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemi init(TRUE) ; } -LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& full_path, const LLUUID& id, BOOL usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) : LLViewerTexture(id, usemipmaps), - mLocalFileName(full_path) + mUrl(url) { init(TRUE) ; generateGLTexture() ; @@ -884,10 +986,18 @@ void LLViewerFetchedTexture::init(bool firstinit) mFetchPriority = 0; mDownloadProgress = 0.f; mFetchDeltaTime = 999999.f; - mDecodeFrame = 0; - mVisibleFrame = 0; mForSculpt = FALSE ; mIsFetched = FALSE ; + + mCachedRawImage = NULL ; + mCachedRawDiscardLevel = -1 ; + mCachedRawImageReady = FALSE ; + + mSavedRawImage = NULL ; + mForceToSaveRawImage = FALSE ; + mSavedRawDiscardLevel = -1 ; + mDesiredSavedRawDiscardLevel = -1 ; + mLastReferencedSavedRawImageTime = 0.0f ; } LLViewerFetchedTexture::~LLViewerFetchedTexture() @@ -924,11 +1034,25 @@ void LLViewerFetchedTexture::cleanup() // Clean up image data destroyRawImage(); + mCachedRawImage = NULL ; + mCachedRawDiscardLevel = -1 ; + mCachedRawImageReady = FALSE ; + mSavedRawImage = NULL ; } void LLViewerFetchedTexture::setForSculpt() { mForSculpt = TRUE ; + if(isForSculptOnly() && !getBoundRecently()) + { + destroyGLTexture() ; //sculpt image does not need gl texture. + } + checkCachedRawSculptImage() ; +} + +BOOL LLViewerFetchedTexture::isForSculptOnly() const +{ + return mForSculpt && !mNeedsGLTexture ; } BOOL LLViewerFetchedTexture::isDeleted() @@ -963,17 +1087,37 @@ void LLViewerFetchedTexture::setInactive() } } +BOOL LLViewerFetchedTexture::isFullyLoaded() const +{ + // Unfortunately, the boolean "mFullyLoaded" is never updated correctly so we use that logic + // to check if the texture is there and completely downloaded + return (mFullWidth != 0) && (mFullHeight != 0) && !mIsFetching && !mHasFetcher; +} + + // virtual void LLViewerFetchedTexture::dump() { LLViewerTexture::dump(); - llinfos << "LLViewerFetchedTexture" - << " mIsMissingAsset " << (S32)mIsMissingAsset - << " mFullWidth " << mFullWidth - << " mFullHeight " << mFullHeight - << " mOrigWidth" << mOrigWidth - << " mOrigHeight" << mOrigHeight + llinfos << "Dump : " << mID + << ", mIsMissingAsset = " << (S32)mIsMissingAsset + << ", mFullWidth = " << (S32)mFullWidth + << ", mFullHeight = " << (S32)mFullHeight + << ", mOrigWidth = " << (S32)mOrigWidth + << ", mOrigHeight = " << (S32)mOrigHeight + << llendl; + llinfos << " : " + << " mFullyLoaded = " << (S32)mFullyLoaded + << ", mFetchState = " << (S32)mFetchState + << ", mFetchPriority = " << (S32)mFetchPriority + << ", mDownloadProgress = " << (F32)mDownloadProgress + << llendl; + llinfos << " : " + << " mHasFetcher = " << (S32)mHasFetcher + << ", mIsFetching = " << (S32)mIsFetching + << ", mIsFetched = " << (S32)mIsFetched + << ", mBoostLevel = " << (S32)mBoostLevel << llendl; } @@ -994,6 +1138,75 @@ void LLViewerFetchedTexture::destroyTexture() mFullyLoaded = FALSE ; } +// +//do not change the discard level of the loaded texture image. +BOOL LLViewerFetchedTexture::keepReuestedDiscardLevel() +{ + if (!mLoadedCallbackList.empty()) + { + return TRUE ; + } + + return FALSE ; +} + +void LLViewerFetchedTexture::addToCreateTexture() +{ + if(isForSculptOnly()) + { + //just update some variables, not to create a real GL texture. + createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ; + mNeedsCreateTexture = FALSE ; + destroyRawImage(); + } + else + { +#if 1 + // + //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up, + //so do not scale down the over qualified image. + //Note: scaling down image is expensensive. Do it only when very necessary. + // + if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !keepReuestedDiscardLevel()) + { + S32 w = mFullWidth >> mRawDiscardLevel; + S32 h = mFullHeight >> mRawDiscardLevel; + + //if big image, do not load extra data + //scale it down to size >= LLViewerTexture::sMinLargeImageSize + if(w * h > LLViewerTexture::sMinLargeImageSize) + { + S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel ; + + if(d_level > 0) + { + S32 i = 0 ; + while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerTexture::sMinLargeImageSize)) + { + i++; + d_level--; + } + if(i > 0) + { + mRawDiscardLevel += i ; + if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0) + { + mNeedsCreateTexture = FALSE ; + destroyRawImage(); + return ; + } + mRawImage->scale(w >> i, h >> i) ; + } + } + } + } +#endif + mNeedsCreateTexture = TRUE; + gTextureList.mCreateTextureList.insert(this); + } + return ; +} + // ONLY called from LLViewerTextureList BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) { @@ -1015,7 +1228,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) if (!gNoRender) { // store original size only for locally-sourced images - if (!mLocalFileName.empty()) + if (mUrl.compare(0, 7, "file://") == 0) { mOrigWidth = mRawImage->getWidth(); mOrigHeight = mRawImage->getHeight(); @@ -1061,7 +1274,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) if(!(res = insertToAtlas())) { - res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename); + res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); resetFaceAtlas() ; } setActive() ; @@ -1115,7 +1328,15 @@ void LLViewerFetchedTexture::processTextureStats() return ; } - if(!mFullWidth || !mFullHeight) + updateVirtualSize() ; + + static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); + + if (textures_fullres) + { + mDesiredDiscardLevel = 0; + } + else if(!mFullWidth || !mFullHeight) { mDesiredDiscardLevel = getMaxDiscardLevel() ; } @@ -1147,16 +1368,6 @@ void LLViewerFetchedTexture::processTextureStats() } } -//texture does not have any data, so we don't know the size of the image, treat it like 32 * 32. -F32 LLViewerFetchedTexture::calcDecodePriorityForUnknownTexture(F32 pixel_priority) -{ - F32 desired = (F32)(log(32.0/pixel_priority) / log_2); - S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired + 1; - ddiscard = llclamp(ddiscard, 1, 9); - - return ddiscard*100000.f; -} - F32 LLViewerFetchedTexture::calcDecodePriority() { #ifndef LL_RELEASE_FOR_DOWNLOAD @@ -1175,22 +1386,28 @@ F32 LLViewerFetchedTexture::calcDecodePriority() { return mDecodePriority; // no change while waiting to create } - - F32 priority; - S32 cur_discard = getDiscardLevel(); - bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); - F32 pixel_priority = fsqrtf(mMaxVirtualSize); - const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame - mDecodeFrame++; - if (pixel_priority > 0.f) + if(mForceToSaveRawImage) { - mVisibleFrame = mDecodeFrame; + return maxDecodePriority() ; } + S32 cur_discard = getDiscardLevel(); + bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); + F32 pixel_priority = fsqrtf(mMaxVirtualSize); + + F32 priority; if (mIsMissingAsset) { priority = 0.0f; } + else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1) + { + priority = -1.0f ; + } + else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) + { + priority = -1.0f; + } else if (mDesiredDiscardLevel > getMaxDiscardLevel()) { // Don't decode anything we don't need @@ -1208,11 +1425,6 @@ F32 LLViewerFetchedTexture::calcDecodePriority() // Always want high boosted images priority = 1.f; } - else if (mVisibleFrame == 0 || (mDecodeFrame - mVisibleFrame > MIN_NOT_VISIBLE_FRAMES)) - { - // Don't decode anything that isn't visible unless it's important - priority = -2.0f; - } else { // Leave the priority as-is @@ -1221,7 +1433,13 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } else if (cur_discard < 0) { - priority = calcDecodePriorityForUnknownTexture(pixel_priority) ; + //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32. + // priority range = 100,000 - 500,000 + static const F64 log_2 = log(2.0); + F32 desired = (F32)(log(32.0/pixel_priority) / log_2); + S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired; + ddiscard = llclamp(ddiscard, 0, 4); + priority = (ddiscard+1)*100000.f; } else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel)) { @@ -1234,29 +1452,47 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } else { - // priority range = 100000-400000 - S32 ddiscard = cur_discard - mDesiredDiscardLevel; + // priority range = 100,000 - 500,000 + S32 desired_discard = mDesiredDiscardLevel; if (getDontDiscard()) { - ddiscard+=2; + desired_discard -= 2; } - else if (mGLTexturep.notNull() && !mGLTexturep->getBoundRecently() && mBoostLevel == 0) + else if (!isJustBound() && mCachedRawImageReady && !mBoostLevel) { - ddiscard-=2; + // We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is + desired_discard = cur_discard; } + else if (mGLTexturep.notNull() && !mGLTexturep->getBoundRecently() && mBoostLevel == LLViewerTexture::BOOST_NONE) + { + // We haven't rendered this in a while, de-prioritize it + desired_discard += 2; + } + S32 ddiscard = cur_discard - desired_discard; ddiscard = llclamp(ddiscard, 0, 4); - priority = ddiscard*100000.f; + priority = (ddiscard+1)*100000.f; } + + // Priority Formula: + // BOOST_HIGH + ADDITIONAL PRI + DELTA DISCARD + BOOST LEVEL + PIXELS + // [10,000,000] + [1-9,000,000] + [1-400,000] + [1-20,000] + [0-999] if (priority > 0.0f) { - pixel_priority = llclamp(pixel_priority, 0.0f, priority-1.f); // priority range = 100000-900000 + pixel_priority = llclamp(pixel_priority, 0.0f, 999.f); + + priority = pixel_priority + 1000.f * mBoostLevel; + if ( mBoostLevel > BOOST_HIGH) { - priority = 1000000.f + pixel_priority + 1000.f * mBoostLevel; + priority += 10000000.f; } - else + + if(mAdditionalDecodePriority > 0.0f) { - priority += 0.f + pixel_priority + 1000.f * mBoostLevel; + // 1-9 + S32 additional_priority = (S32)(1.0f + mAdditionalDecodePriority*8.0f + .5f); // round + // priority range += 0-9,000,000 + priority += 1000000.f * (F32)additional_priority; } } return priority; @@ -1269,6 +1505,36 @@ void LLViewerFetchedTexture::setDecodePriority(F32 priority) mDecodePriority = priority; } +void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority) +{ + priority = llclamp(priority, 0.f, 1.f); + if(mAdditionalDecodePriority < priority) + { + mAdditionalDecodePriority = priority; + } +} + +void LLViewerFetchedTexture::updateVirtualSize() +{ + if(mNeedsResetMaxVirtualSize) + { + addTextureStats(0.f, FALSE) ;//reset + } + if(mFaceList.size() > 0) + { + for(std::list<LLFace*>::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + { + LLFace* facep = *iter ; + if(facep->getDrawable()->isRecentlyVisible()) + { + addTextureStats(facep->getVirtualSize()) ; + setAdditionalDecodePriority(facep->getImportanceToCamera()) ; + } + } + } + mNeedsResetMaxVirtualSize = TRUE ; +} + bool LLViewerFetchedTexture::updateFetch() { mFetchState = 0; @@ -1308,6 +1574,15 @@ bool LLViewerFetchedTexture::updateFetch() { // Sets mRawDiscardLevel, mRawImage, mAuxRawImage S32 fetch_discard = current_discard; + + if(mForceToSaveRawImage) + { + if(fetch_discard >= 0) + { + fetch_discard = llmax(fetch_discard, mSavedRawDiscardLevel) ; + } + } + if (mRawImage.notNull()) sRawCount--; if (mAuxRawImage.notNull()) sAuxCount--; bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); @@ -1347,11 +1622,24 @@ bool LLViewerFetchedTexture::updateFetch() (*iter)->dirtyTexture() ; } } - mIsRawImageValid = TRUE; - gTextureList.mCreateTextureList.insert(this); - mNeedsCreateTexture = TRUE; mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; + + if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) + { + //discard all oversized textures. + destroyRawImage(); + setIsMissingAsset(); + mRawDiscardLevel = INVALID_DISCARD_LEVEL ; + mIsFetching = FALSE ; + } + else + { + mIsRawImageValid = TRUE; + addToCreateTexture() ; + } + + return TRUE ; } else { @@ -1374,13 +1662,13 @@ bool LLViewerFetchedTexture::updateFetch() } else { - llwarns << mID << ": Setting min discard to " << current_discard << llendl; + //llwarns << mID << ": Setting min discard to " << current_discard << llendl; mMinDiscardLevel = current_discard; desired_discard = current_discard; } destroyRawImage(); } - else if (mRawImage.isNull()) + else if (mRawImage.notNull()) { // We have data, but our fetch failed to return raw data // *TODO: FIgure out why this is happening and fix it @@ -1389,12 +1677,29 @@ bool LLViewerFetchedTexture::updateFetch() } else { +// // Useful debugging code for undesired deprioritization of textures. +// if (decode_priority <= 0.0f && desired_discard >= 0 && desired_discard < current_discard) +// { +// llinfos << "Calling updateRequestPriority() with decode_priority = 0.0f" << llendl; +// calcDecodePriority(); +// } LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority); } } - bool make_request = true; - + if (!mDontDiscard) + { + if (mBoostLevel == 0) + { + desired_discard = llmax(desired_discard, current_discard-1); + } + else + { + desired_discard = llmax(desired_discard, current_discard-2); + } + } + + bool make_request = true; if (decode_priority <= 0) { make_request = false; @@ -1407,6 +1712,10 @@ bool LLViewerFetchedTexture::updateFetch() { make_request = false; } + else if (!isJustBound() && mCachedRawImageReady) + { + make_request = false; + } else { if (mIsFetching) @@ -1434,33 +1743,12 @@ bool LLViewerFetchedTexture::updateFetch() h = mGLTexturep->getHeight(0); c = mComponents; } - if (!mDontDiscard) - { - if (mBoostLevel == 0) - { - desired_discard = llmax(desired_discard, current_discard-1); - } - else - { - desired_discard = llmax(desired_discard, current_discard-2); - } - } - + // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; - if (mLocalFileName.empty()) - { - fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(getID(), getTargetHost(), decode_priority, - w, h, c, desired_discard, - needsAux()); - } - else - { - fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mLocalFileName, getID(),getTargetHost(), decode_priority, - w, h, c, desired_discard, - needsAux()); - } - + fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority, + w, h, c, desired_discard, needsAux()); + if (fetch_request_created) { mHasFetcher = TRUE; @@ -1490,9 +1778,82 @@ bool LLViewerFetchedTexture::updateFetch() return mIsFetching ? true : false; } +// +//force to fetch a new raw image for this texture +// +BOOL LLViewerFetchedTexture::forceFetch() +{ + if(!mForceToSaveRawImage) + { + return false ; + } + if(mDesiredSavedRawDiscardLevel < getDiscardLevel()) + { + //no need to force fetching. normal fetching flow will do the work. + //return false ; + } + if (mNeedsCreateTexture) + { + // We may be fetching still (e.g. waiting on write) + // but don't check until we've processed the raw data we have + //return false; + } + if(mIsFetching) + { + return false ; + } + if (mIsMissingAsset) + { + mForceToSaveRawImage = false ; + llassert_always(!mHasFetcher); + return false; // skip + } + if (!mLoadedCallbackList.empty() && mRawImage.notNull()) + { + return false; // process any raw image data in callbacks before replacing + } + if(mRawImage.notNull() && mRawDiscardLevel <= mDesiredSavedRawDiscardLevel) + { + return false ; // mRawImage is enough + } + + S32 desired_discard = mDesiredSavedRawDiscardLevel ; + S32 current_discard = getDiscardLevel(); + + bool fetch_request_created = false; + S32 w=0, h=0, c=0; + if (current_discard >= 0) + { + w = getWidth(0); + h = getHeight(0); + c = getComponents(); + } + fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), maxDecodePriority(), + w, h, c, desired_discard, needsAux()); + + if (fetch_request_created) + { + mHasFetcher = TRUE; + mIsFetching = TRUE; + mRequestedDiscardLevel = desired_discard ; + + mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, + mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); + } + + return mIsFetching ? true : false; +} + void LLViewerFetchedTexture::setIsMissingAsset() { - llwarns << mLocalFileName << " " << mID << ": Marking image as missing" << llendl; + if (mUrl.empty()) + { + llwarns << mID << ": Marking image as missing" << llendl; + } + else + { + llwarns << mUrl << ": Marking image as missing" << llendl; + } if (mHasFetcher) { LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); @@ -1514,7 +1875,13 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call { // Put in list to call this->doLoadedCallbacks() periodically gTextureList.mCallbackList.insert(this); + mLoadedCallbackDesiredDiscardLevel = (S8)discard_level; + } + else + { + mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level) ; } + LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata); mLoadedCallbackList.push_back(entryp); mNeedsAux |= needs_aux; @@ -1643,7 +2010,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() // We have GL data. destroyRawImage(); - readBackRawImage(gl_discard); + reloadRawImage(mLoadedCallbackDesiredDiscardLevel); llassert_always(mRawImage.notNull()); llassert_always(!mNeedsAux || mAuxRawImage.notNull()); } @@ -1752,8 +2119,7 @@ void LLViewerFetchedTexture::forceImmediateUpdate() return ; } -// Was in LLImageGL -LLImageRaw* LLViewerFetchedTexture::readBackRawImage(S8 discard_level) +LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) { llassert_always(mGLTexturep.notNull()) ; llassert_always(discard_level >= 0); @@ -1763,25 +2129,216 @@ LLImageRaw* LLViewerFetchedTexture::readBackRawImage(S8 discard_level) llerrs << "called with existing mRawImage" << llendl; mRawImage = NULL; } - mRawImage = new LLImageRaw(mGLTexturep->getWidth(discard_level), mGLTexturep->getHeight(discard_level), mComponents); - sRawCount++; - mRawDiscardLevel = discard_level; - mGLTexturep->readBackRaw(mRawDiscardLevel, mRawImage, false); - mIsRawImageValid = TRUE; + + if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level) + { + mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; + mRawImage->copy(getSavedRawImage()) ; + mRawDiscardLevel = discard_level ; + } + else + { + //force to fetch raw image again if cached raw image is not good enough. + if(mCachedRawDiscardLevel > discard_level) + { + mRawImage = mCachedRawImage ; + mRawDiscardLevel = mCachedRawDiscardLevel; + + forceToSaveRawImage(discard_level) ; + } + else //cached raw image is good enough, copy it. + { + mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; + mRawImage->copy(mCachedRawImage) ; + mRawDiscardLevel = discard_level ; + } + } + mIsRawImageValid = TRUE ; + sRawCount++; return mRawImage; } void LLViewerFetchedTexture::destroyRawImage() -{ - if (mRawImage.notNull()) sRawCount--; +{ if (mAuxRawImage.notNull()) sAuxCount--; + + if (mRawImage.notNull()) + { + sRawCount--; + setCachedRawImage() ; + + if(mForceToSaveRawImage) + { + saveRawImage() ; + } + } + mRawImage = NULL; mAuxRawImage = NULL; mIsRawImageValid = FALSE; mRawDiscardLevel = INVALID_DISCARD_LEVEL; + + if(mForceToSaveRawImage) + { + forceFetch() ; + } +} + +//use the mCachedRawImage to (re)generate the gl texture. +//virtual +void LLViewerFetchedTexture::switchToCachedImage() +{ + if(mCachedRawImage.notNull()) + { + mRawImage = mCachedRawImage ; + + if (getComponents() != mRawImage->getComponents()) + { + // We've changed the number of components, so we need to move any + // objects using this pool to a different pool. + mComponents = mRawImage->getComponents(); + mGLTexturep->setComponents(mComponents) ; + gTextureList.dirtyImage(this); + } + + mIsRawImageValid = TRUE; + mRawDiscardLevel = mCachedRawDiscardLevel ; + gTextureList.mCreateTextureList.insert(this); + mNeedsCreateTexture = TRUE; + } +} + +void LLViewerFetchedTexture::setCachedRawImage() +{ + if(mRawImage == mCachedRawImage) + { + return ; + } + if(!mIsRawImageValid) + { + return ; + } + + if(mCachedRawImageReady) + { + return ; + } + + if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel) + { + S32 i = 0 ; + S32 w = mRawImage->getWidth() ; + S32 h = mRawImage->getHeight() ; + + S32 max_size = MAX_CACHED_RAW_IMAGE_AREA ; + if(LLViewerTexture::BOOST_TERRAIN == mBoostLevel) + { + max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA ; + } + if(mForSculpt) + { + max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA ; + mCachedRawImageReady = !mRawDiscardLevel ; + } + else + { + mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)) ; + } + + while(((w >> i) * (h >> i)) > max_size) + { + ++i ; + } + + if(i) + { + if(!(w >> i) || !(h >> i)) + { + --i ; + } + //if(mForSculpt) + //{ + // mRawImage->scaleDownWithoutBlending(w >> i, h >> i) ; + //} + //else + { + mRawImage->scale(w >> i, h >> i) ; + } + } + mCachedRawImage = mRawImage ; + mCachedRawDiscardLevel = mRawDiscardLevel + i ; + } +} + +void LLViewerFetchedTexture::checkCachedRawSculptImage() +{ + if(mCachedRawImageReady && mCachedRawDiscardLevel > 0) + { + if(getDiscardLevel() != 0) + { + mCachedRawImageReady = FALSE ; + } + else if(isForSculptOnly()) + { + resetTextureStats() ; //do not update this image any more. + } + } +} + +void LLViewerFetchedTexture::saveRawImage() +{ + if(mRawImage.isNull() || mSavedRawDiscardLevel == mRawDiscardLevel) + { + return ; + } + + mSavedRawDiscardLevel = mRawDiscardLevel ; + mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ; + + if(mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel) + { + mForceToSaveRawImage = FALSE ; + } + + mLastReferencedSavedRawImageTime = sCurrentTime ; } +void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard) +{ + if(!mForceToSaveRawImage && (mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard)) + { + mForceToSaveRawImage = TRUE ; + mDesiredSavedRawDiscardLevel = desired_discard ; + + forceFetch() ; + } +} +void LLViewerFetchedTexture::destroySavedRawImage() +{ + mSavedRawImage = NULL ; + mForceToSaveRawImage = FALSE ; + mSavedRawDiscardLevel = -1 ; + mDesiredSavedRawDiscardLevel = -1 ; + mLastReferencedSavedRawImageTime = 0.0f ; +} + +LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() +{ + mLastReferencedSavedRawImageTime = sCurrentTime ; + + return mSavedRawImage ; +} + +BOOL LLViewerFetchedTexture::hasSavedRawImage() const +{ + return mSavedRawImage.notNull() ; +} + +F32 LLViewerFetchedTexture::getElapsedLastReferencedSavedRawImageTime() const +{ + return mLastReferencedSavedRawImageTime - sCurrentTime ; +} //---------------------------------------------------------------------------------------------- //atlasing //---------------------------------------------------------------------------------------------- @@ -1979,14 +2536,14 @@ BOOL LLViewerFetchedTexture::insertToAtlas() //---------------------------------------------------------------------------------------------- //start of LLViewerLODTexture //---------------------------------------------------------------------------------------------- -LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, BOOL usemipmaps) - : LLViewerFetchedTexture(id, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) + : LLViewerFetchedTexture(id, host, usemipmaps) { init(TRUE) ; } -LLViewerLODTexture::LLViewerLODTexture(const std::string& full_path, const LLUUID& id, BOOL usemipmaps) - : LLViewerFetchedTexture(full_path, id, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) + : LLViewerFetchedTexture(url, id, usemipmaps) { init(TRUE) ; } @@ -2004,12 +2561,25 @@ S8 LLViewerLODTexture::getType() const return LLViewerTexture::LOD_TEXTURE ; } +BOOL LLViewerLODTexture::isUpdateFrozen() +{ + return LLViewerTexture::sFreezeImageScalingDown && !getDiscardLevel() ; +} + // This is gauranteed to get called periodically for every texture //virtual void LLViewerLODTexture::processTextureStats() { + updateVirtualSize() ; + + static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); + + if (textures_fullres) + { + mDesiredDiscardLevel = 0; + } // Generate the request priority and render priority - if (mDontDiscard || !mUseMipMaps) + else if (mDontDiscard || !mUseMipMaps) { mDesiredDiscardLevel = 0; if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) @@ -2038,13 +2608,7 @@ void LLViewerLODTexture::processTextureStats() // If we know the output width and height, we can force the discard // level to the correct value, and thus not decode more texture // data than we need to. - /*if (mBoostLevel == LLViewerTexture::BOOST_UI || - mBoostLevel == LLViewerTexture::BOOST_PREVIEW || - mBoostLevel == LLViewerTexture::BOOST_AVATAR_SELF) // what about AVATAR_BAKED_SELF? - { - discard_level = 0; // full res - } - else*/ if (mKnownDrawWidth && mKnownDrawHeight) + if (mKnownDrawWidth && mKnownDrawHeight) { S32 draw_texels = mKnownDrawWidth * mKnownDrawHeight; @@ -2055,6 +2619,12 @@ void LLViewerLODTexture::processTextureStats() } else { + if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 1.0f) + { + //if is a big image and not being used recently, nor close to the view point, do not load hi-res data. + mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerTexture::sMinLargeImageSize) ; + } + if ((mCalculatedDiscardLevel >= 0.f) && (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) { @@ -2071,13 +2641,11 @@ void LLViewerLODTexture::processTextureStats() } if (mBoostLevel < LLViewerTexture::BOOST_HIGH) { - static const F32 discard_bias = -.5f; // Must be < 1 or highest discard will never load! - discard_level += discard_bias; discard_level += sDesiredDiscardBias; discard_level *= sDesiredDiscardScale; // scale + discard_level += sCameraMovingDiscardBias ; } discard_level = floorf(discard_level); -// discard_level -= (gTextureList.mVideoMemorySetting>>1); // more video ram = higher detail F32 min_discard = 0.f; if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) @@ -2096,46 +2664,39 @@ void LLViewerLODTexture::processTextureStats() // proper action if we don't. // - BOOL increase_discard = FALSE; S32 current_discard = getDiscardLevel(); if ((sDesiredDiscardBias > 0.0f) && (current_discard >= 0 && mDesiredDiscardLevel >= current_discard)) { - if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) + // Limit the amount of GL memory bound each frame + if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale && + (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { - // Limit the amount of GL memory bound each frame - if (mDesiredDiscardLevel > current_discard) - { - increase_discard = TRUE; - } + scaleDown() ; } - if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale) + // Only allow GL to have 2x the video card memory + else if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale && + (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { - // Only allow GL to have 2x the video card memory - if (!mGLTexturep->getBoundRecently()) - { - increase_discard = TRUE; - } - } - if (increase_discard) - { - // llinfos << "DISCARDED: " << mID << " Discard: " << current_discard << llendl; - sBoundTextureMemoryInBytes -= mGLTexturep->mTextureMemory; - sTotalTextureMemoryInBytes -= mGLTexturep->mTextureMemory; - // Increase the discard level (reduce the texture res) - S32 new_discard = current_discard+1; - mGLTexturep->setDiscardLevel(new_discard); - sBoundTextureMemoryInBytes += mGLTexturep->mTextureMemory; - sTotalTextureMemoryInBytes += mGLTexturep->mTextureMemory; - if(LLViewerTextureManager::sTesterp) - { - LLViewerTextureManager::sTesterp->setStablizingTime() ; - } + scaleDown() ; + } } } } +void LLViewerLODTexture::scaleDown() +{ + if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel()) + { + switchToCachedImage() ; + + if(LLViewerTextureManager::sTesterp) + { + LLViewerTextureManager::sTesterp->setStablizingTime() ; + } + } +} //---------------------------------------------------------------------------------------------- //end of LLViewerLODTexture //---------------------------------------------------------------------------------------------- @@ -2224,6 +2785,8 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL setMediaImpl() ; + setCategory(LLViewerTexture::MEDIA) ; + LLViewerTexture* tex = gTextureList.findImage(mID) ; if(tex) //this media is a parcel media for tex. { @@ -2768,7 +3331,7 @@ void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTex mTotalBytesLoadedForLargeImage += data_size ; } - if(imagep->isForSculpt()) + if(imagep->forSculpt()) { mTotalBytesLoadedForSculpties += data_size ; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 020478beef..bde87d1dd5 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -107,11 +107,12 @@ public: enum EBoostLevel { - BOOST_NONE = 0, - BOOST_AVATAR_BAKED = 1, - BOOST_AVATAR = 2, - BOOST_CLOUDS = 3, - BOOST_SCULPTED = 4, + //skip 0 and 1 to avoid mistakenly mixing boost level with boolean numbers. + BOOST_NONE = 2, + BOOST_AVATAR_BAKED = 3, + BOOST_AVATAR = 4, + BOOST_CLOUDS = 5, + BOOST_SCULPTED = 6, BOOST_HIGH = 10, BOOST_TERRAIN = 11, // has to be high priority for minimap / low detail @@ -122,10 +123,23 @@ public: BOOST_UI = 16, BOOST_PREVIEW = 17, BOOST_MAP = 18, - BOOST_AVATAR_SELF = 19, // needed for baking avatar - BOOST_MAX_LEVEL + BOOST_MAP_VISIBLE = 19, + BOOST_AVATAR_SELF = 20, // needed for baking avatar + BOOST_MAX_LEVEL, + + //other texture Categories + LOCAL = BOOST_MAX_LEVEL, + AVATAR_SCRATCH_TEX, + DYNAMIC_TEX, + MEDIA, + ATLAS, + OTHER, + MAX_GL_IMAGE_CATEGORY }; - + static S32 getTotalNumOfCategories() ; + static S32 getIndexFromCategory(S32 category) ; + static S32 getCategoryFromIndex(S32 index) ; + typedef std::list<LLFace*> ll_face_list_t ; protected: @@ -146,7 +160,7 @@ public: virtual BOOL isMissingAsset()const ; virtual void dump(); // debug info to llinfos - /*virtual*/ bool bindDefaultImage(const S32 stage = 0) const ; + /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; /*virtual*/ void forceImmediateUpdate() ; const LLUUID& getID() const { return mID; } @@ -154,9 +168,9 @@ public: void setBoostLevel(S32 level); S32 getBoostLevel() { return mBoostLevel; } - //maxVirtualSize of the texture - void addTextureStats(F32 virtual_size) const ; - void resetTextureStats(BOOL zero = FALSE); + void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const; + void resetTextureStats(); + virtual F32 getMaxVirtualSize() ; LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;} @@ -181,7 +195,7 @@ public: BOOL hasGLTexture() const ; LLGLuint getTexName() const ; BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0); + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLViewerTexture::OTHER); void setFilteringOption(LLTexUnit::eTextureFilterOptions option); void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); @@ -189,7 +203,8 @@ public: BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); void setGLTextureCreated (bool initialized); - + void setCategory(S32 category) ; + LLTexUnit::eTextureAddressMode getAddressMode(void) const ; S32 getMaxDiscardLevel() const; S32 getDiscardLevel() const; @@ -202,8 +217,8 @@ public: BOOL getMask(const LLVector2 &tc); F32 getTimePassedSinceLastBound(); BOOL getMissed() const ; - BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ; - BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const; + BOOL isJustBound()const ; + void forceUpdateBindStats(void) const; U32 getTexelsInAtlas() const ; U32 getTexelsInGLTexture() const ; @@ -221,6 +236,8 @@ public: BOOL getDontDiscard() const { return mDontDiscard; } //----------------- + BOOL isLargeImage() ; + void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;} BOOL hasParcelMedia() const { return mParcelMedia != NULL;} LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;} @@ -233,6 +250,7 @@ protected: private: //note: do not make this function public. /*virtual*/ LLImageGL* getGLTexture() const ; + virtual void switchToCachedImage(); protected: LLUUID mID; @@ -242,7 +260,9 @@ protected: BOOL mUseMipMaps ; S8 mComponents; mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? + mutable S8 mNeedsGLTexture; mutable BOOL mNeedsResetMaxVirtualSize ; + mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority. LLFrameTimer mLastReferencedTimer; ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture @@ -278,7 +298,12 @@ public: static S32 sMaxBoundTextureMemInMegaBytes; static S32 sMaxTotalTextureMemInMegaBytes; static S32 sMaxDesiredTextureMemInBytes ; - static BOOL sDontLoadVolumeTextures; + static S8 sCameraMovingDiscardBias; + static S32 sMaxSculptRez ; + static S32 sMinLargeImageSize ; + static S32 sMaxSmallImageSize ; + static BOOL sFreezeImageScalingDown ;//do not scale down image res if set. + static F32 sCurrentTime ; static BOOL sUseTextureAtlas ; static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects. @@ -298,9 +323,9 @@ class LLViewerFetchedTexture : public LLViewerTexture protected: /*virtual*/ ~LLViewerFetchedTexture(); public: - LLViewerFetchedTexture(const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps); - LLViewerFetchedTexture(const std::string& full_path, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE); public: static F32 maxDecodePriority(); @@ -336,6 +361,8 @@ public: bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; } bool doLoadedCallbacks(); + void addToCreateTexture(); + // ONLY call from LLViewerTextureList BOOL createTexture(S32 usename = 0); void destroyTexture() ; @@ -354,7 +381,11 @@ public: // the priority list, and cause horrible things to happen. void setDecodePriority(F32 priority = -1.0f); F32 getDecodePriority() const { return mDecodePriority; }; + + void setAdditionalDecodePriority(F32 priority) ; + void updateVirtualSize() ; + // setDesiredDiscardLevel is only used by LLViewerTextureList void setDesiredDiscardLevel(S32 discard) { mDesiredDiscardLevel = discard; } S32 getDesiredDiscardLevel() { return mDesiredDiscardLevel; } @@ -378,15 +409,15 @@ public: BOOL isInImageList() const {return mInImageList ;} void setInImageList(BOOL flag) {mInImageList = flag ;} - const std::string& getLocalFileName() const {return mLocalFileName ;} LLFrameTimer* getLastPacketTimer() {return &mLastPacketTimer;} U32 getFetchPriority() const { return mFetchPriority ;} F32 getDownloadProgress() const {return mDownloadProgress ;} - LLImageRaw* readBackRawImage(S8 discard_level) ; + LLImageRaw* reloadRawImage(S8 discard_level) ; void destroyRawImage(); + const std::string& getUrl() const {return mUrl;} //--------------- BOOL isDeleted() ; BOOL isInactive() ; @@ -397,13 +428,35 @@ public: //--------------- void setForSculpt(); - BOOL isForSculpt() const {return mForSculpt;} + BOOL forSculpt() const {return mForSculpt;} + BOOL isForSculptOnly() const; + + //raw image management + void checkCachedRawSculptImage() ; + LLImageRaw* getRawImage()const { return mRawImage ;} + S32 getRawImageLevel() const {return mRawDiscardLevel;} + LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;} + S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;} + BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;} + BOOL isRawImageValid()const { return mIsRawImageValid ; } + void forceToSaveRawImage(S32 desired_discard = 0) ; + void destroySavedRawImage() ; + LLImageRaw* getSavedRawImage() ; + BOOL hasSavedRawImage() const ; + F32 getElapsedLastReferencedSavedRawImageTime() const ; + BOOL isFullyLoaded() const; + +protected: + /*virtual*/ void switchToCachedImage(); private: void init(bool firstinit) ; void cleanup() ; - F32 calcDecodePriorityForUnknownTexture(F32 pixel_priority) ; + void saveRawImage() ; + BOOL forceFetch() ; + void setCachedRawImage() ; + BOOL keepReuestedDiscardLevel(); //for atlas void resetFaceAtlas() ; @@ -424,11 +477,8 @@ protected: S32 mKnownDrawWidth; S32 mKnownDrawHeight; BOOL mKnownDrawSizeChanged ; - - S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space - S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have - S32 mMinDiscardLevel; - + std::string mUrl; + S32 mRequestedDiscardLevel; F32 mRequestedDownloadPriority; S32 mFetchState; @@ -436,8 +486,10 @@ protected: F32 mDownloadProgress; F32 mFetchDeltaTime; F32 mRequestDeltaTime; - S32 mDecodeFrame; - S32 mVisibleFrame; // decode frame where image was last visible + F32 mDecodePriority; // The priority for decoding this image. + S32 mMinDiscardLevel; + S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space + S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have S8 mNeedsAux; // We need to decode the auxiliary channels S8 mDecodingAux; // Are we decoding high components @@ -445,10 +497,10 @@ protected: S8 mHasFetcher; // We've made a fecth request S8 mIsFetching; // Fetch request is active - mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. + mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. - F32 mDecodePriority; // The priority for decoding this image. typedef std::list<LLLoadedCallbackEntry*> callback_list_t; + S8 mLoadedCallbackDesiredDiscardLevel; callback_list_t mLoadedCallbackList; LLPointer<LLImageRaw> mRawImage; @@ -458,6 +510,19 @@ protected: // doing if you use it for anything else! - djs LLPointer<LLImageRaw> mAuxRawImage; + //keep a copy of mRawImage for some special purposes + //when mForceToSaveRawImage is set. + BOOL mForceToSaveRawImage ; + LLPointer<LLImageRaw> mSavedRawImage; + S32 mSavedRawDiscardLevel; + S32 mDesiredSavedRawDiscardLevel; + F32 mLastReferencedSavedRawImageTime ; + + //a small version of the copy of the raw image (<= 64 * 64) + LLPointer<LLImageRaw> mCachedRawImage; + S32 mCachedRawDiscardLevel; + BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit. + LLHost mTargetHost; // if LLHost::invalid, just request from agent's simulator // Timers @@ -486,15 +551,17 @@ protected: /*virtual*/ ~LLViewerLODTexture(){} public: - LLViewerLODTexture(const LLUUID& id, BOOL usemipmaps = TRUE); - LLViewerLODTexture(const std::string& full_path, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE); /*virtual*/ S8 getType() const; // Process image stats to determine priority/quality requirements. /*virtual*/ void processTextureStats(); - + BOOL isUpdateFrozen() ; + private: void init(bool firstinit) ; + void scaleDown() ; private: @@ -601,7 +668,7 @@ public: static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id, BOOL usemipmap = TRUE, - BOOL level_immediate = FALSE, // Get the requested level immediately upon creation. + S32 boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -610,7 +677,16 @@ public: static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename, BOOL usemipmap = TRUE, - BOOL level_immediate = FALSE, // Get the requested level immediately upon creation. + S32 boost_priority = LLViewerTexture::BOOST_NONE, + S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, + LLGLint internal_format = 0, + LLGLenum primary_format = 0, + const LLUUID& force_id = LLUUID::null + ); + + static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url, + BOOL usemipmap = TRUE, + S32 boost_priority = LLViewerTexture::BOOST_NONE, S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index b5986c70f5..081b7cc483 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -44,6 +44,7 @@ #include "llimagetga.h" #include "llimagejpeg.h" #include "llimagepng.h" +#include "llimageworker.h" #include "llsdserialize.h" #include "llsys.h" @@ -68,10 +69,15 @@ void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL; -const S32 IMAGES_PER_REQUEST = 42; -const S32 IMAGES_MIN_UPDATES = 4; // Always update the highest N images each frame -const S32 IMAGES_MAX_PACKET_UPDATES = 1; // Only send N packets of IMAGES_PER_REQUEST in a frame -const F32 RESEND_IMAGE_REQUEST_TIME = 15.f; // seconds +U32 LLViewerTextureList::sTextureBits = 0; +U32 LLViewerTextureList::sTexturePackets = 0; +S32 LLViewerTextureList::sNumImages = 0; +LLStat LLViewerTextureList::sNumImagesStat(32, TRUE); +LLStat LLViewerTextureList::sNumRawImagesStat(32, TRUE); +LLStat LLViewerTextureList::sGLTexMemStat(32, TRUE); +LLStat LLViewerTextureList::sGLBoundMemStat(32, TRUE); +LLStat LLViewerTextureList::sRawMemStat(32, TRUE); +LLStat LLViewerTextureList::sFormattedMemStat(32, TRUE); LLViewerTextureList gTextureList; static LLFastTimer::DeclareTimer FTM_PROCESS_IMAGES("Process Images"); @@ -88,7 +94,7 @@ LLViewerTextureList::LLViewerTextureList() void LLViewerTextureList::init() { - mNumImages = 0; + sNumImages = 0; mMaxResidentTexMemInMegaBytes = 0; mMaxTotalTextureMemInMegaBytes = 0 ; if (gNoRender) @@ -197,7 +203,7 @@ void LLViewerTextureList::doPrefetchImages() if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type) { - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, FALSE, texture_type); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, texture_type); if (image) { image->addTextureStats((F32)pixel_area); @@ -231,6 +237,10 @@ void LLViewerTextureList::shutdown() { continue; // avoid UI, baked, and other special images } + if(!image->getBoundRecently()) + { + continue ; + } S32 desired = image->getDesiredDiscardLevel(); if (desired >= 0 && desired < MAX_DISCARD_LEVEL) { @@ -321,18 +331,31 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& LLGLenum primary_format, const LLUUID& force_id) { - if (gNoRender) - { - // Never mind that this ignores image_set_id; - // getImage() will handle that later. - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE); - } - std::string full_path = gDirUtilp->findSkinnedFilename("textures", filename); if (full_path.empty()) { llwarns << "Failed to find local image file: " << filename << llendl; - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE); + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI); + } + + std::string url = "file://" + full_path; + + return getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); +} + +LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url, + BOOL usemipmaps, + S32 boost_priority, + S8 texture_type, + LLGLint internal_format, + LLGLenum primary_format, + const LLUUID& force_id) +{ + if (gNoRender) + { + // Never mind that this ignores image_set_id; + // getImage() will handle that later. + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI); } // generate UUID based on hash of filename @@ -343,7 +366,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& } else { - new_id.generate(full_path); + new_id.generate(url); } LLPointer<LLViewerFetchedTexture> imagep = findImage(new_id); @@ -353,10 +376,10 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& switch(texture_type) { case LLViewerTexture::FETCHED_TEXTURE: - imagep = new LLViewerFetchedTexture(full_path, new_id, usemipmaps); + imagep = new LLViewerFetchedTexture(url, new_id, usemipmaps); break ; case LLViewerTexture::LOD_TEXTURE: - imagep = new LLViewerLODTexture(full_path, new_id, usemipmaps); + imagep = new LLViewerLODTexture(url, new_id, usemipmaps); break ; default: llerrs << "Invalid texture type " << texture_type << llendl ; @@ -400,7 +423,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, if ((&image_id == NULL) || image_id.isNull()) { - return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE)); + return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI)); } LLPointer<LLViewerFetchedTexture> imagep = findImage(image_id); @@ -428,18 +451,15 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, switch(texture_type) { case LLViewerTexture::FETCHED_TEXTURE: - imagep = new LLViewerFetchedTexture(image_id, usemipmaps); + imagep = new LLViewerFetchedTexture(image_id, request_from_host, usemipmaps); break ; case LLViewerTexture::LOD_TEXTURE: - imagep = new LLViewerLODTexture(image_id, usemipmaps); + imagep = new LLViewerLODTexture(image_id, request_from_host, usemipmaps); break ; default: llerrs << "Invalid texture type " << texture_type << llendl ; } - // Might want to request from host other than where the agent is. JC - imagep->setTargetHost(request_from_host); - if (internal_format && primary_format) { imagep->setExplicitFormat(internal_format, primary_format); @@ -517,7 +537,7 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image) { llwarns << "Image with ID " << image_id << " already in list" << llendl; } - mNumImages++; + sNumImages++; addImageToList(new_image); mUUIDMap[image_id] = new_image; @@ -534,7 +554,7 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) } llverify(mUUIDMap.erase(image->getID()) == 1); - mNumImages--; + sNumImages--; removeImageFromList(image); } } @@ -554,7 +574,9 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_MARK_DIRTY("Dirty Images"); void LLViewerTextureList::updateImages(F32 max_time) { - LLViewerStats::getInstance()->mNumImagesStat.addValue(mNumImages); + LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec()); + + LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages); LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes)); LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes)); @@ -562,10 +584,13 @@ void LLViewerTextureList::updateImages(F32 max_time) LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); updateImagesDecodePriorities(); + + F32 total_max_time = max_time; max_time -= updateImagesFetchTextures(max_time); - max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f); + + max_time = llmax(max_time, total_max_time*.25f); // at least 25% of max_time max_time -= updateImagesCreateTextures(max_time); - max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f); + if (!mDirtyTextureList.empty()) { LLFastTimer t(FTM_IMAGE_MARK_DIRTY); @@ -578,7 +603,7 @@ void LLViewerTextureList::updateImages(F32 max_time) { //trigger loaded callbacks on local textures immediately LLViewerFetchedTexture* image = *iter++; - if (!image->getLocalFileName().empty()) + if (!image->getUrl().empty()) { // Do stuff to handle callbacks, update priorities, etc. didone = image->doLoadedCallbacks(); @@ -636,6 +661,14 @@ void LLViewerTextureList::updateImagesDecodePriorities() } else { + if(imagep->hasSavedRawImage()) + { + if(imagep->getElapsedLastReferencedSavedRawImageTime() > MAX_INACTIVE_TIME) + { + imagep->destroySavedRawImage() ; + } + } + if(imagep->isDeleted()) { continue ; @@ -766,74 +799,76 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) const size_t max_update_count = llmin((S32) (1024*10.f*gFrameIntervalSeconds)+1, 256); // 32 high priority entries - std::set<LLViewerFetchedTexture*> entries; + typedef std::vector<LLViewerFetchedTexture*> entries_list_t; + entries_list_t entries; size_t update_counter = llmin(max_priority_count, mImageList.size()); image_priority_list_t::iterator iter1 = mImageList.begin(); while(update_counter > 0) { - // added extra granularity and verbosity for crash logging during 1.19.1 RC. -Brad - if(iter1 == mImageList.end()) - { - llerrs << "DEV-12002: update_counter not calculated correctly!" << llendl; - return 0.f; - } - - LLPointer<LLViewerFetchedTexture> const & ptr = *iter1; - - LLViewerFetchedTexture * img = ptr.get(); - - // added extra granularity and verbosity for crash logging during 1.19.1 RC. -Brad - if(img == NULL) - { - llwarns << "DEV-12002: image is NULL!" << llendl; - } - - entries.insert(img); - + entries.push_back(*iter1); + ++iter1; update_counter--; } // 256 cycled entries - update_counter = llmin(max_update_count, mUUIDMap.size()); - uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID); - while(update_counter > 0) + update_counter = llmin(max_update_count, mUUIDMap.size()); + if(update_counter > 0) { - if (iter2 == mUUIDMap.end()) + uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID); + uuid_map_t::iterator iter2p = iter2; + while(update_counter > 0) { - iter2 = mUUIDMap.begin(); + if (iter2 == mUUIDMap.end()) + { + iter2 = mUUIDMap.begin(); + } + entries.push_back(iter2->second); + iter2p = iter2++; + update_counter--; } - mLastFetchUUID = iter2->first; - entries.insert(iter2->second); - ++iter2; - update_counter--; + + mLastFetchUUID = iter2p->first; } + S32 fetch_count = 0; S32 min_count = max_priority_count + max_update_count/4; - for (std::set<LLViewerFetchedTexture*>::iterator iter3 = entries.begin(); + for (entries_list_t::iterator iter3 = entries.begin(); iter3 != entries.end(); ) { LLPointer<LLViewerFetchedTexture> imagep = *iter3++; - imagep->updateFetch(); + bool fetching = imagep->updateFetch(); + if (fetching) + { + fetch_count++; + } if (min_count <= 0 && image_op_timer.getElapsedTimeF32() > max_time) { break; } min_count--; } + if (fetch_count == 0) + { + gDebugTimers[0].pause(); + } + else + { + gDebugTimers[0].unpause(); + } return image_op_timer.getElapsedTimeF32(); } void LLViewerTextureList::updateImagesUpdateStats() { - if (mUpdateStats) + if (mUpdateStats && mForceResetTextureStats) { for (image_priority_list_t::iterator iter = mImageList.begin(); iter != mImageList.end(); ) { LLViewerFetchedTexture* imagep = *iter++; - imagep->resetTextureStats(mForceResetTextureStats); + imagep->resetTextureStats(); } mUpdateStats = FALSE; mForceResetTextureStats = FALSE; @@ -1019,6 +1054,9 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage return compressedImage; } +const S32 MIN_VIDEO_RAM = 32; +const S32 MAX_VIDEO_RAM = 512; // 512MB max for performance reasons. + // Returns min setting for TextureMemory (in MB) S32 LLViewerTextureList::getMinVideoRamSetting() { @@ -1137,13 +1175,13 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d if (msg->getReceiveCompressedSize()) { - gTextureList.mTextureBits += msg->getReceiveCompressedSize() * 8; + gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8; } else { - gTextureList.mTextureBits += msg->getReceiveSize() * 8; + gTextureList.sTextureBits += msg->getReceiveSize() * 8; } - gTextureList.mTexturePackets++; + gTextureList.sTexturePackets++; U8 codec; U16 packets; @@ -1171,7 +1209,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1202,13 +1240,13 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d if (msg->getReceiveCompressedSize()) { - gTextureList.mTextureBits += msg->getReceiveCompressedSize() * 8; + gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8; } else { - gTextureList.mTextureBits += msg->getReceiveSize() * 8; + gTextureList.sTextureBits += msg->getReceiveSize() * 8; } - gTextureList.mTexturePackets++; + gTextureList.sTexturePackets++; //llprintline("Start decode, image header..."); msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); @@ -1235,7 +1273,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1401,7 +1439,7 @@ void LLUIImageList::onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_v // for images grabbed from local files, apply clipping rectangle to restore original dimensions // from power-of-2 gl image - if (success && imagep.notNull() && src_vi && !src_vi->getLocalFileName().empty()) + if (success && imagep.notNull() && src_vi && (src_vi->getUrl().compare(0, 7, "file://")==0)) { F32 clip_x = (F32)src_vi->getOriginalWidth() / (F32)src_vi->getFullWidth(); F32 clip_y = (F32)src_vi->getOriginalHeight() / (F32)src_vi->getFullHeight(); @@ -1458,6 +1496,11 @@ bool LLUIImageList::initFromFile() llwarns << "Unable to parse UI image list file " << base_file_path << llendl; return false; } + if (!root->hasAttribute("version")) + { + llwarns << "No valid version number in UI image list file " << base_file_path << llendl; + return false; + } std::vector<std::string> paths; // path to current selected skin diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index fda57ce981..3c9c81a689 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -53,7 +53,6 @@ const BOOL GL_TEXTURE_NO = FALSE; const BOOL IMMEDIATE_YES = TRUE; const BOOL IMMEDIATE_NO = FALSE; -class LLImageJ2C; class LLMessageSystem; class LLTextureView; @@ -131,7 +130,7 @@ private: LLViewerFetchedTexture * getImage(const LLUUID &image_id, BOOL usemipmap = TRUE, - BOOL level_immediate = FALSE, // Get the requested level immediately upon creation. + S32 boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -140,6 +139,15 @@ private: LLViewerFetchedTexture * getImageFromFile(const std::string& filename, BOOL usemipmap = TRUE, + S32 boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. + S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, + LLGLint internal_format = 0, + LLGLenum primary_format = 0, + const LLUUID& force_id = LLUUID::null + ); + + LLViewerFetchedTexture* getImageFromUrl(const std::string& url, + BOOL usemipmap = TRUE, BOOL level_immediate = FALSE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, @@ -149,7 +157,7 @@ private: LLViewerFetchedTexture* createImage(const LLUUID &image_id, BOOL usemipmap = TRUE, - BOOL level_immediate = FALSE, // Get the requested level immediately upon creation. + S32 boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, LLGLint internal_format = 0, LLGLenum primary_format = 0, @@ -159,7 +167,7 @@ private: // Request image from a specific host, used for baked avatar textures. // Implemented in header in case someone changes default params above. JC LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host) - { return getImage(image_id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } + { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } public: typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t; @@ -190,11 +198,18 @@ private: LLFrameTimer mForceDecodeTimer; public: - U32 mTextureBits; - U32 mTexturePackets; + static U32 sTextureBits; + static U32 sTexturePackets; + + static LLStat sNumImagesStat; + static LLStat sNumRawImagesStat; + static LLStat sGLTexMemStat; + static LLStat sGLBoundMemStat; + static LLStat sRawMemStat; + static LLStat sFormattedMemStat; private: - S32 mNumImages; + static S32 sNumImages; static void (*sUUIDCallback)(void**, const LLUUID &); }; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b574a9c110..fc09c946af 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -121,6 +121,7 @@ #include "llhudview.h" #include "llimagebmp.h" #include "llimagej2c.h" +#include "llimageworker.h" #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" @@ -160,7 +161,6 @@ #include "lltoolselectland.h" #include "lltrans.h" #include "lluictrlfactory.h" -#include "lluploaddialog.h" #include "llurldispatcher.h" // SLURL from other app instance #include "llvieweraudio.h" #include "llviewercamera.h" @@ -192,6 +192,7 @@ #include "llbottomtray.h" #include "llnearbychatbar.h" #include "llagentui.h" +#include "llwearablelist.h" #include "llnotificationmanager.h" @@ -330,7 +331,9 @@ public: S32 hours = (S32)(time / (60*60)); S32 mins = (S32)((time - hours*(60*60)) / 60); S32 secs = (S32)((time - hours*(60*60) - mins*60)); - addText(xpos, ypos, llformat(" Debug %d: %d:%02d:%02d", idx, hours,mins,secs)); ypos += y_inc2; + std::string label = gDebugTimerLabel[idx]; + if (label.empty()) label = llformat("Debug: %d", idx); + addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2; } F32 time = gFrameTimeSeconds; @@ -1304,6 +1307,7 @@ LLViewerWindow::LLViewerWindow( // Init the image list. Must happen after GL is initialized and before the images that // LLViewerWindow needs are requested. + LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ; gTextureList.init(); LLViewerTextureManager::init() ; gBumpImageList.init(); @@ -1670,6 +1674,8 @@ void LLViewerWindow::shutdownGL() gSky.cleanup(); stop_glerror(); + LLWearableList::instance().cleanup() ; + gTextureList.shutdown(); stop_glerror(); @@ -1683,7 +1689,10 @@ void LLViewerWindow::shutdownGL() stop_glerror(); LLViewerTextureManager::cleanup() ; - + LLImageGL::cleanupClass() ; + + llinfos << "All texturs and llimagegl images are destroyed!" << llendl ; + llinfos << "Cleaning up select manager" << llendl; LLSelectMgr::getInstance()->cleanup(); @@ -2113,31 +2122,30 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // arrow keys move avatar while chatting hack if (chat_editor && chat_editor->hasFocus()) { - if (chat_editor->getText().empty() || gSavedSettings.getBOOL("ArrowKeysMoveAvatar")) + // If text field is empty, there's no point in trying to move + // cursor with arrow keys, so allow movement + if (chat_editor->getText().empty() + || gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) { - switch(key) + // let Control-Up and Control-Down through for chat line history, + if (!(key == KEY_UP && mask == MASK_CONTROL) + && !(key == KEY_DOWN && mask == MASK_CONTROL)) { - case KEY_LEFT: - case KEY_RIGHT: - case KEY_UP: - // let CTRL UP through for chat line history - if( MASK_CONTROL == mask ) + switch(key) { + case KEY_LEFT: + case KEY_RIGHT: + case KEY_UP: + case KEY_DOWN: + case KEY_PAGE_UP: + case KEY_PAGE_DOWN: + case KEY_HOME: + // when chatbar is empty or ArrowKeysAlwaysMove set, + // pass arrow keys on to avatar... + return FALSE; + default: break; } - case KEY_DOWN: - // let CTRL DOWN through for chat line history - if( MASK_CONTROL == mask ) - { - break; - } - case KEY_PAGE_UP: - case KEY_PAGE_DOWN: - case KEY_HOME: - // when chatbar is empty or ArrowKeysMoveAvatar set, pass arrow keys on to avatar... - return FALSE; - default: - break; } } } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index d7c403739e..c2906b1718 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -324,7 +324,7 @@ public: } ESnapshotType; BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR); BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, - BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_IMAGE_SIZE ); + BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE ); BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ; BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); } void resetSnapshotLoc() const { sSnapshotDir.clear(); } diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index d124cbcdce..999701ece1 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -279,7 +279,6 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, if (mRawImages[i].isNull()) { // Read back a raw image for this discard level, if it exists - mRawImages[i] = new LLImageRaw; S32 min_dim = llmin(mDetailTextures[i]->getFullWidth(), mDetailTextures[i]->getFullHeight()); S32 ddiscard = 0; while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) @@ -287,12 +286,18 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, ddiscard++; min_dim /= 2; } - if (!mDetailTextures[i]->readBackRaw(ddiscard, mRawImages[i], false)) + + mDetailTextures[i]->reloadRawImage(ddiscard) ; + if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later. { - llwarns << "Unable to read raw data for terrain detail texture: " << mDetailTextures[i]->getID() << llendl; - mRawImages[i] = NULL; + mDetailTextures[i]->destroyRawImage() ; + lldebugs << "cached raw data for terrain detail texture is not ready yet: " << mDetailTextures[i]->getID() << llendl; return FALSE; } + + mRawImages[i] = mDetailTextures[i]->getRawImage() ; + mDetailTextures[i]->destroyRawImage() ; + if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE || mDetailTextures[i]->getHeight(ddiscard) != BASE_SIZE || mDetailTextures[i]->getComponents() != 3) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 4bf66ba17e..a6f20922d9 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -689,7 +689,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mBakedTextureDatas[i].mIsUsed = false; mBakedTextureDatas[i].mMaskTexName = 0; mBakedTextureDatas[i].mTextureIndex = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i); - mBakedTextureDatas[i].mMorphMasksValid = FALSE; } mDirtyMesh = TRUE; // Dirty geometry, need to regenerate. @@ -999,7 +998,7 @@ void LLVOAvatar::resetImpostors() // static void LLVOAvatar::deleteCachedImages(bool clearAll) -{ +{ if (LLTexLayerSet::sHasCaches) { lldebugs << "Deleting layer set caches" << llendl; @@ -2385,7 +2384,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) F32 old_angle = mImpostorAngle.mV[i]; F32 angle_diff = fabsf(cur_angle-old_angle); - if (angle_diff > 3.14159f/512.f*distance*mUpdatePeriod) + if (angle_diff > F_PI/512.f*distance*mUpdatePeriod) { mNeedsImpostorUpdate = TRUE; } @@ -2557,7 +2556,7 @@ void LLVOAvatar::idleUpdateLoadingEffect() particle_parameters.mPartImageID = cloud->getID(); particle_parameters.mMaxAge = 0.f; particle_parameters.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE; - particle_parameters.mInnerAngle = 3.14159f; + particle_parameters.mInnerAngle = F_PI; particle_parameters.mOuterAngle = 0.f; particle_parameters.mBurstRate = 0.02f; particle_parameters.mBurstRadius = 0.0f; @@ -3919,7 +3918,7 @@ U32 LLVOAvatar::renderFootShadows() LLGLDepthTest test(GL_TRUE, GL_FALSE); //render foot shadows LLGLEnable blend(GL_BLEND); - gGL.getTexUnit(0)->bind(mShadowImagep.get()); + gGL.getTexUnit(0)->bind(mShadowImagep, TRUE); glColor4fv(mShadow0Facep->getRenderColor().mV); mShadow0Facep->renderIndexed(foot_mask); glColor4fv(mShadow1Facep->getRenderColor().mV); @@ -3967,7 +3966,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) //------------------------------------------------------------------------ // LLVOAvatar::updateTextures() //------------------------------------------------------------------------ -void LLVOAvatar::updateTextures(LLAgent &agent) +void LLVOAvatar::updateTextures() { BOOL render_avatar = TRUE; @@ -6091,28 +6090,6 @@ void LLVOAvatar::addMaskedMorph(EBakedTextureIndex index, LLPolyMorphTarget* mor } } -// invalidates morph masks for a given layer. Don't pass a parameter to invalidate all morph masks. -void LLVOAvatar::invalidateMorphMasks(LLVOAvatarDefines::EBakedTextureIndex index) -{ - setMorphMasksValid(FALSE, index); -} - -// updates morph masks to be a value for a given layer. Don't pass an argument to set value for all morph masks -void LLVOAvatar::setMorphMasksValid(BOOL new_status, LLVOAvatarDefines::EBakedTextureIndex index) -{ - if (index == BAKED_NUM_INDICES) - { - for (U8 tex = 0; tex < (U8)BAKED_NUM_INDICES; tex++) - { - mBakedTextureDatas[tex].mMorphMasksValid = new_status; - } - } - else if (index < BAKED_NUM_INDICES) - { - mBakedTextureDatas[index].mMorphMasksValid = new_status; - } -} - // returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index) { @@ -6121,9 +6098,20 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex inde return FALSE; } - if (!mBakedTextureDatas[index].mMaskedMorphs.empty() && !mBakedTextureDatas[index].mMorphMasksValid) + if (!mBakedTextureDatas[index].mMaskedMorphs.empty()) { - return TRUE; + if (isSelf()) + { + LLTexLayerSet *layer_set = mBakedTextureDatas[index].mTexLayerSet; + if (layer_set) + { + return !layer_set->isMorphValid(); + } + } + else + { + return FALSE; + } } return FALSE; @@ -6520,7 +6508,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) && baked_index != BAKED_SKIRT) { setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE)); + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index f7c794defe..173ad02808 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -125,7 +125,7 @@ public: virtual BOOL updateLOD(); BOOL updateJointLODs(); virtual BOOL isActive() const; // Whether this object needs to do an idleUpdate. - virtual void updateTextures(LLAgent &agent); + virtual void updateTextures(); virtual S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim. virtual void onShift(const LLVector3& shift_vector); virtual U32 getPartitionType() const; @@ -355,10 +355,8 @@ private: // Morph masks //-------------------------------------------------------------------- public: - void invalidateMorphMasks(LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); BOOL morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); void addMaskedMorph(LLVOAvatarDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer); - void setMorphMasksValid(BOOL new_status, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES); //-------------------------------------------------------------------- @@ -489,7 +487,6 @@ protected: // Stores pointers to the joint meshes that this baked texture deals with std::vector< LLViewerJointMesh * > mMeshes; // std::vector<LLViewerJointMesh> mJoints[i]->mMeshParts morph_list_t mMaskedMorphs; - BOOL mMorphMasksValid; }; typedef std::vector<BakedTextureData> bakedtexturedata_vec_t; bakedtexturedata_vec_t mBakedTextureDatas; diff --git a/indra/newview/llvoavatardefines.cpp b/indra/newview/llvoavatardefines.cpp index 5624f19c8d..49c4a1a6c8 100644 --- a/indra/newview/llvoavatardefines.cpp +++ b/indra/newview/llvoavatardefines.cpp @@ -84,34 +84,34 @@ LLVOAvatarDictionary::BakedTextures::BakedTextures() { // Baked textures addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED, - "head", "18ded8d6-bcfc-e415-8539-944c0f5ea7a6", + "head", "a4b9dc38-e13b-4df9-b284-751efb0566ff", 3, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA, 5, WT_SHAPE, WT_SKIN, WT_HAIR, WT_TATTOO, WT_ALPHA)); addEntry(BAKED_UPPER, new BakedEntry(TEX_UPPER_BAKED, - "upper_body", "338c29e3-3024-4dbb-998d-7c04cf4fa88f", + "upper_body", "5943ff64-d26c-4a90-a8c0-d61f56bd98d4", 7, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA, 8, WT_SHAPE, WT_SKIN, WT_SHIRT, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT, WT_TATTOO, WT_ALPHA)); addEntry(BAKED_LOWER, new BakedEntry(TEX_LOWER_BAKED, - "lower_body", "91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f", + "lower_body", "2944ee70-90a7-425d-a5fb-d749c782ed7d", 8, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS, TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA, 9, WT_SHAPE, WT_SKIN, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_UNDERPANTS, WT_TATTOO, WT_ALPHA)); addEntry(BAKED_EYES, new BakedEntry(TEX_EYES_BAKED, - "eyes", "b2cf28af-b840-1071-3c6a-78085d8128b5", + "eyes", "27b1bc0f-979f-4b13-95fe-b981c2ba9788", 2, TEX_EYES_IRIS, TEX_EYES_ALPHA, 2, WT_EYES, WT_ALPHA)); addEntry(BAKED_SKIRT, new BakedEntry(TEX_SKIRT_BAKED, - "skirt", "ea800387-ea1a-14e0-56cb-24f2022f969a", + "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63", 1, TEX_SKIRT, 1, WT_SKIRT)); addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED, - "hair", "0af1ef7c-ad24-11dd-8790-001f5bf833e8", + "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61", 2, TEX_HAIR, TEX_HAIR_ALPHA, 2, WT_HAIR, WT_ALPHA)); } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 758db538a2..7a83070770 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -41,53 +41,22 @@ #include "llvoavatarself.h" #include "llvoavatar.h" -#include <stdio.h> -#include <ctype.h> - -#include "llaudioengine.h" -#include "noise.h" +#include "pipeline.h" -// TODO: Seraph - Remove unnecessary headers. These are copied from llvoavatar.h. #include "llagent.h" // Get state values from here #include "llagentwearables.h" -#include "llviewercontrol.h" -#include "lldrawpoolavatar.h" -#include "lldriverparam.h" -#include "lleditingmotion.h" -#include "llemote.h" -#include "llface.h" -#include "llfirstuse.h" -#include "llheadrotmotion.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" -#include "llkeyframefallmotion.h" -#include "llkeyframestandmotion.h" -#include "llkeyframewalkmotion.h" -#include "llmutelist.h" #include "llselectmgr.h" -#include "llsprite.h" -#include "lltargetingmotion.h" -#include "lltexlayer.h" -#include "lltexglobalcolor.h" #include "lltoolgrab.h" // for needsRenderBeam #include "lltoolmgr.h" // for needsRenderBeam #include "lltoolmorph.h" #include "lltrans.h" #include "llviewercamera.h" -#include "llviewertexturelist.h" #include "llviewermenu.h" #include "llviewerobjectlist.h" -#include "llviewerparcelmgr.h" #include "llviewerstats.h" -#include "llvovolume.h" -#include "llworld.h" -#include "pipeline.h" -#include "llviewershadermgr.h" -#include "llsky.h" -#include "llanimstatelabels.h" -#include "llgesturemgr.h" //needed to trigger the voice gesticulations -#include "llvoiceclient.h" -#include "llvoicevisualizer.h" // Ventrella +#include "llviewerregion.h" #include "llappearancemgr.h" #if LL_MSVC @@ -205,7 +174,10 @@ void LLVOAvatarSelf::markDead() param; param = (LLViewerVisualParam*) getNextVisualParam()) { - param->setIsDummy(TRUE); + if (param->getWearableType() != WT_INVALID) + { + param->setIsDummy(TRUE); + } } return success; @@ -1080,15 +1052,8 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view if (attachment->isObjectAttached(viewer_object)) { const LLUUID& attachment_id = viewer_object->getItemID(); - LLViewerInventoryItem *item = gInventory.getItem(attachment_id); - if (item) - { - LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Adding attachment link:"); - LLAppearanceManager::wearItem(item,false); // Add COF link for item. - gInventory.addChangedMask(LLInventoryObserver::LABEL, attachment_id); - } + LLAppearanceManager::registerAttachment(attachment_id); } - gInventory.notifyObservers(); return attachment; } @@ -1096,12 +1061,12 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view //virtual BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) { - const LLUUID item_id = viewer_object->getItemID(); + const LLUUID attachment_id = viewer_object->getItemID(); if (LLVOAvatar::detachObject(viewer_object)) { // the simulator should automatically handle permission revocation - stopMotionFromSource(item_id); + stopMotionFromSource(attachment_id); LLFollowCamMgr::setCameraActive(viewer_object->getID(), FALSE); LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); @@ -1126,13 +1091,9 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) } else { - LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Removing attachment link:"); - LLAppearanceManager::removeItemLinks(item_id, false); + LLAppearanceManager::unregisterAttachment(attachment_id); } - // BAP - needs to change for label to track link. - gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); - gInventory.notifyObservers(); return TRUE; } return FALSE; @@ -1210,26 +1171,6 @@ void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *sr } // virtual -/* //unused -BOOL LLVOAvatarSelf::getLocalTextureRaw(ETextureIndex index, LLImageRaw* image_raw) const -{ - if (!isIndexLocalTexture(index)) return FALSE; - if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR) return TRUE; - - const LocalTextureData *local_tex_data = getLocalTextureData(index)[0]; - if (local_tex_data->mImage->readBackRaw(-1, image_raw, false)) - { - - return TRUE; - } - - // No data loaded yet - setLocalTexture((ETextureIndex)index, getTEImage(index), FALSE); // <-- non-const, move this elsewhere - return FALSE; -} -*/ - -// virtual BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex_pp, U32 index) const { *tex_pp = NULL; @@ -1426,8 +1367,8 @@ void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_u } // llinfos << "LLVOAvatar::invalidComposite() " << layerset->getBodyRegion() << llendl; - invalidateMorphMasks(layerset->getBakedTexIndex()); layerset->requestUpdate(); + layerset->invalidateMorphMasks(); if( set_by_user ) { @@ -1880,12 +1821,13 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe if (!covered_by_baked) { - if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR) + if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR && imagep->getDiscardLevel() != 0) { F32 desired_pixels; desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); imagep->setBoostLevel(getAvatarBoostLevel()); imagep->addTextureStats( desired_pixels / texel_area_ratio ); + imagep->forceUpdateBindStats() ; if (imagep->getDiscardLevel() < 0) { mHasGrey = TRUE; // for statistics gathering @@ -2183,6 +2125,49 @@ BOOL LLVOAvatarSelf::needsRenderBeam() // static void LLVOAvatarSelf::deleteScratchTextures() { + if(gAuditTexture) + { + S32 total_tex_size = sScratchTexBytes ; + S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ; + + if( sScratchTexNames.checkData( GL_LUMINANCE ) ) + { + LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= tex_size ; + } + if( sScratchTexNames.checkData( GL_ALPHA ) ) + { + LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= tex_size ; + } + if( sScratchTexNames.checkData( GL_COLOR_INDEX ) ) + { + LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= tex_size ; + } + if( sScratchTexNames.checkData( GL_LUMINANCE_ALPHA ) ) + { + LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= 2 * tex_size ; + } + if( sScratchTexNames.checkData( GL_RGB ) ) + { + LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= 3 * tex_size ; + } + if( sScratchTexNames.checkData( GL_RGBA ) ) + { + LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= 4 * tex_size ; + } + //others + while(total_tex_size > 0) + { + LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + total_tex_size -= 4 * tex_size ; + } + } + for( LLGLuint* namep = sScratchTexNames.getFirstData(); namep; namep = sScratchTexNames.getNextData() ) @@ -2205,7 +2190,8 @@ void LLVOAvatarSelf::deleteScratchTextures() BOOL LLVOAvatarSelf::bindScratchTexture( LLGLenum format ) { U32 texture_bytes = 0; - GLuint gl_name = getScratchTexName( format, &texture_bytes ); + S32 components = 0; + GLuint gl_name = getScratchTexName( format, components, &texture_bytes ); if( gl_name ) { gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); @@ -2217,12 +2203,12 @@ BOOL LLVOAvatarSelf::bindScratchTexture( LLGLenum format ) if( *last_bind_time != LLImageGL::sLastFrameTime ) { *last_bind_time = LLImageGL::sLastFrameTime; - LLImageGL::updateBoundTexMem(texture_bytes); + LLImageGL::updateBoundTexMem(texture_bytes, components, LLViewerTexture::AVATAR_SCRATCH_TEX) ; } } else { - LLImageGL::updateBoundTexMem(texture_bytes); + LLImageGL::updateBoundTexMem(texture_bytes, components, LLViewerTexture::AVATAR_SCRATCH_TEX) ; sScratchTexLastBindTime.addData( format, new F32(LLImageGL::sLastFrameTime) ); } return TRUE; @@ -2230,9 +2216,8 @@ BOOL LLVOAvatarSelf::bindScratchTexture( LLGLenum format ) return FALSE; } -LLGLuint LLVOAvatarSelf::getScratchTexName( LLGLenum format, U32* texture_bytes ) -{ - S32 components; +LLGLuint LLVOAvatarSelf::getScratchTexName( LLGLenum format, S32& components, U32* texture_bytes ) +{ GLenum internal_format; switch( format ) { @@ -2278,6 +2263,11 @@ LLGLuint LLVOAvatarSelf::getScratchTexName( LLGLenum format, U32* texture_bytes sScratchTexBytes += *texture_bytes; LLImageGL::sGlobalTextureMemoryInBytes += *texture_bytes; + + if(gAuditTexture) + { + LLImageGL::incTextureCounter(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, components, LLViewerTexture::AVATAR_SCRATCH_TEX) ; + } return name; } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 6e52b33634..8a66422c44 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -241,7 +241,7 @@ public: BOOL bindScratchTexture(LLGLenum format); static void deleteScratchTextures(); protected: - LLGLuint getScratchTexName(LLGLenum format, U32* texture_bytes); + LLGLuint getScratchTexName(LLGLenum format, S32& components, U32* texture_bytes); private: static S32 sScratchTexBytes; static LLMap< LLGLenum, LLGLuint*> sScratchTexNames; diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index 8d3c8b6f1a..177cb16c50 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -101,7 +101,7 @@ void LLVOClouds::setPixelAreaAndAngle(LLAgent &agent) mPixelArea = 1500*100; } -void LLVOClouds::updateTextures(LLAgent &agent) +void LLVOClouds::updateTextures() { getTEImage(0)->addTextureStats(mPixelArea); } diff --git a/indra/newview/llvoclouds.h b/indra/newview/llvoclouds.h index 95e6b96e4e..c4a75f5b5e 100644 --- a/indra/newview/llvoclouds.h +++ b/indra/newview/llvoclouds.h @@ -65,7 +65,7 @@ public: /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. F32 getPartSize(S32 idx); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area void updateFaceSize(S32 idx) { } diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 570a3334b9..f33a5cc818 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -106,7 +106,7 @@ void LLVOGrass::updateSpecies() SpeciesMap::const_iterator it = sSpeciesTable.begin(); mSpecies = (*it).first; } - setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE)); + setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } @@ -322,7 +322,7 @@ void LLVOGrass::setPixelAreaAndAngle(LLAgent &agent) // BUG could speed this up by caching the relative_position and range calculations -void LLVOGrass::updateTextures(LLAgent &agent) +void LLVOGrass::updateTextures() { if (getTEImage(0)) { diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index 124400d356..6a6fcc31c3 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -72,7 +72,7 @@ public: LLStrider<U16>& indicesp); void updateFaceSize(S32 idx) { } - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ BOOL updateLOD(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp index ac2484ddfd..221c6b61ec 100644 --- a/indra/newview/llvoground.cpp +++ b/indra/newview/llvoground.cpp @@ -70,7 +70,7 @@ BOOL LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } -void LLVOGround::updateTextures(LLAgent &agent) +void LLVOGround::updateTextures() { } diff --git a/indra/newview/llvoground.h b/indra/newview/llvoground.h index af3fcd65d4..0ccb0834a2 100644 --- a/indra/newview/llvoground.h +++ b/indra/newview/llvoground.h @@ -51,7 +51,7 @@ public: // Graphical stuff for objects - maybe broken out into render class // later? - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 9bafc03a6d..e777d7362f 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -142,7 +142,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) { mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime; - mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, TRUE); + mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI); mSoundSymbol.mWaveActive [i] = false; mSoundSymbol.mWaveOpacity [i] = 1.0f; mSoundSymbol.mWaveExpansion [i] = 1.0f; diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 143cd2d9c6..9dd0b598dc 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -108,7 +108,7 @@ void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent) } } -void LLVOPartGroup::updateTextures(LLAgent &agent) +void LLVOPartGroup::updateTextures() { // Texture stats for particles need to be updated in a different way... } diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 3dc3292992..18583b4be9 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -61,7 +61,7 @@ public: virtual U32 getPartitionType() const; /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index d44c543266..5ff8f0d267 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -289,7 +289,7 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { - mTexture[which]->createGLTexture(0, mImageRaw[which]); + mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerTexture::LOCAL); mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -376,9 +376,9 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mSun.setIntensity(SUN_INTENSITY); mMoon.setIntensity(0.1f * SUN_INTENSITY); - mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, TRUE); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI); mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, TRUE); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; @@ -472,9 +472,9 @@ void LLVOSky::restoreGL() { mSkyTex[i].restoreGL(); } - mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, TRUE); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI); mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, TRUE); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; @@ -1180,7 +1180,7 @@ BOOL LLVOSky::updateSky() return TRUE; } -void LLVOSky::updateTextures(LLAgent &agent) +void LLVOSky::updateTextures() { if (mSunTexturep) { diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index 62c934fb41..ef74324e58 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -492,7 +492,7 @@ public: // Graphical stuff for objects - maybe broken out into render class // later? - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 164f0f0cad..ef7b161003 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -134,7 +134,7 @@ void LLVOSurfacePatch::setPixelAreaAndAngle(LLAgent &agent) } -void LLVOSurfacePatch::updateTextures(LLAgent &agent) +void LLVOSurfacePatch::updateTextures() { } diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index aaf4d41fa1..10a5888526 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -75,7 +75,7 @@ public: LLStrider<LLVector2> &texCoords1p, LLStrider<U16> &indicesp); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); diff --git a/indra/newview/llvotextbubble.cpp b/indra/newview/llvotextbubble.cpp index f5094c025e..75beab519e 100644 --- a/indra/newview/llvotextbubble.cpp +++ b/indra/newview/llvotextbubble.cpp @@ -115,7 +115,7 @@ BOOL LLVOTextBubble::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } -void LLVOTextBubble::updateTextures(LLAgent &agent) +void LLVOTextBubble::updateTextures() { // Update the image levels of all textures... diff --git a/indra/newview/llvotextbubble.h b/indra/newview/llvotextbubble.h index 45d4df2a7e..7f84dbf631 100644 --- a/indra/newview/llvotextbubble.h +++ b/indra/newview/llvotextbubble.h @@ -44,7 +44,7 @@ public: /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ BOOL updateLOD(); diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 615ae13bc2..235e10f716 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -311,7 +311,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, // // Load Species-Specific data // - mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mBranchLength = sSpeciesTable[mSpecies]->mBranchLength; mTrunkLength = sSpeciesTable[mSpecies]->mTrunkLength; mLeafScale = sSpeciesTable[mSpecies]->mLeafScale; @@ -463,7 +463,7 @@ void LLVOTree::setPixelAreaAndAngle(LLAgent &agent) #endif } -void LLVOTree::updateTextures(LLAgent &agent) +void LLVOTree::updateTextures() { if (mTreeImagep) { diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index 13817fa111..feac9e0675 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -69,7 +69,7 @@ public: // Graphical stuff for objects - maybe broken out into render class later? /*virtual*/ void render(LLAgent &agent); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/indra/newview/llvotreenew.h b/indra/newview/llvotreenew.h index 3fec5855ef..426470101d 100644 --- a/indra/newview/llvotreenew.h +++ b/indra/newview/llvotreenew.h @@ -156,7 +156,7 @@ public: /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ void render(LLAgent &agent); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 7d4bef3f7d..021fc74648 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -53,12 +53,10 @@ #include "lldrawpoolbump.h" #include "llface.h" #include "llspatialpartition.h" - -// TEMP HACK ventrella #include "llhudmanager.h" #include "llflexibleobject.h" - #include "llsky.h" +#include "lltexturefetch.h" #include "llviewercamera.h" #include "llviewertexturelist.h" #include "llviewerregion.h" @@ -75,7 +73,6 @@ const S32 MIN_QUIET_FRAMES_COALESCE = 30; const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; const F32 FORCE_CULL_AREA = 8.f; const F32 MAX_LOD_DISTANCE = 24.f; -const S32 MAX_SCULPT_REZ = 128; BOOL gAnimateTextures = TRUE; @@ -151,7 +148,6 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mRelativeXformInvTrans.setIdentity(); mLOD = MIN_LOD; - mSculptLevel = -2; mTextureAnimp = NULL; mVObjRadius = LLVector3(1,1,0.5f).length(); mNumFaces = 0; @@ -564,28 +560,32 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return TRUE; } -void LLVOVolume::updateTextures(LLAgent &agent) +void LLVOVolume::updateTextures() { const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds - if (mDrawable.notNull() && mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) { - if (mDrawable->isVisible()) - { - updateTextures(); - } + updateTextureVirtualSize(); } } -void LLVOVolume::updateTextures() +void LLVOVolume::updateTextureVirtualSize() { // Update the pixel area of all faces + if(mDrawable.isNull() || !mDrawable->isVisible()) + { + return ; + } + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) { return; } - - if (LLViewerTexture::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible()) + + static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable"); + + if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) { return; } @@ -602,14 +602,15 @@ void LLVOVolume::updateTextures() LLFace* face = mDrawable->getFace(i); const LLTextureEntry *te = face->getTextureEntry(); LLViewerTexture *imagep = face->getTexture(); - if (!imagep || !te || + if (!imagep || !te || face->mExtents[0] == face->mExtents[1]) { continue; } F32 vsize; - + F32 old_size = face->getVirtualSize(); + if (isHUDAttachment()) { F32 area = (F32) LLViewerCamera::getInstance()->getScreenPixelArea(); @@ -619,12 +620,10 @@ void LLVOVolume::updateTextures() } else { - vsize = getTextureVirtualSize(face); + vsize = face->getTextureVirtualSize(); } - mPixelArea = llmax(mPixelArea, face->getPixelArea()); - - F32 old_size = face->getVirtualSize(); + mPixelArea = llmax(mPixelArea, face->getPixelArea()); if (face->mTextureMatrix != NULL) { @@ -636,7 +635,6 @@ void LLVOVolume::updateTextures() } face->setVirtualSize(vsize); - imagep->addTextureStats(vsize); if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { if (vsize < min_vsize) min_vsize = vsize; @@ -665,35 +663,47 @@ void LLVOVolume::updateTextures() { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); LLUUID id = sculpt_params->getSculptTexture(); - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (mSculptTexture.notNull()) { - S32 lod = llmin(mLOD, 3); - F32 lodf = ((F32)(lod + 1.0f)/4.f); - F32 tex_size = lodf * MAX_SCULPT_REZ; - mSculptTexture->addTextureStats(2.f * tex_size * tex_size); mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), (S32)LLViewerTexture::BOOST_SCULPTED)); mSculptTexture->setForSculpt() ; - } - - S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture - S32 current_discard = mSculptLevel; + + if(!mSculptTexture->isCachedRawImageReady()) + { + S32 lod = llmin(mLOD, 3); + F32 lodf = ((F32)(lod + 1.0f)/4.f); + F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; + mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); + + //if the sculpty very close to the view point, load first + { + LLVector3 lookAt = getPositionAgent() - LLViewerCamera::getInstance()->getOrigin(); + F32 dist = lookAt.normVec() ; + F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; + mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; + } + } + + S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture + S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; - if (texture_discard >= 0 && //texture has some data available - (texture_discard < current_discard || //texture has more data than last rebuild - current_discard < 0)) //no previous rebuild - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mSculptChanged = TRUE; - } + if (texture_discard >= 0 && //texture has some data available + (texture_discard < current_discard || //texture has more data than last rebuild + current_discard < 0)) //no previous rebuild + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mSculptChanged = TRUE; + } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) { setDebugText(llformat("T%d C%d V%d\n%dx%d", - texture_discard, current_discard, getVolume()->getSculptLevel(), - mSculptTexture->getHeight(), mSculptTexture->getWidth())); + texture_discard, current_discard, getVolume()->getSculptLevel(), + mSculptTexture->getHeight(), mSculptTexture->getWidth())); } + } } if (getLightTextureID().notNull()) @@ -714,10 +724,10 @@ void LLVOVolume::updateTextures() { setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); - } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); + } else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) { setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); @@ -729,36 +739,6 @@ void LLVOVolume::updateTextures() } } -F32 LLVOVolume::getTextureVirtualSize(LLFace* face) -{ - //get area of circle around face - LLVector3 center = face->getPositionAgent(); - LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f; - - F32 face_area = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); - - face->setPixelArea(face_area); - - if (face_area <= 0) - { - return 0.f; - } - - //get area of circle in texture space - LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0]; - F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; - if (texel_area <= 0) - { - // Probably animated, use default - texel_area = 1.f; - } - - //apply texel area to face area to get accurate ratio - face_area /= llclamp(texel_area, 1.f/64.f, 16.f); - - return face_area; -} - BOOL LLVOVolume::isActive() const { return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()); @@ -835,7 +815,6 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) return mDrawable; } - BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume) { // Check if we need to change implementations @@ -876,7 +855,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail if (isSculpted()) { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (mSculptTexture.notNull()) { //ignore sculpt GL usage since bao fixed this in a separate branch @@ -890,7 +869,6 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail { sculpt(); } - mSculptLevel = getVolume()->getSculptLevel(); } } else @@ -905,32 +883,22 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() -{ - U16 sculpt_height = 0; - U16 sculpt_width = 0; - S8 sculpt_components = 0; - const U8* sculpt_data = NULL; - +{ if (mSculptTexture.notNull()) - { - S32 discard_level; - S32 desired_discard = 0; // lower discard levels have MUCH less resolution - - discard_level = desired_discard; + { + U16 sculpt_height = 0; + U16 sculpt_width = 0; + S8 sculpt_components = 0; + const U8* sculpt_data = NULL; + + S32 discard_level = mSculptTexture->getDiscardLevel() ; + LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; S32 max_discard = mSculptTexture->getMaxDiscardLevel(); if (discard_level > max_discard) discard_level = max_discard; // clamp to the best we can do - S32 best_discard = mSculptTexture->getDiscardLevel(); - if (discard_level < best_discard) - discard_level = best_discard; // clamp to what we have - - if (best_discard == -1) - discard_level = -1; // and if we have nothing, set to nothing - - - S32 current_discard = getVolume()->getSculptLevel(); + S32 current_discard = getVolume()->getSculptLevel() ; if(current_discard < -2) { llwarns << "WARNING!!: Current discard of sculpty at " << current_discard @@ -951,18 +919,7 @@ void LLVOVolume::sculpt() if (current_discard == discard_level) // no work to do here return; - LLPointer<LLImageRaw> raw_image = new LLImageRaw(); - BOOL is_valid = mSculptTexture->readBackRaw(discard_level, raw_image, FALSE); - - sculpt_height = raw_image->getHeight(); - sculpt_width = raw_image->getWidth(); - sculpt_components = raw_image->getComponents(); - - if(is_valid) - { - is_valid = mSculptTexture->isValidForSculpt(discard_level, sculpt_width, sculpt_height, sculpt_components) ; - } - if(!is_valid) + if(!raw_image) { sculpt_width = 0; sculpt_height = 0; @@ -974,10 +931,10 @@ void LLVOVolume::sculpt() } } else - { - if (raw_image->getDataSize() < sculpt_height * sculpt_width * sculpt_components) - llerrs << "Sculpt: image data size = " << raw_image->getDataSize() - << " < " << sculpt_height << " x " << sculpt_width << " x " <<sculpt_components << llendl; + { + sculpt_height = raw_image->getHeight(); + sculpt_width = raw_image->getWidth(); + sculpt_components = raw_image->getComponents(); sculpt_data = raw_image->getData(); @@ -1013,12 +970,6 @@ BOOL LLVOVolume::calcLOD() return FALSE; } - //update face texture sizes on lod calculation - //if (mDrawable->isVisible()) - //{ - // updateTextures(); - //} - S32 cur_detail = 0; F32 radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length(); @@ -1036,7 +987,7 @@ BOOL LLVOVolume::calcLOD() } // DON'T Compensate for field of view changing on FOV zoom. - distance *= 3.14159f/3.f; + distance *= F_PI/3.f; cur_detail = computeLODDetail(llround(distance, 0.01f), llround(radius, 0.01f)); @@ -1687,6 +1638,45 @@ bool LLVOVolume::hasMedia() const return result; } +LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) +{ + LLVector3 result = LLVector3::zero; + + LLFace* facep = mDrawable->getFace(face_id); + if(facep) + { + LLStrider<LLVector3> verticesp; + LLStrider<LLVector3> normalsp; + LLStrider<LLVector2> texCoordsp; + LLStrider<U16> indicesp; + S32 index_offset; + index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); + + if(index_offset != -1 && (normalsp.get() != NULL)) + { + U16 count = facep->getGeomCount(); + U16 i; + + for(i=0; i < count; i++) + { + LLVector3 normal = *normalsp++; +// llinfos << "adding " << normal << llendl; + result += normal; + } + } + } + + if(!result.isNull()) + { +// llinfos << "before conversion: " << result << llendl; + result = volumeDirectionToAgent(result); + result.normalize(); +// llinfos << "after conversion: " << result << llendl; + } + + return result; +} + void LLVOVolume::requestMediaDataUpdate() { sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this)); @@ -1796,20 +1786,19 @@ void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type) { - // NOTE: This logic duplicates the logic in the server (in particular, in llmediaservice.cpp). + // NOTE: This logic ALMOST duplicates the logic in the server (in particular, in llmediaservice.cpp). if (NULL == media_entry ) return false; // XXX should we assert here? - // The agent has permissions to navigate if: - // - agent has edit permissions, or + // The agent has permissions if: // - world permissions are on, or // - group permissions are on, and agent_id is in the group, or // - agent permissions are on, and agent_id is the owner - if (permModify()) - { - return true; - } - + // *NOTE: We *used* to check for modify permissions here (i.e. permissions were + // granted if permModify() was true). However, this doesn't make sense in the + // viewer: we don't want to show controls or allow interaction if the author + // has deemed it so. See DEV-42115. + U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl(); // World permissions @@ -2784,7 +2773,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e if (face == -1) { start_face = 0; - end_face = volume->getNumFaces(); + end_face = volume->getNumVolumeFaces(); } else { @@ -2799,8 +2788,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit) { - LLFace* face = mDrawable->getFace(face_hit); - + LLFace* face = mDrawable->getFace(face_hit); + if (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))) { v_end = p; @@ -3047,7 +3036,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLVOVolume* vobj = drawablep->getVOVolume(); llassert_always(vobj); - vobj->updateTextures(); + vobj->updateTextureVirtualSize(); vobj->preRebuild(); drawablep->clearState(LLDrawable::HAS_ALPHA); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 00810b22c4..784ef16ba3 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -139,7 +139,7 @@ public: BOOL getVolumeChanged() const { return mVolumeChanged; } - F32 getTextureVirtualSize(LLFace* face); + /*virtual*/ F32 getRadius() const { return mVObjRadius; }; const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; @@ -187,8 +187,8 @@ public: /*virtual*/ void updateFaceSize(S32 idx); /*virtual*/ BOOL updateLOD(); void updateRadius(); - /*virtual*/ void updateTextures(LLAgent &agent); - void updateTextures(); + /*virtual*/ void updateTextures(); + void updateTextureVirtualSize(); void updateFaceFlags(); void regenFaces(); @@ -263,6 +263,8 @@ public: F64 getTotalMediaInterest() const; bool hasMedia() const; + + LLVector3 getApproximateFaceNormal(U8 face_id); protected: S32 computeLODDetail(F32 distance, F32 radius); @@ -284,7 +286,6 @@ private: LLFrameTimer mTextureUpdateTimer; S32 mLOD; BOOL mLODChanged; - S32 mSculptLevel; BOOL mSculptChanged; F32 mSpotLightPriority; LLMatrix4 mRelativeXform; diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 0c967f9020..e5ff62746e 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -100,7 +100,7 @@ void LLVOWater::setPixelAreaAndAngle(LLAgent &agent) // virtual -void LLVOWater::updateTextures(LLAgent &agent) +void LLVOWater::updateTextures() { } diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h index 28a5633c58..3cc031e589 100644 --- a/indra/newview/llvowater.h +++ b/indra/newview/llvowater.h @@ -68,7 +68,7 @@ public: /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area virtual U32 getPartitionType() const; diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 8621e5e1d9..d3238f16a8 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -49,12 +49,12 @@ const U32 LLVOWLSky::MAX_SKY_DETAIL = 180; inline U32 LLVOWLSky::getNumStacks(void) { - return gSavedSettings.getU32("WLSkyDetail"); + return llmin(MAX_SKY_DETAIL, llmax(MIN_SKY_DETAIL, gSavedSettings.getU32("WLSkyDetail"))); } inline U32 LLVOWLSky::getNumSlices(void) { - return 2 * gSavedSettings.getU32("WLSkyDetail"); + return 2 * llmin(MAX_SKY_DETAIL, llmax(MIN_SKY_DETAIL, gSavedSettings.getU32("WLSkyDetail"))); } inline U32 LLVOWLSky::getFanNumVerts(void) diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 4cd29bb838..2b4861ce4f 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -60,7 +60,7 @@ static std::string asset_id_to_filename(const LLUUID &asset_id); LLWearable::LLWearable(const LLTransactionID& transaction_id) : mDefinitionVersion(LLWearable::sCurrentDefinitionVersion), - mType(WT_SHAPE) + mType(WT_INVALID) { mTransactionID = transaction_id; mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); @@ -68,7 +68,7 @@ LLWearable::LLWearable(const LLTransactionID& transaction_id) : LLWearable::LLWearable(const LLAssetID& asset_id) : mDefinitionVersion( LLWearable::sCurrentDefinitionVersion ), - mType(WT_SHAPE) + mType(WT_INVALID) { mAssetID = asset_id; mTransactionID.setNull(); @@ -181,13 +181,7 @@ void LLWearable::createVisualParams() { if (param->getWearableType() == mType) { - if (mVisualParamIndexMap[param->getID()]) - { - delete mVisualParamIndexMap[param->getID()]; - } - LLViewerVisualParam *new_param = param->cloneParam(this); - new_param->setIsDummy(FALSE); - mVisualParamIndexMap[param->getID()] = new_param; + addVisualParam(param->cloneParam(this)); } } @@ -661,7 +655,7 @@ void LLWearable::writeToAvatar( BOOL set_by_user, BOOL update_customize_floater { image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te); } - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE ); + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); // MULTI-WEARABLE: replace hard-coded 0 avatar->setLocalTextureTE(te, image, set_by_user, 0); } @@ -750,7 +744,8 @@ void LLWearable::copyDataFrom(const LLWearable* src) mDescription = src->mDescription; mPermissions = src->mPermissions; mSaleInfo = src->mSaleInfo; - mType = src->mType; + + setType(src->mType); mSavedVisualParamMap.clear(); // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed) @@ -763,9 +758,6 @@ void LLWearable::copyDataFrom(const LLWearable* src) S32 id = param->getID(); F32 weight = src->getVisualParamWeight(id); mSavedVisualParamMap[id] = weight; - - // Clones a visual param from src and adds it to this wearable. Value of param is taken from current value of source param, not saved. - addVisualParam(param->cloneParam(this)); } } @@ -860,6 +852,7 @@ void LLWearable::addVisualParam(LLVisualParam *param) { delete mVisualParamIndexMap[param->getID()]; } + param->setIsDummy(FALSE); mVisualParamIndexMap[param->getID()] = param; } @@ -1123,7 +1116,7 @@ void LLWearable::saveNewAsset() const { llinfos << "Update Agent Inventory via capability" << llendl; LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType(getAssetType()); + body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetToFolderType(getAssetType())); body["asset_type"] = LLAssetType::lookup(getAssetType()); body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE); body["name"] = getName(); diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index da62223aac..9bde85dcaf 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -70,6 +70,11 @@ struct LLWearableArrivedData LLWearableList::~LLWearableList() { + llassert_always(mList.empty()) ; +} + +void LLWearableList::cleanup() +{ for_each(mList.begin(), mList.end(), DeletePairedPointer()); mList.clear(); } diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h index e5155c66a4..cf1a9bddff 100644 --- a/indra/newview/llwearablelist.h +++ b/indra/newview/llwearablelist.h @@ -44,6 +44,7 @@ class LLWearableList : public LLSingleton<LLWearableList> public: LLWearableList() {} ~LLWearableList(); + void cleanup() ; S32 getLength() const { return mList.size(); } diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 3204c2d264..72431bd22f 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -43,8 +43,9 @@ #include "llfloatermediabrowser.h" #include "llfloaterreg.h" #include "llalertdialog.h" +#include "lltoastalertpanel.h" -class URLLoader : public LLAlertDialog::URLLoader +class URLLoader : public LLAlertURLLoader { virtual void load(const std::string& url , bool force_open_externally) { @@ -65,6 +66,7 @@ static URLLoader sAlertURLLoader; void LLWeb::initClass() { LLAlertDialog::setURLLoader(&sAlertURLLoader); + LLToastAlertPanel::setURLLoader(&sAlertURLLoader); } diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index 1581153c19..c6fd35c142 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -196,7 +196,7 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate) escaped_filename += ".xml"; std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", escaped_filename)); - llinfos << "Loading WindLight sky setting from " << pathName << llendl; + //llinfos << "Loading WindLight sky setting from " << pathName << llendl; llifstream presetsXML; presetsXML.open(pathName.c_str()); diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index f198f3a0cf..66cb02ce99 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -34,57 +34,81 @@ #include "llworldmap.h" -#include "llregionhandle.h" +#include "llworldmapmessage.h" #include "message.h" - -#include "llagent.h" -#include "llmapresponders.h" -#include "llviewercontrol.h" -#include "llfloaterworldmap.h" #include "lltracker.h" #include "llviewertexturelist.h" -#include "llviewerregion.h" -#include "llregionflags.h" #include "lltrans.h" -const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // 10 minutes +// Timers to temporise database requests +const F32 AGENTS_UPDATE_TIMER = 60.0; // Seconds between 2 agent requests for a region +const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // Seconds before we consider re-requesting item data for the grid + +//--------------------------------------------------------------------------- +// LLItemInfo +//--------------------------------------------------------------------------- -// For DEV-17507, do lazy image loading in llworldmapview.cpp instead, -// limiting requests to currently visible regions and minimizing the -// number of textures being requested simultaneously. -// -// Uncomment IMMEDIATE_IMAGE_LOAD to restore the old behavior -// -//#define IMMEDIATE_IMAGE_LOAD LLItemInfo::LLItemInfo(F32 global_x, F32 global_y, const std::string& name, - LLUUID id, - S32 extra, S32 extra2) + LLUUID id) : mName(name), mToolTip(""), mPosGlobal(global_x, global_y, 40.0), mID(id), - mSelected(FALSE), - mExtra(extra), - mExtra2(extra2) + mCount(1) +// mSelected(false) +// mColor() { - mRegionHandle = to_region_handle(mPosGlobal); } -LLSimInfo::LLSimInfo() -: mHandle(0), +//--------------------------------------------------------------------------- +// LLSimInfo +//--------------------------------------------------------------------------- + +LLSimInfo::LLSimInfo(U64 handle) +: mHandle(handle), mName(), mAgentsUpdateTime(0), - mShowAgentLocations(FALSE), mAccess(0x0), mRegionFlags(0x0), - mWaterHeight(0.f), - mAlpha(-1.f) + mFirstAgentRequest(true) +// mWaterHeight(0.f) +{ +} + +void LLSimInfo::setLandForSaleImage (LLUUID image_id) { + mMapImageID = image_id; + + // Fetch the image + if (mMapImageID.notNull()) + { + mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); + } + else + { + mOverlayImage = NULL; + } } +LLPointer<LLViewerFetchedTexture> LLSimInfo::getLandForSaleImage () +{ + if (mOverlayImage.isNull() && mMapImageID.notNull()) + { + // Fetch the image if it hasn't been done yet (unlikely but...) + mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); + } + if (!mOverlayImage.isNull()) + { + // Boost the fetch level when we try to access that image + mOverlayImage->setBoostLevel(LLViewerTexture::BOOST_MAP); + } + return mOverlayImage; +} -LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const +LLVector3d LLSimInfo::getGlobalPos(const LLVector3& local_pos) const { LLVector3d pos = from_region_handle(mHandle); pos.mdV[VX] += local_pos.mV[VX]; @@ -93,128 +117,184 @@ LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const return pos; } +LLVector3d LLSimInfo::getGlobalOrigin() const +{ + return from_region_handle(mHandle); +} LLVector3 LLSimInfo::getLocalPos(LLVector3d global_pos) const { LLVector3d sim_origin = from_region_handle(mHandle); return LLVector3(global_pos - sim_origin); } +void LLSimInfo::clearImage() +{ + if (!mOverlayImage.isNull()) + { + mOverlayImage->setBoostLevel(0); + mOverlayImage = NULL; + } +} - -//--------------------------------------------------------------------------- -// World Map -//--------------------------------------------------------------------------- - -LLWorldMap::LLWorldMap() : - mIsTrackingUnknownLocation( FALSE ), - mInvalidLocation( FALSE ), - mIsTrackingDoubleClick( FALSE ), - mIsTrackingCommit( FALSE ), - mUnknownLocation( 0, 0, 0 ), - mRequestLandForSale(true), - mCurrentMap(0), - mMinX(U32_MAX), - mMaxX(U32_MIN), - mMinY(U32_MAX), - mMaxY(U32_MIN), - mNeighborMap(NULL), - mTelehubCoverageMap(NULL), - mNeighborMapWidth(0), - mNeighborMapHeight(0), - mSLURLRegionName(), - mSLURLRegionHandle(0), - mSLURL(), - mSLURLCallback(0), - mSLURLTeleport(false) -{ - for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map) +void LLSimInfo::dropImagePriority() +{ + if (!mOverlayImage.isNull()) { - mMapLoaded[map] = FALSE; - mMapBlockLoaded[map] = new BOOL[MAP_BLOCK_RES*MAP_BLOCK_RES]; - for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx) - { - mMapBlockLoaded[map][idx] = FALSE; - } + mOverlayImage->setBoostLevel(0); } } +// Update the agent count for that region +void LLSimInfo::updateAgentCount(F64 time) +{ + if ((time - mAgentsUpdateTime > AGENTS_UPDATE_TIMER) || mFirstAgentRequest) + { + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_AGENT_LOCATIONS, mHandle); + mAgentsUpdateTime = time; + mFirstAgentRequest = false; + } +} -LLWorldMap::~LLWorldMap() +// Get the total agents count +const S32 LLSimInfo::getAgentCount() const { - reset(); - for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map) + S32 total_agent_count = 0; + for (LLSimInfo::item_info_list_t::const_iterator it = mAgentLocations.begin(); it != mAgentLocations.end(); ++it) { - delete[] mMapBlockLoaded[map]; + total_agent_count += it->getCount(); } + return total_agent_count; } +bool LLSimInfo::isName(const std::string& name) const +{ + return (LLStringUtil::compareInsensitive(name, mName) == 0); +} -void LLWorldMap::reset() +void LLSimInfo::dump() const { - for_each(mSimInfoMap.begin(), mSimInfoMap.end(), DeletePairedPointer()); - mSimInfoMap.clear(); + U32 x_pos, y_pos; + from_region_handle(mHandle, &x_pos, &y_pos); + + LL_INFOS("World Map") << x_pos << "," << y_pos + << " " << mName + << " " << (S32)mAccess + << " " << std::hex << mRegionFlags << std::dec +// << " " << mWaterHeight + << LL_ENDL; +} + +void LLSimInfo::clearItems() +{ + mTelehubs.clear(); + mInfohubs.clear(); + mPGEvents.clear(); + mMatureEvents.clear(); + mAdultEvents.clear(); + mLandForSale.clear(); + mLandForSaleAdult.clear(); +// We persist the agent count though as it is updated on a frequent basis +// mAgentLocations.clear(); +} + +void LLSimInfo::insertAgentLocation(const LLItemInfo& item) +{ + std::string name = item.getName(); - for (S32 m=0; m<MAP_SIM_IMAGE_TYPES; ++m) + // Find the last item in the list with a different name and erase them + item_info_list_t::iterator lastiter; + for (lastiter = mAgentLocations.begin(); lastiter != mAgentLocations.end(); ++lastiter) + { + LLItemInfo& info = *lastiter; + if (info.isName(name)) + { + break; + } + } + if (lastiter != mAgentLocations.begin()) { - mMapLoaded[m] = FALSE; + mAgentLocations.erase(mAgentLocations.begin(), lastiter); } + // Now append the new location + mAgentLocations.push_back(item); +} + +//--------------------------------------------------------------------------- +// World Map +//--------------------------------------------------------------------------- + +LLWorldMap::LLWorldMap() : + mIsTrackingLocation( false ), + mIsTrackingFound( false ), + mIsInvalidLocation( false ), + mIsTrackingDoubleClick( false ), + mIsTrackingCommit( false ), + mTrackingLocation( 0, 0, 0 ), + mFirstRequest(true) +{ + //LL_INFOS("World Map") << "Creating the World Map -> LLWorldMap::LLWorldMap()" << LL_ENDL; + mMapBlockLoaded = new bool[MAP_BLOCK_RES*MAP_BLOCK_RES]; clearSimFlags(); - - eraseItems(); +} - mMinX = U32_MAX; - mMaxX = U32_MIN; - mMinY = U32_MAX; - mMaxY = U32_MIN; +LLWorldMap::~LLWorldMap() +{ + //LL_INFOS("World Map") << "Destroying the World Map -> LLWorldMap::~LLWorldMap()" << LL_ENDL; + reset(); + delete[] mMapBlockLoaded; +} - delete [] mNeighborMap; - mNeighborMap = NULL; - delete [] mTelehubCoverageMap; - mTelehubCoverageMap = NULL; - mNeighborMapWidth = 0; - mNeighborMapHeight = 0; +void LLWorldMap::reset() +{ + clearItems(true); // Clear the items lists + clearImageRefs(); // Clear the world mipmap and the land for sale tiles + clearSimFlags(); // Clear the block info flags array - for (S32 i=0; i<MAP_SIM_IMAGE_TYPES; i++) - { - mMapLayers[i].clear(); - } + // Finally, clear the region map itself + for_each(mSimInfoMap.begin(), mSimInfoMap.end(), DeletePairedPointer()); + mSimInfoMap.clear(); } -void LLWorldMap::eraseItems() +// Returns true if the items have been cleared +bool LLWorldMap::clearItems(bool force) { - if (mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER) + bool clear = false; + if ((mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER) || mFirstRequest || force) { mRequestTimer.reset(); - mTelehubs.clear(); - mInfohubs.clear(); - mPGEvents.clear(); - mMatureEvents.clear(); - mAdultEvents.clear(); - mLandForSale.clear(); + LLSimInfo* sim_info = NULL; + for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) + { + sim_info = it->second; + if (sim_info) + { + sim_info->clearItems(); + } + } + clear = true; + mFirstRequest = false; } -// mAgentLocationsMap.clear(); // persists -// mNumAgents.clear(); // persists + return clear; } - void LLWorldMap::clearImageRefs() { + // We clear the reference to the images we're holding. + // Images hold by the world mipmap first + mWorldMipmap.reset(); + + // Images hold by the region map + LLSimInfo* sim_info = NULL; for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) { - LLSimInfo* info = (*it).second; - if (info->mCurrentImage) - { - info->mCurrentImage->setBoostLevel(0); - info->mCurrentImage = NULL; - } - if (info->mOverlayImage) + sim_info = it->second; + if (sim_info) { - info->mOverlayImage->setBoostLevel(0); - info->mOverlayImage = NULL; + sim_info->clearImage(); } } } @@ -222,15 +302,25 @@ void LLWorldMap::clearImageRefs() // Doesn't clear the already-loaded sim infos, just re-requests them void LLWorldMap::clearSimFlags() { - for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map) + for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx) { - for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx) - { - mMapBlockLoaded[map][idx] = FALSE; - } + mMapBlockLoaded[idx] = false; } } +LLSimInfo* LLWorldMap::createSimInfoFromHandle(const U64 handle) +{ + LLSimInfo* sim_info = new LLSimInfo(handle); + mSimInfoMap[handle] = sim_info; + return sim_info; +} + +void LLWorldMap::equalizeBoostLevels() +{ + mWorldMipmap.equalizeBoostLevels(); + return; +} + LLSimInfo* LLWorldMap::simInfoFromPosGlobal(const LLVector3d& pos_global) { U64 handle = to_region_handle(pos_global); @@ -242,11 +332,7 @@ LLSimInfo* LLWorldMap::simInfoFromHandle(const U64 handle) sim_info_map_t::iterator it = mSimInfoMap.find(handle); if (it != mSimInfoMap.end()) { - LLSimInfo* sim_info = (*it).second; - if (sim_info) - { - return sim_info; - } + return it->second; } return NULL; } @@ -257,762 +343,273 @@ LLSimInfo* LLWorldMap::simInfoFromName(const std::string& sim_name) LLSimInfo* sim_info = NULL; if (!sim_name.empty()) { - for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) + // Iterate through the entire sim info map and compare the name + sim_info_map_t::iterator it; + for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) { - sim_info = (*it).second; - if (sim_info - && (0 == LLStringUtil::compareInsensitive(sim_name, sim_info->mName)) ) + sim_info = it->second; + if (sim_info && sim_info->isName(sim_name) ) { + // break out of loop if success break; } - sim_info = NULL; } + // If we got to the end, we haven't found the sim. Reset the ouput value to NULL. + if (it == mSimInfoMap.end()) + sim_info = NULL; } return sim_info; } bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, std::string & outSimName ) { - bool gotSimName = true; + LLSimInfo* sim_info = simInfoFromPosGlobal(pos_global); - U64 handle = to_region_handle(pos_global); - - sim_info_map_t::iterator it = mSimInfoMap.find(handle); - if (it != mSimInfoMap.end()) + if (sim_info) { - LLSimInfo* info = (*it).second; - outSimName = info->mName; + outSimName = sim_info->getName(); } else { - gotSimName = false; outSimName = "(unknown region)"; } - return gotSimName; + return (sim_info != NULL); } -void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer) +void LLWorldMap::reloadItems(bool force) { - mCurrentMap = layer; - if (!mMapLoaded[layer] || request_layer) + //LL_INFOS("World Map") << "LLWorldMap::reloadItems()" << LL_ENDL; + if (clearItems(force)) { - sendMapLayerRequest(); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_TELEHUB); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_PG_EVENT); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_MATURE_EVENT); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_ADULT_EVENT); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_LAND_FOR_SALE); } - - if (mTelehubs.size() == 0 || - mInfohubs.size() == 0) - { - // Request for telehubs - sendItemRequest(MAP_ITEM_TELEHUB); - } - - if (mPGEvents.size() == 0) - { - // Request for events - sendItemRequest(MAP_ITEM_PG_EVENT); - } - - if (mMatureEvents.size() == 0) - { - // Request for events (mature) - sendItemRequest(MAP_ITEM_MATURE_EVENT); - } - - if (mAdultEvents.size() == 0) - { - // Request for events (adult) - sendItemRequest(MAP_ITEM_ADULT_EVENT); - } - - if (mLandForSale.size() == 0) - { - // Request for Land For Sale - sendItemRequest(MAP_ITEM_LAND_FOR_SALE); - } - - if (mLandForSaleAdult.size() == 0) - { - // Request for Land For Sale - sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT); - } - - clearImageRefs(); - clearSimFlags(); } -void LLWorldMap::sendItemRequest(U32 type, U64 handle) -{ - LLMessageSystem* msg = gMessageSystem; - S32 layer = mCurrentMap; - - msg->newMessageFast(_PREHASH_MapItemRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, layer); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - - msg->nextBlockFast(_PREHASH_RequestData); - msg->addU32Fast(_PREHASH_ItemType, type); - msg->addU64Fast(_PREHASH_RegionHandle, handle); // If zero, filled in on sim - - gAgent.sendReliableMessage(); -} -// public -void LLWorldMap::sendMapLayerRequest() +// static public +// Insert a region in the region map +// returns true if region inserted, false otherwise +bool LLWorldMap::insertRegion(U32 x_world, U32 y_world, std::string& name, LLUUID& image_id, U32 accesscode, U32 region_flags) { - if (!gAgent.getRegion()) return; - - LLSD body; - body["Flags"] = mCurrentMap; - std::string url = gAgent.getRegion()->getCapability( - gAgent.isGodlike() ? "MapLayerGod" : "MapLayer"); - - if (!url.empty()) + // This region doesn't exist + if (accesscode == 255) { - llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl; - LLHTTPClient::post(url, body, new LLMapLayerResponder()); + // Checks if the track point is in it and invalidates it if it is + if (LLWorldMap::getInstance()->isTrackingInRectangle( x_world, y_world, x_world + REGION_WIDTH_UNITS, y_world + REGION_WIDTH_UNITS)) + { + LLWorldMap::getInstance()->setTrackingInvalid(); + } + // return failure to insert + return false; } else { - llinfos << "LLWorldMap::sendMapLayerRequest via message system" << llendl; - LLMessageSystem* msg = gMessageSystem; - S32 layer = mCurrentMap; - - // Request for layer - msg->newMessageFast(_PREHASH_MapLayerRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, layer); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - gAgent.sendReliableMessage(); - - if (mRequestLandForSale) + U64 handle = to_region_handle(x_world, y_world); + //LL_INFOS("World Map") << "Map sim : " << name << ", ID : " << image_id.getString() << LL_ENDL; + // Insert the region in the region map of the world map + // Loading the LLSimInfo object with what we got and insert it in the map + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if (siminfo == NULL) { - msg->newMessageFast(_PREHASH_MapLayerRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, 2); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - gAgent.sendReliableMessage(); + siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); } + siminfo->setName(name); + siminfo->setAccess(accesscode); + siminfo->setRegionFlags(region_flags); + // siminfo->setWaterHeight((F32) water_height); + siminfo->setLandForSaleImage(image_id); + + // Handle the location tracking (for teleport, UI feedback and info display) + if (LLWorldMap::getInstance()->isTrackingInRectangle( x_world, y_world, x_world + REGION_WIDTH_UNITS, y_world + REGION_WIDTH_UNITS)) + { + if (siminfo->isDown()) + { + // We were tracking this location, but it's no available + LLWorldMap::getInstance()->setTrackingInvalid(); + } + else + { + // We were tracking this location, and it does exist and is available + LLWorldMap::getInstance()->setTrackingValid(); + } + } + // return insert region success + return true; } } -// public -void LLWorldMap::sendNamedRegionRequest(std::string region_name) -{ - LLMessageSystem* msg = gMessageSystem; - S32 layer = mCurrentMap; - - // Request for layer - msg->newMessageFast(_PREHASH_MapNameRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, layer); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - msg->nextBlockFast(_PREHASH_NameData); - msg->addStringFast(_PREHASH_Name, region_name); - gAgent.sendReliableMessage(); -} -// public -void LLWorldMap::sendNamedRegionRequest(std::string region_name, - url_callback_t callback, - const std::string& callback_url, - bool teleport) // immediately teleport when result returned -{ - mSLURLRegionName = region_name; - mSLURLRegionHandle = 0; - mSLURL = callback_url; - mSLURLCallback = callback; - mSLURLTeleport = teleport; - - sendNamedRegionRequest(region_name); -} - -void LLWorldMap::sendHandleRegionRequest(U64 region_handle, - url_callback_t callback, - const std::string& callback_url, - bool teleport) // immediately teleport when result returned -{ - mSLURLRegionName.clear(); - mSLURLRegionHandle = region_handle; - mSLURL = callback_url; - mSLURLCallback = callback; - mSLURLTeleport = teleport; - - U32 global_x; - U32 global_y; - from_region_handle(region_handle, &global_x, &global_y); - U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); - U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); - - sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); -} - -// public -void LLWorldMap::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) -{ - S32 layer = mCurrentMap; - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MapBlockRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - U32 flags = layer; - flags |= (return_nonexistent ? 0x10000 : 0); - msg->addU32Fast(_PREHASH_Flags, flags); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - msg->nextBlockFast(_PREHASH_PositionData); - msg->addU16Fast(_PREHASH_MinX, min_x); - msg->addU16Fast(_PREHASH_MinY, min_y); - msg->addU16Fast(_PREHASH_MaxX, max_x); - msg->addU16Fast(_PREHASH_MaxY, max_y); - gAgent.sendReliableMessage(); - - if (mRequestLandForSale) - { - msg->newMessageFast(_PREHASH_MapBlockRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_Flags, 2); - msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim - msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim - msg->nextBlockFast(_PREHASH_PositionData); - msg->addU16Fast(_PREHASH_MinX, min_x); - msg->addU16Fast(_PREHASH_MinY, min_y); - msg->addU16Fast(_PREHASH_MaxX, max_x); - msg->addU16Fast(_PREHASH_MaxY, max_y); - gAgent.sendReliableMessage(); - } -} - -// public static -void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**) +// static public +// Insert an item in the relevant region map +// returns true if item inserted, false otherwise +bool LLWorldMap::insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 type, S32 extra, S32 extra2) { - llinfos << "LLWorldMap::processMapLayerReply from message system" << llendl; - - U32 agent_flags; - msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); - - if (agent_flags != (U32)LLWorldMap::getInstance()->mCurrentMap) - { - llwarns << "Invalid or out of date map image type returned!" << llendl; - return; - } + // Create an item record for the received object + LLItemInfo new_item((F32)x_world, (F32)y_world, name, uuid); - LLUUID image_id; - //U32 left, right, top, bottom; + // Compute a region handle based on the objects coordinates + LLVector3d pos((F32)x_world, (F32)y_world, 40.0); + U64 handle = to_region_handle(pos); - S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_LayerData); - - LLWorldMap::getInstance()->mMapLayers[agent_flags].clear(); - - BOOL adjust = FALSE; - for (S32 block=0; block<num_blocks; ++block) + // Get the region record for that handle or NULL if we haven't browsed it yet + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if (siminfo == NULL) { - LLWorldMapLayer new_layer; - new_layer.LayerDefined = TRUE; - msg->getUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block); - new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); - - gGL.getTexUnit(0)->bind(new_layer.LayerImage); - new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); - - U32 left, right, top, bottom; - msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Left, left, block); - msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Right, right, block); - msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Top, top, block); - msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Bottom, bottom, block); - - new_layer.LayerExtents.mLeft = left; - new_layer.LayerExtents.mRight = right; - new_layer.LayerExtents.mBottom = bottom; - new_layer.LayerExtents.mTop = top; - - F32 x_meters = F32(left*REGION_WIDTH_UNITS); - F32 y_meters = F32(bottom*REGION_WIDTH_UNITS); - adjust = LLWorldMap::getInstance()->extendAABB(U32(x_meters), U32(y_meters), - U32(x_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getWidth()), - U32(y_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getHeight())) || adjust; - - LLWorldMap::getInstance()->mMapLayers[agent_flags].push_back(new_layer); + siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); } - LLWorldMap::getInstance()->mMapLoaded[agent_flags] = TRUE; - if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); -} - -// public static -void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) -{ - U32 agent_flags; - msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); - - if ((S32)agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES) + //LL_INFOS("World Map") << "Process item : type = " << type << LL_ENDL; + switch (type) { - llwarns << "Invalid map image type returned! " << agent_flags << llendl; - return; - } - - S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data); - - bool found_null_sim = false; - - BOOL adjust = FALSE; - for (S32 block=0; block<num_blocks; ++block) - { - U16 x_regions; - U16 y_regions; - std::string name; - U8 accesscode; - U32 region_flags; - U8 water_height; - U8 agents; - LLUUID image_id; - msg->getU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block); - msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block); - msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block); - msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, accesscode, block); - msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block); - msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block); - msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block); - - U32 x_meters = x_regions * REGION_WIDTH_UNITS; - U32 y_meters = y_regions * REGION_WIDTH_UNITS; - - U64 handle = to_region_handle(x_meters, y_meters); - - if (accesscode == 255) - { - // This region doesn't exist - if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256) - { - // We were tracking this location, but it doesn't exist - LLWorldMap::getInstance()->mInvalidLocation = TRUE; - } - - found_null_sim = true; - } - else + case MAP_ITEM_TELEHUB: // telehubs { - adjust = LLWorldMap::getInstance()->extendAABB(x_meters, - y_meters, - x_meters+REGION_WIDTH_UNITS, - y_meters+REGION_WIDTH_UNITS) || adjust; - -// llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl; - - LLSimInfo* siminfo = new LLSimInfo(); - sim_info_map_t::iterator iter = LLWorldMap::getInstance()->mSimInfoMap.find(handle); - if (iter != LLWorldMap::getInstance()->mSimInfoMap.end()) - { - LLSimInfo* oldinfo = iter->second; - for (S32 image=0; image<MAP_SIM_IMAGE_TYPES; ++image) - { - siminfo->mMapImageID[image] = oldinfo->mMapImageID[image]; - } - delete oldinfo; - } - LLWorldMap::getInstance()->mSimInfoMap[handle] = siminfo; - - siminfo->mHandle = handle; - siminfo->mName.assign( name ); - siminfo->mAccess = accesscode; - siminfo->mRegionFlags = region_flags; - siminfo->mWaterHeight = (F32) water_height; - siminfo->mMapImageID[agent_flags] = image_id; - -#ifdef IMMEDIATE_IMAGE_LOAD - siminfo->mCurrentImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); - siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); -#endif + /* Merov: we are not using the hub color anymore for display so commenting that out + // Telehub color + U32 X = x_world / REGION_WIDTH_UNITS; + U32 Y = y_world / REGION_WIDTH_UNITS; + F32 red = fmod((F32)X * 0.11f, 1.f) * 0.8f; + F32 green = fmod((F32)Y * 0.11f, 1.f) * 0.8f; + F32 blue = fmod(1.5f * (F32)(X + Y) * 0.11f, 1.f) * 0.8f; + F32 add_amt = (X % 2) ? 0.15f : -0.15f; + add_amt += (Y % 2) ? -0.15f : 0.15f; + LLColor4 color(red + add_amt, green + add_amt, blue + add_amt); + new_item.setColor(color); + */ - if (siminfo->mMapImageID[2].notNull()) + // extra2 specifies whether this is an infohub or a telehub. + if (extra2) { -#ifdef IMMEDIATE_IMAGE_LOAD - siminfo->mOverlayImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); -#endif + siminfo->insertInfoHub(new_item); } else { - siminfo->mOverlayImage = NULL; - } - - if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters && - LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256) - { - if (siminfo->mAccess == SIM_ACCESS_DOWN) - { - // We were tracking this location, but it doesn't exist - LLWorldMap::getInstance()->mInvalidLocation = true; - } - else - { - // We were tracking this location, and it does exist - bool is_tracking_dbl = LLWorldMap::getInstance()->mIsTrackingDoubleClick == TRUE; - gFloaterWorldMap->trackLocation(LLWorldMap::getInstance()->mUnknownLocation); - if (is_tracking_dbl) - { - LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); - gAgent.teleportViaLocation( pos_global ); - } - } + siminfo->insertTeleHub(new_item); } + break; } - - if(LLWorldMap::getInstance()->mSLURLCallback != NULL) + case MAP_ITEM_PG_EVENT: // events + case MAP_ITEM_MATURE_EVENT: + case MAP_ITEM_ADULT_EVENT: { - // Server returns definitive capitalization, SLURL might not have that. - if ((LLStringUtil::compareInsensitive(LLWorldMap::getInstance()->mSLURLRegionName, name)==0) - || (LLWorldMap::getInstance()->mSLURLRegionHandle == handle)) + std::string timeStr = "["+ LLTrans::getString ("TimeHour")+"]:[" + +LLTrans::getString ("TimeMin")+"] [" + +LLTrans::getString ("TimeAMPM")+"]"; + LLSD substitution; + substitution["datetime"] = (S32) extra; + LLStringUtil::format (timeStr, substitution); + new_item.setTooltip(timeStr); + + // HACK: store Z in extra2 + new_item.setElevation((F64)extra2); + if (type == MAP_ITEM_PG_EVENT) { - url_callback_t callback = LLWorldMap::getInstance()->mSLURLCallback; - - LLWorldMap::getInstance()->mSLURLCallback = NULL; - LLWorldMap::getInstance()->mSLURLRegionName.clear(); - LLWorldMap::getInstance()->mSLURLRegionHandle = 0; - - callback(handle, LLWorldMap::getInstance()->mSLURL, image_id, LLWorldMap::getInstance()->mSLURLTeleport); + siminfo->insertPGEvent(new_item); } - } - } - - if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); - gFloaterWorldMap->updateSims(found_null_sim); -} - -// public static -void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) -{ - U32 type; - msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type); - - S32 num_blocks = msg->getNumberOfBlocks("Data"); - - for (S32 block=0; block<num_blocks; ++block) - { - U32 X, Y; - std::string name; - S32 extra, extra2; - LLUUID uuid; - msg->getU32Fast(_PREHASH_Data, _PREHASH_X, X, block); - msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, Y, block); - msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_ID, uuid, block); - msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra, extra, block); - msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra2, extra2, block); - - F32 world_x = (F32)X; - X /= REGION_WIDTH_UNITS; - F32 world_y = (F32)Y; - Y /= REGION_WIDTH_UNITS; - - LLItemInfo new_item(world_x, world_y, name, uuid, extra, extra2); - LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(new_item.mRegionHandle); - - switch (type) - { - case MAP_ITEM_TELEHUB: // telehubs + else if (type == MAP_ITEM_MATURE_EVENT) { - // Telehub color, store in extra as 4 U8's - U8 *color = (U8 *)&new_item.mExtra; - - F32 red = fmod((F32)X * 0.11f, 1.f) * 0.8f; - F32 green = fmod((F32)Y * 0.11f, 1.f) * 0.8f; - F32 blue = fmod(1.5f * (F32)(X + Y) * 0.11f, 1.f) * 0.8f; - F32 add_amt = (X % 2) ? 0.15f : -0.15f; - add_amt += (Y % 2) ? -0.15f : 0.15f; - color[0] = U8((red + add_amt) * 255); - color[1] = U8((green + add_amt) * 255); - color[2] = U8((blue + add_amt) * 255); - color[3] = 255; - - // extra2 specifies whether this is an infohub or a telehub. - if (extra2) - { - LLWorldMap::getInstance()->mInfohubs.push_back(new_item); - } - else - { - LLWorldMap::getInstance()->mTelehubs.push_back(new_item); - } - - break; + siminfo->insertMatureEvent(new_item); } - case MAP_ITEM_PG_EVENT: // events - case MAP_ITEM_MATURE_EVENT: - case MAP_ITEM_ADULT_EVENT: + else if (type == MAP_ITEM_ADULT_EVENT) { - std::string timeStr = "["+ LLTrans::getString ("TimeHour")+"]:[" - +LLTrans::getString ("TimeMin")+"] [" - +LLTrans::getString ("TimeAMPM")+"]"; - LLSD substitution; - substitution["datetime"] = (S32) extra; - LLStringUtil::format (timeStr, substitution); - new_item.mToolTip = timeStr; - - // HACK: store Z in extra2 - new_item.mPosGlobal.mdV[VZ] = (F64)extra2; - if (type == MAP_ITEM_PG_EVENT) - { - LLWorldMap::getInstance()->mPGEvents.push_back(new_item); - } - else if (type == MAP_ITEM_MATURE_EVENT) - { - LLWorldMap::getInstance()->mMatureEvents.push_back(new_item); - } - else if (type == MAP_ITEM_ADULT_EVENT) - { - LLWorldMap::getInstance()->mAdultEvents.push_back(new_item); - } - - break; + siminfo->insertAdultEvent(new_item); } - case MAP_ITEM_LAND_FOR_SALE: // land for sale - case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale + break; + } + case MAP_ITEM_LAND_FOR_SALE: // land for sale + case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale + { + std::string tooltip = llformat("%d sq. m. L$%d", extra, extra2); + new_item.setTooltip(tooltip); + if (type == MAP_ITEM_LAND_FOR_SALE) { - new_item.mToolTip = llformat("%d sq. m. L$%d", new_item.mExtra, new_item.mExtra2); - if (type == MAP_ITEM_LAND_FOR_SALE) - { - LLWorldMap::getInstance()->mLandForSale.push_back(new_item); - } - else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT) - { - LLWorldMap::getInstance()->mLandForSaleAdult.push_back(new_item); - } - break; + siminfo->insertLandForSale(new_item); } - case MAP_ITEM_CLASSIFIED: // classifieds + else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT) { - //DEPRECATED: no longer used - break; + siminfo->insertLandForSaleAdult(new_item); } - case MAP_ITEM_AGENT_LOCATIONS: // agent locations + break; + } + case MAP_ITEM_CLASSIFIED: // classifieds + { + //DEPRECATED: no longer used + break; + } + case MAP_ITEM_AGENT_LOCATIONS: // agent locations + { +// LL_INFOS("World Map") << "New Location " << new_item.mName << LL_ENDL; + if (extra > 0) { - if (!siminfo) - { - llinfos << "siminfo missing for " << new_item.mPosGlobal.mdV[0] << ", " << new_item.mPosGlobal.mdV[1] << llendl; - break; - } -// llinfos << "New Location " << new_item.mName << llendl; - - item_info_list_t& agentcounts = LLWorldMap::getInstance()->mAgentLocationsMap[new_item.mRegionHandle]; - - // Find the last item in the list with a different name and erase them - item_info_list_t::iterator lastiter; - for (lastiter = agentcounts.begin(); lastiter!=agentcounts.end(); ++lastiter) - { - const LLItemInfo& info = *lastiter; - if (info.mName == new_item.mName) - { - break; - } - } - if (lastiter != agentcounts.begin()) - { - agentcounts.erase(agentcounts.begin(), lastiter); - } - // Now append the new location - if (new_item.mExtra > 0) - { - agentcounts.push_back(new_item); - } - break; + new_item.setCount(extra); + siminfo->insertAgentLocation(new_item); } - default: - break; - }; - } -} - -void LLWorldMap::dump() -{ - for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) - { - U64 handle = (*it).first; - LLSimInfo* info = (*it).second; - - U32 x_pos, y_pos; - from_region_handle(handle, &x_pos, &y_pos); - - llinfos << x_pos << "," << y_pos - << " " << info->mName - << " " << (S32)info->mAccess - << " " << std::hex << info->mRegionFlags << std::dec - << " " << info->mWaterHeight - //<< " " << info->mTelehubName - //<< " " << info->mTelehubPosition - << llendl; - - if (info->mCurrentImage) - { - llinfos << "image discard " << (S32)info->mCurrentImage->getDiscardLevel() - << " fullwidth " << info->mCurrentImage->getFullWidth() - << " fullheight " << info->mCurrentImage->getFullHeight() - << " maxvirt " << info->mCurrentImage->getMaxVirtualSize() - //<< " maxdisc " << (S32)info->mCurrentImage->getMaxDiscardLevel() - << llendl; + break; } + default: + break; } + return true; } - -BOOL LLWorldMap::extendAABB(U32 min_x, U32 min_y, U32 max_x, U32 max_y) +bool LLWorldMap::isTrackingInRectangle(F64 x0, F64 y0, F64 x1, F64 y1) { - BOOL rv = FALSE; - if (min_x < mMinX) - { - rv = TRUE; - mMinX = min_x; - } - if (min_y < mMinY) - { - rv = TRUE; - mMinY = min_y; - } - if (max_x > mMaxX) - { - rv = TRUE; - mMaxX = max_x; - } - if (max_y > mMaxY) - { - rv = TRUE; - mMaxY = max_y; - } - lldebugs << "World map aabb: (" << mMinX << ", " << mMinY << "), (" - << mMaxX << ", " << mMaxY << ")" << llendl; - return rv; + if (!mIsTrackingLocation) + return false; + return ((mTrackingLocation[0] >= x0) && (mTrackingLocation[0] < x1) && (mTrackingLocation[1] >= y0) && (mTrackingLocation[1] < y1)); } - -U32 LLWorldMap::getWorldWidth() const +// Drop priority of all images being fetched by the map +void LLWorldMap::dropImagePriorities() { - return mMaxX - mMinX; -} - - -U32 LLWorldMap::getWorldHeight() const -{ - return mMaxY - mMinY; -} - -BOOL LLWorldMap::coveredByTelehub(LLSimInfo* infop) -{ - /*if (!mTelehubCoverageMap) + // Drop the download of tiles priority to nil + mWorldMipmap.dropBoostLevels(); + // Same for the "land for sale" tiles per region + for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) { - return FALSE; + LLSimInfo* info = it->second; + info->dropImagePriority(); } - U32 x_pos, y_pos; - from_region_handle(infop->mHandle, &x_pos, &y_pos); - x_pos /= REGION_WIDTH_UNITS; - y_pos /= REGION_WIDTH_UNITS; - - S32 index = x_pos - (mMinX / REGION_WIDTH_UNITS - 1) + (mNeighborMapWidth * (y_pos - (mMinY / REGION_WIDTH_UNITS - 1))); - return mTelehubCoverageMap[index] != 0; */ - return FALSE; } -void LLWorldMap::updateTelehubCoverage() +// Load all regions in a given rectangle (in region grid coordinates, i.e. world / 256 meters) +void LLWorldMap::updateRegions(S32 x0, S32 y0, S32 x1, S32 y1) { - /*S32 neighbor_width = getWorldWidth() / REGION_WIDTH_UNITS + 2; - S32 neighbor_height = getWorldHeight() / REGION_WIDTH_UNITS + 2; - if (neighbor_width > mNeighborMapWidth || neighbor_height > mNeighborMapHeight) - { - mNeighborMapWidth = neighbor_width; - mNeighborMapHeight = neighbor_height; - delete mNeighborMap; - delete mTelehubCoverageMap; - - mNeighborMap = new U8[mNeighborMapWidth * mNeighborMapHeight]; - mTelehubCoverageMap = new U8[mNeighborMapWidth * mNeighborMapHeight]; - } - - memset(mNeighborMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8)); - memset(mTelehubCoverageMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8)); + // Convert those boundaries to the corresponding (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) block coordinates + x0 = x0 / MAP_BLOCK_SIZE; + x1 = x1 / MAP_BLOCK_SIZE; + y0 = y0 / MAP_BLOCK_SIZE; + y1 = y1 / MAP_BLOCK_SIZE; - // leave 1 sim border - S32 min_x = (mMinX / REGION_WIDTH_UNITS) - 1; - S32 min_y = (mMinY / REGION_WIDTH_UNITS) - 1; - - std::map<U64, LLSimInfo*>::const_iterator it; - for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) + // Load the region info those blocks + for (S32 block_x = llmax(x0, 0); block_x <= llmin(x1, MAP_BLOCK_RES-1); ++block_x) { - U64 handle = (*it).first; - //LLSimInfo* info = (*it).second; - - U32 x_pos, y_pos; - from_region_handle(handle, &x_pos, &y_pos); - x_pos /= REGION_WIDTH_UNITS; - y_pos /= REGION_WIDTH_UNITS; - x_pos -= min_x; - y_pos -= min_y; - - S32 index = x_pos + (mNeighborMapWidth * y_pos); - mNeighborMap[index - 1]++; - mNeighborMap[index + 1]++; - mNeighborMap[index - mNeighborMapWidth]++; - mNeighborMap[index + mNeighborMapWidth]++; - } - - for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) - { - U64 handle = (*it).first; - LLSimInfo* info = (*it).second; - - U32 x_pos, y_pos; - from_region_handle(handle, &x_pos, &y_pos); - x_pos /= REGION_WIDTH_UNITS; - y_pos /= REGION_WIDTH_UNITS; - x_pos -= min_x; - y_pos -= min_y; - - S32 index = x_pos + (mNeighborMapWidth * y_pos); - - if (!info->mTelehubName.empty() && mNeighborMap[index]) + for (S32 block_y = llmax(y0, 0); block_y <= llmin(y1, MAP_BLOCK_RES-1); ++block_y) { - S32 x_start = llmax(0, S32(x_pos - 5)); - S32 x_span = llmin(mNeighborMapWidth - 1, (S32)(x_pos + 5)) - x_start + 1; - S32 y_start = llmax(0, (S32)y_pos - 5); - S32 y_end = llmin(mNeighborMapHeight - 1, (S32)(y_pos + 5)); - for (S32 y_index = y_start; y_index <= y_end; y_index++) + S32 offset = block_x | (block_y * MAP_BLOCK_RES); + if (!mMapBlockLoaded[offset]) { - memset(&mTelehubCoverageMap[x_start + y_index * mNeighborMapWidth], 0xff, sizeof(U8) * x_span); + //LL_INFOS("World Map") << "Loading Block (" << block_x << "," << block_y << ")" << LL_ENDL; + LLWorldMapMessage::getInstance()->sendMapBlockRequest(block_x * MAP_BLOCK_SIZE, block_y * MAP_BLOCK_SIZE, (block_x * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1, (block_y * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1); + mMapBlockLoaded[offset] = true; } } } +} - for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) +void LLWorldMap::dump() +{ + LL_INFOS("World Map") << "LLWorldMap::dump()" << LL_ENDL; + for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) { - U64 handle = (*it).first; - //LLSimInfo* info = (*it).second; - - U32 x_pos, y_pos; - from_region_handle(handle, &x_pos, &y_pos); - x_pos /= REGION_WIDTH_UNITS; - y_pos /= REGION_WIDTH_UNITS; - - S32 index = x_pos - min_x + (mNeighborMapWidth * (y_pos - min_y)); - mTelehubCoverageMap[index] *= mNeighborMap[index]; - }*/ + LLSimInfo* info = it->second; + if (info) + { + info->dump(); + } + } } + diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h index 366de8f071..7e37727b86 100644 --- a/indra/newview/llworldmap.h +++ b/indra/newview/llworldmap.h @@ -33,203 +33,243 @@ #ifndef LL_LLWORLDMAP_H #define LL_LLWORLDMAP_H -#include <map> -#include <string> -#include <vector> +#include "llworldmipmap.h" #include <boost/function.hpp> -#include "v3math.h" #include "v3dmath.h" -#include "llframetimer.h" -#include "llmapimagetype.h" #include "lluuid.h" #include "llpointer.h" #include "llsingleton.h" +#include "llviewerregion.h" #include "llviewertexture.h" -#include "lleventinfo.h" -#include "v3color.h" - -class LLMessageSystem; - +// Description of objects like hubs, events, land for sale, people and more (TBD). +// Note: we don't store a "type" in there so we need to store instances of this class in +// well known objects (i.e. list of objects which type is "well known"). class LLItemInfo { public: - LLItemInfo(F32 global_x, F32 global_y, const std::string& name, LLUUID id, S32 extra = 0, S32 extra2 = 0); - - std::string mName; - std::string mToolTip; - LLVector3d mPosGlobal; - LLUUID mID; - BOOL mSelected; - S32 mExtra; - S32 mExtra2; - U64 mRegionHandle; -}; + LLItemInfo(F32 global_x, F32 global_y, const std::string& name, LLUUID id); + + // Setters + void setTooltip(std::string& tooltip) { mToolTip = tooltip; } + void setElevation(F64 z) { mPosGlobal.mdV[VZ] = z; } + void setCount(S32 count) { mCount = count; } +// void setSelected(bool selected) { mSelected = selected; } +// void setColor(LLColor4 color) { mColor = color; } + + // Accessors + const LLVector3d& getGlobalPosition() const { return mPosGlobal; } + const std::string& getName() const { return mName; } + const std::string& getToolTip() const { return mToolTip; } + const LLUUID& getUUID() const { return mID; } + S32 getCount() const { return mCount; } + + U64 getRegionHandle() const { return to_region_handle(mPosGlobal); } // Build the handle on the fly -// Map layers, see indra_constants.h -// 0 - Prim -// 1 - Terrain Only -// 2 - Overlay: Land For Sale + bool isName(const std::string& name) const { return (mName == name); } // True if name same as item's name +// bool isSelected() const { return mSelected; } +private: + std::string mName; // Name of the individual item + std::string mToolTip; // Tooltip : typically, something to be displayed to the user when selecting this item + LLVector3d mPosGlobal; // Global world position + LLUUID mID; // UUID of the item + S32 mCount; // Number of elements in item (e.g. people count) + // Currently not used but might prove useful one day so we comment out +// bool mSelected; // Selected or not: updated by the viewer UI, not the simulator or asset DB +// LLColor4 mColor; // Color of the item +}; + +// Info per region +// Such records are stored in a global map hold by the LLWorldMap and indexed by region handles. +// To avoid creating too many of them, they are requested in "blocks" corresponding to areas covered by the screen. +// Unfortunately, when the screen covers the whole world (zoomed out), that can translate in requesting info for +// every sim on the grid... Not good... +// To avoid this, the code implements a cut-off threshold for overlay graphics and, therefore, all LLSimInfo. +// In other words, when zooming out too much, we simply stop requesting LLSimInfo and +// LLItemInfo and just display the map tiles. +// As they are stored in different structures (LLSimInfo and LLWorldMipmap), this strategy is now workable. class LLSimInfo { public: - LLSimInfo(); + LLSimInfo(U64 handle); - LLVector3d getGlobalPos(LLVector3 local_pos) const; + // Convert local region coordinates into world coordinates + LLVector3d getGlobalPos(const LLVector3& local_pos) const; + // Get the world coordinates of the SW corner of that region + LLVector3d getGlobalOrigin() const; LLVector3 getLocalPos(LLVector3d global_pos) const; -public: - U64 mHandle; - std::string mName; - - F64 mAgentsUpdateTime; - BOOL mShowAgentLocations; // are agents visible? + void clearImage(); // Clears the reference to the Land for sale image for that region + void dropImagePriority(); // Drops the boost level of the Land for sale image for that region + void updateAgentCount(F64 time); // Send an item request for agent count on that region if time's up - U8 mAccess; - U32 mRegionFlags; - F32 mWaterHeight; + // Setters + void setName(std::string& name) { mName = name; } + void setAccess (U32 accesscode) { mAccess = accesscode; } + void setRegionFlags (U32 region_flags) { mRegionFlags = region_flags; } + void setLandForSaleImage (LLUUID image_id); +// void setWaterHeight (F32 water_height) { mWaterHeight = water_height; } - F32 mAlpha; + // Accessors + std::string getName() const { return mName; } + const std::string getFlagsString() const { return LLViewerRegion::regionFlagsToString(mRegionFlags); } + const std::string getAccessString() const { return LLViewerRegion::accessToString((U8)mAccess); } - // Image ID for the current overlay mode. - LLUUID mMapImageID[MAP_SIM_IMAGE_TYPES]; + const S32 getAgentCount() const; // Compute the total agents count + LLPointer<LLViewerFetchedTexture> getLandForSaleImage(); // Get the overlay image, fetch it if necessary - // Hold a reference to the currently displayed image. - LLPointer<LLViewerFetchedTexture> mCurrentImage; - LLPointer<LLViewerFetchedTexture> mOverlayImage; -}; + bool isName(const std::string& name) const; + bool isDown() { return (mAccess == SIM_ACCESS_DOWN); } + bool isPG() { return (mAccess <= SIM_ACCESS_PG); } -#define MAP_BLOCK_RES 256 + // Debug only + void dump() const; // Print the region info to the standard output -struct LLWorldMapLayer -{ - BOOL LayerDefined; - LLPointer<LLViewerFetchedTexture> LayerImage; - LLUUID LayerImageID; - LLRect LayerExtents; + // Items lists handling + typedef std::vector<LLItemInfo> item_info_list_t; + void clearItems(); + + void insertTeleHub(const LLItemInfo& item) { mTelehubs.push_back(item); } + void insertInfoHub(const LLItemInfo& item) { mInfohubs.push_back(item); } + void insertPGEvent(const LLItemInfo& item) { mPGEvents.push_back(item); } + void insertMatureEvent(const LLItemInfo& item) { mMatureEvents.push_back(item); } + void insertAdultEvent(const LLItemInfo& item) { mAdultEvents.push_back(item); } + void insertLandForSale(const LLItemInfo& item) { mLandForSale.push_back(item); } + void insertLandForSaleAdult(const LLItemInfo& item) { mLandForSaleAdult.push_back(item); } + void insertAgentLocation(const LLItemInfo& item); + + const LLSimInfo::item_info_list_t& getTeleHub() const { return mTelehubs; } + const LLSimInfo::item_info_list_t& getInfoHub() const { return mInfohubs; } + const LLSimInfo::item_info_list_t& getPGEvent() const { return mPGEvents; } + const LLSimInfo::item_info_list_t& getMatureEvent() const { return mMatureEvents; } + const LLSimInfo::item_info_list_t& getAdultEvent() const { return mAdultEvents; } + const LLSimInfo::item_info_list_t& getLandForSale() const { return mLandForSale; } + const LLSimInfo::item_info_list_t& getLandForSaleAdult() const { return mLandForSaleAdult; } + const LLSimInfo::item_info_list_t& getAgentLocation() const { return mAgentLocations; } - LLWorldMapLayer() : LayerDefined(FALSE) { } +private: + U64 mHandle; // This is a hash of the X and Y world coordinates of the SW corner of the sim + std::string mName; // Region name + + F64 mAgentsUpdateTime; // Time stamp giving the last time the agents information was requested for that region + bool mFirstAgentRequest; // Init agent request flag + + U32 mAccess; // Down/up and maturity rating of the region + U32 mRegionFlags; // Tell us if the siminfo has been received (if non 0) and what kind of region it is (Sandbox, allow damage) + // Currently not used but might prove useful one day so we comment out +// F32 mWaterHeight; // Water height on the region (not actively used) + + // Handling the "land for sale / land for auction" overlay image + LLUUID mMapImageID; // Image ID of the overlay image + LLPointer<LLViewerFetchedTexture> mOverlayImage; // Reference to the overlay image + + // Items for this region + // Those are data received through item requests (as opposed to block requests for the rest of the data) + item_info_list_t mTelehubs; // List of tele hubs in the region + item_info_list_t mInfohubs; // List of info hubs in the region + item_info_list_t mPGEvents; // List of PG events in the region + item_info_list_t mMatureEvents; // List of Mature events in the region + item_info_list_t mAdultEvents; // List of Adult events in the region (AO) + item_info_list_t mLandForSale; // List of Land for sales in the region + item_info_list_t mLandForSaleAdult; // List of Adult Land for sales in the region (AO) + item_info_list_t mAgentLocations; // List of agents in the region }; +// We request region data on the world by "blocks" of (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) regions +// This is to reduce the number of requests to the asset DB and get things in big "blocks" +const S32 MAP_MAX_SIZE = 2048; +const S32 MAP_BLOCK_SIZE = 4; +const S32 MAP_BLOCK_RES = (MAP_MAX_SIZE / MAP_BLOCK_SIZE); class LLWorldMap : public LLSingleton<LLWorldMap> { public: - typedef boost::function<void(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)> - url_callback_t; - LLWorldMap(); ~LLWorldMap(); - // clears the list + // Clear all: list of region info, tiles, blocks and items void reset(); - // clear the visible items - void eraseItems(); + void clearImageRefs(); // Clears the image references + void dropImagePriorities(); // Drops the priority of the images being fetched + void reloadItems(bool force = false); // Reload the items (people, hub, etc...) - // Removes references to cached images - void clearImageRefs(); + // Region Map access + typedef std::map<U64, LLSimInfo*> sim_info_map_t; + const LLWorldMap::sim_info_map_t& getRegionMap() const { return mSimInfoMap; } + void updateRegions(S32 x0, S32 y0, S32 x1, S32 y1); // Requests region info for a rectangle of regions (in grid coordinates) - // Clears the flags indicating that we've received sim infos - // Causes a re-request of the sim info without erasing extisting info - void clearSimFlags(); + // Insert a region and items in the map global instance + // Note: x_world and y_world in world coordinates (meters) + static bool insertRegion(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 accesscode, U32 region_flags); + static bool insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 type, S32 extra, S32 extra2); - // Returns simulator information, or NULL if out of range + // Get info on sims (region) : note that those methods only search the range of loaded sims (the one that are being browsed) + // *not* the entire world. So a NULL return does not mean a down or unexisting region, just an out of range region. LLSimInfo* simInfoFromHandle(const U64 handle); - - // Returns simulator information, or NULL if out of range LLSimInfo* simInfoFromPosGlobal(const LLVector3d& pos_global); - - // Returns simulator information for named sim, or NULL if non-existent LLSimInfo* simInfoFromName(const std::string& sim_name); - // Gets simulator name for a global position, returns true if it was found + // Gets simulator name from a global position, returns true if found bool simNameFromPosGlobal(const LLVector3d& pos_global, std::string& outSimName ); - // Sets the current layer - void setCurrentLayer(S32 layer, bool request_layer = false); - - void sendMapLayerRequest(); - void sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent = false); - void sendNamedRegionRequest(std::string region_name); - void sendNamedRegionRequest(std::string region_name, - url_callback_t callback, - const std::string& callback_url, - bool teleport); - void sendHandleRegionRequest(U64 region_handle, - url_callback_t callback, - const std::string& callback_url, - bool teleport); - void sendItemRequest(U32 type, U64 handle = 0); - - static void processMapLayerReply(LLMessageSystem*, void**); - static void processMapBlockReply(LLMessageSystem*, void**); - static void processMapItemReply(LLMessageSystem*, void**); - - void dump(); - - // Extend the bounding box of the list of simulators. Returns true - // if the extents changed. - BOOL extendAABB(U32 x_min, U32 y_min, U32 x_max, U32 y_max); - - // build coverage maps for telehub region visualization - void updateTelehubCoverage(); - BOOL coveredByTelehub(LLSimInfo* infop); - - // Bounds of the world, in meters - U32 getWorldWidth() const; - U32 getWorldHeight() const; -public: - // Map from region-handle to simulator info - typedef std::map<U64, LLSimInfo*> sim_info_map_t; - sim_info_map_t mSimInfoMap; + // Debug only + void dump(); // Print the world info to the standard output - BOOL mIsTrackingUnknownLocation, mInvalidLocation, mIsTrackingDoubleClick, mIsTrackingCommit; - LLVector3d mUnknownLocation; + // Track handling + void cancelTracking() { mIsTrackingLocation = false; mIsTrackingFound = false; mIsInvalidLocation = false; mIsTrackingDoubleClick = false; mIsTrackingCommit = false; } - bool mRequestLandForSale; + void setTracking(const LLVector3d& loc) { mIsTrackingLocation = true; mTrackingLocation = loc; mIsTrackingFound = false; mIsInvalidLocation = false; mIsTrackingDoubleClick = false; mIsTrackingCommit = false;} + void setTrackingInvalid() { mIsTrackingFound = true; mIsInvalidLocation = true; } + void setTrackingValid() { mIsTrackingFound = true; mIsInvalidLocation = false; } + void setTrackingDoubleClick() { mIsTrackingDoubleClick = true; } + void setTrackingCommit() { mIsTrackingCommit = true; } - typedef std::vector<LLItemInfo> item_info_list_t; - item_info_list_t mTelehubs; - item_info_list_t mInfohubs; - item_info_list_t mPGEvents; - item_info_list_t mMatureEvents; - item_info_list_t mAdultEvents; - item_info_list_t mLandForSale; - item_info_list_t mLandForSaleAdult; - - std::map<U64,S32> mNumAgents; - - typedef std::map<U64, item_info_list_t> agent_list_map_t; - agent_list_map_t mAgentLocationsMap; - - std::vector<LLWorldMapLayer> mMapLayers[MAP_SIM_IMAGE_TYPES]; - BOOL mMapLoaded[MAP_SIM_IMAGE_TYPES]; - BOOL * mMapBlockLoaded[MAP_SIM_IMAGE_TYPES]; - S32 mCurrentMap; - - // AABB of the list of simulators - U32 mMinX; - U32 mMaxX; - U32 mMinY; - U32 mMaxY; - - U8* mNeighborMap; - U8* mTelehubCoverageMap; - S32 mNeighborMapWidth; - S32 mNeighborMapHeight; + bool isTracking() { return mIsTrackingLocation; } + bool isTrackingValidLocation() { return mIsTrackingFound && !mIsInvalidLocation; } + bool isTrackingInvalidLocation() { return mIsTrackingFound && mIsInvalidLocation; } + bool isTrackingDoubleClick() { return mIsTrackingDoubleClick; } + bool isTrackingCommit() { return mIsTrackingCommit; } + bool isTrackingInRectangle(F64 x0, F64 y0, F64 x1, F64 y1); + + LLVector3d getTrackedPositionGlobal() const { return mTrackingLocation; } + + // World Mipmap delegation: currently used when drawing the mipmap + void equalizeBoostLevels(); + LLPointer<LLViewerFetchedTexture> getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load = true) { return mWorldMipmap.getObjectsTile(grid_x, grid_y, level, load); } private: - LLTimer mRequestTimer; - - // search for named region for url processing - std::string mSLURLRegionName; - U64 mSLURLRegionHandle; - std::string mSLURL; - url_callback_t mSLURLCallback; - bool mSLURLTeleport; + bool clearItems(bool force = false); // Clears the item lists + void clearSimFlags(); // Clears the block flags indicating that we've already requested region infos + + // Create a region record corresponding to the handle, insert it in the region map and returns a pointer + LLSimInfo* createSimInfoFromHandle(const U64 handle); + + // Map from region-handle to region info + sim_info_map_t mSimInfoMap; + + // Holds the tiled mipmap of the world. This is the structure that contains the images used for rendering. + LLWorldMipmap mWorldMipmap; + + // The World is divided in "blocks" of (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) regions that get requested at once. + // This boolean table avoids "blocks" to be requested multiple times. + // Issue: Not sure this scheme is foolproof though as I've seen + // cases where a block is never retrieved and, because of this boolean being set, never re-requested + bool * mMapBlockLoaded; // Telling us if the block of regions has been requested or not + + // Track location data : used while there's nothing tracked yet by LLTracker + bool mIsTrackingLocation; // True when we're tracking a point + bool mIsTrackingFound; // True when the tracking position has been found, valid or not + bool mIsInvalidLocation; // The region is down or the location does not correspond to an existing region + bool mIsTrackingDoubleClick; // User double clicked to set the location (i.e. teleport when found please...) + bool mIsTrackingCommit; // User used the search or landmark fields to set the location + LLVector3d mTrackingLocation; // World global position being tracked + + // General grid items request timing flags (used for events,hubs and land for sale) + LLTimer mRequestTimer; + bool mFirstRequest; }; #endif diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp new file mode 100644 index 0000000000..6a074d9697 --- /dev/null +++ b/indra/newview/llworldmapmessage.cpp @@ -0,0 +1,261 @@ +/** + * @file llworldmapmessage.cpp + * @brief Handling of the messages to the DB made by and for the world map. + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llworldmapmessage.h" + +#include "llworldmap.h" +#include "llagent.h" +#include "llfloaterworldmap.h" + +const U32 LAYER_FLAG = 2; + +//--------------------------------------------------------------------------- +// World Map Message Handling +//--------------------------------------------------------------------------- + +LLWorldMapMessage::LLWorldMapMessage() : + mSLURLRegionName(), + mSLURLRegionHandle(0), + mSLURL(), + mSLURLCallback(0), + mSLURLTeleport(false) +{ +} + +LLWorldMapMessage::~LLWorldMapMessage() +{ +} + +void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) +{ + //LL_INFOS("World Map") << "Send item request : type = " << type << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_MapItemRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_Flags, LAYER_FLAG); + msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim + msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim + + msg->nextBlockFast(_PREHASH_RequestData); + msg->addU32Fast(_PREHASH_ItemType, type); + msg->addU64Fast(_PREHASH_RegionHandle, handle); // If zero, filled in on sim + + gAgent.sendReliableMessage(); +} + +void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name) +{ + //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + + // Request for region data + msg->newMessageFast(_PREHASH_MapNameRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_Flags, LAYER_FLAG); + msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim + msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim + msg->nextBlockFast(_PREHASH_NameData); + msg->addStringFast(_PREHASH_Name, region_name); + gAgent.sendReliableMessage(); +} + +void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name, + url_callback_t callback, + const std::string& callback_url, + bool teleport) // immediately teleport when result returned +{ + //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL; + mSLURLRegionName = region_name; + mSLURLRegionHandle = 0; + mSLURL = callback_url; + mSLURLCallback = callback; + mSLURLTeleport = teleport; + + sendNamedRegionRequest(region_name); +} + +void LLWorldMapMessage::sendHandleRegionRequest(U64 region_handle, + url_callback_t callback, + const std::string& callback_url, + bool teleport) // immediately teleport when result returned +{ + //LL_INFOS("World Map") << "LLWorldMap::sendHandleRegionRequest()" << LL_ENDL; + mSLURLRegionName.clear(); + mSLURLRegionHandle = region_handle; + mSLURL = callback_url; + mSLURLCallback = callback; + mSLURLTeleport = teleport; + + U32 global_x; + U32 global_y; + from_region_handle(region_handle, &global_x, &global_y); + U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); + U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); + + sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); +} + +void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) +{ + //LL_INFOS("World Map") << "LLWorldMap::sendMapBlockRequest()" << ", min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << "), nonexistent = " << return_nonexistent << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MapBlockRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + U32 flags = LAYER_FLAG; + flags |= (return_nonexistent ? 0x10000 : 0); + msg->addU32Fast(_PREHASH_Flags, flags); + msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim + msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim + msg->nextBlockFast(_PREHASH_PositionData); + msg->addU16Fast(_PREHASH_MinX, min_x); + msg->addU16Fast(_PREHASH_MinY, min_y); + msg->addU16Fast(_PREHASH_MaxX, max_x); + msg->addU16Fast(_PREHASH_MaxY, max_y); + gAgent.sendReliableMessage(); +} + +// public static +void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) +{ + U32 agent_flags; + msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); + + // There's only one flag that we ever use here + if (agent_flags != LAYER_FLAG) + { + llwarns << "Invalid map image type returned! layer = " << agent_flags << llendl; + return; + } + + S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data); + //LL_INFOS("World Map") << "LLWorldMap::processMapBlockReply(), num_blocks = " << num_blocks << LL_ENDL; + + bool found_null_sim = false; + + for (S32 block=0; block<num_blocks; ++block) + { + U16 x_regions; + U16 y_regions; + std::string name; + U8 accesscode; + U32 region_flags; +// U8 water_height; +// U8 agents; + LLUUID image_id; + msg->getU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block); + msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block); + msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block); + msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, accesscode, block); + msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block); +// msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block); +// msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block); + msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block); + + U32 x_world = (U32)(x_regions) * REGION_WIDTH_UNITS; + U32 y_world = (U32)(y_regions) * REGION_WIDTH_UNITS; + + // Insert that region in the world map, if failure, flag it as a "null_sim" + if (!(LLWorldMap::getInstance()->insertRegion(x_world, y_world, name, image_id, (U32)accesscode, region_flags))) + { + found_null_sim = true; + } + + // If we hit a valid tracking location, do what needs to be done app level wise + if (LLWorldMap::getInstance()->isTrackingValidLocation()) + { + LLVector3d pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal(); + if (LLWorldMap::getInstance()->isTrackingDoubleClick()) + { + // Teleport if the user double clicked + gAgent.teleportViaLocation(pos_global); + } + // Update the "real" tracker information + gFloaterWorldMap->trackLocation(pos_global); + } + + // Handle the SLURL callback if any + if(LLWorldMapMessage::getInstance()->mSLURLCallback != NULL) + { + U64 handle = to_region_handle(x_world, y_world); + // Check if we reached the requested region + if ((LLStringUtil::compareInsensitive(LLWorldMapMessage::getInstance()->mSLURLRegionName, name)==0) + || (LLWorldMapMessage::getInstance()->mSLURLRegionHandle == handle)) + { + url_callback_t callback = LLWorldMapMessage::getInstance()->mSLURLCallback; + + LLWorldMapMessage::getInstance()->mSLURLCallback = NULL; + LLWorldMapMessage::getInstance()->mSLURLRegionName.clear(); + LLWorldMapMessage::getInstance()->mSLURLRegionHandle = 0; + + callback(handle, LLWorldMapMessage::getInstance()->mSLURL, image_id, LLWorldMapMessage::getInstance()->mSLURLTeleport); + } + } + } + // Tell the UI to update itself + gFloaterWorldMap->updateSims(found_null_sim); +} + +// public static +void LLWorldMapMessage::processMapItemReply(LLMessageSystem* msg, void**) +{ + //LL_INFOS("World Map") << "LLWorldMap::processMapItemReply()" << LL_ENDL; + U32 type; + msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type); + + S32 num_blocks = msg->getNumberOfBlocks("Data"); + + for (S32 block=0; block<num_blocks; ++block) + { + U32 X, Y; + std::string name; + S32 extra, extra2; + LLUUID uuid; + msg->getU32Fast(_PREHASH_Data, _PREHASH_X, X, block); + msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, Y, block); + msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block); + msg->getUUIDFast(_PREHASH_Data, _PREHASH_ID, uuid, block); + msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra, extra, block); + msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra2, extra2, block); + + LLWorldMap::getInstance()->insertItem(X, Y, name, uuid, type, extra, extra2); + } +} + diff --git a/indra/newview/llworldmapmessage.h b/indra/newview/llworldmapmessage.h new file mode 100644 index 0000000000..2c8fedcb10 --- /dev/null +++ b/indra/newview/llworldmapmessage.h @@ -0,0 +1,83 @@ +/** + * @file llworldmapmessage.h + * @brief Handling of the messages to the DB made by and for the world map. + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLWORLDMAPMESSAGE_H +#define LL_LLWORLDMAPMESSAGE_H + +// Handling of messages (send and process) as well as SLURL callback if necessary +class LLMessageSystem; + +class LLWorldMapMessage : public LLSingleton<LLWorldMapMessage> +{ +public: + typedef boost::function<void(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)> + url_callback_t; + + LLWorldMapMessage(); + ~LLWorldMapMessage(); + + // Process incoming answers to map stuff requests + static void processMapBlockReply(LLMessageSystem*, void**); + static void processMapItemReply(LLMessageSystem*, void**); + + // Request data for all regions in a rectangular area. Coordinates in grids (i.e. meters / 256). + void sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent = false); + + // Various methods to request LLSimInfo data to the simulator and asset DB + void sendNamedRegionRequest(std::string region_name); + void sendNamedRegionRequest(std::string region_name, + url_callback_t callback, + const std::string& callback_url, + bool teleport); + void sendHandleRegionRequest(U64 region_handle, + url_callback_t callback, + const std::string& callback_url, + bool teleport); + + // Request item data for regions + // Note: the handle works *only* when requesting agent count (type = MAP_ITEM_AGENT_LOCATIONS). In that case, + // the request will actually be transitting through the spaceserver (all that is done on the sim). + // All other values of type do create a global grid request to the asset DB. So no need to try to get, say, + // the events for one particular region. For such a request, the handle is ignored. + void sendItemRequest(U32 type, U64 handle = 0); + +private: + // Search for region (by name or handle) for SLURL processing and teleport + // None of this relies explicitly on the LLWorldMap instance so better handle it here + std::string mSLURLRegionName; + U64 mSLURLRegionHandle; + std::string mSLURL; + url_callback_t mSLURLCallback; + bool mSLURLTeleport; +}; + +#endif // LL_LLWORLDMAPMESSAGE_H diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 823db027ee..60b1e59645 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -46,7 +46,6 @@ #include "llagent.h" #include "llcallingcard.h" #include "llviewercontrol.h" -#include "llcylinder.h" #include "llfloatermap.h" #include "llfloaterworldmap.h" #include "llfocusmgr.h" @@ -57,25 +56,29 @@ #include "llviewercamera.h" #include "llviewertexture.h" #include "llviewertexturelist.h" -#include "llviewermenu.h" -#include "llviewerparceloverlay.h" #include "llviewerregion.h" #include "llviewerwindow.h" -#include "llworldmap.h" -#include "lltexturefetch.h" -#include "llappviewer.h" // Only for constants! #include "lltrans.h" #include "llglheaders.h" +// Basically a C++ implementation of the OCEAN_COLOR defined in mapstitcher.py +// Please ensure consistency between those 2 files (TODO: would be better to get that color from an asset source...) +// # Constants +// OCEAN_COLOR = "#1D475F" +const F32 OCEAN_RED = (F32)(0x1D)/255.f; +const F32 OCEAN_GREEN = (F32)(0x47)/255.f; +const F32 OCEAN_BLUE = (F32)(0x5F)/255.f; + const F32 GODLY_TELEPORT_HEIGHT = 200.f; const S32 SCROLL_HINT_WIDTH = 65; const F32 BIG_DOT_RADIUS = 5.f; BOOL LLWorldMapView::sHandledLastClick = FALSE; -LLUIImagePtr LLWorldMapView::sAvatarYouSmallImage = NULL; LLUIImagePtr LLWorldMapView::sAvatarSmallImage = NULL; -LLUIImagePtr LLWorldMapView::sAvatarLargeImage = NULL; +LLUIImagePtr LLWorldMapView::sAvatarYouImage = NULL; +LLUIImagePtr LLWorldMapView::sAvatarYouLargeImage = NULL; +LLUIImagePtr LLWorldMapView::sAvatarLevelImage = NULL; LLUIImagePtr LLWorldMapView::sAvatarAboveImage = NULL; LLUIImagePtr LLWorldMapView::sAvatarBelowImage = NULL; @@ -93,35 +96,34 @@ LLUIImagePtr LLWorldMapView::sClassifiedsImage = NULL; LLUIImagePtr LLWorldMapView::sForSaleImage = NULL; LLUIImagePtr LLWorldMapView::sForSaleAdultImage = NULL; -F32 LLWorldMapView::sThresholdA = 48.f; -F32 LLWorldMapView::sThresholdB = 96.f; F32 LLWorldMapView::sPanX = 0.f; F32 LLWorldMapView::sPanY = 0.f; F32 LLWorldMapView::sTargetPanX = 0.f; F32 LLWorldMapView::sTargetPanY = 0.f; S32 LLWorldMapView::sTrackingArrowX = 0; S32 LLWorldMapView::sTrackingArrowY = 0; -F32 LLWorldMapView::sPixelsPerMeter = 1.f; -F32 CONE_SIZE = 0.6f; +bool LLWorldMapView::sVisibleTilesLoaded = false; +F32 LLWorldMapView::sMapScale = 128.f; std::map<std::string,std::string> LLWorldMapView::sStringsMap; -#define SIM_NULL_MAP_SCALE 1 // width in pixels, where we start drawing "null" sims -#define SIM_MAP_AGENT_SCALE 2 // width in pixels, where we start drawing agents -#define SIM_MAP_SCALE 1 // width in pixels, where we start drawing sim tiles - -// Updates for agent locations. -#define AGENTS_UPDATE_TIME 60.0 // in seconds +// Fetch and draw info thresholds +const F32 DRAW_TEXT_THRESHOLD = 96.f; // Don't draw text under that resolution value (res = width region in meters) +const S32 DRAW_SIMINFO_THRESHOLD = 3; // Max level for which we load or display sim level information (level in LLWorldMipmap sense) +const S32 DRAW_LANDFORSALE_THRESHOLD = 2; // Max level for which we load or display land for sale picture data (level in LLWorldMipmap sense) +// When on, draw an outline for each mipmap tile gotten from S3 +#define DEBUG_DRAW_TILE 0 void LLWorldMapView::initClass() { - sAvatarYouSmallImage = LLUI::getUIImage("map_avatar_you_8.tga"); - sAvatarSmallImage = LLUI::getUIImage("map_avatar_8.tga"); - sAvatarLargeImage = LLUI::getUIImage("map_avatar_16.tga"); - sAvatarAboveImage = LLUI::getUIImage("map_avatar_above_8.tga"); - sAvatarBelowImage = LLUI::getUIImage("map_avatar_below_8.tga"); + sAvatarSmallImage = LLUI::getUIImage("map_avatar_8.tga"); + sAvatarYouImage = LLUI::getUIImage("map_avatar_16.tga"); + sAvatarYouLargeImage = LLUI::getUIImage("map_avatar_you_32.tga"); + sAvatarLevelImage = LLUI::getUIImage("map_avatar_32.tga"); + sAvatarAboveImage = LLUI::getUIImage("map_avatar_above_32.tga"); + sAvatarBelowImage = LLUI::getUIImage("map_avatar_below_32.tga"); sHomeImage = LLUI::getUIImage("map_home.tga"); sTelehubImage = LLUI::getUIImage("map_telehub.tga"); @@ -145,9 +147,10 @@ void LLWorldMapView::initClass() // static void LLWorldMapView::cleanupClass() { - sAvatarYouSmallImage = NULL; sAvatarSmallImage = NULL; - sAvatarLargeImage = NULL; + sAvatarYouImage = NULL; + sAvatarYouLargeImage = NULL; + sAvatarLevelImage = NULL; sAvatarAboveImage = NULL; sAvatarBelowImage = NULL; @@ -167,7 +170,7 @@ void LLWorldMapView::cleanupClass() LLWorldMapView::LLWorldMapView() : LLPanel(), - mBackgroundColor( LLColor4( 4.f/255.f, 4.f/255.f, 75.f/255.f, 1.f ) ), + mBackgroundColor( LLColor4( OCEAN_RED, OCEAN_GREEN, OCEAN_BLUE, 1.f ) ), mItemPicked(FALSE), mPanning( FALSE ), mMouseDownPanX( 0 ), @@ -176,7 +179,8 @@ LLWorldMapView::LLWorldMapView() mMouseDownY( 0 ), mSelectIDStart(0) { - sPixelsPerMeter = gMapScale / REGION_WIDTH_METERS; + //LL_INFOS("World Map") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL; + clearLastClick(); } @@ -215,6 +219,7 @@ BOOL LLWorldMapView::postBuild() LLWorldMapView::~LLWorldMapView() { + //LL_INFOS("World Map") << "Destroying the map -> LLWorldMapView::~LLWorldMapView()" << LL_ENDL; cleanupTextures(); } @@ -228,14 +233,14 @@ void LLWorldMapView::cleanupTextures() // static void LLWorldMapView::setScale( F32 scale ) { - if (scale != gMapScale) + if (scale != sMapScale) { - F32 old_scale = gMapScale; + F32 old_scale = sMapScale; - gMapScale = scale; - if (gMapScale == 0.f) + sMapScale = scale; + if (sMapScale <= 0.f) { - gMapScale = 0.1f; + sMapScale = 0.1f; } F32 ratio = (scale / old_scale); @@ -243,8 +248,7 @@ void LLWorldMapView::setScale( F32 scale ) sPanY *= ratio; sTargetPanX = sPanX; sTargetPanY = sPanY; - - sPixelsPerMeter = gMapScale / REGION_WIDTH_METERS; + sVisibleTilesLoaded = false; } } @@ -256,6 +260,7 @@ void LLWorldMapView::translatePan( S32 delta_x, S32 delta_y ) sPanY += delta_y; sTargetPanX = sPanX; sTargetPanY = sPanY; + sVisibleTilesLoaded = false; } @@ -269,18 +274,22 @@ void LLWorldMapView::setPan( S32 x, S32 y, BOOL snap ) sPanX = sTargetPanX; sPanY = sTargetPanY; } + sVisibleTilesLoaded = false; } +bool LLWorldMapView::showRegionInfo() +{ + return (LLWorldMipmap::scaleToLevel(sMapScale) <= DRAW_SIMINFO_THRESHOLD ? true : false); +} /////////////////////////////////////////////////////////////////////////////////// // HELPERS BOOL is_agent_in_region(LLViewerRegion* region, LLSimInfo* info) { - return ((region && info) && (info->mName == region->getName())); + return (region && info && info->isName(region->getName())); } - /////////////////////////////////////////////////////////////////////////////////// void LLWorldMapView::draw() @@ -292,7 +301,7 @@ void LLWorldMapView::draw() F64 current_time = LLTimer::getElapsedSeconds(); mVisibleRegions.clear(); - + // animate pan if necessary sPanX = lerp(sPanX, sTargetPanX, LLCriticalDamp::getInterpolant(0.1f)); sPanY = lerp(sPanY, sTargetPanY, LLCriticalDamp::getInterpolant(0.1f)); @@ -303,10 +312,12 @@ void LLWorldMapView::draw() const F32 half_height = F32(height) / 2.0f; LLVector3d camera_global = gAgent.getCameraPositionGlobal(); + S32 level = LLWorldMipmap::scaleToLevel(sMapScale); + LLLocalClipRect clip(getLocalRect()); { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - + glMatrixMode(GL_MODELVIEW); // Clear the background alpha to 0 @@ -319,307 +330,59 @@ void LLWorldMapView::draw() } gGL.flush(); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setColorMask(true, true); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - F32 layer_alpha = 1.f; - - // Draw one image per layer - for (U32 layer_idx=0; layer_idx<LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap].size(); ++layer_idx) - { - if (!LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx].LayerDefined) - { - continue; - } - LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx]; - LLViewerFetchedTexture *current_image = layer->LayerImage; - - if (current_image->isMissingAsset()) - { - continue; // better to draw nothing than the missing asset image - } - - LLVector3d origin_global((F64)layer->LayerExtents.mLeft * REGION_WIDTH_METERS, (F64)layer->LayerExtents.mBottom * REGION_WIDTH_METERS, 0.f); - - // Find x and y position relative to camera's center. - LLVector3d rel_region_pos = origin_global - camera_global; - F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * gMapScale; - F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * gMapScale; - - F32 pix_width = gMapScale*(layer->LayerExtents.getWidth() + 1); - F32 pix_height = gMapScale*(layer->LayerExtents.getHeight() + 1); - - // When the view isn't panned, 0,0 = center of rectangle - F32 bottom = sPanY + half_height + relative_y; - F32 left = sPanX + half_width + relative_x; - F32 top = bottom + pix_height; - F32 right = left + pix_width; - F32 pixel_area = pix_width*pix_height; - // discard layers that are outside the rectangle - // and discard small layers - if (top < 0.f || - bottom > height || - right < 0.f || - left > width || - (pixel_area < 4*4)) - { - current_image->setBoostLevel(0); - continue; - } - - current_image->setBoostLevel(LLViewerTexture::BOOST_MAP); - current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY])); - - if (!current_image->hasGLTexture()) - { - continue; // better to draw nothing than the default image - } - -// LLTextureView::addDebugImage(current_image); - - // Draw using the texture. If we don't clamp we get artifact at - // the edge. - gGL.getTexUnit(0)->bind(current_image); - - // Draw map image into RGB - //gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - gGL.flush(); - gGL.setColorMask(true, false); - gGL.color4f(1.f, 1.f, 1.f, layer_alpha); - - gGL.begin(LLRender::QUADS); - gGL.texCoord2f(0.0f, 1.0f); - gGL.vertex3f(left, top, -1.0f); - gGL.texCoord2f(0.0f, 0.0f); - gGL.vertex3f(left, bottom, -1.0f); - gGL.texCoord2f(1.0f, 0.0f); - gGL.vertex3f(right, bottom, -1.0f); - gGL.texCoord2f(1.0f, 1.0f); - gGL.vertex3f(right, top, -1.0f); - gGL.end(); - - // draw an alpha of 1 where the sims are visible - gGL.flush(); - gGL.setColorMask(false, true); - gGL.color4f(1.f, 1.f, 1.f, 1.f); - - gGL.begin(LLRender::QUADS); - gGL.texCoord2f(0.0f, 1.0f); - gGL.vertex2f(left, top); - gGL.texCoord2f(0.0f, 0.0f); - gGL.vertex2f(left, bottom); - gGL.texCoord2f(1.0f, 0.0f); - gGL.vertex2f(right, bottom); - gGL.texCoord2f(1.0f, 1.0f); - gGL.vertex2f(right, top); - gGL.end(); - } +#if 1 + // Draw the image tiles + drawMipmap(width, height); gGL.flush(); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setColorMask(true, true); - // there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code? - F32 sim_alpha = 1.f; - - // Draw one image per region, centered on the camera position. - const S32 MAX_SIMULTANEOUS_TEX = 100; - const S32 MAX_REQUEST_PER_TICK = 5; - const S32 MIN_REQUEST_PER_TICK = 1; - S32 textures_requested_this_tick = 0; - - for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin(); - it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) + // Draw per sim overlayed information (names, mature, offline...) + for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin(); + it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) { - U64 handle = (*it).first; - LLSimInfo* info = (*it).second; + U64 handle = it->first; + LLSimInfo* info = it->second; - LLViewerFetchedTexture* simimage = info->mCurrentImage; - LLViewerFetchedTexture* overlayimage = info->mOverlayImage; - - if (gMapScale < SIM_MAP_SCALE) - { - if (simimage != NULL) simimage->setBoostLevel(0); - if (overlayimage != NULL) overlayimage->setBoostLevel(0); - continue; - } - LLVector3d origin_global = from_region_handle(handle); - LLVector3d camera_global = gAgent.getCameraPositionGlobal(); // Find x and y position relative to camera's center. LLVector3d rel_region_pos = origin_global - camera_global; - F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * gMapScale; - F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * gMapScale; + F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale; + F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale; + // Coordinates of the sim in pixels in the UI panel // When the view isn't panned, 0,0 = center of rectangle - F32 bottom = sPanY + half_height + relative_y; - F32 left = sPanX + half_width + relative_x; - F32 top = bottom + gMapScale ; - F32 right = left + gMapScale ; - - // Switch to world map texture (if available for this region) if either: - // 1. Tiles are zoomed out small enough, or - // 2. Sim's texture has not been loaded yet - F32 map_scale_cutoff = SIM_MAP_SCALE; - if ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) > 0) - { - map_scale_cutoff = SIM_NULL_MAP_SCALE; - } - - info->mShowAgentLocations = (gMapScale >= SIM_MAP_AGENT_SCALE); - - bool sim_visible = - (gMapScale >= map_scale_cutoff) && - (simimage != NULL) && - (simimage->hasGLTexture()); - - if (sim_visible) - { - // Fade in - if (info->mAlpha < 0.0f) - info->mAlpha = 1.f; // don't fade initially - else - info->mAlpha = lerp(info->mAlpha, 1.f, LLCriticalDamp::getInterpolant(0.15f)); - } - else - { - // Fade out - if (info->mAlpha < 0.0f) - info->mAlpha = 0.f; // don't fade initially - else - info->mAlpha = lerp(info->mAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f)); - } - - // discard regions that are outside the rectangle - // and discard small regions - if (top < 0.f || - bottom > height || - right < 0.f || - left > width ) + F32 bottom = sPanY + half_height + relative_y; + F32 left = sPanX + half_width + relative_x; + F32 top = bottom + sMapScale ; + F32 right = left + sMapScale ; + + // Discard if region is outside the screen rectangle (not visible on screen) + if ((top < 0.f) || (bottom > height) || + (right < 0.f) || (left > width) ) { - if (simimage != NULL) simimage->setBoostLevel(0); - if (overlayimage != NULL) overlayimage->setBoostLevel(0); + // Drop the "land for sale" fetching priority since it's outside the view rectangle + info->dropImagePriority(); continue; } - if (info->mCurrentImage.isNull()) - { - if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) || - ((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) && - (textures_requested_this_tick < MAX_REQUEST_PER_TICK))) - { - textures_requested_this_tick++; - info->mCurrentImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); - info->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); - simimage = info->mCurrentImage; - gGL.getTexUnit(0)->bind(simimage); - } - } - if (info->mOverlayImage.isNull() && info->mMapImageID[2].notNull()) - { - if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) || - ((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) && - (textures_requested_this_tick < MAX_REQUEST_PER_TICK))) - { - textures_requested_this_tick++; - info->mOverlayImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[2], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); - info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); - overlayimage = info->mOverlayImage; - gGL.getTexUnit(0)->bind(overlayimage); - } - } + // This list is used by other methods to know which regions are indeed displayed on screen mVisibleRegions.push_back(handle); - // See if the agents need updating - if (current_time - info->mAgentsUpdateTime > AGENTS_UPDATE_TIME) - { - LLWorldMap::getInstance()->sendItemRequest(MAP_ITEM_AGENT_LOCATIONS, info->mHandle); - info->mAgentsUpdateTime = current_time; - } - - // Bias the priority escalation for images nearer - LLVector3d center_global = origin_global; - center_global.mdV[VX] += 128.0; - center_global.mdV[VY] += 128.0; - - S32 draw_size = llround(gMapScale); - if (simimage != NULL) - { - simimage->setBoostLevel(LLViewerTexture::BOOST_MAP); - simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); - } - - if (overlayimage != NULL) - { - overlayimage->setBoostLevel(LLViewerTexture::BOOST_MAP); - overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); - } - -// LLTextureView::addDebugImage(simimage); - if (sim_visible && info->mAlpha > 0.001f) + // Update the agent count for that region if we're not too zoomed out already + if (level <= DRAW_SIMINFO_THRESHOLD) { - // Draw using the texture. If we don't clamp we get artifact at - // the edge. - LLGLSUIDefault gls_ui; - if (simimage != NULL) - gGL.getTexUnit(0)->bind(simimage); - - gGL.setSceneBlendType(LLRender::BT_ALPHA); - F32 alpha = sim_alpha * info->mAlpha; - gGL.color4f(1.f, 1.0f, 1.0f, alpha); - - gGL.begin(LLRender::QUADS); - gGL.texCoord2f(0.f, 1.f); - gGL.vertex3f(left, top, 0.f); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex3f(left, bottom, 0.f); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3f(right, bottom, 0.f); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex3f(right, top, 0.f); - gGL.end(); - - if (gSavedSettings.getBOOL("MapShowLandForSale") && overlayimage && overlayimage->hasGLTexture()) - { - gGL.getTexUnit(0)->bind(overlayimage); - gGL.color4f(1.f, 1.f, 1.f, alpha); - gGL.begin(LLRender::QUADS); - gGL.texCoord2f(0.f, 1.f); - gGL.vertex3f(left, top, -0.5f); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex3f(left, bottom, -0.5f); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex3f(right, bottom, -0.5f); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex3f(right, top, -0.5f); - gGL.end(); - } - - if ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) == 0) - { - // draw an alpha of 1 where the sims are visible (except NULL sims) - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - gGL.setColorMask(false, true); - gGL.color4f(1.f, 1.f, 1.f, 1.f); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin(LLRender::QUADS); - gGL.vertex2f(left, top); - gGL.vertex2f(left, bottom); - gGL.vertex2f(right, bottom); - gGL.vertex2f(right, top); - gGL.end(); - - gGL.flush(); - gGL.setColorMask(true, true); - } + info->updateAgentCount(current_time); } - if (info->mAccess == SIM_ACCESS_DOWN) + if (info->isDown()) { // Draw a transparent red square over down sims gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA); @@ -633,18 +396,15 @@ void LLWorldMapView::draw() gGL.vertex2f(right, top); gGL.end(); } - - // As part of the AO project, we no longer want to draw access indicators; - // it's too complicated to get all the rules straight and will only + // As part of the AO project, we no longer want to draw access indicators; + // it's too complicated to get all the rules straight and will only // cause confusion. /********************** - // If this is mature, and you are not, draw a line across it - if (info->mAccess != SIM_ACCESS_DOWN - && info->mAccess > SIM_ACCESS_PG - && gAgent.isTeen()) + else if (!info->isPG() && gAgent.isTeen()) { + // If this is a mature region, and you are not, draw a line across it gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); - + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color3f(1.f, 0.f, 0.f); gGL.begin(LLRender::LINES); @@ -655,68 +415,67 @@ void LLWorldMapView::draw() gGL.end(); } **********************/ - - // Draw the region name in the lower left corner - LLFontGL* font = LLFontGL::getFontSansSerifSmall(); - - std::string mesg; - if (gMapScale < sThresholdA) + else if (gSavedSettings.getBOOL("MapShowLandForSale") && (level <= DRAW_LANDFORSALE_THRESHOLD)) { + // Draw the overlay image "Land for Sale / Land for Auction" + LLViewerFetchedTexture* overlayimage = info->getLandForSaleImage(); + if (overlayimage) + { + // Inform the fetch mechanism of the size we need + S32 draw_size = llround(sMapScale); + overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); + // Draw something whenever we have enough info + if (overlayimage->hasGLTexture()) + { + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); + gGL.getTexUnit(0)->bind(overlayimage); + gGL.color4f(1.f, 1.f, 1.f, 1.f); + gGL.begin(LLRender::QUADS); + gGL.texCoord2f(0.f, 1.f); + gGL.vertex3f(left, top, -0.5f); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex3f(left, bottom, -0.5f); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex3f(right, bottom, -0.5f); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex3f(right, top, -0.5f); + gGL.end(); + } + } } - else if (gMapScale < sThresholdB) + else { - // mesg = llformat( info->mAgents); + // If we're not displaying the "land for sale", drop its fetching priority + info->dropImagePriority(); } - else + + // Draw the region name in the lower left corner + if (sMapScale >= DRAW_TEXT_THRESHOLD) { - //mesg = llformat("%d / %s (%s)", - // info->mAgents, - // info->mName.c_str(), - // LLViewerRegion::accessToShortString(info->mAccess).c_str() ); - if (info->mAccess == SIM_ACCESS_DOWN) + LLFontGL* font = LLFontGL::getFontSansSerifSmall(); + std::string mesg; + if (info->isDown()) { - mesg = llformat( "%s (%s)", info->mName.c_str(), sStringsMap["offline"].c_str()); + mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str()); } else { - mesg = info->mName; + mesg = info->getName(); } - } - - if (!mesg.empty()) - { - font->renderUTF8( - mesg, 0, - llfloor(left + 3), - llfloor(bottom + 2), - LLColor4::white, - LLFontGL::LEFT, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); - - // If map texture is still loading, - // display "Loading" placeholder text. - if ((simimage != NULL) && - simimage->getDiscardLevel() != 1 && - simimage->getDiscardLevel() != 0) + if (!mesg.empty()) { font->renderUTF8( - sStringsMap["loading"], 0, - llfloor(left + 18), - llfloor(top - 25), + mesg, 0, + llfloor(left + 3), llfloor(bottom + 2), LLColor4::white, - LLFontGL::LEFT, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); } } } - // #endif used to be here + #endif - // there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code? + #if 1 // Draw background rectangle LLGLSUIDefault gls_ui; { @@ -726,69 +485,49 @@ void LLWorldMapView::draw() gGL.color4fv( mBackgroundColor.mV ); gl_rect_2d(0, height, width, 0); } - + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setSceneBlendType(LLRender::BT_ALPHA); - // Infohubs - if (gSavedSettings.getBOOL("MapShowInfohubs")) //(gMapScale >= sThresholdB) + // Draw item infos if we're not zoomed out too much and there's something to draw + if ((level <= DRAW_SIMINFO_THRESHOLD) && (gSavedSettings.getBOOL("MapShowInfohubs") || + gSavedSettings.getBOOL("MapShowTelehubs") || + gSavedSettings.getBOOL("MapShowLandForSale") || + gSavedSettings.getBOOL("MapShowEvents") || + gSavedSettings.getBOOL("ShowMatureEvents") || + gSavedSettings.getBOOL("ShowAdultEvents"))) { - drawGenericItems(LLWorldMap::getInstance()->mInfohubs, sInfohubImage); + drawItems(); } - // Telehubs - if (gSavedSettings.getBOOL("MapShowTelehubs")) //(gMapScale >= sThresholdB) - { - drawGenericItems(LLWorldMap::getInstance()->mTelehubs, sTelehubImage); - } - - // Home Sweet Home + // Draw the Home location (always) LLVector3d home; if (gAgent.getHomePosGlobal(&home)) { drawImage(home, sHomeImage); } - if (gSavedSettings.getBOOL("MapShowLandForSale")) - { - drawGenericItems(LLWorldMap::getInstance()->mLandForSale, sForSaleImage); - // for 1.23, we're showing normal land and adult land in the same UI; you don't - // get a choice about which ones you want. If you're currently asking for adult - // content and land you'll get the adult land. - if (gAgent.canAccessAdult()) - { - drawGenericItems(LLWorldMap::getInstance()->mLandForSaleAdult, sForSaleAdultImage); - } - } - - if (gSavedSettings.getBOOL("MapShowEvents") || - gSavedSettings.getBOOL("ShowMatureEvents") || - gSavedSettings.getBOOL("ShowAdultEvents") ) - { - drawEvents(); - } - - // Now draw your avatar after all that other stuff. + // Draw the current agent after all that other stuff. LLVector3d pos_global = gAgent.getPositionGlobal(); - drawImage(pos_global, sAvatarLargeImage); + drawImage(pos_global, sAvatarYouImage); LLVector3 pos_map = globalPosToView(pos_global); if (!pointInView(llround(pos_map.mV[VX]), llround(pos_map.mV[VY]))) { - drawTracking(pos_global, - lerp(LLColor4::yellow, LLColor4::orange, 0.4f), - TRUE, - "You are here", - "", - llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking + drawTracking(pos_global, + lerp(LLColor4::yellow, LLColor4::orange, 0.4f), + TRUE, + "You are here", + "", + llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking } - // Show your viewing angle + // Draw the current agent viewing angle drawFrustum(); // Draw icons for the avatars in each region. - // Drawn after your avatar so you can see nearby people. - if (gSavedSettings.getBOOL("MapShowPeople")) + // Drawn this after the current agent avatar so one can see nearby people + if (gSavedSettings.getBOOL("MapShowPeople") && (level <= DRAW_SIMINFO_THRESHOLD)) { drawAgents(); } @@ -798,9 +537,9 @@ void LLWorldMapView::draw() if ( LLTracker::TRACKING_AVATAR == tracking_status ) { drawTracking( LLAvatarTracker::instance().getGlobalPos(), map_track_color, TRUE, LLTracker::getLabel(), "" ); - } - else if ( LLTracker::TRACKING_LANDMARK == tracking_status - || LLTracker::TRACKING_LOCATION == tracking_status ) + } + else if ( LLTracker::TRACKING_LANDMARK == tracking_status + || LLTracker::TRACKING_LOCATION == tracking_status ) { // While fetching landmarks, will have 0,0,0 location for a while, // so don't draw. JC @@ -810,31 +549,33 @@ void LLWorldMapView::draw() drawTracking( pos_global, map_track_color, TRUE, LLTracker::getLabel(), LLTracker::getToolTip() ); } } - else if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation) + else if (LLWorldMap::getInstance()->isTracking()) { - if (LLWorldMap::getInstance()->mInvalidLocation) + if (LLWorldMap::getInstance()->isTrackingInvalidLocation()) { - // We know this location to be invalid + // We know this location to be invalid, draw a blue circle LLColor4 loading_color(0.0, 0.5, 1.0, 1.0); - drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, getString("InvalidLocation"), ""); + drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, getString("InvalidLocation"), ""); } else { + // We don't know yet what that location is, draw a throbing blue circle double value = fmod(current_time, 2); - value = 0.5 + 0.5*cos(value * 3.14159f); + value = 0.5 + 0.5*cos(value * F_PI); LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0); - drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, getString("Loading"), ""); + drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, getString("Loading"), ""); } } - // #endif used to be here - + #endif + // turn off the scissor LLGLDisable no_scissor(GL_SCISSOR_TEST); - + updateDirections(); LLView::draw(); + // Get sim info for all sims in view updateVisibleBlocks(); } // end draw() @@ -845,36 +586,182 @@ void LLWorldMapView::setVisible(BOOL visible) LLPanel::setVisible(visible); if (!visible) { - for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; map++) + // Drop the download of tiles and images priority to nil if we hide the map + LLWorldMap::getInstance()->dropImagePriorities(); + } +} + +void LLWorldMapView::drawMipmap(S32 width, S32 height) +{ + // Compute the level of the mipmap to use for the current scale level + S32 level = LLWorldMipmap::scaleToLevel(sMapScale); + // Set the tile boost level so that unused tiles get to 0 + LLWorldMap::getInstance()->equalizeBoostLevels(); + + // Render whatever we already have loaded if we haven't the current level + // complete and use it as a background (scaled up or scaled down) + if (!sVisibleTilesLoaded) + { + // Note: the (load = false) parameter avoids missing tiles to be fetched (i.e. we render what we have, no more) + // Check all the lower res levels and render them in reverse order (worse to best) + // We need to traverse all the levels as the user can zoom in very fast + for (S32 l = LLWorldMipmap::MAP_LEVELS; l > level; l--) { - for (U32 layer_idx=0; layer_idx<LLWorldMap::getInstance()->mMapLayers[map].size(); ++layer_idx) - { - if (LLWorldMap::getInstance()->mMapLayers[map][layer_idx].LayerDefined) - { - LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[map][layer_idx]; - layer->LayerImage->setBoostLevel(0); - } - } + drawMipmapLevel(width, height, l, false); } - for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin(); - it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) + // Skip the current level, as we'll do it anyway here under... + + // Just go one level down in res as it can really get too much stuff + // when zooming out and too small to see anyway... + if (level > 1) { - LLSimInfo* info = (*it).second; - if (info->mCurrentImage.notNull()) + drawMipmapLevel(width, height, level - 1, false); + } + } + else + { + //LL_INFOS("World Map") << "Render complete, don't draw background..." << LL_ENDL; + } + + // Render the current level + sVisibleTilesLoaded = drawMipmapLevel(width, height, level); + + return; +} + +// Return true if all the tiles required to render that level have been fetched or are truly missing +bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load) +{ + // Check input level + llassert (level > 0); + if (level <= 0) + return false; + + // Count tiles hit and completed + S32 completed_tiles = 0; + S32 total_tiles = 0; + + // Size in meters (global) of each tile of that level + S32 tile_width = LLWorldMipmap::MAP_TILE_SIZE * (1 << (level - 1)); + // Dimension of the screen in meter at that scale + LLVector3d pos_SW = viewPosToGlobal(0, 0); + LLVector3d pos_NE = viewPosToGlobal(width, height); + // Add external band of tiles on the outskirt so to hit the partially displayed tiles right and top + pos_NE[VX] += tile_width; + pos_NE[VY] += tile_width; + + // Iterate through the tiles on screen: we just need to ask for one tile every tile_width meters + U32 grid_x, grid_y; + for (F64 index_y = pos_SW[VY]; index_y < pos_NE[VY]; index_y += tile_width) + { + for (F64 index_x = pos_SW[VX]; index_x < pos_NE[VX]; index_x += tile_width) + { + // Compute the world coordinates of the current point + LLVector3d pos_global(index_x, index_y, pos_SW[VZ]); + // Convert to the mipmap level coordinates for that point (i.e. which tile to we hit) + LLWorldMipmap::globalToMipmap(pos_global[VX], pos_global[VY], level, &grid_x, &grid_y); + // Get the tile. Note: NULL means that the image does not exist (so it's considered "complete" as far as fetching is concerned) + LLPointer<LLViewerFetchedTexture> simimage = LLWorldMap::getInstance()->getObjectsTile(grid_x, grid_y, level, load); + if (simimage) { - info->mCurrentImage->setBoostLevel(0); + // Checks that the image has a valid texture + if (simimage->hasGLTexture()) + { + // Increment the number of completly fetched tiles + completed_tiles++; + + // Convert those coordinates (SW corner of the mipmap tile) into world (meters) coordinates + pos_global[VX] = grid_x * REGION_WIDTH_METERS; + pos_global[VY] = grid_y * REGION_WIDTH_METERS; + // Now to screen coordinates for SW corner of that tile + LLVector3 pos_screen = globalPosToView (pos_global); + F32 left = pos_screen[VX]; + F32 bottom = pos_screen[VY]; + // Compute the NE corner coordinates of the tile now + pos_global[VX] += tile_width; + pos_global[VY] += tile_width; + pos_screen = globalPosToView (pos_global); + F32 right = pos_screen[VX]; + F32 top = pos_screen[VY]; + + // Draw the tile + LLGLSUIDefault gls_ui; + gGL.getTexUnit(0)->bind(simimage.get()); + simimage->setAddressMode(LLTexUnit::TAM_CLAMP); + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.color4f(1.f, 1.0f, 1.0f, 1.0f); + + gGL.begin(LLRender::QUADS); + gGL.texCoord2f(0.f, 1.f); + gGL.vertex3f(left, top, 0.f); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex3f(left, bottom, 0.f); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex3f(right, bottom, 0.f); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex3f(right, top, 0.f); + gGL.end(); +#if DEBUG_DRAW_TILE + drawTileOutline(level, top, left, bottom, right); +#endif // DEBUG_DRAW_TILE + } + //else + //{ + // Waiting for a tile -> the level is not complete + // LL_INFOS("World Map") << "Unfetched tile. level = " << level << LL_ENDL; + //} } - if (info->mOverlayImage.notNull()) + else { - info->mOverlayImage->setBoostLevel(0); + // Unexistent tiles are counted as "completed" + completed_tiles++; } + // Increment the number of tiles in that level / screen + total_tiles++; } } + return (completed_tiles == total_tiles); +} + +// Draw lines (rectangle outline and cross) to visualize the position of the tile +// Used for debug only +void LLWorldMapView::drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right) +{ + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + if (level == 1) + gGL.color3f(1.f, 0.f, 0.f); // red + else if (level == 2) + gGL.color3f(0.f, 1.f, 0.f); // green + else if (level == 3) + gGL.color3f(0.f, 0.f, 1.f); // blue + else if (level == 4) + gGL.color3f(1.f, 1.f, 0.f); // yellow + else if (level == 5) + gGL.color3f(1.f, 0.f, 1.f); // magenta + else if (level == 6) + gGL.color3f(0.f, 1.f, 1.f); // cyan + else if (level == 7) + gGL.color3f(1.f, 1.f, 1.f); // white + else + gGL.color3f(0.f, 0.f, 0.f); // black + gGL.begin(LLRender::LINE_STRIP); + gGL.vertex2f(left, top); + gGL.vertex2f(right, bottom); + gGL.vertex2f(left, bottom); + gGL.vertex2f(right, top); + gGL.vertex2f(left, top); + gGL.vertex2f(left, bottom); + gGL.vertex2f(right, bottom); + gGL.vertex2f(right, top); + gGL.end(); } -void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image) +void LLWorldMapView::drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image) { - LLWorldMap::item_info_list_t::const_iterator e; + LLSimInfo::item_info_list_t::const_iterator e; for (e = items.begin(); e != items.end(); ++e) { drawGenericItem(*e, image); @@ -883,7 +770,7 @@ void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, void LLWorldMapView::drawGenericItem(const LLItemInfo& item, LLUIImagePtr image) { - drawImage(item.mPosGlobal, image); + drawImage(item.getGlobalPosition(), image); } @@ -906,137 +793,91 @@ void LLWorldMapView::drawImageStack(const LLVector3d& global_pos, LLUIImagePtr i } } - -void LLWorldMapView::drawAgents() +void LLWorldMapView::drawItems() { - static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white); - static LLUIColor map_avatar_friend_color = LLUIColorTable::instance().getColor("MapAvatarFriendColor", LLColor4::white); - - F32 agents_scale = (gMapScale * 0.9f) / 256.f; + bool mature_enabled = gAgent.canAccessMature(); + bool adult_enabled = gAgent.canAccessAdult(); + + BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("ShowMatureEvents"); + BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("ShowAdultEvents"); for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) { U64 handle = *iter; - LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); - if (siminfo && (siminfo->mAccess == SIM_ACCESS_DOWN)) + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if ((info == NULL) || (info->isDown())) { continue; } - LLWorldMap::agent_list_map_t::iterator counts_iter = LLWorldMap::getInstance()->mAgentLocationsMap.find(handle); - if (siminfo && siminfo->mShowAgentLocations && counts_iter != LLWorldMap::getInstance()->mAgentLocationsMap.end()) + // Infohubs + if (gSavedSettings.getBOOL("MapShowInfohubs")) { - // Show Individual agents (or little stacks where real agents are) - LLWorldMap::item_info_list_t& agentcounts = counts_iter->second; - S32 sim_agent_count = 0; - for (LLWorldMap::item_info_list_t::iterator iter = agentcounts.begin(); - iter != agentcounts.end(); ++iter) - { - const LLItemInfo& info = *iter; - S32 agent_count = info.mExtra; - sim_agent_count += info.mExtra; - // Here's how we'd choose the color if info.mID were available but it's not being sent: - //LLColor4 color = (agent_count == 1 && is_agent_friend(info.mID)) ? map_avatar_friend_color : map_avatar_color; - drawImageStack(info.mPosGlobal, sAvatarSmallImage, agent_count, 3.f, map_avatar_color); - } - LLWorldMap::getInstance()->mNumAgents[handle] = sim_agent_count; // override mNumAgents for this sim + drawGenericItems(info->getInfoHub(), sInfohubImage); } - else + // Telehubs + if (gSavedSettings.getBOOL("MapShowTelehubs")) + { + drawGenericItems(info->getTeleHub(), sTelehubImage); + } + // Land for sale + if (gSavedSettings.getBOOL("MapShowLandForSale")) { - // Show agent 'stack' at center of sim - S32 num_agents = LLWorldMap::getInstance()->mNumAgents[handle]; - if (num_agents > 0) + drawGenericItems(info->getLandForSale(), sForSaleImage); + // for 1.23, we're showing normal land and adult land in the same UI; you don't + // get a choice about which ones you want. If you're currently asking for adult + // content and land you'll get the adult land. + if (gAgent.canAccessAdult()) { - LLVector3d region_center = from_region_handle(handle); - region_center[VX] += REGION_WIDTH_METERS / 2; - region_center[VY] += REGION_WIDTH_METERS / 2; - // Reduce the stack size as you zoom out - always display at lease one agent where there is one or more - S32 agent_count = (S32)(((num_agents-1) * agents_scale + (num_agents-1) * 0.1f)+.1f) + 1; - drawImageStack(region_center, sAvatarSmallImage, agent_count, 3.f, map_avatar_color); + drawGenericItems(info->getLandForSaleAdult(), sForSaleAdultImage); } } + // PG Events + if (gSavedSettings.getBOOL("MapShowEvents")) + { + drawGenericItems(info->getPGEvent(), sEventImage); + } + // Mature Events + if (show_mature) + { + drawGenericItems(info->getMatureEvent(), sEventMatureImage); + } + // Adult Events + if (show_adult) + { + drawGenericItems(info->getAdultEvent(), sEventAdultImage); + } } } - -void LLWorldMapView::drawEvents() +void LLWorldMapView::drawAgents() { - bool mature_enabled = gAgent.canAccessMature(); - bool adult_enabled = gAgent.canAccessAdult(); - - BOOL show_pg = gSavedSettings.getBOOL("MapShowEvents"); - BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("ShowMatureEvents"); - BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("ShowAdultEvents"); + static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white); - // First the non-selected events - LLWorldMap::item_info_list_t::const_iterator e; - if (show_pg) + for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) { - for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e) + U64 handle = *iter; + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if ((siminfo == NULL) || (siminfo->isDown())) { - if (!e->mSelected) - { - drawGenericItem(*e, sEventImage); - } + continue; } - } - if (show_mature) - { - for (e = LLWorldMap::getInstance()->mMatureEvents.begin(); e != LLWorldMap::getInstance()->mMatureEvents.end(); ++e) - { - if (!e->mSelected) - { - drawGenericItem(*e, sEventMatureImage); - } - } - } - if (show_adult) - { - for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e) - { - if (!e->mSelected) - { - drawGenericItem(*e, sEventAdultImage); - } - } - } - // Then the selected events - if (show_pg) - { - for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e) + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAgentLocation().begin(); + while (it != siminfo->getAgentLocation().end()) { - if (e->mSelected) - { - drawGenericItem(*e, sEventImage); - } + // Show Individual agents (or little stacks where real agents are) + + // Here's how we'd choose the color if info.mID were available but it's not being sent: + // LLColor4 color = (agent_count == 1 && is_agent_friend(info.mID)) ? friend_color : avatar_color; + drawImageStack(it->getGlobalPosition(), sAvatarSmallImage, it->getCount(), 3.f, map_avatar_color); + ++it; } } - if (show_mature) - { - for (e = LLWorldMap::getInstance()->mMatureEvents.begin(); e != LLWorldMap::getInstance()->mMatureEvents.end(); ++e) - { - if (e->mSelected) - { - drawGenericItem(*e, sEventMatureImage); - } - } - } - if (show_adult) - { - for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e) - { - if (e->mSelected) - { - drawGenericItem(*e, sEventAdultImage); - } - } - } } - void LLWorldMapView::drawFrustum() { // Draw frustum - F32 meters_to_pixels = gMapScale/ REGION_WIDTH_METERS; + F32 meters_to_pixels = sMapScale/ REGION_WIDTH_METERS; F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); @@ -1077,8 +918,8 @@ LLVector3 LLWorldMapView::globalPosToView( const LLVector3d& global_pos ) LLVector3 pos_local; pos_local.setVec(relative_pos_global); // convert to floats from doubles - pos_local.mV[VX] *= sPixelsPerMeter; - pos_local.mV[VY] *= sPixelsPerMeter; + pos_local.mV[VX] *= sMapScale / REGION_WIDTH_METERS; + pos_local.mV[VY] *= sMapScale / REGION_WIDTH_METERS; // leave Z component in meters @@ -1162,7 +1003,7 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y ) LLVector3 pos_local( (F32)x, (F32)y, 0.f ); - pos_local *= ( REGION_WIDTH_METERS / gMapScale ); + pos_local *= ( REGION_WIDTH_METERS / sMapScale ); LLVector3d pos_global; pos_global.setVec( pos_local ); @@ -1183,23 +1024,20 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y ) BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, MASK mask ) { LLVector3d pos_global = viewPosToGlobal(x, y); - + U64 handle = to_region_handle(pos_global); std::string tooltip_msg; - LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); if (info) { LLViewerRegion *region = gAgent.getRegion(); - std::string message = - llformat("%s (%s)", - info->mName.c_str(), - LLViewerRegion::accessToString(info->mAccess).c_str()); + std::string message = llformat("%s (%s)", info->getName().c_str(), info->getAccessString().c_str()); - if (info->mAccess != SIM_ACCESS_DOWN) + if (!info->isDown()) { - S32 agent_count = LLWorldMap::getInstance()->mNumAgents[info->mHandle]; - if (region && region->getHandle() == info->mHandle) + S32 agent_count = info->getAgentCount(); + if (region && (region->getHandle() == handle)) { ++agent_count; // Bump by 1 if we're here } @@ -1208,6 +1046,8 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, MASK mask ) // zoomed out, so don't display anything about the count. JC if (agent_count > 0) { + // Merov: i18n horror!!! Even using gettext(), concatenating strings is not localizable. + // The singular/plural switch form here under might make no sense in some languages. Don't do that. message += llformat("\n%d ", agent_count); if (agent_count == 1) @@ -1223,7 +1063,7 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, MASK mask ) tooltip_msg.assign( message ); // Optionally show region flags - std::string region_flags = LLViewerRegion::regionFlagsToString(info->mRegionFlags); + std::string region_flags = info->getFlagsString(); if (!region_flags.empty()) { @@ -1263,6 +1103,9 @@ static void drawDot(F32 x_pixels, F32 y_pixels, } else { + // Draw V indicator for above or below + // *TODO: Replace this vector drawing with icons + F32 left = x_pixels - dot_radius; F32 right = x_pixels + dot_radius; F32 center = (left + right) * 0.5f; @@ -1271,13 +1114,14 @@ static void drawDot(F32 x_pixels, F32 y_pixels, gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4fv( color.mV ); - LLUI::setLineWidth(1.5f); - F32 h_bar = relative_z > HEIGHT_THRESHOLD ? top : bottom; // horizontal bar Y + LLUI::setLineWidth(3.0f); + F32 point = relative_z > HEIGHT_THRESHOLD ? top : bottom; // Y pos of the point of the V + F32 back = relative_z > HEIGHT_THRESHOLD ? bottom : top; // Y pos of the ends of the V gGL.begin( LLRender::LINES ); - gGL.vertex2f(center, top); - gGL.vertex2f(left, h_bar); - gGL.vertex2f(right, h_bar); - gGL.vertex2f(right, bottom); + gGL.vertex2f(left, back); + gGL.vertex2f(center, point); + gGL.vertex2f(center, point); + gGL.vertex2f(right, back); gGL.end(); LLUI::setLineWidth(1.0f); } @@ -1292,7 +1136,7 @@ void LLWorldMapView::drawAvatar(F32 x_pixels, F32 dot_radius) { const F32 HEIGHT_THRESHOLD = 7.f; - LLUIImagePtr dot_image = sAvatarSmallImage; + LLUIImagePtr dot_image = sAvatarLevelImage; if(relative_z < -HEIGHT_THRESHOLD) { dot_image = sAvatarBelowImage; @@ -1301,10 +1145,12 @@ void LLWorldMapView::drawAvatar(F32 x_pixels, { dot_image = sAvatarAboveImage; } - dot_image->draw( - llround(x_pixels) - dot_image->getWidth()/2, - llround(y_pixels) - dot_image->getHeight()/2, - color); + S32 dot_width = llround(dot_radius * 2.f); + dot_image->draw(llround(x_pixels - dot_radius), + llround(y_pixels - dot_radius), + dot_width, + dot_width, + color); } // Pass relative Z of 0 to draw at same level. @@ -1565,7 +1411,7 @@ void LLWorldMapView::reshape( S32 width, S32 height, BOOL called_from_parent ) bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track) { - LLVector3 pos_view = globalPosToView(item.mPosGlobal); + LLVector3 pos_view = globalPosToView(item.getGlobalPosition()); S32 item_x = llround(pos_view.mV[VX]); S32 item_y = llround(pos_view.mV[VY]); @@ -1574,12 +1420,12 @@ bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bo if (y < item_y - BIG_DOT_RADIUS) return false; if (y > item_y + BIG_DOT_RADIUS) return false; - LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromHandle(item.mRegionHandle); + LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromHandle(item.getRegionHandle()); if (sim_info) { if (track) { - gFloaterWorldMap->trackLocation(item.mPosGlobal); + gFloaterWorldMap->trackLocation(item.getGlobalPosition()); } } @@ -1588,8 +1434,8 @@ bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bo gFloaterWorldMap->trackGenericItem(item); } - item.mSelected = TRUE; - *id = item.mID; +// item.setSelected(true); + *id = item.getUUID(); return true; } @@ -1612,108 +1458,116 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, *hit_type = 0; // hit nothing - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; - LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE; - LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; + LLWorldMap::getInstance()->cancelTracking(); - LLWorldMap::item_info_list_t::iterator it; - - // clear old selected stuff - for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it) - { - (*it).mSelected = FALSE; - } - for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it) + S32 level = LLWorldMipmap::scaleToLevel(sMapScale); + // If the zoom level is not too far out already, test hits + if (level <= DRAW_SIMINFO_THRESHOLD) { - (*it).mSelected = FALSE; - } - for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it) - { - (*it).mSelected = FALSE; - } - for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it) - { - (*it).mSelected = FALSE; - } - - // Select event you clicked on - if (gSavedSettings.getBOOL("MapShowEvents")) - { - for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it) - { - LLItemInfo& event = *it; - - if (checkItemHit(x, y, event, id, false)) - { - *hit_type = MAP_ITEM_PG_EVENT; - mItemPicked = TRUE; - gFloaterWorldMap->trackEvent(event); - return; - } - } - } - if (gSavedSettings.getBOOL("ShowMatureEvents")) - { - for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it) - { - LLItemInfo& event = *it; - - if (checkItemHit(x, y, event, id, false)) - { - *hit_type = MAP_ITEM_MATURE_EVENT; - mItemPicked = TRUE; - gFloaterWorldMap->trackEvent(event); - return; - } - } - } - if (gSavedSettings.getBOOL("ShowAdultEvents")) - { - for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it) - { - LLItemInfo& event = *it; - - if (checkItemHit(x, y, event, id, false)) - { - *hit_type = MAP_ITEM_ADULT_EVENT; - mItemPicked = TRUE; - gFloaterWorldMap->trackEvent(event); - return; - } - } - } - - if (gSavedSettings.getBOOL("MapShowLandForSale")) - { - for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it) - { - LLItemInfo& land = *it; + bool show_mature = gAgent.canAccessMature() && gSavedSettings.getBOOL("ShowMatureEvents"); + bool show_adult = gAgent.canAccessAdult() && gSavedSettings.getBOOL("ShowAdultEvents"); - if (checkItemHit(x, y, land, id, true)) - { - *hit_type = MAP_ITEM_LAND_FOR_SALE; - mItemPicked = TRUE; - return; - } - } - - for (it = LLWorldMap::getInstance()->mLandForSaleAdult.begin(); it != LLWorldMap::getInstance()->mLandForSaleAdult.end(); ++it) + // Test hits if trackable data are displayed, otherwise, we don't even bother + if (gSavedSettings.getBOOL("MapShowEvents") || show_mature || show_adult || gSavedSettings.getBOOL("MapShowLandForSale")) { - LLItemInfo& land = *it; - - if (checkItemHit(x, y, land, id, true)) + // Iterate through the visible regions + for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) { - *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT; - mItemPicked = TRUE; - return; + U64 handle = *iter; + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if ((siminfo == NULL) || (siminfo->isDown())) + { + continue; + } + // If on screen check hits with the visible item lists + if (gSavedSettings.getBOOL("MapShowEvents")) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getPGEvent().begin(); + while (it != siminfo->getPGEvent().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, false)) + { + *hit_type = MAP_ITEM_PG_EVENT; + mItemPicked = TRUE; + gFloaterWorldMap->trackEvent(event); + return; + } + ++it; + } + } + if (show_mature) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getMatureEvent().begin(); + while (it != siminfo->getMatureEvent().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, false)) + { + *hit_type = MAP_ITEM_MATURE_EVENT; + mItemPicked = TRUE; + gFloaterWorldMap->trackEvent(event); + return; + } + ++it; + } + } + if (show_adult) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAdultEvent().begin(); + while (it != siminfo->getAdultEvent().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, false)) + { + *hit_type = MAP_ITEM_ADULT_EVENT; + mItemPicked = TRUE; + gFloaterWorldMap->trackEvent(event); + return; + } + ++it; + } + } + if (gSavedSettings.getBOOL("MapShowLandForSale")) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getLandForSale().begin(); + while (it != siminfo->getLandForSale().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, true)) + { + *hit_type = MAP_ITEM_LAND_FOR_SALE; + mItemPicked = TRUE; + return; + } + ++it; + } + // for 1.23, we're showing normal land and adult land in the same UI; you don't + // get a choice about which ones you want. If you're currently asking for adult + // content and land you'll get the adult land. + if (gAgent.canAccessAdult()) + { + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getLandForSaleAdult().begin(); + while (it != siminfo->getLandForSaleAdult().end()) + { + LLItemInfo event = *it; + if (checkItemHit(x, y, event, id, true)) + { + *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT; + mItemPicked = TRUE; + return; + } + ++it; + } + } + } } } } - // If we get here, we haven't clicked on an icon + // If we get here, we haven't clicked on anything gFloaterWorldMap->trackLocation(pos_global); mItemPicked = FALSE; - *id = LLUUID::null; return; } @@ -1774,59 +1628,36 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask ) return FALSE; } -U32 LLWorldMapView::updateBlock(S32 block_x, S32 block_y) +void LLWorldMapView::updateVisibleBlocks() { - U32 blocks_requested = 0; - S32 offset = block_x | (block_y * MAP_BLOCK_RES); - if (!LLWorldMap::getInstance()->mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset]) + if (LLWorldMipmap::scaleToLevel(sMapScale) > DRAW_SIMINFO_THRESHOLD) { -// llinfos << "Loading Block (" << block_x << "," << block_y << ")" << llendl; - LLWorldMap::getInstance()->sendMapBlockRequest(block_x << 3, block_y << 3, (block_x << 3) + 7, (block_y << 3) + 7); - LLWorldMap::getInstance()->mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset] = TRUE; - blocks_requested++; + // If we're zoomed out too much, we just don't load all those sim info: too much! + return; } - return blocks_requested; -} -U32 LLWorldMapView::updateVisibleBlocks() -{ - if (gMapScale < SIM_MAP_SCALE) - { - // We don't care what is loaded if we're zoomed out - return 0; - } + // Load the blocks visible in the current World Map view + // Get the World Map view coordinates and boundaries LLVector3d camera_global = gAgent.getCameraPositionGlobal(); - - F32 pixels_per_region = gMapScale; const S32 width = getRect().getWidth(); const S32 height = getRect().getHeight(); - // Convert pan to sim coordinates - S32 world_center_x_lo = S32(((-sPanX - width/2) / pixels_per_region) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); - S32 world_center_x_hi = S32(((-sPanX + width/2) / pixels_per_region) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); - S32 world_center_y_lo = S32(((-sPanY - height/2) / pixels_per_region) + (camera_global.mdV[1] / REGION_WIDTH_METERS)); - S32 world_center_y_hi = S32(((-sPanY + height/2)/ pixels_per_region) + (camera_global.mdV[1] / REGION_WIDTH_METERS)); - - // Find the corresponding 8x8 block - S32 world_block_x_lo = world_center_x_lo >> 3; - S32 world_block_x_hi = world_center_x_hi >> 3; - S32 world_block_y_lo = world_center_y_lo >> 3; - S32 world_block_y_hi = world_center_y_hi >> 3; - - U32 blocks_requested = 0; - const U32 max_blocks_requested = 9; + const F32 half_width = F32(width) / 2.0f; + const F32 half_height = F32(height) / 2.0f; - for (S32 block_x = llmax(world_block_x_lo, 0); block_x <= llmin(world_block_x_hi, MAP_BLOCK_RES-1); ++block_x) - { - for (S32 block_y = llmax(world_block_y_lo, 0); block_y <= llmin(world_block_y_hi, MAP_BLOCK_RES-1); ++block_y) - { - blocks_requested += updateBlock(block_x, block_y); - if (blocks_requested >= max_blocks_requested) - return blocks_requested; - } - } - return blocks_requested; -} + // Compute center into sim grid coordinates + S32 world_center_x = S32((-sPanX / sMapScale) + (camera_global.mdV[0] / REGION_WIDTH_METERS)); + S32 world_center_y = S32((-sPanY / sMapScale) + (camera_global.mdV[1] / REGION_WIDTH_METERS)); + + // Compute the boundaries into sim grid coordinates + S32 world_left = world_center_x - S32(half_width / sMapScale) - 1; + S32 world_right = world_center_x + S32(half_width / sMapScale) + 1; + S32 world_bottom = world_center_y - S32(half_height / sMapScale) - 1; + S32 world_top = world_center_y + S32(half_height / sMapScale) + 1; + + //LL_INFOS("World Map") << "LLWorldMapView::updateVisibleBlocks() : sMapScale = " << sMapScale << ", left = " << world_left << ", right = " << world_right << ", bottom = " << world_bottom << ", top = " << world_top << LL_ENDL; + LLWorldMap::getInstance()->updateRegions(world_left, world_bottom, world_right, world_top); +} BOOL LLWorldMapView::handleHover( S32 x, S32 y, MASK mask ) { @@ -1915,16 +1746,16 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask ) } default: { - if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation) + if (LLWorldMap::getInstance()->isTracking()) { - LLWorldMap::getInstance()->mIsTrackingDoubleClick = TRUE; + LLWorldMap::getInstance()->setTrackingDoubleClick(); } else { // Teleport if we got a valid location LLVector3d pos_global = viewPosToGlobal(x,y); LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); - if (sim_info && sim_info->mAccess != SIM_ACCESS_DOWN) + if (sim_info && !sim_info->isDown()) { gAgent.teleportViaLocation( pos_global ); } diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index 66793f0101..9eecacb2d8 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -30,27 +30,23 @@ * $/LicenseInfo$ */ -// Global map of the world. +// View of the global map of the world + +// The data (model) for the global map (a singleton, unique to the application instance) is +// in LLWorldMap and is typically accessed using LLWorldMap::getInstance() #ifndef LL_LLWORLDMAPVIEW_H #define LL_LLWORLDMAPVIEW_H #include "llpanel.h" -#include "v3math.h" -#include "v3dmath.h" -#include "v4color.h" -#include "llviewertexture.h" -#include "llmapimagetype.h" #include "llworldmap.h" - -class LLItemInfo; +#include "v4color.h" const S32 DEFAULT_TRACKING_ARROW_SIZE = 16; -class LLColor4; -class LLColor4U; -class LLCoordGL; -class LLViewerTexture; +class LLUUID; +class LLVector3d; +class LLVector3; class LLTextBox; @@ -77,22 +73,26 @@ public: bool checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track); void handleClick(S32 x, S32 y, MASK mask, S32* hit_type, LLUUID* id); - // Scale and pan are shared across all instances. + // Scale and pan are shared across all instances! (i.e. Terrain and Objects maps are always registered) static void setScale( F32 scale ); static void translatePan( S32 delta_x, S32 delta_y ); static void setPan( S32 x, S32 y, BOOL snap = TRUE ); + // Return true if the current scale level is above the threshold for accessing region info + static bool showRegionInfo(); LLVector3 globalPosToView(const LLVector3d& global_pos); LLVector3d viewPosToGlobal(S32 x,S32 y); virtual void draw(); - void drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image); + void drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image); void drawGenericItem(const LLItemInfo& item, LLUIImagePtr image); void drawImage(const LLVector3d& global_pos, LLUIImagePtr image, const LLColor4& color = LLColor4::white); void drawImageStack(const LLVector3d& global_pos, LLUIImagePtr image, U32 count, F32 offset, const LLColor4& color); void drawAgents(); - void drawEvents(); + void drawItems(); void drawFrustum(); + void drawMipmap(S32 width, S32 height); + bool drawMipmapLevel(S32 width, S32 height, S32 level, bool load = true); static void cleanupTextures(); @@ -108,7 +108,7 @@ public: F32 y_pixels, const LLColor4& color, F32 relative_z = 0.f, - F32 dot_radius = 3.f); + F32 dot_radius = 5.f); static void drawTrackingCircle( const LLRect& rect, S32 x, S32 y, const LLColor4& color, @@ -129,9 +129,7 @@ public: static void clearLastClick() { sHandledLastClick = FALSE; } // if the view changes, download additional sim info as needed - // return value is number of blocks newly requested. - U32 updateBlock(S32 block_x, S32 block_y); - U32 updateVisibleBlocks(); + void updateVisibleBlocks(); protected: void setDirectionPos( LLTextBox* text_box, F32 rotation ); @@ -140,11 +138,13 @@ protected: public: LLColor4 mBackgroundColor; - static LLUIImagePtr sAvatarYouSmallImage; static LLUIImagePtr sAvatarSmallImage; - static LLUIImagePtr sAvatarLargeImage; + static LLUIImagePtr sAvatarYouImage; + static LLUIImagePtr sAvatarYouLargeImage; + static LLUIImagePtr sAvatarLevelImage; static LLUIImagePtr sAvatarAboveImage; static LLUIImagePtr sAvatarBelowImage; + static LLUIImagePtr sTelehubImage; static LLUIImagePtr sInfohubImage; static LLUIImagePtr sHomeImage; @@ -157,9 +157,7 @@ public: static LLUIImagePtr sForSaleImage; static LLUIImagePtr sForSaleAdultImage; - static F32 sThresholdA; - static F32 sThresholdB; - static F32 sPixelsPerMeter; // world meters to map pixels + static F32 sMapScale; // scale = size of a region in pixels BOOL mItemPicked; @@ -169,6 +167,7 @@ public: static F32 sTargetPanY; // in pixels static S32 sTrackingArrowX; static S32 sTrackingArrowY; + static bool sVisibleTilesLoaded; // Are we mid-pan from a user drag? BOOL mPanning; @@ -191,10 +190,14 @@ public: static BOOL sHandledLastClick; S32 mSelectIDStart; + // Keep the list of regions that are displayed on screen. Avoids iterating through the whole region map after draw(). typedef std::vector<U64> handle_list_t; handle_list_t mVisibleRegions; // set every frame static std::map<std::string,std::string> sStringsMap; + +private: + void drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right); }; #endif diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp new file mode 100644 index 0000000000..8d3165b98c --- /dev/null +++ b/indra/newview/llworldmipmap.cpp @@ -0,0 +1,275 @@ +/** + * @file llworldmipmap.cpp + * @brief Data storage for the S3 mipmap of the entire world. + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llworldmipmap.h" + +#include "llviewertexturelist.h" +#include "math.h" // log() + +// Turn this on to output tile stats in the standard output +#define DEBUG_TILES_STAT 0 + +LLWorldMipmap::LLWorldMipmap() : + mCurrentLevel(0) +{ +} + +LLWorldMipmap::~LLWorldMipmap() +{ + reset(); +} + +// Delete all sublevel maps and clean them +void LLWorldMipmap::reset() +{ + for (int level = 0; level < MAP_LEVELS; level++) + { + mWorldObjectsMipMap[level].clear(); + } +} + +// This method should be called before each use of the mipmap (typically, before each draw), so that to let +// the boost level of unused tiles to drop to 0 (BOOST_NONE). +// Tiles that are accessed have had their boost level pushed to BOOST_MAP_VISIBLE so we can identify them. +// The result of this strategy is that if a tile is not used during 2 consecutive loops, its boost level drops to 0. +void LLWorldMipmap::equalizeBoostLevels() +{ +#if DEBUG_TILES_STAT + S32 nb_missing = 0; + S32 nb_tiles = 0; + S32 nb_visible = 0; +#endif // DEBUG_TILES_STAT + // For each level + for (S32 level = 0; level < MAP_LEVELS; level++) + { + sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level]; + // For each tile + for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) + { + LLPointer<LLViewerFetchedTexture> img = iter->second; + S32 current_boost_level = img->getBoostLevel(); + if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE) + { + // If level was BOOST_MAP_VISIBLE, the tile has been used in the last draw so keep it high + img->setBoostLevel(LLViewerTexture::BOOST_MAP); + } + else + { + // If level was BOOST_MAP only (or anything else...), the tile wasn't used in the last draw + // so we drop its boost level to BOOST_NONE. + img->setBoostLevel(LLViewerTexture::BOOST_NONE); + } +#if DEBUG_TILES_STAT + // Increment some stats if compile option on + nb_tiles++; + if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE) + { + nb_visible++; + } + if (img->isMissingAsset()) + { + nb_missing++; + } +#endif // DEBUG_TILES_STAT + } + } +#if DEBUG_TILES_STAT + LL_INFOS("World Map") << "LLWorldMipmap tile stats : total requested = " << nb_tiles << ", visible = " << nb_visible << ", missing = " << nb_missing << LL_ENDL; +#endif // DEBUG_TILES_STAT +} + +// This method should be used when the mipmap is not actively used for a while, e.g., the map UI is hidden +void LLWorldMipmap::dropBoostLevels() +{ + // For each level + for (S32 level = 0; level < MAP_LEVELS; level++) + { + sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level]; + // For each tile + for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) + { + LLPointer<LLViewerFetchedTexture> img = iter->second; + img->setBoostLevel(LLViewerTexture::BOOST_NONE); + } + } +} + +LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load) +{ + // Check the input data + llassert(level <= MAP_LEVELS); + llassert(level >= 1); + + // If the *loading* level changed, cleared the new level from "missed" tiles + // so that we get a chance to reload them + if (load && (level != mCurrentLevel)) + { + cleanMissedTilesFromLevel(level); + mCurrentLevel = level; + } + + // Build the region handle + U64 handle = convertGridToHandle(grid_x, grid_y); + + // Check if the image is around already + sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level-1]; + sublevel_tiles_t::iterator found = level_mipmap.find(handle); + + // If not there and load on, go load it + if (found == level_mipmap.end()) + { + if (load) + { + // Load it + LLPointer<LLViewerFetchedTexture> img = loadObjectsTile(grid_x, grid_y, level); + // Insert the image in the map + level_mipmap.insert(sublevel_tiles_t::value_type( handle, img )); + // Find the element again in the map (it's there now...) + found = level_mipmap.find(handle); + } + else + { + // Return with NULL if not found and we're not trying to load + return NULL; + } + } + + // Get the image pointer and check if this asset is missing + LLPointer<LLViewerFetchedTexture> img = found->second; + if (img->isMissingAsset()) + { + // Return NULL if asset missing + return NULL; + } + else + { + // Boost the tile level so to mark it's in use *if* load on + if (load) + { + img->setBoostLevel(LLViewerTexture::BOOST_MAP_VISIBLE); + } + return img; + } +} + +LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level) +{ + // Get the grid coordinates +// std::string imageurl = llformat("http://map.secondlife.com.s3.amazonaws.com/%d/%05d/%05d/map-%d-%d-%d-objects.jpg", + std::string imageurl = llformat("http://map.secondlife.com.s3.amazonaws.com/map-%d-%d-%d-objects.jpg", + level, grid_x, grid_y, level, grid_x, grid_y); + + // DO NOT COMMIT!! DEBUG ONLY!!! + // Use a local jpeg for every tile to test map speed without S3 access + //imageurl = "file://C:\\Develop\\mapserver-distribute-3\\indra\\build-vc80\\mapserver\\relwithdebinfo\\regions\\00995\\01001\\region-995-1001-prims.jpg"; + // END DEBUG + //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; + + LLPointer<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE); + img->setBoostLevel(LLViewerTexture::BOOST_MAP); + + // Return the smart pointer + return img; +} + +// This method is used to clean up a level from tiles marked as "missing". +// The idea is to allow tiles that have been improperly marked missing to be reloaded when retraversing the level again. +// When zooming in and out rapidly, some tiles are never properly loaded and, eventually marked missing. +// This creates "blue" areas in a subresolution that never got a chance to reload if we don't clean up the level. +void LLWorldMipmap::cleanMissedTilesFromLevel(S32 level) +{ + // Check the input data + llassert(level <= MAP_LEVELS); + llassert(level >= 0); + + // This happens when the object is first initialized + if (level == 0) + { + return; + } + + // Iterate through the subresolution level and suppress the tiles that are marked as missing + // Note: erasing in a map while iterating through it is bug prone. Using a postfix increment is mandatory here. + sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level-1]; + sublevel_tiles_t::iterator it = level_mipmap.begin(); + while (it != level_mipmap.end()) + { + LLPointer<LLViewerFetchedTexture> img = it->second; + if (img->isMissingAsset()) + { + level_mipmap.erase(it++); + } + else + { + ++it; + } + } + return; +} + +// static methods +// Compute the level in the world mipmap (between 1 and MAP_LEVELS, as in the URL) given the scale (size of a sim in screen pixels) +S32 LLWorldMipmap::scaleToLevel(F32 scale) +{ + // If scale really small, picks up the higest level there is (lowest resolution) + if (scale <= F32_MIN) + return MAP_LEVELS; + // Compute the power of two resolution level knowing the base level + S32 level = llfloor((log(REGION_WIDTH_METERS/scale)/log(2.0f)) + 1.0f); + // Check bounds and return the value + if (level > MAP_LEVELS) + return MAP_LEVELS; + else if (level < 1) + return 1; + else + return level; +} + +// Convert world coordinates to mipmap grid coordinates at a given level (between 1 and MAP_LEVELS) +void LLWorldMipmap::globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y) +{ + // Check the input data + llassert(level <= MAP_LEVELS); + llassert(level >= 1); + + // Convert world coordinates into grid coordinates + *grid_x = lltrunc(global_x/REGION_WIDTH_METERS); + *grid_y = lltrunc(global_y/REGION_WIDTH_METERS); + // Compute the valid grid coordinates at that level of the mipmap + S32 regions_in_tile = 1 << (level - 1); + *grid_x = *grid_x - (*grid_x % regions_in_tile); + *grid_y = *grid_y - (*grid_y % regions_in_tile); +} + + diff --git a/indra/newview/llworldmipmap.h b/indra/newview/llworldmipmap.h new file mode 100644 index 0000000000..ecf1003468 --- /dev/null +++ b/indra/newview/llworldmipmap.h @@ -0,0 +1,100 @@ +/** + * @file llworldmipmap.h + * @brief Data storage for the S3 mipmap of the entire world. + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLWORLDMIPMAP_H +#define LL_LLWORLDMIPMAP_H + +#include <map> + +#include "llmemory.h" // LLPointer +#include "indra_constants.h" // REGION_WIDTH_UNITS +#include "llregionhandle.h" // to_region_handle() + +class LLViewerFetchedTexture; + +// LLWorldMipmap : Mipmap handling of all the tiles used to render the world at any resolution. +// This class provides a clean structured access to the hierarchy of tiles stored in the +// Amazon S3 repository and abstracts its directory/file structure. +// The interface of this class though still assumes that the caller knows the general level/tiles +// structure (at least, that it exists...) but doesn't requite the caller to know the details of it. +// IOW, you need to know that rendering levels exists as well as grid coordinates for regions, +// but you can ignore where those tiles are located, how to get them, etc... +// The class API gives you back LLPointer<LLViewerFetchedTexture> per tile. + +// See llworldmipmapview.cpp for the implementation of a class who knows how to render an LLWorldMipmap. + +// Implementation notes: +// - On the S3 servers, the tiles are rendered in 2 flavors: Objects and Terrain. +// - For the moment, LLWorldMipmap implements access only to the Objects tiles. +class LLWorldMipmap +{ +public: + // Parameters of the mipmap + static const S32 MAP_LEVELS = 8; // Number of subresolution levels computed by the mapserver + static const S32 MAP_TILE_SIZE = 256; // Width in pixels of the tiles computed by the mapserver + + LLWorldMipmap(); + ~LLWorldMipmap(); + + // Clear up the maps and release all image handles + void reset(); + // Manage the boost levels between loops (typically draw() loops) + void equalizeBoostLevels(); + // Drop the boost levels to none (used when hiding the map) + void dropBoostLevels(); + // Get the tile smart pointer, does the loading if necessary + LLPointer<LLViewerFetchedTexture> getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load = true); + + // Helper functions: those are here as they depend solely on the topology of the mipmap though they don't access it + // Convert sim scale (given in sim width in display pixels) into a mipmap level + static S32 scaleToLevel(F32 scale); + // Convert world coordinates to mipmap grid coordinates at a given level + static void globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y); + +private: + // Get a handle (key) from grid coordinates + U64 convertGridToHandle(U32 grid_x, U32 grid_y) { return to_region_handle(grid_x * REGION_WIDTH_UNITS, grid_y * REGION_WIDTH_UNITS); } + // Load the relevant tile from S3 + LLPointer<LLViewerFetchedTexture> loadObjectsTile(U32 grid_x, U32 grid_y, S32 level); + // Clear a level from its "missing" tiles + void cleanMissedTilesFromLevel(S32 level); + + // The mipmap is organized by resolution level (MAP_LEVELS of them). Each resolution level is an std::map + // using a region_handle as a key and storing a smart pointer to the image as a value. + typedef std::map<U64, LLPointer<LLViewerFetchedTexture> > sublevel_tiles_t; + sublevel_tiles_t mWorldObjectsMipMap[MAP_LEVELS]; +// sublevel_tiles_t mWorldTerrainMipMap[MAP_LEVELS]; + + S32 mCurrentLevel; // The level last accessed by a getObjectsTile() +}; + +#endif // LL_LLWORLDMIPMAP_H diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 0dc1a88ee8..2daaf77772 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1464,6 +1464,7 @@ F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera F32 dist = lookAt.length(); //ramp down distance for nearby objects + //shrink dist by dist/16. if (dist < 16.f) { dist /= 16.f; @@ -1474,7 +1475,7 @@ F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera //get area of circle around node F32 app_angle = atanf(size.length()/dist); F32 radius = app_angle*LLDrawable::sCurPixelAngle; - return radius*radius * 3.14159f; + return radius*radius * F_PI; } void LLPipeline::grabReferences(LLCullResult& result) @@ -3002,15 +3003,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO"); - //by bao - //fake vertex buffer updating - //to guaranttee at least updating one VBO buffer every frame - //to walk around the bug caused by ATI card --> DEV-3855 - // - if(forceVBOUpdate) - gSky.mVOSkyp->updateDummyVertexBuffer() ; - - // Initialize lots of GL state to "safe" values glMatrixMode(GL_TEXTURE); glLoadIdentity(); diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index 433070ce34..38291e45c9 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -134,8 +134,8 @@ TOOLMEDIAOPEN CURSOR "toolmediaopen.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,0,3256 - PRODUCTVERSION 2,0,0,3256 + FILEVERSION 2,0,0,200030 + PRODUCTVERSION 2,0,0,200030 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -152,12 +152,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "2.0.0.3256" + VALUE "FileVersion", "2.0.0.200030" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "2.0.0.3256" + VALUE "ProductVersion", "2.0.0.200030" END END BLOCK "VarFileInfo" diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 1e0da13162..572a4cf9e9 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -651,7 +651,7 @@ value="0 0 0 .33" /> <color name="TimeTextColor" - reference="LtGray_50" /> + reference="LtGray" /> <color name="TitleBarFocusColor" reference="White_10" /> diff --git a/indra/newview/skins/default/html/da/loading/loading.html b/indra/newview/skins/default/html/da/loading/loading.html index cdad5702b9..5f3426eb60 100644 --- a/indra/newview/skins/default/html/da/loading/loading.html +++ b/indra/newview/skins/default/html/da/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Indlæser...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Indlæser... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/de/loading/loading.html b/indra/newview/skins/default/html/de/loading/loading.html index 3eddbc24f5..44a621b216 100644 --- a/indra/newview/skins/default/html/de/loading/loading.html +++ b/indra/newview/skins/default/html/de/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Wird geladen...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Wird geladen... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/en-us/loading/loading.html b/indra/newview/skins/default/html/en-us/loading/loading.html index 34e5c84c4d..1c62d2f73e 100644 --- a/indra/newview/skins/default/html/en-us/loading/loading.html +++ b/indra/newview/skins/default/html/en-us/loading/loading.html @@ -1,9 +1,9 @@ -<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="sl_logo_rotate_black.gif" align="absmiddle"><br/> loading...
- </td>
- </tr>
-</table>
-</body>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="sl_logo_rotate_black.gif" align="absmiddle"><br/> loading... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/es/loading/loading.html b/indra/newview/skins/default/html/es/loading/loading.html index f03284ba8c..c4260b34c0 100644 --- a/indra/newview/skins/default/html/es/loading/loading.html +++ b/indra/newview/skins/default/html/es/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Cargando...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Cargando... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/fr/loading/loading.html b/indra/newview/skins/default/html/fr/loading/loading.html index 23c0ef03bc..b3953448e9 100644 --- a/indra/newview/skins/default/html/fr/loading/loading.html +++ b/indra/newview/skins/default/html/fr/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Chargement...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Chargement... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/hu/loading/loading.html b/indra/newview/skins/default/html/hu/loading/loading.html index ade91f76c2..ab15a073ba 100644 --- a/indra/newview/skins/default/html/hu/loading/loading.html +++ b/indra/newview/skins/default/html/hu/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Betöltés folyamatban...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Betöltés folyamatban... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/it/loading/loading.html b/indra/newview/skins/default/html/it/loading/loading.html index 0f9af31f6e..ab37e41f04 100644 --- a/indra/newview/skins/default/html/it/loading/loading.html +++ b/indra/newview/skins/default/html/it/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Attendi...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Attendi... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/ja/loading/loading.html b/indra/newview/skins/default/html/ja/loading/loading.html index 069dc5d12f..35cf74a35f 100644 --- a/indra/newview/skins/default/html/ja/loading/loading.html +++ b/indra/newview/skins/default/html/ja/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> ãƒãƒ¼ãƒ‰ä¸...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> ãƒãƒ¼ãƒ‰ä¸... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/nl/loading/loading.html b/indra/newview/skins/default/html/nl/loading/loading.html index 39a8691f3f..0215bd7e47 100644 --- a/indra/newview/skins/default/html/nl/loading/loading.html +++ b/indra/newview/skins/default/html/nl/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Laden...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Laden... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/pl/loading/loading.html b/indra/newview/skins/default/html/pl/loading/loading.html index 515890c2d5..50f3dfb0c5 100644 --- a/indra/newview/skins/default/html/pl/loading/loading.html +++ b/indra/newview/skins/default/html/pl/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Åadowanie...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Åadowanie... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/pt/loading/loading.html b/indra/newview/skins/default/html/pt/loading/loading.html index 635ea62406..a83e1123d0 100644 --- a/indra/newview/skins/default/html/pt/loading/loading.html +++ b/indra/newview/skins/default/html/pt/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Carregando...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Carregando... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/ru/loading/loading.html b/indra/newview/skins/default/html/ru/loading/loading.html index dcc0d73c1a..892c0b9f7f 100644 --- a/indra/newview/skins/default/html/ru/loading/loading.html +++ b/indra/newview/skins/default/html/ru/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Загрузка...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Загрузка... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/tr/loading/loading.html b/indra/newview/skins/default/html/tr/loading/loading.html index e7812e7c8e..1ac07bff34 100644 --- a/indra/newview/skins/default/html/tr/loading/loading.html +++ b/indra/newview/skins/default/html/tr/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Yükleniyor...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Yükleniyor... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/uk/loading/loading.html b/indra/newview/skins/default/html/uk/loading/loading.html index 0f67994635..3b5b8679b4 100644 --- a/indra/newview/skins/default/html/uk/loading/loading.html +++ b/indra/newview/skins/default/html/uk/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Завантаж...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> Завантаж... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/html/zh/loading/loading.html b/indra/newview/skins/default/html/zh/loading/loading.html index 462ea291d9..d1d5d25c92 100644 --- a/indra/newview/skins/default/html/zh/loading/loading.html +++ b/indra/newview/skins/default/html/zh/loading/loading.html @@ -1,10 +1,10 @@ -<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
-<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
-<table width="100%" height="100%" border="0">
- <tr>
- <td align="center" valign="middle" style="font-size:0.8em;">
- <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> 请ç‰å¾…...
- </td>
- </tr>
-</table>
-</body>
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> +<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;"> +<table width="100%" height="100%" border="0"> + <tr> + <td align="center" valign="middle" style="font-size:0.8em;"> + <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/> 请ç‰å¾…... + </td> + </tr> +</table> +</body> diff --git a/indra/newview/skins/default/textures/Blank.png b/indra/newview/skins/default/textures/Blank.png Binary files differnew file mode 100644 index 0000000000..f38e9f9100 --- /dev/null +++ b/indra/newview/skins/default/textures/Blank.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.png Binary files differnew file mode 100644 index 0000000000..3cfe2e850e --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.png Binary files differnew file mode 100644 index 0000000000..bb5d85e410 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.png Binary files differnew file mode 100644 index 0000000000..2b50986780 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.png Binary files differnew file mode 100644 index 0000000000..9876aa456c --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.png Binary files differnew file mode 100644 index 0000000000..f481fed88c --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.png Binary files differnew file mode 100644 index 0000000000..d58b4ff990 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.png Binary files differnew file mode 100644 index 0000000000..6e73898992 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png Binary files differnew file mode 100644 index 0000000000..98f1f04b9a --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png diff --git a/indra/newview/skins/default/textures/default_profile_picture.j2c b/indra/newview/skins/default/textures/default_profile_picture.j2c Binary files differindex c53a22e816..f21742cf09 100644 --- a/indra/newview/skins/default/textures/default_profile_picture.j2c +++ b/indra/newview/skins/default/textures/default_profile_picture.j2c diff --git a/indra/newview/skins/default/textures/icons/Inv_Alpha.png b/indra/newview/skins/default/textures/icons/Inv_Alpha.png Binary files differnew file mode 100644 index 0000000000..b65dc1929d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_Alpha.png diff --git a/indra/newview/skins/default/textures/icons/Inv_Tattoo.png b/indra/newview/skins/default/textures/icons/Inv_Tattoo.png Binary files differnew file mode 100644 index 0000000000..a632197eb5 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_Tattoo.png diff --git a/indra/newview/skins/default/textures/inv_folder_inbox.tga b/indra/newview/skins/default/textures/inv_folder_inbox.tga Binary files differnew file mode 100644 index 0000000000..04539c2cc4 --- /dev/null +++ b/indra/newview/skins/default/textures/inv_folder_inbox.tga diff --git a/indra/newview/skins/default/textures/map_avatar_32.tga b/indra/newview/skins/default/textures/map_avatar_32.tga Binary files differnew file mode 100644 index 0000000000..aebeab4093 --- /dev/null +++ b/indra/newview/skins/default/textures/map_avatar_32.tga diff --git a/indra/newview/skins/default/textures/map_avatar_above_32.tga b/indra/newview/skins/default/textures/map_avatar_above_32.tga Binary files differnew file mode 100644 index 0000000000..65bd0561a7 --- /dev/null +++ b/indra/newview/skins/default/textures/map_avatar_above_32.tga diff --git a/indra/newview/skins/default/textures/map_avatar_below_32.tga b/indra/newview/skins/default/textures/map_avatar_below_32.tga Binary files differnew file mode 100644 index 0000000000..496c44b369 --- /dev/null +++ b/indra/newview/skins/default/textures/map_avatar_below_32.tga diff --git a/indra/newview/skins/default/textures/map_avatar_you_32.tga b/indra/newview/skins/default/textures/map_avatar_you_32.tga Binary files differnew file mode 100644 index 0000000000..782207efd6 --- /dev/null +++ b/indra/newview/skins/default/textures/map_avatar_you_32.tga diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Link_Over.png b/indra/newview/skins/default/textures/navbar/Favorite_Link_Over.png Binary files differnew file mode 100644 index 0000000000..d4f126f969 --- /dev/null +++ b/indra/newview/skins/default/textures/navbar/Favorite_Link_Over.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index a75d38d967..fba8e0b06c 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -27,6 +27,8 @@ <texture name="BackArrow_Off" file_name="icons/BackArrow_Off.png" preload="false" /> <texture name="BackArrow_Press" file_name="icons/BackArrow_Press.png" preload="false" /> + <texture name="Blank" file_name="Blank.png" preload="false" /> + <texture name="BottomTray_BG" file_name="bottomtray/BottomTray_BG.png" preload="false" /> <texture name="BuyArrow_Off" file_name="navbar/BuyArrow_Off.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> @@ -49,6 +51,16 @@ <texture name="Cam_Pan_Off" file_name="bottomtray/Cam_Pan_Off.png" preload="false" /> <texture name="Cam_Pan_Over" file_name="bottomtray/CCam_Pan_Over.png" preload="false" /> <texture name="Cam_Pan_Press" file_name="bottomtray/Cam_Pan_Press.png" preload="false" /> + + <texture name="Cam_Preset_Back_Off" file_name="bottomtray/Cam_Preset_Back_Off.png" preload="false" /> + <texture name="Cam_Preset_Back_On" file_name="bottomtray/Cam_Preset_Back_On.png" preload="false" /> + <texture name="Cam_Preset_Eye_Off" file_name="bottomtray/Cam_Preset_Eye_Off.png" preload="false" /> + <texture name="Cam_Preset_Eye_On" file_name="bottomtray/Cam_Preset_Eye_On.png" preload="false" /> + <texture name="Cam_Preset_Front_Off" file_name="bottomtray/Cam_Preset_Front_Off.png" preload="false" /> + <texture name="Cam_Preset_Front_On" file_name="bottomtray/Cam_Preset_Front_On.png" preload="false" /> + <texture name="Cam_Preset_Side_Off" file_name="bottomtray/Cam_Preset_Side_Off.png" preload="false" /> + <texture name="Cam_Preset_Side_On" file_name="bottomtray/Cam_Preset_Side_On.png" preload="false" /> + <texture name="Cam_Rotate_In" file_name="bottomtray/Cam_Rotate_In.png" preload="false" /> <texture name="Cam_Rotate_Out" file_name="bottomtray/Cam_Rotate_Out.png" preload="false" /> <texture name="Cam_Tracking_In" file_name="bottomtray/Cam_Tracking_In.png" preload="false" /> @@ -67,7 +79,9 @@ <texture name="ComboButton_Over" file_name="widgets/ComboButton_Over.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="ComboButton_Press" file_name="widgets/ComboButton_Press.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="ComboButton_Selected" file_name="widgets/ComboButton_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> + <texture name="ComboButton_UpSelected" file_name="widgets/ComboButton_UpSelected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> + <texture name="ComboButton_UpOff" file_name="widgets/ComboButton_UpOff.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> <texture name="Container" file_name="containers/Container.png" preload="false" /> <texture name="DisclosureArrow_Closed_Off" file_name="widgets/DisclosureArrow_Closed_Off.png" preload="true" /> @@ -89,6 +103,7 @@ <texture name="Favorite_Star_Off" file_name="navbar/Favorite_Star_Off.png" preload="false" /> <texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" /> <texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" /> + <texture name="Favorite_Link_Over" file_name="navbar/Favorite_Link_Over.png" preload="false" /> <texture name="FileMenu_BarSelect" file_name="navbar/FileMenu_BarSelect.png" preload="false" scale.left="2" scale.top="0" scale.right="2" scale.bottom="0" /> <texture name="FileMenu_BG" file_name="navbar/FileMenu_BG.png" preload="false" /> @@ -233,6 +248,8 @@ <texture name="NearbyVoice_Lvl3" file_name="bottomtray/NearbyVoice_Lvl3.png" preload="false" /> <texture name="NearbyVoice_On" file_name="bottomtray/NearbyVoice_On.png" preload="false" /> + <texture name="Notices_Unread" file_name="bottomtray/Notices_Unread.png" preload="true" /> + <texture name="Object_Cone" file_name="build/Object_Cone.png" preload="false" /> <texture name="Object_Cube" file_name="build/Object_Cube.png" preload="false" /> <texture name="Object_Cylinder" file_name="build/Object_Cylinder.png" preload="false" /> @@ -396,6 +413,10 @@ <texture name="TabIcon_Home_Off" file_name="taskpanel/TabIcon_Home_Off.png" preload="false" /> <texture name="TabIcon_Home_Over" file_name="taskpanel/TabIcon_Home_Over.png" preload="false" /> <texture name="TabIcon_Home_Selected" file_name="taskpanel/TabIcon_Home_Selected.png" preload="false" /> + <texture name="TabIcon_Inventory_Large" file_name="taskpanel/TabIcon_Inventory_Large.png" preload="false" /> + <texture name="TabIcon_Inventory_Off" file_name="taskpanel/TabIcon_Inventory_Off.png" preload="false" /> + <texture name="TabIcon_Inventory_Over" file_name="taskpanel/TabIcon_Inventory_Over.png" preload="false" /> + <texture name="TabIcon_Inventory_Selected" file_name="taskpanel/TabIcon_Inventory_Selected.png" preload="false" /> <texture name="TabIcon_Me_Large" file_name="taskpanel/TabIcon_Me_Large.png" preload="false" /> <texture name="TabIcon_Me_Off" file_name="taskpanel/TabIcon_Me_Off.png" preload="false" /> <texture name="TabIcon_Me_Over" file_name="taskpanel/TabIcon_Me_Over.png" preload="false" /> @@ -488,9 +509,6 @@ <!--WARNING OLD ART *do not use*--> - <texture name="Banner_ForSale" file_name="Banner_ForSale.png" preload="false" /> - <texture name="Banner_YouAreHere" file_name="Banner_YouAreHere.png" preload="false" /> - <texture name="btn_chatbar.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" /> <texture name="btn_chatbar_selected.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" /> diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png b/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png Binary files differnew file mode 100644 index 0000000000..2330cb420b --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png b/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png Binary files differnew file mode 100644 index 0000000000..b7b5c2e1d4 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml index 81d4d3fdfd..f0c9c45d04 100644 --- a/indra/newview/skins/default/xui/da/floater_about.xml +++ b/indra/newview/skins/default/xui/da/floater_about.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_about" title="Om [APP_NAME]"> +<floater name="floater_about" title="OM [APP_NAME]"> <tab_container name="about_tab"> <panel name="credits_panel"> <text_editor name="credits_editor"> diff --git a/indra/newview/skins/default/xui/da/floater_about_land.xml b/indra/newview/skins/default/xui/da/floater_about_land.xml index c4cf722159..cb5d618dde 100644 --- a/indra/newview/skins/default/xui/da/floater_about_land.xml +++ b/indra/newview/skins/default/xui/da/floater_about_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterland" title="Om land"> +<floater name="floaterland" title="OM LAND"> <tab_container name="landtab"> <panel label="Generelt" name="land_general_panel"> <text name="Name:"> diff --git a/indra/newview/skins/default/xui/da/floater_auction.xml b/indra/newview/skins/default/xui/da/floater_auction.xml index f981242f8a..8f793557be 100644 --- a/indra/newview/skins/default/xui/da/floater_auction.xml +++ b/indra/newview/skins/default/xui/da/floater_auction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_auction" title="Start Linden land salg"> +<floater name="floater_auction" title="START LINDEN LAND SALG"> <check_box label="Vis ogsÃ¥ gul aftegning af omrÃ¥de" name="fence_check" /> <button label="Foto" label_selected="Foto" name="snapshot_btn" /> <button label="OK" label_selected="OK" name="ok_btn" /> diff --git a/indra/newview/skins/default/xui/da/floater_avatar_picker.xml b/indra/newview/skins/default/xui/da/floater_avatar_picker.xml index f93f0a3525..0ddb6e9dbe 100644 --- a/indra/newview/skins/default/xui/da/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/da/floater_avatar_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatarpicker" title="Vælg beboer"> +<floater name="avatarpicker" title="VÆLG BEBOER"> <tab_container name="ResidentChooserTabs"> <panel label="Søg" name="SearchPanel"> <text name="InstructSearchResidentName"> diff --git a/indra/newview/skins/default/xui/da/floater_avatar_textures.xml b/indra/newview/skins/default/xui/da/floater_avatar_textures.xml index e3a736b200..27bfa367f6 100644 --- a/indra/newview/skins/default/xui/da/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/da/floater_avatar_textures.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="avatar_texture_debug" title="Avatar teksturer"> +<floater name="avatar_texture_debug" title="AVATAR TEKSTURER"> <text name="baked_label"> Faste teksturer </text> diff --git a/indra/newview/skins/default/xui/da/floater_beacons.xml b/indra/newview/skins/default/xui/da/floater_beacons.xml index 318a23df4c..18bc7aeb31 100644 --- a/indra/newview/skins/default/xui/da/floater_beacons.xml +++ b/indra/newview/skins/default/xui/da/floater_beacons.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="beacons" title="Pejlelys"> +<floater name="beacons" title="PEJLELYS"> <panel name="beacons_panel"> <check_box label="Kun scriptede objekter med "rør"" name="touch_only" /> <check_box label="Scriptede objekter" name="scripted" /> diff --git a/indra/newview/skins/default/xui/da/floater_build_options.xml b/indra/newview/skins/default/xui/da/floater_build_options.xml index 3b3e14ad64..7eb0d4c035 100644 --- a/indra/newview/skins/default/xui/da/floater_build_options.xml +++ b/indra/newview/skins/default/xui/da/floater_build_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="build options floater" title="Gitter indstillinger"> +<floater name="build options floater" title="GITTER INDSTILLINGER"> <spinner label="Gitter enhed (meter)" name="GridResolution" width="200" label_width="136"/> <spinner label="Gitter rækkevidde (meter)" name="GridDrawSize" width="200" label_width="136"/> <check_box label="Aktiver lÃ¥sning til under-enheder" name="GridSubUnit" /> diff --git a/indra/newview/skins/default/xui/da/floater_bulk_perms.xml b/indra/newview/skins/default/xui/da/floater_bulk_perms.xml index 77ae7fe060..9cf44d6479 100644 --- a/indra/newview/skins/default/xui/da/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/da/floater_bulk_perms.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterbulkperms" title="Masse-ændring af rettigheder pÃ¥ indhold"> +<floater name="floaterbulkperms" title="MASSE-ÆNDRING AF RETTIGHEDER PÃ… INDHOLD"> <text name="applyto"> Indholdstyper </text> diff --git a/indra/newview/skins/default/xui/da/floater_bumps.xml b/indra/newview/skins/default/xui/da/floater_bumps.xml index 62a1cd9e5c..704e6c3608 100644 --- a/indra/newview/skins/default/xui/da/floater_bumps.xml +++ b/indra/newview/skins/default/xui/da/floater_bumps.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_bumps" title="Bump, skub & slag"> +<floater name="floater_bumps" title="BUMP, SKUB & SLAG"> <string name="none_detected"> Ingen registreret </string> diff --git a/indra/newview/skins/default/xui/da/floater_buy_contents.xml b/indra/newview/skins/default/xui/da/floater_buy_contents.xml index c9df548747..8dccf32304 100644 --- a/indra/newview/skins/default/xui/da/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/da/floater_buy_contents.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_buy_contents" title="Køb indhold"> +<floater name="floater_buy_contents" title="KØB INDHOLD"> <text name="contains_text"> [NAME] indeholder: </text> diff --git a/indra/newview/skins/default/xui/da/floater_buy_currency.xml b/indra/newview/skins/default/xui/da/floater_buy_currency.xml index 1c5876572b..a2b6dec91c 100644 --- a/indra/newview/skins/default/xui/da/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/da/floater_buy_currency.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="buy currency" title="Køb valuta"> +<floater name="buy currency" title="KØB VALUTA"> <text name="info_buying"> Køber valuta: </text> diff --git a/indra/newview/skins/default/xui/da/floater_buy_land.xml b/indra/newview/skins/default/xui/da/floater_buy_land.xml index 1d42ffb45a..71e6eaa7f7 100644 --- a/indra/newview/skins/default/xui/da/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/da/floater_buy_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy land" title="Køb land"> +<floater name="buy land" title="KØB LAND"> <text name="region_name_label"> Region: </text> diff --git a/indra/newview/skins/default/xui/da/floater_buy_object.xml b/indra/newview/skins/default/xui/da/floater_buy_object.xml index f0e22c8eee..266753902b 100644 --- a/indra/newview/skins/default/xui/da/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/da/floater_buy_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="contents" title="Køb kopi af objekt"> +<floater name="contents" title="KØB KOPI AF OBJEKT"> <text name="contents_text"> og dets indhold: </text> diff --git a/indra/newview/skins/default/xui/da/floater_choose_group.xml b/indra/newview/skins/default/xui/da/floater_choose_group.xml index 01c5bf3367..9f02f281db 100644 --- a/indra/newview/skins/default/xui/da/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/da/floater_choose_group.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="groups" title="Grupper"> +<floater name="groups" title="GRUPPER"> <text name="groupdesc"> Vælg en gruppe: </text> diff --git a/indra/newview/skins/default/xui/da/floater_color_picker.xml b/indra/newview/skins/default/xui/da/floater_color_picker.xml index c8e1fc813b..d0a47b76e0 100644 --- a/indra/newview/skins/default/xui/da/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/da/floater_color_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="ColorPicker" title="Farve vælger"> +<floater name="ColorPicker" title="FARVE VÆLGER"> <text name="r_val_text"> Rød: </text> diff --git a/indra/newview/skins/default/xui/da/floater_customize.xml b/indra/newview/skins/default/xui/da/floater_customize.xml index b434bea1ce..b2409f1682 100644 --- a/indra/newview/skins/default/xui/da/floater_customize.xml +++ b/indra/newview/skins/default/xui/da/floater_customize.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater customize" title="Appearance" width="509"> +<floater name="floater customize" title="APPEARANCE" width="509"> <tab_container name="customize tab container" width="507"> <placeholder label="Krops Dele" name="body_parts_placeholder"/> <panel label="Kropsbygning" name="Shape"> diff --git a/indra/newview/skins/default/xui/da/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/da/floater_day_cycle_options.xml index 0ca7874c37..94cf4546e3 100644 --- a/indra/newview/skins/default/xui/da/floater_day_cycle_options.xml +++ b/indra/newview/skins/default/xui/da/floater_day_cycle_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Day Cycle Floater" title="Dag cyklus opsætning"> +<floater name="Day Cycle Floater" title="DAG CYKLUS OPSÆTNING"> <tab_container name="Day Cycle Tabs"> <panel label="Dag cyklus" name="Day Cycle"> <button label="?" name="WLDayCycleHelp" /> diff --git a/indra/newview/skins/default/xui/da/floater_device_settings.xml b/indra/newview/skins/default/xui/da/floater_device_settings.xml index 28afd7c459..5e53a697f2 100644 --- a/indra/newview/skins/default/xui/da/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/da/floater_device_settings.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_device_settings" title="Stemme chat indstillinger" /> +<floater name="floater_device_settings" title="STEMME CHAT INDSTILLINGER" /> diff --git a/indra/newview/skins/default/xui/da/floater_env_settings.xml b/indra/newview/skins/default/xui/da/floater_env_settings.xml index 907771c67a..6c5b6d3b6b 100644 --- a/indra/newview/skins/default/xui/da/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/da/floater_env_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Environment Editor Floater" title="Redigering af omgivelser"> +<floater name="Environment Editor Floater" title="REDIGERING AF OMGIVELSER"> <text name="EnvTimeText"> Tid pÃ¥ dagen </text> diff --git a/indra/newview/skins/default/xui/da/floater_font_test.xml b/indra/newview/skins/default/xui/da/floater_font_test.xml index 7d8ef1b310..591d07188c 100644 --- a/indra/newview/skins/default/xui/da/floater_font_test.xml +++ b/indra/newview/skins/default/xui/da/floater_font_test.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Font test"> +<floater name="contents" title="FONT TEST"> <text name="linea"> OverrideTest, skal vises her som fonten 'Times'. (Fra default/xui/en-us) </text> diff --git a/indra/newview/skins/default/xui/da/floater_gesture.xml b/indra/newview/skins/default/xui/da/floater_gesture.xml index 800693ea8c..11ecc8bd9a 100644 --- a/indra/newview/skins/default/xui/da/floater_gesture.xml +++ b/indra/newview/skins/default/xui/da/floater_gesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="gestures" title="Aktive bevægelser"> +<floater name="gestures" title="AKTIVE BEVÆGELSER"> <text name="help_label"> Dobbelt-klik pÃ¥ en bevægelse for at afspille animation og lyd. </text> diff --git a/indra/newview/skins/default/xui/da/floater_hardware_settings.xml b/indra/newview/skins/default/xui/da/floater_hardware_settings.xml index dcc1b8d2e8..fc1231ceef 100644 --- a/indra/newview/skins/default/xui/da/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/da/floater_hardware_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Hardware Settings Floater" title="Hardware opsætning"> +<floater name="Hardware Settings Floater" title="HARDWARE OPSÆTNING"> <text name="Filtering:"> Filtrering: </text> diff --git a/indra/newview/skins/default/xui/da/floater_hud.xml b/indra/newview/skins/default/xui/da/floater_hud.xml index 0f11e2346d..18584e57ca 100644 --- a/indra/newview/skins/default/xui/da/floater_hud.xml +++ b/indra/newview/skins/default/xui/da/floater_hud.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_hud" title="Tutorial" /> +<floater name="floater_hud" title="TUTORIAL" /> diff --git a/indra/newview/skins/default/xui/da/floater_inspect.xml b/indra/newview/skins/default/xui/da/floater_inspect.xml index 56c3f6f784..0610e9408f 100644 --- a/indra/newview/skins/default/xui/da/floater_inspect.xml +++ b/indra/newview/skins/default/xui/da/floater_inspect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="inspect" title="Inspecér objekter"> +<floater name="inspect" title="INSPECÉR OBJEKTER"> <scroll_list name="object_list" tool_tip="Vælg et objekt fra listen for at markere det"> <column label="Objekt navn" name="object_name"/> <column label="Objekt ejer" name="owner_name"/> diff --git a/indra/newview/skins/default/xui/da/floater_inventory.xml b/indra/newview/skins/default/xui/da/floater_inventory.xml index 0b931bd7f4..8bfe7164d0 100644 --- a/indra/newview/skins/default/xui/da/floater_inventory.xml +++ b/indra/newview/skins/default/xui/da/floater_inventory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Inventory" title="Beholdning"> +<floater name="Inventory" title="BEHOLDNING"> <search_editor label="Skriv her for at søge" name="inventory search editor" /> <tab_container name="inventory filter tabs"> <inventory_panel label="Alle ting" name="All Items" /> diff --git a/indra/newview/skins/default/xui/da/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/da/floater_inventory_item_properties.xml index 9f28440fb0..fbcf202c54 100644 --- a/indra/newview/skins/default/xui/da/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/da/floater_inventory_item_properties.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="item properties" title="Egenskaber for Objekt i Beholdning"> +<floater name="item properties" title="EGENSKABER FOR OBJEKT I BEHOLDNING"> <text name="LabelItemNameTitle"> Navn: </text> diff --git a/indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml index 60a7d78aea..af2910fe58 100644 --- a/indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Inventory Finder" title="inventory_recent_items"> +<floater name="Inventory Finder" title="INVENTORY_RECENT_ITEMS"> <check_box label="Animation" name="check_animation" /> <check_box label="Visitkort" name="check_calling_card" /> <check_box label="Tøj" name="check_clothing" /> diff --git a/indra/newview/skins/default/xui/da/floater_joystick.xml b/indra/newview/skins/default/xui/da/floater_joystick.xml index 280650a04b..4954b7b619 100644 --- a/indra/newview/skins/default/xui/da/floater_joystick.xml +++ b/indra/newview/skins/default/xui/da/floater_joystick.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Joystick" title="Joystick opsætning"> +<floater name="Joystick" title="JOYSTICK OPSÆTNING"> <check_box name="enable_joystick" label="Aktiver Joystick:"/> <spinner label="X akse mapping" name="JoystickAxis1"/> <spinner label="Y akse mapping" name="JoystickAxis2"/> diff --git a/indra/newview/skins/default/xui/da/floater_lagmeter.xml b/indra/newview/skins/default/xui/da/floater_lagmeter.xml index 7e7c2dc0d3..bcf15ea926 100644 --- a/indra/newview/skins/default/xui/da/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/da/floater_lagmeter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="Lag mÃ¥ler"> +<floater name="floater_lagmeter" title="LAG MÃ…LER"> <button label="" label_selected="" name="client_lagmeter" tool_tip="Status for klient lag"/> <text name="client"> Klient: diff --git a/indra/newview/skins/default/xui/da/floater_land_holdings.xml b/indra/newview/skins/default/xui/da/floater_land_holdings.xml index bd623e7b75..39c906eb18 100644 --- a/indra/newview/skins/default/xui/da/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/da/floater_land_holdings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="land holdings floater" title="Mit land"> +<floater name="land holdings floater" title="MIT LAND"> <scroll_list name="parcel list"> <column label="Navn" name="name"/> <column label="Region" name="location"/> diff --git a/indra/newview/skins/default/xui/da/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/da/floater_live_lsleditor.xml index 112dc70e45..cfc5fb8860 100644 --- a/indra/newview/skins/default/xui/da/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/da/floater_live_lsleditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="Script: Nyt script"> +<floater name="script ed float" title="SCRIPT: NYT SCRIPT"> <button label="Nulstil" label_selected="Reset" name="Reset" /> <check_box label="Kører" name="running" /> <check_box label="Mono" name="mono" /> diff --git a/indra/newview/skins/default/xui/da/floater_lsl_guide.xml b/indra/newview/skins/default/xui/da/floater_lsl_guide.xml index d345409859..ebc86c5c73 100644 --- a/indra/newview/skins/default/xui/da/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/da/floater_lsl_guide.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="LSL Wiki"> +<floater name="script ed float" title="LSL WIKI"> <check_box label="Følg markøreren" name="lock_check" /> <combo_box label="LÃ¥s" name="history_combo" left_delta="114" width="70"/> <button label="Tilbage" name="back_btn" /> diff --git a/indra/newview/skins/default/xui/da/floater_media_browser.xml b/indra/newview/skins/default/xui/da/floater_media_browser.xml index 50004cfa0c..47667973ba 100644 --- a/indra/newview/skins/default/xui/da/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/da/floater_media_browser.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_about" title="Medie vælger"> +<floater name="floater_about" title="MEDIE VÆLGER"> <layout_stack name="stack1"> <layout_panel name="nav_controls"> <button label="Tilbage" name="back" /> diff --git a/indra/newview/skins/default/xui/da/floater_mem_leaking.xml b/indra/newview/skins/default/xui/da/floater_mem_leaking.xml index 6d5b5bc0ce..e7ad821d40 100644 --- a/indra/newview/skins/default/xui/da/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/da/floater_mem_leaking.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="MemLeak" title="Memory Leaking Simulation"> +<floater name="MemLeak" title="MEMORY LEAKING SIMULATION"> <spinner label="Leaking Speed (bytes per frame):" name="leak_speed" /> <spinner label="Max Leaked Memory (MB):" name="max_leak" /> <text name="total_leaked_label"> diff --git a/indra/newview/skins/default/xui/da/floater_mute_object.xml b/indra/newview/skins/default/xui/da/floater_mute_object.xml index e64557b177..4145918b49 100644 --- a/indra/newview/skins/default/xui/da/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/da/floater_mute_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="mute by name" title="Bloker objekt via navn"> +<floater name="mute by name" title="BLOKER OBJEKT VIA NAVN"> <text name="message"> Blokering via navn har ikke betydning for lyde. Du skal skrive det præcise navn pÃ¥ objektet. diff --git a/indra/newview/skins/default/xui/da/floater_my_friends.xml b/indra/newview/skins/default/xui/da/floater_my_friends.xml index 687266a08a..54b401076c 100644 --- a/indra/newview/skins/default/xui/da/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/da/floater_my_friends.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_my_friends" title="Kontakter"> +<floater name="floater_my_friends" title="KONTAKTER"> <tab_container name="friends_and_groups"> <panel label="Venner" name="friends_panel" /> <panel label="Grupper" name="groups_panel" /> diff --git a/indra/newview/skins/default/xui/da/floater_openobject.xml b/indra/newview/skins/default/xui/da/floater_openobject.xml index d37e3177fa..5875b7a967 100644 --- a/indra/newview/skins/default/xui/da/floater_openobject.xml +++ b/indra/newview/skins/default/xui/da/floater_openobject.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="objectcontents" title="Objekt indhold"> +<floater name="objectcontents" title="OBJEKT INDHOLD"> <text name="object_name"> [DESC]: </text> diff --git a/indra/newview/skins/default/xui/da/floater_perm_prefs.xml b/indra/newview/skins/default/xui/da/floater_perm_prefs.xml index f4b9b0a664..69a8d3af94 100644 --- a/indra/newview/skins/default/xui/da/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/da/floater_perm_prefs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="perm prefs" title="Standard tilladelser ved hentning"> +<floater name="perm prefs" title="STANDARD TILLADELSER VED HENTNING"> <panel label="Tilladelser" name="permissions"> <button label="?" label_selected="?" name="help"/> <check_box label="Del med gruppe" name="share_with_group"/> diff --git a/indra/newview/skins/default/xui/da/floater_postcard.xml b/indra/newview/skins/default/xui/da/floater_postcard.xml index 24d45062ae..cd61e7ac97 100644 --- a/indra/newview/skins/default/xui/da/floater_postcard.xml +++ b/indra/newview/skins/default/xui/da/floater_postcard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Postcard" title="E-mail billede"> +<floater name="Postcard" title="E-MAIL BILLEDE"> <text name="to_label"> Send til: </text> diff --git a/indra/newview/skins/default/xui/da/floater_preferences.xml b/indra/newview/skins/default/xui/da/floater_preferences.xml index 26e932e3cc..e251c9ad2c 100644 --- a/indra/newview/skins/default/xui/da/floater_preferences.xml +++ b/indra/newview/skins/default/xui/da/floater_preferences.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Preferences" title="Indstillinger"> +<floater name="Preferences" title="INDSTILLINGER"> <button label="OK" label_selected="OK" name="OK" /> <button label="Annullér" label_selected="Annullér" name="Cancel" /> <button label="Gem" label_selected="Gem" name="Apply" /> diff --git a/indra/newview/skins/default/xui/da/floater_preview_classified.xml b/indra/newview/skins/default/xui/da/floater_preview_classified.xml index 6cc4c139f1..cf2d14b80a 100644 --- a/indra/newview/skins/default/xui/da/floater_preview_classified.xml +++ b/indra/newview/skins/default/xui/da/floater_preview_classified.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="classified_preview" title="Annonce information" /> +<floater name="classified_preview" title="ANNONCE INFORMATION" /> diff --git a/indra/newview/skins/default/xui/da/floater_preview_event.xml b/indra/newview/skins/default/xui/da/floater_preview_event.xml index f1be35e1c3..584085fea0 100644 --- a/indra/newview/skins/default/xui/da/floater_preview_event.xml +++ b/indra/newview/skins/default/xui/da/floater_preview_event.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="event_preview" title="Event information" /> +<floater name="event_preview" title="EVENT INFORMATION" /> diff --git a/indra/newview/skins/default/xui/da/floater_preview_notecard.xml b/indra/newview/skins/default/xui/da/floater_preview_notecard.xml index 68d04d6f9b..7258824878 100644 --- a/indra/newview/skins/default/xui/da/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/da/floater_preview_notecard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="preview notecard" title="Note:"> +<floater name="preview notecard" title="NOTE:"> <button label="Gem" label_selected="Gem" name="Save"/> <text name="desc txt"> Beskrivelse: diff --git a/indra/newview/skins/default/xui/da/floater_region_info.xml b/indra/newview/skins/default/xui/da/floater_region_info.xml index 9f6e326cf3..5c95c8ed5e 100644 --- a/indra/newview/skins/default/xui/da/floater_region_info.xml +++ b/indra/newview/skins/default/xui/da/floater_region_info.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="regioninfo" title="Region/Estate" /> +<floater name="regioninfo" title="REGION/ESTATE" /> diff --git a/indra/newview/skins/default/xui/da/floater_report_abuse.xml b/indra/newview/skins/default/xui/da/floater_report_abuse.xml index 01f152c43a..6f1e2884eb 100644 --- a/indra/newview/skins/default/xui/da/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/da/floater_report_abuse.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_report_abuse" title="Rapportér misbrug"> +<floater name="floater_report_abuse" title="RAPPORTÉR MISBRUG"> <texture_picker label="" name="screenshot"/> <check_box label="Inkludér billede" name="screen_check"/> <text name="reporter_title"> diff --git a/indra/newview/skins/default/xui/da/floater_script_debug.xml b/indra/newview/skins/default/xui/da/floater_script_debug.xml index 17e14cd9b9..df60a2e23f 100644 --- a/indra/newview/skins/default/xui/da/floater_script_debug.xml +++ b/indra/newview/skins/default/xui/da/floater_script_debug.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <multi_floater name="script debug floater" title="Script advarsel/fejl"> <tab_container name="Preview Tabs"> - <floater label="Script" name="all_scripts" title="[All scripts]" /> + <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]" /> </tab_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/da/floater_script_preview.xml b/indra/newview/skins/default/xui/da/floater_script_preview.xml index 6990e8db0e..ede277bbd2 100644 --- a/indra/newview/skins/default/xui/da/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/da/floater_script_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="preview lsl text" title="Script: Rotation Script"> +<floater name="preview lsl text" title="SCRIPT: ROTATION SCRIPT"> <text name="desc txt"> Beskrivelse: </text> diff --git a/indra/newview/skins/default/xui/da/floater_script_queue.xml b/indra/newview/skins/default/xui/da/floater_script_queue.xml index 47dbf534bd..3f54c92426 100644 --- a/indra/newview/skins/default/xui/da/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/da/floater_script_queue.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="queue" title="Nulstil forløb"> +<floater name="queue" title="NULSTIL FORLØB"> <button label="Luk" label_selected="Luk" name="close" /> </floater> diff --git a/indra/newview/skins/default/xui/da/floater_script_search.xml b/indra/newview/skins/default/xui/da/floater_script_search.xml index d4dae8951f..62f311be6e 100644 --- a/indra/newview/skins/default/xui/da/floater_script_search.xml +++ b/indra/newview/skins/default/xui/da/floater_script_search.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script search" title="Script søgning"> +<floater name="script search" title="SCRIPT SØGNING"> <check_box label="Store/smÃ¥ bogstaver har ingen betydning" name="case_text" /> <button label="Søg" label_selected="Søg" name="search_btn" /> <button label="Erstat" label_selected="Erstat" name="replace_btn" /> diff --git a/indra/newview/skins/default/xui/da/floater_sell_land.xml b/indra/newview/skins/default/xui/da/floater_sell_land.xml index 87023b4f64..fcbe0abe08 100644 --- a/indra/newview/skins/default/xui/da/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/da/floater_sell_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="sell land" title="Sælg land"> +<floater name="sell land" title="SÆLG LAND"> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> <text name="info_parcel_label"> diff --git a/indra/newview/skins/default/xui/da/floater_settings_debug.xml b/indra/newview/skins/default/xui/da/floater_settings_debug.xml index 60f99deae2..c1429ed3a3 100644 --- a/indra/newview/skins/default/xui/da/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/da/floater_settings_debug.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="settings_debug" title="Tekniske indstillinger"> +<floater name="settings_debug" title="TEKNISKE INDSTILLINGER"> <combo_box name="boolean_combo"> <combo_box.item name="TRUE" label="TRUE (Valgt)" /> <combo_box.item name="FALSE" label="FALSE (Fravalgt)" /> diff --git a/indra/newview/skins/default/xui/da/floater_snapshot.xml b/indra/newview/skins/default/xui/da/floater_snapshot.xml index d7a5179890..3eed869db4 100644 --- a/indra/newview/skins/default/xui/da/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/da/floater_snapshot.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Snapshot" title="Se foto"> +<floater name="Snapshot" title="SE FOTO"> <text name="type_label"> Hvor skal foto hen? </text> diff --git a/indra/newview/skins/default/xui/da/floater_sound_preview.xml b/indra/newview/skins/default/xui/da/floater_sound_preview.xml index 606d290e1d..e54bdf4f42 100644 --- a/indra/newview/skins/default/xui/da/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/da/floater_sound_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Sound Preview" title="sound.wav"> +<floater name="Sound Preview" title="SOUND.WAV"> <text name="name_label"> Navn: </text> diff --git a/indra/newview/skins/default/xui/da/floater_statistics.xml b/indra/newview/skins/default/xui/da/floater_statistics.xml index 0443553d50..8c33f3ecb3 100644 --- a/indra/newview/skins/default/xui/da/floater_statistics.xml +++ b/indra/newview/skins/default/xui/da/floater_statistics.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="stats floater" title="Statistik"/> +<floater name="stats floater" title="STATISTIK"/> diff --git a/indra/newview/skins/default/xui/da/floater_telehub.xml b/indra/newview/skins/default/xui/da/floater_telehub.xml index cd1fb33831..bf31da9515 100644 --- a/indra/newview/skins/default/xui/da/floater_telehub.xml +++ b/indra/newview/skins/default/xui/da/floater_telehub.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="telehub" title="Telehub"> +<floater name="telehub" title="TELEHUB"> <text name="status_text_connected"> Telehub forbundet til objekt [OBJECT] </text> diff --git a/indra/newview/skins/default/xui/da/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/da/floater_texture_ctrl.xml index c35e3aec4c..4167e2938a 100644 --- a/indra/newview/skins/default/xui/da/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/da/floater_texture_ctrl.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="texture picker" title="Vælg: Tekstur"> +<floater name="texture picker" title="VÆLG: TEKSTUR"> <string name="choose_picture"> Klik for at vælge et billede </string> diff --git a/indra/newview/skins/default/xui/da/floater_tools.xml b/indra/newview/skins/default/xui/da/floater_tools.xml index e50494ff9e..c3287bac84 100644 --- a/indra/newview/skins/default/xui/da/floater_tools.xml +++ b/indra/newview/skins/default/xui/da/floater_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="toolbox floater" title="" short_title="Byg"> +<floater name="toolbox floater" title="" short_title="BYG"> <button label="" label_selected="" name="button focus" tool_tip="Fokus"/> <button label="" label_selected="" name="button move" tool_tip="Flyt"/> <button label="" label_selected="" name="button edit" tool_tip="Redigér"/> diff --git a/indra/newview/skins/default/xui/da/floater_top_objects.xml b/indra/newview/skins/default/xui/da/floater_top_objects.xml index dc4605cc12..0cfbe77def 100644 --- a/indra/newview/skins/default/xui/da/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/da/floater_top_objects.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="top_objects" title="Indlæser..."> +<floater name="top_objects" title="INDLÆSER..."> <text name="title_text"> Henter... </text> diff --git a/indra/newview/skins/default/xui/da/floater_water.xml b/indra/newview/skins/default/xui/da/floater_water.xml index 33a10579ab..63880b4a69 100644 --- a/indra/newview/skins/default/xui/da/floater_water.xml +++ b/indra/newview/skins/default/xui/da/floater_water.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Water Floater" title="Avanceret opsætning af vand"> +<floater name="Water Floater" title="AVANCERET OPSÆTNING AF VAND"> <text name="KeyFramePresetsText"> Vand opsætninger: </text> diff --git a/indra/newview/skins/default/xui/da/floater_windlight_options.xml b/indra/newview/skins/default/xui/da/floater_windlight_options.xml index 9754b1f074..4786609b53 100644 --- a/indra/newview/skins/default/xui/da/floater_windlight_options.xml +++ b/indra/newview/skins/default/xui/da/floater_windlight_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="WindLight floater" title="Avanceret opsætning for himmel"> +<floater name="WindLight floater" title="AVANCERET OPSÆTNING FOR HIMMEL"> <text name="KeyFramePresetsText"> Faste indstillinger: </text> diff --git a/indra/newview/skins/default/xui/da/floater_world_map.xml b/indra/newview/skins/default/xui/da/floater_world_map.xml index d4b58f6232..62930716ce 100644 --- a/indra/newview/skins/default/xui/da/floater_world_map.xml +++ b/indra/newview/skins/default/xui/da/floater_world_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="worldmap" title="Verdenskort"> +<floater name="worldmap" title="VERDENSKORT"> <tab_container name="maptab"> <panel label="Objekter" name="objects_mapview"/> <panel label="Terræn" name="terrain_mapview"/> diff --git a/indra/newview/skins/default/xui/da/panel_edit_profile.xml b/indra/newview/skins/default/xui/da/panel_edit_profile.xml index 74b7c7dd72..b4d0fa20ef 100644 --- a/indra/newview/skins/default/xui/da/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/da/panel_edit_profile.xml @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="edit_profile_panel">
- <string name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
- </string>
- <string name="AcctTypeResident"
- value="Beboer" />
- <string name="AcctTypeTrial"
- value="På prøve" />
- <string name="AcctTypeCharterMember"
- value="æresmedlem" />
- <string name="AcctTypeEmployee"
- value="Linden Lab medarbejder" />
- <string name="PaymentInfoUsed"
- value="Betalende medlem" />
- <string name="PaymentInfoOnFile"
- value="Registreret betalende" />
- <string name="NoPaymentInfoOnFile"
- value="Ingen betalingsinfo" />
- <string name="AgeVerified"
- value="Alders-checket" />
- <string name="NotAgeVerified"
- value="Ikke alders-checket" />
- <string name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=da
- </string>
- <panel name="scroll_content_panel">
- <panel name="data_panel" >
- <panel name="lifes_images_panel">
- <panel name="second_life_image_panel">
- <text name="second_life_photo_title_text">
- [SECOND_LIFE]:
- </text>
- </panel>
- </panel>
- <text name="title_partner_text" value="Partner:"/>
- <panel name="partner_data_panel">
- <text name="partner_text" value="[FIRST] [LAST]"/>
- </panel>
- <text name="text_box3">
- Optaget autosvar:
- </text>
- </panel>
- </panel>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="edit_profile_panel"> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string name="AcctTypeResident" + value="Beboer" /> + <string name="AcctTypeTrial" + value="På prøve" /> + <string name="AcctTypeCharterMember" + value="æresmedlem" /> + <string name="AcctTypeEmployee" + value="Linden Lab medarbejder" /> + <string name="PaymentInfoUsed" + value="Betalende medlem" /> + <string name="PaymentInfoOnFile" + value="Registreret betalende" /> + <string name="NoPaymentInfoOnFile" + value="Ingen betalingsinfo" /> + <string name="AgeVerified" + value="Alders-checket" /> + <string name="NotAgeVerified" + value="Ikke alders-checket" /> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=da + </string> + <panel name="scroll_content_panel"> + <panel name="data_panel" > + <panel name="lifes_images_panel"> + <panel name="second_life_image_panel"> + <text name="second_life_photo_title_text"> + [SECOND_LIFE]: + </text> + </panel> + </panel> + <text name="title_partner_text" value="Partner:"/> + <panel name="partner_data_panel"> + <text name="partner_text" value="[FIRST] [LAST]"/> + </panel> + <text name="text_box3"> + Optaget autosvar: + </text> + </panel> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml index d36f5a43f6..6e51fe3e2d 100644 --- a/indra/newview/skins/default/xui/de/floater_about.xml +++ b/indra/newview/skins/default/xui/de/floater_about.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_about" title="Über [APP_NAME]"> +<floater name="floater_about" title="ÜBER [APP_NAME]"> <tab_container name="about_tab"> <panel name="credits_panel"> <text_editor name="credits_editor"> diff --git a/indra/newview/skins/default/xui/de/floater_about_land.xml b/indra/newview/skins/default/xui/de/floater_about_land.xml index 853302d15c..ceb831c12d 100644 --- a/indra/newview/skins/default/xui/de/floater_about_land.xml +++ b/indra/newview/skins/default/xui/de/floater_about_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterland" title="Land-Info"> +<floater name="floaterland" title="LAND-INFO"> <tab_container name="landtab"> <panel label="Allgemein" name="land_general_panel"> <text name="Name:"> diff --git a/indra/newview/skins/default/xui/de/floater_auction.xml b/indra/newview/skins/default/xui/de/floater_auction.xml index 42f6a07dc3..9d0db766c9 100644 --- a/indra/newview/skins/default/xui/de/floater_auction.xml +++ b/indra/newview/skins/default/xui/de/floater_auction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_auction" title="Linden-Landverkauf starten"> +<floater name="floater_auction" title="LINDEN-LANDVERKAUF STARTEN"> <check_box label="Gelben Auswahlrahmen einschließen" name="fence_check" /> <button label="Foto" label_selected="Foto" name="snapshot_btn" /> <button label="OK" label_selected="OK" name="ok_btn" /> diff --git a/indra/newview/skins/default/xui/de/floater_avatar_picker.xml b/indra/newview/skins/default/xui/de/floater_avatar_picker.xml index c546d91d72..e1ea792694 100644 --- a/indra/newview/skins/default/xui/de/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/de/floater_avatar_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatarpicker" title="Einwohner auswählen"> +<floater name="avatarpicker" title="EINWOHNER AUSWÄHLEN"> <tab_container name="ResidentChooserTabs"> <panel label="Suchen" name="SearchPanel"> <text name="InstructSearchResidentName"> diff --git a/indra/newview/skins/default/xui/de/floater_avatar_textures.xml b/indra/newview/skins/default/xui/de/floater_avatar_textures.xml index 823d6de78b..3072735c66 100644 --- a/indra/newview/skins/default/xui/de/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/de/floater_avatar_textures.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatar_texture_debug" title="Avatar-Texturen"> +<floater name="avatar_texture_debug" title="AVATAR-TEXTUREN"> <text name="label"> Gebackene Texturen </text> diff --git a/indra/newview/skins/default/xui/de/floater_beacons.xml b/indra/newview/skins/default/xui/de/floater_beacons.xml index 0992727e73..58e2e2681f 100644 --- a/indra/newview/skins/default/xui/de/floater_beacons.xml +++ b/indra/newview/skins/default/xui/de/floater_beacons.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="beacons" title="Beacons"> +<floater name="beacons" title="BEACONS"> <panel name="beacons_panel"> <check_box label="Auf Berührung beschränkte Skriptobjekte" name="touch_only"/> <check_box label="Skripting-Objekte" name="scripted"/> diff --git a/indra/newview/skins/default/xui/de/floater_build_options.xml b/indra/newview/skins/default/xui/de/floater_build_options.xml index de3617ed25..58f117f6b1 100644 --- a/indra/newview/skins/default/xui/de/floater_build_options.xml +++ b/indra/newview/skins/default/xui/de/floater_build_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="build options floater" title="Rasteroptionen"> +<floater name="build options floater" title="RASTEROPTIONEN"> <spinner label="Rastereinheit (Meter)" name="GridResolution" /> <spinner label="Rastergröße (Meter)" name="GridDrawSize" /> <check_box label="Einrasten von Untereinheiten aktivieren" name="GridSubUnit" /> diff --git a/indra/newview/skins/default/xui/de/floater_bulk_perms.xml b/indra/newview/skins/default/xui/de/floater_bulk_perms.xml index f058a0ed96..fff6aa4b73 100644 --- a/indra/newview/skins/default/xui/de/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/de/floater_bulk_perms.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterbulkperms" title="Mehrere Inhaltsberechtigungen ändern"> +<floater name="floaterbulkperms" title="MEHRERE INHALTSBERECHTIGUNGEN ÄNDERN"> <text name="applyto"> Inhaltsarten </text> diff --git a/indra/newview/skins/default/xui/de/floater_bumps.xml b/indra/newview/skins/default/xui/de/floater_bumps.xml index 7b21042c2b..b7909bf02d 100644 --- a/indra/newview/skins/default/xui/de/floater_bumps.xml +++ b/indra/newview/skins/default/xui/de/floater_bumps.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_bumps" title="Rempler, Stöße und Schläge"> +<floater name="floater_bumps" title="REMPLER, STÖßE UND SCHLÄGE"> <text name="none_detected"> Nicht erkannt </text> diff --git a/indra/newview/skins/default/xui/de/floater_buy_contents.xml b/indra/newview/skins/default/xui/de/floater_buy_contents.xml index 01858b3c36..47ea6a1bd4 100644 --- a/indra/newview/skins/default/xui/de/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/de/floater_buy_contents.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_buy_contents" title="Inhalte kaufen" min_width="300"> +<floater name="floater_buy_contents" title="INHALTE KAUFEN" min_width="300"> <text name="contains_text"> [NAME] enthält: </text> diff --git a/indra/newview/skins/default/xui/de/floater_buy_currency.xml b/indra/newview/skins/default/xui/de/floater_buy_currency.xml index 787f469854..05750a1782 100644 --- a/indra/newview/skins/default/xui/de/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/de/floater_buy_currency.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="buy currency" title="Geld kaufen"> +<floater name="buy currency" title="GELD KAUFEN"> <text name="info_buying"> Kaufe Geld: </text> diff --git a/indra/newview/skins/default/xui/de/floater_buy_land.xml b/indra/newview/skins/default/xui/de/floater_buy_land.xml index e0abf8fae9..72a35db78c 100644 --- a/indra/newview/skins/default/xui/de/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/de/floater_buy_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy land" title="Land kaufen"> +<floater name="buy land" title="LAND KAUFEN"> <text name="region_name_label"> Region: </text> diff --git a/indra/newview/skins/default/xui/de/floater_buy_object.xml b/indra/newview/skins/default/xui/de/floater_buy_object.xml index 3cfa59ff06..df6bf76240 100644 --- a/indra/newview/skins/default/xui/de/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/de/floater_buy_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="contents" title="Objektkopie kaufen"> +<floater name="contents" title="OBJEKTKOPIE KAUFEN"> <text name="contents_text"> samt Inhalt: </text> diff --git a/indra/newview/skins/default/xui/de/floater_choose_group.xml b/indra/newview/skins/default/xui/de/floater_choose_group.xml index dd29aa7550..398645347b 100644 --- a/indra/newview/skins/default/xui/de/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/de/floater_choose_group.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="groups" title="Gruppen"> +<floater name="groups" title="GRUPPEN"> <text name="groupdesc"> Gruppe wählen: </text> diff --git a/indra/newview/skins/default/xui/de/floater_color_picker.xml b/indra/newview/skins/default/xui/de/floater_color_picker.xml index fa2f616249..47f256918a 100644 --- a/indra/newview/skins/default/xui/de/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/de/floater_color_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="ColorPicker" title="Farbauswahl"> +<floater name="ColorPicker" title="FARBAUSWAHL"> <text name="r_val_text"> Rot: </text> diff --git a/indra/newview/skins/default/xui/de/floater_customize.xml b/indra/newview/skins/default/xui/de/floater_customize.xml index 06b53dd8b4..f1ecd21c01 100644 --- a/indra/newview/skins/default/xui/de/floater_customize.xml +++ b/indra/newview/skins/default/xui/de/floater_customize.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater customize" title="Aussehen"> +<floater name="floater customize" title="AUSSEHEN"> <tab_container name="customize tab container"> <placeholder label="Körperteile" name="body_parts_placeholder"/> <panel label="Form" name="Shape"> diff --git a/indra/newview/skins/default/xui/de/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/de/floater_day_cycle_options.xml index d5a216a0b5..7f4dc4a79e 100644 --- a/indra/newview/skins/default/xui/de/floater_day_cycle_options.xml +++ b/indra/newview/skins/default/xui/de/floater_day_cycle_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Day Cycle Floater" title="Tageszyklus-Editor"> +<floater name="Day Cycle Floater" title="TAGESZYKLUS-EDITOR"> <tab_container name="Day Cycle Tabs"> <panel label="Tageszyklus" name="Day Cycle"> <button label=" ?" name="WLDayCycleHelp" /> diff --git a/indra/newview/skins/default/xui/de/floater_device_settings.xml b/indra/newview/skins/default/xui/de/floater_device_settings.xml index 734f4e942c..9108f3c2e5 100644 --- a/indra/newview/skins/default/xui/de/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/de/floater_device_settings.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_device_settings" title="Geräte-Einstellungen für Voice-Chat" /> +<floater name="floater_device_settings" title="GERÄTE-EINSTELLUNGEN FÜR VOICE-CHAT" /> diff --git a/indra/newview/skins/default/xui/de/floater_env_settings.xml b/indra/newview/skins/default/xui/de/floater_env_settings.xml index 3717ff6a48..c9afcc8471 100644 --- a/indra/newview/skins/default/xui/de/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/de/floater_env_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Environment Editor Floater" title="Umwelt-Editor"> +<floater name="Environment Editor Floater" title="UMWELT-EDITOR"> <text name="EnvTimeText"> Tageszeit </text> diff --git a/indra/newview/skins/default/xui/de/floater_font_test.xml b/indra/newview/skins/default/xui/de/floater_font_test.xml index 54278fc094..522d966431 100644 --- a/indra/newview/skins/default/xui/de/floater_font_test.xml +++ b/indra/newview/skins/default/xui/de/floater_font_test.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Schriftart-Test"> +<floater name="contents" title="SCHRIFTART-TEST"> <text name="linea"> OverrideTest, sollte hier als Times angezeigt werden. (Aus default/xui/en-us) </text> diff --git a/indra/newview/skins/default/xui/de/floater_gesture.xml b/indra/newview/skins/default/xui/de/floater_gesture.xml index bdee3b8664..aff0a9b92d 100644 --- a/indra/newview/skins/default/xui/de/floater_gesture.xml +++ b/indra/newview/skins/default/xui/de/floater_gesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="gestures" title="Aktive Gesten"> +<floater name="gestures" title="AKTIVE GESTEN"> <text name="help_label"> Doppelklicken Sie auf eine Geste, um Animationen und Sound abzuspielen. </text> diff --git a/indra/newview/skins/default/xui/de/floater_god_tools.xml b/indra/newview/skins/default/xui/de/floater_god_tools.xml index c7cfb5d9d3..f93a9b9476 100644 --- a/indra/newview/skins/default/xui/de/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/de/floater_god_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="godtools floater" title="Gott-Werkzeuge"> +<floater name="godtools floater" title="GOTT-WERKZEUGE"> <tab_container name="GodTools Tabs"> <panel label="Raster" name="grid"> <button label="Alle Benutzer hinauswerfen" label_selected="Alle Benutzer hinauswerfen" diff --git a/indra/newview/skins/default/xui/de/floater_hardware_settings.xml b/indra/newview/skins/default/xui/de/floater_hardware_settings.xml index 4051776b0d..68f7d6872e 100644 --- a/indra/newview/skins/default/xui/de/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/de/floater_hardware_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Hardware Settings Floater" title="Hardware-Einstellungen"> +<floater name="Hardware Settings Floater" title="HARDWARE-EINSTELLUNGEN"> <text name="Filtering:"> Filtern: </text> diff --git a/indra/newview/skins/default/xui/de/floater_hud.xml b/indra/newview/skins/default/xui/de/floater_hud.xml index 0f11e2346d..18584e57ca 100644 --- a/indra/newview/skins/default/xui/de/floater_hud.xml +++ b/indra/newview/skins/default/xui/de/floater_hud.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_hud" title="Tutorial" /> +<floater name="floater_hud" title="TUTORIAL" /> diff --git a/indra/newview/skins/default/xui/de/floater_inspect.xml b/indra/newview/skins/default/xui/de/floater_inspect.xml index f8c9b62824..f9421788bd 100644 --- a/indra/newview/skins/default/xui/de/floater_inspect.xml +++ b/indra/newview/skins/default/xui/de/floater_inspect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="inspect" title="Objekt prüfen" min_width="450" > +<floater name="inspect" title="OBJEKT PRÜFEN" min_width="450" > <scroll_list name="object_list" tool_tip="Wählen Sie ein Objekt aus dieser Liste, um es in der Second Life-Welt zu markieren"> <column label="Objektname" name="object_name" /> diff --git a/indra/newview/skins/default/xui/de/floater_inventory.xml b/indra/newview/skins/default/xui/de/floater_inventory.xml index c8c67240d8..6444e87882 100644 --- a/indra/newview/skins/default/xui/de/floater_inventory.xml +++ b/indra/newview/skins/default/xui/de/floater_inventory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Inventory" title="Inventar"> +<floater name="Inventory" title="INVENTAR"> <search_editor label="Suchanfrage hier eintippen" name="inventory search editor" /> <tab_container name="inventory filter tabs"> <inventory_panel label="Alle Objekte" name="All Items" /> diff --git a/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml index 3e79a31abd..ef85efdae0 100644 --- a/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="item properties" title="Inventarobjekt-Eigenschaften"> +<floater name="item properties" title="INVENTAROBJEKT-EIGENSCHAFTEN"> <text name="LabelItemNameTitle"> Name: </text> diff --git a/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml index 2f2eb5aa8d..8dfffe06d1 100644 --- a/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Inventory Finder" title="inventar_letzte_objekte"> +<floater name="Inventory Finder" title="INVENTAR_LETZTE_OBJEKTE"> <check_box label="Animation" name="check_animation" /> <check_box label="Visitenkarten" name="check_calling_card" /> <check_box label="Kleidung" name="check_clothing" /> diff --git a/indra/newview/skins/default/xui/de/floater_joystick.xml b/indra/newview/skins/default/xui/de/floater_joystick.xml index ccf6f14ead..9507d063d1 100644 --- a/indra/newview/skins/default/xui/de/floater_joystick.xml +++ b/indra/newview/skins/default/xui/de/floater_joystick.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Joystick" title="Joystick-Konfiguration"> +<floater name="Joystick" title="JOYSTICK-KONFIGURATION"> <check_box name="enable_joystick" width="80" label="Joystick aktivieren:"/> <text left="140" name="joystick_type" width="360"/> <spinner label="X-Achse" name="JoystickAxis1"/> diff --git a/indra/newview/skins/default/xui/de/floater_lagmeter.xml b/indra/newview/skins/default/xui/de/floater_lagmeter.xml index 4dd9fd6c76..9468557fc4 100644 --- a/indra/newview/skins/default/xui/de/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/de/floater_lagmeter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_lagmeter" title="Lag-Anzeige"> +<floater name="floater_lagmeter" title="LAG-ANZEIGE"> <button name="client_lagmeter" tool_tip="Client-Lag-Status" /> <text name="client"> Client: diff --git a/indra/newview/skins/default/xui/de/floater_land_holdings.xml b/indra/newview/skins/default/xui/de/floater_land_holdings.xml index 6854903382..3975211117 100644 --- a/indra/newview/skins/default/xui/de/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/de/floater_land_holdings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="land holdings floater" title="Mein Land"> +<floater name="land holdings floater" title="MEIN LAND"> <scroll_list name="parcel list"> <column label="Parzellenname" name="name"/> <column label="Region" name="location"/> diff --git a/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml index 8d499bc300..5afeb03395 100644 --- a/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="Skript: Neues Skript"> +<floater name="script ed float" title="SKRIPT: NEUES SKRIPT"> <button label="Zurücksetzen" label_selected="Zurücksetzen" name="Reset" /> <check_box label="Läuft" name="running" /> <check_box label="Mono" name="mono" /> diff --git a/indra/newview/skins/default/xui/de/floater_lsl_guide.xml b/indra/newview/skins/default/xui/de/floater_lsl_guide.xml index d7f56b302d..dd6d559c40 100644 --- a/indra/newview/skins/default/xui/de/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/de/floater_lsl_guide.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="LSL-Wiki"> +<floater name="script ed float" title="LSL-WIKI"> <check_box label="Cursor folgen" name="lock_check" /> <combo_box label="Sperren" name="history_combo" /> <button label="Zurück" name="back_btn" /> diff --git a/indra/newview/skins/default/xui/de/floater_media_browser.xml b/indra/newview/skins/default/xui/de/floater_media_browser.xml index ee2532127e..a16c2408fe 100644 --- a/indra/newview/skins/default/xui/de/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/de/floater_media_browser.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_about" title="Medienbrowser"> +<floater name="floater_about" title="MEDIENBROWSER"> <layout_stack name="stack1"> <layout_panel name="nav_controls"> <button label="Zurück" name="back" /> diff --git a/indra/newview/skins/default/xui/de/floater_mem_leaking.xml b/indra/newview/skins/default/xui/de/floater_mem_leaking.xml index 0b77a7fe9d..44249a6075 100644 --- a/indra/newview/skins/default/xui/de/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/de/floater_mem_leaking.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="MemLeak" title="Speicherverlust-Simulation"> +<floater name="MemLeak" title="SPEICHERVERLUST-SIMULATION"> <spinner label="Verlustgeschwindigkeit (Bytes pro Frame):" name="leak_speed" /> <spinner label="Max. Speicherverlust (MB):" name="max_leak" /> <text name="total_leaked_label"> diff --git a/indra/newview/skins/default/xui/de/floater_mute_object.xml b/indra/newview/skins/default/xui/de/floater_mute_object.xml index 60c6ff008c..8cc8a56523 100644 --- a/indra/newview/skins/default/xui/de/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/de/floater_mute_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="mute by name" title="Objekt nach Name stummschalten"> +<floater name="mute by name" title="OBJEKT NACH NAME STUMMSCHALTEN"> <text name="message"> Stummschalten nach Name betrifft nur Chat und IM, keine Sounds. Sie müssen den Objektnamen exakt angeben. diff --git a/indra/newview/skins/default/xui/de/floater_my_friends.xml b/indra/newview/skins/default/xui/de/floater_my_friends.xml index fc24bcece4..30614b7578 100644 --- a/indra/newview/skins/default/xui/de/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/de/floater_my_friends.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_my_friends" title="Kontakte"> +<floater name="floater_my_friends" title="KONTAKTE"> <tab_container name="friends_and_groups"> <panel label="Freunde" name="friends_panel" /> <panel label="Gruppen" name="groups_panel" /> diff --git a/indra/newview/skins/default/xui/de/floater_notification.xml b/indra/newview/skins/default/xui/de/floater_notification.xml index 48ff900d5a..48a26a0e98 100644 --- a/indra/newview/skins/default/xui/de/floater_notification.xml +++ b/indra/newview/skins/default/xui/de/floater_notification.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="notification" title="Konsole: Meldungen"> +<floater name="notification" title="KONSOLE: MELDUNGEN"> <text_editor name="payload"> Wird geladen... </text_editor> diff --git a/indra/newview/skins/default/xui/de/floater_notifications_console.xml b/indra/newview/skins/default/xui/de/floater_notifications_console.xml index a1cd69899c..0c075dd63a 100644 --- a/indra/newview/skins/default/xui/de/floater_notifications_console.xml +++ b/indra/newview/skins/default/xui/de/floater_notifications_console.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="notifications_console" title="Konsole: Meldungen"> +<floater name="notifications_console" title="KONSOLE: MELDUNGEN"> <combo_box label="Meldungsart auswählen" name="notification_types" width="412" /> <button label="Hinzufügen" name="add_notification" left="417" width="78" /> </floater> diff --git a/indra/newview/skins/default/xui/de/floater_openobject.xml b/indra/newview/skins/default/xui/de/floater_openobject.xml index fa465c08c7..d7575876e1 100644 --- a/indra/newview/skins/default/xui/de/floater_openobject.xml +++ b/indra/newview/skins/default/xui/de/floater_openobject.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="objectcontents" title="Objektinhalte"> +<floater name="objectcontents" title="OBJEKTINHALTE"> <text name="object_name"> [DESC]: </text> diff --git a/indra/newview/skins/default/xui/de/floater_perm_prefs.xml b/indra/newview/skins/default/xui/de/floater_perm_prefs.xml index 83ec725487..3641f41b8c 100644 --- a/indra/newview/skins/default/xui/de/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/de/floater_perm_prefs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="perm prefs" title="Hochlade-Berechtigungen (Standard)"> +<floater name="perm prefs" title="HOCHLADE-BERECHTIGUNGEN (STANDARD)"> <panel label="Berechtigungen" name="permissions"> <button label="?" label_selected="?" name="help"/> <check_box label="Mit Gruppe teilen" name="share_with_group"/> diff --git a/indra/newview/skins/default/xui/de/floater_post_process.xml b/indra/newview/skins/default/xui/de/floater_post_process.xml index e10806d255..a6ed8cc3df 100644 --- a/indra/newview/skins/default/xui/de/floater_post_process.xml +++ b/indra/newview/skins/default/xui/de/floater_post_process.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Post-Process Floater" title="Post-Processing-Einstellungen"> +<floater name="Post-Process Floater" title="POST-PROCESSING-EINSTELLUNGEN"> <tab_container name="Post-Process Tabs"> <panel label="Farbfilter" name="wmiColorFilterPanel"> <check_box label="Ein" name="wmiColorFilterToggle" /> diff --git a/indra/newview/skins/default/xui/de/floater_postcard.xml b/indra/newview/skins/default/xui/de/floater_postcard.xml index 2755704660..fc552339d3 100644 --- a/indra/newview/skins/default/xui/de/floater_postcard.xml +++ b/indra/newview/skins/default/xui/de/floater_postcard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Postcard" title="Foto per E-Mail senden"> +<floater name="Postcard" title="FOTO PER E-MAIL SENDEN"> <text name="to_label"> E-Mail des Empfängers: </text> diff --git a/indra/newview/skins/default/xui/de/floater_preferences.xml b/indra/newview/skins/default/xui/de/floater_preferences.xml index 5f68282b9f..02aa440be7 100644 --- a/indra/newview/skins/default/xui/de/floater_preferences.xml +++ b/indra/newview/skins/default/xui/de/floater_preferences.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Preferences" title="Einstellungen"> +<floater name="Preferences" title="EINSTELLUNGEN"> <button label="OK" label_selected="OK" name="OK" /> <button label="Abbrechen" label_selected="Abbrechen" name="Cancel" /> <button label="Übernehmen" label_selected="Übernehmen" name="Apply" /> diff --git a/indra/newview/skins/default/xui/de/floater_preview_classified.xml b/indra/newview/skins/default/xui/de/floater_preview_classified.xml index 2257785fda..be702145c3 100644 --- a/indra/newview/skins/default/xui/de/floater_preview_classified.xml +++ b/indra/newview/skins/default/xui/de/floater_preview_classified.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="classified_preview" title="Vertrauliche Informationen" /> +<floater name="classified_preview" title="VERTRAULICHE INFORMATIONEN" /> diff --git a/indra/newview/skins/default/xui/de/floater_preview_event.xml b/indra/newview/skins/default/xui/de/floater_preview_event.xml index 75e1113eff..21e8c67787 100644 --- a/indra/newview/skins/default/xui/de/floater_preview_event.xml +++ b/indra/newview/skins/default/xui/de/floater_preview_event.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="event_preview" title="Event-Informationen" /> +<floater name="event_preview" title="EVENT-INFORMATIONEN" /> diff --git a/indra/newview/skins/default/xui/de/floater_preview_notecard.xml b/indra/newview/skins/default/xui/de/floater_preview_notecard.xml index da90d66e4d..2c3258440f 100644 --- a/indra/newview/skins/default/xui/de/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/de/floater_preview_notecard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="preview notecard" title="Hinweis:"> +<floater name="preview notecard" title="HINWEIS:"> <button label="Speichern" label_selected="Speichern" name="Save" /> <text name="desc txt"> Beschreibung: diff --git a/indra/newview/skins/default/xui/de/floater_region_info.xml b/indra/newview/skins/default/xui/de/floater_region_info.xml index 4c28c7f5b0..e7dd09d4da 100644 --- a/indra/newview/skins/default/xui/de/floater_region_info.xml +++ b/indra/newview/skins/default/xui/de/floater_region_info.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="regioninfo" title="Region/Grundstück" /> +<floater name="regioninfo" title="REGION/GRUNDSTÜCK" /> diff --git a/indra/newview/skins/default/xui/de/floater_report_abuse.xml b/indra/newview/skins/default/xui/de/floater_report_abuse.xml index a8df587cfa..a5dd9fa4b1 100644 --- a/indra/newview/skins/default/xui/de/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/de/floater_report_abuse.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_report_abuse" title="Missbrauch melden"> +<floater name="floater_report_abuse" title="MISSBRAUCH MELDEN"> <texture_picker label="" name="screenshot"/> <check_box bottom_delta="-20" label="Screenshot einschließen" name="screen_check"/> <text name="reporter_title"> diff --git a/indra/newview/skins/default/xui/de/floater_script_debug.xml b/indra/newview/skins/default/xui/de/floater_script_debug.xml index f8c1543fdd..585a6c36ea 100644 --- a/indra/newview/skins/default/xui/de/floater_script_debug.xml +++ b/indra/newview/skins/default/xui/de/floater_script_debug.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <multi_floater name="script debug floater" title="Skriptwarnung/Fehler"> <tab_container name="Preview Tabs"> - <floater label="Skript" name="all_scripts" title="[All scripts]" /> + <floater label="Skript" name="all_scripts" title="[ALL SCRIPTS]" /> </tab_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/de/floater_script_preview.xml b/indra/newview/skins/default/xui/de/floater_script_preview.xml index 3ab5732055..be6017cff5 100644 --- a/indra/newview/skins/default/xui/de/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/de/floater_script_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="preview lsl text" title="Skript: Rotationsskript"> +<floater name="preview lsl text" title="SKRIPT: ROTATIONSSKRIPT"> <text name="desc txt"> Beschreibung: </text> diff --git a/indra/newview/skins/default/xui/de/floater_script_queue.xml b/indra/newview/skins/default/xui/de/floater_script_queue.xml index 63d5ef2478..b2011a4dfb 100644 --- a/indra/newview/skins/default/xui/de/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/de/floater_script_queue.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="queue" title="Rückgängig"> +<floater name="queue" title="RÜCKGÄNGIG"> <button label="Schließen" label_selected="Schließen" name="close" left="215" width="72"/> </floater> diff --git a/indra/newview/skins/default/xui/de/floater_script_search.xml b/indra/newview/skins/default/xui/de/floater_script_search.xml index bd93427456..aae302e230 100644 --- a/indra/newview/skins/default/xui/de/floater_script_search.xml +++ b/indra/newview/skins/default/xui/de/floater_script_search.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script search" title="Skriptsuche"> +<floater name="script search" title="SKRIPTSUCHE"> <check_box label="Groß-/Kleinschreibung irrelevant" name="case_text" /> <button label="Suchen" label_selected="Suchen" name="search_btn" /> <button label="Ersetzen" label_selected="Ersetzen" name="replace_btn" /> diff --git a/indra/newview/skins/default/xui/de/floater_sell_land.xml b/indra/newview/skins/default/xui/de/floater_sell_land.xml index 1499bb0152..47ab51d502 100644 --- a/indra/newview/skins/default/xui/de/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/de/floater_sell_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="sell land" title="Land verkaufen"> +<floater name="sell land" title="LAND VERKAUFEN"> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> <text name="info_parcel_label"> diff --git a/indra/newview/skins/default/xui/de/floater_settings_debug.xml b/indra/newview/skins/default/xui/de/floater_settings_debug.xml index 034cfca017..ea3295797d 100644 --- a/indra/newview/skins/default/xui/de/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/de/floater_settings_debug.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="settings_debug" title="Debug-Einstellungen"> +<floater name="settings_debug" title="DEBUG-EINSTELLUNGEN"> <combo_box name="boolean_combo"> <combo_box.item name="TRUE" label="WAHR" /> <combo_box.item name="FALSE" label="FALSCH" /> diff --git a/indra/newview/skins/default/xui/de/floater_snapshot.xml b/indra/newview/skins/default/xui/de/floater_snapshot.xml index bc8a1f42f1..64db511aa9 100644 --- a/indra/newview/skins/default/xui/de/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/de/floater_snapshot.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Snapshot" title="Foto-Vorschau"> +<floater name="Snapshot" title="FOTO-VORSCHAU"> <text name="type_label"> Zweck des Fotos </text> diff --git a/indra/newview/skins/default/xui/de/floater_sound_preview.xml b/indra/newview/skins/default/xui/de/floater_sound_preview.xml index 1e5ac179b5..14126b6a44 100644 --- a/indra/newview/skins/default/xui/de/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/de/floater_sound_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Sound Preview" title="sound.wav"> +<floater name="Sound Preview" title="SOUND.WAV"> <text name="name_label"> Name: </text> diff --git a/indra/newview/skins/default/xui/de/floater_statistics.xml b/indra/newview/skins/default/xui/de/floater_statistics.xml index 26e976a59c..506c18bd98 100644 --- a/indra/newview/skins/default/xui/de/floater_statistics.xml +++ b/indra/newview/skins/default/xui/de/floater_statistics.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="stats floater" title="Statistikleiste"/> +<floater name="stats floater" title="STATISTIKLEISTE"/> diff --git a/indra/newview/skins/default/xui/de/floater_telehub.xml b/indra/newview/skins/default/xui/de/floater_telehub.xml index 264411c166..2ba4e575a8 100644 --- a/indra/newview/skins/default/xui/de/floater_telehub.xml +++ b/indra/newview/skins/default/xui/de/floater_telehub.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="telehub" title="Telehub" min_height="310" height="310" > +<floater name="telehub" title="TELEHUB" min_height="310" height="310" > <text name="status_text_connected"> Telehub verbunden mit Objekt [OBJECT] </text> diff --git a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml index fff6ab5c74..7e2fc26fdf 100644 --- a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="texture picker" title="Auswählen: Textur"> +<floater name="texture picker" title="AUSWÄHLEN: TEXTUR"> <string name="choose_picture"> Zum Auswählen eines Bildes hier klicken </string> diff --git a/indra/newview/skins/default/xui/de/floater_tools.xml b/indra/newview/skins/default/xui/de/floater_tools.xml index 2815fd34a2..6bad64324b 100644 --- a/indra/newview/skins/default/xui/de/floater_tools.xml +++ b/indra/newview/skins/default/xui/de/floater_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="toolbox floater" title="" short_title="Bauen"> +<floater name="toolbox floater" title="" short_title="BAUEN"> <button label="" label_selected="" name="button focus" tool_tip="Fokus"/> <button label="" label_selected="" name="button move" tool_tip="Verschieben"/> <button label="" label_selected="" name="button edit" tool_tip="Bearbeiten"/> diff --git a/indra/newview/skins/default/xui/de/floater_top_objects.xml b/indra/newview/skins/default/xui/de/floater_top_objects.xml index f9e7becee1..082eb8894d 100644 --- a/indra/newview/skins/default/xui/de/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/de/floater_top_objects.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="top_objects" title="wird geladen..."> +<floater name="top_objects" title="WIRD GELADEN..."> <text name="title_text"> Wird geladen... </text> diff --git a/indra/newview/skins/default/xui/de/floater_water.xml b/indra/newview/skins/default/xui/de/floater_water.xml index 95b469434a..0880470c58 100644 --- a/indra/newview/skins/default/xui/de/floater_water.xml +++ b/indra/newview/skins/default/xui/de/floater_water.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Water Floater" title="Erweiterter Wasser-Editor"> +<floater name="Water Floater" title="ERWEITERTER WASSER-EDITOR"> <text name="KeyFramePresetsText"> Voreinstellungen: </text> diff --git a/indra/newview/skins/default/xui/de/floater_windlight_options.xml b/indra/newview/skins/default/xui/de/floater_windlight_options.xml index 8df412dab6..df0b513a85 100644 --- a/indra/newview/skins/default/xui/de/floater_windlight_options.xml +++ b/indra/newview/skins/default/xui/de/floater_windlight_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="WindLight floater" title="Erweiterter Himmel-Editor"> +<floater name="WindLight floater" title="ERWEITERTER HIMMEL-EDITOR"> <text name="KeyFramePresetsText"> Voreinstellungen: </text> diff --git a/indra/newview/skins/default/xui/de/floater_world_map.xml b/indra/newview/skins/default/xui/de/floater_world_map.xml index d3366e5871..665eafe5b8 100644 --- a/indra/newview/skins/default/xui/de/floater_world_map.xml +++ b/indra/newview/skins/default/xui/de/floater_world_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="worldmap" title="Weltkarte"> +<floater name="worldmap" title="WELTKARTE"> <tab_container name="maptab"> <panel label="Objekte" name="objects_mapview"/> <panel label="Terrain" name="terrain_mapview"/> diff --git a/indra/newview/skins/default/xui/de/panel_edit_profile.xml b/indra/newview/skins/default/xui/de/panel_edit_profile.xml index 1f67e0231d..3203eacdb5 100644 --- a/indra/newview/skins/default/xui/de/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/de/panel_edit_profile.xml @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="edit_profile_panel">
- <string name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
- </string>
- <string name="AcctTypeResident"
- value="Einwohner" />
- <string name="AcctTypeTrial"
- value="Test" />
- <string name="AcctTypeCharterMember"
- value="Charta-Mitglied" />
- <string name="AcctTypeEmployee"
- value="Linden Lab-Mitarbeiter" />
- <string name="PaymentInfoUsed"
- value="Zahlungsinfo verwendet" />
- <string name="PaymentInfoOnFile"
- value="Zahlungsinfo archiviert" />
- <string name="NoPaymentInfoOnFile"
- value="Keine Zahlungsinfo archiviert" />
- <string name="AgeVerified"
- value="Altersgeprüft" />
- <string name="NotAgeVerified"
- value="Nicht altersgeprüft" />
- <string name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=de
- </string>
- <panel name="scroll_content_panel">
- <panel name="data_panel" >
- <panel name="lifes_images_panel">
- <panel name="second_life_image_panel">
- <text name="second_life_photo_title_text">
- [SECOND_LIFE]:
- </text>
- </panel>
- </panel>
- <text name="title_partner_text" value="Partner:"/>
- <panel name="partner_data_panel">
- <text name="partner_text" value="[FIRST] [LAST]"/>
- </panel>
- <text name="text_box3">
- Antwort für Beschäftigt-Modus:
- </text>
- </panel>
- </panel>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="edit_profile_panel"> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string name="AcctTypeResident" + value="Einwohner" /> + <string name="AcctTypeTrial" + value="Test" /> + <string name="AcctTypeCharterMember" + value="Charta-Mitglied" /> + <string name="AcctTypeEmployee" + value="Linden Lab-Mitarbeiter" /> + <string name="PaymentInfoUsed" + value="Zahlungsinfo verwendet" /> + <string name="PaymentInfoOnFile" + value="Zahlungsinfo archiviert" /> + <string name="NoPaymentInfoOnFile" + value="Keine Zahlungsinfo archiviert" /> + <string name="AgeVerified" + value="Altersgeprüft" /> + <string name="NotAgeVerified" + value="Nicht altersgeprüft" /> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=de + </string> + <panel name="scroll_content_panel"> + <panel name="data_panel" > + <panel name="lifes_images_panel"> + <panel name="second_life_image_panel"> + <text name="second_life_photo_title_text"> + [SECOND_LIFE]: + </text> + </panel> + </panel> + <text name="title_partner_text" value="Partner:"/> + <panel name="partner_data_panel"> + <text name="partner_text" value="[FIRST] [LAST]"/> + </panel> + <text name="text_box3"> + Antwort für Beschäftigt-Modus: + </text> + </panel> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/favorites_bar_button.xml b/indra/newview/skins/default/xui/en/favorites_bar_button.xml index c35cbb1539..361f5a7bc8 100644 --- a/indra/newview/skins/default/xui/en/favorites_bar_button.xml +++ b/indra/newview/skins/default/xui/en/favorites_bar_button.xml @@ -9,10 +9,10 @@ image_disabled_selected="transparent.j2c" image_selected="transparent.j2c" image_unselected="transparent.j2c" - image_hover_selected="FileMenu_BarSelect" - image_hover_unselected="FileMenu_BarSelect" - image_pressed="FileMenu_BarSelect" - image_pressed_selected="FileMenu_BarSelect" + image_hover_selected="Favorite_Link_Over" + image_hover_unselected="Favorite_Link_Over" + image_pressed="Favorite_Link_Over" + image_pressed_selected="Favorite_Link_Over" hover_glow_amount="0.15" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 3789369e74..4d5268681b 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -7,7 +7,7 @@ help_topic="floater_aaa" save_rect="true" can_resize="true" - title="About [APP_NAME]" + title="ABOUT [APP_NAME]" width="470"> <text_editor follows="left|top|right|bottom" diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 3f2636ae52..2ff99dcf5a 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -6,7 +6,7 @@ name="floater_about" help_topic="floater_about" save_rect="true" - title="About [APP_NAME]" + title="ABOUT [APP_NAME]" width="470"> <floater.string name="AboutHeader"> @@ -69,7 +69,7 @@ Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number tab_position="top"> <panel border="true" - label="Support" + label="Info" help_topic="about_support_tab" name="support_panel"> <text_editor diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 033e18a139..615d1bf18d 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1,13 +1,12 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - legacy_header_height="18" can_tear_off="false" height="420" layout="topleft" name="floaterland" help_topic="floaterland" save_rect="true" - title="About Land" + title="ABOUT LAND" width="460"> <floater.string name="Minutes"> @@ -26,28 +25,24 @@ remaining </floater.string> <tab_container - follows="all" + follows="left|top|right|bottom" height="400" - halign="center" layout="topleft" - font="SansSerifSmall" left="1" - tab_padding_right="5" - tab_height="20" name="landtab" tab_position="top" top="20" width="459"> - <panel + <panel border="true" - follows="all" + follows="left|top|right|bottom" height="380" label="General" layout="topleft" left="1" help_topic="land_general_tab" name="land_general_panel" - top="0" + top="-31" width="458"> <panel.string name="new users only"> @@ -536,7 +531,7 @@ Go to World menu > About Land or select another parcel to show its details. </panel> <panel border="true" - follows="all" + follows="left|top|right|bottom" height="380" label="Covenant" layout="topleft" @@ -632,7 +627,7 @@ Go to World menu > About Land or select another parcel to show its details. length="1" enabled="false" follows="left|top|right|bottom" - handle_edit_keys_directly="true" + handle_edit_keys_directly="true" height="115" layout="topleft" left_delta="0" @@ -803,7 +798,7 @@ Go to World menu > About Land or select another parcel to show its details. </panel> <panel border="true" - follows="all" + follows="left|top|right|bottom" height="380" label="Objects" layout="topleft" @@ -854,7 +849,7 @@ Go to World menu > About Land or select another parcel to show its details. left_delta="152" name="objects_available" top_delta="0" - width="212"> + width="260"> [COUNT] out of [MAX] ([AVAILABLE] available) </text> <text @@ -875,7 +870,7 @@ Go to World menu > About Land or select another parcel to show its details. follows="left|top" height="16" layout="topleft" - left_delta="152" + left_delta="200" name="object_contrib_text" top_delta="0" width="212"> @@ -899,7 +894,7 @@ Go to World menu > About Land or select another parcel to show its details. follows="left|top" height="16" layout="topleft" - left_delta="152" + left_delta="200" name="total_objects_text" top_delta="0" width="48"> @@ -914,7 +909,7 @@ Go to World menu > About Land or select another parcel to show its details. left="28" name="Owned by parcel owner:" top="84" - width="128"> + width="176"> Owned by parcel owner: </text> <text @@ -923,7 +918,7 @@ Go to World menu > About Land or select another parcel to show its details. follows="left|top" height="16" layout="topleft" - left_delta="128" + left_delta="176" name="owner_objects_text" top_delta="0" width="48"> @@ -939,7 +934,7 @@ Go to World menu > About Land or select another parcel to show its details. label_selected="Show" layout="topleft" name="ShowOwner" - right="-190" + right="-140" width="60" /> <button bottom="100" @@ -951,7 +946,7 @@ Go to World menu > About Land or select another parcel to show its details. label_selected="Return..." layout="topleft" name="ReturnOwner..." - right="-60" + right="-10" tool_tip="Return objects to their owners." width="119" /> <text @@ -963,7 +958,7 @@ Go to World menu > About Land or select another parcel to show its details. left="28" name="Set to group:" top="104" - width="128"> + width="176"> Set to group: </text> <text @@ -972,7 +967,7 @@ Go to World menu > About Land or select another parcel to show its details. follows="left|top" height="16" layout="topleft" - left_delta="128" + left_delta="176" name="group_objects_text" top_delta="0" width="48"> @@ -988,7 +983,7 @@ Go to World menu > About Land or select another parcel to show its details. label_selected="Show" layout="topleft" name="ShowGroup" - right="-190" + right="-140" width="60" /> <button bottom="120" @@ -1000,7 +995,7 @@ Go to World menu > About Land or select another parcel to show its details. label_selected="Return..." layout="topleft" name="ReturnGroup..." - right="-60" + right="-10" tool_tip="Return objects to their owners." width="119" /> <text @@ -1012,7 +1007,7 @@ Go to World menu > About Land or select another parcel to show its details. left="28" name="Owned by others:" top="124" - width="128"> + width="176"> Owned by others: </text> <text @@ -1021,7 +1016,7 @@ Go to World menu > About Land or select another parcel to show its details. follows="left|top" height="16" layout="topleft" - left_delta="128" + left_delta="176" name="other_objects_text" top_delta="0" width="48"> @@ -1037,7 +1032,7 @@ Go to World menu > About Land or select another parcel to show its details. label_selected="Show" layout="topleft" name="ShowOther" - right="-190" + right="-140" width="60" /> <button bottom="140" @@ -1049,7 +1044,7 @@ Go to World menu > About Land or select another parcel to show its details. label_selected="Return..." layout="topleft" name="ReturnOther..." - right="-60" + right="-10" tool_tip="Return objects to their owners." width="119" /> <text @@ -1061,7 +1056,7 @@ Go to World menu > About Land or select another parcel to show its details. left="28" name="Selected / sat upon:" top="144" - width="128"> + width="176"> Selected / sat upon: </text> <text @@ -1070,7 +1065,7 @@ Go to World menu > About Land or select another parcel to show its details. follows="left|top" height="16" layout="topleft" - left_delta="128" + left_delta="176" name="selected_objects_text" top_delta="0" width="48"> @@ -1097,7 +1092,7 @@ Go to World menu > About Land or select another parcel to show its details. layout="topleft" max_length="6" name="clean other time" - right="-100" + right="-50" width="56" /> <text type="string" @@ -1169,7 +1164,7 @@ Go to World menu > About Land or select another parcel to show its details. </panel> <panel border="true" - follows="all" + follows="left|top|right|bottom" height="333" label="Options" layout="topleft" @@ -1595,15 +1590,16 @@ Only large parcels can be listed in search. value="Anywhere" /> </combo_box> </panel> - <panel + <panel border="true" - follows="all" + follows="left|top|right|bottom" height="363" label="Media" layout="topleft" left_delta="0" help_topic="land_media_tab" name="land_media_panel" + top_delta="1" width="458"> <text type="string" @@ -1614,22 +1610,24 @@ Only large parcels can be listed in search. left="10" name="with media:" top="9" - width="100"> + width="65"> Type: </text> <combo_box - height="20" + height="18" layout="topleft" - left_pad="10" + left_pad="5" name="media type" tool_tip="Specify if the URL is a movie, web page, or other media" - width="150" /> + top_delta="-2" + width="120" /> <text follows="left|top" height="16" layout="topleft" left_pad="10" name="mime_type" + top_delta="2" width="200" /> <text type="string" @@ -1639,30 +1637,32 @@ Only large parcels can be listed in search. layout="topleft" left="10" name="at URL:" - top_pad="10" - width="100"> + top="29" + width="65"> Home URL: </text> <line_editor + bottom_delta="0" follows="left|top" - height="20" + height="16" layout="topleft" - left_pad="10" + left="80" max_length="255" name="media_url" + right="-80" select_on_focus="true" - width="270" - /> + text_readonly_color="0.576471 0.662745 0.835294 1" /> <button follows="left|top" font="SansSerifSmall" - height="20" - label="Set" - label_selected="Set" + height="16" + label="Set..." + label_selected="Set..." layout="topleft" - left_pad="5" + left_pad="8" name="set_media_url" - width="50" /> + top_delta="0" + width="60" /> <text type="string" length="1" @@ -1671,34 +1671,37 @@ Only large parcels can be listed in search. layout="topleft" left="10" name="CurrentURL:" - top_pad="10" - width="100"> + top="49" + width="65"> Current URL: </text> <text follows="left|top" height="16" layout="topleft" - left_pad="10" + left_pad="5" name="current_url" - width="260">http://</text> + top_delta="0" + width="300" /> <button follows="left|top" - height="20" - label="Reset" - label_selected="Reset" + font="SansSerifSmall" + height="16" + label="Reset..." + label_selected="Reset..." layout="topleft" left_pad="6" name="reset_media_url" + top_delta="0" width="60" /> <check_box height="16" label="Hide URL" layout="topleft" - left="120" + left="100" name="hide_media_url" tool_tip="Checking this option will hide the media url to any non-authorized viewers of this parcel information. Note this is not available for HTML types." - top_pad="2" + top="89" width="200" /> <text type="string" @@ -1708,20 +1711,23 @@ Only large parcels can be listed in search. layout="topleft" left="10" name="Description:" - top_pad="10" - width="100"> + top="49" + width="364"> Description: </text> <line_editor + border_style="line" + border_thickness="1" + bottom_delta="0" follows="left|top" - height="35" + height="16" layout="topleft" + left="80" + max_length="255" name="url_description" - left_pad="10" + right="-80" select_on_focus="true" - tool_tip="Text displayed next to play/load button" - top_delta="0" - width="270" /> + tool_tip="Text displayed next to play/load button" /> <text type="string" length="1" @@ -1730,9 +1736,10 @@ Only large parcels can be listed in search. layout="topleft" left="10" name="Media texture:" - top_pad="10" - width="100"> - Replace Texture: + top="69" + width="364"> + Replace +Texture: </text> <texture_picker allow_no_texture="true" @@ -1740,7 +1747,7 @@ Only large parcels can be listed in search. follows="left|top" height="80" layout="topleft" - left_pad="10" + left_delta="70" name="media texture" tool_tip="Click to choose a picture" top_delta="0" @@ -1749,22 +1756,25 @@ Only large parcels can be listed in search. type="string" length="1" follows="left|top" - height="50" + height="16" layout="topleft" - left_pad="10" + left_delta="75" name="replace_texture_help" - top_delta="0" - word_wrap="true" - width="240"> - Objects using this texture will show the movie or web page after you click the play arrow. + top="85" + width="270"> + Objects using this texture will show the movie or + web page after you click the play arrow. + + Select the thumbnail to choose a different texture. </text> <check_box height="16" label="Auto scale" layout="topleft" + left_delta="70" name="media_auto_scale" tool_tip="Checking this option will scale the content for this parcel automatically. It may be slightly slower and lower quality visually but no other texture scaling or alignment will be required." - top_pad="3" + top_delta="0" width="200" /> <text type="string" @@ -1772,11 +1782,11 @@ Only large parcels can be listed in search. follows="left|top" height="16" layout="topleft" - left="10" - top_pad="10" + left="85" name="media_size" tool_tip="Size to render Web media, leave 0 for default." - width="100"> + top="185" + width="85"> Size: </text> <spinner @@ -1788,22 +1798,12 @@ Only large parcels can be listed in search. increment="1" initial_value="0" layout="topleft" - left_pad="10" + left_delta="65" max_val="1024" name="media_size_width" tool_tip="Size to render Web media, leave 0 for default." top_delta="0" width="64" /> - <text - type="string" - length="1" - follows="left|top" - height="16" - layout="topleft" - left_pad="5" - name="pixels"> - px wide - </text> <spinner decimal_digits="0" enabled="false" @@ -1813,21 +1813,23 @@ Only large parcels can be listed in search. increment="1" initial_value="0" layout="topleft" - left="120" - top_pad="3" + left_pad="16" max_val="1024" name="media_size_height" tool_tip="Size to render Web media, leave 0 for default." + top_delta="0" width="64" /> <text type="string" length="1" + bottom_delta="0" follows="left|top" height="16" layout="topleft" - left_pad="5" - name="pixels"> - px high + left_delta="70" + name="pixels" + right="-10"> + pixels </text> <text type="string" @@ -1837,15 +1839,15 @@ Only large parcels can be listed in search. layout="topleft" left="10" name="Options:" - top_pad="10" - width="100"> + top="237" + width="292"> Options: </text> <check_box height="16" label="Loop" layout="topleft" - left_pad="10" + left_delta="70" name="media_loop" tool_tip="Play media in a loop. When the media has finished playing, it will restart from the beginning." top_delta="0" @@ -1853,9 +1855,9 @@ Only large parcels can be listed in search. </panel> <panel border="true" - follows="all" + follows="left|top|right|bottom" height="363" - label="Sound" + label="Audio" layout="topleft" left_delta="0" help_topic="land_audio_tab" @@ -1947,7 +1949,7 @@ Only large parcels can be listed in search. </panel> <panel border="true" - follows="all" + follows="left|top|right|bottom" height="333" label="Access" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_activeim.xml b/indra/newview/skins/default/xui/en/floater_activeim.xml index 1bc9cde044..96fe0aa70c 100644 --- a/indra/newview/skins/default/xui/en/floater_activeim.xml +++ b/indra/newview/skins/default/xui/en/floater_activeim.xml @@ -30,4 +30,4 @@ name="chiclet_row_panel_list" width="318"/> </scroll_container> -</floater>
\ No newline at end of file +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_animation_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_preview.xml index ab3d5722f0..ebce758d3d 100644 --- a/indra/newview/skins/default/xui/en/floater_animation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_animation_preview.xml @@ -455,7 +455,6 @@ Maximum animation length is [MAX_LENGTH] seconds. layout="topleft" left="10" name="play_btn" - picture_style="true" tool_tip="Play/pause your animation" top_pad="0" width="28" /> @@ -467,7 +466,6 @@ Maximum animation length is [MAX_LENGTH] seconds. layout="topleft" left_pad="4" name="stop_btn" - picture_style="true" tool_tip="Stop animation playback" top_delta="0" width="28" /> diff --git a/indra/newview/skins/default/xui/en/floater_auction.xml b/indra/newview/skins/default/xui/en/floater_auction.xml index aae6508041..9c6d114c4c 100644 --- a/indra/newview/skins/default/xui/en/floater_auction.xml +++ b/indra/newview/skins/default/xui/en/floater_auction.xml @@ -8,7 +8,7 @@ min_width="420" name="floater_auction" help_topic="floater_auction" - title="Start Linden Land Sale" + title="START LINDEN LAND SALE" width="420"> <floater.string name="already for sale"> diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml index 1fd9b95318..a0f9bb59fd 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml @@ -8,7 +8,7 @@ min_width="265" name="avatarpicker" help_topic="avatarpicker" - title="Choose Resident" + title="CHOOSE RESIDENT" width="265"> <floater.string name="not_found"> @@ -116,7 +116,6 @@ height="20" width="20" name="RefreshFriends" - picture_style="true" image_overlay="Refresh_Off"> <button.commit_callback function="Refresh.FriendList"/> @@ -188,7 +187,6 @@ height="28" width="28" name="Refresh" - picture_style="true" image_overlay="Refresh_Off" /> <scroll_list follows="all" diff --git a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml index 4f2a36e518..a0cb94eb69 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml @@ -5,7 +5,7 @@ layout="topleft" name="avatar_texture_debug" help_topic="avatar_texture_debug" - title="Avatar Textures" + title="AVATAR TEXTURES" width="1250"> <floater.string name="InvalidAvatar"> diff --git a/indra/newview/skins/default/xui/en/floater_beacons.xml b/indra/newview/skins/default/xui/en/floater_beacons.xml index 1c83799e72..c8f6c613af 100644 --- a/indra/newview/skins/default/xui/en/floater_beacons.xml +++ b/indra/newview/skins/default/xui/en/floater_beacons.xml @@ -8,7 +8,7 @@ save_rect="true" save_visibility="true" single_instance="true" - title="Beacons" + title="BEACONS" width="240"> <panel follows="left|top|right|bottom" diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml index bddbbdd3b2..f0e678af00 100644 --- a/indra/newview/skins/default/xui/en/floater_build_options.xml +++ b/indra/newview/skins/default/xui/en/floater_build_options.xml @@ -7,7 +7,7 @@ name="build options floater" help_topic="build_options_floater" save_rect="true" - title="Grid Options" + title="GRID OPTIONS" width="264"> <spinner control_name="GridResolution" diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml index 02958bee74..7ae079f553 100644 --- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml @@ -6,7 +6,7 @@ layout="topleft" name="floaterbulkperms" help_topic="floaterbulkperms" - title="Edit Content Permissions" + title="EDIT CONTENT PERMISSIONS" width="270"> <floater.string name="nothing_to_modify_text"> diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml index 2917096f3c..303c28d7c8 100644 --- a/indra/newview/skins/default/xui/en/floater_bumps.xml +++ b/indra/newview/skins/default/xui/en/floater_bumps.xml @@ -6,7 +6,7 @@ name="floater_bumps" help_topic="floater_bumps" save_rect="true" - title="Bumps, Pushes & Hits" + title="BUMPS, PUSHES & HITS" width="400"> <floater.string name="none_detected"> diff --git a/indra/newview/skins/default/xui/en/floater_buy_contents.xml b/indra/newview/skins/default/xui/en/floater_buy_contents.xml index aacc3ad8d0..833e8beb8d 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_contents.xml @@ -9,7 +9,7 @@ name="floater_buy_contents" help_topic="floater_buy_contents" save_rect="true" - title="Buy Contents" + title="BUY CONTENTS" width="280"> <floater.string name="no_copy_text"> diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml index 88712bda5e..75711cdf89 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml @@ -4,7 +4,7 @@ can_minimize="false" height="275" layout="topleft" - title="Buy L$" + title="BUY L$" name="buy currency" help_topic="buy_linden_dollars" single_instance="true" diff --git a/indra/newview/skins/default/xui/en/floater_buy_land.xml b/indra/newview/skins/default/xui/en/floater_buy_land.xml index 8314549132..6e0c3dfe54 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml @@ -7,7 +7,7 @@ name="buy land" help_topic="buy_land" single_instance="true" - title="Buy Land" + title="BUY LAND" width="740"> <floater.string name="can_resell"> @@ -115,7 +115,7 @@ Try selecting a smaller area. </floater.string> <floater.string name="buy_for_US"> - Buy L$ [AMOUNT] for approx. US$ [AMOUNT2], + Buy L$ [AMOUNT] for approx. [LOCAL_AMOUNT], </floater.string> <floater.string name="parcel_meters"> @@ -172,10 +172,6 @@ supports [AMOUNT2] objects name="no_parcel_selected"> (no parcel selected) </floater.string> - <floater.string - name="buy_currency"> - Buy L$ [LINDENS] for approx. US$ [USD] - </floater.string> <text type="string" length="1" @@ -667,7 +663,7 @@ This parcel is 512 m² of land. name="currency_est" top="409" width="178"> - for approx. US$ [AMOUNT2] + for approx. [LOCAL_AMOUNT] </text> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml index 49ea3f5dd1..f0e5e30010 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml @@ -10,7 +10,7 @@ help_topic="contents" save_rect="true" single_instance="true" - title="Buy Copy of Object" + title="BUY COPY OF OBJECT" width="280"> <floater.string name="title_buy_text"> diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 1b69418013..5c09bc3a02 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -34,7 +34,7 @@ mouse_opaque="false" name="controls" width="148"> - <joystick_track + <joystick_track follows="top|left" height="78" image_selected="Cam_Tracking_In" @@ -42,7 +42,6 @@ layout="topleft" left="45" name="cam_track_stick" - picture_style="true" quadrant="left" scale_image="false" sound_flags="3" @@ -51,7 +50,7 @@ visible="false" width="78" /> <!--TODO: replace with slider, + - images --> - <joystick_zoom + <joystick_zoom follows="top|left" height="78" image_unselected="ScrollThumb_Vert" @@ -59,7 +58,6 @@ left="7" minus_image="ScrollThumb_Vert" name="zoom" - picture_style="true" plus_image="ScrollThumb_Vert" quadrant="left" scale_image="false" @@ -75,7 +73,6 @@ layout="topleft" left="45" name="cam_rotate_stick" - picture_style="true" quadrant="left" scale_image="false" sound_flags="3" @@ -83,70 +80,65 @@ tool_tip="Orbit camera around focus" top="22" width="78" /> - <panel + <panel height="78" layout="topleft" left="36" name="camera_presets" - top="30" + top="20" visible="false" width="78"> <button - height="30" - image_selected="CameraPreset_Rear" - image_unselected="CameraPreset_Rear" + height="40" + image_selected="Cam_Preset_Back_On" + image_unselected="Cam_Preset_Back_Off" layout="topleft" - left="5" + left="0" name="rear_view" - picture_style="true" tool_tip="Rear View" top="2" - width="30"> + width="40"> <click_callback function="CameraPresets.ChangeView" parameter="rear_view" /> </button> <button - height="30" - image_selected="CameraPreset_3_4" - image_unselected="CameraPreset_3_4" + height="40" + image_selected="Cam_Preset_Side_On" + image_unselected="Cam_Preset_Side_Off" layout="topleft" left_pad="5" name="group_view" - picture_style="true" tool_tip="Group View" top="2" - width="30"> + width="40"> <click_callback function="CameraPresets.ChangeView" parameter="group_view" /> </button> <button - height="30" - image_selected="CameraPreset_Front" - image_unselected="CameraPreset_Front" + height="40" + image_selected="Cam_Preset_Front_On" + image_unselected="Cam_Preset_Front_Off" layout="topleft" - left="5" + left="0" name="front_view" - picture_style="true" tool_tip="Front View" top_pad="5" - width="30"> + width="40"> <click_callback function="CameraPresets.ChangeView" parameter="front_view" /> </button> <button - height="30" - image_selected="CameraPreset_Mouselook" - image_unselected="CameraPreset_Mouselook" + height="40" + image_selected="Cam_Preset_Eye_Off" + image_unselected="Cam_Preset_Eye_Off" layout="topleft" left_pad="5" name="mouselook_view" - picture_style="true" tool_tip="Mouselook View" - top_pad="-30" - width="30"> + width="40"> <click_callback function="CameraPresets.ChangeView" parameter="mouselook_view" /> @@ -172,7 +164,6 @@ name="orbit_btn" tab_stop="false" tool_tip="Orbit camera" - value="true" width="25"> </button> <button diff --git a/indra/newview/skins/default/xui/en/floater_choose_group.xml b/indra/newview/skins/default/xui/en/floater_choose_group.xml index 8b34fda96c..dc1ee5f24e 100644 --- a/indra/newview/skins/default/xui/en/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/en/floater_choose_group.xml @@ -5,7 +5,7 @@ layout="topleft" name="groups" help_topic="groups" - title="Groups" + title="GROUPS" width="280"> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_color_picker.xml b/indra/newview/skins/default/xui/en/floater_color_picker.xml index 686b8dc40f..4380ff8f4b 100644 --- a/indra/newview/skins/default/xui/en/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_color_picker.xml @@ -7,7 +7,7 @@ layout="topleft" name="ColorPicker" help_topic="colorpicker" - title="Color Picker" + title="COLOR PICKER" width="440"> <text type="string" @@ -168,27 +168,29 @@ <check_box follows="left|bottom" height="20" - label="Apply Now" + label="Apply now" layout="topleft" left="12" name="apply_immediate" top_pad="185" width="100" /> - <button - follows="left|top" - height="32" + <button + follows="left|bottom" + height="28" + image_selected="eye_button_active.tga" + image_unselected="eye_button_inactive.tga" layout="topleft" - left_pad="30" - name="color_pipette" - picture_style="true" - width="32" /> + left_pad="50" + name="Pipette" + width="28" /> <button follows="right|bottom" height="20" label="Ok" - label_selected="Select" + label_selected="Ok" layout="topleft" - left_pad="50" + right="-120" + top_delta="9" name="select_btn" width="100" /> <button @@ -198,6 +200,7 @@ label_selected="Cancel" layout="topleft" left_pad="5" + right="-10" name="cancel_btn" width="100" /> <text diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml index 07d76f4810..6c4f10e61e 100644 --- a/indra/newview/skins/default/xui/en/floater_customize.xml +++ b/indra/newview/skins/default/xui/en/floater_customize.xml @@ -9,7 +9,7 @@ name="floater customize" help_topic="floater_customize" save_rect="true" - title="Appearance" + title="APPEARANCE" top_delta="-185" width="494"> <tab_container @@ -193,7 +193,7 @@ font="SansSerif" height="16" layout="topleft" - left="26" + left="8" name="title" top="8" width="355"> @@ -299,7 +299,7 @@ scratch and wear it. left="8" name="Create New" top="104" - width="120" /> + width="140" /> <button follows="right|bottom" height="20" @@ -342,9 +342,10 @@ scratch and wear it. top="4" width="18" /> <icon + follows="left|top" height="16" layout="topleft" - left_delta="-325" + left="8" mouse_opaque="true" top_delta="3" width="16" /> @@ -399,7 +400,7 @@ scratch and wear it. font="SansSerif" height="16" layout="topleft" - left="26" + left="8" name="title" top="8" width="355"> @@ -599,7 +600,7 @@ scratch and wear it. <icon height="16" layout="topleft" - left_delta="-325" + left="8" mouse_opaque="true" top_delta="3" width="16" /> @@ -654,7 +655,7 @@ scratch and wear it. font="SansSerif" height="16" layout="topleft" - left="26" + left="8" name="title" top="8" width="355"> @@ -1015,7 +1016,7 @@ scratch and wear it. <icon height="16" layout="topleft" - left_delta="-325" + left="8" mouse_opaque="true" top_delta="3" width="16" /> @@ -1100,7 +1101,7 @@ scratch and wear it. font="SansSerif" height="16" layout="topleft" - left="26" + left="8" name="title" top="8" width="355"> @@ -1221,7 +1222,7 @@ scratch and wear it. <icon height="16" layout="topleft" - left_delta="-325" + left="8" mouse_opaque="true" top_delta="3" width="16" /> @@ -1306,7 +1307,7 @@ scratch and wear it. font="SansSerif" height="16" layout="topleft" - left="26" + left="8" name="title" top="8" width="355"> diff --git a/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml index b0d636445d..35f3e643c3 100644 --- a/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml +++ b/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml @@ -6,7 +6,7 @@ name="Day Cycle Floater" help_topic="day_cycle_floater" save_rect="true" - title="Day Cycle Editor" + title="DAY CYCLE EDITOR" width="646"> <tab_container follows="left|top" diff --git a/indra/newview/skins/default/xui/en/floater_device_settings.xml b/indra/newview/skins/default/xui/en/floater_device_settings.xml index 2b23980423..91a7a678da 100644 --- a/indra/newview/skins/default/xui/en/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_device_settings.xml @@ -1,11 +1,11 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" height="260" layout="topleft" name="floater_device_settings" help_topic="floater_device_settings" - title="Voice Chat Device Settings" + title="VOICE CHAT DEVICE SETTINGS" width="405"> <panel bottom="260" diff --git a/indra/newview/skins/default/xui/en/floater_env_settings.xml b/indra/newview/skins/default/xui/en/floater_env_settings.xml index 7c22311f66..5233cb023d 100644 --- a/indra/newview/skins/default/xui/en/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_env_settings.xml @@ -6,7 +6,7 @@ name="Environment Editor Floater" help_topic="environment_editor_floater" save_rect="true" - title="Environment Editor" + title="ENVIRONMENT EDITOR" width="600"> <floater.string name="timeStr"> diff --git a/indra/newview/skins/default/xui/en/floater_font_test.xml b/indra/newview/skins/default/xui/en/floater_font_test.xml index 8b14f691d6..3ab19ec9d9 100644 --- a/indra/newview/skins/default/xui/en/floater_font_test.xml +++ b/indra/newview/skins/default/xui/en/floater_font_test.xml @@ -8,7 +8,7 @@ min_width="154" name="contents" help_topic="contents" - title="Font Test" + title="FONT TEST" width="500"> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_gesture.xml b/indra/newview/skins/default/xui/en/floater_gesture.xml index 128d518e12..b23482655c 100644 --- a/indra/newview/skins/default/xui/en/floater_gesture.xml +++ b/indra/newview/skins/default/xui/en/floater_gesture.xml @@ -5,7 +5,7 @@ height="465" name="gestures" help_topic="gestures" - title="Gestures" + title="GESTURES" background_visible="true" follows="all" label="Places" @@ -68,7 +68,6 @@ layout="topleft" left="10" name="recent_viewsort_btn" - picture_style="true" top="5" width="18" /> <button @@ -81,7 +80,6 @@ layout="topleft" left_pad="5" name="new_gesture_btn" - picture_style="true" tool_tip="Make new gesture" top_delta="0" width="18" /> @@ -95,7 +93,6 @@ layout="topleft" left_pad="230" name="del_btn" - picture_style="true" tool_tip="Delete this gesture" top_delta="0" width="18" /> diff --git a/indra/newview/skins/default/xui/en/floater_god_tools.xml b/indra/newview/skins/default/xui/en/floater_god_tools.xml index 97cb6e259c..79eed52fbf 100644 --- a/indra/newview/skins/default/xui/en/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_god_tools.xml @@ -5,7 +5,7 @@ layout="topleft" name="godtools floater" help_topic="godtools_floater" - title="God Tools" + title="GOD TOOLS" width="400"> <tab_container follows="left|top" diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml index cd98f21918..1e2440580e 100644 --- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml @@ -5,7 +5,7 @@ layout="topleft" name="Hardware Settings Floater" help_topic="hardware_settings_floater" - title="Hardware Settings" + title="HARDWARE SETTINGS" width="500"> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml index d2fe8d0e6d..f50ff01230 100644 --- a/indra/newview/skins/default/xui/en/floater_help_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml @@ -10,7 +10,7 @@ help_topic="floater_help_browser" save_rect="true" single_instance="true" - title="Help Browser" + title="HELP BROWSER" width="620"> <floater.string name="home_page_url"> diff --git a/indra/newview/skins/default/xui/en/floater_hud.xml b/indra/newview/skins/default/xui/en/floater_hud.xml index 6e8950c49a..99a6a95828 100644 --- a/indra/newview/skins/default/xui/en/floater_hud.xml +++ b/indra/newview/skins/default/xui/en/floater_hud.xml @@ -8,7 +8,7 @@ help_topic="floater_hud" save_rect="true" save_visibility="true" - title="Tutorial" + title="TUTORIAL" width="362"> <web_browser border_visible="false" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 70af2f63b6..452d28d4ea 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -15,7 +15,7 @@ width="520" can_resize="true" min_width="350" - min_height="350"> + min_height="369"> <layout_stack follows="left|top|right|bottom" height="354" width="520" diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml index dcb93c6e2f..16873df310 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -8,7 +8,7 @@ layout="topleft" name="incoming call" help_topic="incoming_call" - title="Unknown Person is calling" + title="UNKNOWN PERSON IS CALLING" width="240"> <floater.string name="anonymous"> diff --git a/indra/newview/skins/default/xui/en/floater_inspect.xml b/indra/newview/skins/default/xui/en/floater_inspect.xml index 9f7723c51b..3f7642fafe 100644 --- a/indra/newview/skins/default/xui/en/floater_inspect.xml +++ b/indra/newview/skins/default/xui/en/floater_inspect.xml @@ -9,7 +9,7 @@ name="inspect" help_topic="inspect" save_rect="true" - title="Inspect Objects" + title="INSPECT OBJECTS" width="400"> <floater.string name="timeStamp"> diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml index dfa6c83b4e..30639f955f 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory.xml @@ -12,7 +12,7 @@ save_rect="true" save_visibility="true" single_instance="true" - title="Inventory" + title="INVENTORY" width="467"> <floater.string name="Title"> @@ -30,405 +30,16 @@ name="Fetched"> Fetched </floater.string> - <filter_editor - search_button_visible="false" - text_pad_left="12" - follows="left|top|right" - height="16" - label="Type here to search" - layout="topleft" - left="6" - name="inventory search editor" - top="34" - width="455" /> - <tab_container - follows="all" - height="508" - halign="center" - layout="topleft" - left_delta="-4" - name="inventory filter tabs" - tab_position="top" - tab_height="20" - top_pad="5" - width="463"> - <inventory_panel - follows="left|top|right|bottom" - height="491" - label="All Items" - layout="topleft" - left="1" - name="All Items" - top="16" - width="461" /> - <inventory_panel - follows="left|top|right|bottom" - height="491" - label="Recent Items" - layout="topleft" - left_delta="0" - name="Recent Items" - top_delta="0" - width="461" /> - </tab_container> - <menu_bar - bg_visible="false" - follows="left|top|right" - height="18" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="Inventory Menu" - top_delta="-38" - width="461"> - <menu - height="101" - label="File" - layout="topleft" - left="0" - mouse_opaque="false" - name="File" - tear_off="true" - top="-117" - width="128"> - <menu_item_call - label="Open" - layout="topleft" - name="Open"> - <menu_item_call.on_click - function="Inventory.DoToSelected" - parameter="open" /> - </menu_item_call> - <menu - create_jump_keys="true" - label="Upload" - layout="topleft" - name="upload" - tear_off="true"> - <menu_item_call - label="Image (L$[COST])..." - layout="topleft" - name="Upload Image" - shortcut="control|U"> - <menu_item_call.on_click - function="File.UploadImage" - parameter="" /> - <menu_item_call.on_enable - function="File.EnableUpload" /> - </menu_item_call> - <menu_item_call - label="Sound (L$[COST])..." - layout="topleft" - name="Upload Sound"> - <menu_item_call.on_click - function="File.UploadSound" - parameter="" /> - <menu_item_call.on_enable - function="File.EnableUpload" /> - </menu_item_call> - <menu_item_call - label="Animation (L$[COST])..." - layout="topleft" - name="Upload Animation"> - <menu_item_call.on_click - function="File.UploadAnim" - parameter="" /> - <menu_item_call.on_enable - function="File.EnableUpload" /> - </menu_item_call> - <menu_item_call - label="Bulk (L$[COST] per file)..." - layout="topleft" - name="Bulk Upload"> - <menu_item_call.on_click - function="File.UploadBulk" - parameter="" /> - </menu_item_call> - <menu_item_separator - layout="topleft" /> - </menu> - <menu_item_separator - layout="topleft" /> - <menu_item_call - label="New Window" - layout="topleft" - name="New Window"> - <menu_item_call.on_click - function="Inventory.NewWindow" /> - </menu_item_call> - <menu_item_separator - layout="topleft" - name="separator2" /> - <menu_item_call - label="Show Filters" - layout="topleft" - name="Show Filters"> - <menu_item_call.on_click - function="Inventory.ShowFilters" /> - </menu_item_call> - <menu_item_call - label="Reset Filters" - layout="topleft" - name="Reset Current"> - <menu_item_call.on_click - function="Inventory.ResetFilter" /> - </menu_item_call> - <menu_item_call - label="Close All Folders" - layout="topleft" - name="Close All Folders"> - <menu_item_call.on_click - function="Inventory.CloseAllFolders" /> - </menu_item_call> - <menu_item_separator - layout="topleft" - name="separator3" /> - <menu_item_call - label="Empty Trash" - layout="topleft" - name="Empty Trash"> - <menu_item_call.on_click - function="Inventory.EmptyTrash" /> - </menu_item_call> - <menu_item_call - label="Empty Lost And Found" - layout="topleft" - name="Empty Lost And Found"> - <menu_item_call.on_click - function="Inventory.EmptyLostAndFound" /> - </menu_item_call> - </menu> - <menu - height="121" - label="Create" - layout="topleft" - left="0" - mouse_opaque="false" - name="Create" - tear_off="true" - top="-201" - width="121"> - <menu_item_call - label="New Folder" - layout="topleft" - name="New Folder"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="category" /> - </menu_item_call> - <menu_item_call - label="New Script" - layout="topleft" - name="New Script"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="lsl" /> - </menu_item_call> - <menu_item_call - label="New Note" - layout="topleft" - name="New Note"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="notecard" /> - </menu_item_call> - <menu_item_call - label="New Gesture" - layout="topleft" - name="New Gesture"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="gesture" /> - </menu_item_call> - <menu - height="175" - label="New Clothes" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="New Clothes" - top_pad="514" - width="125"> - <menu_item_call - label="New Shirt" - layout="topleft" - name="New Shirt"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="shirt" /> - </menu_item_call> - <menu_item_call - label="New Pants" - layout="topleft" - name="New Pants"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="pants" /> - </menu_item_call> - <menu_item_call - label="New Shoes" - layout="topleft" - name="New Shoes"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="shoes" /> - </menu_item_call> - <menu_item_call - label="New Socks" - layout="topleft" - name="New Socks"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="socks" /> - </menu_item_call> - <menu_item_call - label="New Jacket" - layout="topleft" - name="New Jacket"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="jacket" /> - </menu_item_call> - <menu_item_call - label="New Skirt" - layout="topleft" - name="New Skirt"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="skirt" /> - </menu_item_call> - <menu_item_call - label="New Gloves" - layout="topleft" - name="New Gloves"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="gloves" /> - </menu_item_call> - <menu_item_call - label="New Undershirt" - layout="topleft" - name="New Undershirt"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="undershirt" /> - </menu_item_call> - <menu_item_call - label="New Underpants" - layout="topleft" - name="New Underpants"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="underpants" /> - </menu_item_call> - <menu_item_call - label="New Alpha" - layout="topleft" - name="New Alpha"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="alpha" /> - </menu_item_call> - <menu_item_call - label="New Tattoo" - layout="topleft" - name="New Tattoo"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="tattoo" /> - </menu_item_call> - </menu> - <menu - height="85" - label="New Body Parts" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="New Body Parts" - top_pad="514" - width="118"> - <menu_item_call - label="New Shape" - layout="topleft" - name="New Shape"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="shape" /> - </menu_item_call> - <menu_item_call - label="New Skin" - layout="topleft" - name="New Skin"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="skin" /> - </menu_item_call> - <menu_item_call - label="New Hair" - layout="topleft" - name="New Hair"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="hair" /> - </menu_item_call> - <menu_item_call - label="New Eyes" - layout="topleft" - name="New Eyes"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="eyes" /> - </menu_item_call> - </menu> - </menu> - <menu - height="49" - label="Sort" - layout="topleft" - left="0" - mouse_opaque="false" - name="Sort" - tear_off="true" - top="-113" - width="118"> - <menu_item_check - control_name="Inventory.SortByName" - label="By Name" - layout="topleft" - name="By Name"> - <menu_item_check.on_click - function="Inventory.SetSortBy" - parameter="name" /> - </menu_item_check> - <menu_item_check - control_name="Inventory.SortByDate" - label="By Date" - layout="topleft" - name="By Date"> - <menu_item_check.on_click - function="Inventory.SetSortBy" - parameter="date" /> - </menu_item_check> - <menu_item_separator - layout="topleft" /> - <menu_item_check - control_name="Inventory.FoldersAlwaysByName" - label="Folders Always By Name" - layout="topleft" - name="Folders Always By Name"> - <menu_item_check.on_click - function="Inventory.SetSortBy" - parameter="foldersalwaysbyname" /> - </menu_item_check> - <menu_item_check - control_name="Inventory.SystemFoldersToTop" - label="System Folders To Top" - layout="topleft" - name="System Folders To Top"> - <menu_item_check.on_click - function="Inventory.SetSortBy" - parameter="systemfolderstotop" /> - </menu_item_check> - </menu> - </menu_bar> +<panel + bottom="560" + class="panel_main_inventory" + filename="panel_main_inventory.xml" + follows="all" + layout="topleft" + left="0" + label="Inventory Panel" + name="Inventory Panel" + top="15" + width="467"> +</panel> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml index 4f0609c7f8..4ca6002c13 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml @@ -7,7 +7,7 @@ name="item properties" help_topic="item_properties" save_rect="true" - title="Inventory Item Properties" + title="INVENTORY ITEM PROPERTIES" width="350"> <floater.string name="unknown"> diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml index 0042f97a8e..90fee857fb 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml @@ -6,7 +6,7 @@ layout="topleft" name="Inventory Finder" help_topic="inventory_finder" - title="inventory_recent_items" + title="INVENTORY_RECENT_ITEMS" width="280"> <icon height="16" diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml index e2da059ace..4d67e4c343 100644 --- a/indra/newview/skins/default/xui/en/floater_joystick.xml +++ b/indra/newview/skins/default/xui/en/floater_joystick.xml @@ -5,7 +5,7 @@ layout="topleft" name="Joystick" help_topic="joystick" - title="Joystick Configuration" + title="JOYSTICK CONFIGURATION" width="550"> <floater.string name="NoDevice"> diff --git a/indra/newview/skins/default/xui/en/floater_lagmeter.xml b/indra/newview/skins/default/xui/en/floater_lagmeter.xml index 309475098f..19f5155f88 100644 --- a/indra/newview/skins/default/xui/en/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/en/floater_lagmeter.xml @@ -6,7 +6,7 @@ name="floater_lagmeter" help_topic="floater_lagmeter" save_rect="true" - title="Lag Meter" + title="LAG METER" width="350"> <floater.string name="max_title_msg"> @@ -184,7 +184,6 @@ layout="topleft" left="8" name="client_lagmeter" - picture_style="true" tab_stop="false" tool_tip="Client lag status" top="24" @@ -233,7 +232,6 @@ layout="topleft" left="8" name="network_lagmeter" - picture_style="true" tab_stop="false" tool_tip="Network lag status" top="64" @@ -282,7 +280,6 @@ layout="topleft" left="8" name="server_lagmeter" - picture_style="true" tab_stop="false" tool_tip="Server lag status" top="104" diff --git a/indra/newview/skins/default/xui/en/floater_land_holdings.xml b/indra/newview/skins/default/xui/en/floater_land_holdings.xml index 46d74b6aff..2c04a94613 100644 --- a/indra/newview/skins/default/xui/en/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/en/floater_land_holdings.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - height="400" + height="430" layout="topleft" name="land holdings floater" help_topic="land_holdings_floater" - title="My Land" - width="280"> + title="MY LAND" + width="600"> <floater.string name="area_string"> [AREA] m² @@ -15,81 +15,82 @@ draw_heading="true" height="170" layout="topleft" - left="8" + left="10" name="parcel list" - top="24" - width="270"> + top="28" + width="580"> <scroll_list.columns label="Parcel" name="name" - width="69" /> + width="167" /> <scroll_list.columns label="Region" name="location" - width="74" /> + width="180" /> <scroll_list.columns label="Type" name="type" - width="55" /> + width="145" /> <scroll_list.columns label="Area" name="area" - width="10" /> + width="88" /> <scroll_list.columns label="" name="hidden" width="-1" /> </scroll_list> <button - height="20" - font="SansSerifSmall" + height="23" + font="SansSerifBold" label="Teleport" label_selected="Teleport" layout="topleft" - left_delta="4" + top="208" + left="10" name="Teleport" tool_tip="Teleport to the center of this land." - top_pad="4" - width="100" /> + width="80" /> <button - height="20" - font="SansSerifSmall" + height="23" + font="SansSerifBold" label="Map" label_selected="Map" layout="topleft" - left_pad="4" + top="208" + left="95" name="Show on Map" tool_tip="Show this land on the world map" - top_delta="0" - width="100" /> + width="80" /> <text type="string" length="1" follows="left|top" - height="16" layout="topleft" - left="12" + top="251" + left="10" name="contrib_label" - top="222" - width="480"> + height="16" + width="580"> Contributions to your groups: </text> <scroll_list draw_heading="true" height="75" layout="topleft" - left_delta="-4" name="grant list" - top_pad="4" - width="270"> + top="271" + left="10" + width="580"> <scroll_list.columns label="Group" name="group" - width="125" /> + width="290" + left_pad="10" /> <scroll_list.columns label="Area" name="area" - width="125" /> + width="290" /> </scroll_list> <text type="string" @@ -97,12 +98,11 @@ follows="left|top" height="16" layout="topleft" - left_delta="4" name="allowed_label" - top_pad="4" - width="150"> - Allowed land holdings at -current payment plan: + top="366" + left="10" + width="290"> + Allowed land holdings at current payment plan: </text> <text type="string" @@ -110,10 +110,10 @@ current payment plan: follows="left|top" height="16" layout="topleft" - left_pad="5" name="allowed_text" - top_delta="10" - width="132"> + top="366" + left="305" + width="290"> [AREA] m² </text> <text @@ -122,10 +122,10 @@ current payment plan: follows="left|top" height="16" layout="topleft" - left="12" + top="386" + left="10" name="current_label" - top_pad="5" - width="150"> + width="290"> Current land holdings: </text> <text @@ -134,10 +134,10 @@ current payment plan: follows="left|top" height="16" layout="topleft" - left_pad="5" + top="386" + left="305" name="current_text" - top_delta="0" - width="132"> + width="290"> [AREA] m² </text> <text @@ -147,12 +147,11 @@ current payment plan: font="SansSerifBold" height="16" layout="topleft" - left="12" + top="406" + left="10" name="available_label" - top_pad="5" - width="150"> - Available for land -purchases: + width="290"> + Available for land purchases: </text> <text type="string" @@ -161,10 +160,10 @@ purchases: font="SansSerifBold" height="16" layout="topleft" - left_pad="5" name="available_text" - top_delta="5" - width="140"> + top="406" + left="305" + width="290"> [AREA] m² </text> -</floater>
\ No newline at end of file +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml index 93bbb0107e..e94717fe32 100644 --- a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" bevel_style="none" @@ -12,7 +12,7 @@ name="script ed float" help_topic="script_ed_float" save_rect="true" - title="Script: New Script" + title="SCRIPT: NEW SCRIPT" width="500"> <floater.string name="not_allowed"> diff --git a/indra/newview/skins/default/xui/en/floater_lsl_guide.xml b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml index 4dcf168605..a5b477313c 100644 --- a/indra/newview/skins/default/xui/en/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml @@ -10,7 +10,7 @@ name="script ed float" help_topic="script_ed_float" save_rect="true" - title="LSL Wiki" + title="LSL WIKI" width="370"> <check_box follows="top|left" diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml index b11892be74..d6b20c8015 100644 --- a/indra/newview/skins/default/xui/en/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml @@ -10,7 +10,7 @@ help_topic="floater_about" save_rect="true" single_instance="true" - title="Media Browser" + title="MEDIA BROWSER" width="820"> <floater.string name="home_page_url"> @@ -127,7 +127,6 @@ layout="topleft" left_delta="55" name="play" - picture_style="true" top_delta="0" width="55" /> <button @@ -138,7 +137,6 @@ layout="topleft" left_delta="0" name="pause" - picture_style="true" top_delta="0" width="55" /> <button diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml index 4218c15408..68dd2001af 100644 --- a/indra/newview/skins/default/xui/en/floater_media_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml @@ -15,9 +15,9 @@ min_height="430" min_width="620" mouse_opaque="true" - name="Medis Settings" + name="Media Settings" help_topic = "media_settings" - title="Media Settings"> + title="MEDIA SETTINGS"> <button bottom="-525" enabled="true" diff --git a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml index 560acafd4f..28a29c42aa 100644 --- a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml @@ -7,7 +7,7 @@ layout="topleft" name="MemLeak" help_topic="memleak" - title="Simulate a Memory Leak" + title="SIMULATE A MEMORY LEAK" width="350"> <spinner decimal_digits="0" diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml index 02cbef5987..5a8ffcebea 100644 --- a/indra/newview/skins/default/xui/en/floater_moveview.xml +++ b/indra/newview/skins/default/xui/en/floater_moveview.xml @@ -56,7 +56,6 @@ layout="topleft" left="17" name="turn left btn" - picture_style="true" scale_image="false" tool_tip="Turn left (press Left Arrow or A)" top="45" @@ -70,7 +69,6 @@ layout="topleft" left_pad="34" name="turn right btn" - picture_style="true" scale_image="false" tool_tip="Turn right (press Right Arrow or D)" top_delta="0" @@ -84,7 +82,6 @@ layout="topleft" left="10" name="move up btn" - picture_style="true" scale_image="false" tool_tip="Fly up, press "E"" top="14" @@ -98,7 +95,6 @@ layout="topleft" left_pad="45" name="move down btn" - picture_style="true" scale_image="false" tool_tip="Fly down, press "C"" top_delta="0" @@ -112,7 +108,6 @@ layout="topleft" left="46" name="forward btn" - picture_style="true" quadrant="up" scale_image="false" tool_tip="Walk forward (press up arrow or W)" @@ -127,7 +122,6 @@ layout="topleft" left_delta="0" name="backward btn" - picture_style="true" quadrant="down" scale_image="false" tool_tip="Walk backward (press down arrow or S)" diff --git a/indra/newview/skins/default/xui/en/floater_mute_object.xml b/indra/newview/skins/default/xui/en/floater_mute_object.xml index 33b1dac8a5..454b1c43b2 100644 --- a/indra/newview/skins/default/xui/en/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/en/floater_mute_object.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" can_minimize="false" @@ -6,7 +6,7 @@ layout="topleft" name="block by name" help_topic="mute_by_name" - title="Block object by name" + title="BLOCK OBJECT BY NAME" width="375"> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_my_friends.xml b/indra/newview/skins/default/xui/en/floater_my_friends.xml index 689221b9c7..e7efcc7844 100644 --- a/indra/newview/skins/default/xui/en/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/en/floater_my_friends.xml @@ -11,7 +11,7 @@ help_topic="floater_my_friends" save_rect="true" single_instance="true" - title="Contacts" + title="CONTACTS" width="395"> <tab_container follows="all" diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml index e7c5bf8585..7f58ea132e 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -13,7 +13,7 @@ name="nearby_chat" help_topic="nearby_chat" save_rect="true" - title="Nearby Chat" + title="NEARBY CHAT" save_dock_state="true" save_visibility="true" single_instance="true" diff --git a/indra/newview/skins/default/xui/en/floater_notification.xml b/indra/newview/skins/default/xui/en/floater_notification.xml index f9cb22055a..1f9ddecac2 100644 --- a/indra/newview/skins/default/xui/en/floater_notification.xml +++ b/indra/newview/skins/default/xui/en/floater_notification.xml @@ -6,7 +6,7 @@ layout="topleft" min_height="50" name="notification" - title="Notifications Console" + title="NOTIFICATIONS CONSOLE" width="200"> <text_editor type="string" diff --git a/indra/newview/skins/default/xui/en/floater_notifications_console.xml b/indra/newview/skins/default/xui/en/floater_notifications_console.xml index 03a2aad96d..ca81b9bcf0 100644 --- a/indra/newview/skins/default/xui/en/floater_notifications_console.xml +++ b/indra/newview/skins/default/xui/en/floater_notifications_console.xml @@ -8,7 +8,7 @@ name="notifications_console" help_topic="notifications_console" single_instance="true" - title="Notifications Console" + title="NOTIFICATIONS CONSOLE" width="500"> <combo_box follows="left|right|top" diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml index cc50f43339..3fd118df1c 100644 --- a/indra/newview/skins/default/xui/en/floater_openobject.xml +++ b/indra/newview/skins/default/xui/en/floater_openobject.xml @@ -10,7 +10,7 @@ name="objectcontents" help_topic="objectcontents" save_rect="true" - title="Object Contents" + title="OBJECT CONTENTS" width="300"> <text type="string" @@ -26,7 +26,7 @@ width="284"> [DESC]: </text> - <panel_inventory + <panel_inventory_object background_visible="false" draw_border="false" follows="all" diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml index b4becfa022..509cffe490 100644 --- a/indra/newview/skins/default/xui/en/floater_pay.xml +++ b/indra/newview/skins/default/xui/en/floater_pay.xml @@ -2,22 +2,29 @@ <floater legacy_header_height="18" can_minimize="false" - height="185" + height="200" layout="topleft" name="Give Money" help_topic="give_money" save_rect="true" width="225"> + <string + name="payee_group"> + Pay Group + </string> + <string + name="payee_resident"> + Pay Resident + </string> <text type="string" length="1" follows="left|top" - font="SansSerifBold" height="18" layout="topleft" left="12" name="payee_label" - top="7" + top="22" width="75"> Pay: </text> @@ -45,7 +52,6 @@ </text> <button height="23" - font="SansSerifSmall" label="L$1" label_selected="L$1" layout="topleft" @@ -55,8 +61,7 @@ width="80" /> <button height="23" - label="L$1" - font="SansSerif" + label="L$5" label_selected="L$5" layout="topleft" left_pad="15" @@ -65,7 +70,6 @@ <button height="23" label="L$10" - font="SansSerifHuge" label_selected="L$10" layout="topleft" left="25" diff --git a/indra/newview/skins/default/xui/en/floater_pay_object.xml b/indra/newview/skins/default/xui/en/floater_pay_object.xml index 8d230023cc..1946920a9c 100644 --- a/indra/newview/skins/default/xui/en/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/en/floater_pay_object.xml @@ -8,32 +8,14 @@ help_topic="give_money" save_rect="true" width="225"> - <text - type="string" - length="1" - follows="left|top" - font="SansSerifBold" - height="18" - layout="topleft" - left="12" - name="payee_group" - top="7" - width="75"> - Pay group: - </text> - <text - type="string" - length="1" - follows="left|top" - font="SansSerifBold" - height="18" - layout="topleft" - left="12" - name="payee_resident" - top="7" - width="75"> - Pay resident: - </text> + <string + name="payee_group"> + Pay Group + </string> + <string + name="payee_resident"> + Pay Resident + </string> <icon height="16" width="16" @@ -41,7 +23,7 @@ mouse_opaque="true" name="icon_person" tool_tip="Person" - top_pad="0" + top_pad="24" left="10" /> <text diff --git a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml index 0967706cc2..6faab84159 100644 --- a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml @@ -6,7 +6,7 @@ name="perm prefs" help_topic="perm_prefs" save_rect="true" - title="Default Upload Permissions" + title="DEFAULT UPLOAD PERMISSIONS" width="315"> <panel follows="left|top|right|bottom" diff --git a/indra/newview/skins/default/xui/en/floater_post_process.xml b/indra/newview/skins/default/xui/en/floater_post_process.xml index 46554beede..05559adf89 100644 --- a/indra/newview/skins/default/xui/en/floater_post_process.xml +++ b/indra/newview/skins/default/xui/en/floater_post_process.xml @@ -5,7 +5,7 @@ layout="topleft" name="Post-Process Floater" help_topic="post_process_floater" - title="Post-Process Settings" + title="POST-PROCESS SETTINGS" width="400"> <tab_container follows="left|top" diff --git a/indra/newview/skins/default/xui/en/floater_postcard.xml b/indra/newview/skins/default/xui/en/floater_postcard.xml index b13bd1740c..3a7b6cc832 100644 --- a/indra/newview/skins/default/xui/en/floater_postcard.xml +++ b/indra/newview/skins/default/xui/en/floater_postcard.xml @@ -10,7 +10,7 @@ min_width="450" name="Postcard" help_topic="postcard" - title="Email Snapshot" + title="EMAIL SNAPSHOT" width="450"> <floater.string name="default_subject"> diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml index d2a2a7ce02..d182cdc6bb 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences.xml @@ -9,7 +9,7 @@ name="Preferences" help_topic="preferences" single_instance="true" - title="Preferences" + title="PREFERENCES" width="620"> <button follows="right|bottom" diff --git a/indra/newview/skins/default/xui/en/floater_preview_classified.xml b/indra/newview/skins/default/xui/en/floater_preview_classified.xml index 7c8c6d7207..2017cf2bd1 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_classified.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_classified.xml @@ -7,7 +7,7 @@ name="classified_preview" help_topic="classified_preview" save_rect="true" - title="Classified Information" + title="CLASSIFIED INFORMATION" width="440"> <floater.string name="Title"> diff --git a/indra/newview/skins/default/xui/en/floater_preview_event.xml b/indra/newview/skins/default/xui/en/floater_preview_event.xml index f5ab8c95d7..a4066b34c5 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_event.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_event.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" auto_tile="true" @@ -7,7 +7,7 @@ name="event_preview" help_topic="event_preview" save_rect="true" - title="Event Information" + title="EVENT INFORMATION" width="440"> <floater.string name="Title"> diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml index fc838f27b4..66408a5057 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml @@ -8,7 +8,7 @@ name="Gesture" help_topic="gesture" save_rect="true" - title="Gesture Shortcut" + title="GESTURE SHORTCUT" width="260"> <scroll_list follows="top|left" @@ -54,4 +54,4 @@ name="save_btn" top_delta="0" width="80" /--> -</floater>
\ No newline at end of file +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml index b489ae2e77..26252a7a16 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml @@ -8,7 +8,7 @@ name="Gesture" help_topic="gesture" save_rect="true" - title="Gesture Shortcut" + title="GESTURE SHORTCUT" width="260"> <text type="string" @@ -85,4 +85,4 @@ tool_tip="Replace the trigger word(s) with these words. For example, trigger 'hello' replace with 'howdy' will turn the chat 'I wanted to say hello' into 'I wanted to say howdy' as well as playing the gesture" top_delta="-4" width="135" /> -</floater>
\ No newline at end of file +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml index 8a07f3ad1e..34f707cd2a 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml @@ -8,7 +8,7 @@ name="Gesture" help_topic="gesture" save_rect="true" - title="Gesture Shortcut" + title="GESTURE SHORTCUT" width="260"> <scroll_list follows="top|left" @@ -239,4 +239,4 @@ unless you add wait steps. name="wait_time_editor" top_delta="0" width="50" /--> -</floater>
\ No newline at end of file +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml index b44de8e178..06dbdc9539 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml @@ -11,7 +11,7 @@ min_width="234" name="preview notecard" help_topic="preview_notecard" - title="Note:" + title="NOTE:" width="400"> <floater.string name="no_object"> diff --git a/indra/newview/skins/default/xui/en/floater_region_info.xml b/indra/newview/skins/default/xui/en/floater_region_info.xml index ae01d0bdf4..9bb30f8e86 100644 --- a/indra/newview/skins/default/xui/en/floater_region_info.xml +++ b/indra/newview/skins/default/xui/en/floater_region_info.xml @@ -6,7 +6,7 @@ layout="topleft" name="regioninfo" save_rect="true" - title="Region/Estate" + title="REGION/ESTATE" width="480"> <tab_container bottom="512" diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index 88f09b521c..696233676c 100644 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -5,7 +5,7 @@ layout="topleft" name="floater_report_abuse" help_topic="floater_report_abuse" - title="Report Abuse" + title="REPORT ABUSE" width="333"> <floater.string name="Screenshot"> @@ -126,7 +126,6 @@ layout="topleft" left_delta="0" name="pick_btn" - picture_style="true" image_overlay="Inv_Object" tool_tip="Object Picker - Identify an object as the subject of this report" top_pad="0" diff --git a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml index 0029fcb09b..bd9925be1d 100644 --- a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml +++ b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml @@ -7,8 +7,8 @@ layout="topleft" name="script" help_topic="script" - short_title="[All scripts]" - title="[All scripts]" + short_title="[ALL SCRIPTS]" + title="[ALL SCRIPTS]" width="440"> <text_editor bottom="197" diff --git a/indra/newview/skins/default/xui/en/floater_script_preview.xml b/indra/newview/skins/default/xui/en/floater_script_preview.xml index c29a2f4516..bb0702c353 100644 --- a/indra/newview/skins/default/xui/en/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_script_preview.xml @@ -11,7 +11,7 @@ name="preview lsl text" help_topic="preview_lsl_text" save_rect="true" - title="Script: Rotation Script" + title="SCRIPT: ROTATION SCRIPT" top_delta="0" width="500"> <floater.string diff --git a/indra/newview/skins/default/xui/en/floater_script_queue.xml b/indra/newview/skins/default/xui/en/floater_script_queue.xml index 8a44252426..60a26fcf1d 100644 --- a/indra/newview/skins/default/xui/en/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/en/floater_script_queue.xml @@ -8,7 +8,7 @@ name="queue" help_topic="queue" save_rect="true" - title="Reset Progress" + title="RESET PROGRESS" width="300"> <floater.string name="Starting"> diff --git a/indra/newview/skins/default/xui/en/floater_script_search.xml b/indra/newview/skins/default/xui/en/floater_script_search.xml index 79c4438dd6..ade0156bc7 100644 --- a/indra/newview/skins/default/xui/en/floater_script_search.xml +++ b/indra/newview/skins/default/xui/en/floater_script_search.xml @@ -6,7 +6,7 @@ layout="topleft" name="script search" help_topic="script_search" - title="Script Search" + title="SCRIPT SEARCH" width="300"> <check_box control_name="LSLFindCaseInsensitivity" diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml index 2f4d7c50a1..f7ba719dc2 100644 --- a/indra/newview/skins/default/xui/en/floater_search.xml +++ b/indra/newview/skins/default/xui/en/floater_search.xml @@ -10,7 +10,7 @@ help_topic="floater_search" save_rect="true" single_instance="true" - title="Search [SECOND_LIFE]" + title="SEARCH [SECOND_LIFE]" width="620"> <floater.string name="search_url"> diff --git a/indra/newview/skins/default/xui/en/floater_sell_land.xml b/indra/newview/skins/default/xui/en/floater_sell_land.xml index 8fedd0a89f..2cf800fb15 100644 --- a/indra/newview/skins/default/xui/en/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/en/floater_sell_land.xml @@ -7,13 +7,12 @@ name="sell land" help_topic="sell_land" single_instance="true" - title="Sell Land" + title="SELL LAND" width="313"> <scroll_container color="DkGray2" follows="left|top|right|bottom" height="435" - min_height="300" layout="topleft" name="profile_scroll" reserve_scroll_corner="true" @@ -96,27 +95,16 @@ width="200"> To sell this parcel: </text> - <icon - follows="top|left" - height="64" - image_name="badge_note.j2c" - layout="topleft" - left="0" - name="step_price" - top="206" - width="64" /> <text type="string" length="1" - bottom_delta="-38" follows="top|left" font="SansSerif" height="16" layout="topleft" - left="72" - name="price_label" - right="-20"> - Set a price: + left="30" + name="price_label"> + 1. Set a price: </text> <text type="string" @@ -124,9 +112,8 @@ follows="top|left" height="16" layout="topleft" - left="72" - name="price_text" - right="-20"> + left="40" + name="price_text"> Choose an appropriate price. </text> <text @@ -134,7 +121,7 @@ length="1" height="16" layout="topleft" - left="72" + left="40" name="price_ld" width="20"> L$ @@ -156,32 +143,22 @@ length="1" height="16" layout="topleft" - left="72" + left="40" name="price_per_m" top_delta="25" width="200"> (L$[PER_METER] per m²) </text> - <icon - follows="top|left" - height="64" - image_name="badge_note.j2c" - layout="topleft" - left="0" - name="step_sell_to" - width="64" /> <text type="string" length="1" - bottom_delta="-38" follows="top|left" font="SansSerif" height="16" layout="topleft" - left="72" - name="sell_to_label" - right="-20"> - Sell the land to: + left="30" + name="sell_to_label"> + 2. Sell the land to: </text> <text type="string" @@ -189,7 +166,7 @@ follows="top|left" height="25" layout="topleft" - left="72" + left="40" word_wrap="true" name="sell_to_text" right="-20"> @@ -235,26 +212,16 @@ name="sell_to_select_agent" top_delta="0" width="60" /> - <icon - follows="top|left" - height="64" - image_name="badge_note.j2c" - layout="topleft" - left="0" - name="step_sell_objects" - width="64" /> <text type="string" length="1" - bottom_delta="-38" follows="top|left" font="SansSerif" height="16" layout="topleft" - left="72" - name="sell_objects_label" - right="-20"> - Sell the objects with the land? + left="30" + name="sell_objects_label"> + 3. Sell the objects with the land? </text> <text type="string" @@ -264,7 +231,7 @@ height="25" layout="topleft" word_wrap="true" - left="72" + left="40" name="sell_objects_text"> Land owner's transferable objects on parcel will change ownership. </text> @@ -273,7 +240,7 @@ follows="top|right" height="40" layout="topleft" - left="72" + left="40" name="sell_objects" right="420"> <radio_item @@ -304,7 +271,7 @@ label="Show Objects" layout="topleft" name="show_objects" - left="100" + left="70" top_pad="10" width="110" /> <text 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 02b3cee97c..ffb11f3f18 100644 --- a/indra/newview/skins/default/xui/en/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/en/floater_settings_debug.xml @@ -6,7 +6,7 @@ layout="topleft" name="settings_debug" help_topic="settings_debug" - title="Debug Settings" + title="DEBUG SETTINGS" width="350"> <combo_box allow_text_entry="true" diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 4f2be37ade..95a40e27f7 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -8,7 +8,7 @@ name="Snapshot" help_topic="snapshot" save_rect="true" - title="Snapshot Preview" + title="SNAPSHOT PREVIEW" width="215"> <floater.string name="unknown"> diff --git a/indra/newview/skins/default/xui/en/floater_sound_preview.xml b/indra/newview/skins/default/xui/en/floater_sound_preview.xml index 6145b722f1..ca54ee6604 100644 --- a/indra/newview/skins/default/xui/en/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_sound_preview.xml @@ -5,7 +5,7 @@ layout="topleft" name="Sound Preview" help_topic="sound_preview" - title="sound.wav" + title="SOUND.WAV" width="300"> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_statistics.xml b/indra/newview/skins/default/xui/en/floater_statistics.xml index ab783b0735..3a4e845141 100644 --- a/indra/newview/skins/default/xui/en/floater_statistics.xml +++ b/indra/newview/skins/default/xui/en/floater_statistics.xml @@ -8,5 +8,5 @@ mouse_opaque="false" name="stats floater" help_topic="stats_floater" - title="Statistics" + title="STATISTICS" width="250" /> diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index bdc2874281..68a4867167 100644 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -9,7 +9,7 @@ help_topic="statistics" save_rect="true" save_visibility="true" - title="Statistics" + title="STATISTICS" width="250"> <scroll_container follows="top|left|bottom|right" diff --git a/indra/newview/skins/default/xui/en/floater_telehub.xml b/indra/newview/skins/default/xui/en/floater_telehub.xml index faf1a378f2..cc0ab8c57e 100644 --- a/indra/newview/skins/default/xui/en/floater_telehub.xml +++ b/indra/newview/skins/default/xui/en/floater_telehub.xml @@ -5,7 +5,7 @@ layout="topleft" name="telehub" help_topic="telehub" - title="Telehub" + title="TELEHUB" width="280"> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_test_button.xml b/indra/newview/skins/default/xui/en/floater_test_button.xml index 89a1ddda99..2bd0d1a0fa 100644 --- a/indra/newview/skins/default/xui/en/floater_test_button.xml +++ b/indra/newview/skins/default/xui/en/floater_test_button.xml @@ -96,7 +96,6 @@ layout="topleft" left="200" name="image_button" - picture_style="true" top="20" width="16" /> <button @@ -107,7 +106,6 @@ layout="topleft" left_delta="0" name="image_color_button" - picture_style="true" top_pad="10" width="16" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml index c954607ffe..9143048aeb 100644 --- a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml +++ b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml @@ -6,7 +6,7 @@ layout="topleft" name="floater_test_inspectors" help_topic="floater_test_inspectors" - title="Test Inspectors" + title="TEST INSPECTORS" width="400"> <text height="20" diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml index f39d27761c..8dba05f1ee 100644 --- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml +++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml @@ -2,11 +2,11 @@ <floater legacy_header_height="18" can_resize="true" - height="400" + height="450" layout="topleft" name="floater_test_textbox" help_topic="floater_test_textbox" - width="400"> + width="600"> <text type="string" length="1" @@ -48,61 +48,80 @@ First line of multiple lines Second line of multiple lines </text> + <text + top_pad="10" + left="10" + right="-10" + follows="top|left" + font.name="SansSerifSmall" + name="test_text10" + tool_tip="text"> + SansSerifSmall. РуÑÑкий ä¸æ–‡ (简体) The quick brown fox jumped over the lazy dog. + </text> + <text + top_pad="10" + left="10" + right="-10" + follows="top|left" + font.name="SansSerif" + name="test_text11" + tool_tip="text"> + SansSerif. РуÑÑкий ä¸æ–‡ (简体) The quick brown fox jumped over the lazy dog. + </text> + <text + top_pad="10" + left="10" + right="-10" + follows="top|left" + font.name="SansSerifLarge" + name="test_text12" + tool_tip="text"> + SansSerifLarge. РуÑÑкий ä¸æ–‡ (简体) The quick brown fox jumped over the lazy dog. + </text> + <text + top_pad="10" + left="10" + right="-10" + follows="top|left" + font.name="SansSerifHuge" + name="test_text13" + tool_tip="text"> + SansSerifHuge. РуÑÑкий ä¸æ–‡ (简体) The quick brown fox jumped over the lazy dog. + </text> <text type="string" length="1" font="SansSerif" - height="10" - layout="topleft" - left_delta="0" - top_pad="30" - width="300"> - font SansSerif - </text> - <text - type="string" - length="1" - follows="bottom|right" - height="10" - layout="topleft" - left_delta="0" - top_pad="10" - width="300"> - follows bottom right - </text> - <text - type="string" - length="1" - font="SansSerifSmall" font.style="BOLD" height="10" layout="topleft" left_delta="0" - top_pad="10" + top_pad="40" width="300"> - font style BOLD + SansSerif BOLD </text> <text type="string" length="1" - font="SansSerifSmall" + font="SansSerif" font.style="BOLD|UNDERLINE" height="10" layout="topleft" left_delta="0" top_pad="10" width="300"> - font style BOLD UNDERLINE + SansSerif BOLD UNDERLINE </text> <text type="string" length="1" + font="SansSerif" height="10" layout="topleft" left_delta="0" top_pad="10" width="300"> - font style UNDERLINE + SansSerif UNDERLINE </text> <text type="string" @@ -145,11 +164,11 @@ <text type="string" length="1" - bottom="390" + height="60" label="N" layout="topleft" left="10" - name="centered_text" + name="left_aligned_text" width="380" halign="left" text_color="1 1 1 0.7" diff --git a/indra/newview/skins/default/xui/en/floater_test_widgets.xml b/indra/newview/skins/default/xui/en/floater_test_widgets.xml index 129fd863dd..44dcb07526 100644 --- a/indra/newview/skins/default/xui/en/floater_test_widgets.xml +++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml @@ -18,7 +18,7 @@ legacy_header_height="18" can_dock="true" can_resize="true" - title="Test Floater" + title="TEST FLOATER" height="500" min_width="850" min_height="500" @@ -338,13 +338,13 @@ line to actually fit height="400" halign="center" layout="topleft" - left="575" + left="525" name="group_tab_container" tab_position="top" tab_height="20" tool_tip="tab container" top="80" - width="250"> + width="300"> <!-- "panel" is a container for widgets. It is automatically resized to fit the parent tab_container. --> <panel @@ -380,6 +380,46 @@ line to actually fit tool_tip="Color Swatch: Click to open Color Picker" top_delta="0" width="80" /> + <text + top_pad="10" + left="10" + width="250" + follows="top|left" + font.name="SansSerifSmall" + name="test_text10" + tool_tip="text"> + SansSerifSmall. РуÑÑкий ä¸æ–‡ (简体) + </text> + <text + top_pad="10" + left="10" + width="250" + follows="top|left" + font.name="SansSerif" + name="test_text11" + tool_tip="text"> + SansSerif. РуÑÑкий ä¸æ–‡ (简体) + </text> + <text + top_pad="10" + left="10" + width="250" + follows="top|left" + font.name="SansSerifLarge" + name="test_text12" + tool_tip="text"> + SansSerifLarge. РуÑÑкий ä¸æ–‡ (简体) + </text> + <text + top_pad="10" + left="10" + width="250" + follows="top|left" + font.name="SansSerifHuge" + name="test_text13" + tool_tip="text"> + SansSerifHuge. РуÑÑкий ä¸æ–‡ (简体) + </text> </panel> <!-- panels can also refer to other floaters or panels --> <panel diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml index 0a1f6e0e29..4679ae467d 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -9,7 +9,7 @@ min_width="410" name="texture picker" help_topic="texture_picker" - title="Pick: Texture" + title="PICK: TEXTURE" width="410"> <floater.string name="choose_picture"> @@ -23,14 +23,16 @@ type="string" length="1" follows="left|top" + text_color="White" + font="SansSerifBig" halign="center" - height="14" + height="17" layout="topleft" left="4" name="Multiple" top="96" width="163"> - Multiple + Multiple textures </text> <text type="string" @@ -42,7 +44,7 @@ name="unknown" top_pad="80" width="163"> - Dimensions: [DIMENSIONS] + Size: [DIMENSIONS] </text> <button enabled="false" @@ -55,7 +57,7 @@ left_delta="0" name="Default" top_pad="4" - width="64" /> + width="80" /> <button enabled="false" follows="left|bottom" @@ -67,7 +69,7 @@ left_pad="4" name="None" top_delta="0" - width="64" /> + width="80" /> <button follows="left|bottom" font="SansSerifSmall" @@ -77,75 +79,75 @@ layout="topleft" left="4" name="Blank" - top="232" - width="64" /> - <check_box - height="24" + top_pad="5" + width="80" /> + <button + follows="left|bottom" + height="28" + image_selected="eye_button_active.tga" + image_unselected="eye_button_inactive.tga" + layout="topleft" + left_pad="50" + top_delta="3" + name="Pipette" + width="28" /> + <check_box + follows="left|bottom" + height="20" initial_value="true" - label="Show Folders" + label="Apply now" layout="topleft" - left="175" - name="show_folders_check" - top="20" - width="201" /> + left="4" + name="apply_immediate_check" + top="262" + width="120" /> <filter_editor follows="left|top|right" - height="16" - label="Type here to search" + height="23" + label="Filter textures" layout="topleft" - left_delta="0" + left="175" name="inventory search editor" - top_delta="0" + top="20" width="231" /> <inventory_panel allow_multi_select="false" - border="true" - follows="left|top|right|bottom" - height="216" + bg_visible="true" + bg_alpha_color="DkGray2" + border="false" + follows="all" + height="200" layout="topleft" left_delta="0" name="inventory panel" top_pad="4" width="231" /> - <check_box - follows="left|bottom" - height="20" - initial_value="true" - label="Apply Immediately" - layout="topleft" - left="4" - name="apply_immediate_check" - top="262" - width="150" /> - <button - follows="left|bottom" - height="32" - image_selected="eye_button_active.tga" - image_unselected="eye_button_inactive.tga" + <check_box + height="14" + initial_value="false" + label="Show folders" layout="topleft" - left="139" - name="Pipette" - picture_style="true" - top="250" - width="32" /> - <button + name="show_folders_check" + top_pad="0" + left_delta="-3" + width="200" /> + <button follows="right|bottom" height="20" - label="Cancel" - label_selected="Cancel" + label="Ok" + label_selected="Ok" layout="topleft" - left="186" - name="Cancel" - top="262" + right="-120" + name="Select" width="100" /> <button follows="right|bottom" height="20" - label="Select" - label_selected="Select" + label="Cancel" + label_selected="Cancel" layout="topleft" - left_pad="4" - name="Select" - top_delta="0" + right="-10" + left_pad="5" + name="Cancel" width="100" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index f566dbdb75..c33d7cf31d 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -9,7 +9,7 @@ name="toolbox floater" help_topic="toolbox_floater" save_rect="true" - short_title="Build Tools" + short_title="BUILD TOOLS" single_instance="true" sound_flags="0" width="280"> @@ -75,7 +75,6 @@ layout="topleft" left="10" name="button focus" - picture_style="true" tool_tip="Focus" width="20"> <button.commit_callback @@ -92,7 +91,6 @@ layout="topleft" left_pad="20" name="button move" - picture_style="true" tool_tip="Move" width="20"> <button.commit_callback @@ -109,7 +107,6 @@ layout="topleft" left_pad="20" name="button edit" - picture_style="true" tool_tip="Edit" width="20"> <button.commit_callback @@ -126,7 +123,6 @@ layout="topleft" left_pad="20" name="button create" - picture_style="true" tool_tip="Create" width="20"> <button.commit_callback @@ -143,7 +139,6 @@ layout="topleft" left_pad="20" name="button land" - picture_style="true" tool_tip="Land" width="20"> <button.commit_callback @@ -320,8 +315,6 @@ image_disabled="ForwardArrow_Disabled" image_selected="ForwardArrow_Press" image_unselected="ForwardArrow_Off" - picture_style="true" - label_selected="Options" layout="topleft" name="Options..." tool_tip="Grid options" @@ -342,7 +335,6 @@ layout="topleft" left="4" name="ToolCube" - picture_style="true" tool_tip="Cube" top="51" width="20" /> @@ -356,7 +348,6 @@ layout="topleft" left_delta="26" name="ToolPrism" - picture_style="true" tool_tip="Prism" top_delta="0" width="20" /> @@ -370,7 +361,6 @@ layout="topleft" left_delta="26" name="ToolPyramid" - picture_style="true" tool_tip="Pyramid" top_delta="0" width="20" /> @@ -384,7 +374,6 @@ layout="topleft" left_delta="26" name="ToolTetrahedron" - picture_style="true" tool_tip="Tetrahedron" top_delta="0" width="20" /> @@ -398,7 +387,6 @@ layout="topleft" left_delta="26" name="ToolCylinder" - picture_style="true" tool_tip="Cylinder" top_delta="0" width="20" /> @@ -412,7 +400,6 @@ layout="topleft" left_delta="26" name="ToolHemiCylinder" - picture_style="true" tool_tip="Hemicylinder" top_delta="0" width="20" /> @@ -426,7 +413,6 @@ layout="topleft" left_delta="26" name="ToolCone" - picture_style="true" tool_tip="Cone" top_delta="0" width="20" /> @@ -440,7 +426,6 @@ layout="topleft" left_delta="26" name="ToolHemiCone" - picture_style="true" tool_tip="Hemicone" top_delta="0" width="20" /> @@ -454,7 +439,6 @@ layout="topleft" left_delta="26" name="ToolSphere" - picture_style="true" tool_tip="Sphere" top_delta="0" width="20" /> @@ -468,7 +452,6 @@ layout="topleft" left_delta="26" name="ToolHemiSphere" - picture_style="true" tool_tip="Hemisphere" top_delta="0" width="20" /> @@ -482,7 +465,6 @@ layout="topleft" left="4" name="ToolTorus" - picture_style="true" tool_tip="Torus" top="77" width="20" /> @@ -496,7 +478,6 @@ layout="topleft" left_delta="26" name="ToolTube" - picture_style="true" tool_tip="Tube" top_delta="0" width="20" /> @@ -510,7 +491,6 @@ layout="topleft" left_delta="26" name="ToolRing" - picture_style="true" tool_tip="Ring" top_delta="0" width="20" /> @@ -524,7 +504,6 @@ layout="topleft" left_delta="26" name="ToolTree" - picture_style="true" tool_tip="Tree" top_delta="0" width="20" /> @@ -538,7 +517,6 @@ layout="topleft" left_delta="26" name="ToolGrass" - picture_style="true" tool_tip="Grass" top_delta="0" width="20" /> @@ -927,7 +905,6 @@ left_pad="0" top_delta="0" name="button set group" - picture_style="true" tab_stop="false" tool_tip="Choose a group to share this object's permissions" width="10" /> @@ -1034,8 +1011,11 @@ label="Original" value="1" /> </combo_box> -<!-- NEW PRICE SPINNER --> - <spinner +<!-- NEW PRICE SPINNER +Objects are allowed to be for sale for L$0 to invoke buy UI behavior +even though the user gets a free copy. +--> + <spinner follows="left|top" decimal_digits="0" increment="1" @@ -1046,7 +1026,7 @@ label="Price: L$" label_width="65" width="150" - min_val="1" + min_val="0" height="20" max_val="999999999" /> <check_box @@ -2700,7 +2680,6 @@ layout="topleft" left_pad="0" name="add_media" - picture_style="true" tab_stop="false" top_delta="0" tool_tip="Add Media" @@ -2716,7 +2695,6 @@ layout="topleft" left_pad="5" name="delete_media" - picture_style="true" tool_tip="Delete this media texture" top_delta="0" width="18"> @@ -2733,7 +2711,6 @@ layout="topleft" left_pad="10" name="edit_media" - picture_style="true" top_delta="0" width="18"> <button.commit_callback @@ -2793,7 +2770,7 @@ left_pad="8" name="button permissions" width="130" /> - <panel_inventory + <panel_inventory_object follows="left|top" height="210" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_top_objects.xml b/indra/newview/skins/default/xui/en/floater_top_objects.xml index 2f53422d51..d2db26daec 100644 --- a/indra/newview/skins/default/xui/en/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/en/floater_top_objects.xml @@ -8,7 +8,7 @@ min_width="450" name="top_objects" help_topic="top_objects" - title="loading..." + title="LOADING..." width="550"> <floater.string name="top_scripts_title"> diff --git a/indra/newview/skins/default/xui/en/floater_ui_preview.xml b/indra/newview/skins/default/xui/en/floater_ui_preview.xml index 380e51977f..8b2136c2dc 100644 --- a/indra/newview/skins/default/xui/en/floater_ui_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_ui_preview.xml @@ -9,7 +9,7 @@ name="gui_preview_tool" help_topic="gui_preview_tool" single_instance="true" - title="XUI Preview Tool" + title="XUI PREVIEW TOOL" width="750"> <panel bottom="640" diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml index 012b69c3e3..b13a11c05d 100644 --- a/indra/newview/skins/default/xui/en/floater_water.xml +++ b/indra/newview/skins/default/xui/en/floater_water.xml @@ -6,7 +6,7 @@ name="Water Floater" help_topic="water_floater" save_rect="true" - title="Advanced Water Editor" + title="ADVANCED WATER EDITOR" width="700"> <floater.string name="WLDefaultWaterNames"> @@ -16,7 +16,7 @@ type="string" length="1" follows="left|top|right" - font="SansSerif" + font.style="BOLD" height="16" layout="topleft" left="10" @@ -28,7 +28,7 @@ <combo_box height="18" layout="topleft" - left_delta="110" + left_pad="10" name="WaterPresetsCombo" top_delta="-2" width="150" /> @@ -40,7 +40,7 @@ left_pad="20" name="WaterNewPreset" top_delta="1" - width="70" /> + width="90" /> <button height="20" label="Save" @@ -49,7 +49,7 @@ left_pad="10" name="WaterSavePreset" top_delta="0" - width="70" /> + width="90" /> <button height="20" label="Delete" @@ -58,8 +58,9 @@ left_pad="10" name="WaterDeletePreset" top_delta="0" - width="70" /> + width="90" /> <tab_container + border="false" follows="left|top" height="180" halign="center" @@ -67,20 +68,20 @@ left="0" name="Water Tabs" tab_position="top" - tab_height="20" top="60" width="700"> <panel border="true" - follows="left|top|right|bottom" + border_color="EmphasisColor" + follows="all" height="180" label="Settings" layout="topleft" - left="1" + left="0" mouse_opaque="false" help_topic="water_settings_tab" name="Settings" - top="60" + top="0" width="698"> <text type="string" @@ -92,11 +93,10 @@ left="10" name="BHText" top="4" - width="355"> + width="200"> Water Fog Color </text> <color_swatch - border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" color="0.5 0.5 0.5 1" follows="left|top" @@ -117,7 +117,7 @@ left="10" name="WaterFogDensText" top="74" - width="355"> + width="200"> Fog Density Exponent </text> <slider @@ -142,7 +142,7 @@ left_delta="-14" name="WaterUnderWaterFogModText" top_delta="4" - width="355"> + width="200"> Underwater Fog Modifier </text> <slider @@ -167,83 +167,44 @@ left="245" name="BDensText" top="4" - width="355"> + width="200"> Reflection Wavelet Scale </text> - <text - type="string" - length="1" - follows="left|top|right" - halign="center" - height="16" - layout="topleft" - left="245" - name="BHText2" - top="21" - width="10"> - 1 - </text> - <text - type="string" - length="1" - follows="left|top|right" - halign="center" - height="16" - layout="topleft" - left_delta="0" - name="BHText3" - top_delta="11" - width="10"> - 2 - </text> - <text - type="string" - length="1" - follows="left|top|right" - halign="center" - height="16" - layout="topleft" - left_delta="0" - name="BHText4" - top_delta="11" - width="10"> - 3 - </text> <slider control_name="WaterNormalScaleX" decimal_digits="1" follows="left" - height="10" + height="15" initial_value="0.7" + label="1" layout="topleft" - left_pad="4" max_val="10" name="WaterNormalScaleX" - top_delta="-3" + top_pad="20" width="200" /> <slider control_name="WaterNormalScaleY" decimal_digits="1" follows="left" - height="10" + height="15" initial_value="0.7" + label="2" layout="topleft" - left_delta="0" max_val="10" name="WaterNormalScaleY" - top_pad="1" + top_pad="0" width="200" /> <slider control_name="WaterNormalScaleZ" decimal_digits="1" follows="left" - height="10" + height="15" initial_value="0.7" + label="3" layout="topleft" - left_delta="0" max_val="10" name="WaterNormalScaleZ" - top_pad="1" + top_pad="0" width="200" /> <text type="string" @@ -252,10 +213,9 @@ font="SansSerif" height="16" layout="topleft" - left_delta="-14" name="HDText" - top_delta="2" - width="355"> + top_pad="-10" + width="200"> Fresnel Scale </text> <slider @@ -266,9 +226,8 @@ increment="0.01" initial_value="0.7" layout="topleft" - left="259" name="WaterFresnelScale" - top="100" + top_pad="20" width="200" /> <text type="string" @@ -277,10 +236,9 @@ font="SansSerif" height="16" layout="topleft" - left_delta="-14" name="FresnelOffsetText" - top_delta="-1" - width="355"> + top_pad="-10" + width="200"> Fresnel Offset </text> <slider @@ -291,9 +249,8 @@ increment="0.01" initial_value="0.7" layout="topleft" - left="259" name="WaterFresnelOffset" - top="135" + top_pad="20" width="200" /> <text type="string" @@ -305,7 +262,7 @@ left="480" name="DensMultText" top="4" - width="355"> + width="200"> Refract Scale Above </text> <slider @@ -330,7 +287,7 @@ left_delta="-14" name="WaterScaleBelowText" top_delta="-3" - width="355"> + width="200"> Refract Scale Below </text> <slider @@ -355,7 +312,7 @@ left_delta="-14" name="MaxAltText" top_delta="-2" - width="355"> + width="200"> Blur Multiplier </text> <slider @@ -373,15 +330,15 @@ </panel> <panel border="true" - follows="left|top|right|bottom" + follows="all" height="180" label="Image" layout="topleft" - left_delta="0" + left="0" mouse_opaque="false" help_topic="water_waves_tab" name="Waves" - top_delta="44" + top="0" width="698"> <text type="string" @@ -392,8 +349,8 @@ layout="topleft" left="10" name="BHText" - top="4" - width="355"> + top="10" + width="200"> Big Wave Direction </text> <text @@ -405,7 +362,7 @@ layout="topleft" left="10" name="WaterWave1DirXText" - top="21" + top_pad="4" width="10"> X </text> @@ -418,7 +375,7 @@ layout="topleft" left_delta="0" name="WaterWave1DirYText" - top_delta="11" + top_delta="18" width="10"> Y </text> @@ -434,7 +391,7 @@ max_val="4" min_val="-4" name="WaterWave1DirX" - top="40" + top="55" width="200" /> <slider control_name="WaterWave1DirY" @@ -448,7 +405,7 @@ max_val="4" min_val="-4" name="WaterWave1DirY" - top_pad="1" + top_pad="5" width="200" /> <text type="string" @@ -472,7 +429,7 @@ layout="topleft" left="10" name="WaterWave2DirXText" - top="71" + top="90" width="10"> X </text> @@ -485,7 +442,7 @@ layout="topleft" left_delta="0" name="WaterWave2DirYText" - top_delta="11" + top_delta="20" width="10"> Y </text> @@ -501,7 +458,7 @@ max_val="4" min_val="-4" name="WaterWave2DirX" - top="90" + top="115" width="200" /> <slider control_name="WaterWave2DirY" @@ -515,7 +472,7 @@ max_val="4" min_val="-4" name="WaterWave2DirY" - top_pad="1" + top_pad="10" width="200" /> <text type="string" @@ -527,7 +484,7 @@ left="240" name="BHText3" top="4" - width="355"> + width="200"> Normal Map </text> <texture_picker diff --git a/indra/newview/skins/default/xui/en/floater_windlight_options.xml b/indra/newview/skins/default/xui/en/floater_windlight_options.xml index fd905d7a14..0cb7814c6a 100644 --- a/indra/newview/skins/default/xui/en/floater_windlight_options.xml +++ b/indra/newview/skins/default/xui/en/floater_windlight_options.xml @@ -6,7 +6,7 @@ name="WindLight floater" help_topic="windlight_floater" save_rect="true" - title="Advanced Sky Editor" + title="ADVANCED SKY EDITOR" width="700"> <floater.string name="WLDefaultSkyNames"> diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 93755fa253..387ffbd5b3 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -13,40 +13,17 @@ save_rect="true" save_visibility="true" single_instance="true" - title="World Map" + title="WORLD MAP" width="800"> - <tab_container + <panel + filename="panel_world_map.xml" follows="left|top|right|bottom" height="565" layout="topleft" left="15" - name="maptab" - tab_position="top" + name="objects_mapview" top="25" - width="542"> - <panel - filename="panel_world_map.xml" - follows="left|top|right|bottom" - height="550" - label="Objects" - layout="topleft" - left="1" - help_topic="worldmap_objects_tab" - name="objects_mapview" - top="19" - width="540" /> - <panel - filename="panel_world_map.xml" - follows="left|top|right|bottom" - height="550" - label="Terrain" - layout="topleft" - left_delta="0" - help_topic="worldmap_terrain_tab" - name="terrain_mapview" - top_delta="3" - width="540" /> - </tab_container> + width="542" /> <icon follows="top|right" height="16" @@ -210,7 +187,7 @@ label="Telehub" layout="topleft" left_pad="4" - name="telehubchk" + name="telehub_chk" top_delta="0" width="110" /> <icon diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index 65dfb13f4a..f3da62a896 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -150,11 +150,9 @@ comment="Size of large font (points, or 1/72 of an inch)" size="10.0" /> - <!-- Changed Medium size to address menu font size not matching spec. - May want to revert/update after menu font configuration has been enabled. --> <font_size name="Medium" comment="Size of medium font (points, or 1/72 of an inch)" - size="8.0" + size="9.0" /> <font_size name="Small" comment="Size of small font (points, or 1/72 of an inch)" diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index 6b13e2f1c7..2c1e2b6dc0 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -102,7 +102,6 @@ left_pad="0" top_delta="4" name="mute_btn" - picture_style="true" width="16" /> <avatar_icon follows="all" @@ -122,12 +121,13 @@ image_unselected="ForwardArrow_Off" layout="topleft" name="view_profile_btn" - picture_style="true" right="-8" top="35" left_delta="110" tab_stop="false" width="18" /> + <!-- Overlapping buttons for default actions + llinspectavatar.cpp makes visible the most likely default action --> <button follows="bottom|left" height="23" @@ -136,6 +136,16 @@ top="246" name="add_friend_btn" width="100" /> + <button + follows="bottom|left" + height="23" + label="IM" + left_delta="0" + top_delta="0" + name="im_btn" + width="100" + commit_callback.function="InspectAvatar.IM" + /> <menu_button follows="top|left" height="18" @@ -144,7 +154,6 @@ image_unselected="OptionsMenu_Off" menu_filename="menu_inspect_avatar_gear.xml" name="gear_btn" - picture_style="true" right="-10" top="249" width="18" /> @@ -157,7 +166,6 @@ image_unselected="OptionsMenu_Off" menu_filename="menu_inspect_self_gear.xml" name="gear_self_btn" - picture_style="true" right="-10" top="249" width="18" /> diff --git a/indra/newview/skins/default/xui/en/inspect_group.xml b/indra/newview/skins/default/xui/en/inspect_group.xml index db12daa6e0..e5e5007c56 100644 --- a/indra/newview/skins/default/xui/en/inspect_group.xml +++ b/indra/newview/skins/default/xui/en/inspect_group.xml @@ -73,6 +73,8 @@ L$123 to join name="group_icon" top="24" width="38" /> + <!-- Must be tab_stop="true" so something can hold focus even when the + other buttons are disabled or invisible, otherwise inspector closes --> <button follows="top|left" height="18" @@ -80,11 +82,10 @@ L$123 to join image_selected="ForwardArrow_Press" image_unselected="ForwardArrow_Off" name="view_profile_btn" - picture_style="true" right="-8" top="35" left_delta="110" - tab_stop="false" + tab_stop="true" width="18" commit_callback.function="InspectGroup.ViewProfile" /> <button diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml index fe492e0ae8..1365a0483f 100644 --- a/indra/newview/skins/default/xui/en/inspect_object.xml +++ b/indra/newview/skins/default/xui/en/inspect_object.xml @@ -151,10 +151,11 @@ This is a really long description for an object being as how it is at least 80 c width="75" /> <icon name="secure_browsing" - image_name="map_infohub.tga" + image_name="Lock" left_delta="80" - width="16" - height="16" + visible="false" + width="18" + height="18" top_delta="2" tool_tip="Secure Browsing" follows="left|top"/> @@ -168,7 +169,6 @@ This is a really long description for an object being as how it is at least 80 c image_unselected="OptionsMenu_Off" menu_filename="menu_inspect_object_gear.xml" name="gear_btn" - picture_style="true" right="-10" top_delta="5" width="18" /> @@ -180,7 +180,6 @@ This is a really long description for an object being as how it is at least 80 c image_unselected="ForwardArrow_Off" layout="topleft" name="more_info_btn" - picture_style="true" right="-5" top="20" left_delta="110" diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml index 6049476a43..590621062c 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml @@ -7,7 +7,6 @@ name="Gear Menu">
<menu_item_call
label="View Profile"
- layout="topleft"
enabled="true"
name="view_profile">
<menu_item_call.on_click
@@ -15,49 +14,42 @@ </menu_item_call>
<menu_item_call
label="Add Friend"
- layout="topleft"
name="add_friend">
<menu_item_call.on_click
function="InspectAvatar.AddFriend"/>
</menu_item_call>
<menu_item_call
label="IM"
- layout="topleft"
name="im">
<menu_item_call.on_click
function="InspectAvatar.IM"/>
</menu_item_call>
<menu_item_call
label="Call"
- layout="topleft"
enabled="true"
name="call">
</menu_item_call>
<menu_item_call
label="Teleport"
- layout="topleft"
name="teleport">
<menu_item_call.on_click
function="InspectAvatar.Teleport"/>
</menu_item_call>
<menu_item_call
label="Invite to Group"
- layout="topleft"
name="invite_to_group">
<menu_item_call.on_click
function="InspectAvatar.InviteToGroup"/>
</menu_item_call>
- <menu_item_separator layout="topleft" />
+ <menu_item_separator />
<menu_item_call
label="Block"
- layout="topleft"
name="block">
<menu_item_call.on_click
function="InspectAvatar.Block"/>
</menu_item_call>
<menu_item_call
label="Report"
- layout="topleft"
name="report">
<menu_item_call.on_click
function="InspectAvatar.Report"/>
@@ -88,7 +80,6 @@ </menu_item_call>
<menu_item_call
label="Find On Map"
- layout="topleft"
name="find_on_map">
<menu_item_call.on_click
function="InspectAvatar.FindOnMap"/>
@@ -97,16 +88,16 @@ </menu_item_call>
<menu_item_call
label="Zoom In"
- layout="topleft"
name="zoom_in">
<menu_item_call.on_click
function="InspectAvatar.ZoomIn"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleZoomIn"/>
</menu_item_call>
<menu_item_call
label="Pay"
- layout="topleft"
name="pay">
<menu_item_call.on_click
function="InspectAvatar.Pay"/>
</menu_item_call>
-</menu>
\ No newline at end of file +</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml index 93c53981f3..04a247fd54 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml @@ -73,7 +73,7 @@ <menu_item_call label="Edit" layout="topleft" - name="report"> + name="edit"> <menu_item_call.on_click function="Object.Edit" /> <menu_item_call.on_enable diff --git a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml index 240822e5ca..3d65878cf8 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml @@ -1,53 +1,49 @@ -<?xml version="1.0" encoding="utf-8"?>
-<menu
- create_jump_keys="true"
- layout="topleft"
- mouse_opaque="false"
- visible="false"
- name="Gear Menu">
- <menu_item_call
- label="Stand Up"
- layout="topleft"
- enabled="true"
- name="stand_up">
- <menu_item_call.on_click
- function="Self.StandUp"
- parameter="" />
- <menu_item_call.on_visible
- function="Self.VisibleStandUp" />
- </menu_item_call>
- <menu_item_call
- label="My Appearance"
- layout="topleft"
- name="my_appearance">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="appearance" />
- <menu_item_call.on_enable
- function="Edit.EnableCustomizeAvatar" />
- </menu_item_call>
- <menu_item_call
- label="My Profile"
- layout="topleft"
- enabled="true"
- name="my_profile">
- <menu_item_call.on_click
- function="ShowAgentProfile"
- parameter="agent" />
- </menu_item_call>
- <menu_item_call
- label="My Friends"
- layout="topleft"
- name="my_friends">
- <menu_item_call.on_click
- function="Self.Friends"
- parameter="" />
- </menu_item_call>
- <menu_item_call
- label="My Groups"
- layout="topleft"
- name="my_groups">
- <menu_item_call.on_click
- function="Self.Groups" />
- </menu_item_call>
-</menu>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8"?> +<menu + create_jump_keys="true" + layout="topleft" + mouse_opaque="false" + visible="false" + name="Gear Menu"> + <menu_item_call + label="Stand Up" + enabled="true" + name="stand_up"> + <menu_item_call.on_click + function="Self.StandUp" + parameter="" /> + <menu_item_call.on_visible + function="Self.VisibleStandUp" /> + </menu_item_call> + <menu_item_call + label="My Appearance" + name="my_appearance"> + <menu_item_call.on_click + function="ShowFloater" + parameter="appearance" /> + <menu_item_call.on_enable + function="Edit.EnableCustomizeAvatar" /> + </menu_item_call> + <menu_item_call + label="My Profile" + enabled="true" + name="my_profile"> + <menu_item_call.on_click + function="ShowAgentProfile" + parameter="agent" /> + </menu_item_call> + <menu_item_call + label="My Friends" + name="my_friends"> + <menu_item_call.on_click + function="SideTray.PanelPeopleTab" + parameter="friends_panel" /> + </menu_item_call> + <menu_item_call + label="My Groups" + name="my_groups"> + <menu_item_call.on_click + function="SideTray.PanelPeopleTab" + parameter="groups_panel" /> + </menu_item_call> +</menu> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 62940b87dc..8b6ab4e4d8 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -553,6 +553,16 @@ <menu_item_separator layout="topleft" /> <menu_item_call + label="Save As" + layout="topleft" + name="Save As"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="save_as" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call label="Detach From Yourself" layout="topleft" name="Detach From Yourself"> diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml new file mode 100644 index 0000000000..b07a8bb512 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml @@ -0,0 +1,229 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu + layout="topleft" + left="0" + mouse_opaque="false" + name="menu_inventory_add" + visible="false"> + <menu + create_jump_keys="true" + label="Upload" + layout="topleft" + name="upload" + tear_off="true"> + <menu_item_call + label="Image (L$[COST])..." + layout="topleft" + name="Upload Image" + shortcut="control|U"> + <menu_item_call.on_click + function="File.UploadImage" + parameter="" /> + <menu_item_call.on_enable + function="File.EnableUpload" /> + </menu_item_call> + <menu_item_call + label="Sound (L$[COST])..." + layout="topleft" + name="Upload Sound"> + <menu_item_call.on_click + function="File.UploadSound" + parameter="" /> + <menu_item_call.on_enable + function="File.EnableUpload" /> + </menu_item_call> + <menu_item_call + label="Animation (L$[COST])..." + layout="topleft" + name="Upload Animation"> + <menu_item_call.on_click + function="File.UploadAnim" + parameter="" /> + <menu_item_call.on_enable + function="File.EnableUpload" /> + </menu_item_call> + <menu_item_call + label="Bulk (L$[COST] per file)..." + layout="topleft" + name="Bulk Upload"> + <menu_item_call.on_click + function="File.UploadBulk" + parameter="" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + </menu> + + <menu_item_call + label="New Folder" + layout="topleft" + name="New Folder"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="category" /> + </menu_item_call> + <menu_item_call + label="New Script" + layout="topleft" + name="New Script"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="lsl" /> + </menu_item_call> + <menu_item_call + label="New Note" + layout="topleft" + name="New Note"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="notecard" /> + </menu_item_call> + <menu_item_call + label="New Gesture" + layout="topleft" + name="New Gesture"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="gesture" /> + </menu_item_call> + <menu + height="175" + label="New Clothes" + layout="topleft" + left_delta="0" + mouse_opaque="false" + name="New Clothes" + top_pad="514" + width="125"> + <menu_item_call + label="New Shirt" + layout="topleft" + name="New Shirt"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="shirt" /> + </menu_item_call> + <menu_item_call + label="New Pants" + layout="topleft" + name="New Pants"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="pants" /> + </menu_item_call> + <menu_item_call + label="New Shoes" + layout="topleft" + name="New Shoes"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="shoes" /> + </menu_item_call> + <menu_item_call + label="New Socks" + layout="topleft" + name="New Socks"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="socks" /> + </menu_item_call> + <menu_item_call + label="New Jacket" + layout="topleft" + name="New Jacket"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="jacket" /> + </menu_item_call> + <menu_item_call + label="New Skirt" + layout="topleft" + name="New Skirt"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="skirt" /> + </menu_item_call> + <menu_item_call + label="New Gloves" + layout="topleft" + name="New Gloves"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="gloves" /> + </menu_item_call> + <menu_item_call + label="New Undershirt" + layout="topleft" + name="New Undershirt"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="undershirt" /> + </menu_item_call> + <menu_item_call + label="New Underpants" + layout="topleft" + name="New Underpants"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="underpants" /> + </menu_item_call> + <menu_item_call + label="New Alpha" + layout="topleft" + name="New Alpha"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="alpha" /> + </menu_item_call> + <menu_item_call + label="New Tattoo" + layout="topleft" + name="New Tattoo"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="tattoo" /> + </menu_item_call> + </menu> + <menu + height="85" + label="New Body Parts" + layout="topleft" + left_delta="0" + mouse_opaque="false" + name="New Body Parts" + top_pad="514" + width="118"> + <menu_item_call + label="New Shape" + layout="topleft" + name="New Shape"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="shape" /> + </menu_item_call> + <menu_item_call + label="New Skin" + layout="topleft" + name="New Skin"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="skin" /> + </menu_item_call> + <menu_item_call + label="New Hair" + layout="topleft" + name="New Hair"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="hair" /> + </menu_item_call> + <menu_item_call + label="New Eyes" + layout="topleft" + name="New Eyes"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="eyes" /> + </menu_item_call> + </menu> +</menu>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml new file mode 100644 index 0000000000..435a3e6d34 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu + bottom="806" + layout="topleft" + left="0" + mouse_opaque="false" + name="menu_gear_default" + visible="false"> + <menu_item_call + label="New Inventory Window" + layout="topleft" + name="new_window"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="new_window" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Sort by Name" + layout="topleft" + name="sort_by_name"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="sort_by_name" /> + </menu_item_call> + <menu_item_call + label="Sort by Most Recent" + layout="topleft" + name="sort_by_recent"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="sort_by_recent" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Show Filters" + layout="topleft" + name="show_filters"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="show_filters" /> + </menu_item_call> + <menu_item_call + label="Reset Filters" + layout="topleft" + name="reset_filters"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="reset_filters" /> + </menu_item_call> + <menu_item_call + label="Close All Folders" + layout="topleft" + name="close_folders"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="close_folders" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Empty Trash" + layout="topleft" + name="empty_trash"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="empty_trash" /> + </menu_item_call> + <menu_item_call + label="Empty Lost and Found" + layout="topleft" + name="empty_lostnfound"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="empty_lostnfound" /> + </menu_item_call> + <menu_item_call + label="Save Texture As" + layout="topleft" + name="Save Texture As"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="save_texture" /> + <on_enable + function="Inventory.GearDefault.Enable" + parameter="save_texture" /> + </menu_item_call> +</menu> diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index c3ee6e250b..5eb0560962 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -10,22 +10,18 @@ <menu create_jump_keys="true" label="Me" - layout="topleft" name="File"> <menu_item_call label="Preferences" - layout="topleft" name="Preferences..." shortcut="control|P"> <menu_item_call.on_click function="ShowFloater" parameter="preferences" /> </menu_item_call> - <menu_item_separator - layout="topleft" /> + <menu_item_separator /> <menu_item_call label="Quit [APP_NAME]" - layout="topleft" name="Quit" shortcut="control|Q"> <menu_item_call.on_click @@ -36,7 +32,6 @@ <menu create_jump_keys="true" label="Edit" - layout="topleft" name="Edit" width="153"> </menu> @@ -44,22 +39,18 @@ <menu create_jump_keys="true" label="Help" - layout="topleft" name="Help"> <menu_item_call label="[SECOND_LIFE] Help" - layout="topleft" name="Second Life Help" shortcut="F1"> <menu_item_call.on_click function="ShowFloater" parameter="help f1" /> </menu_item_call> - <menu_item_separator - layout="topleft" /> + <menu_item_separator /> <menu_item_call label="About [APP_NAME]" - layout="topleft" name="About Second Life"> <menu_item_call.on_click function="ShowFloater" @@ -69,7 +60,6 @@ <menu create_jump_keys="true" label="Debug" - layout="topleft" name="Debug" tear_off="true"> <!-- Need a copy of the edit menu here so keyboard shortcuts like @@ -78,12 +68,10 @@ <menu create_jump_keys="true" label="Edit" - layout="topleft" name="Edit" tear_off="true"> <menu_item_call label="Undo" - layout="topleft" name="Undo" shortcut="control|Z"> <menu_item_call.on_click @@ -93,7 +81,6 @@ </menu_item_call> <menu_item_call label="Redo" - layout="topleft" name="Redo" shortcut="control|Y"> <menu_item_call.on_click @@ -101,11 +88,9 @@ <menu_item_call.on_enable function="Edit.EnableRedo" /> </menu_item_call> - <menu_item_separator - layout="topleft" /> + <menu_item_separator /> <menu_item_call label="Cut" - layout="topleft" name="Cut" shortcut="control|X"> <menu_item_call.on_click @@ -115,7 +100,6 @@ </menu_item_call> <menu_item_call label="Copy" - layout="topleft" name="Copy" shortcut="control|C"> <menu_item_call.on_click @@ -125,7 +109,6 @@ </menu_item_call> <menu_item_call label="Paste" - layout="topleft" name="Paste" shortcut="control|V"> <menu_item_call.on_click @@ -135,7 +118,6 @@ </menu_item_call> <menu_item_call label="Delete" - layout="topleft" name="Delete" shortcut="Del"> <menu_item_call.on_click @@ -145,7 +127,6 @@ </menu_item_call> <menu_item_call label="Duplicate" - layout="topleft" name="Duplicate" shortcut="control|D"> <menu_item_call.on_click @@ -153,11 +134,9 @@ <menu_item_call.on_enable function="Edit.EnableDuplicate" /> </menu_item_call> - <menu_item_separator - layout="topleft" /> + <menu_item_separator /> <menu_item_call label="Select All" - layout="topleft" name="Select All" shortcut="control|A"> <menu_item_call.on_click @@ -167,7 +146,6 @@ </menu_item_call> <menu_item_call label="Deselect" - layout="topleft" name="Deselect" shortcut="control|E"> <menu_item_call.on_click @@ -179,7 +157,6 @@ <menu_item_separator /> <menu_item_call label="Show Debug Settings" - layout="topleft" name="Debug Settings"> <menu_item_call.on_click function="Advanced.ShowDebugSettings" @@ -187,7 +164,6 @@ </menu_item_call> <menu_item_call label="UI/Color Settings" - layout="topleft" name="UI/Color Settings"> <menu_item_call.on_click function="Advanced.ShowDebugSettings" @@ -196,7 +172,6 @@ <menu_item_separator /> <menu_item_call label="XUI Preview Tool" - layout="topleft" name="UI Preview Tool" shortcut="control|T"> <menu_item_call.on_click @@ -205,33 +180,23 @@ </menu_item_call> <menu_item_separator /> <menu_item_call - label="Widget Test" - layout="topleft" - name="Widget Test" - shortcut="control|shift|T"> - <menu_item_call.on_click - function="ShowFloater" - parameter="test_widgets" /> - </menu_item_call> - <menu_item_call - label="Inspectors Test" - name="inspectors_test" - shortcut="control|shift|I" - > - <menu_item_call.on_click - function="ShowFloater" - parameter="test_inspectors" /> - </menu_item_call> - <menu_item_call label="Show Side Tray" name="Show Side Tray"> <menu_item_call.on_click function="Advanced.ShowSideTray" /> </menu_item_call> + <menu_item_check + label="Reg In Client Test (restart)" + name="Reg In Client Test (restart)"> + <menu_item_check.on_check + control="RegInClient" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="RegInClient" /> + </menu_item_check> <menu_item_separator /> <menu_item_call label="Show TOS" - layout="topleft" name="TOS"> <menu_item_call.on_click function="ShowFloater" @@ -239,7 +204,6 @@ </menu_item_call> <menu_item_call label="Show Critical Message" - layout="topleft" name="Critical"> <menu_item_call.on_click function="ShowFloater" diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml index eedb4383bb..f1117d1419 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml @@ -31,9 +31,6 @@ function="CheckControl" parameter="FriendsListShowIcons" /> </menu_item_check> - <menu_item_call name="organize_offline" label="Organize Offline Friends"> - <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="organize_offline" /> - </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> <menu_item_call.on_click function="SideTray.ShowPanel" parameter="panel_block_list_sidetray" /> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml index 2bec745410..6dd44255bf 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml @@ -13,4 +13,15 @@ function="CheckControl" parameter="GroupListShowIcons" /> </menu_item_check> + <menu_item_check + label="Leave Selected Group" + layout="topleft" + name="Leave Selected Group"> + <menu_item_check.on_click + function="People.Groups.ViewSort.Action" + parameter="show_icons" /> + <menu_item_check.on_check + function="CheckControl" + parameter="GroupListShowIcons" /> + </menu_item_check> </menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml index c002cd078f..39f9e48609 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml @@ -2,15 +2,36 @@ <menu name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false"> - <menu_item_call name="sort_recent" label="Sort by Recent Speakers"> - <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_recent" /> - </menu_item_call> - <menu_item_call name="sort_name" label="Sort by Name"> - <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_name" /> - </menu_item_call> - <menu_item_call name="sort_distance" label="Sort by Distance"> - <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_distance" /> - </menu_item_call> + <menu_item_check + label="Sort by Recent Speakers" + name="sort_by_recent_speakers"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_by_recent_speakers"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_by_recent_speakers"/> + </menu_item_check> + <menu_item_check + label="Sort by Name" + name="sort_name"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_name"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_name"/> + </menu_item_check> + <menu_item_check + label="Sort by Distance" + name="sort_distance"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_distance"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_distance"/> + </menu_item_check> <menu_item_separator layout="topleft" /> <menu_item_check name="view_icons" label="View People Icons"> <menu_item_check.on_click diff --git a/indra/newview/skins/default/xui/en/menu_url_map.xml b/indra/newview/skins/default/xui/en/menu_url_map.xml new file mode 100644 index 0000000000..2ca9e3b3fe --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_url_map.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Url Popup"> + <menu_item_call + label="Show on Map" + layout="topleft" + name="show_on_map"> + <menu_item_call.on_click + function="Url.Execute" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Teleport to Location" + layout="topleft" + name="teleport_to_location"> + <menu_item_call.on_click + function="Url.Teleport" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Copy SLurl to clipboard" + layout="topleft" + name="url_copy"> + <menu_item_call.on_click + function="Url.CopyUrl" /> + </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml index 6f7e659f48..35c2269b0d 100644 --- a/indra/newview/skins/default/xui/en/menu_url_objectim.xml +++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml @@ -12,6 +12,13 @@ <menu_item_separator layout="topleft" /> <menu_item_call + label="Show on Map" + layout="topleft" + name="show_on_map"> + <menu_item_call.on_click + function="Url.ShowOnMap" /> + </menu_item_call> + <menu_item_call label="Teleport to Object Location" layout="topleft" name="teleport_to_object"> diff --git a/indra/newview/skins/default/xui/en/menu_url_parcel.xml b/indra/newview/skins/default/xui/en/menu_url_parcel.xml index 3804f7f780..f477c310fb 100644 --- a/indra/newview/skins/default/xui/en/menu_url_parcel.xml +++ b/indra/newview/skins/default/xui/en/menu_url_parcel.xml @@ -12,6 +12,15 @@ <menu_item_separator layout="topleft" /> <menu_item_call + label="Show on Map" + layout="topleft" + name="show_on_map"> + <menu_item_call.on_click + function="Url.ShowOnMap" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call label="Copy SLurl to clipboard" layout="topleft" name="url_copy"> diff --git a/indra/newview/skins/default/xui/en/menu_url_slurl.xml b/indra/newview/skins/default/xui/en/menu_url_slurl.xml index 58714f1f42..98abc206a5 100644 --- a/indra/newview/skins/default/xui/en/menu_url_slurl.xml +++ b/indra/newview/skins/default/xui/en/menu_url_slurl.xml @@ -12,6 +12,13 @@ <menu_item_separator layout="topleft" /> <menu_item_call + label="Show on Map" + layout="topleft" + name="show_on_map"> + <menu_item_call.on_click + function="Url.ShowOnMap" /> + </menu_item_call> + <menu_item_call label="Teleport to Location" layout="topleft" name="teleport_to_location"> diff --git a/indra/newview/skins/default/xui/en/menu_url_teleport.xml b/indra/newview/skins/default/xui/en/menu_url_teleport.xml index ff52d7e109..289e32bcf4 100644 --- a/indra/newview/skins/default/xui/en/menu_url_teleport.xml +++ b/indra/newview/skins/default/xui/en/menu_url_teleport.xml @@ -12,6 +12,15 @@ <menu_item_separator layout="topleft" /> <menu_item_call + label="Show on Map" + layout="topleft" + name="show_on_map"> + <menu_item_call.on_click + function="Url.ShowOnMap" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call label="Copy SLurl to clipboard" layout="topleft" name="url_copy"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 3f63f493b1..66c9060b06 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -98,6 +98,24 @@ function="World.SetBusy"/> </menu_item_call> </menu> + <menu_item_call + label="Request Admin Status" + layout="topleft" + name="Request Admin Options" + shortcut="control|alt|G" + visible="false"> + <menu_item_call.on_click + function="Advanced.RequestAdminStatus" /> + </menu_item_call> + <menu_item_call + label="Leave Admin Status" + layout="topleft" + name="Leave Admin Options" + shortcut="control|alt|shift|G" + visible="false"> + <menu_item_call.on_click + function="Advanced.LeaveAdminStatus" /> + </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_call @@ -114,25 +132,22 @@ layout="topleft" name="Communicate" tear_off="true"> - <menu_item_check + <menu_item_call label="My Friends" layout="topleft" name="My Friends" shortcut="control|shift|F"> - <menu_item_check.on_check - function="Floater.Visible" - parameter="contacts.friends" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="contacts.friends" /> - </menu_item_check> + <menu_item_call.on_click + function="SideTray.PanelPeopleTab" + parameter="friends_panel" /> + </menu_item_call> <menu_item_call label="My Groups" layout="topleft" name="My Groups"> <menu_item_call.on_click - function="Floater.Show" - parameter="contacts.groups" /> + function="SideTray.PanelPeopleTab" + parameter="groups_panel" /> </menu_item_call> <menu_item_separator layout="topleft" /> @@ -155,18 +170,15 @@ function="Floater.Toggle" parameter="nearby_chat" /> </menu_item_check> - <menu_item_check - label="Nearby Speakers" + <menu_item_call + label="Nearby People" layout="topleft" name="Active Speakers" shortcut="control|shift|A"> - <menu_item_check.on_check - function="Floater.Visible" - parameter="active_speakers" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="active_speakers" /> - </menu_item_check> + <menu_item_call.on_click + function="SideTray.PanelPeopleTab" + parameter="nearby_panel" /> + </menu_item_call> <menu_item_check label="Nearby Media" layout="topleft" @@ -1921,6 +1933,42 @@ parameter="debug" /> </menu_item_check> <menu_item_check + label="Notifications Console" + layout="topleft" + name="Notifications" + shortcut="control|shift|5"> + <menu_item_check.on_check + function="Advanced.CheckConsole" + parameter="notifications" /> + <menu_item_check.on_click + function="Floater.Show" + parameter="notifications_console" /> + </menu_item_check> + <menu_item_check + label="Texture Size Console" + layout="topleft" + name="Texture Size" + shortcut="control|shift|6"> + <menu_item_check.on_check + function="Advanced.CheckConsole" + parameter="texture size" /> + <menu_item_check.on_click + function="Advanced.ToggleConsole" + parameter="texture size" /> + </menu_item_check> + <menu_item_check + label="Texture Category Console" + layout="topleft" + name="Texture Category" + shortcut="control|shift|7"> + <menu_item_check.on_check + function="Advanced.CheckConsole" + parameter="texture category" /> + <menu_item_check.on_click + function="Advanced.ToggleConsole" + parameter="texture category" /> + </menu_item_check> + <menu_item_check label="Fast Timers" layout="topleft" name="Fast Timers" @@ -2477,19 +2525,43 @@ label="Disable Textures" name="Disable Textures"> <menu_item_check.on_check - function="Advanced.CheckDisableTextures" - parameter="DisableTextures" /> + function="CheckControl" + parameter="TextureDisable" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="TextureDisable" /> + </menu_item_check> + <menu_item_check + label="Full Res Textures" + layout="topleft" + name="Rull Res Textures"> + <menu_item_check.on_check + function="CheckControl" + parameter="TextureLoadFullRes" /> <menu_item_check.on_click - function="Advanced.ToggleDisableTextures" /> + function="ToggleControl" + parameter="TextureLoadFullRes" /> + </menu_item_check> + <menu_item_check + label="Audit Textures" + layout="topleft" + name="Audit Textures"> + <menu_item_check.on_check + function="CheckControl" + parameter="AuditTexture" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="AuditTexture" /> </menu_item_check> <menu_item_check label="Texture Atlas" name="Texture Atlas"> <menu_item_check.on_check - function="Advanced.CheckTextureAtlas" + function="CheckControl" parameter="TextureAtlas" /> <menu_item_check.on_click - function="Advanced.ToggleTextureAtlas" /> + function="ToggleControl" + parameter="TextureAtlas" /> </menu_item_check> <menu_item_check label="Render Attached Lights" @@ -2512,8 +2584,8 @@ parameter="RenderAttachedParticles" /> </menu_item_check> <menu_item_check - label="Hover Highlight Objects" - name="Hover Highlight Objects"> + label="Hover Glow Objects" + name="Hover Glow Objects"> <menu_item_check.on_check function="CheckControl" parameter="RenderHighlightEnable" /> diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml index 2de9449ea6..76c0d027f3 100644 --- a/indra/newview/skins/default/xui/en/mime_types.xml +++ b/indra/newview/skins/default/xui/en/mime_types.xml @@ -163,8 +163,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="application/javascript"> <label name="application/javascript_label"> @@ -208,7 +208,7 @@ </mimetype> <mimetype name="application/smil"> <label name="application/smil_label"> - Synchronized Multimedia Integration Language (SMIL) + Synchronized Multimedia Integration Language (SMIL) </label> <widgettype> movie @@ -348,8 +348,8 @@ web </widgettype> <impl> - media_plugin_webkit - </impl> + media_plugin_webkit + </impl> </mimetype> <mimetype menu="1" name="text/plain"> <label name="text/plain_label"> @@ -381,8 +381,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="video/mp4"> <label name="video/mp4_label"> @@ -392,8 +392,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype menu="1" name="video/quicktime"> <label name="video/quicktime_label"> @@ -403,8 +403,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="video/x-ms-asf"> <label name="video/x-ms-asf_label"> @@ -414,8 +414,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="video/x-ms-wmv"> <label name="video/x-ms-wmv_label"> @@ -425,8 +425,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype menu="1" name="video/x-msvideo"> <label name="video/x-msvideo_label"> @@ -436,7 +436,7 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> </mimetypes> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d479acb20c..ccd8bc569e 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4994,7 +4994,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a <notification icon="notify.tga" name="UserGiveItem" - type="notify"> + type="offer"> [NAME] has given you a [OBJECTTYPE] named '[OBJECTNAME]'. <form name="form"> <button @@ -5040,7 +5040,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a <notification icon="notify.tga" name="TeleportOffered" - type="notify"> + type="offer"> [NAME] has offered to teleport you to their location: [MESSAGE] @@ -5077,7 +5077,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a <notification icon="notify.tga" name="OfferFriendship" - type="notify"> + type="offer"> [NAME] is offering friendship. [MESSAGE] @@ -5117,7 +5117,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a <notification icon="notify.tga" name="FriendshipAccepted" - type="notify"> + type="offer"> [NAME] accepted your friendship offer. </notification> @@ -5681,7 +5681,7 @@ An error has occurred while trying to connect to voice chat for [VOICE_CHANNEL_N name="ServerVersionChanged" priority="high" type="notifytip"> -You just entered a region using a different server version, which may affect performance. Click to see the release notes. +You just entered a region using a different server version, which may affect performance. [[URL] View the release notes.] </notification> <notification diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index 18761c3bb9..0c42686531 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -76,7 +76,6 @@ left_pad="3" right="-31" name="info_btn" - picture_style="true" top_delta="-2" width="16" /> <button @@ -87,7 +86,6 @@ left_pad="5" right="-3" name="profile_btn" - picture_style="true" top_delta="-2" width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_avatar_tag.xml b/indra/newview/skins/default/xui/en/panel_avatar_tag.xml index e4f6e7bd44..16c8660781 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_tag.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_tag.xml @@ -55,7 +55,6 @@ top="65" left="10" right="-10" - can_resize="true" height="100" follows="left|top|bottom|right" font="SansSerifSmall" diff --git a/indra/newview/skins/default/xui/en/panel_bars.xml b/indra/newview/skins/default/xui/en/panel_bars.xml index 9c06329eaf..527ec4e007 100644 --- a/indra/newview/skins/default/xui/en/panel_bars.xml +++ b/indra/newview/skins/default/xui/en/panel_bars.xml @@ -5,65 +5,14 @@ layout="topleft" left="0" mouse_opaque="false" - name="bottom_panel" + name="screen" width="1024"> - <panel - follows="left|right|top|bottom" - height="728" - layout="topleft" - left="0" - mouse_opaque="false" - name="status" - top="0" - width="1024" /> - <layout_stack - border_size="0" - follows="left|right|bottom|top" - height="768" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="bar_stack" - top_delta="0" - use_bounding_rect="true" - width="1024"> - <layout_panel - follows="left|right|top|bottom" - height="768" - layout="topleft" - left="0" - mouse_opaque="false" - name="spacer" - top="0" - user_resize="false" - width="1024" /> - <layout_panel - auto_resize="false" - height="200" - layout="topleft" - min_height="200" - mouse_opaque="false" - name="overlay" - use_bounding_rect="true" - user_resize="false" - width="1024" /> - <layout_panel - auto_resize="false" - filename="panel_toolbar.xml" - layout="topleft" - min_height="28" - name="toolbar" - use_bounding_rect="true" - user_resize="false" - width="1024" /> + <layout_stack name="menu_stack" orientation="vertical" height="768" border_size="0"> + <panel auto_resize="false" width="1024" name="status_bar" filename="panel_status_bar.xml"/> + <panel auto_resize="false" width="1024" height="65" name="navigation bar" filename="panel_navigation_bar.xml"/> + <layout_stack name="hud_stack" orientation="horizontal" auto_resize="true" width="1024" height="500" follows="all"> + <panel auto_resize="true" name="floater_view" height="500"/> + <panel auto_resize="false" filename="panel_side_tray.xml" height="500" width="333"/> </layout_stack> - <panel - follows="left|right|top|bottom" - height="728" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="hud" - top_delta="-10" - width="1024" /> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 920593e7ae..f833e0a1cb 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -60,7 +60,7 @@ min_width="96" name="speak_panel" user_resize="false"> - <chiclet_talk + <talk_button follows="right" height="23" speak_button.tab_stop="true" @@ -93,7 +93,7 @@ min_width="76" name="gesture_panel" user_resize="false"> - <gesture_combo_box + <button follows="right" height="23" label="Gesture" @@ -258,11 +258,11 @@ user_resize="false"> <chiclet_notification follows="right" - height="25" + height="23" layout="topleft" left="0" name="sys_well" - top="3" + top="4" width="34"> <button auto_resize="true" @@ -271,8 +271,9 @@ follows="right" flash_color="EmphasisColor" name="Unread" - picture_style="true" - image_overlay="Widget_UpArrow" /> + image_overlay="Notices_Unread" + width="20" + /> <unread_notifications width="34" height="23" @@ -289,6 +290,6 @@ layout="topleft" right="-1" top="0" - width="10"/> + width="26"/> </layout_stack> -</panel>
\ No newline at end of file +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml index a9f622e018..64519b2571 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_header.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml @@ -1,53 +1,44 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel + background_visible="true" + bevel_style="in" + bg_alpha_color="black" follows="left|top|right" - height="57" - label="im_header_container" + height="20" + label="im_header" layout="topleft" - left="8" - name="im_header_container"> - <panel - background_visible="true" - bevel_style="in" - bg_alpha_color="black" - follows="left|top|right" - height="30" - label="im_header" + name="im_header" > + <avatar_icon + follows="left" + height="16" + image_name="icon_avatar_online.tga" layout="topleft" - name="im_header" - top_pad="17"> - <avatar_icon - follows="left" - height="20" - image_name="icon_avatar_online.tga" - layout="topleft" - left="5" - mouse_opaque="true" - name="avatar_icon" - top="5" - width="20" /> - <text - follows="left|right" - font="SansSerifBigBold" - height="20" - layout="topleft" - left_pad="10" - right="-50" - name="user_name" - text_color="white" - top="5" - value="Darth Vader" - use_ellipses="true" /> - <text - follows="right" - font="SansSerifBig" - height="20" - layout="topleft" - name="time_box" - right="0" - text_color="white" - top="5" - value="23:30" - width="50" /> - </panel> + left="2" + mouse_opaque="true" + name="avatar_icon" + top="2" + width="16" /> + <text + follows="left|right" + font="SansSerifBigBold" + height="20" + layout="topleft" + left_pad="6" + right="-50" + name="user_name" + text_color="white" + top="3" + value="Darth Vader" + use_ellipses="true" /> + <text + follows="right" + font="SansSerifBig" + height="20" + layout="topleft" + name="time_box" + right="0" + text_color="white" + top="3" + value="23:30" + width="50" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_chat_separator.xml b/indra/newview/skins/default/xui/en/panel_chat_separator.xml index bacc750e86..d0a2ddb289 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_separator.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_separator.xml @@ -1,16 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel + background_visible="true" + bg_alpha_color="black" follows="left|right|top" - height="9" + height="1" layout="topleft" - left="8" - name="chat_separator_container"> - <panel - background_visible="true" - bg_alpha_color="black" - follows="left|right|top" - height="1" - layout="topleft" - name="chat_separator_panel" - top_pad="3" /> -</panel> + name="chat_separator_panel" /> diff --git a/indra/newview/skins/default/xui/en/panel_edit_eyes.xml b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml index 9789da5796..c514054c41 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_eyes.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml @@ -37,13 +37,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="eyes_main_tab" title="Eyes"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="eyes_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_gloves.xml b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml index 517cdd75fb..f9ef038314 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_gloves.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml @@ -49,13 +49,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="gloves_main_tab" title="Gloves"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="gloves_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_hair.xml b/indra/newview/skins/default/xui/en/panel_edit_hair.xml index d2ee2ebf2a..e7d1c05301 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_hair.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_hair.xml @@ -37,13 +37,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="hair_color_tab" title="Color"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="hair_color_param_list" @@ -51,13 +49,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="hair_style_tab" title="Style"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="hair_style_param_list" @@ -65,13 +61,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="hair_eyebrows_tab" title="Eyebrows"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="hair_eyebrows_param_list" @@ -79,13 +73,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="hair_facial_tab" title="Facial"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="hair_facial_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_jacket.xml b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml index 0b54944e29..f4c03399fe 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_jacket.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml @@ -61,13 +61,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="jacket_main_tab" title="Jacket"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="jacket_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_pants.xml b/indra/newview/skins/default/xui/en/panel_edit_pants.xml index 939314f9f9..ab105afd88 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pants.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pants.xml @@ -49,13 +49,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="pants_main_tab" title="Pants"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="pants_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml index bac6f6e4d1..f4a212ba0a 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml @@ -17,7 +17,6 @@ image_overlay="BackArrow_Off" layout="topleft" name="back_btn" - picture_style="true" left="10" tab_stop="false" top="2" @@ -65,9 +64,9 @@ top="20" left="10" name="pick_snapshot" /> - <button + <icon height="18" - image_overlay="AddItem_Off" + image_name="AddItem_Off" layout="topleft" right="-5" name="edit_icon" diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml index fedc49ae87..2378ae518b 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml @@ -116,9 +116,9 @@ top_pad="0" width="102" /> </panel> - <button + <icon height="18" - image_overlay="AddItem_Off" + image_name="AddItem_Off" layout="topleft" name="2nd_life_edit_icon" label="" @@ -171,9 +171,9 @@ top_pad="0" width="102" /> </panel> - <button + <icon height="18" - image_overlay="AddItem_Off" + image_name="AddItem_Off" layout="topleft" name="real_world_edit_icon" label="" diff --git a/indra/newview/skins/default/xui/en/panel_edit_shape.xml b/indra/newview/skins/default/xui/en/panel_edit_shape.xml index a9dfcb82d6..45c4b92338 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shape.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shape.xml @@ -59,13 +59,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shape_body_tab" title="Body"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shape_body_param_list" @@ -73,13 +71,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shape_head_tab" title="Head"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shape_head_param_list" @@ -87,13 +83,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shape_eyes_tab" title="Eyes"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shape_eyes_param_list" @@ -101,13 +95,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shape_ears_tab" title="Ears"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shape_ears_param_list" @@ -115,13 +107,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shape_nose_tab" title="Nose"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shape_nose_param_list" @@ -129,13 +119,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shape_mouth_tab" title="Mouth"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shape_mouth_param_list" @@ -143,13 +131,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shape_chin_tab" title="Chin"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shape_chin_param_list" @@ -157,13 +143,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shape_torso_tab" title="Torso"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shape_torso_param_list" @@ -171,13 +155,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shape_legs_tab" title="Legs"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shape_legs_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_shirt.xml b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml index 258ee06697..9a13dfa3c4 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shirt.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml @@ -49,13 +49,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shirt_main_tab" title="Shirt"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shirt_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_shoes.xml b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml index 22fced4aac..154b9d959c 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shoes.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml @@ -49,13 +49,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="shoes_main_tab" title="Shoes"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="shoes_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_skin.xml b/indra/newview/skins/default/xui/en/panel_edit_skin.xml index 1a00277f43..918606b54c 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_skin.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_skin.xml @@ -64,13 +64,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="skin_color_tab" title="Skin Color"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="skin_color_param_list" @@ -78,13 +76,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="skin_face_tab" title="Face Detail"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="skin_face_param_list" @@ -92,13 +88,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="skin_makeup_tab" title="Makeup"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="skin_makeup_param_list" @@ -106,13 +100,11 @@ width="303" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="skin_body_tab" title="Body Detail"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="skin_body_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_skirt.xml b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml index 411d433604..d0f4d75444 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_skirt.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml @@ -49,13 +49,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="skirt_main_tab" title="Skirt"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="skirt_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_socks.xml b/indra/newview/skins/default/xui/en/panel_edit_socks.xml index faff67795c..acc6d482a7 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_socks.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_socks.xml @@ -49,13 +49,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="socks_main_tab" title="Socks"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="socks_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_underpants.xml b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml index bb0b353a01..4f5c1c08b7 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_underpants.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml @@ -49,13 +49,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="underpants_main_tab" title="Underpants"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="underpants_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml index 097cb14ee6..715674e88b 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml @@ -49,13 +49,11 @@ top_pad="10" width="303"> <accordion_tab - can_resize="false" layout="topleft" min_height="150" name="undershirt_main_tab" title="Undershirt"> <scrolling_panel_list - draw_heading="false" follows="all" left="0" name="undershirt_main_param_list" diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 77b887de9b..f76a56bda4 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -137,7 +137,6 @@ left="0" image_overlay="BackArrow_Off" layout="topleft" name="back_btn" - picture_style="true" left="10" top="7" /> <text diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index a85c55f9b2..4f24c7a745 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -1,14 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel follows="all" - height="412" + height="380" label="General" class="panel_group_general" layout="topleft" left="0" top="0" name="general_tab" - width="313"> + width="303"> <panel.string name="help_text"> The General tab contains general information about this group, a list of members, general Group Preferences and member options. @@ -41,7 +41,7 @@ Hover your mouse over the options for more help. draw_heading="true" follows="left|top" heading_height="16" - height="160" + height="130" layout="topleft" left_delta="0" name="visible_members" diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index 7e24ad2c94..de1323d9cb 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -5,7 +5,7 @@ background_visible="true" height="570" label="Group Info" layout="topleft" - min_height="350" + min_height="425" left="0" top="20" name="GroupInfo" @@ -32,7 +32,6 @@ background_visible="true" image_overlay="BackArrow_Off" layout="topleft" name="back" - picture_style="true" left="10" tab_stop="false" top="2" @@ -60,7 +59,7 @@ background_visible="true" top_delta="5" width="250" height="20" - visible="true" /> + visible="false" /> <texture_picker follows="left|top" height="113" @@ -112,59 +111,92 @@ background_visible="true" left_delta="0" top_pad="6" height="23" - label="Join now!" - label_selected="Join now!" + label="JOIN NOW!" name="btn_join" visible="true" width="120" /> <accordion follows="all" - height="405" + height="425" layout="topleft" left="0" name="groups_accordion" - top_pad="20" - width="333"> + top_pad="15" + width="336"> <accordion_tab - can_resize="false" + expanded="true" layout="topleft" name="group_general_tab" title="General"> - <panel - border="false" - class="panel_group_general" - filename="panel_group_general.xml" + <scroll_container + color="DkGray2" + opaque="true" + height="323" + follows="all" layout="topleft" left="0" - help_topic="group_general_tab" - name="group_general_tab_panel" top="0" - width="333" /> + name="general_scroll" + reserve_scroll_corner="false" + width="333"> + <panel + border="false" + class="panel_group_general" + filename="panel_group_general.xml" + layout="topleft" + left="0" + help_topic="group_general_tab" + name="group_general_tab_panel" + top="0" + width="303" /> + </scroll_container> </accordion_tab> <accordion_tab - can_resize="false" expanded="false" layout="topleft" name="group_roles_tab" title="Roles"> - <panel - border="false" + <scroll_container + color="DkGray2" + opaque="true" + height="323" + follows="all" + layout="topleft" + left="0" + top="0" + name="roles_scroll" + reserve_scroll_corner="false" + width="333"> + <panel + border="false" class="panel_group_roles" - filename="panel_group_roles.xml" - layout="topleft" - left="0" - help_topic="group_roles_tab" + filename="panel_group_roles.xml" + layout="topleft" + left="0" + help_topic="group_roles_tab" name="group_roles_tab_panel" - top="0" - width="333" /> + top="0" + width="303" /> + </scroll_container> </accordion_tab> <accordion_tab - can_resize="false" expanded="false" layout="topleft" name="group_notices_tab" title="Notices"> + <scroll_container + color="DkGray2" + opaque="true" + height="323" + follows="all" + layout="topleft" + left="0" + top="0" + name="notices_scroll" + reserve_scroll_corner="false" + width="333"> <panel + border="false" class="panel_group_notices" filename="panel_group_notices.xml" layout="topleft" @@ -172,14 +204,25 @@ background_visible="true" help_topic="group_notices_tab" name="group_notices_tab_panel" top="0" - width="333" /> + width="303" /> + </scroll_container> </accordion_tab> - <accordion_tab - can_resize="false" + <accordion_tab expanded="false" layout="topleft" name="group_land_tab" title="Land/Assets"> + <scroll_container + color="DkGray2" + opaque="true" + height="323" + follows="all" + layout="topleft" + left="0" + top="0" + name="land_scroll" + reserve_scroll_corner="false" + width="333"> <panel border="false" class="panel_group_land_money" @@ -189,41 +232,42 @@ background_visible="true" help_topic="group_land_money_tab" name="group_land_tab_panel" top="0" - width="333" /> + width="313" /> + </scroll_container> </accordion_tab> </accordion> - <button + <button follows="top|left" - height="20" + height="22" image_overlay="Refresh_Off" layout="topleft" - name="btn_refresh" - picture_style="true" left="5" - width="20" /> - <button - height="20" - font="SansSerifSmall" - label="Save" - label_selected="Save" - name="btn_apply" - left_pad="5" - width="65" /> - <button + name="btn_refresh" + top_pad="-15" + width="23" /> + <button height="20" label="Create" - label_selected="Create" + label_selected="New group" name="btn_create" - left_pad="5" + left_pad="10" visible="false" - width="65" /> - <button - left_pad="5" + width="100" /> + <!-- <button + left_pad="10" height="20" label="Cancel" label_selected="Cancel" name="btn_cancel" visible="false" + width="65" />--> + <button + height="20" + font="SansSerifSmall" + label="Save" + label_selected="Save" + name="btn_apply" + left_pad="10" + right="-10" width="65" /> - </panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index c81c7113ae..0c6f81f8fd 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -1,25 +1,25 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - border="true" + border="false" follows="all" height="510" label="Land & L$" layout="topleft" left="1" name="land_money_tab" - top="490" - width="280"> + top="0" + width="313"> <panel.string name="help_text"> - Parcels owned by the group are listed along with contribution details. A warning appears until the Total Land in Use is less than or equal to the Total Contribution. The Planning, Details, and Sales tabs provide information about the group's finances. + Parcels owned by a group are listed along with contribution details. A warning appears until the Total Land in Use is less than or = to the Total Contribution. </panel.string> <panel.string name="cant_view_group_land_text"> - You do not have permission to view group owned land. + You don't have permission to view group owned land </panel.string> <panel.string name="cant_view_group_accounting_text"> - You do not have permission to view the group's accounting information. + You don't have permission to view the group's accounting information. </panel.string> <panel.string name="loading_txt"> @@ -27,7 +27,7 @@ </panel.string> <panel.string name="land_contrib_error"> - Unable to set your land contribution. + Unable to set your land contribution </panel.string> <!-- <text type="string" @@ -44,29 +44,29 @@ <scroll_list draw_heading="true" follows="top" - heading_height="14" - height="100" + heading_height="20" + height="150" layout="topleft" - left="5" + left="0" name="group_parcel_list" - top_pad="10" - width="265"> + top_pad="0" + width="313"> <scroll_list.columns label="Parcel" name="name" - width="67" /> + width="78" /> <scroll_list.columns label="Region" name="location" - width="72" /> + width="78" /> <scroll_list.columns label="Type" name="type" - width="60" /> + width="70" /> <scroll_list.columns label="Area" name="area" - width="20" /> + width="50" /> <scroll_list.columns label="" name="hidden" @@ -74,14 +74,14 @@ </scroll_list> <button follows="top" - height="20" + height="23" label="Map" label_selected="Map" layout="topleft" - left="150" name="map_button" - top_pad="10" - width="125" + right="-10" + top_pad="5" + width="95" enabled="false" /> <text type="string" @@ -91,11 +91,12 @@ layout="topleft" left="5" name="total_contributed_land_label" - top_pad="10" + top_pad="0" width="130"> Total Contribution: </text> <text + text_color="EmphasisColor" type="string" follows="left|top" height="16" @@ -119,6 +120,7 @@ Total Land In Use: </text> <text + text_color="EmphasisColor" type="string" follows="left|top" height="16" @@ -142,6 +144,7 @@ Land Available: </text> <text + text_color="EmphasisColor" type="string" follows="left|top" height="16" @@ -168,19 +171,19 @@ border_style="line" border_thickness="1" follows="left|top" - height="16" + height="19" layout="topleft" left_pad="5" max_length="10" name="your_contribution_line_editor" - top_delta="-2" + top_delta="0" width="95" /> <text type="string" follows="left|top" height="16" layout="topleft" - left_pad="5" + left_pad="3" name="your_contribution_units" top_delta="2"> m² @@ -193,13 +196,13 @@ layout="topleft" left="140" name="your_contribution_max_value" - top_pad="0" + top_pad="2" width="95"> ([AMOUNT] max) </text> <icon height="16" - image_name="smicon_warn.tga" + image_name="notify_next" layout="topleft" left="9" name="group_over_limit_icon" @@ -211,14 +214,14 @@ type="string" word_wrap="true" font="SansSerifSmall" - height="40" + height="35" layout="topleft" - left_pad="5" + left_pad="0" name="group_over_limit_text" - text_color="GroupOverTierColor" + text_color="EmphasisColor" top_delta="0" - width="250"> - Group members must contribute more land credits to support land in use. + width="290"> + Group members must contribute more land credits to support land in use </text> <text type="string" @@ -242,128 +245,122 @@ name="group_money_tab_container" tab_position="top" tab_height="20" - top_pad="10" - width="265"> + top_pad="2" + tab_min_width="70" + width="300"> <panel - border="true" + border="false" follows="all" height="180" - label="Planning" + label="PLANNING" layout="topleft" - left="1" + left="0" help_topic="group_money_planning_tab" name="group_money_planning_tab" top="5" - width="265"> + width="300"> <text_editor type="string" - bg_readonly_color="0.784314 0.819608 0.8 1" follows="all" - font="Monospace" - height="168" + font="SansSerif" + height="140" layout="topleft" - left="8" + left="0" max_length="4096" name="group_money_planning_text" - top="5" - width="250" + top="0" + width="300" word_wrap="true"> - Computing... + Loading... </text_editor> </panel> <panel - border="true" - follows="left|top|right|bottom" + border="false" + follows="all" height="180" - label="Details" + label="DETAILS" layout="topleft" - left_delta="0" + left="0" help_topic="group_money_details_tab" name="group_money_details_tab" - top_delta="0" - width="265"> + top="5" + width="300"> <text_editor type="string" - bg_readonly_color="0.784314 0.819608 0.8 1" follows="all" - font="Monospace" height="140" layout="topleft" - left="8" + left="0" max_length="4096" name="group_money_details_text" - top="7" - width="250" + top="0" + width="300" word_wrap="true"> - Computing... + Loading... </text_editor> - <button - height="20" - label="< Earlier" - label_selected="< Earlier" - layout="topleft" - left="5" - name="earlier_details_button" - tool_tip="Go back in time" - top_pad="10" - width="125" /> <button - height="20" - label="Later >" - label_selected="Later >" - layout="topleft" - left_pad="5" - name="later_details_button" - tool_tip="Go forward in time" - top_delta="0" - width="125" /> + follows="left|top" + height="23" + image_overlay="Arrow_Left_Off" + layout="topleft" + name="earlier_details_button" + tool_tip="Back" + top_pad="3" + right="-35" + width="31" /> + <button + follows="left|top" + height="23" + image_overlay="Arrow_Right_Off" + layout="topleft" + left_pad="10" + name="later_details_button" + tool_tip="Next" + width="31" /> </panel> <panel - border="true" - follows="left|top|right|bottom" + border="false" + follows="all" height="180" - label="Sales" + label="SALES" layout="topleft" left_delta="0" help_topic="group_money_sales_tab" name="group_money_sales_tab" top_delta="-1" - width="265"> + width="300"> <text_editor type="string" - bg_readonly_color="0.784314 0.819608 0.8 1" follows="all" - font="Monospace" height="140" layout="topleft" - left="8" + left="0" max_length="4096" name="group_money_sales_text" - top="7" - width="250" + top="0" + width="300" word_wrap="true"> - Computing... + Loading... </text_editor> - <button - height="20" - label="< Earlier" - label_selected="< Earlier" - layout="topleft" - left="5" - name="earlier_sales_button" - tool_tip="Go back in time" - top_pad="10" - width="125" /> - <button - height="20" - label="Later >" - label_selected="Later >" - layout="topleft" - left_pad="5" + <button + follows="left|top" + height="23" + image_overlay="Arrow_Left_Off" + layout="topleft" + name="earlier_sales_button" + tool_tip="Back" + top_pad="3" + right="-35" + width="31" /> + <button + follows="left|top" + height="23" + image_overlay="Arrow_Right_Off" + layout="topleft" + left_pad="10" name="later_sales_button" - tool_tip="Go forward in time" - top_delta="0" - width="125" /> + tool_tip="Next" + width="31" /> </panel> </tab_container> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml index ffa485051c..5f6b911620 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml @@ -54,7 +54,6 @@ left_pad="3" right="-31" name="info_btn" - picture_style="true" top_delta="-2" width="16" /> <!--*TODO: Should only appear on rollover--> @@ -66,7 +65,6 @@ left_pad="5" right="-3" name="profile_btn" - picture_style="true" top_delta="-2" width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 0e4d490369..24a4005a45 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -1,14 +1,13 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - border="true" follows="all" height="485" label="Notices" layout="topleft" - left="1" + left="0" name="notices_tab" - top="485" - width="280"> + top="0" + width="313"> <panel.string name="help_text"> Notices are a quick way to communicate across a @@ -20,60 +19,48 @@ the General tab. </panel.string> <panel.string name="no_notices_text"> - There are no past notices. + There are no past notices </panel.string> - <!--<text - follows="left|top" - type="string" - font="SansSerifBig" - height="16" - layout="topleft" - left="10" - name="lbl" - top_pad="10" - width="269"> - Group Notices Archive - </text> --> <text follows="left|top" type="string" word_wrap="true" - height="40" + height="30" layout="topleft" - left_delta="10" + left="10" name="lbl2" - text_color="EmphasisColor" - top_pad="10" - width="270"> - Notices are kept for 14 days. Notice lists are limited to 200 notices per group on a daily basis. + top="5" + width="300"> + Notices are kept for 14 days +Groups are limited to 200 notices/group daily </text> <scroll_list follows="left|top" column_padding="0" draw_heading="true" - heading_height="14" - height="109" + heading_height="16" + height="125" layout="topleft" - left_delta="0" + left="0" name="notice_list" top_pad="0" - width="265"> + width="303"> <scroll_list.columns label="" name="icon" - width="16" /> + width="20" /> <scroll_list.columns label="Subject" name="subject" - width="100" /> + width="125" /> <scroll_list.columns label="From" name="from" - width="83" /> + width="90" /> <scroll_list.columns label="Date" name="date" - width="50" /> + width="30" /> <scroll_list.columns name="sort" width="-1" /> @@ -84,39 +71,40 @@ the General tab. layout="topleft" name="notice_list_none_found" visible="false"> - None found. + None found </text> - <button - follows="left|top" - height="20" - font="SansSerifSmall" - label="New Notice" - label_selected="Create New Notice" - layout="topleft" - left_delta="0" - name="create_new_notice" - top_delta="4" - width="125" /> - <button - follows="left|top" - height="20" - font="SansSerifSmall" - label="Refresh" - label_selected="Refresh List" + <button + follows="bottom|left" + height="18" + image_selected="AddItem_Press" + image_unselected="AddItem_Off" + image_disabled="AddItem_Disabled" + layout="topleft" + label="Create a new notice" + left="15" + name="create_new_notice" + tool_tip="Create a new notice" + top_delta="-5" + width="18" /> + <button + follows="top|left" + height="22" + image_overlay="Refresh_Off" layout="topleft" - left_pad="12" name="refresh_notices" - top_delta="0" - width="125" /> + right="-5" + top_delta="5" + width="23" /> <panel follows="left|top" - height="268" + height="300" label="Create New Notice" layout="topleft" left="0" - name="panel_create_new_notice" top_pad="10" - width="265"> + visible="false" + name="panel_create_new_notice" + width="303"> <text follows="left|top" type="string" @@ -127,30 +115,16 @@ the General tab. mouse_opaque="false" name="lbl" text_color="EmphasisColor" - top_pad="0" - width="265"> + top="0" + width="200"> Create a Notice </text> <text follows="left|top" type="string" - word_wrap="true" - height="90" - layout="topleft" - left_delta="0" - name="lbl2" - text_color="EmphasisColor" - top_pad="4" - width="195"> - You can add a single item to a notice by dragging it from your inventory to this panel. Attached items must be copiable and transferrable, and you can't send a folder. - </text> - <text - follows="left|top" - type="string" halign="left" height="16" layout="topleft" - left_delta="0" name="lbl3" top_pad="10" width="60"> @@ -164,8 +138,7 @@ the General tab. left_pad="3" max_length="63" name="create_subject" - top_delta="-1" - width="200" /> + width="220" /> <text follows="left|top" type="string" @@ -174,106 +147,100 @@ the General tab. layout="topleft" left="10" name="lbl4" - top_pad="10" + top_pad="5" width="60"> Message: </text> <text_editor - height="75" + height="90" layout="topleft" left_pad="3" max_length="511" name="create_message" top_delta="0" - width="200" + width="220" word_wrap="true" /> <text follows="left|top" type="string" halign="left" - height="16" + height="14" layout="topleft" left="10" name="lbl5" - top_pad="10" - width="60"> + width="200"> Attach: </text> <line_editor enabled="false" - height="16" + height="19" layout="topleft" - left_pad="3" - max_length="63" + max_length="90" mouse_opaque="false" name="create_inventory_name" - top_delta="0" - width="200" /> + top_pad="2" + width="285" /> + <text + text_color="EmphasisColor" + follows="left|top" + type="string" + halign="right" + height="34" + layout="topleft" + left="10" + name="string" + top_pad="15" + word_wrap="true" + width="150"> + Drag here to attach something -- > + </text> <icon - height="16" + height="72" + image_name="DropTarget" layout="topleft" - left_delta="0" - name="create_inv_icon" - top_delta="0" - width="16" /> + left_pad="10" + mouse_opaque="true" + name="drop_icon" + top_delta="-10" + width="72" /> <button follows="left|top" - height="20" - font="SansSerifSmall" - label="Remove Attachment" - label_selected="Remove Attachment" + height="23" + label="Remove" layout="topleft" - left="10" + left="70" name="remove_attachment" - top_pad="10" - width="135" /> + top_delta="45" + width="90" /> <button follows="left|top" - height="20" - font="SansSerifSmall" + height="23" label="Send" label_selected="Send Notice" layout="topleft" - left_delta="138" + right="-10" + top_pad="20" name="send_notice" - top_delta="0" - width="125" /> - <panel - bevel_style="in" - border="true" - height="71" - layout="topleft" - left="200" - name="drop_target2" - top="20" - width="71" /> - <icon - height="59" - image_name="icon_groupnoticeinventory.tga" - layout="topleft" - left_delta="6" - mouse_opaque="true" - name="drop_icon" - top="26" - width="59" /> - <group_drop_target + width="100" /> + <group_drop_target height="466" - layout="topleft" + top="0" left="0" + layout="topleft" name="drop_target" tool_tip="Drag an inventory item onto the message box to send it with the notice. You must have permission to copy and transfer the object to send it with the notice." - top="-198" - width="280" /> + width="295" /> </panel> <panel follows="left|top" - height="268" + height="300" label="View Past Notice" layout="topleft" left="0" + visible="true" name="panel_view_past_notice" - top="197" - width="265"> + top="180" + width="303"> <text type="string" font="SansSerifBig" @@ -294,9 +261,9 @@ the General tab. layout="topleft" left_delta="0" name="lbl2" - top_pad="4" + top_pad="2" width="265"> - To send a new notice, click the 'New Notice' button above. + To send a new notice, click the + button </text> <text type="string" @@ -305,7 +272,7 @@ the General tab. layout="topleft" left_delta="0" name="lbl3" - top_pad="24" + top_pad="15" visible="false" width="60"> Subject: @@ -336,13 +303,13 @@ the General tab. </text> <text_editor enabled="false" - height="150" + height="205" layout="topleft" left="10" max_length="511" name="view_message" top_delta="-35" - width="260" + width="285" word_wrap="true" /> <line_editor enabled="false" @@ -353,7 +320,7 @@ the General tab. mouse_opaque="false" name="view_inventory_name" top_pad="10" - width="260" /> + width="285" /> <icon height="16" layout="topleft" @@ -363,14 +330,12 @@ the General tab. width="16" /> <button follows="left|top" - height="20" - font="SansSerifSmall" - label="Open Attachment" - label_selected="Open Attachment" + height="23" + label="Open attachment" layout="topleft" - left_delta="0" + right="-10" name="open_attachment" - top_pad="10" + top_pad="5" width="135" /> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml index e87859f788..5ed464bcec 100644 --- a/indra/newview/skins/default/xui/en/panel_group_roles.xml +++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel border="false" - height="412" + height="552" label="Members & Roles" layout="topleft" left="0" @@ -18,158 +18,28 @@ </panel.string> <panel.string name="help_text" /> - <!--<panel - follows="left|top" - height="80" - layout="topleft" - left="10" - name="members_header" - top_pad="10" - width="270"> - <text - type="string" - font="SansSerifBig" - height="16" - layout="topleft" - left="0" - name="static" - top="0" - width="270"> - Members & Roles - </text> - <text - type="string" - word_wrap="true" - height="40" - layout="topleft" - left_delta="0" - name="static2" - top_pad="4" - width="270"> - Group Members are assigned Roles with Abilities. These settings can easily be customized, allowing for greater organization and flexibility. - </text> - </panel> - <panel - follows="left|top" - height="24" - layout="topleft" - left_delta="0" - name="roles_header" - top_delta="0" - visible="false" - width="270"> - <text - type="string" - font="SansSerifBig" - height="16" - layout="topleft" - left="0" - name="static" - top="0" - width="270"> - Roles - </text> - <text - type="string" - word_wrap="true" - height="40" - layout="topleft" - left_delta="0" - name="role_properties_modifiable" - top_pad="4" - visible="false" - width="270"> - Select a Role below. You can modify its Name, Description and Member Title. - </text> - <text - type="string" - word_wrap="true" - height="40" - layout="topleft" - left_delta="0" - name="role_properties_not_modifiable" - top_delta="0" - width="270"> - Select a Role below to see its properties, Members and allowed Abilities. - </text> - <text - type="string" - word_wrap="true" - height="16" - layout="topleft" - left_delta="0" - name="role_actions_modifiable" - top_delta="24" - visible="false" - width="270"> - You can also assign Abilities to the Role. - </text> - <text - type="string" - word_wrap="true" - height="16" - layout="topleft" - left_delta="0" - name="role_actions_not_modifiable" - top_delta="0" - width="270"> - You may view, but not modify, assigned Abilities. - </text> - </panel> - <panel - follows="left|top" - height="24" - layout="topleft" - left_delta="0" - name="actions_header" - top_delta="0" - visible="false" - width="270"> - <text - type="string" - font="SansSerifBig" - height="16" - layout="topleft" - left="0" - name="static" - top="0" - width="270"> - Abilities - </text> - <text - type="string" - word_wrap="true" - height="40" - layout="topleft" - left_delta="0" - name="static2" - top_pad="4" - width="270"> - You can view an Ability's Description and which Roles and Members can execute the Ability. - </text> - </panel> --> <tab_container - border="true" + border="false" follows="left|top" - height="260" + height="245" halign="center" layout="topleft" left="5" name="roles_tab_container" tab_position="top" tab_height="20" - top="0" + tab_min_width="96" + top="3" width="303"> <panel border="false" - height="260" - label="Members" + height="220" + label="MEMBERS" layout="topleft" - left="1" + left="0" help_topic="roles_members_tab" name="members_sub_tab" tool_tip="Members" - top="17" class="panel_group_members_subtab" width="300"> <panel.string @@ -187,8 +57,7 @@ clicking on their names. follows="left|top|right" max_length="250" label="Filter Members" - name="filter_input" - font="SansSerif" /> + name="filter_input" /> <!-- <button enabled="false" font="SansSerifSmall" @@ -229,6 +98,7 @@ clicking on their names. font="SansSerifSmall" label="Invite" layout="topleft" + left="5" name="member_invite" top_pad="3" width="100" /> @@ -238,8 +108,10 @@ clicking on their names. label="Eject" layout="topleft" left_pad="5" + right="-5" name="member_eject" width="100" /> + <!--What is this?--> <icon height="16" image_name="Inv_FolderClosed" @@ -250,15 +122,14 @@ clicking on their names. </panel> <panel border="false" - height="164" - label="Roles" + height="220" + label="ROLES" layout="topleft" - left_delta="0" + left="0" help_topic="roles_roles_tab" name="roles_sub_tab" class="panel_group_roles_subtab" - top="17" - width="265"> + width="300"> <panel.string name="help_text"> Roles have a title and an allowed list of Abilities @@ -282,40 +153,19 @@ including the Everyone and Owner Roles. name="power_partial_icon"> checkbox_enabled_false.tga </panel.string> - <filter_editor - layout="topleft" - top="10" - left="4" - width="260" - height="20" - follows="left|top|right" - max_length="250" - label="Filter Roles" - name="filter_input" - font="SansSerif" /> - <!--<line_editor - border_style="line" - border_thickness="1" - follows="left|top" - height="16" - layout="topleft" - left="4" - max_length="63" - name="search_text" - top="10" - width="90" /> - <button - font="SansSerifSmall" - height="20" - label="Search" - layout="topleft" - left_pad="5" - name="search_button" - top_delta="-2" - width="80" /> + <filter_editor + layout="topleft" + top="10" + left="4" + width="280" + height="20" + follows="left|top|right" + max_length="250" + label="Filter Roles" + name="filter_input" /> + <!-- <button enabled="false" - font="SansSerifSmall" height="20" label="Show All" layout="topleft" @@ -326,11 +176,13 @@ including the Everyone and Owner Roles. <scroll_list column_padding="0" draw_heading="true" + draw_stripes="false" follows="left|top" heading_height="20" height="150" layout="topleft" - left="4" + search_column="1" + left="0" name="role_list" top_pad="4" width="300"> @@ -352,7 +204,7 @@ including the Everyone and Owner Roles. font="SansSerifSmall" label="Add Role" layout="topleft" - left_delta="0" + left="5" name="role_create" top_pad="6" width="125" /> @@ -362,20 +214,20 @@ including the Everyone and Owner Roles. label="Delete Role" layout="topleft" left_pad="5" + right="-5" name="role_delete" top_delta="0" width="125" /> </panel> <panel border="false" - height="164" - label="Abilities" + height="220" + label="ABILITIES" layout="topleft" - left_delta="0" + left="0" help_topic="roles_actions_tab" name="actions_sub_tab" class="panel_group_actions_subtab" - top="17" tool_tip="You can view an Ability's Description and which Roles and Members can execute the Ability." width="300"> <panel.string @@ -383,37 +235,17 @@ including the Everyone and Owner Roles. Abilities allow Members in Roles to do specific things in this group. There's a broad variety of Abilities. </panel.string> - <filter_editor - layout="topleft" - top="10" - left="4" - width="255" - height="20" - follows="left|top|right" - max_length="250" - label="Filter Abilities" - name="filter_input" - font="SansSerif" /> - <!--<line_editor - border_style="line" - border_thickness="1" - follows="left|top" - height="16" - layout="topleft" - left="4" - max_length="63" - name="search_text" - top="10" - width="90" /> - <button - font="SansSerifSmall" - height="20" - label="Search" - layout="topleft" - left_pad="5" - name="search_button" - top_delta="-2" - width="80" /> + <filter_editor + layout="topleft" + top="10" + left="4" + width="280" + height="20" + follows="left|top|right" + max_length="250" + label="Filter Abilities" + name="filter_input" /> + <!-- <button enabled="false" font="SansSerifSmall" @@ -428,19 +260,19 @@ things in this group. There's a broad variety of Abilities. column_padding="0" draw_stripes="false" follows="left|top" - height="100" + height="160" layout="topleft" - left="6" + left="0" multi_select="true" name="action_list" search_column="1" tool_tip="Select an Ability to view more details" top_pad="6" - width="255"> + width="300"> <scroll_list.columns label="" name="icon" - width="18" /> + width="16" /> <scroll_list.columns label="" name="action" @@ -448,7 +280,7 @@ things in this group. There's a broad variety of Abilities. </scroll_list> <icon height="16" - image_name="inv_folder_plain_closed.tga" + image_name="Inv_FolderClosed" layout="topleft" name="power_folder_icon" visible="false" @@ -456,105 +288,93 @@ things in this group. There's a broad variety of Abilities. </panel> </tab_container> <panel - height="150" + height="252" layout="topleft" follows="left|top" left="10" name="members_footer" - top_pad="2" + top_pad="10" + top_delta="0" width="300"> <text type="string" - font="SansSerif" height="16" layout="topleft" follows="left|top" left="0" name="static" - top_pad="0" - width="100"> + top_pad="5" + width="295"> Assigned Roles </text> - <text - type="string" - font="SansSerif" - height="16" - layout="topleft" - follows="left|top" - left_pad="35" - name="static2" - top_delta="0" - width="100"> - Allowed Abilities - </text> <scroll_list draw_stripes="false" follows="left|top" - height="150" + height="80" layout="topleft" left="0" name="member_assigned_roles" - top_pad="5" - width="130"> + top_pad="0" + width="295"> <scroll_list.columns label="" name="checkbox" - width="18" /> + width="30" /> <scroll_list.columns label="" name="role" - width="107" /> + width="265" /> </scroll_list> - <scroll_list - draw_stripes="false" - height="150" + <text + type="string" + height="16" layout="topleft" follows="left|top" - left_pad="5" + left="0" + name="static2" + top_pad="5" + width="295"> + Allowed Abilities + </text> + <scroll_list + draw_stripes="false" + height="80" + layout="topleft" + left="0" name="member_allowed_actions" + search_column="2" tool_tip="For details of each allowed ability see the abilities tab" - top_delta="0" - width="130"> + top_pad="0" + width="295"> <scroll_list.columns label="" name="icon" - width="14" /> + width="20" /> <scroll_list.columns label="" name="action" - width="126" /> + width="275" /> </scroll_list> </panel> <panel - height="252" + height="297" layout="topleft" - left_delta="0" + left="10" name="roles_footer" top_delta="0" + top="245" visible="false" - width="270"> + width="300"> <text type="string" - font="SansSerif" height="16" layout="topleft" left="0" name="static" top="0" - width="100"> + width="140"> Name </text> - <text - type="string" - font="SansSerif" - height="16" - layout="topleft" - left_pad="35" - name="static2" - top_delta="0" - width="100"> - Description - </text> <line_editor type="string" border_style="line" @@ -563,21 +383,19 @@ things in this group. There's a broad variety of Abilities. height="20" layout="topleft" left="0" - max_length="20" + max_length="295" name="role_name" top_pad="0" - width="130"> + width="295"> Employees </line_editor> <text type="string" - font="SansSerif" height="16" layout="topleft" - left_delta="0" name="static3" - top_pad="10" - width="100"> + top_pad="5" + width="295"> Title </text> <line_editor @@ -587,158 +405,159 @@ things in this group. There's a broad variety of Abilities. follows="left|top" height="20" layout="topleft" - left_delta="0" - max_length="20" + max_length="295" name="role_title" top_pad="0" - width="130"> - (waiting) + width="295"> + (waiting) </line_editor> + <text + type="string" + height="16" + layout="topleft" + left="0" + name="static2" + top_pad="5" + width="100"> + Description + </text> <text_editor type="string" halign="left" - height="48" + height="35" layout="topleft" - left="135" - max_length="254" + left="0" + max_length="295" name="role_description" - top="16" - width="130" + top_pad="0" + width="295" word_wrap="true"> - (waiting) + (waiting) </text_editor> <text type="string" - font="SansSerif" height="16" layout="topleft" + follows="left|top" left="0" - name="static4" - top="85" - width="120"> - Assigned Members - </text> - <text - type="string" - font="SansSerif" - height="16" - layout="topleft" - left_pad="15" - name="static5" - tool_tip="A list of abilities the currently selected role can perform" - top_delta="0" - width="100"> - Allowed Abilities + name="static" + top_pad="5" + width="295"> + Assigned Roles </text> <name_list draw_stripes="false" - height="150" + height="50" layout="topleft" left="0" name="role_assigned_members" top_pad="0" - width="130" /> + width="295" /> <check_box - height="16" - label="Members are visible" + height="15" + label="Reveal members" layout="topleft" - left_delta="0" name="role_visible_in_list" tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group." - top_pad="10" - width="130" /> + top_pad="3" + width="290" /> + <text + type="string" + height="16" + layout="topleft" + follows="left|top" + left="0" + name="static2" + top_pad="5" + width="295"> + Allowed Abilities + </text> <scroll_list draw_stripes="false" - height="150" + height="50" layout="topleft" - left="135" + left="0" name="role_allowed_actions" search_column="2" tool_tip="For details of each allowed ability see the abilities tab" - top="101" - width="130"> + top_pad="0" + width="295"> <scroll_list.columns label="" name="icon" - width="2" /> + width="20" /> <scroll_list.columns label="" name="checkbox" - width="16" /> + width="20" /> <scroll_list.columns label="" name="action" - width="220" /> + width="250" /> </scroll_list> </panel> <panel - height="215" + height="303" layout="topleft" - left_delta="0" + left="10" name="actions_footer" top_delta="0" + top="245" visible="false" - width="265"> + width="300"> <text type="string" - font="SansSerif" height="16" layout="topleft" - left="0" name="static" - top="0" width="200"> - Description + Ability description </text> <text_editor type="string" enabled="false" halign="left" - height="48" + height="80" layout="topleft" left_delta="0" max_length="512" name="action_description" top_pad="0" - width="265" + width="295" word_wrap="true"> This Ability is 'Eject Members from this Group'. Only an Owner can eject another Owner. </text_editor> <text type="string" - font="SansSerif" height="16" layout="topleft" left_delta="0" name="static2" - top_pad="10" - width="125"> - Roles with Ability + top_pad="5" + width="295"> + Roles with this ability </text> - <text + <scroll_list + height="60" + layout="topleft" + left="0" + name="action_roles" + top_pad="0" + width="295" /> + <text type="string" - font="SansSerif" height="16" layout="topleft" - left_pad="10" name="static3" - top_delta="0" - width="125"> - Members with Ability + top_pad="5" + width="295"> + Members with this ability </text> - <scroll_list - height="150" - layout="topleft" - left="0" - name="action_roles" - top="90" - width="130" /> <name_list - height="150" + height="100" layout="topleft" - left_pad="5" name="action_members" - top_delta="0" - width="130" /> + top_pad="0" + width="295" /> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml index c8b134cdf0..e81532ec3e 100644 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml @@ -14,7 +14,7 @@ width="125"/> <text - follows="left|right" + follows="top|left|right" font="SansSerifBig" height="16" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index 03ba7f7c81..b01ddbf75a 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -43,6 +43,16 @@ name="acquired_date"> [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] </string> + <!-- Texture names for rating icons --> + <string + name="icon_PG" + value="parcel_drk_PG" /> + <string + name="icon_M" + value="parcel_drk_M" /> + <string + name="icon_R" + value="parcel_drk_R" /> <button follows="top|right" height="23" @@ -50,7 +60,6 @@ layout="topleft" left="10" name="back_btn" - picture_style="true" tab_stop="false" top="0" width="23" /> @@ -126,6 +135,24 @@ top_pad="10" value="Du waltz die spritz" width="300" /> + <icon + follows="top|left" + height="16" + image_name="unknown" + layout="topleft" + left="10" + name="maturity_icon" + top_pad="10" + width="18" /> + <text + follows="right|top" + height="16" + layout="topleft" + left_pad="8" + name="maturity_value" + top_delta="0" + value="unknown" + width="268" /> <panel follows="left|top|right" height="55" diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 5293043ba7..f05684db10 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -31,7 +31,7 @@ left="0" mouse_opaque="true" name="favorites_list" - start_folder="favorite" + start_folder="Favorite" width="380"/> </accordion_tab> <accordion_tab @@ -47,7 +47,7 @@ left="0" mouse_opaque="true" name="landmarks_list" - start_folder="landmark" + start_folder="Landmarks" width="380"/> </accordion_tab> <accordion_tab @@ -63,13 +63,13 @@ left="0" mouse_opaque="true" name="my_inventory_list" - start_folder="inventory" + start_folder="INVENTORY" width="380"/> - </accordion_tab> - <accordion_tab - layout="topleft" - name="tab_library" - title="Library"> + </accordion_tab> + <accordion_tab + layout="topleft" + name="tab_library" + title="Library"> <inventory_subtree_panel allow_multi_select="true" border="true" @@ -79,7 +79,7 @@ left="0" mouse_opaque="true" name="library_list" - start_folder="library" + start_folder="LIBRARY" width="380"/> </accordion_tab> </accordion> @@ -103,7 +103,6 @@ layout="topleft" left="10" name="options_gear_btn" - picture_style="true" top="6" width="18" /> <button @@ -115,7 +114,6 @@ layout="topleft" left_pad="5" name="add_btn" - picture_style="true" tool_tip="Add new landmark" width="18" /> <dnd_button @@ -126,7 +124,6 @@ layout="topleft" right="-5" name="trash_btn" - picture_style="true" tool_tip="Remove selected landmark" top="6" width="18" /> diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index afe00271f7..1646cba0a7 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -15,27 +15,34 @@ name="real_url"> http://secondlife.com/app/login/ </panel.string> + <string name="reg_in_client_url"> + http://secondlife.eniac15.lindenlab.com/reg-in-client/ + </string> <panel.string name="forgot_password_url"> http://secondlife.com/account/request.php </panel.string> + <!-- *NOTE: Custom resize logic for login_html in llpanellogin.cpp --> <web_browser border_visible="false" bottom="600" follows="all" - layout="topleft" left="0" name="login_html" - right="-1" start_url="" - top="1" /> + top="0" + height="600" + width="800"/> + <panel + follows="left|bottom|right" + name="login_widgets" + layout="topleft" + left="0" + top="0"> <text - type="string" - length="1" follows="left|bottom" font="SansSerif" height="16" - layout="topleft" left="32" name="first_name_text" top="530" @@ -46,7 +53,6 @@ follows="left|bottom" handle_edit_keys_directly="true" height="20" - layout="topleft" left_delta="0" max_length="31" name="first_name_edit" @@ -55,12 +61,9 @@ top_pad="2" width="120" /> <text - type="string" - length="1" follows="left|bottom" font="SansSerif" height="16" - layout="topleft" left="164" name="last_name_text" top="530" @@ -72,7 +75,6 @@ font="SansSerif" handle_edit_keys_directly="true" height="20" - layout="topleft" left_delta="0" max_length="31" name="last_name_edit" @@ -81,12 +83,9 @@ top_pad="2" width="120" /> <text - type="string" - length="1" follows="left|bottom" font="SansSerif" height="16" - layout="topleft" left="296" name="password_text" top="530" @@ -98,7 +97,6 @@ font="SansSerif" handle_edit_keys_directly="true" height="20" - layout="topleft" left_delta="0" max_length="16" name="password_edit" @@ -124,12 +122,9 @@ name="server_combo" width="100" /> <text - type="string" - length="1" follows="left|bottom" font="SansSerif" height="16" - layout="topleft" left="32" name="start_location_text" top="576" @@ -141,7 +136,6 @@ control_name="LoginLocation" follows="left|bottom" height="23" - layout="topleft" left_pad="0" max_chars="128" name="start_location_combo" @@ -165,20 +159,14 @@ follows="left|bottom" height="16" label="Remember password" - layout="topleft" left_pad="10" name="remember_check" top_delta="3" width="138" /> <text - type="string" - length="1" follows="right|bottom" halign="right" height="16" - hover="true" - hover_color="0.2 0.45 0.72 1" - layout="topleft" left="-210" name="create_new_account_text" top="539" @@ -186,14 +174,9 @@ Create a new account </text> <text - type="string" - length="1" follows="right|bottom" halign="right" height="16" - hover="true" - hover_color="0.2 0.45 0.72 1" - layout="topleft" left_delta="0" name="forgot_password_text" top_pad="4" @@ -201,18 +184,14 @@ Forgot your name or password? </text> <text - type="string" - length="1" follows="right|bottom" halign="right" height="16" - hover="true" - hover_color="0.2 0.45 0.72 1" - layout="topleft" left="-310" name="channel_text" top="579" width="300"> [VERSION] </text> + </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml new file mode 100644 index 0000000000..fcee0ef953 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -0,0 +1,467 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="400"
+ label="Things"
+ layout="topleft"
+ min_height="350"
+ min_width="240"
+ name="main inventory panel"
+ width="330">
+ <panel.string
+ name="Title">
+ Things
+ </panel.string>
+ <filter_editor
+ text_pad_left="12"
+ follows="left|top|right"
+ font="SanSerif"
+ height="20"
+ label="Filter"
+ layout="topleft"
+ left="15"
+ name="inventory search editor"
+ top="34"
+ width="300" />
+ <tab_container
+ follows="left|top|right|bottom"
+ height="300"
+ layout="topleft"
+ left_delta="-4"
+ name="inventory filter tabs"
+ tab_position="top"
+ top_pad="4"
+ width="305">
+ <inventory_panel
+ follows="left|top|right|bottom"
+ height="295"
+ label="All Items"
+ layout="topleft"
+ left="1"
+ name="All Items"
+ top="16"
+ width="290" />
+ <inventory_panel
+ follows="left|top|right|bottom"
+ height="295"
+ label="Recent Items"
+ layout="topleft"
+ left_delta="0"
+ name="Recent Items"
+ top_delta="0"
+ width="290" />
+ </tab_container>
+
+ <panel
+ background_visible="true"
+ bevel_style="none"
+ bottom="0"
+ follows="left|right|bottom"
+ height="30"
+ layout="bottomleft"
+ left="0"
+ visible="true"
+ name="bottom_panel"
+ width="330">
+ <button
+ follows="bottom|left"
+ tool_tip="Show additional options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="options_gear_btn"
+ picture_style="true"
+ top="6"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_btn"
+ picture_style="true"
+ tool_tip="Add new item"
+ width="18" />
+ <dnd_button
+ follows="bottom|right"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ layout="topleft"
+ right="-5"
+ name="trash_btn"
+ picture_style="true"
+ tool_tip="Remove selected item"
+ top="6"
+ width="18" />
+ </panel>
+
+ <menu_bar
+ bg_visible="false"
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="Inventory Menu"
+ top="15"
+ visible="true"
+ width="290">
+ <menu
+ height="101"
+ label="File"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="File"
+ tear_off="true"
+ top="-117"
+ width="128">
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="Open">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="open" />
+ </menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Upload"
+ layout="topleft"
+ name="upload"
+ tear_off="true">
+ <menu_item_call
+ label="Image (L$[COST])..."
+ layout="topleft"
+ name="Upload Image"
+ shortcut="control|U">
+ <menu_item_call.on_click
+ function="File.UploadImage"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sound (L$[COST])..."
+ layout="topleft"
+ name="Upload Sound">
+ <menu_item_call.on_click
+ function="File.UploadSound"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Animation (L$[COST])..."
+ layout="topleft"
+ name="Upload Animation">
+ <menu_item_call.on_click
+ function="File.UploadAnim"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Bulk (L$[COST] per file)..."
+ layout="topleft"
+ name="Bulk Upload">
+ <menu_item_call.on_click
+ function="File.UploadBulk"
+ parameter="" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="New Window"
+ layout="topleft"
+ name="New Window">
+ <menu_item_call.on_click
+ function="Inventory.NewWindow" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="separator2" />
+ <menu_item_call
+ label="Show Filters"
+ layout="topleft"
+ name="Show Filters">
+ <menu_item_call.on_click
+ function="Inventory.ShowFilters" />
+ </menu_item_call>
+ <menu_item_call
+ label="Reset Filters"
+ layout="topleft"
+ name="Reset Current">
+ <menu_item_call.on_click
+ function="Inventory.ResetFilter" />
+ </menu_item_call>
+ <menu_item_call
+ label="Close All Folders"
+ layout="topleft"
+ name="Close All Folders">
+ <menu_item_call.on_click
+ function="Inventory.CloseAllFolders" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="separator3" />
+ <menu_item_call
+ label="Empty Trash"
+ layout="topleft"
+ name="Empty Trash">
+ <menu_item_call.on_click
+ function="Inventory.EmptyTrash" />
+ </menu_item_call>
+ <menu_item_call
+ label="Empty Lost And Found"
+ layout="topleft"
+ name="Empty Lost And Found">
+ <menu_item_call.on_click
+ function="Inventory.EmptyLostAndFound" />
+ </menu_item_call>
+ </menu>
+ <menu
+ height="121"
+ label="Create"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="Create"
+ tear_off="true"
+ top="-201"
+ width="121">
+ <menu_item_call
+ label="New Folder"
+ layout="topleft"
+ name="New Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Script"
+ layout="topleft"
+ name="New Script">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="lsl" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Note"
+ layout="topleft"
+ name="New Note">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="notecard" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gesture"
+ layout="topleft"
+ name="New Gesture">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gesture" />
+ </menu_item_call>
+ <menu
+ height="175"
+ label="New Clothes"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Clothes"
+ top_pad="514"
+ width="125">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha"
+ layout="topleft"
+ name="New Alpha">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="tattoo" />
+ </menu_item_call>
+ </menu>
+ <menu
+ height="85"
+ label="New Body Parts"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Body Parts"
+ top_pad="514"
+ width="118">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ <menu
+ height="49"
+ label="Sort"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="Sort"
+ tear_off="true"
+ top="-113"
+ width="118">
+ <menu_item_check
+ control_name="Inventory.SortByName"
+ label="By Name"
+ layout="topleft"
+ name="By Name">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="name" />
+ </menu_item_check>
+ <menu_item_check
+ control_name="Inventory.SortByDate"
+ label="By Date"
+ layout="topleft"
+ name="By Date">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="date" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ control_name="Inventory.FoldersAlwaysByName"
+ label="Folders Always By Name"
+ layout="topleft"
+ name="Folders Always By Name">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="foldersalwaysbyname" />
+ </menu_item_check>
+ <menu_item_check
+ control_name="Inventory.SystemFoldersToTop"
+ label="System Folders To Top"
+ layout="topleft"
+ name="System Folders To Top">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="systemfolderstotop" />
+ </menu_item_check>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index a289ce3cf7..a90337d31a 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -7,6 +7,7 @@ height="65" layout="topleft" name="navigation_bar" + chrome="true" width="600"> <icon follows="all" @@ -22,7 +23,7 @@ <icon follows="all" image_name="NavBar_BG_NoFav" - mouse_opaque="true" + mouse_opaque="false" name="bg_icon_no_fav" scale_image="true" visible="false" @@ -51,7 +52,6 @@ layout="topleft" left="10" name="back_btn" - picture_style="true" tool_tip="Go back to previous location" top="3" width="31" /> @@ -69,7 +69,6 @@ layout="topleft" left_pad="0" name="forward_btn" - picture_style="true" tool_tip="Go forward one location" top_delta="0" width="31" /> @@ -86,7 +85,6 @@ layout="topleft" left_pad="7" name="home_btn" - picture_style="true" tool_tip="Teleport to my home location" top_delta="0" width="32" /> @@ -127,7 +125,6 @@ <!-- left_pad="5" --> <!-- mouse_opaque="false" --> <!-- name="search_bg" --> - <!-- picture_style="true" --> <!-- top_delta="0" --> <!-- width="168" /> --> @@ -148,7 +145,8 @@ top_delta="0" width="200" > <combo_editor - label="Search" /> + label="Search [SECOND_LIFE]" + name="search_combo_editor"/> </search_combo_box> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml index 5333dfa2f5..b9c9100ebc 100644 --- a/indra/newview/skins/default/xui/en/panel_notes.xml +++ b/indra/newview/skins/default/xui/en/panel_notes.xml @@ -17,13 +17,16 @@ left="0" top="0" height="517" + width="313" border_size="0"> <panel name="notes_stack" follows="all" layout="topleft" top="0" - left="0"> + left="0" + height="475" + width="313"> <scroll_container color="DkGray2" follows="all" @@ -31,8 +34,11 @@ left="0" name="profile_scroll" opaque="true" + height="475" + width="313" top="0"> <panel + height="450" layout="topleft" name="profile_scroll_panel" top="0" @@ -104,7 +110,8 @@ layout="topleft" left="0" name="notes_buttons_panel" - auto_resize="false"> + auto_resize="false" + width="313"> <button follows="bottom|left" height="19" diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index 0d34aa0f08..34a185fb44 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -2,9 +2,6 @@ <panel background_opaque="false" border_visible="false" - border = "false" - border_drop_shadow_visible = "false" - drop_shadow_visible = "false" background_visible="true" bg_alpha_color="0.3 0.3 0.3 0" bg_opaque_color="0.3 0.3 0.3 0" @@ -18,12 +15,7 @@ <!-- THIS PANEL CONTROLS TOAST HEIGHT? --> <panel border_visible="false" - drop_shadow="false" bevel_style="none" - border_style="none" - border = "false" - border_drop_shadow_visible = "false" - drop_shadow_visible = "false" background_visible="true" bg_alpha_color="0.3 0.3 0.3 0" bg_opaque_color="0.3 0.3 0.3 0" @@ -67,9 +59,6 @@ v_pad="0" bg_readonly_color="0.0 0.0 0.0 0" border_visible="false" - border = "false" - border_drop_shadow_visible = "false" - drop_shadow_visible = "false" embedded_items="false" enabled="false" follows="left|right|top|bottom" diff --git a/indra/newview/skins/default/xui/en/panel_notifications_channel.xml b/indra/newview/skins/default/xui/en/panel_notifications_channel.xml index c67ae41677..7b6c0f33da 100644 --- a/indra/newview/skins/default/xui/en/panel_notifications_channel.xml +++ b/indra/newview/skins/default/xui/en/panel_notifications_channel.xml @@ -71,7 +71,6 @@ layout="topleft" left_delta="0" name="header" - picture_style="true" top_delta="-20" width="100" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index e234a7b358..d6e2aa64fa 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -75,7 +75,6 @@ background_visible="true" multi_select="true" name="avatar_list" top="0" - volume_column_width="20" width="313" /> <panel follows="left|right|bottom" @@ -95,7 +94,6 @@ background_visible="true" layout="topleft" left="10" name="nearby_view_sort_btn" - picture_style="true" top="5" width="18" /> <button @@ -107,7 +105,6 @@ background_visible="true" layout="topleft" left_pad="5" name="add_friend_btn" - picture_style="true" top_delta="0" tool_tip="Add selected resident to your friends List" width="18" /> @@ -132,7 +129,6 @@ background_visible="true" top="0" width="313"> <accordion_tab - can_resize="false" layout="topleft" height="235" min_height="150" @@ -149,7 +145,6 @@ background_visible="true" width="313" /> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" height="235" name="tab_all" @@ -183,7 +178,6 @@ background_visible="true" layout="topleft" left="10" name="friends_viewsort_btn" - picture_style="true" top="5" width="18" /> <button @@ -195,7 +189,6 @@ background_visible="true" layout="topleft" left_pad="5" name="add_btn" - picture_style="true" tool_tip="Offer friendship to a resident" top_delta="0" width="18" /> @@ -209,7 +202,6 @@ background_visible="true" left_pad="10" right="-10" name="del_btn" - picture_style="true" tool_tip="Remove selected person from your Friends list" top_delta="0" width="18" /> @@ -252,7 +244,6 @@ background_visible="true" layout="topleft" left="10" name="groups_viewsort_btn" - picture_style="true" top="7" width="18" /> <button @@ -264,7 +255,6 @@ background_visible="true" layout="topleft" left_pad="5" name="plus_btn" - picture_style="true" tool_tip="Join group/Create new group" top_delta="0" width="18" /> @@ -277,23 +267,9 @@ background_visible="true" layout="topleft" left_pad="24" name="activate_btn" - picture_style="true" tool_tip="Activate selected group" top_delta="5" width="10" /> - <button - follows="bottom|left" - height="18" - image_selected="TrashItem_Press" - image_unselected="TrashItem_Off" - layout="topleft" - left_pad="10" - right="-10" - name="minus_btn" - picture_style="true" - tool_tip="Leave selected group" - top_delta="-5" - width="18" /> </panel> </panel> <panel @@ -336,7 +312,6 @@ background_visible="true" layout="topleft" left="10" name="recent_viewsort_btn" - picture_style="true" top="7" width="18" /> <button @@ -348,7 +323,6 @@ background_visible="true" layout="topleft" left_pad="5" name="add_friend_btn" - picture_style="true" top_delta="0" tool_tip="Add selected resident to your friends List" width="18" /> diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml index 3cc9c3f38a..cf18aa2d39 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_info.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml @@ -15,7 +15,6 @@ image_overlay="BackArrow_Off" layout="topleft" name="back_btn" - picture_style="true" left="10" tab_stop="false" top="2" diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml index 38ea6b6196..7ff227ecb6 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml @@ -75,7 +75,6 @@ image_unselected="BuyArrow_Press" layout="topleft" name="info_chevron" - picture_style="true" right="-7" tab_stop="false" top="27" diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml index a2296edc2f..dbe76e553b 100644 --- a/indra/newview/skins/default/xui/en/panel_picks.xml +++ b/indra/newview/skins/default/xui/en/panel_picks.xml @@ -82,7 +82,6 @@ layout="topleft" left="0" name="gear_menu_btn" - picture_style="true" top="5" width="18" /> <button @@ -94,7 +93,6 @@ layout="topleft" left_pad="15" name="new_btn" - picture_style="true" tool_tip="Create new pick at current location" top="5" width="18" /> @@ -106,7 +104,6 @@ image_unselected="TrashItem_Off" layout="topleft" name="trash_btn" - picture_style="true" right="-10" top="5" width="18" /> diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index 4dc65fa736..d3eb548207 100644 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -92,6 +92,52 @@ name="acquired_date"> [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] </string> + <!-- Texture names for parcel permissions icons --> + <string + name="icon_PG" + value="parcel_drk_PG" /> + <string + name="icon_M" + value="parcel_drk_M" /> + <string + name="icon_R" + value="parcel_drk_R" /> + <string + name="icon_Voice" + value="parcel_drk_Voice" /> + <string + name="icon_VoiceNo" + value="parcel_drk_VoiceNo" /> + <string + name="icon_Fly" + value="parcel_drk_Fly" /> + <string + name="icon_FlyNo" + value="parcel_drk_FlyNo" /> + <string + name="icon_Push" + value="parcel_drk_Push" /> + <string + name="icon_PushNo" + value="parcel_drk_PushNo" /> + <string + name="icon_Build" + value="parcel_drk_Build" /> + <string + name="icon_BuildNo" + value="parcel_drk_BuildNo" /> + <string + name="icon_Scripts" + value="parcel_drk_Scripts" /> + <string + name="icon_ScriptsNo" + value="parcel_drk_ScriptsNo" /> + <string + name="icon_Damage" + value="parcel_drk_Damage" /> + <string + name="icon_DamageNo" + value="parcel_drk_DamageNo" /> <button follows="top|right" height="23" @@ -99,7 +145,6 @@ layout="topleft" left="10" name="back_btn" - picture_style="true" tab_stop="false" top="0" width="23" /> @@ -127,7 +172,7 @@ width="313"> <panel bg_alpha_color="DkGray2" - follows="all" + follows="top|left|right" height="533" layout="topleft" left="0" @@ -212,15 +257,6 @@ use_ellipses="true" value="SampleRegion" width="290" /> - <!-- <icon - follows="top|right" - height="16" - image_name="Icon_For_Sale" - layout="topleft" - left="3" - mouse_opaque="true" - name="icon_for_sale" - width="16" />--> <text follows="left|top|right" height="14" @@ -260,6 +296,24 @@ top_delta="0" value="Alex Superduperlongenamenton" width="205" /> + <icon + follows="top|left" + height="16" + image_name="unknown" + layout="topleft" + left="10" + name="maturity_icon" + top_delta="0" + width="18" /> + <text + follows="right|top" + height="16" + layout="topleft" + left_pad="8" + name="maturity_value" + top_delta="0" + value="unknown" + width="268" /> <accordion follows="all" height="230" @@ -272,222 +326,211 @@ layout="topleft" name="parcel_characteristics_tab" title="Parcel"> - <scroll_container - color="DkGray2" + <panel follows="all" - height="132" + height="160" layout="topleft" left="0" - name="parcel_scroll" - opaque="true" top="0" - width="290"> - <panel - follows="all" - height="165" + width="275"> + <icon + follows="top|left" + height="16" + image_name="parcel_drk_PG" layout="topleft" - left="0" + left="20" + name="rating_icon" top="0" - width="275"> - <icon - follows="top|left" - height="16" - image_name="parcel_drk_PG" - layout="topleft" - left="20" - name="rating_icon" - top="0" - width="18" /> - <text - follows="left|top" - height="16" - layout="topleft" - left_pad="8" - name="rating_label" - value="Rating:" - width="80" /> - <text - follows="right|top" - height="16" - layout="topleft" - left_pad="0" - name="rating_value" - top_delta="0" - value="unknown" - width="120" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Voice" - layout="topleft" - left="20" - name="voice_icon" - top_pad="5" - width="22" /> - <text - follows="left|top" - height="18" - layout="topleft" - left_pad="8" - name="voice_label" - top_delta="0" - value="Voice:" - width="76" /> - <text - follows="right|top" - height="18" - layout="topleft" - left_pad="0" - name="voice_value" - top_delta="0" - value="On" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Fly" - layout="topleft" - left="20" - name="fly_icon" - top_pad="3" - width="22" /> - <text - follows="left|top" - height="16" - layout="topleft" - left_pad="8" - name="fly_label" - value="Fly:" - width="76" /> - <text - follows="right|top" - height="16" - layout="topleft" - left_pad="0" - name="fly_value" - top_delta="0" - value="On" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Push" - layout="topleft" - left="20" - name="push_icon" - top_pad="3" - width="22" /> - <text - follows="left|top" - height="14" - layout="topleft" - left_pad="8" - name="push_label" - value="Push:" - width="76" /> - <text - follows="right|top" - height="14" - layout="topleft" - left_pad="0" - name="push_value" - top_delta="0" - value="Off" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Build" - layout="topleft" - left="20" - name="build_icon" - top_pad="3" - width="22" /> - <text - follows="left|top" - height="14" - layout="topleft" - left_pad="8" - name="build_label" - value="Build:" - width="76" /> - <text - follows="right|top" - height="15" - layout="topleft" - left_pad="0" - name="build_value" - top_delta="0" - value="On" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Scripts" - layout="topleft" - left="20" - name="scripts_icon" - top_pad="3" - width="22" /> - <text - follows="left|top" - height="14" - layout="topleft" - left_pad="8" - name="scripts_label" - value="Scripts:" - width="76" /> - <text - follows="right|top" - height="14" - layout="topleft" - left_pad="0" - name="scripts_value" - top_delta="0" - value="On" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Damage" - layout="topleft" - left="20" - name="damage_icon" - top_pad="7" - width="22" /> - <text - follows="left|top" - height="14" - layout="topleft" - left_pad="8" - name="damage_label" - value="Damage:" - width="76" /> - <text - follows="right|top" - height="14" - layout="topleft" - left_pad="0" - name="damage_value" - top_delta="0" - value="Off" - width="60" /> - <button - follows="bottom|right" - height="19" - label="About Land" - layout="topleft" - name="about_land_btn" - right="-5" - tab_stop="false" - top="138" - width="90"> - <click_callback - function="ShowFloater" - parameter="about_land" /> - </button> - </panel> - </scroll_container> + width="18" /> + <text + follows="left|top" + height="16" + layout="topleft" + left_pad="8" + name="rating_label" + value="Rating:" + width="80" /> + <text + follows="right|top" + height="16" + layout="topleft" + left_pad="0" + name="rating_value" + top_delta="0" + value="unknown" + width="120" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Voice" + layout="topleft" + left="20" + name="voice_icon" + top_pad="5" + width="22" /> + <text + follows="left|top" + height="18" + layout="topleft" + left_pad="8" + name="voice_label" + top_delta="0" + value="Voice:" + width="76" /> + <text + follows="right|top" + height="18" + layout="topleft" + left_pad="0" + name="voice_value" + top_delta="0" + value="On" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Fly" + layout="topleft" + left="20" + name="fly_icon" + top_pad="3" + width="22" /> + <text + follows="left|top" + height="16" + layout="topleft" + left_pad="8" + name="fly_label" + value="Fly:" + width="76" /> + <text + follows="right|top" + height="16" + layout="topleft" + left_pad="0" + name="fly_value" + top_delta="0" + value="On" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Push" + layout="topleft" + left="20" + name="push_icon" + top_pad="3" + width="22" /> + <text + follows="left|top" + height="14" + layout="topleft" + left_pad="8" + name="push_label" + value="Push:" + width="76" /> + <text + follows="right|top" + height="14" + layout="topleft" + left_pad="0" + name="push_value" + top_delta="0" + value="Off" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Build" + layout="topleft" + left="20" + name="build_icon" + top_pad="3" + width="22" /> + <text + follows="left|top" + height="14" + layout="topleft" + left_pad="8" + name="build_label" + value="Build:" + width="76" /> + <text + follows="right|top" + height="15" + layout="topleft" + left_pad="0" + name="build_value" + top_delta="0" + value="On" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Scripts" + layout="topleft" + left="20" + name="scripts_icon" + top_pad="3" + width="22" /> + <text + follows="left|top" + height="14" + layout="topleft" + left_pad="8" + name="scripts_label" + value="Scripts:" + width="76" /> + <text + follows="right|top" + height="14" + layout="topleft" + left_pad="0" + name="scripts_value" + top_delta="0" + value="On" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Damage" + layout="topleft" + left="20" + name="damage_icon" + top_pad="7" + width="22" /> + <text + follows="left|top" + height="14" + layout="topleft" + left_pad="8" + name="damage_label" + value="Damage:" + width="76" /> + <text + follows="right|top" + height="14" + layout="topleft" + left_pad="0" + name="damage_value" + top_delta="0" + value="Off" + width="60" /> + <button + follows="bottom|right" + height="19" + label="About Land" + layout="topleft" + name="about_land_btn" + right="-5" + tab_stop="false" + top="138" + width="90"> + <click_callback + function="ShowFloater" + parameter="about_land" /> + </button> + </panel> </accordion_tab> <accordion_tab expanded="false" diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 488b9582d5..5efacb68be 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -104,10 +104,9 @@ background_visible="true" follows="bottom|right" font="SansSerifSmall" height="19" - image_disabled="ForwardArrow_Disabled" + image_disabled="ForwardArrow_Off" image_selected="ForwardArrow_Press" image_unselected="ForwardArrow_Off" - picture_style="true" layout="topleft" name="overflow_btn" right="-10" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index b8fc72b754..06f0710406 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -28,7 +28,19 @@ top="10" name="bubble_text_chat" width="150" /> - + <color_swatch + border_color="0.45098 0.517647 0.607843 1" + can_apply_immediately="true" + color="0 0 0 1" + control_name="BackgroundChatColor" + follows="left|top" + height="47" + layout="topleft" + left_delta="280" + name="background" + tool_tip="Choose color for bubble chat" + top_delta="1" + width="44" /> <slider control_name="ChatBubbleOpacity" follows="left|top" @@ -37,8 +49,8 @@ initial_value="1" label="Opacity" layout="topleft" - left_delta="50" - top_pad="5" + left_delta="-230" + top_pad="-28" label_width="50" name="bubble_chat_opacity" width="200" /> @@ -200,7 +212,7 @@ Avatars: width="256" top_pad="0"/> <check_box - control_name="ArrowKeysMoveAvatar" + control_name="ArrowKeysAlwaysMove" follows="left|top" height="20" label="Arrow keys always move me" @@ -260,7 +272,7 @@ Avatars: width="315" /> <radio_item height="16" - label="In window" + label="In a window" layout="topleft" left_delta="175" name="1" @@ -272,13 +284,13 @@ Avatars: enabled_control="EnableVoiceChat" control_name="PushToTalkToggle" height="20" - label="Use Push-to-talk in toggle mode" + label="Toggle mode for microphone when I press the Speak trigger key:" layout="topleft" left="30" name="push_to_talk_toggle_check" width="237" top_pad="-25" - tool_tip="When in toggle mode, press and release the push-to-talk trigger to switch your microphone on and off. When not in toggle mode, the microphone is active only when the trigger is held down."/> + tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."/> <line_editor follows="top|left" control_name="PushToTalkButton" @@ -288,7 +300,7 @@ Avatars: left_delta="50" max_length="254" name="modifier_combo" - label="Push-to-talk trigger" + label="Push-to-Speak trigger" top_pad="0" width="280" /> <button diff --git a/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml index 159323538c..a94df4150d 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml @@ -73,7 +73,6 @@ layout="topleft" left_delta="137" name="enable_this_popup" - picture_style="true" top_pad="10" width="43"> <button.commit_callback @@ -92,7 +91,6 @@ layout="topleft" left_pad="50" name="disable_this_popup" - picture_style="true" top_delta="0" width="43"> <button.commit_callback diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 051cb51d25..645863e7a4 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -220,37 +220,12 @@ <color_swatch border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" - color="0 0 0 1" - control_name="BackgroundChatColor" - follows="left|top" - height="47" - layout="topleft" - left="180" - name="background" - top_pad="-17" - width="44" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_pad="5" - mouse_opaque="false" - name="text_box8" - top_delta="5" - width="95"> - Bubble - </text> - <color_swatch - border_color="0.45098 0.517647 0.607843 1" - can_apply_immediately="true" color="0.6 0.6 1 1" control_name="HTMLLinkColor" follows="left|top" height="47" layout="topleft" - left="350" + left="180" name="links" top_pad="-17" width="44" /> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index b1308a1942..9b10edde33 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -109,19 +109,7 @@ name="ui_scale_slider" top_pad="2" width="180" /> - <spinner - control_name="UIScaleFactor" - height="16" - increment="0.025" - initial_value="1" - layout="topleft" - left_pad="10" - max_val="1.4" - min_val="0.75" - name="ui_scale_slider" - top_delta="0" - width="58" /> - <text + <text type="string" length="1" follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index ce7939c00f..acf4601bfe 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -94,6 +94,7 @@ layout="topleft" left="30" mouse_opaque="false" + name="Logs:" top_pad="10" width="350"> Logs: @@ -184,6 +185,7 @@ layout="topleft" left_delta="0" mouse_opaque="false" + name="log_path_desc" top_pad="1" width="128" text_color="LtGray_50"> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index 832c9775ce..d454b9e5c8 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -40,7 +40,6 @@ layout="topleft" left_pad="16" name="mute_audio" - picture_style="true" tab_stop="false" top_delta="-2" width="22" /> @@ -86,7 +85,6 @@ layout="topleft" left_pad="16" name="mute_wind" - picture_style="true" tab_stop="false" top_delta="-2" width="22" /> @@ -122,7 +120,6 @@ layout="topleft" left_pad="16" name="mute_ui" - picture_style="true" tab_stop="false" top_delta="-2" width="22" /> @@ -158,7 +155,6 @@ layout="topleft" left_pad="16" name="mute_media" - picture_style="true" tab_stop="false" top_delta="-2" width="22" /> @@ -194,7 +190,6 @@ layout="topleft" left_pad="16" name="mute_sfx" - picture_style="true" tab_stop="false" top_delta="-2" width="22" /> @@ -230,19 +225,21 @@ layout="topleft" left_pad="16" name="mute_music" - picture_style="true" tab_stop="false" top_delta="-2" width="22" /> - <check_box - height="16" - control_name ="EnableVoiceChat" - disabled_control="CmdLineDisableVoice" - label="Enable Voice" - layout="topleft" - left="22" + <check_box + label_text.halign="left" + follows="right|top" + height="16" + control_name ="EnableVoiceChat" + disabled_control="CmdLineDisableVoice" + label="Voice" + left="50" name="enable_voice_check" - width="100"> + top_pad="5" + width="110" + > </check_box> <slider control_name="AudioLevelVoice" @@ -252,16 +249,15 @@ height="15" increment="0.05" initial_value="0.5" - label="Voice" - label_width="60" + label_width="0" layout="topleft" - left="100" + left="165" + top_delta="0" name="Voice Volume" show_text="false" slider_label.halign="right" - top_pad="-15" volume="true" - width="250"> + width="185"> <slider.commit_callback function="Pref.setControlFalse" parameter="MuteVoice" /> @@ -278,7 +274,6 @@ layout="topleft" left_pad="16" name="mute_voice" - picture_style="true" tab_stop="false" top_delta="-2" width="22" /> @@ -296,7 +291,7 @@ <icon follows="left" height="18" - image_name="CameraView_Off" + image_name="Cam_FreeCam_Off" name="camera_icon" mouse_opaque="false" visible="true" @@ -323,32 +318,33 @@ height="16" label="Camera position" left_pad="1" - follows="topleft" + follows="topleft" name="0" top_delta="-30" width="200" /> <radio_item height="16" - follows="topleft" + follows="topleft" label="Avatar position" left_delta="0" name="1" top_delta="19" width="200" /> </radio_group> - <button - control_name="ShowDeviceSettings" - follows="left|bottom" - height="19" - is_toggle="true" - label="Input / Output Devices" - layout="topleft" - left="165" - top_pad="12" - name="device_settings_btn" - width="190" /> + <button + control_name="ShowDeviceSettings" + follows="left|bottom" + height="19" + is_toggle="true" + label="Input/Output Devices" + layout="topleft" + left="165" + top_pad="12" + name="device_settings_btn" + width="190"> + </button> <panel - background_visible="true" + background_visible="true" bg_alpha_color="DkGray" visiblity_control="ShowDeviceSettings" border="false" @@ -357,8 +353,13 @@ label="DeviceSettings" layout="topleft" left="0" - name="Device Settings" + name="device_settings_panel" + class="panel_voice_device_settings" width="501"> + <panel.string + name="default_text"> + Default + </panel.string> <icon height="18" image_name="Microphone_On" @@ -382,6 +383,7 @@ </text> <combo_box height="19" + control_name="VoiceInputAudioDevice" layout="topleft" left="165" max_chars="128" @@ -400,7 +402,8 @@ width="200"> My volume: </text> - <slider + <slider_bar + control_name="AudioLevelMic" follows="left|top" height="17" increment="0.05" @@ -492,6 +495,7 @@ Output </text> <combo_box + control_name="VoiceOutputAudioDevice" height="19" layout="topleft" left="165" @@ -500,17 +504,4 @@ top_pad="0" width="200" /> </panel> - <!-- Until new panel is hooked up to code, we need to be able to get to - the old window to change input devices. James --> - <button - follows="left|bottom" - label="Old" - name="legacy_device_window_btn" - height="16" - left="20" - top="-270" - width="40" - commit_callback.function="Floater.Show" - commit_callback.parameter="pref_voicedevicesettings" - /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index b21fbc1795..3bdd7114ee 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -82,7 +82,6 @@ image_unselected="media_btn_back.png" layout="topleft" tool_tip="Step back" - picture_style="true" width="22" top_delta="4"> <button.commit_callback @@ -103,7 +102,6 @@ image_unselected="media_btn_forward.png" layout="topleft" tool_tip="Step forward" - picture_style="true" top_delta="0" min_width="17" width="17"> @@ -141,7 +139,6 @@ image_unselected="media_btn_home.png" layout="topleft" tool_tip="Home page" - picture_style="true" min_width="22" width="22"> <button.commit_callback @@ -162,7 +159,6 @@ image_unselected="button_anim_stop.tga" layout="topleft" tool_tip="Stop media" - picture_style="true" min_width="22" width="22"> <button.commit_callback @@ -199,7 +195,6 @@ image_unselected="media_btn_reload.png" layout="topleft" tool_tip="Reload" - picture_style="true" min_width="22" width="22"> <button.commit_callback @@ -219,7 +214,6 @@ image_selected="media_btn_stoploading.png" image_unselected="media_btn_stoploading.png" layout="topleft" - picture_style="true" tool_tip = "Stop loading" min_width="22" width="22"> @@ -241,7 +235,6 @@ image_unselected="button_anim_play.tga" layout="topleft" tool_tip = "Play media" - picture_style="true" min_width="22" width="22"> <button.commit_callback @@ -261,8 +254,7 @@ image_selected="button_anim_pause.tga" image_unselected="button_anim_pause.tga" layout="topleft" - tool_tip = "Pause media" - picture_style="true"> + tool_tip = "Pause media"> <button.commit_callback function="MediaCtrl.Pause" /> </button> @@ -367,7 +359,6 @@ function="MediaCtrl.CommitURL" /> is_toggle="true" layout="topleft" scale_image="false" - picture_style="true" tool_tip="Mute This Media" top_delta="22" min_width="24" @@ -391,7 +382,6 @@ function="MediaCtrl.CommitURL" /> image_unselected="media_btn_scrollup.png" layout="topleft" tool_tip="Volume up" - picture_style="true" scale_image="true" min_width="20" width="20" > @@ -414,7 +404,6 @@ function="MediaCtrl.CommitURL" /> image_unselected="media_btn_scrolldown.png" layout="topleft" tool_tip="Volume down" - picture_style="true" scale_image="true" min_width="20" width="20"> @@ -423,6 +412,8 @@ function="MediaCtrl.CommitURL" /> </button> </layout_panel> <!-- Scroll pad --> +<!-- +disabled <layout_panel name="media_panel_scroll" auto_resize="false" @@ -446,7 +437,6 @@ function="MediaCtrl.CommitURL" /> image_unselected="media_btn_scrollup.png" layout="topleft" tool_tip="Scroll up" - picture_style="true" scale_image="false" left="12" top_delta="4" @@ -460,7 +450,6 @@ function="MediaCtrl.CommitURL" /> layout="topleft" left="3" tool_tip="Scroll left" - picture_style="true" scale_image="false" top="12" min_width="8" @@ -473,7 +462,6 @@ function="MediaCtrl.CommitURL" /> layout="topleft" left_pad="9" tool_tip="Scroll right" - picture_style="true" scale_image="false" top_delta="0" min_width="8" @@ -486,12 +474,13 @@ function="MediaCtrl.CommitURL" /> layout="topleft" left="12" tool_tip="Scroll down" - picture_style="true" scale_image="false" top="20" min_width="8" width="8" /> </layout_panel> +disabled +--> <layout_panel name="zoom_frame" auto_resize="false" @@ -505,14 +494,32 @@ function="MediaCtrl.CommitURL" /> image_selected="media_btn_optimalzoom.png" image_unselected="media_btn_optimalzoom.png" layout="topleft" - tool_tip="Zoom" - picture_style="true" + tool_tip="Zoom into media" min_width="22" width="22"> <button.commit_callback function="MediaCtrl.Zoom" /> </button> </layout_panel> + <layout_panel + name="close" + auto_resize="false" + user_resize="false" + layout="topleft" + min_width="21" + width="21" > + <button + height="22" + image_selected="media_btn_done.png" + image_unselected="media_btn_done.png" + layout="topleft" + tool_tip ="Zoom Back" + top_delta="-4" + width="21" > + <button.commit_callback + function="MediaCtrl.Close" /> + </button> + </layout_panel> <!-- <panel height="22" @@ -542,7 +549,6 @@ function="MediaCtrl.CommitURL" /> image_unselected="media_btn_newwindow.png" layout="topleft" tool_tip = "Open URL in browser" - picture_style="true" top_delta="-3" min_width="24" width="24" > @@ -567,26 +573,6 @@ function="MediaCtrl.CommitURL" /> </panel> --> <layout_panel - name="close" - auto_resize="false" - user_resize="false" - layout="topleft" - min_width="21" - width="21" > - <button - height="22" - image_selected="media_btn_done.png" - image_unselected="media_btn_done.png" - layout="topleft" - tool_tip ="Close media control" - picture_style="true" - top_delta="-4" - width="21" > - <button.commit_callback - function="MediaCtrl.Close" /> - </button> - </layout_panel> - <layout_panel width="0" layout="topleft" user_resize="false" /> diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index c3a92f9d9a..a0055383b1 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -31,7 +31,6 @@ color="DkGray2" follows="all" height="485" - min_height="300" layout="topleft" name="profile_scroll" reserve_scroll_corner="true" @@ -59,7 +58,7 @@ default_image_name="None" enabled="false" follows="top|left" - height="117" + height="102" layout="topleft" left="0" name="2nd_life_pic" @@ -81,7 +80,7 @@ height="95" layout="topleft" left="107" - max_length="512" + textbox.max_length="512" name="sl_description_edit" top_pad="-3" width="173" @@ -103,7 +102,7 @@ default_image_name="None" enabled="false" follows="top|left" - height="117" + height="102" layout="topleft" left="0" name="real_world_pic" @@ -124,7 +123,7 @@ height="95" layout="topleft" left="107" - max_length="512" + textbox.max_length="512" name="fl_description_edit" top_pad="-3" width="173" diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml index 4b2e901718..b015346a79 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml @@ -21,7 +21,6 @@ image_overlay="BackArrow_Off" layout="topleft" name="back" - picture_style="true" left="10" tab_stop="false" top="2" diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml index a312e4cf13..18c2228906 100644 --- a/indra/newview/skins/default/xui/en/panel_progress.xml +++ b/indra/newview/skins/default/xui/en/panel_progress.xml @@ -129,7 +129,6 @@ layout="topleft" left="-106" name="cancel_btn" - picture_style="true" top="700" width="90" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_scrolling_param.xml b/indra/newview/skins/default/xui/en/panel_scrolling_param.xml index 21ecd01839..44afadf65a 100644 --- a/indra/newview/skins/default/xui/en/panel_scrolling_param.xml +++ b/indra/newview/skins/default/xui/en/panel_scrolling_param.xml @@ -56,7 +56,6 @@ layout="topleft" left="2" name="less" - picture_style="true" tab_stop="false" top="0" width="132" /> @@ -70,7 +69,6 @@ layout="topleft" left_pad="2" name="more" - picture_style="true" tab_stop="false" top_delta="0" width="132" /> diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index 3f64c9c633..a9874f4553 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<!-- Side tray cannot show background because it is always +<!-- Side tray cannot show background because it is always partially on screen to hold tab buttons. --> <side_tray name="sidebar" @@ -10,7 +10,7 @@ > <!-- Individual tabs must show background to have seemless appearance up to tray panel header word like "Home". - Embedded panels are inset by a pixel and so their + Embedded panels are inset by a pixel and so their backgrounds will not block the world fully. --> <sidetray_tab name="sidebar_home" @@ -70,7 +70,7 @@ </panel_container> </sidetray_tab> - + <sidetray_tab name="sidebar_places" help_topic="sidebar_places" @@ -128,4 +128,23 @@ /> </sidetray_tab> + <sidetray_tab + name="sidebar_inventory" + help_topic="sidebar_inventory" + tab_title="Inventory" + description="Browse your inventory." + image="TabIcon_Things_Off" + image_selected="TabIcon_Things_Selected" + mouse_opaque="false" + background_visible="true" + > + <panel + class="sidepanel_inventory" + name="sidepanel_inventory" + filename="sidepanel_inventory.xml" + label="Edit Inventory" + font="SansSerifBold" + /> + </sidetray_tab> + </side_tray> diff --git a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml index 9845a9eb78..0a9c70303e 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml @@ -19,16 +19,17 @@ top="4" value="Side Panel" width="255" /> - <button + <button follows="left|right|top" - font="SansSerif" - height="23" - label="?" + height="16" + image_selected="Icon_Help_Press" + image_unselected="Icon_Help_Foreground" + image_disabled="Icon_Help_Press" layout="topleft" name="show_help" - top="5" - right="-8" - width="28" + top="10" + right="-11" + width="16" tool_tip="Show Help"> <button.commit_callback function="Button.ShowHelp" /> diff --git a/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml index 247054772e..9636e32187 100644 --- a/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml +++ b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml @@ -12,7 +12,7 @@ bg_alpha_color="DkGray2" class="panel_sidetray_home_info" follows="left|top|right" - height="120" + height="90" layout="topleft" left="15" top="17" @@ -42,7 +42,7 @@ width="20" /> <text follows="left|right|bottom" - height="120" + height="90" layout="topleft" left="10" mouse_opaque="false" @@ -59,7 +59,7 @@ bg_alpha_color="DkGray2" class="panel_sidetray_home_info" follows="left|top|right" - height="120" + height="90" layout="topleft" left="15" top_pad="15" @@ -89,7 +89,7 @@ image_name="TabIcon_Places_Selected"/> <text follows="all" - height="120" + height="90" layout="topleft" left="10" mouse_opaque="false" @@ -106,7 +106,7 @@ bg_alpha_color="DkGray2" class="panel_sidetray_home_info" follows="left|top|right" - height="120" + height="90" layout="topleft" left="15" top_pad="15" @@ -136,7 +136,7 @@ image_name="TabIcon_Me_Selected"/> <text follows="all" - height="120" + height="90" layout="topleft" left="10" mouse_opaque="false" @@ -153,7 +153,7 @@ bg_alpha_color="DkGray2" class="panel_sidetray_home_info" follows="left|top|right" - height="120" + height="90" layout="topleft" left="15" top_pad="15" @@ -183,7 +183,7 @@ image_name="TabIcon_Appearance_Selected"/> <text follows="all" - height="120" + height="90" layout="topleft" left="10" mouse_opaque="false" @@ -195,4 +195,51 @@ Change your appearance and current look. </text> </panel> + <panel + background_visible="true" + bg_alpha_color="DkGray2" + class="panel_sidetray_home_info" + follows="left|top|right" + height="90" + layout="topleft" + left="15" + top_pad="15" + name="sidebar_inventory" + width="303"> + <text + follows="left|right|top" + font="SansSerifBigBold" + height="30" + layout="topleft" + left="10" + mouse_opaque="false" + name="tab_name" + text_color="EmphasisColor" + top="10" + value="My Inventory" + width="200" + word_wrap="true" /> + <icon + follows="top|right" + height="20" + layout="topleft" + name="tab_icon" + right="-10" + top="10" + width="20" + image_name="TabIcon_Inventory_Selected"/> + <text + follows="all" + height="90" + layout="topleft" + left="10" + mouse_opaque="false" + name="tab_description" + right="-10" + text_color="white" + top="40" + word_wrap="true"> + Browse your inventory. + </text> + </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml index 4169c6245b..01204ba779 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml @@ -10,12 +10,10 @@ name="history_accordion" width="380"> <accordion_tab - can_resize="false" layout="topleft" name="today" title="Today"> <flat_list_view - draw_heading="false" follows="all" height="150" layout="topleft" @@ -26,12 +24,10 @@ </flat_list_view> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" name="yesterday" title="Yesterday"> <flat_list_view - draw_heading="false" follows="all" height="150" layout="topleft" @@ -42,12 +38,10 @@ </flat_list_view> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" name="2_days_ago" title="2 days ago"> <flat_list_view - draw_heading="false" follows="all" height="150" layout="topleft" @@ -58,12 +52,10 @@ </flat_list_view> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" name="3_days_ago" title="3 days ago"> <flat_list_view - draw_heading="false" follows="all" height="150" layout="topleft" @@ -74,12 +66,10 @@ </flat_list_view> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" name="4_days_ago" title="4 days ago"> <flat_list_view - draw_heading="false" follows="all" height="150" layout="topleft" @@ -90,12 +80,10 @@ </flat_list_view> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" name="5_days_ago" title="5 days ago"> <flat_list_view - draw_heading="false" follows="all" height="150" layout="topleft" @@ -106,12 +94,10 @@ </flat_list_view> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" name="6_days_and_older" title="6 days and older"> <flat_list_view - draw_heading="false" follows="all" height="150" layout="topleft" @@ -122,12 +108,10 @@ </flat_list_view> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" name="1_month_and_older" title="1 month and older"> <flat_list_view - draw_heading="false" follows="all" height="150" layout="topleft" @@ -138,12 +122,10 @@ </flat_list_view> </accordion_tab> <accordion_tab - can_resize="false" layout="topleft" name="6_months_and_older" title="6 months and older"> <flat_list_view - draw_heading="false" follows="all" height="150" layout="topleft" @@ -176,7 +158,6 @@ layout="topleft" left="10" name="gear_btn" - picture_style="true" top="5" width="18" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml index f559343b34..1f67a0a732 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml @@ -49,24 +49,13 @@ width="242" /> <button follows="right" - height="16" - image_pressed="Info_Press" - image_unselected="Info_Over" - left_pad="3" - right="-31" - name="info_btn" - picture_style="true" - top_delta="-2" - width="16" /> - <button - follows="right" height="20" image_overlay="ForwardArrow_Off" layout="topleft" left_pad="5" right="-3" name="profile_btn" - picture_style="true" top_delta="-2" + visible="false" width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml new file mode 100644 index 0000000000..cbcc3f10ad --- /dev/null +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="570"
+ label="Things"
+ layout="topleft"
+ min_height="350"
+ min_width="240"
+ name="objects panel"
+ width="333">
+ <panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="sidepanel__inventory_panel"
+ top="0"
+ label=""
+ height="570"
+ visible="true"
+ width="330">
+ <panel
+ class="panel_main_inventory"
+ filename="panel_main_inventory.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="panel_main_inventory"
+ top="0"
+ label=""
+ height="500"
+ width="330" />
+ <panel
+ height="25"
+ layout="bottomright"
+ help_topic="item_button_tab"
+ name="button_panel"
+ left="5"
+ bottom="5"
+ width="313">
+ <button
+ enabled="true"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Info"
+ layout="topleft"
+ left="0"
+ name="info_btn"
+ top="0"
+ width="60" />
+ <button
+ enabled="true"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Share"
+ layout="topleft"
+ left_pad="5"
+ name="share_btn"
+ top="0"
+ width="60" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Wear"
+ layout="topleft"
+ left="130"
+ name="wear_btn"
+ top="0"
+ width="60" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Play"
+ layout="topleft"
+ name="play_btn"
+ left="130"
+ top="0"
+ width="50" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Teleport"
+ layout="topleft"
+ left="130"
+ name="teleport_btn"
+ top="0"
+ width="77" />
+ </panel>
+ </panel>
+
+ <panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ class="sidepanel_item_info"
+ filename="sidepanel_item_info.xml"
+ name="sidepanel__item_panel"
+ top="0"
+ label=""
+ height="570"
+ visible="false"
+ width="330">
+ </panel>
+
+ <panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ class="sidepanel_task_info"
+ filename="sidepanel_task_info.xml"
+ name="sidepanel__task_panel"
+ top="0"
+ label=""
+ height="570"
+ visible="false"
+ width="330">
+ </panel>
+
+</panel>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml new file mode 100644 index 0000000000..39cd75074e --- /dev/null +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -0,0 +1,511 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ auto_tile="true"
+ height="570"
+ layout="topleft"
+ name="item properties"
+ help_topic="item_properties"
+ save_rect="true"
+ title="Inventory Item Properties"
+ width="333">
+ <panel.string
+ name="unknown">
+ (unknown)
+ </panel.string>
+ <panel.string
+ name="public">
+ (public)
+ </panel.string>
+ <panel.string
+ name="you_can">
+ You can:
+ </panel.string>
+ <panel.string
+ name="owner_can">
+ Owner can:
+ </panel.string>
+ <panel.string
+ name="acquiredDate">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </panel.string>
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ right="-50"
+ mouse_opaque="true"
+ name="IconLocked"
+ top="4"
+ width="18" />
+ <button
+ follows="top|right"
+ height="25"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ picture_style="true"
+ right="-5"
+ tab_stop="false"
+ top="0"
+ width="25" />
+ <panel
+ follows="all"
+ height="500"
+ label=""
+ layout="topleft"
+ left="5"
+ help_topic=""
+ top="30"
+ border="1"
+ width="313">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="5"
+ name="LabelItemNameTitle"
+ top="5"
+ width="78">
+ Name:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ max_length="63"
+ name="LabelItemName"
+ top_delta="0"
+ width="225" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="5"
+ name="LabelItemDescTitle"
+ top_delta="20"
+ width="78">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ max_length="127"
+ name="LabelItemDesc"
+ top_delta="0"
+ width="225" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LabelCreatorTitle"
+ top="65"
+ width="78">
+ Creator:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="LabelCreatorName"
+ top_delta="0"
+ width="200">
+ Nicole Linden
+ </text>
+ <button
+ follows="top|right"
+ font="SansSerifSmall"
+ height="16"
+ label="Profile..."
+ layout="topleft"
+ left_delta="144"
+ name="BtnCreator"
+ top_delta="0"
+ width="78" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LabelOwnerTitle"
+ top="85"
+ width="78">
+ Owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="LabelOwnerName"
+ top_delta="0"
+ width="200">
+ Thrax Linden
+ </text>
+ <button
+ follows="top|right"
+ font="SansSerifSmall"
+ height="16"
+ label="Profile..."
+ layout="topleft"
+ left_delta="144"
+ name="BtnOwner"
+ top_delta="0"
+ width="78" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LabelAcquiredTitle"
+ top="105"
+ width="78">
+ Acquired:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="LabelAcquiredDate"
+ top_delta="0"
+ width="252">
+ Wed May 24 12:50:46 2006
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="OwnerLabel"
+ top="125"
+ width="78">
+ You:
+ </text>
+ <check_box
+ height="16"
+ label="Edit"
+ layout="topleft"
+ left_pad="5"
+ name="CheckOwnerModify"
+ top_delta="0"
+ width="78" />
+ <check_box
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="0"
+ name="CheckOwnerCopy"
+ top_pad="5"
+ width="88" />
+ <check_box
+ height="16"
+ label="Resell"
+ layout="topleft"
+ left_delta="0"
+ name="CheckOwnerTransfer"
+ top_pad="5"
+ width="106" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="AnyoneLabel"
+ top_pad="5"
+ width="78">
+ Anyone:
+ </text>
+ <check_box
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_pad="5"
+ name="CheckEveryoneCopy"
+ top_delta="0"
+ width="130" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="GroupLabel"
+ top_pad="5"
+ width="78">
+ Group:
+ </text>
+ <check_box
+ height="16"
+ label="Share"
+ layout="topleft"
+ left_pad="5"
+ name="CheckShareWithGroup"
+ top_delta="5"
+ width="106" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="NextOwnerLabel"
+ top_pad="5"
+ width="78">
+ Next owner:
+ </text>
+ <check_box
+ height="16"
+ label="Edit"
+ layout="topleft"
+ left_pad="5"
+ name="CheckNextOwnerModify"
+ top_delta="0"
+ width="78" />
+ <check_box
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="0"
+ name="CheckNextOwnerCopy"
+ top_pad="5"
+ width="88" />
+ <check_box
+ height="16"
+ label="Resell"
+ layout="topleft"
+ left_delta="0"
+ name="CheckNextOwnerTransfer"
+ top_pad="5"
+ width="106" />
+ <check_box
+ height="16"
+ label="For Sale"
+ layout="topleft"
+ left="10"
+ name="CheckPurchase"
+ top_pad="5"
+ width="78" />
+ <combo_box
+ height="19"
+ left_pad="5"
+ layout="topleft"
+ follows="left|top"
+ name="combobox sale copy"
+ width="90">
+ <combo_box.item
+ label="Copy"
+ name="Copy"
+ value="Copy" />
+ <combo_box.item
+ label="Original"
+ name="Original"
+ value="Original" />
+ </combo_box>
+ <spinner
+ follows="left|top"
+ decimal_digits="0"
+ increment="1"
+ control_name="Edit Cost"
+ name="Edit Cost"
+ label="Price: L$"
+ label_width="60"
+ left="10"
+ width="180"
+ min_val="1"
+ height="19"
+ max_val="999999999"
+ top_pad="5"/>
+ <!--line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="5"
+ max_length="25"
+ name="EditPrice"
+ top_delta="0"
+ width="242" /-->
+ <!--text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="BaseMaskDebug"
+ top="155"
+ width="330">
+ B:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="OwnerMaskDebug"
+ top_delta="0"
+ width="270">
+ O:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="GroupMaskDebug"
+ top_delta="0"
+ width="210">
+ G:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="EveryoneMaskDebug"
+ top_delta="0"
+ width="150">
+ E:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="NextMaskDebug"
+ top_delta="0"
+ width="90">
+ N:
+ </text-->
+ <!--text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="SaleLabel"
+ top_pad="5"
+ width="330">
+ Mark Item:
+ </text-->
+ <!--radio_group
+ draw_border="false"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="RadioSaleType"
+ top_delta="0"
+ width="252">
+ <radio_item
+ height="16"
+ label="Original"
+ layout="topleft"
+ left="0"
+ name="radio"
+ top="0"
+ width="70" />
+ <radio_item
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="60"
+ name="radio2"
+ top_delta="0"
+ width="70" />
+ </radio_group-->
+ <!--text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="TextPrice"
+ top_pad="5"
+ width="78">
+ Price: L$
+ </text-->
+ </panel>
+ <panel
+ height="25"
+ layout="bottomright"
+ help_topic="button_tab"
+ name="button_panel"
+ left="5"
+ bottom="5"
+ width="313">
+ <button
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Edit"
+ layout="topleft"
+ left="0"
+ name="edit_btn"
+ top="0"
+ width="50" />
+ <button
+ follows="bottom|right"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-1"
+ top="0"
+ width="70" />
+ <button
+ follows="bottom|right"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Save"
+ layout="topleft"
+ name="save_btn"
+ left_pad="-135"
+ top="0"
+ width="60" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index e842517853..c850dce141 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -73,8 +73,13 @@ <string name="TooltipParcelUrl">Click to view this parcel's description</string> <string name="TooltipTeleportUrl">Click to teleport to this location</string> <string name="TooltipObjectIMUrl">Click to view this object's description</string> + <string name="TooltipMapUrl">Click to view this location on a map</string> <string name="TooltipSLAPP">Click to run the secondlife:// command</string> <string name="CurrentURL" value=" CurrentURL: [CurrentURL]" /> + + <!-- text for SLURL labels --> + <string name="SLurlLabelTeleport">Teleport to</string> + <string name="SLurlLabelShowOnMap">Show Map for</string> <!-- ButtonToolTips, llfloater.cpp --> <string name="BUTTON_CLOSE_DARWIN">Close (⌘W)</string> @@ -2042,9 +2047,6 @@ this texture in your inventory <!-- panel contents --> <string name="PanelContentsNewScript">New Script</string> - <!-- panel avatar --> - <!-- <string name="None">None</string> Duplicate--> - <!-- Mute --> <string name="MuteByName">(by name)</string> <string name="MuteAgent">(resident)</string> @@ -2301,9 +2303,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Body Thick">Body Thick</string> <string name="Body Thickness">Body Thickness</string> <string name="Body Thin">Body Thin</string> -<string name="Bottom">Bottom</string> -<string name="Bottom Left">Bottom Left</string> -<string name="Bottom Right">Bottom Right</string> <string name="Bow Legged">Bow Legged</string> <string name="Breast Buoyancy">Breast Buoyancy</string> @@ -2325,13 +2324,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="no bustle">No Bustle</string> <string name="more bustle">More Bustle</string> -<string name="Center">Center</string> -<string name="Center 2">Center 2</string> <string name="Chaplin">Chaplin</string> <string name="Cheek Bones">Cheek Bones</string> -<string name="Chest">Chest</string> <string name="Chest Size">Chest Size</string> -<string name="Chin">Chin</string> <string name="Chin Angle">Chin Angle</string> <string name="Chin Cleft">Chin Cleft</string> <string name="Chin Curtains">Chin Curtains</string> @@ -2495,22 +2490,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Jowls">Jowls</string> <string name="Knee Angle">Knee Angle</string> <string name="Knock Kneed">Knock Kneed</string> -<string name="L Forearm">L Forearm</string> -<string name="L Lower Leg">L Lower Leg</string> -<string name="L Upper Arm">L Upper Arm</string> -<string name="L Upper Leg">L Upper Leg</string> <string name="Large">Large</string> <string name="Large Hands">Large Hands</string> -<string name="Left">Left</string> -<string name="Left Ear">Left Ear</string> -<string name="Left Eyeball">Left Eyeball</string> -<string name="Left Foot">Left Foot</string> -<string name="Left Hand">Left Hand</string> -<string name="Left Hip">Left Hip</string> <string name="Left Part">Left Part</string> -<string name="Left Pec">Left Pec</string> -<string name="Left Shoulder">Left Shoulder</string> <string name="Leg Length">Leg Length</string> <string name="Leg Muscles">Leg Muscles</string> <string name="Less">Less</string> @@ -2528,7 +2511,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Less Square">Less Square</string> <string name="Less Volume">Less Volume</string> <string name="Less soul">Less soul</string> -<string name="Light">Light</string> <string name="Lighter">Lighter</string> <string name="Lip Cleft">Lip Cleft</string> <string name="Lip Cleft Depth">Lip Cleft Depth</string> @@ -2591,7 +2573,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="More soul">More soul</string> <string name="Moustache">Moustache</string> -<string name="Mouth">Mouth</string> <string name="Mouth Corner">Mouth Corner</string> <string name="Mouth Position">Mouth Position</string> <string name="Mowhawk">Mowhawk</string> @@ -2619,10 +2600,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="No Spikes">No Spikes</string> <string name="No White">No White</string> <string name="No Wrinkles">No Wrinkles</string> -<string name="None">None</string> <string name="Normal Lower">Normal Lower</string> <string name="Normal Upper">Normal Upper</string> -<string name="Nose">Nose</string> <string name="Nose Left">Nose Left</string> <string name="Nose Right">Nose Right</string> <string name="Nose Size">Nose Size</string> @@ -2662,7 +2641,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Part">Part</string> <string name="Part Bangs">Part Bangs</string> <string name="Pectorals">Pectorals</string> -<string name="Pelvis">Pelvis</string> <string name="Pigment">Pigment</string> <string name="Pigtails">Pigtails</string> <string name="Pink">Pink</string> @@ -2678,24 +2656,12 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Pop Right Eye">Pop Right Eye</string> <string name="Puffy">Puffy</string> <string name="Puffy Eyelids">Puffy Eyelids</string> -<string name="R Forearm">R Forearm</string> -<string name="R Lower Leg">R Lower Leg</string> -<string name="R Upper Arm">R Upper Arm</string> -<string name="R Upper Leg">R Upper Leg</string> <string name="Rainbow Color">Rainbow Color</string> <string name="Red Hair">Red Hair</string> <string name="Red Skin">Red Skin</string> <string name="Regular">Regular</string> <string name="Regular Muscles">Regular Muscles</string> -<string name="Right">Right</string> -<string name="Right Ear">Right Ear</string> -<string name="Right Eyeball">Right Eyeball</string> -<string name="Right Foot">Right Foot</string> -<string name="Right Hand">Right Hand</string> -<string name="Right Hip">Right Hip</string> <string name="Right Part">Right Part</string> -<string name="Right Pec">Right Pec</string> -<string name="Right Shoulder">Right Shoulder</string> <string name="Rosy Complexion">Rosy Complexion</string> <string name="Round">Round</string> <string name="Round Forehead">Round Forehead</string> @@ -2752,7 +2718,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Skinny Neck">Skinny Neck</string> <string name="Skirt Fit">Skirt Fit</string> <string name="Skirt Length">Skirt Length</string> -<string name="Skull">Skull</string> <string name="Slanted Forehead">Slanted Forehead</string> <string name="Sleeve Length">Sleeve Length</string> @@ -2775,12 +2740,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Sparse">Sparse</string> <string name="Spiked Hair">Spiked Hair</string> -<string name="Spine">Spine</string> <string name="Square">Square</string> <string name="Square Toe">Square Toe</string> <string name="Squash Head">Squash Head</string> <string name="Squash/Stretch Head">Squash/Stretch Head</string> -<string name="Stomach">Stomach</string> <string name="Stretch Head">Stretch Head</string> <string name="Sunken">Sunken</string> <string name="Sunken Chest">Sunken Chest</string> @@ -2812,9 +2775,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Tilt Right">Tilt Right</string> <string name="Toe Shape">Toe Shape</string> <string name="Toe Thickness">Toe Thickness</string> -<string name="Top">Top</string> -<string name="Top Left">Top Left</string> -<string name="Top Right">Top Right</string> <string name="Torso Length">Torso Length</string> <string name="Torso Muscles">Torso Muscles</string> <string name="Torso Scrawny">Torso Scrawny</string> @@ -2885,6 +2845,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Unnamed">(Unnamed)</string> <string name="IM_moderated_chat_label">(Moderated: Voices off by default)</string> <string name="IM_unavailable_text_label">Text chat is not available for this call.</string> + <string name="IM_muted_text_label">Your text chat has been disabled by a Group Moderator.</string> + <string name="IM_default_text_label">Click here to instant message.</string> + <string name="IM_to_label">To</string> + <string name="IM_moderator_label">(Moderator)</string> <string name="ringing-im"> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml index fcfe89c653..08c337455c 100644 --- a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <accordion_tab + font="SansSerifBold" header_bg_color="DkGray2" - header_txt_color="LtGray" header_collapse_img="Accordion_ArrowClosed_Off" header_collapse_img_pressed="Accordion_ArrowClosed_Press" header_expand_img="Accordion_ArrowOpened_Off" @@ -9,5 +9,6 @@ header_image="Accordion_Off" header_image_over="Accordion_Over" header_image_pressed="Accordion_Press" - header_image_selected="Accordion_Selected" + header_image_expanded="Accordion_Selected" + header_text_color="LtGray" /> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml index ea6997ebd5..32916c0816 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -6,6 +6,10 @@ right_text_pad="15" left_widget_pad="0" right_widget_pad="10" + top_separator_pad="5" + bottom_separator_pad="5" + top_header_pad="17" + bottom_header_pad="10" max_length="2147483647" enabled="false" track_bottom="true" diff --git a/indra/newview/skins/default/xui/en/widgets/combo_box.xml b/indra/newview/skins/default/xui/en/widgets/combo_box.xml index 9ed3749308..fa3cb9275e 100644 --- a/indra/newview/skins/default/xui/en/widgets/combo_box.xml +++ b/indra/newview/skins/default/xui/en/widgets/combo_box.xml @@ -4,7 +4,6 @@ max_chars="20" follows="right|top"> <combo_box.combo_button name="Combobox Button" - label="" hover_glow_amount="0.15" font="SansSerifSmall" scale_image="false" @@ -12,7 +11,6 @@ image_selected="ComboButton_Selected" image_disabled="ComboButton_Disabled" /> <combo_box.drop_down_button name="Drop Down Button" - label="" hover_glow_amount="0.15" font="SansSerifSmall" scale_image="true" diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml index f2e48c517d..d88bcfab1d 100644 --- a/indra/newview/skins/default/xui/en/widgets/location_input.xml +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -20,7 +20,6 @@ allow_new_values="true" > <info_button name="Place Information" - label="" width="16" height="16" follows="left|top" @@ -30,7 +29,6 @@ image_disabled_selected="Info_Off" image_disabled="Info_Off" /> <add_landmark_button name="Add Landmark" - label="" hover_glow_amount="0.15" image_hover_selected="Favorite_Star_Over" image_hover_unselected="Favorite_Star_Over" diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item.xml b/indra/newview/skins/default/xui/en/widgets/menu_item.xml new file mode 100644 index 0000000000..c98e9cb6b8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/menu_item.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Use this for the top-level menu styling --> +<menu_item + font="SansSerifSmall" + > +</menu_item> diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml index f482ff3b89..9a79243b03 100644 --- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml @@ -7,14 +7,14 @@ background_image="TextField_Search_Off" background_image_disabled="TextField_Search_Disabled" background_image_focused="TextField_Search_Active" > - <search_button label="" + <search_button top_pad="4" left_pad="4" width="13" height="13" image_unselected="Search" image_selected="Search" /> - <clear_button label="" + <clear_button image_unselected="Icon_Close_Foreground" image_selected="Icon_Close_Press" /> </search_editor> diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml index fe2f1423b7..f1401140de 100644 --- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml @@ -2,6 +2,7 @@ <tab_container tab_min_width="60" tab_max_width="150" font_halign="center" + font="SansSerif" tab_height="21"> <first_tab tab_top_image_unselected="TabTop_Left_Off" tab_top_image_selected="TabTop_Left_Selected" diff --git a/indra/newview/skins/default/xui/en/widgets/talk_button.xml b/indra/newview/skins/default/xui/en/widgets/talk_button.xml new file mode 100644 index 0000000000..d9f39b6937 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/talk_button.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Derives from LLUICtrl --> +<talk_button> + <!-- To make speak button look green when selected set: + image_selected="SegmentedBtn_Left_Selected" + image_unselected="SegmentedBtn_Left_Off" + --> + <speak_button + name="left" + label="Speak" + label_selected="Speak" + font="SansSerifSmall" + tab_stop="false" + is_toggle="true" + /> + <show_button + name="right" + label="" + left="0" + top="0" + right="20" + bottom="0" + tab_stop="false" + is_toggle="true" + image_selected="ComboButton_UpSelected" + image_unselected="ComboButton_UpOff" + /> + <monitor + name="monitor" + left="0" + top="18" + right="18" + bottom="0" + /> +</talk_button> diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml index 071d505569..5545ab29e0 100644 --- a/indra/newview/skins/default/xui/es/floater_about.xml +++ b/indra/newview/skins/default/xui/es/floater_about.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_about" title="Acerca de [APP_NAME]"> +<floater name="floater_about" title="ACERCA DE [APP_NAME]"> <tab_container name="about_tab"> <panel name="credits_panel"> <text_editor name="credits_editor"> diff --git a/indra/newview/skins/default/xui/es/floater_about_land.xml b/indra/newview/skins/default/xui/es/floater_about_land.xml index bc775c1b1c..7575df4b98 100644 --- a/indra/newview/skins/default/xui/es/floater_about_land.xml +++ b/indra/newview/skins/default/xui/es/floater_about_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterland" title="Acerca del terreno"> +<floater name="floaterland" title="ACERCA DEL TERRENO"> <tab_container name="landtab"> <panel label="General" name="land_general_panel"> <text name="Name:"> diff --git a/indra/newview/skins/default/xui/es/floater_auction.xml b/indra/newview/skins/default/xui/es/floater_auction.xml index c6d89891bc..5196ac0b78 100644 --- a/indra/newview/skins/default/xui/es/floater_auction.xml +++ b/indra/newview/skins/default/xui/es/floater_auction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_auction" title="Empezar venta de terreno Linden"> +<floater name="floater_auction" title="EMPEZAR VENTA DE TERRENO LINDEN"> <check_box label="Incluir la valla amarilla de selección" name="fence_check"/> <button label="Foto" label_selected="Foto" name="snapshot_btn"/> <button label="OK" label_selected="OK" name="ok_btn"/> diff --git a/indra/newview/skins/default/xui/es/floater_avatar_picker.xml b/indra/newview/skins/default/xui/es/floater_avatar_picker.xml index 68a56ac678..df0147b191 100644 --- a/indra/newview/skins/default/xui/es/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/es/floater_avatar_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatarpicker" title="Elegir a un residente"> +<floater name="avatarpicker" title="ELEGIR A UN RESIDENTE"> <tab_container name="ResidentChooserTabs"> <panel label="Buscar" name="SearchPanel"> <text name="InstructSearchResidentName"> diff --git a/indra/newview/skins/default/xui/es/floater_avatar_textures.xml b/indra/newview/skins/default/xui/es/floater_avatar_textures.xml index 6344768c7f..8febe4b0a9 100644 --- a/indra/newview/skins/default/xui/es/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/es/floater_avatar_textures.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatar_texture_debug" title="Texturas del avatar"> +<floater name="avatar_texture_debug" title="TEXTURAS DEL AVATAR"> <text name="baked_label"> Texturas predeterminadas </text> diff --git a/indra/newview/skins/default/xui/es/floater_beacons.xml b/indra/newview/skins/default/xui/es/floater_beacons.xml index 9282cb04a6..2df90bc911 100644 --- a/indra/newview/skins/default/xui/es/floater_beacons.xml +++ b/indra/newview/skins/default/xui/es/floater_beacons.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="beacons" title="Balizas"> +<floater name="beacons" title="BALIZAS"> <panel name="beacons_panel"> <check_box label="Objetos con script sólo al tocarlos" name="touch_only"/> <check_box label="Objetos con script" name="scripted"/> diff --git a/indra/newview/skins/default/xui/es/floater_build_options.xml b/indra/newview/skins/default/xui/es/floater_build_options.xml index c3e4acacf0..3d839bf645 100644 --- a/indra/newview/skins/default/xui/es/floater_build_options.xml +++ b/indra/newview/skins/default/xui/es/floater_build_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="build options floater" title="Opciones de la cuadrÃcula"> +<floater name="build options floater" title="OPCIONES DE LA CUADRÃCULA"> <spinner label="Unidad de la cuadrÃcula (metros)" name="GridResolution" width="250" label_width="192"/> <spinner label="Graduación de la cuadrÃcula (metros)" name="GridDrawSize" width="250" label_width="192"/> <check_box label="Activar subunidades" name="GridSubUnit"/> diff --git a/indra/newview/skins/default/xui/es/floater_bulk_perms.xml b/indra/newview/skins/default/xui/es/floater_bulk_perms.xml index 3251713074..0553f4c672 100644 --- a/indra/newview/skins/default/xui/es/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/es/floater_bulk_perms.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterbulkperms" title="Cambio masivo de los permisos del contenido"> +<floater name="floaterbulkperms" title="CAMBIO MASIVO DE LOS PERMISOS DEL CONTENIDO"> <text name="applyto"> Tipos de contenido </text> diff --git a/indra/newview/skins/default/xui/es/floater_bumps.xml b/indra/newview/skins/default/xui/es/floater_bumps.xml index ed43e93688..0522f788bb 100644 --- a/indra/newview/skins/default/xui/es/floater_bumps.xml +++ b/indra/newview/skins/default/xui/es/floater_bumps.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_bumps" title="Choques, empujones, e impactos"> +<floater name="floater_bumps" title="CHOQUES, EMPUJONES, E IMPACTOS"> <text name="none_detected"> No se han detectado </text> diff --git a/indra/newview/skins/default/xui/es/floater_buy_contents.xml b/indra/newview/skins/default/xui/es/floater_buy_contents.xml index 2346798f94..c4d269ff39 100644 --- a/indra/newview/skins/default/xui/es/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/es/floater_buy_contents.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_buy_contents" title="Comprar el contenido"> +<floater name="floater_buy_contents" title="COMPRAR EL CONTENIDO"> <text name="contains_text"> [NAME] contiene: </text> diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml index a01e07e694..af542acbce 100644 --- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy currency" title="Comprar dinero"> +<floater name="buy currency" title="COMPRAR DINERO"> <text name="info_buying"> Comprando dinero: </text> diff --git a/indra/newview/skins/default/xui/es/floater_buy_land.xml b/indra/newview/skins/default/xui/es/floater_buy_land.xml index 7ee15955eb..7ff45fcf79 100644 --- a/indra/newview/skins/default/xui/es/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/es/floater_buy_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy land" title="Comprar terreno"> +<floater name="buy land" title="COMPRAR TERRENO"> <text name="region_name_label"> Región: </text> diff --git a/indra/newview/skins/default/xui/es/floater_buy_object.xml b/indra/newview/skins/default/xui/es/floater_buy_object.xml index 8e713f362b..26696bc868 100644 --- a/indra/newview/skins/default/xui/es/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/es/floater_buy_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Comprar una copia del objeto"> +<floater name="contents" title="COMPRAR UNA COPIA DEL OBJETO"> <text name="contents_text"> y sus contenidos: </text> diff --git a/indra/newview/skins/default/xui/es/floater_choose_group.xml b/indra/newview/skins/default/xui/es/floater_choose_group.xml index 71331abb65..a5967b814e 100644 --- a/indra/newview/skins/default/xui/es/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/es/floater_choose_group.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="groups" title="Grupos"> +<floater name="groups" title="GRUPOS"> <text name="groupdesc"> Elegir un grupo: </text> diff --git a/indra/newview/skins/default/xui/es/floater_color_picker.xml b/indra/newview/skins/default/xui/es/floater_color_picker.xml index 616c373d18..4395ee6890 100644 --- a/indra/newview/skins/default/xui/es/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/es/floater_color_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="ColorPicker" title="Paleta de colores"> +<floater name="ColorPicker" title="PALETA DE COLORES"> <text name="r_val_text"> Rojo: </text> diff --git a/indra/newview/skins/default/xui/es/floater_customize.xml b/indra/newview/skins/default/xui/es/floater_customize.xml index 1322b9a5cf..94452dae6b 100644 --- a/indra/newview/skins/default/xui/es/floater_customize.xml +++ b/indra/newview/skins/default/xui/es/floater_customize.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater customize" title="Apariencia" width="527"> +<floater name="floater customize" title="APARIENCIA" width="527"> <tab_container name="customize tab container" width="525"> <placeholder label="Partes del cuerpo" name="body_parts_placeholder"/> <panel label="Forma" name="Shape" width="389"> diff --git a/indra/newview/skins/default/xui/es/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/es/floater_day_cycle_options.xml index 9ee7fc3ead..fc2b12d1e4 100644 --- a/indra/newview/skins/default/xui/es/floater_day_cycle_options.xml +++ b/indra/newview/skins/default/xui/es/floater_day_cycle_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Day Cycle Floater" title="Editor del ciclo de un dÃa"> +<floater name="Day Cycle Floater" title="EDITOR DEL CICLO DE UN DÃA"> <tab_container name="Day Cycle Tabs"> <panel label="Ciclo de un dÃa" name="Day Cycle"> <button label="?" name="WLDayCycleHelp"/> diff --git a/indra/newview/skins/default/xui/es/floater_device_settings.xml b/indra/newview/skins/default/xui/es/floater_device_settings.xml index e8989f44ef..eadf04a417 100644 --- a/indra/newview/skins/default/xui/es/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/es/floater_device_settings.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_device_settings" title="Configuración de los dispositivos del chat de voz"/> +<floater name="floater_device_settings" title="CONFIGURACIÓN DE LOS DISPOSITIVOS DEL CHAT DE VOZ"/> diff --git a/indra/newview/skins/default/xui/es/floater_env_settings.xml b/indra/newview/skins/default/xui/es/floater_env_settings.xml index 65710fc5ed..5d6ba47daf 100644 --- a/indra/newview/skins/default/xui/es/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/es/floater_env_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Environment Editor Floater" title="Editor del entorno"> +<floater name="Environment Editor Floater" title="EDITOR DEL ENTORNO"> <text name="EnvTimeText"> Duración de un dÃa diff --git a/indra/newview/skins/default/xui/es/floater_font_test.xml b/indra/newview/skins/default/xui/es/floater_font_test.xml index e6b8087b60..9a665321a4 100644 --- a/indra/newview/skins/default/xui/es/floater_font_test.xml +++ b/indra/newview/skins/default/xui/es/floater_font_test.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Prueba de fuentes"> +<floater name="contents" title="PRUEBA DE FUENTES"> <text name="linea"> OverrideTest, deberÃa de aparecer aquà en Times. (Desde default/xui/en-us) </text> diff --git a/indra/newview/skins/default/xui/es/floater_gesture.xml b/indra/newview/skins/default/xui/es/floater_gesture.xml index e7f1a7aca2..496881f2d2 100644 --- a/indra/newview/skins/default/xui/es/floater_gesture.xml +++ b/indra/newview/skins/default/xui/es/floater_gesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="gestures" title="Gestos disponibles"> +<floater name="gestures" title="GESTOS DISPONIBLES"> <text name="help_label"> Pulse dos veces en un gesto para reproducir las animaciones y sonidos. diff --git a/indra/newview/skins/default/xui/es/floater_god_tools.xml b/indra/newview/skins/default/xui/es/floater_god_tools.xml index ea2571ecb8..78ec76e32b 100644 --- a/indra/newview/skins/default/xui/es/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/es/floater_god_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="godtools floater" title="Herramientas de Dios"> +<floater name="godtools floater" title="HERRAMIENTAS DE DIOS"> <tab_container name="GodTools Tabs"> <panel label="Red" name="grid"> <button label="Expulsar a todos los usuarios" diff --git a/indra/newview/skins/default/xui/es/floater_hardware_settings.xml b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml index 29750ee737..9418252036 100644 --- a/indra/newview/skins/default/xui/es/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Hardware Settings Floater" title="Configuración del hardware"> +<floater name="Hardware Settings Floater" title="CONFIGURACIÓN DEL HARDWARE"> <text name="Filtering:"> Filtrado: </text> diff --git a/indra/newview/skins/default/xui/es/floater_hud.xml b/indra/newview/skins/default/xui/es/floater_hud.xml index d31bcedf05..e458913452 100644 --- a/indra/newview/skins/default/xui/es/floater_hud.xml +++ b/indra/newview/skins/default/xui/es/floater_hud.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_hud" title="Tutorial"/> +<floater name="floater_hud" title="TUTORIAL"/> diff --git a/indra/newview/skins/default/xui/es/floater_inspect.xml b/indra/newview/skins/default/xui/es/floater_inspect.xml index 026081bc04..3c8b38648f 100644 --- a/indra/newview/skins/default/xui/es/floater_inspect.xml +++ b/indra/newview/skins/default/xui/es/floater_inspect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="inspect" title="Examinar objetos" min_width="450"> +<floater name="inspect" title="EXAMINAR OBJETOS" min_width="450"> <scroll_list name="object_list" tool_tip="Seleccione un objeto de esta lista para realzarlo en el mundo"> <column label="Nombre del objeto" name="object_name"/> <column label="Propietario" name="owner_name"/> diff --git a/indra/newview/skins/default/xui/es/floater_inventory.xml b/indra/newview/skins/default/xui/es/floater_inventory.xml index 7da14c0579..8d16d6089e 100644 --- a/indra/newview/skins/default/xui/es/floater_inventory.xml +++ b/indra/newview/skins/default/xui/es/floater_inventory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory" title="Inventario"> +<floater name="Inventory" title="INVENTARIO"> <search_editor label="Escriba aquà para buscar" name="inventory search editor"/> <tab_container name="inventory filter tabs"> <inventory_panel label="Todos los Ãtems" name="All Items"/> diff --git a/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml index 4df3ca2cf6..7abdfceb94 100644 --- a/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="item properties" title="Propiedades del Ãtem del inventario"> +<floater name="item properties" title="PROPIEDADES DEL ÃTEM DEL INVENTARIO"> <text name="LabelItemNameTitle"> Nombre: </text> diff --git a/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml index 7cd787bfb5..0cbee11bfb 100644 --- a/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory Finder" title="Ãtems_recientes_del_inventario"> +<floater name="Inventory Finder" title="ÃTEMS_RECIENTES_DEL_INVENTARIO"> <check_box label="Animaciones" name="check_animation"/> <check_box label="Tarjetas de visita" name="check_calling_card"/> <check_box label="Ropa" name="check_clothing"/> diff --git a/indra/newview/skins/default/xui/es/floater_joystick.xml b/indra/newview/skins/default/xui/es/floater_joystick.xml index 2e0fb87744..75c53dd646 100644 --- a/indra/newview/skins/default/xui/es/floater_joystick.xml +++ b/indra/newview/skins/default/xui/es/floater_joystick.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Joystick" title="Configuración del joystick"> +<floater name="Joystick" title="CONFIGURACIÓN DEL JOYSTICK"> <check_box name="enable_joystick" label="Activar el joystick:"/> <text left="140" name="joystick_type" width="360"/> <spinner label="Mapping: eje X" name="JoystickAxis1" label_width="118" width="161"/> diff --git a/indra/newview/skins/default/xui/es/floater_lagmeter.xml b/indra/newview/skins/default/xui/es/floater_lagmeter.xml index 1af0bb065c..54c4ce8c6a 100644 --- a/indra/newview/skins/default/xui/es/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/es/floater_lagmeter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="Medidor del lag"> +<floater name="floater_lagmeter" title="MEDIDOR DEL LAG"> <button label="" label_selected="" name="client_lagmeter" tool_tip="Estado del lag del cliente"/> <text name="client"> Cliente: diff --git a/indra/newview/skins/default/xui/es/floater_land_holdings.xml b/indra/newview/skins/default/xui/es/floater_land_holdings.xml index 5df319905d..bcdebf4588 100644 --- a/indra/newview/skins/default/xui/es/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/es/floater_land_holdings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="land holdings floater" title="Mi terreno"> +<floater name="land holdings floater" title="MI TERRENO"> <scroll_list name="parcel list"> <column label="Nombre de la parcela" name="name"/> <column label="Región" name="location"/> diff --git a/indra/newview/skins/default/xui/es/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/es/floater_live_lsleditor.xml index 226c3482af..02be809319 100644 --- a/indra/newview/skins/default/xui/es/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/es/floater_live_lsleditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="script ed float" title="Script: script nuevo"> +<floater name="script ed float" title="SCRIPT: SCRIPT NUEVO"> <button label="Reiniciar" label_selected="Reiniciar" name="Reset"/> <check_box label="Ejecutándose" name="running" left="4"/> <check_box label="Mono" name="mono" left="106"/> diff --git a/indra/newview/skins/default/xui/es/floater_lsl_guide.xml b/indra/newview/skins/default/xui/es/floater_lsl_guide.xml index 859a2d3812..0cde2fe5bc 100644 --- a/indra/newview/skins/default/xui/es/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/es/floater_lsl_guide.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="script ed float" title="Wiki de LSL"> +<floater name="script ed float" title="WIKI DE LSL"> <check_box label="Seguir al cursor" name="lock_check"/> <combo_box label="Bloquear" name="history_combo" left_delta="120" width="70"/> <button label="Atrás" name="back_btn" left_delta="75"/> diff --git a/indra/newview/skins/default/xui/es/floater_media_browser.xml b/indra/newview/skins/default/xui/es/floater_media_browser.xml index 79c8980c02..ff50b56a32 100644 --- a/indra/newview/skins/default/xui/es/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/es/floater_media_browser.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_about" title="Navegador"> +<floater name="floater_about" title="NAVEGADOR"> <layout_stack name="stack1"> <layout_panel name="nav_controls"> <button label="Atrás" name="back" width="75"/> diff --git a/indra/newview/skins/default/xui/es/floater_mem_leaking.xml b/indra/newview/skins/default/xui/es/floater_mem_leaking.xml index a2791d6432..6d5e987409 100644 --- a/indra/newview/skins/default/xui/es/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/es/floater_mem_leaking.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="MemLeak" title="Prueba de la fuga de memoria"> +<floater name="MemLeak" title="PRUEBA DE LA FUGA DE MEMORIA"> <spinner label="Velocidad de la fuga (bites por fotograma):" name="leak_speed"/> <spinner label="Fuga de memoria máx. (MB):" name="max_leak"/> <text name="total_leaked_label"> diff --git a/indra/newview/skins/default/xui/es/floater_mute_object.xml b/indra/newview/skins/default/xui/es/floater_mute_object.xml index 0cf38c09ee..390333cd1d 100644 --- a/indra/newview/skins/default/xui/es/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/es/floater_mute_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="mute by name" title="Ignorar un objeto según su nombre"> +<floater name="mute by name" title="IGNORAR UN OBJETO SEGÚN SU NOMBRE"> <text name="message" bottom_delta="-40"> Ignorar según el nombre sólo afecta al chat y los MI del objeto, no a sus sonidos. diff --git a/indra/newview/skins/default/xui/es/floater_my_friends.xml b/indra/newview/skins/default/xui/es/floater_my_friends.xml index d555eed305..07f362560b 100644 --- a/indra/newview/skins/default/xui/es/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/es/floater_my_friends.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_my_friends" title="Contactos"> +<floater name="floater_my_friends" title="CONTACTOS"> <tab_container name="friends_and_groups"> <panel label="Amigos" name="friends_panel"/> <panel label="Grupos" name="groups_panel"/> diff --git a/indra/newview/skins/default/xui/es/floater_openobject.xml b/indra/newview/skins/default/xui/es/floater_openobject.xml index 60487b829c..89c79e8833 100644 --- a/indra/newview/skins/default/xui/es/floater_openobject.xml +++ b/indra/newview/skins/default/xui/es/floater_openobject.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="objectcontents" title="Contenido del objeto"> +<floater name="objectcontents" title="CONTENIDO DEL OBJETO"> <text name="object_name"> [DESC]: </text> diff --git a/indra/newview/skins/default/xui/es/floater_perm_prefs.xml b/indra/newview/skins/default/xui/es/floater_perm_prefs.xml index 4a3977be3d..7d3c8e62f3 100644 --- a/indra/newview/skins/default/xui/es/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/es/floater_perm_prefs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="perm prefs" title="Permisos de subida por defecto"> +<floater name="perm prefs" title="PERMISOS DE SUBIDA POR DEFECTO"> <panel label="Permisos" name="permissions"> <button label="?" label_selected="?" name="help"/> <check_box label="Compartir con el grupo" name="share_with_group"/> diff --git a/indra/newview/skins/default/xui/es/floater_post_process.xml b/indra/newview/skins/default/xui/es/floater_post_process.xml index acac2b2bf9..5c62ccde36 100644 --- a/indra/newview/skins/default/xui/es/floater_post_process.xml +++ b/indra/newview/skins/default/xui/es/floater_post_process.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="Configuración del procesamiento"> +<floater name="Post-Process Floater" title="CONFIGURACIÓN DEL PROCESAMIENTO"> <tab_container name="Post-Process Tabs"> <panel label="Color del filtro" name="wmiColorFilterPanel"> <check_box label="Activar" name="wmiColorFilterToggle"/> diff --git a/indra/newview/skins/default/xui/es/floater_postcard.xml b/indra/newview/skins/default/xui/es/floater_postcard.xml index 6a9811c058..ace3204cc7 100644 --- a/indra/newview/skins/default/xui/es/floater_postcard.xml +++ b/indra/newview/skins/default/xui/es/floater_postcard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Postcard" title="Foto por correo electrónico"> +<floater name="Postcard" title="FOTO POR CORREO ELECTRÓNICO"> <text name="to_label"> Correo electrónico del destinatario: diff --git a/indra/newview/skins/default/xui/es/floater_preferences.xml b/indra/newview/skins/default/xui/es/floater_preferences.xml index df7fc93dd9..5fe4ae3b64 100644 --- a/indra/newview/skins/default/xui/es/floater_preferences.xml +++ b/indra/newview/skins/default/xui/es/floater_preferences.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Preferences" title="Preferencias" min_width="350" width="646"> +<floater name="Preferences" title="PREFERENCIAS" min_width="350" width="646"> <button label="OK" label_selected="OK" name="OK"/> <button label="Cancelar" label_selected="Cancelar" name="Cancel"/> <button label="Aplicar" label_selected="Aplicar" name="Apply"/> diff --git a/indra/newview/skins/default/xui/es/floater_preview_classified.xml b/indra/newview/skins/default/xui/es/floater_preview_classified.xml index f2fa38ead8..8114c7f3c2 100644 --- a/indra/newview/skins/default/xui/es/floater_preview_classified.xml +++ b/indra/newview/skins/default/xui/es/floater_preview_classified.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="classified_preview" title="Información clasificada"/> +<floater name="classified_preview" title="INFORMACIÓN CLASIFICADA"/> diff --git a/indra/newview/skins/default/xui/es/floater_preview_event.xml b/indra/newview/skins/default/xui/es/floater_preview_event.xml index 7f727b0502..04cb0de4d4 100644 --- a/indra/newview/skins/default/xui/es/floater_preview_event.xml +++ b/indra/newview/skins/default/xui/es/floater_preview_event.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="event_preview" title="Información de eventos"/> +<floater name="event_preview" title="INFORMACIÓN DE EVENTOS"/> diff --git a/indra/newview/skins/default/xui/es/floater_preview_notecard.xml b/indra/newview/skins/default/xui/es/floater_preview_notecard.xml index 4d11520335..35f795a7ec 100644 --- a/indra/newview/skins/default/xui/es/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/es/floater_preview_notecard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="preview notecard" title="Nota:"> +<floater name="preview notecard" title="NOTA:"> <button label="Guardar" label_selected="Guardar" name="Save"/> <text name="desc txt"> Descripción: diff --git a/indra/newview/skins/default/xui/es/floater_region_info.xml b/indra/newview/skins/default/xui/es/floater_region_info.xml index b5a85378c2..46d0839238 100644 --- a/indra/newview/skins/default/xui/es/floater_region_info.xml +++ b/indra/newview/skins/default/xui/es/floater_region_info.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="regioninfo" title="Región/Estado"/> +<floater name="regioninfo" title="REGIÓN/ESTADO"/> diff --git a/indra/newview/skins/default/xui/es/floater_report_abuse.xml b/indra/newview/skins/default/xui/es/floater_report_abuse.xml index 8ae8c212e6..a075c51247 100644 --- a/indra/newview/skins/default/xui/es/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/es/floater_report_abuse.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_report_abuse" title="Denuncia de Infracción"> +<floater name="floater_report_abuse" title="DENUNCIA DE INFRACCIÓN"> <texture_picker label="" name="screenshot"/> <check_box label="Incluir una captura de pantalla" name="screen_check"/> <text name="reporter_title"> diff --git a/indra/newview/skins/default/xui/es/floater_script_debug.xml b/indra/newview/skins/default/xui/es/floater_script_debug.xml index e33ffb7d96..e7eddfd9f3 100644 --- a/indra/newview/skins/default/xui/es/floater_script_debug.xml +++ b/indra/newview/skins/default/xui/es/floater_script_debug.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <multi_floater name="script debug floater" title="Alerta/Error de los scripts"> <tab_container name="Preview Tabs"> - <floater label="Script" name="all_scripts" title="[Todos los scripts]"/> + <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]"/> </tab_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/es/floater_script_preview.xml b/indra/newview/skins/default/xui/es/floater_script_preview.xml index 0d8cd0b406..79984e7bc1 100644 --- a/indra/newview/skins/default/xui/es/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/es/floater_script_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="preview lsl text" title="Script: script de rotación"> +<floater name="preview lsl text" title="SCRIPT: SCRIPT DE ROTACIÓN"> <text name="desc txt"> Descripción: </text> diff --git a/indra/newview/skins/default/xui/es/floater_script_queue.xml b/indra/newview/skins/default/xui/es/floater_script_queue.xml index dcd2bfe5b0..ace596cd9a 100644 --- a/indra/newview/skins/default/xui/es/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/es/floater_script_queue.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="queue" title="Reinicio"> +<floater name="queue" title="REINICIO"> <button label="Cerrar" label_selected="Cerrar" name="close"/> </floater> diff --git a/indra/newview/skins/default/xui/es/floater_script_search.xml b/indra/newview/skins/default/xui/es/floater_script_search.xml index 3c8dc2fe9c..a59f258a18 100644 --- a/indra/newview/skins/default/xui/es/floater_script_search.xml +++ b/indra/newview/skins/default/xui/es/floater_script_search.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="script search" title="Buscar en el script" width="320"> +<floater name="script search" title="BUSCAR EN EL SCRIPT" width="320"> <check_box label="Indiferente mays./mins." name="case_text" left="75"/> <button label="Buscar" label_selected="Buscar" name="search_btn" width="85"/> <button label="Reemplazar" label_selected="Reemplazar" name="replace_btn" left="100" width="85"/> diff --git a/indra/newview/skins/default/xui/es/floater_sell_land.xml b/indra/newview/skins/default/xui/es/floater_sell_land.xml index bce13c1e33..c6e8746250 100644 --- a/indra/newview/skins/default/xui/es/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/es/floater_sell_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="sell land" title="Vender el terreno"> +<floater name="sell land" title="VENDER EL TERRENO"> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> <text name="info_parcel_label"> diff --git a/indra/newview/skins/default/xui/es/floater_settings_debug.xml b/indra/newview/skins/default/xui/es/floater_settings_debug.xml index 1d5ad2f34c..0e8e6bdfd2 100644 --- a/indra/newview/skins/default/xui/es/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/es/floater_settings_debug.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="settings_debug" title="Configuración del depurador"> +<floater name="settings_debug" title="CONFIGURACIÓN DEL DEPURADOR"> <combo_box name="boolean_combo"> <combo_box.item name="TRUE" label="TRUE" /> <combo_box.item name="FALSE" label="FALSE" /> diff --git a/indra/newview/skins/default/xui/es/floater_snapshot.xml b/indra/newview/skins/default/xui/es/floater_snapshot.xml index c1ace23503..afea6c09fe 100644 --- a/indra/newview/skins/default/xui/es/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/es/floater_snapshot.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Snapshot" title="Vista previa de la foto"> +<floater name="Snapshot" title="VISTA PREVIA DE LA FOTO"> <text name="type_label"> Destino de la foto </text> diff --git a/indra/newview/skins/default/xui/es/floater_sound_preview.xml b/indra/newview/skins/default/xui/es/floater_sound_preview.xml index e69ac10123..8b8d9f13ce 100644 --- a/indra/newview/skins/default/xui/es/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/es/floater_sound_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Sound Preview" title="sound.wav"> +<floater name="Sound Preview" title="SOUND.WAV"> <text name="name_label"> Nombre: </text> diff --git a/indra/newview/skins/default/xui/es/floater_statistics.xml b/indra/newview/skins/default/xui/es/floater_statistics.xml index 6e644cacf1..c9b0a76df0 100644 --- a/indra/newview/skins/default/xui/es/floater_statistics.xml +++ b/indra/newview/skins/default/xui/es/floater_statistics.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="stats floater" title="EstadÃsticas"/> +<floater name="stats floater" title="ESTADÃSTICAS"/> diff --git a/indra/newview/skins/default/xui/es/floater_telehub.xml b/indra/newview/skins/default/xui/es/floater_telehub.xml index 74084e9db9..b2dddfb7f7 100644 --- a/indra/newview/skins/default/xui/es/floater_telehub.xml +++ b/indra/newview/skins/default/xui/es/floater_telehub.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="telehub" title="Punto de Teleporte" min_height="310" height="310"> +<floater name="telehub" title="PUNTO DE TELEPORTE" min_height="310" height="310"> <text name="status_text_connected"> Punto de Teleporte conectado al objeto [OBJECT] </text> diff --git a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml index 8b661a6041..09d6e7e4aa 100644 --- a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="texture picker" title="Elegir: Textura"> +<floater name="texture picker" title="ELEGIR: TEXTURA"> <string name="choose_picture"> Pulse para elegir una imagen </string> diff --git a/indra/newview/skins/default/xui/es/floater_tools.xml b/indra/newview/skins/default/xui/es/floater_tools.xml index da842d22c6..24db352ac4 100644 --- a/indra/newview/skins/default/xui/es/floater_tools.xml +++ b/indra/newview/skins/default/xui/es/floater_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="toolbox floater" title="" short_title="Construir" width="288"> +<floater name="toolbox floater" title="" short_title="CONSTRUIR" width="288"> <button label="" label_selected="" name="button focus" tool_tip="Visión"/> <button label="" label_selected="" name="button move" tool_tip="Mover"/> <button label="" label_selected="" name="button edit" tool_tip="Editar"/> diff --git a/indra/newview/skins/default/xui/es/floater_top_objects.xml b/indra/newview/skins/default/xui/es/floater_top_objects.xml index 95f2c39d42..29ae9991af 100644 --- a/indra/newview/skins/default/xui/es/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/es/floater_top_objects.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="top_objects" title="cargando..."> +<floater name="top_objects" title="CARGANDO..."> <text name="title_text"> Cargando... </text> diff --git a/indra/newview/skins/default/xui/es/floater_water.xml b/indra/newview/skins/default/xui/es/floater_water.xml index 934fc7882b..c86e49a355 100644 --- a/indra/newview/skins/default/xui/es/floater_water.xml +++ b/indra/newview/skins/default/xui/es/floater_water.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Water Floater" title="Editor avanzado del agua"> +<floater name="Water Floater" title="EDITOR AVANZADO DEL AGUA"> <text name="KeyFramePresetsText"> Agua predefinida: </text> diff --git a/indra/newview/skins/default/xui/es/floater_windlight_options.xml b/indra/newview/skins/default/xui/es/floater_windlight_options.xml index e240dea0b5..0697f05553 100644 --- a/indra/newview/skins/default/xui/es/floater_windlight_options.xml +++ b/indra/newview/skins/default/xui/es/floater_windlight_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="WindLight floater" title="Editor avanzado del cielo"> +<floater name="WindLight floater" title="EDITOR AVANZADO DEL CIELO"> <text name="KeyFramePresetsText"> Cielos definidos: </text> diff --git a/indra/newview/skins/default/xui/es/floater_world_map.xml b/indra/newview/skins/default/xui/es/floater_world_map.xml index 6521e72d5a..4d7337bef7 100644 --- a/indra/newview/skins/default/xui/es/floater_world_map.xml +++ b/indra/newview/skins/default/xui/es/floater_world_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="worldmap" title="Mapa del Mundo"> +<floater name="worldmap" title="MAPA DEL MUNDO"> <tab_container name="maptab"> <panel label="Objetos" name="objects_mapview"/> <panel label="Terreno" name="terrain_mapview"/> diff --git a/indra/newview/skins/default/xui/es/panel_edit_profile.xml b/indra/newview/skins/default/xui/es/panel_edit_profile.xml index bcf4128e01..c12dd8d58c 100644 --- a/indra/newview/skins/default/xui/es/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/es/panel_edit_profile.xml @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="edit_profile_panel">
- <string name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
- </string>
- <string name="AcctTypeResident"
- value="Residente" />
- <string name="AcctTypeTrial"
- value="Prueba" />
- <string name="AcctTypeCharterMember"
- value="Miembro fundador" />
- <string name="AcctTypeEmployee"
- value="Empleado de Linden Lab" />
- <string name="PaymentInfoUsed"
- value="Ha usado una forma de pago" />
- <string name="PaymentInfoOnFile"
- value="Hay infor. de la forma de pago" />
- <string name="NoPaymentInfoOnFile"
- value="Sin infor. de la forma de pago" />
- <string name="AgeVerified"
- value="Edad verificada" />
- <string name="NotAgeVerified"
- value="Edad no verificada" />
- <string name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=es
- </string>
- <panel name="scroll_content_panel">
- <panel name="data_panel" >
- <panel name="lifes_images_panel">
- <panel name="second_life_image_panel">
- <text name="second_life_photo_title_text">
- [SECOND_LIFE]:
- </text>
- </panel>
- </panel>
- <text name="title_partner_text" value="Compañero/a:"/>
- <panel name="partner_data_panel">
- <text name="partner_text" value="[FIRST] [LAST]"/>
- </panel>
- <text name="text_box3">
- Mensaje en el estado ocupado:
- </text>
- </panel>
- </panel>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="edit_profile_panel"> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string name="AcctTypeResident" + value="Residente" /> + <string name="AcctTypeTrial" + value="Prueba" /> + <string name="AcctTypeCharterMember" + value="Miembro fundador" /> + <string name="AcctTypeEmployee" + value="Empleado de Linden Lab" /> + <string name="PaymentInfoUsed" + value="Ha usado una forma de pago" /> + <string name="PaymentInfoOnFile" + value="Hay infor. de la forma de pago" /> + <string name="NoPaymentInfoOnFile" + value="Sin infor. de la forma de pago" /> + <string name="AgeVerified" + value="Edad verificada" /> + <string name="NotAgeVerified" + value="Edad no verificada" /> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=es + </string> + <panel name="scroll_content_panel"> + <panel name="data_panel" > + <panel name="lifes_images_panel"> + <panel name="second_life_image_panel"> + <text name="second_life_photo_title_text"> + [SECOND_LIFE]: + </text> + </panel> + </panel> + <text name="title_partner_text" value="Compañero/a:"/> + <panel name="partner_data_panel"> + <text name="partner_text" value="[FIRST] [LAST]"/> + </panel> + <text name="text_box3"> + Mensaje en el estado ocupado: + </text> + </panel> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml index 7b918be075..53e48352f1 100644 --- a/indra/newview/skins/default/xui/fr/floater_about.xml +++ b/indra/newview/skins/default/xui/fr/floater_about.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_about" title="A propos de [APP_NAME]"> +<floater name="floater_about" title="A PROPOS DE [APP_NAME]"> <tab_container name="about_tab"> <panel name="credits_panel"> <text_editor name="credits_editor"> diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml index f2d2dbfa07..0729c79cbb 100644 --- a/indra/newview/skins/default/xui/fr/floater_about_land.xml +++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterland" title="À propos du terrain"> +<floater name="floaterland" title="À PROPOS DU TERRAIN"> <tab_container name="landtab"> <panel label="Général" name="land_general_panel"> <text name="Name:"> diff --git a/indra/newview/skins/default/xui/fr/floater_auction.xml b/indra/newview/skins/default/xui/fr/floater_auction.xml index 4bdf9df1be..3ec95a60c5 100644 --- a/indra/newview/skins/default/xui/fr/floater_auction.xml +++ b/indra/newview/skins/default/xui/fr/floater_auction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_auction" title="Commencer la vente de terrain Linden"> +<floater name="floater_auction" title="COMMENCER LA VENTE DE TERRAIN LINDEN"> <check_box label="Inclure le marquage de sélection jaune" name="fence_check" /> <combo_box name="saletype_combo"> <combo_box.item name="Auction" label="Enchères" /> diff --git a/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml b/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml index 01b4c944f3..c713d3e930 100644 --- a/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatarpicker" title="Choisir le résident"> +<floater name="avatarpicker" title="CHOISIR LE RÉSIDENT"> <tab_container name="ResidentChooserTabs"> <panel label="Rechercher" name="SearchPanel"> <text name="InstructSearchResidentName"> diff --git a/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml b/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml index f4e3a1615c..569126f3ec 100644 --- a/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatar_texture_debug" title="Textures de l'avatar"> +<floater name="avatar_texture_debug" title="TEXTURES DE L'AVATAR"> <text name="label"> Textures fixées </text> diff --git a/indra/newview/skins/default/xui/fr/floater_beacons.xml b/indra/newview/skins/default/xui/fr/floater_beacons.xml index 0b060983ee..4f5c5d442f 100644 --- a/indra/newview/skins/default/xui/fr/floater_beacons.xml +++ b/indra/newview/skins/default/xui/fr/floater_beacons.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="beacons" title="Balises"> +<floater name="beacons" title="BALISES"> <panel name="beacons_panel"> <check_box label="Objets scriptés avec Toucher uniquement" name="touch_only"/> <check_box label="Objets scriptés" name="scripted"/> diff --git a/indra/newview/skins/default/xui/fr/floater_build_options.xml b/indra/newview/skins/default/xui/fr/floater_build_options.xml index 3451c2de4c..76e8e2f637 100644 --- a/indra/newview/skins/default/xui/fr/floater_build_options.xml +++ b/indra/newview/skins/default/xui/fr/floater_build_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="build options floater" title="Options de la grille"> +<floater name="build options floater" title="OPTIONS DE LA GRILLE"> <spinner label="Unité (mètres)" name="GridResolution" /> <spinner label="Mesures (mètres)" name="GridDrawSize" /> <check_box label="Activer la fixation des sous-unités" name="GridSubUnit" /> diff --git a/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml b/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml index b868aa33ad..98b7faa2cc 100644 --- a/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterbulkperms" title="Changement des droits relatifs au contenu"> +<floater name="floaterbulkperms" title="CHANGEMENT DES DROITS RELATIFS AU CONTENU"> <text name="applyto"> Types de contenu </text> diff --git a/indra/newview/skins/default/xui/fr/floater_bumps.xml b/indra/newview/skins/default/xui/fr/floater_bumps.xml index e12c7ed17d..e439c30524 100644 --- a/indra/newview/skins/default/xui/fr/floater_bumps.xml +++ b/indra/newview/skins/default/xui/fr/floater_bumps.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_bumps" title="Collisions, coups et bousculades"> +<floater name="floater_bumps" title="COLLISIONS, COUPS ET BOUSCULADES"> <text name="none_detected"> Aucun détecté </text> diff --git a/indra/newview/skins/default/xui/fr/floater_buy_contents.xml b/indra/newview/skins/default/xui/fr/floater_buy_contents.xml index 916b270500..e8b47f5365 100644 --- a/indra/newview/skins/default/xui/fr/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/fr/floater_buy_contents.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_buy_contents" title="Acheter ce contenu"> +<floater name="floater_buy_contents" title="ACHETER CE CONTENU"> <text name="contains_text"> [NAME] contient : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml index 85d67218d3..9112d30be2 100644 --- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy currency" title="Acheter des L$"> +<floater name="buy currency" title="ACHETER DES L$"> <text left="5" name="info_buying"> Achat de L$ : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_buy_land.xml b/indra/newview/skins/default/xui/fr/floater_buy_land.xml index aaf1577114..2b93098847 100644 --- a/indra/newview/skins/default/xui/fr/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/fr/floater_buy_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy land" title="Acheter le terrain"> +<floater name="buy land" title="ACHETER LE TERRAIN"> <text name="region_name_label"> Région : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_buy_object.xml b/indra/newview/skins/default/xui/fr/floater_buy_object.xml index 9e0ce25b97..893d559e6e 100644 --- a/indra/newview/skins/default/xui/fr/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/fr/floater_buy_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Acheter une copie de l'objet"> +<floater name="contents" title="ACHETER UNE COPIE DE L'OBJET"> <text name="contents_text"> et ses contenus : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_choose_group.xml b/indra/newview/skins/default/xui/fr/floater_choose_group.xml index ade440f296..15cdd4d332 100644 --- a/indra/newview/skins/default/xui/fr/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/fr/floater_choose_group.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="groups" title="Groupes"> +<floater name="groups" title="GROUPES"> <text name="groupdesc"> Choisissez un groupe : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_color_picker.xml b/indra/newview/skins/default/xui/fr/floater_color_picker.xml index 94bcad070e..996f3e9b07 100644 --- a/indra/newview/skins/default/xui/fr/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/fr/floater_color_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="ColorPicker" title="Choix de texture et de couleur"> +<floater name="ColorPicker" title="CHOIX DE TEXTURE ET DE COULEUR"> <text name="r_val_text"> Rouge : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_customize.xml b/indra/newview/skins/default/xui/fr/floater_customize.xml index 1250c46933..bf70c5415e 100644 --- a/indra/newview/skins/default/xui/fr/floater_customize.xml +++ b/indra/newview/skins/default/xui/fr/floater_customize.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater customize" title="Apparence" width="548"> +<floater name="floater customize" title="APPARENCE" width="548"> <tab_container name="customize tab container" tab_min_width="150" width="546"> <placeholder label="Parties du corps" name="body_parts_placeholder"/> <panel label="Silhouette" left="154" name="Shape" width="389"> diff --git a/indra/newview/skins/default/xui/fr/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/fr/floater_day_cycle_options.xml index 1103539898..0b36b7b8ca 100644 --- a/indra/newview/skins/default/xui/fr/floater_day_cycle_options.xml +++ b/indra/newview/skins/default/xui/fr/floater_day_cycle_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Day Cycle Floater" title="Editeur du cycle du jour"> +<floater name="Day Cycle Floater" title="EDITEUR DU CYCLE DU JOUR"> <tab_container name="Day Cycle Tabs"> <panel label="Cycle du jour" name="Day Cycle"> <button label="?" name="WLDayCycleHelp" /> diff --git a/indra/newview/skins/default/xui/fr/floater_device_settings.xml b/indra/newview/skins/default/xui/fr/floater_device_settings.xml index 656f1c4fba..5374b4e593 100644 --- a/indra/newview/skins/default/xui/fr/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/fr/floater_device_settings.xml @@ -1,3 +1,3 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater name="floater_device_settings" - title="Paramètres du matériel utilisé pour le chat vocal" /> + title="PARAMÈTRES DU MATÉRIEL UTILISÉ POUR LE CHAT VOCAL" /> diff --git a/indra/newview/skins/default/xui/fr/floater_env_settings.xml b/indra/newview/skins/default/xui/fr/floater_env_settings.xml index 1d14142dd3..7d6de114be 100644 --- a/indra/newview/skins/default/xui/fr/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/fr/floater_env_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Environment Editor Floater" title="Éditeur d'environnement"> +<floater name="Environment Editor Floater" title="ÉDITEUR D'ENVIRONNEMENT"> <text bottom="-45" name="EnvTimeText"> Heure de la journée diff --git a/indra/newview/skins/default/xui/fr/floater_font_test.xml b/indra/newview/skins/default/xui/fr/floater_font_test.xml index 11eb11a0d7..3a32e8adc5 100644 --- a/indra/newview/skins/default/xui/fr/floater_font_test.xml +++ b/indra/newview/skins/default/xui/fr/floater_font_test.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Test de la police"> +<floater name="contents" title="TEST DE LA POLICE"> <text name="linea"> OverrideTest, Times-BOLD doit être sélectionné ici. (De default/xui/fr) </text> diff --git a/indra/newview/skins/default/xui/fr/floater_gesture.xml b/indra/newview/skins/default/xui/fr/floater_gesture.xml index 4411fee480..b3026478ff 100644 --- a/indra/newview/skins/default/xui/fr/floater_gesture.xml +++ b/indra/newview/skins/default/xui/fr/floater_gesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="gestures" title="Gestes utilisés"> +<floater name="gestures" title="GESTES UTILISÉS"> <text name="help_label"> Double-cliquez sur un geste pour jouer les animations et les sons. diff --git a/indra/newview/skins/default/xui/fr/floater_god_tools.xml b/indra/newview/skins/default/xui/fr/floater_god_tools.xml index 461956ff34..33cb43f7ac 100644 --- a/indra/newview/skins/default/xui/fr/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/fr/floater_god_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="godtools floater" title="Outils divins"> +<floater name="godtools floater" title="OUTILS DIVINS"> <tab_container name="GodTools Tabs"> <panel label="Grille" name="grid"> <button label="Éjecter tous" label_selected="Éjecter tous" name="Kick all users" width="175" /> diff --git a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml index 11d7fc28e9..6c1ea09c90 100644 --- a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Hardware Settings Floater" title="Configuration du matériel"> +<floater name="Hardware Settings Floater" title="CONFIGURATION DU MATÉRIEL"> <text name="Filtering:"> Filtres : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_hud.xml b/indra/newview/skins/default/xui/fr/floater_hud.xml index 55c8b57ae2..13ca0e8770 100644 --- a/indra/newview/skins/default/xui/fr/floater_hud.xml +++ b/indra/newview/skins/default/xui/fr/floater_hud.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_hud" title="Didacticiel" /> +<floater name="floater_hud" title="DIDACTICIEL" /> diff --git a/indra/newview/skins/default/xui/fr/floater_inspect.xml b/indra/newview/skins/default/xui/fr/floater_inspect.xml index f140c66de0..944a157f17 100644 --- a/indra/newview/skins/default/xui/fr/floater_inspect.xml +++ b/indra/newview/skins/default/xui/fr/floater_inspect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="inspect" title="Inspecter les objets"> +<floater name="inspect" title="INSPECTER LES OBJETS"> <scroll_list name="object_list" tool_tip="Sélectionner un objet de la liste pour le mettre en surbrillance dans le Monde."> <column label="Nom" name="object_name" /> diff --git a/indra/newview/skins/default/xui/fr/floater_inventory.xml b/indra/newview/skins/default/xui/fr/floater_inventory.xml index 7173025d18..a83a95fa75 100644 --- a/indra/newview/skins/default/xui/fr/floater_inventory.xml +++ b/indra/newview/skins/default/xui/fr/floater_inventory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory" title="Inventaire"> +<floater name="Inventory" title="INVENTAIRE"> <search_editor label="Saisissez votre recherche ici" name="inventory search editor"/> <tab_container name="inventory filter tabs"> <inventory_panel label="Tous les objets" name="All Items"/> diff --git a/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml index ec83d5bcaa..2885a7e316 100644 --- a/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="item properties" title="Propriétés de l'objet de l'inventaire"> +<floater name="item properties" title="PROPRIÉTÉS DE L'OBJET DE L'INVENTAIRE"> <text name="LabelItemNameTitle"> Nom : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml index 634bb6e2e9..8fb8d3c6f4 100644 --- a/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory Finder" title="inventory_recent_items"> +<floater name="Inventory Finder" title="INVENTORY_RECENT_ITEMS"> <check_box label="Animations" name="check_animation"/> <check_box label="Cartes de visite" name="check_calling_card"/> <check_box label="Habits" name="check_clothing"/> diff --git a/indra/newview/skins/default/xui/fr/floater_joystick.xml b/indra/newview/skins/default/xui/fr/floater_joystick.xml index 75800847d7..546c95de4c 100644 --- a/indra/newview/skins/default/xui/fr/floater_joystick.xml +++ b/indra/newview/skins/default/xui/fr/floater_joystick.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Joystick" title="Configuration du joystick"> +<floater name="Joystick" title="CONFIGURATION DU JOYSTICK"> <check_box name="enable_joystick" label="Activer :"/> <spinner label="Mapping axe des X " name="JoystickAxis1"/> <spinner label="Mapping axe des Y" name="JoystickAxis2"/> diff --git a/indra/newview/skins/default/xui/fr/floater_lagmeter.xml b/indra/newview/skins/default/xui/fr/floater_lagmeter.xml index 54069c9c49..593ad903b9 100644 --- a/indra/newview/skins/default/xui/fr/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/fr/floater_lagmeter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="Mesure du lag"> +<floater name="floater_lagmeter" title="MESURE DU LAG"> <button name="client_lagmeter" tool_tip="Statut du lag client"/> <text name="client"> Client : diff --git a/indra/newview/skins/default/xui/fr/floater_land_holdings.xml b/indra/newview/skins/default/xui/fr/floater_land_holdings.xml index 9c4f4ee966..17adafa8d9 100644 --- a/indra/newview/skins/default/xui/fr/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/fr/floater_land_holdings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="land holdings floater" title="Mes terrains"> +<floater name="land holdings floater" title="MES TERRAINS"> <scroll_list name="parcel list"> <column label="Nom de la parcelle" name="name"/> <column label="Région" name="location"/> diff --git a/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml index e2e2a9af9a..76db22cea4 100644 --- a/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="Script : Nouveau script"> +<floater name="script ed float" title="SCRIPT : NOUVEAU SCRIPT"> <button label="Réinitialiser" label_selected="Réinitialiser" name="Reset" width="100" left="390"/> <check_box label="Exécution en cours" name="running" left="4"/> <check_box label="Mono" name="mono" left="130"/> diff --git a/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml b/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml index 5dc0fa76a3..2e3d88264e 100644 --- a/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="Wiki LSL"> +<floater name="script ed float" title="WIKI LSL"> <check_box label="Suivre le curseur" name="lock_check" /> <combo_box label="Verrouiller" name="history_combo" left_delta="120" width="70"/> <button label="Précédente" name="back_btn" left_delta="75"/> diff --git a/indra/newview/skins/default/xui/fr/floater_media_browser.xml b/indra/newview/skins/default/xui/fr/floater_media_browser.xml index e75b45c43a..5a787a6bf9 100644 --- a/indra/newview/skins/default/xui/fr/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/fr/floater_media_browser.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_about" title="Navigateur"> +<floater name="floater_about" title="NAVIGATEUR"> <layout_stack name="stack1"> <layout_panel name="nav_controls"> <button label="Précédente" name="back" width="75"/> diff --git a/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml b/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml index 8ee3a23b95..e62aad6cd3 100644 --- a/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="MemLeak" title="Simulation fuite mémoire"> +<floater name="MemLeak" title="SIMULATION FUITE MÉMOIRE"> <spinner label="Vitesse de la fuite (octets) :" name="leak_speed" /> <spinner label="Max mémoire perdue (Mo) :" name="max_leak" /> <text name="total_leaked_label"> diff --git a/indra/newview/skins/default/xui/fr/floater_mute_object.xml b/indra/newview/skins/default/xui/fr/floater_mute_object.xml index 23d351f32d..aae5770d51 100644 --- a/indra/newview/skins/default/xui/fr/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/fr/floater_mute_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="mute by name" title="Ignorer les objets par nom"> +<floater name="mute by name" title="IGNORER LES OBJETS PAR NOM"> <text name="message"> Cette fonction ne marche que pour les chats et les IM, pas les sons. Saisissez le nom exact de l'objet. diff --git a/indra/newview/skins/default/xui/fr/floater_my_friends.xml b/indra/newview/skins/default/xui/fr/floater_my_friends.xml index 911647d8be..841a42a0ea 100644 --- a/indra/newview/skins/default/xui/fr/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/fr/floater_my_friends.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_my_friends" title="Contacts"> +<floater name="floater_my_friends" title="CONTACTS"> <tab_container name="friends_and_groups"> <panel label="Amis" name="friends_panel" /> <panel label="Groupes" name="groups_panel" /> diff --git a/indra/newview/skins/default/xui/fr/floater_notification.xml b/indra/newview/skins/default/xui/fr/floater_notification.xml index 7ca2dc3a64..62727da007 100644 --- a/indra/newview/skins/default/xui/fr/floater_notification.xml +++ b/indra/newview/skins/default/xui/fr/floater_notification.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="notification" title="Console de notifications"> +<floater name="notification" title="CONSOLE DE NOTIFICATIONS"> <text_editor name="payload"> Chargement.. </text_editor> diff --git a/indra/newview/skins/default/xui/fr/floater_notifications_console.xml b/indra/newview/skins/default/xui/fr/floater_notifications_console.xml index 7262fe8fe2..fd3782bac2 100644 --- a/indra/newview/skins/default/xui/fr/floater_notifications_console.xml +++ b/indra/newview/skins/default/xui/fr/floater_notifications_console.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="notifications_console" title="Console de notifications"> +<floater name="notifications_console" title="CONSOLE DE NOTIFICATIONS"> <combo_box label="Sélectionner le type de notification" name="notification_types" width="412"/> <button label="Ajouter" name="add_notification" left="417" width="78"/> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_openobject.xml b/indra/newview/skins/default/xui/fr/floater_openobject.xml index 3761200d48..5ffa2f236d 100644 --- a/indra/newview/skins/default/xui/fr/floater_openobject.xml +++ b/indra/newview/skins/default/xui/fr/floater_openobject.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="objectcontents" title="Contenu des objets"> +<floater name="objectcontents" title="CONTENU DES OBJETS"> <text name="object_name"> [DESC]: </text> diff --git a/indra/newview/skins/default/xui/fr/floater_perm_prefs.xml b/indra/newview/skins/default/xui/fr/floater_perm_prefs.xml index 9ea970d89d..4b885f3afb 100644 --- a/indra/newview/skins/default/xui/fr/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/fr/floater_perm_prefs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="perm prefs" title="Droits par défaut"> +<floater name="perm prefs" title="DROITS PAR DÉFAUT"> <panel label="Droits" name="permissions"> <button label="?" label_selected="?" name="help"/> <check_box label="Partager avec le groupe" name="share_with_group"/> diff --git a/indra/newview/skins/default/xui/fr/floater_post_process.xml b/indra/newview/skins/default/xui/fr/floater_post_process.xml index 52afb340a6..a22c7512e5 100644 --- a/indra/newview/skins/default/xui/fr/floater_post_process.xml +++ b/indra/newview/skins/default/xui/fr/floater_post_process.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Post-Process Floater" title="Paramètres post-traitement"> +<floater name="Post-Process Floater" title="PARAMÈTRES POST-TRAITEMENT"> <tab_container name="Post-Process Tabs"> <panel label="Filtre couleur" name="wmiColorFilterPanel"> <check_box label="Activer" name="wmiColorFilterToggle" /> diff --git a/indra/newview/skins/default/xui/fr/floater_postcard.xml b/indra/newview/skins/default/xui/fr/floater_postcard.xml index ab21d7423a..9c998c1838 100644 --- a/indra/newview/skins/default/xui/fr/floater_postcard.xml +++ b/indra/newview/skins/default/xui/fr/floater_postcard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Postcard" title="Envoyer la photo par e-mail"> +<floater name="Postcard" title="ENVOYER LA PHOTO PAR E-MAIL"> <text name="to_label" width="135"> E-mail du destinataire : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_preferences.xml b/indra/newview/skins/default/xui/fr/floater_preferences.xml index 9dab4d642c..ccd29a01dc 100644 --- a/indra/newview/skins/default/xui/fr/floater_preferences.xml +++ b/indra/newview/skins/default/xui/fr/floater_preferences.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Preferences" title="Préférences" min_width="330" width="626"> +<floater name="Preferences" title="PRÉFÉRENCES" min_width="330" width="626"> <button label="À propos" label_selected="À propos" name="About..." /> <button label="OK" label_selected="OK" name="OK" /> <button label="Annuler" label_selected="Annuler" name="Cancel" /> diff --git a/indra/newview/skins/default/xui/fr/floater_preview_classified.xml b/indra/newview/skins/default/xui/fr/floater_preview_classified.xml index 1b6f26150d..436a386dc8 100644 --- a/indra/newview/skins/default/xui/fr/floater_preview_classified.xml +++ b/indra/newview/skins/default/xui/fr/floater_preview_classified.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="classified_preview" title="Informations sur la petite annonce" /> +<floater name="classified_preview" title="INFORMATIONS SUR LA PETITE ANNONCE" /> diff --git a/indra/newview/skins/default/xui/fr/floater_preview_event.xml b/indra/newview/skins/default/xui/fr/floater_preview_event.xml index e7fc2aa8dd..30eeeec70d 100644 --- a/indra/newview/skins/default/xui/fr/floater_preview_event.xml +++ b/indra/newview/skins/default/xui/fr/floater_preview_event.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="event_preview" title="Informations sur l'événement" /> +<floater name="event_preview" title="INFORMATIONS SUR L'ÉVÉNEMENT" /> diff --git a/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml b/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml index a23b906df6..ea52442236 100644 --- a/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="preview notecard" title="Remarque :"> +<floater name="preview notecard" title="REMARQUE :"> <button label="Enregistrer" label_selected="Enregistrer" name="Save" /> <text name="desc txt"> Description : diff --git a/indra/newview/skins/default/xui/fr/floater_region_info.xml b/indra/newview/skins/default/xui/fr/floater_region_info.xml index d69f212b86..3ec1ebf7e6 100644 --- a/indra/newview/skins/default/xui/fr/floater_region_info.xml +++ b/indra/newview/skins/default/xui/fr/floater_region_info.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="regioninfo" title="Région et domaine"/> +<floater name="regioninfo" title="RÉGION ET DOMAINE"/> diff --git a/indra/newview/skins/default/xui/fr/floater_report_abuse.xml b/indra/newview/skins/default/xui/fr/floater_report_abuse.xml index 687b3068e6..be97165a3e 100644 --- a/indra/newview/skins/default/xui/fr/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/fr/floater_report_abuse.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_report_abuse" title="Signaler une infraction"> +<floater name="floater_report_abuse" title="SIGNALER UNE INFRACTION"> <texture_picker label="" name="screenshot"/> <check_box label="Inclure une capture d'écran" name="screen_check"/> <text name="reporter_title" width="60"> diff --git a/indra/newview/skins/default/xui/fr/floater_script_debug.xml b/indra/newview/skins/default/xui/fr/floater_script_debug.xml index 3664222fd2..e257aac6c4 100644 --- a/indra/newview/skins/default/xui/fr/floater_script_debug.xml +++ b/indra/newview/skins/default/xui/fr/floater_script_debug.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <multi_floater name="script debug floater" title="Erreurs/alertes de scripts"> <tab_container name="Preview Tabs"> - <floater label="Script" name="all_scripts" title="[All scripts]" /> + <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]" /> </tab_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/fr/floater_script_preview.xml b/indra/newview/skins/default/xui/fr/floater_script_preview.xml index b767081625..43541e8de3 100644 --- a/indra/newview/skins/default/xui/fr/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/fr/floater_script_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="preview lsl text" title="Script : Script de rotation"> +<floater name="preview lsl text" title="SCRIPT : SCRIPT DE ROTATION"> <text name="desc txt"> Description : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_script_queue.xml b/indra/newview/skins/default/xui/fr/floater_script_queue.xml index 55487f75db..d5f39e7ace 100644 --- a/indra/newview/skins/default/xui/fr/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/fr/floater_script_queue.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="queue" title="Réinitialiser progression"> +<floater name="queue" title="RÉINITIALISER PROGRESSION"> <button label="Fermer" label_selected="Fermer" name="close" /> </floater> diff --git a/indra/newview/skins/default/xui/fr/floater_script_search.xml b/indra/newview/skins/default/xui/fr/floater_script_search.xml index 6f912026c4..49b0ffe542 100644 --- a/indra/newview/skins/default/xui/fr/floater_script_search.xml +++ b/indra/newview/skins/default/xui/fr/floater_script_search.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script search" title="Recherche de scripts" width="320"> +<floater name="script search" title="RECHERCHE DE SCRIPTS" width="320"> <check_box label="Non sensible à la casse" name="case_text" left="75"/> <button label="Rechercher" label_selected="Rechercher" name="search_btn" width="96"/> <button label="Remplacer" label_selected="Remplacer" name="replace_btn" left="111" width="96"/> diff --git a/indra/newview/skins/default/xui/fr/floater_sell_land.xml b/indra/newview/skins/default/xui/fr/floater_sell_land.xml index 643a9435db..81c3ccc79a 100644 --- a/indra/newview/skins/default/xui/fr/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/fr/floater_sell_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="sell land" title="Vendre terrain"> +<floater name="sell land" title="VENDRE TERRAIN"> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> <text name="info_parcel_label"> diff --git a/indra/newview/skins/default/xui/fr/floater_settings_debug.xml b/indra/newview/skins/default/xui/fr/floater_settings_debug.xml index e67b8e2f79..f0781d0b32 100644 --- a/indra/newview/skins/default/xui/fr/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/fr/floater_settings_debug.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="settings_debug" title="Paramétrages du mode Debug"> +<floater name="settings_debug" title="PARAMÉTRAGES DU MODE DEBUG"> <combo_box name="boolean_combo"> <combo_box.item name="TRUE" label="TRUE" /> <combo_box.item name="FALSE" label="FALSE" /> diff --git a/indra/newview/skins/default/xui/fr/floater_snapshot.xml b/indra/newview/skins/default/xui/fr/floater_snapshot.xml index 49c6ff04a6..a28e64f7af 100644 --- a/indra/newview/skins/default/xui/fr/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/fr/floater_snapshot.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Snapshot" title="Prévisualiser la photo" width="247"> +<floater name="Snapshot" title="PRÉVISUALISER LA PHOTO" width="247"> <text name="type_label"> Destination de la photo </text> diff --git a/indra/newview/skins/default/xui/fr/floater_sound_preview.xml b/indra/newview/skins/default/xui/fr/floater_sound_preview.xml index 1ab3a4a714..9e2b30b3f6 100644 --- a/indra/newview/skins/default/xui/fr/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/fr/floater_sound_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Sound Preview" title="sound.wav"> +<floater name="Sound Preview" title="SOUND.WAV"> <text name="name_label"> Nom : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_statistics.xml b/indra/newview/skins/default/xui/fr/floater_statistics.xml index 0768c3ace4..a2e3c199ab 100644 --- a/indra/newview/skins/default/xui/fr/floater_statistics.xml +++ b/indra/newview/skins/default/xui/fr/floater_statistics.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="stats floater" title="Statistiques"/> +<floater name="stats floater" title="STATISTIQUES"/> diff --git a/indra/newview/skins/default/xui/fr/floater_telehub.xml b/indra/newview/skins/default/xui/fr/floater_telehub.xml index e6201785bd..c89eea517e 100644 --- a/indra/newview/skins/default/xui/fr/floater_telehub.xml +++ b/indra/newview/skins/default/xui/fr/floater_telehub.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="telehub" title="Téléhub" min_height="310" height="310" > +<floater name="telehub" title="TÉLÉHUB" min_height="310" height="310" > <text name="status_text_connected"> Téléhub connecté à l'objet [OBJECT] </text> diff --git a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml index fa8b65d8a5..ff84025a44 100644 --- a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="texture picker" title="Texture"> +<floater name="texture picker" title="TEXTURE"> <string name="choose_picture"> Cliquez pour sélectionner une image </string> diff --git a/indra/newview/skins/default/xui/fr/floater_tools.xml b/indra/newview/skins/default/xui/fr/floater_tools.xml index e8db326e15..3638c3fb42 100644 --- a/indra/newview/skins/default/xui/fr/floater_tools.xml +++ b/indra/newview/skins/default/xui/fr/floater_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="toolbox floater" title="" short_title="Construire"> +<floater name="toolbox floater" title="" short_title="CONSTRUIRE"> <button label="" label_selected="" name="button focus" tool_tip="Mise au point"/> <button label="" label_selected="" name="button move" tool_tip="Déplacer"/> <button label="" label_selected="" name="button edit" tool_tip="Modifier"/> diff --git a/indra/newview/skins/default/xui/fr/floater_top_objects.xml b/indra/newview/skins/default/xui/fr/floater_top_objects.xml index 69a3d0cd18..479559367f 100644 --- a/indra/newview/skins/default/xui/fr/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/fr/floater_top_objects.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="top_objects" title="en cours de chargement..."> +<floater name="top_objects" title="EN COURS DE CHARGEMENT..."> <text name="title_text"> Chargement... </text> diff --git a/indra/newview/skins/default/xui/fr/floater_water.xml b/indra/newview/skins/default/xui/fr/floater_water.xml index 9b77c2450d..3de5fee0ce 100644 --- a/indra/newview/skins/default/xui/fr/floater_water.xml +++ b/indra/newview/skins/default/xui/fr/floater_water.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Water Floater" title="Éditeur d'eau avancé"> +<floater name="Water Floater" title="ÉDITEUR D'EAU AVANCé"> <text name="KeyFramePresetsText"> Préréglages eau : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_windlight_options.xml b/indra/newview/skins/default/xui/fr/floater_windlight_options.xml index d1a62dc6bc..4ff55d87b6 100644 --- a/indra/newview/skins/default/xui/fr/floater_windlight_options.xml +++ b/indra/newview/skins/default/xui/fr/floater_windlight_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="WindLight floater" title="Éditeur de ciel avancé" width="706"> +<floater name="WindLight floater" title="ÉDITEUR DE CIEL AVANCÉ" width="706"> <text name="KeyFramePresetsText"> Préréglages ciel : </text> diff --git a/indra/newview/skins/default/xui/fr/floater_world_map.xml b/indra/newview/skins/default/xui/fr/floater_world_map.xml index ec2db5f163..1f76202dee 100644 --- a/indra/newview/skins/default/xui/fr/floater_world_map.xml +++ b/indra/newview/skins/default/xui/fr/floater_world_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="worldmap" title="Carte du monde"> +<floater name="worldmap" title="CARTE DU MONDE"> <tab_container name="maptab" width="955"> <panel label="Objets" name="objects_mapview" width="953"/> <panel label="Terrain" name="terrain_mapview" width="953"/> diff --git a/indra/newview/skins/default/xui/fr/panel_edit_profile.xml b/indra/newview/skins/default/xui/fr/panel_edit_profile.xml index f62ea7c80f..3a1585bce2 100644 --- a/indra/newview/skins/default/xui/fr/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/fr/panel_edit_profile.xml @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="edit_profile_panel">
- <string name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
- </string>
- <string name="AcctTypeResident"
- value="Résident" />
- <string name="AcctTypeTrial"
- value="Essai" />
- <string name="AcctTypeCharterMember"
- value="Membre originaire" />
- <string name="AcctTypeEmployee"
- value="Employé(e) de Linden Lab" />
- <string name="PaymentInfoUsed"
- value="Infos de paiement utilisées" />
- <string name="PaymentInfoOnFile"
- value="Infos de paiement enregistrées" />
- <string name="NoPaymentInfoOnFile"
- value="Aucune info de paiement" />
- <string name="AgeVerified"
- value="Âge vérifié" />
- <string name="NotAgeVerified"
- value="Âge non vérifié" />
- <string name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=fr
- </string>
- <panel name="scroll_content_panel">
- <panel name="data_panel" >
- <panel name="lifes_images_panel">
- <panel name="second_life_image_panel">
- <text name="second_life_photo_title_text">
- [SECOND_LIFE]:
- </text>
- </panel>
- </panel>
- <text name="title_partner_text" value="Partenaire :"/>
- <panel name="partner_data_panel">
- <text name="partner_text" value="[FIRST] [LAST]"/>
- </panel>
- <text name="text_box3">
- Réponse si occupé(e) :
- </text>
- </panel>
- </panel>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="edit_profile_panel"> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string name="AcctTypeResident" + value="Résident" /> + <string name="AcctTypeTrial" + value="Essai" /> + <string name="AcctTypeCharterMember" + value="Membre originaire" /> + <string name="AcctTypeEmployee" + value="Employé(e) de Linden Lab" /> + <string name="PaymentInfoUsed" + value="Infos de paiement utilisées" /> + <string name="PaymentInfoOnFile" + value="Infos de paiement enregistrées" /> + <string name="NoPaymentInfoOnFile" + value="Aucune info de paiement" /> + <string name="AgeVerified" + value="Âge vérifié" /> + <string name="NotAgeVerified" + value="Âge non vérifié" /> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=fr + </string> + <panel name="scroll_content_panel"> + <panel name="data_panel" > + <panel name="lifes_images_panel"> + <panel name="second_life_image_panel"> + <text name="second_life_photo_title_text"> + [SECOND_LIFE]: + </text> + </panel> + </panel> + <text name="title_partner_text" value="Partenaire :"/> + <panel name="partner_data_panel"> + <text name="partner_text" value="[FIRST] [LAST]"/> + </panel> + <text name="text_box3"> + Réponse si occupé(e) : + </text> + </panel> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml index 2c91375930..a5aff9d486 100644 --- a/indra/newview/skins/default/xui/it/floater_about.xml +++ b/indra/newview/skins/default/xui/it/floater_about.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_about" title="Informazioni su [APP_NAME]"> +<floater name="floater_about" title="INFORMAZIONI SU [APP_NAME]"> <tab_container name="about_tab"> <panel name="credits_panel"> <text_editor name="credits_editor"> diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml index ede581c5ed..f2bd150ad7 100644 --- a/indra/newview/skins/default/xui/it/floater_about_land.xml +++ b/indra/newview/skins/default/xui/it/floater_about_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterland" title="Informazioni sul terreno"> +<floater name="floaterland" title="INFORMAZIONI SUL TERRENO"> <tab_container name="landtab"> <panel label="Generale" name="land_general_panel"> <text name="Name:"> diff --git a/indra/newview/skins/default/xui/it/floater_auction.xml b/indra/newview/skins/default/xui/it/floater_auction.xml index edbb9ab9a9..bba76a83cc 100644 --- a/indra/newview/skins/default/xui/it/floater_auction.xml +++ b/indra/newview/skins/default/xui/it/floater_auction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_auction" title="Inizia a vendere terra Linden"> +<floater name="floater_auction" title="INIZIA A VENDERE TERRA LINDEN"> <check_box label="Includi barriere di selezione gialle" name="fence_check"/> <button label="Fotografia" label_selected="Fotografia" name="snapshot_btn"/> <button label="OK" label_selected="OK" name="ok_btn"/> diff --git a/indra/newview/skins/default/xui/it/floater_avatar_picker.xml b/indra/newview/skins/default/xui/it/floater_avatar_picker.xml index a223e30fb5..89a61eeca8 100644 --- a/indra/newview/skins/default/xui/it/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/it/floater_avatar_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatarpicker" title="Scegli residente"> +<floater name="avatarpicker" title="SCEGLI RESIDENTE"> <tab_container name="ResidentChooserTabs"> <panel label="Cerca" name="SearchPanel"> <text name="InstructSearchResidentName"> diff --git a/indra/newview/skins/default/xui/it/floater_avatar_textures.xml b/indra/newview/skins/default/xui/it/floater_avatar_textures.xml index 281f436224..f55b23af35 100644 --- a/indra/newview/skins/default/xui/it/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/it/floater_avatar_textures.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatar_texture_debug" title="Texture dell'Avatar"> +<floater name="avatar_texture_debug" title="TEXTURE DELL'AVATAR"> <text name="baked_label"> Texture Visualizzate </text> diff --git a/indra/newview/skins/default/xui/it/floater_beacons.xml b/indra/newview/skins/default/xui/it/floater_beacons.xml index 035b073729..126c03e855 100644 --- a/indra/newview/skins/default/xui/it/floater_beacons.xml +++ b/indra/newview/skins/default/xui/it/floater_beacons.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="beacons" title="Segnali luminosi"> +<floater name="beacons" title="SEGNALI LUMINOSI"> <panel name="beacons_panel"> <check_box label="Oggetti scriptati con solo 'tocca' abilitato" name="touch_only"/> <check_box label="Oggetti scriptati" name="scripted"/> diff --git a/indra/newview/skins/default/xui/it/floater_build_options.xml b/indra/newview/skins/default/xui/it/floater_build_options.xml index 2c60aeda2b..c6ee0f7917 100644 --- a/indra/newview/skins/default/xui/it/floater_build_options.xml +++ b/indra/newview/skins/default/xui/it/floater_build_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="build options floater" title="Opzioni della griglia"> +<floater name="build options floater" title="OPZIONI DELLA GRIGLIA"> <spinner label="Unità di misura della griglia (metri)" name="GridResolution" width="250" label_width="192"/> <spinner label="Estensione della griglia (metri)" name="GridDrawSize" width="250" label_width="192"/> <check_box label="Abilita sotto-unità di movimento" name="GridSubUnit"/> diff --git a/indra/newview/skins/default/xui/it/floater_bulk_perms.xml b/indra/newview/skins/default/xui/it/floater_bulk_perms.xml index 7ca57f34b3..7f5b68279e 100644 --- a/indra/newview/skins/default/xui/it/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/it/floater_bulk_perms.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterbulkperms" title="Modifica in massa i permessi del contenuto"> +<floater name="floaterbulkperms" title="MODIFICA IN MASSA I PERMESSI DEL CONTENUTO"> <text name="applyto"> Tipi di contenuto </text> diff --git a/indra/newview/skins/default/xui/it/floater_bumps.xml b/indra/newview/skins/default/xui/it/floater_bumps.xml index d9ce29fa08..23fa1a41a6 100644 --- a/indra/newview/skins/default/xui/it/floater_bumps.xml +++ b/indra/newview/skins/default/xui/it/floater_bumps.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_bumps" title="Collisioni, spinte e colpi"> +<floater name="floater_bumps" title="COLLISIONI, SPINTE E COLPI"> <string name="none_detected"> Nessuno rilevato </string> diff --git a/indra/newview/skins/default/xui/it/floater_buy_contents.xml b/indra/newview/skins/default/xui/it/floater_buy_contents.xml index 2836f98970..1a6f64c07e 100644 --- a/indra/newview/skins/default/xui/it/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/it/floater_buy_contents.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_buy_contents" title="Compra i contenuti"> +<floater name="floater_buy_contents" title="COMPRA I CONTENUTI"> <text name="contains_text"> [NAME] contiene: </text> diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml index a24f0dbe7a..6b881683f1 100644 --- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy currency" title="Acquista valuta"> +<floater name="buy currency" title="ACQUISTA VALUTA"> <text name="info_buying"> Acquistando valuta: </text> diff --git a/indra/newview/skins/default/xui/it/floater_buy_land.xml b/indra/newview/skins/default/xui/it/floater_buy_land.xml index d6036c19dd..b5d7ba0763 100644 --- a/indra/newview/skins/default/xui/it/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/it/floater_buy_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy land" title="Compra terra"> +<floater name="buy land" title="COMPRA TERRA"> <text name="region_name_label"> Regione: </text> diff --git a/indra/newview/skins/default/xui/it/floater_buy_object.xml b/indra/newview/skins/default/xui/it/floater_buy_object.xml index 90ff84a89c..e99d432367 100644 --- a/indra/newview/skins/default/xui/it/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/it/floater_buy_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Compra una copia dell'oggetto"> +<floater name="contents" title="COMPRA UNA COPIA DELL'OGGETTO"> <text name="contents_text"> e dei suoi contenuti: </text> diff --git a/indra/newview/skins/default/xui/it/floater_choose_group.xml b/indra/newview/skins/default/xui/it/floater_choose_group.xml index 3b5fc79bd8..00f2692295 100644 --- a/indra/newview/skins/default/xui/it/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/it/floater_choose_group.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="groups" title="Gruppi"> +<floater name="groups" title="GRUPPI"> <text name="groupdesc"> Scegli un gruppo: </text> diff --git a/indra/newview/skins/default/xui/it/floater_color_picker.xml b/indra/newview/skins/default/xui/it/floater_color_picker.xml index 1e6d7bc3f0..297b006e72 100644 --- a/indra/newview/skins/default/xui/it/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/it/floater_color_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="ColorPicker" title="Tavolozza colori"> +<floater name="ColorPicker" title="TAVOLOZZA COLORI"> <text name="r_val_text"> Rosso: </text> diff --git a/indra/newview/skins/default/xui/it/floater_customize.xml b/indra/newview/skins/default/xui/it/floater_customize.xml index eac673e004..ad6111718a 100644 --- a/indra/newview/skins/default/xui/it/floater_customize.xml +++ b/indra/newview/skins/default/xui/it/floater_customize.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater customize" title="Aspetto fisico" width="551"> +<floater name="floater customize" title="ASPETTO FISICO" width="551"> <tab_container name="customize tab container" tab_min_width="120" width="549"> <placeholder label="Parti del corpo" name="body_parts_placeholder"/> <panel label="Forma del corpo" name="Shape" left="124" width="389"> diff --git a/indra/newview/skins/default/xui/it/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/it/floater_day_cycle_options.xml index 4c62d4f5a2..7d50e322c0 100644 --- a/indra/newview/skins/default/xui/it/floater_day_cycle_options.xml +++ b/indra/newview/skins/default/xui/it/floater_day_cycle_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Day Cycle Floater" title="Editor delle ciclo giorno/notte"> +<floater name="Day Cycle Floater" title="EDITOR DELLE CICLO GIORNO/NOTTE"> <tab_container name="Day Cycle Tabs"> <panel label="Ciclo giorno/notte" name="Day Cycle"> <button label="?" name="WLDayCycleHelp"/> diff --git a/indra/newview/skins/default/xui/it/floater_device_settings.xml b/indra/newview/skins/default/xui/it/floater_device_settings.xml index cbf965bf93..932978809d 100644 --- a/indra/newview/skins/default/xui/it/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/it/floater_device_settings.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_device_settings" title="Impostazioni dispositivi Voice Chat"/> +<floater name="floater_device_settings" title="IMPOSTAZIONI DISPOSITIVI VOICE CHAT"/> diff --git a/indra/newview/skins/default/xui/it/floater_env_settings.xml b/indra/newview/skins/default/xui/it/floater_env_settings.xml index 36f97bda81..32858d18cd 100644 --- a/indra/newview/skins/default/xui/it/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/it/floater_env_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Environment Editor Floater" title="Editor dell'ambiente"> +<floater name="Environment Editor Floater" title="EDITOR DELL'AMBIENTE"> <text name="EnvTimeText"> Ora del giorno diff --git a/indra/newview/skins/default/xui/it/floater_font_test.xml b/indra/newview/skins/default/xui/it/floater_font_test.xml index 27b87a931d..859c068b11 100644 --- a/indra/newview/skins/default/xui/it/floater_font_test.xml +++ b/indra/newview/skins/default/xui/it/floater_font_test.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Tipo di carattere per test"> +<floater name="contents" title="TIPO DI CARATTERE PER TEST"> <text name="linea"> OverrideTest, dovrebbe apparire qui come Times. (Dal default/xui/en-us) </text> diff --git a/indra/newview/skins/default/xui/it/floater_gesture.xml b/indra/newview/skins/default/xui/it/floater_gesture.xml index 997e13ecb5..91b7381d13 100644 --- a/indra/newview/skins/default/xui/it/floater_gesture.xml +++ b/indra/newview/skins/default/xui/it/floater_gesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="gestures" title="Gesture attive"> +<floater name="gestures" title="GESTURE ATTIVE"> <text name="help_label"> Fai doppio click su una gesture per azionare animazioni e suoni. diff --git a/indra/newview/skins/default/xui/it/floater_hardware_settings.xml b/indra/newview/skins/default/xui/it/floater_hardware_settings.xml index 688f9137a2..cdf3e970a6 100644 --- a/indra/newview/skins/default/xui/it/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/it/floater_hardware_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Hardware Settings Floater" title="Impostazioni Hardware"> +<floater name="Hardware Settings Floater" title="IMPOSTAZIONI HARDWARE"> <text name="Filtering:"> Filtraggio: </text> diff --git a/indra/newview/skins/default/xui/it/floater_hud.xml b/indra/newview/skins/default/xui/it/floater_hud.xml index d31bcedf05..e458913452 100644 --- a/indra/newview/skins/default/xui/it/floater_hud.xml +++ b/indra/newview/skins/default/xui/it/floater_hud.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_hud" title="Tutorial"/> +<floater name="floater_hud" title="TUTORIAL"/> diff --git a/indra/newview/skins/default/xui/it/floater_inspect.xml b/indra/newview/skins/default/xui/it/floater_inspect.xml index 6028c40557..1a4e6c3c1b 100644 --- a/indra/newview/skins/default/xui/it/floater_inspect.xml +++ b/indra/newview/skins/default/xui/it/floater_inspect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="inspect" title="Ispeziona oggetti" min_width="450"> +<floater name="inspect" title="ISPEZIONA OGGETTI" min_width="450"> <scroll_list name="object_list" tool_tip="Seleziona un oggetto da questo elenco per evidenziarlo inworld"> <column label="Nome dell'oggetto" name="object_name"/> <column label="Proprietario" name="owner_name"/> diff --git a/indra/newview/skins/default/xui/it/floater_inventory.xml b/indra/newview/skins/default/xui/it/floater_inventory.xml index f21f213497..e3325463d6 100644 --- a/indra/newview/skins/default/xui/it/floater_inventory.xml +++ b/indra/newview/skins/default/xui/it/floater_inventory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory" title="Inventario"> +<floater name="Inventory" title="INVENTARIO"> <search_editor label="Scrivi qui per cercare" name="inventory search editor"/> <tab_container name="inventory filter tabs"> <inventory_panel label="Tutti gli elementi" name="All Items"/> diff --git a/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml index e32f57e9f4..8860fd8207 100644 --- a/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="item properties" title="Proprietà dell'oggetto nell'inventario"> +<floater name="item properties" title="PROPRIETÀ DELL'OGGETTO NELL'INVENTARIO"> <text name="LabelItemNameTitle"> Nome: </text> diff --git a/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml index c2c05b4023..b5a17b2fc1 100644 --- a/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory Finder" title="Inventario_Cose_recenti" width="165"> +<floater name="Inventory Finder" title="INVENTARIO_COSE_RECENTI" width="165"> <check_box label="Animazioni" name="check_animation"/> <check_box label="Biglietti da visita" name="check_calling_card"/> <check_box label="Abiti" name="check_clothing"/> diff --git a/indra/newview/skins/default/xui/it/floater_joystick.xml b/indra/newview/skins/default/xui/it/floater_joystick.xml index b7b7663910..d74ff9bfb4 100644 --- a/indra/newview/skins/default/xui/it/floater_joystick.xml +++ b/indra/newview/skins/default/xui/it/floater_joystick.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Joystick" title="Configurazione Joystick"> +<floater name="Joystick" title="CONFIGURAZIONE JOYSTICK"> <check_box name="enable_joystick" label="Abilita Joystick:"/> <text left="120" name="joystick_type" width="380"/> <spinner label="Mapping: asse X" name="JoystickAxis1" label_width="140" width="180" left="12"/> diff --git a/indra/newview/skins/default/xui/it/floater_lagmeter.xml b/indra/newview/skins/default/xui/it/floater_lagmeter.xml index af70ad9d31..5ed748da69 100644 --- a/indra/newview/skins/default/xui/it/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/it/floater_lagmeter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="Misuratore del lag"> +<floater name="floater_lagmeter" title="MISURATORE DEL LAG"> <button label="" label_selected="" name="client_lagmeter" tool_tip="Stato del lag del programma in locale"/> <text left="30" name="client_lag_cause" right="-10" /> <text left="30" name="network_lag_cause" right="-10" /> diff --git a/indra/newview/skins/default/xui/it/floater_land_holdings.xml b/indra/newview/skins/default/xui/it/floater_land_holdings.xml index 85661c28d7..8a6689f6af 100644 --- a/indra/newview/skins/default/xui/it/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/it/floater_land_holdings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="land holdings floater" title="Il mio terreno"> +<floater name="land holdings floater" title="IL MIO TERRENO"> <scroll_list name="parcel list"> <column label="Nome del terreno" name="name"/> <column label="Regione" name="location"/> diff --git a/indra/newview/skins/default/xui/it/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/it/floater_live_lsleditor.xml index bb1f6116cf..bd50ad3df7 100644 --- a/indra/newview/skins/default/xui/it/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/it/floater_live_lsleditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="script ed float" title="Script: Nuovo script"> +<floater name="script ed float" title="SCRIPT: NUOVO SCRIPT"> <button label="Ripristina" label_selected="Ripristina" name="Reset"/> <check_box label="In esecuzione" name="running" left="4"/> <check_box label="Mono" name="mono" left="106"/> diff --git a/indra/newview/skins/default/xui/it/floater_lsl_guide.xml b/indra/newview/skins/default/xui/it/floater_lsl_guide.xml index ec62dd087d..4241a32ec1 100644 --- a/indra/newview/skins/default/xui/it/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/it/floater_lsl_guide.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="script ed float" title="LSL Wiki"> +<floater name="script ed float" title="LSL WIKI"> <check_box label="Segui il cursore" name="lock_check"/> <combo_box label="Blocca" name="history_combo" left_delta="120" width="70"/> <button label="Indietro" name="back_btn" left_delta="75"/> diff --git a/indra/newview/skins/default/xui/it/floater_media_browser.xml b/indra/newview/skins/default/xui/it/floater_media_browser.xml index 4d3462b348..7a5f9c9fcb 100644 --- a/indra/newview/skins/default/xui/it/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/it/floater_media_browser.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_about" title="Browser multimediale"> +<floater name="floater_about" title="BROWSER MULTIMEDIALE"> <layout_stack name="stack1"> <layout_panel name="nav_controls"> <button label="Indietro" name="back" width="75"/> diff --git a/indra/newview/skins/default/xui/it/floater_mem_leaking.xml b/indra/newview/skins/default/xui/it/floater_mem_leaking.xml index 4bd0e6ae6b..d180953157 100644 --- a/indra/newview/skins/default/xui/it/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/it/floater_mem_leaking.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="MemLeak" title="Simulazione di perdità di memoria"> +<floater name="MemLeak" title="SIMULAZIONE DI PERDITÀ DI MEMORIA"> <spinner label="Perdità di velocità (bytes per frame):" name="leak_speed"/> <spinner label="Memoria Persa Max (MB):" name="max_leak"/> <text name="total_leaked_label"> diff --git a/indra/newview/skins/default/xui/it/floater_mute_object.xml b/indra/newview/skins/default/xui/it/floater_mute_object.xml index 6bacdcab41..a72bfe9681 100644 --- a/indra/newview/skins/default/xui/it/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/it/floater_mute_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="mute by name" title="Ignora l'oggetto dal nome"> +<floater name="mute by name" title="IGNORA L'OGGETTO DAL NOME"> <text name="message"> Ignora per nome ha effetti sull'oggetto in chat e IM, non nei suoni. Devi scrivere esattamente il nome dell'oggetto. diff --git a/indra/newview/skins/default/xui/it/floater_my_friends.xml b/indra/newview/skins/default/xui/it/floater_my_friends.xml index a77b8aff80..faeba0a6d9 100644 --- a/indra/newview/skins/default/xui/it/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/it/floater_my_friends.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_my_friends" title="Contatti"> +<floater name="floater_my_friends" title="CONTATTI"> <tab_container name="friends_and_groups"> <panel label="Amici" name="friends_panel"/> <panel label="Gruppi" name="groups_panel"/> diff --git a/indra/newview/skins/default/xui/it/floater_openobject.xml b/indra/newview/skins/default/xui/it/floater_openobject.xml index d04a6f3632..0c2029e18e 100644 --- a/indra/newview/skins/default/xui/it/floater_openobject.xml +++ b/indra/newview/skins/default/xui/it/floater_openobject.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="objectcontents" title="Contenuto dell'oggetto"> +<floater name="objectcontents" title="CONTENUTO DELL'OGGETTO"> <text name="object_name"> [DESC]: </text> diff --git a/indra/newview/skins/default/xui/it/floater_perm_prefs.xml b/indra/newview/skins/default/xui/it/floater_perm_prefs.xml index 8037481f37..46de31455b 100644 --- a/indra/newview/skins/default/xui/it/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/it/floater_perm_prefs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="perm prefs" title="Permessi di base di importazione"> +<floater name="perm prefs" title="PERMESSI DI BASE DI IMPORTAZIONE"> <panel label="Permessi" name="permissions"> <button label="?" label_selected="?" name="help"/> <check_box label="Condividi con il gruppo" name="share_with_group"/> diff --git a/indra/newview/skins/default/xui/it/floater_post_process.xml b/indra/newview/skins/default/xui/it/floater_post_process.xml index 226970041b..3aa8b29101 100644 --- a/indra/newview/skins/default/xui/it/floater_post_process.xml +++ b/indra/newview/skins/default/xui/it/floater_post_process.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="Impostazioni di post-produzione"> +<floater name="Post-Process Floater" title="IMPOSTAZIONI DI POST-PRODUZIONE"> <tab_container name="Post-Process Tabs"> <panel label="Filtro Colore" name="wmiColorFilterPanel"> <check_box label="Abilita" name="wmiColorFilterToggle"/> diff --git a/indra/newview/skins/default/xui/it/floater_postcard.xml b/indra/newview/skins/default/xui/it/floater_postcard.xml index 5132771acc..5ea3b634d4 100644 --- a/indra/newview/skins/default/xui/it/floater_postcard.xml +++ b/indra/newview/skins/default/xui/it/floater_postcard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Postcard" title="Invia la fotografia via email"> +<floater name="Postcard" title="INVIA LA FOTOGRAFIA VIA EMAIL"> <text name="to_label" width="135"> Email del destinatario: </text> diff --git a/indra/newview/skins/default/xui/it/floater_preferences.xml b/indra/newview/skins/default/xui/it/floater_preferences.xml index 6277300bee..172449554d 100644 --- a/indra/newview/skins/default/xui/it/floater_preferences.xml +++ b/indra/newview/skins/default/xui/it/floater_preferences.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Preferences" title="Preferenze" min_width="350" width="646"> +<floater name="Preferences" title="PREFERENZE" min_width="350" width="646"> <button label="OK" label_selected="OK" name="OK"/> <button label="Annulla" label_selected="Annulla" name="Cancel"/> <button label="Applica" label_selected="Applica" name="Apply"/> diff --git a/indra/newview/skins/default/xui/it/floater_preview_classified.xml b/indra/newview/skins/default/xui/it/floater_preview_classified.xml index f78c70b1fe..5819bd37a5 100644 --- a/indra/newview/skins/default/xui/it/floater_preview_classified.xml +++ b/indra/newview/skins/default/xui/it/floater_preview_classified.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="classified_preview" title="Informazione Riservata"/> +<floater name="classified_preview" title="INFORMAZIONE RISERVATA"/> diff --git a/indra/newview/skins/default/xui/it/floater_preview_event.xml b/indra/newview/skins/default/xui/it/floater_preview_event.xml index 7cc99a9fea..dca38c363f 100644 --- a/indra/newview/skins/default/xui/it/floater_preview_event.xml +++ b/indra/newview/skins/default/xui/it/floater_preview_event.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="event_preview" title="Informazione sull'evento"/> +<floater name="event_preview" title="INFORMAZIONE SULL'EVENTO"/> diff --git a/indra/newview/skins/default/xui/it/floater_preview_notecard.xml b/indra/newview/skins/default/xui/it/floater_preview_notecard.xml index b0608c8546..81a51223b0 100644 --- a/indra/newview/skins/default/xui/it/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/it/floater_preview_notecard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="preview notecard" title="Nota:"> +<floater name="preview notecard" title="NOTA:"> <button label="Salva" label_selected="Salva" name="Save"/> <text name="desc txt"> Descrizione: diff --git a/indra/newview/skins/default/xui/it/floater_region_info.xml b/indra/newview/skins/default/xui/it/floater_region_info.xml index a802550bf4..a715cf1f06 100644 --- a/indra/newview/skins/default/xui/it/floater_region_info.xml +++ b/indra/newview/skins/default/xui/it/floater_region_info.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="regioninfo" title="Regione/Proprietà "/> +<floater name="regioninfo" title="REGIONE/PROPRIETÀ"/> diff --git a/indra/newview/skins/default/xui/it/floater_report_abuse.xml b/indra/newview/skins/default/xui/it/floater_report_abuse.xml index c67fc69db6..4b969354fe 100644 --- a/indra/newview/skins/default/xui/it/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/it/floater_report_abuse.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_report_abuse" title="Denuncia di Abuso"> +<floater name="floater_report_abuse" title="DENUNCIA DI ABUSO"> <check_box label="Includi una fotografia" name="screen_check"/> <text name="reporter_title"> Segnalato da: diff --git a/indra/newview/skins/default/xui/it/floater_script_debug.xml b/indra/newview/skins/default/xui/it/floater_script_debug.xml index 39736dde67..89bf80da5e 100644 --- a/indra/newview/skins/default/xui/it/floater_script_debug.xml +++ b/indra/newview/skins/default/xui/it/floater_script_debug.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <multi_floater name="script debug floater" title="Avvisi/Errori Script"> <tab_container name="Preview Tabs"> - <floater label="Script" name="all_scripts" title="[Tutti gli script]"/> + <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]"/> </tab_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/it/floater_script_preview.xml b/indra/newview/skins/default/xui/it/floater_script_preview.xml index 20af60b2d4..934ffd5395 100644 --- a/indra/newview/skins/default/xui/it/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/it/floater_script_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="preview lsl text" title="Script: Script di rotazione"> +<floater name="preview lsl text" title="SCRIPT: SCRIPT DI ROTAZIONE"> <text name="desc txt"> Descrizione: </text> diff --git a/indra/newview/skins/default/xui/it/floater_script_queue.xml b/indra/newview/skins/default/xui/it/floater_script_queue.xml index e5b38fea62..37eb3e4bbf 100644 --- a/indra/newview/skins/default/xui/it/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/it/floater_script_queue.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="queue" title="Progressione reset"> +<floater name="queue" title="PROGRESSIONE RESET"> <button label="Chiudi" label_selected="Chiudi" name="close"/> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_script_search.xml b/indra/newview/skins/default/xui/it/floater_script_search.xml index 470fb76135..e5f923f7a3 100644 --- a/indra/newview/skins/default/xui/it/floater_script_search.xml +++ b/indra/newview/skins/default/xui/it/floater_script_search.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="script search" title="Cerca Script" width="320"> +<floater name="script search" title="CERCA SCRIPT" width="320"> <check_box label="Senza distinzione tra maiuscole e minuscole" name="case_text" left="65"/> <button label="Cerca" label_selected="Cerca" name="search_btn" width="85"/> <button label="Sostituisci" label_selected="Sostituisci" name="replace_btn" left="100" width="85"/> diff --git a/indra/newview/skins/default/xui/it/floater_sell_land.xml b/indra/newview/skins/default/xui/it/floater_sell_land.xml index 79dd2c5abf..91712a706b 100644 --- a/indra/newview/skins/default/xui/it/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/it/floater_sell_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="sell land" title="Vendi terra"> +<floater name="sell land" title="VENDI TERRA"> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> <text name="info_parcel_label"> diff --git a/indra/newview/skins/default/xui/it/floater_settings_debug.xml b/indra/newview/skins/default/xui/it/floater_settings_debug.xml index 6dd1b7978d..aec3c8aa9d 100644 --- a/indra/newview/skins/default/xui/it/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/it/floater_settings_debug.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="settings_debug" title="Configurazioni per il debug"> +<floater name="settings_debug" title="CONFIGURAZIONI PER IL DEBUG"> <combo_box name="boolean_combo"> <combo_box.item name="TRUE" label="VERO"/> <combo_box.item name="FALSE" label="FALSO"/> diff --git a/indra/newview/skins/default/xui/it/floater_snapshot.xml b/indra/newview/skins/default/xui/it/floater_snapshot.xml index 808158ff7e..e226ce6ffe 100644 --- a/indra/newview/skins/default/xui/it/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/it/floater_snapshot.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Snapshot" title="Anteprima della fotografia" width="247"> +<floater name="Snapshot" title="ANTEPRIMA DELLA FOTOGRAFIA" width="247"> <text name="type_label"> Destinazione della fotografia </text> diff --git a/indra/newview/skins/default/xui/it/floater_sound_preview.xml b/indra/newview/skins/default/xui/it/floater_sound_preview.xml index 8611732983..221e5e5b53 100644 --- a/indra/newview/skins/default/xui/it/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/it/floater_sound_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Sound Preview" title="sound.wav"> +<floater name="Sound Preview" title="SOUND.WAV"> <text name="name_label"> Nome: </text> diff --git a/indra/newview/skins/default/xui/it/floater_statistics.xml b/indra/newview/skins/default/xui/it/floater_statistics.xml index 6083949b8c..00df1ff994 100644 --- a/indra/newview/skins/default/xui/it/floater_statistics.xml +++ b/indra/newview/skins/default/xui/it/floater_statistics.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="stats floater" title="Statistiche"/> +<floater name="stats floater" title="STATISTICHE"/> diff --git a/indra/newview/skins/default/xui/it/floater_telehub.xml b/indra/newview/skins/default/xui/it/floater_telehub.xml index 0c5199dbc7..de5c32574f 100644 --- a/indra/newview/skins/default/xui/it/floater_telehub.xml +++ b/indra/newview/skins/default/xui/it/floater_telehub.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="telehub" title="Telehub" min_height="310" height="310" width="286"> +<floater name="telehub" title="TELEHUB" min_height="310" height="310" width="286"> <text name="status_text_connected"> Telehub connesso all'oggetto [OBJECT] </text> diff --git a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml index 65bc8ba41d..836f85b48c 100644 --- a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="texture picker" title="Preferiti: Immagine"> +<floater name="texture picker" title="PREFERITI: IMMAGINE"> <string name="choose_picture"> Clicca per scegliere l'immagine </string> diff --git a/indra/newview/skins/default/xui/it/floater_tools.xml b/indra/newview/skins/default/xui/it/floater_tools.xml index 8fc1818ccc..8e6f27e162 100644 --- a/indra/newview/skins/default/xui/it/floater_tools.xml +++ b/indra/newview/skins/default/xui/it/floater_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="toolbox floater" title="" short_title="Costruisci" width="288"> +<floater name="toolbox floater" title="" short_title="COSTRUISCI" width="288"> <button label="" label_selected="" name="button focus" tool_tip="Focus"/> <button label="" label_selected="" name="button move" tool_tip="Muoviti"/> <button label="" label_selected="" name="button edit" tool_tip="Modifica"/> diff --git a/indra/newview/skins/default/xui/it/floater_top_objects.xml b/indra/newview/skins/default/xui/it/floater_top_objects.xml index 470e21769c..9b406199e9 100644 --- a/indra/newview/skins/default/xui/it/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/it/floater_top_objects.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="top_objects" title="In caricamento..."> +<floater name="top_objects" title="IN CARICAMENTO..."> <text name="title_text"> In caricamento... </text> diff --git a/indra/newview/skins/default/xui/it/floater_water.xml b/indra/newview/skins/default/xui/it/floater_water.xml index 33f91ed1c8..13db1d4589 100644 --- a/indra/newview/skins/default/xui/it/floater_water.xml +++ b/indra/newview/skins/default/xui/it/floater_water.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Water Floater" title="Editor avanzato dell'acqua"> +<floater name="Water Floater" title="EDITOR AVANZATO DELL'ACQUA"> <text name="KeyFramePresetsText" width="224"> Impostazioni predeterminate dell'acqua: </text> diff --git a/indra/newview/skins/default/xui/it/floater_windlight_options.xml b/indra/newview/skins/default/xui/it/floater_windlight_options.xml index 5076c777dc..e86d656e39 100644 --- a/indra/newview/skins/default/xui/it/floater_windlight_options.xml +++ b/indra/newview/skins/default/xui/it/floater_windlight_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="WindLight floater" title="Editor avanzato del cielo"> +<floater name="WindLight floater" title="EDITOR AVANZATO DEL CIELO"> <text name="KeyFramePresetsText"> Cieli predefiniti: </text> diff --git a/indra/newview/skins/default/xui/it/floater_world_map.xml b/indra/newview/skins/default/xui/it/floater_world_map.xml index e19335fe07..6fb7b93bc7 100644 --- a/indra/newview/skins/default/xui/it/floater_world_map.xml +++ b/indra/newview/skins/default/xui/it/floater_world_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="worldmap" title="Mappa"> +<floater name="worldmap" title="MAPPA"> <tab_container name="maptab"> <panel label="Oggetti" name="objects_mapview"/> <panel label="Terreno" name="terrain_mapview"/> diff --git a/indra/newview/skins/default/xui/it/panel_edit_profile.xml b/indra/newview/skins/default/xui/it/panel_edit_profile.xml index 0eba7bf3b6..33f3c367c2 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_profile.xml @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="edit_profile_panel">
- <string name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
- </string>
- <string name="AcctTypeResident"
- value="Residente" />
- <string name="AcctTypeTrial"
- value="Prova" />
- <string name="AcctTypeCharterMember"
- value="Membro privilegiato" />
- <string name="AcctTypeEmployee"
- value="Impiegato della Linden Lab" />
- <string name="PaymentInfoUsed"
- value="Info. di pagamento usate" />
- <string name="PaymentInfoOnFile"
- value="Info. di pagamento in archivio" />
- <string name="NoPaymentInfoOnFile"
- value="Nessuna info. di pagamento" />
- <string name="AgeVerified"
- value="Età verificata" />
- <string name="NotAgeVerified"
- value="Età non verificata" />
- <string name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=it
- </string>
- <panel name="scroll_content_panel">
- <panel name="data_panel" >
- <panel name="lifes_images_panel">
- <panel name="second_life_image_panel">
- <text name="second_life_photo_title_text">
- [SECOND_LIFE]:
- </text>
- </panel>
- </panel>
- <text name="title_partner_text" value="Partner:"/>
- <panel name="partner_data_panel">
- <text name="partner_text" value="[FIRST] [LAST]"/>
- </panel>
- <text name="text_box3">
- Risposta agli IM quando sono in 'Occupato':
- </text>
- </panel>
- </panel>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="edit_profile_panel"> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string name="AcctTypeResident" + value="Residente" /> + <string name="AcctTypeTrial" + value="Prova" /> + <string name="AcctTypeCharterMember" + value="Membro privilegiato" /> + <string name="AcctTypeEmployee" + value="Impiegato della Linden Lab" /> + <string name="PaymentInfoUsed" + value="Info. di pagamento usate" /> + <string name="PaymentInfoOnFile" + value="Info. di pagamento in archivio" /> + <string name="NoPaymentInfoOnFile" + value="Nessuna info. di pagamento" /> + <string name="AgeVerified" + value="Età verificata" /> + <string name="NotAgeVerified" + value="Età non verificata" /> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=it + </string> + <panel name="scroll_content_panel"> + <panel name="data_panel" > + <panel name="lifes_images_panel"> + <panel name="second_life_image_panel"> + <text name="second_life_photo_title_text"> + [SECOND_LIFE]: + </text> + </panel> + </panel> + <text name="title_partner_text" value="Partner:"/> + <panel name="partner_data_panel"> + <text name="partner_text" value="[FIRST] [LAST]"/> + </panel> + <text name="text_box3"> + Risposta agli IM quando sono in 'Occupato': + </text> + </panel> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml index a9b3d81a3b..834d49e169 100644 --- a/indra/newview/skins/default/xui/ja/floater_about.xml +++ b/indra/newview/skins/default/xui/ja/floater_about.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater name="floater_about" title="[APP_NAME]ã«ã¤ã„ã¦"> <tab_container name="about_tab"> <panel name="credits_panel"> diff --git a/indra/newview/skins/default/xui/ja/floater_device_settings.xml b/indra/newview/skins/default/xui/ja/floater_device_settings.xml index 5c258df9fd..f189acf101 100644 --- a/indra/newview/skins/default/xui/ja/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/ja/floater_device_settings.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_device_settings" title="ボイスãƒãƒ£ãƒƒãƒˆæ©Ÿå™¨ã®è¨å®š" />
\ No newline at end of file +<floater name="floater_device_settings" title="ボイスãƒãƒ£ãƒƒãƒˆæ©Ÿå™¨ã®è¨å®š" /> diff --git a/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml index d4037487b7..2200809925 100644 --- a/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Inventory Finder" title="inventory_recent_items"> +<floater name="Inventory Finder" title="INVENTORY_RECENT_ITEMS"> <check_box label="アニメーション" name="check_animation" /> <check_box label="コーリング・カード" name="check_calling_card" /> <check_box label="æœ" name="check_clothing" /> diff --git a/indra/newview/skins/default/xui/ja/floater_lsl_guide.xml b/indra/newview/skins/default/xui/ja/floater_lsl_guide.xml index 55eba966dc..e535fc731f 100644 --- a/indra/newview/skins/default/xui/ja/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/ja/floater_lsl_guide.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="LSL Wiki"> +<floater name="script ed float" title="LSL WIKI"> <check_box label="カーソルを追ã†" name="lock_check" /> <combo_box label="ãƒãƒƒã‚¯" name="history_combo" /> <button label="戻る" name="back_btn" /> diff --git a/indra/newview/skins/default/xui/ja/floater_script_debug.xml b/indra/newview/skins/default/xui/ja/floater_script_debug.xml index dd934e3592..0ac7a988e0 100644 --- a/indra/newview/skins/default/xui/ja/floater_script_debug.xml +++ b/indra/newview/skins/default/xui/ja/floater_script_debug.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <multi_floater name="script debug floater" title="スクリプトè¦å‘Šï¼ã‚¨ãƒ©ãƒ¼"> <tab_container name="Preview Tabs"> - <floater label="スクリプト" name="all_scripts" title="[All scripts]" /> + <floater label="スクリプト" name="all_scripts" title="[ALL SCRIPTS]" /> </tab_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/ja/floater_sound_preview.xml b/indra/newview/skins/default/xui/ja/floater_sound_preview.xml index b247914389..d5109fe539 100644 --- a/indra/newview/skins/default/xui/ja/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/ja/floater_sound_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Sound Preview" title="sound.wav"> +<floater name="Sound Preview" title="SOUND.WAV"> <text name="name_label"> åå‰ï¼š </text> diff --git a/indra/newview/skins/default/xui/ja/panel_edit_profile.xml b/indra/newview/skins/default/xui/ja/panel_edit_profile.xml index ca4ab3e773..2cf8456187 100644 --- a/indra/newview/skins/default/xui/ja/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/ja/panel_edit_profile.xml @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="edit_profile_panel">
- <string name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
- </string>
- <string name="AcctTypeResident"
- value="ä½äºº" />
- <string name="AcctTypeTrial"
- value="トライアル" />
- <string name="AcctTypeCharterMember"
- value="特権メンãƒãƒ¼" />
- <string name="AcctTypeEmployee"
- value="Linden Lab従æ¥å“¡" />
- <string name="PaymentInfoUsed"
- value="支払ã„æƒ…å ±ç™»éŒ²æ¸ˆ" />
- <string name="PaymentInfoOnFile"
- value="支払ã„æƒ…å ±ç™»éŒ²æ¸ˆã¿" />
- <string name="NoPaymentInfoOnFile"
- value="支払ã„æƒ…å ±æœªç™»éŒ²" />
- <string name="AgeVerified"
- value="年齢確èªæ¸ˆã¿" />
- <string name="NotAgeVerified"
- value="年齢未確èª" />
- <string name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=ja
- </string>
- <panel name="scroll_content_panel">
- <panel name="data_panel" >
- <panel name="lifes_images_panel">
- <panel name="second_life_image_panel">
- <text name="second_life_photo_title_text">
- [SECOND_LIFE]:
- </text>
- </panel>
- </panel>
- <text name="title_partner_text" value="パートナー:"/>
- <panel name="partner_data_panel">
- <text name="partner_text" value="[FIRST] [LAST]"/>
- </panel>
- <text name="text_box3">
- å–ã‚Šè¾¼ã¿ä¸å¿œç”メッセージ:
- </text>
- </panel>
- </panel>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="edit_profile_panel"> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string name="AcctTypeResident" + value="ä½äºº" /> + <string name="AcctTypeTrial" + value="トライアル" /> + <string name="AcctTypeCharterMember" + value="特権メンãƒãƒ¼" /> + <string name="AcctTypeEmployee" + value="Linden Lab従æ¥å“¡" /> + <string name="PaymentInfoUsed" + value="支払ã„æƒ…å ±ç™»éŒ²æ¸ˆ" /> + <string name="PaymentInfoOnFile" + value="支払ã„æƒ…å ±ç™»éŒ²æ¸ˆã¿" /> + <string name="NoPaymentInfoOnFile" + value="支払ã„æƒ…å ±æœªç™»éŒ²" /> + <string name="AgeVerified" + value="年齢確èªæ¸ˆã¿" /> + <string name="NotAgeVerified" + value="年齢未確èª" /> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=ja + </string> + <panel name="scroll_content_panel"> + <panel name="data_panel" > + <panel name="lifes_images_panel"> + <panel name="second_life_image_panel"> + <text name="second_life_photo_title_text"> + [SECOND_LIFE]: + </text> + </panel> + </panel> + <text name="title_partner_text" value="パートナー:"/> + <panel name="partner_data_panel"> + <text name="partner_text" value="[FIRST] [LAST]"/> + </panel> + <text name="text_box3"> + å–ã‚Šè¾¼ã¿ä¸å¿œç”メッセージ: + </text> + </panel> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/nl/floater_about.xml b/indra/newview/skins/default/xui/nl/floater_about.xml index 9ad947df66..0c57a22be1 100644 --- a/indra/newview/skins/default/xui/nl/floater_about.xml +++ b/indra/newview/skins/default/xui/nl/floater_about.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_about" title="Over [APP_NAME]"> +<floater name="floater_about" title="OVER [APP_NAME]"> <tab_container name="about_tab"> <panel name="credits_panel"> <text_editor name="credits_editor"> diff --git a/indra/newview/skins/default/xui/nl/floater_about_land.xml b/indra/newview/skins/default/xui/nl/floater_about_land.xml index 6aa80c00db..3a77de70d2 100644 --- a/indra/newview/skins/default/xui/nl/floater_about_land.xml +++ b/indra/newview/skins/default/xui/nl/floater_about_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterland" title="Over land"> +<floater name="floaterland" title="OVER LAND"> <tab_container name="landtab"> <panel label="Algemeen" name="land_general_panel"> <text name="Name:"> diff --git a/indra/newview/skins/default/xui/nl/floater_auction.xml b/indra/newview/skins/default/xui/nl/floater_auction.xml index eb061e028d..611024699b 100644 --- a/indra/newview/skins/default/xui/nl/floater_auction.xml +++ b/indra/newview/skins/default/xui/nl/floater_auction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_auction" title="Start Linden Land Verkoop"> +<floater name="floater_auction" title="START LINDEN LAND VERKOOP"> <check_box label="Voeg geel selectie kader toe" name="fence_check"/> <button label="Foto" label_selected="Foto" name="snapshot_btn"/> <button label="OK" label_selected="OK" name="ok_btn"/> diff --git a/indra/newview/skins/default/xui/nl/floater_beacons.xml b/indra/newview/skins/default/xui/nl/floater_beacons.xml index 84196ac14f..ecc485e354 100644 --- a/indra/newview/skins/default/xui/nl/floater_beacons.xml +++ b/indra/newview/skins/default/xui/nl/floater_beacons.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="beacons" title="Bakens"> +<floater name="beacons" title="BAKENS"> <panel name="beacons_panel"> <check_box label="Gescripte objecten met alleen Aanraken" name="touch_only"/> <check_box label="Gescripte objecten" name="scripted"/> diff --git a/indra/newview/skins/default/xui/nl/floater_bulk_perms.xml b/indra/newview/skins/default/xui/nl/floater_bulk_perms.xml index 7f35ec45a9..5374ffc26a 100644 --- a/indra/newview/skins/default/xui/nl/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/nl/floater_bulk_perms.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterbulkperms" title="Bulk wijzigen inhoud permissies"> +<floater name="floaterbulkperms" title="BULK WIJZIGEN INHOUD PERMISSIES"> <text name="applyto"> Inhoud Typen </text> diff --git a/indra/newview/skins/default/xui/nl/floater_bumps.xml b/indra/newview/skins/default/xui/nl/floater_bumps.xml index 9dbfe405aa..df9a99d62e 100644 --- a/indra/newview/skins/default/xui/nl/floater_bumps.xml +++ b/indra/newview/skins/default/xui/nl/floater_bumps.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_bumps" title="Botsingen, duwen & slaan"> +<floater name="floater_bumps" title="BOTSINGEN, DUWEN & SLAAN"> <string name="none_detected"> Geen gedetecteerd </string> diff --git a/indra/newview/skins/default/xui/nl/floater_buy_contents.xml b/indra/newview/skins/default/xui/nl/floater_buy_contents.xml index df0614b3d2..4c0ff7d04a 100644 --- a/indra/newview/skins/default/xui/nl/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/nl/floater_buy_contents.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_buy_contents" title="Koop inhoud"> +<floater name="floater_buy_contents" title="KOOP INHOUD"> <text name="contains_text"> [NAME] bevat: </text> diff --git a/indra/newview/skins/default/xui/nl/floater_buy_currency.xml b/indra/newview/skins/default/xui/nl/floater_buy_currency.xml index 9f740b86c8..b6fc743abe 100644 --- a/indra/newview/skins/default/xui/nl/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/nl/floater_buy_currency.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy currency" title="Koop valuta"> +<floater name="buy currency" title="KOOP VALUTA"> <text name="info_buying"> Valuta kopen </text> diff --git a/indra/newview/skins/default/xui/nl/floater_buy_land.xml b/indra/newview/skins/default/xui/nl/floater_buy_land.xml index 1bb02cc7d0..04990e78db 100644 --- a/indra/newview/skins/default/xui/nl/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/nl/floater_buy_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy land" title="Koop land"> +<floater name="buy land" title="KOOP LAND"> <text name="region_name_label"> Regio: </text> diff --git a/indra/newview/skins/default/xui/nl/floater_buy_object.xml b/indra/newview/skins/default/xui/nl/floater_buy_object.xml index c83f2008c6..5d2d9dd3d0 100644 --- a/indra/newview/skins/default/xui/nl/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/nl/floater_buy_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Koop een kopie van object"> +<floater name="contents" title="KOOP EEN KOPIE VAN OBJECT"> <text name="contents_text"> en zijn inhoud: </text> diff --git a/indra/newview/skins/default/xui/nl/floater_choose_group.xml b/indra/newview/skins/default/xui/nl/floater_choose_group.xml index 3f6ce44cfd..8d54d62d2d 100644 --- a/indra/newview/skins/default/xui/nl/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/nl/floater_choose_group.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="groups" title="Groepen"> +<floater name="groups" title="GROEPEN"> <text name="groupdesc"> Kies een groep: </text> diff --git a/indra/newview/skins/default/xui/nl/floater_color_picker.xml b/indra/newview/skins/default/xui/nl/floater_color_picker.xml index a357e874f7..9b61af0710 100644 --- a/indra/newview/skins/default/xui/nl/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/nl/floater_color_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="ColorPicker" title="Kleurkiezer"> +<floater name="ColorPicker" title="KLEURKIEZER"> <text name="r_val_text"> Rood: </text> diff --git a/indra/newview/skins/default/xui/nl/floater_customize.xml b/indra/newview/skins/default/xui/nl/floater_customize.xml index 99a109ab78..4de26347e1 100644 --- a/indra/newview/skins/default/xui/nl/floater_customize.xml +++ b/indra/newview/skins/default/xui/nl/floater_customize.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater customize" title="Uiterlijk" width="551"> +<floater name="floater customize" title="UITERLIJK" width="551"> <tab_container name="customize tab container" tab_min_width="120" width="549"> <placeholder label="Lichaamsdelen" name="body_parts_placeholder"/> <panel label="Postuur" name="Shape" left="124" width="389"> diff --git a/indra/newview/skins/default/xui/nl/floater_env_settings.xml b/indra/newview/skins/default/xui/nl/floater_env_settings.xml index d66c0b2205..3c207040d2 100644 --- a/indra/newview/skins/default/xui/nl/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/nl/floater_env_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Environment Editor Floater" title="Omgeving editor"> +<floater name="Environment Editor Floater" title="OMGEVING EDITOR"> <text bottom="-42" name="EnvTimeText"> Tijd van de dag diff --git a/indra/newview/skins/default/xui/nl/floater_font_test.xml b/indra/newview/skins/default/xui/nl/floater_font_test.xml index 8e8b07ee1a..31e53e7fba 100644 --- a/indra/newview/skins/default/xui/nl/floater_font_test.xml +++ b/indra/newview/skins/default/xui/nl/floater_font_test.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Lettertypetest"> +<floater name="contents" title="LETTERTYPETEST"> <text name="linea"> Overschrijf test, zou hier moeten verschijnen als Times (vanuit default/xui/en-us). </text> diff --git a/indra/newview/skins/default/xui/nl/floater_gesture.xml b/indra/newview/skins/default/xui/nl/floater_gesture.xml index d38972d5fe..4fa994c69e 100644 --- a/indra/newview/skins/default/xui/nl/floater_gesture.xml +++ b/indra/newview/skins/default/xui/nl/floater_gesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="gestures" title="Actieve gebaren"> +<floater name="gestures" title="ACTIEVE GEBAREN"> <text name="help_label"> Dubbelklik een gebaar om animaties en geluiden af te spelen </text> diff --git a/indra/newview/skins/default/xui/nl/floater_hud.xml b/indra/newview/skins/default/xui/nl/floater_hud.xml index 9da732ff2f..8ef7de1b02 100644 --- a/indra/newview/skins/default/xui/nl/floater_hud.xml +++ b/indra/newview/skins/default/xui/nl/floater_hud.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_hud" title="Handleiding"/> +<floater name="floater_hud" title="HANDLEIDING"/> diff --git a/indra/newview/skins/default/xui/nl/floater_inspect.xml b/indra/newview/skins/default/xui/nl/floater_inspect.xml index 96c9d59f90..6a0885b57f 100644 --- a/indra/newview/skins/default/xui/nl/floater_inspect.xml +++ b/indra/newview/skins/default/xui/nl/floater_inspect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="inspect" title="Objecten inspecteren"> +<floater name="inspect" title="OBJECTEN INSPECTEREN"> <scroll_list name="object_list" tool_tip="Selecteer een object van deze lijst om het in-wereld te markeren"> <column label="Objectnaam" name="object_name"/> <column label="Eigenaar" name="owner_name"/> diff --git a/indra/newview/skins/default/xui/nl/floater_inventory.xml b/indra/newview/skins/default/xui/nl/floater_inventory.xml index 272fa3c899..a69039d811 100644 --- a/indra/newview/skins/default/xui/nl/floater_inventory.xml +++ b/indra/newview/skins/default/xui/nl/floater_inventory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory" title="Inventaris"> +<floater name="Inventory" title="INVENTARIS"> <search_editor label="Typ hier om te zoeken" name="inventory search editor"/> <tab_container name="inventory filter tabs"> <inventory_panel label="Alle items" name="All Items"/> diff --git a/indra/newview/skins/default/xui/nl/floater_joystick.xml b/indra/newview/skins/default/xui/nl/floater_joystick.xml index ccc39034f5..505e3cd719 100644 --- a/indra/newview/skins/default/xui/nl/floater_joystick.xml +++ b/indra/newview/skins/default/xui/nl/floater_joystick.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Joystick" title="Joystick configuratie"> +<floater name="Joystick" title="JOYSTICK CONFIGURATIE"> <check_box name="enable_joystick" width="80" label="Joystick inschakelen:"/> <text left="146" name="joystick_type" width="360"/> <spinner label="X-as mapping" name="JoystickAxis1"/> diff --git a/indra/newview/skins/default/xui/nl/floater_lagmeter.xml b/indra/newview/skins/default/xui/nl/floater_lagmeter.xml index e8b1fb14bc..e3943c2470 100644 --- a/indra/newview/skins/default/xui/nl/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/nl/floater_lagmeter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="Lag meter"> +<floater name="floater_lagmeter" title="LAG METER"> <button label="" label_selected="" name="client_lagmeter" tool_tip="Client lag status"/> <text name="client"> Client: diff --git a/indra/newview/skins/default/xui/nl/floater_lsl_guide.xml b/indra/newview/skins/default/xui/nl/floater_lsl_guide.xml index 556d151c8c..27b3ff834e 100644 --- a/indra/newview/skins/default/xui/nl/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/nl/floater_lsl_guide.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="script ed float" title="LSL Wiki"> +<floater name="script ed float" title="LSL WIKI"> <check_box label="Volg cursor" name="lock_check"/> <combo_box label="Vergrendelen" name="history_combo"/> <button label="Terug" name="back_btn"/> diff --git a/indra/newview/skins/default/xui/nl/floater_mem_leaking.xml b/indra/newview/skins/default/xui/nl/floater_mem_leaking.xml index 1c7e070e4a..d0b25587b6 100644 --- a/indra/newview/skins/default/xui/nl/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/nl/floater_mem_leaking.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="MemLeak" title="Geheugenlek simulatie"> +<floater name="MemLeak" title="GEHEUGENLEK SIMULATIE"> <spinner label="Leksnelheid (bytes per frame):" name="leak_speed"/> <spinner label="Max gelekt geheugen (MB):" name="max_leak"/> <text name="total_leaked_label"> diff --git a/indra/newview/skins/default/xui/nl/floater_mute_object.xml b/indra/newview/skins/default/xui/nl/floater_mute_object.xml index ca3b34c3a2..7a34be1bd7 100644 --- a/indra/newview/skins/default/xui/nl/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/nl/floater_mute_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="mute by name" title="Negeer object op naam"> +<floater name="mute by name" title="NEGEER OBJECT OP NAAM"> <text name="message" bottom_delta="-40"> Negeer op naam heeft alleen invloed op object chat en IM, niet op geluiden. U dient de naam van het object diff --git a/indra/newview/skins/default/xui/nl/floater_my_friends.xml b/indra/newview/skins/default/xui/nl/floater_my_friends.xml index ed81e6baf9..8d709d3c00 100644 --- a/indra/newview/skins/default/xui/nl/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/nl/floater_my_friends.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_my_friends" title="Contacten"> +<floater name="floater_my_friends" title="CONTACTEN"> <tab_container name="friends_and_groups"> <panel label="Vrienden" name="friends_panel"/> <panel label="Groepen" name="groups_panel"/> diff --git a/indra/newview/skins/default/xui/nl/floater_openobject.xml b/indra/newview/skins/default/xui/nl/floater_openobject.xml index 10b502be1c..832c63403d 100644 --- a/indra/newview/skins/default/xui/nl/floater_openobject.xml +++ b/indra/newview/skins/default/xui/nl/floater_openobject.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="objectcontents" title="Object inhoud"> +<floater name="objectcontents" title="OBJECT INHOUD"> <text name="object_name"> [DESC]: </text> diff --git a/indra/newview/skins/default/xui/nl/floater_perm_prefs.xml b/indra/newview/skins/default/xui/nl/floater_perm_prefs.xml index c1c9492286..f946c42678 100644 --- a/indra/newview/skins/default/xui/nl/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/nl/floater_perm_prefs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="perm prefs" title="Standaard upload Permissies"> +<floater name="perm prefs" title="STANDAARD UPLOAD PERMISSIES"> <panel label="Permissies" name="permissions"> <button label="?" label_selected="?" name="help"/> <check_box label="Delen met groep" name="share_with_group"/> diff --git a/indra/newview/skins/default/xui/nl/floater_post_process.xml b/indra/newview/skins/default/xui/nl/floater_post_process.xml index 45fc211aeb..e627f81a70 100644 --- a/indra/newview/skins/default/xui/nl/floater_post_process.xml +++ b/indra/newview/skins/default/xui/nl/floater_post_process.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="Nabewerkinginstellingen"> +<floater name="Post-Process Floater" title="NABEWERKINGINSTELLINGEN"> <tab_container name="Post-Process Tabs"> <panel label="Kleurfilter" name="wmiColorFilterPanel"> <check_box label="Inschakelen" name="wmiColorFilterToggle"/> diff --git a/indra/newview/skins/default/xui/nl/floater_postcard.xml b/indra/newview/skins/default/xui/nl/floater_postcard.xml index a6d10f2244..c2d092fdd4 100644 --- a/indra/newview/skins/default/xui/nl/floater_postcard.xml +++ b/indra/newview/skins/default/xui/nl/floater_postcard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Postcard" title="Email foto"> +<floater name="Postcard" title="EMAIL FOTO"> <text name="to_label"> Ontvanger e-mail: </text> diff --git a/indra/newview/skins/default/xui/nl/floater_preferences.xml b/indra/newview/skins/default/xui/nl/floater_preferences.xml index 25984ee65a..6fc8005fd2 100644 --- a/indra/newview/skins/default/xui/nl/floater_preferences.xml +++ b/indra/newview/skins/default/xui/nl/floater_preferences.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Preferences" title="Voorkeuren"> +<floater name="Preferences" title="VOORKEUREN"> <button label="OK" label_selected="OK" name="OK"/> <button label="Annuleren" label_selected="Annuleren" name="Cancel"/> <button label="Toepassen" label_selected="Toepassen" name="Apply"/> diff --git a/indra/newview/skins/default/xui/nl/floater_region_info.xml b/indra/newview/skins/default/xui/nl/floater_region_info.xml index 3d4386bc16..0a98da3b4e 100644 --- a/indra/newview/skins/default/xui/nl/floater_region_info.xml +++ b/indra/newview/skins/default/xui/nl/floater_region_info.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="regioninfo" title="Regio/estate"/> +<floater name="regioninfo" title="REGIO/ESTATE"/> diff --git a/indra/newview/skins/default/xui/nl/floater_report_abuse.xml b/indra/newview/skins/default/xui/nl/floater_report_abuse.xml index 012198d7b6..19b11ede0a 100644 --- a/indra/newview/skins/default/xui/nl/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/nl/floater_report_abuse.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_report_abuse" title="Misbruik rapporteren"> +<floater name="floater_report_abuse" title="MISBRUIK RAPPORTEREN"> <check_box label="Voeg schermafbeelding toe" name="screen_check"/> <text name="reporter_title" width="110"> Rapporteur: diff --git a/indra/newview/skins/default/xui/nl/floater_script_debug.xml b/indra/newview/skins/default/xui/nl/floater_script_debug.xml index 306ad5d1a3..15e57f30d6 100644 --- a/indra/newview/skins/default/xui/nl/floater_script_debug.xml +++ b/indra/newview/skins/default/xui/nl/floater_script_debug.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <multi_floater name="script debug floater" title="Script waarschuwing/fout"> <tab_container name="Preview Tabs"> - <floater label="Script" name="all_scripts" title="[Alle scripts]"/> + <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]"/> </tab_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/nl/floater_script_queue.xml b/indra/newview/skins/default/xui/nl/floater_script_queue.xml index 38c227e53c..f79ad8faf3 100644 --- a/indra/newview/skins/default/xui/nl/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/nl/floater_script_queue.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="queue" title="Voortgang opnieuw instellen"> +<floater name="queue" title="VOORTGANG OPNIEUW INSTELLEN"> <button label="Sluiten" label_selected="Sluiten" name="close"/> </floater> diff --git a/indra/newview/skins/default/xui/nl/floater_sell_land.xml b/indra/newview/skins/default/xui/nl/floater_sell_land.xml index 3981f3ccc2..468a383cfc 100644 --- a/indra/newview/skins/default/xui/nl/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/nl/floater_sell_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="sell land" title="Verkoop land"> +<floater name="sell land" title="VERKOOP LAND"> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> <text name="info_parcel_label"> diff --git a/indra/newview/skins/default/xui/nl/floater_snapshot.xml b/indra/newview/skins/default/xui/nl/floater_snapshot.xml index c7174d42f3..251f3690da 100644 --- a/indra/newview/skins/default/xui/nl/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/nl/floater_snapshot.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Snapshot" title="Fotovoorbeeld"> +<floater name="Snapshot" title="FOTOVOORBEELD"> <text name="type_label"> Fotobestemming </text> diff --git a/indra/newview/skins/default/xui/nl/floater_statistics.xml b/indra/newview/skins/default/xui/nl/floater_statistics.xml index b899c32a56..7684a73663 100644 --- a/indra/newview/skins/default/xui/nl/floater_statistics.xml +++ b/indra/newview/skins/default/xui/nl/floater_statistics.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="stats floater" title="Statistieken"/> +<floater name="stats floater" title="STATISTIEKEN"/> diff --git a/indra/newview/skins/default/xui/nl/floater_telehub.xml b/indra/newview/skins/default/xui/nl/floater_telehub.xml index 8fe8e06c03..7b745d967c 100644 --- a/indra/newview/skins/default/xui/nl/floater_telehub.xml +++ b/indra/newview/skins/default/xui/nl/floater_telehub.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="telehub" title="Telehub" width="292"> +<floater name="telehub" title="TELEHUB" width="292"> <text name="status_text_connected"> Telehub verbonden met object [OBJECT] </text> diff --git a/indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml index 13a68747c6..c8caa8caf4 100644 --- a/indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="texture picker" title="Kies: Textuur"> +<floater name="texture picker" title="KIES: TEXTUUR"> <string name="choose_picture"> Klik om een afbeelding te kiezen </string> diff --git a/indra/newview/skins/default/xui/nl/floater_tools.xml b/indra/newview/skins/default/xui/nl/floater_tools.xml index cb0c1ad89a..f79d3dbd6b 100644 --- a/indra/newview/skins/default/xui/nl/floater_tools.xml +++ b/indra/newview/skins/default/xui/nl/floater_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="toolbox floater" title="" short_title="Bouwen" width="288"> +<floater name="toolbox floater" title="" short_title="BOUWEN" width="288"> <button label="" label_selected="" name="button focus" tool_tip="Focus"/> <button label="" label_selected="" name="button move" tool_tip="Verplaats"/> <button label="" label_selected="" name="button edit" tool_tip="Bewerk"/> diff --git a/indra/newview/skins/default/xui/nl/floater_top_objects.xml b/indra/newview/skins/default/xui/nl/floater_top_objects.xml index cc252352eb..2bbb701df8 100644 --- a/indra/newview/skins/default/xui/nl/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/nl/floater_top_objects.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="top_objects" title="laden…"> +<floater name="top_objects" title="LADEN…"> <text name="title_text"> Laden… </text> diff --git a/indra/newview/skins/default/xui/nl/floater_water.xml b/indra/newview/skins/default/xui/nl/floater_water.xml index 2238008fd8..1fb1ca241b 100644 --- a/indra/newview/skins/default/xui/nl/floater_water.xml +++ b/indra/newview/skins/default/xui/nl/floater_water.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Water Floater" title="Geavanceerde water editor"> +<floater name="Water Floater" title="GEAVANCEERDE WATER EDITOR"> <combo_box bottom="-50" height="18" left_delta="116" name="WaterPresetsCombo" width="150" /> <text name="KeyFramePresetsText"> Watervoorinstellingen diff --git a/indra/newview/skins/default/xui/nl/floater_world_map.xml b/indra/newview/skins/default/xui/nl/floater_world_map.xml index e1eebaf92f..bc14f92126 100644 --- a/indra/newview/skins/default/xui/nl/floater_world_map.xml +++ b/indra/newview/skins/default/xui/nl/floater_world_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="worldmap" title="Wereldkaart"> +<floater name="worldmap" title="WERELDKAART"> <tab_container name="maptab"> <panel label="Objecten" name="objects_mapview"/> <panel label="Terrein" name="terrain_mapview"/> diff --git a/indra/newview/skins/default/xui/nl/panel_edit_profile.xml b/indra/newview/skins/default/xui/nl/panel_edit_profile.xml index 00f8c087de..172395e20a 100644 --- a/indra/newview/skins/default/xui/nl/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/nl/panel_edit_profile.xml @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="edit_profile_panel">
- <string name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
- </string>
- <string name="AcctTypeResident"
- value="Inwoner" />
- <string name="AcctTypeTrial"
- value="Proef" />
- <string name="AcctTypeCharterMember"
- value="Charter lid" />
- <string name="AcctTypeEmployee"
- value="Linden Lab werknemer" />
- <string name="PaymentInfoUsed"
- value="Betalingsinformatie gebruikt" />
- <string name="PaymentInfoOnFile"
- value="Betalingsinformatie aanwezig" />
- <string name="NoPaymentInfoOnFile"
- value="Geen betalingsinfo aanwezig" />
- <string name="AgeVerified"
- value="Leeftijd geverifieerd" />
- <string name="NotAgeVerified"
- value="Leeftijd niet geverifieerd" />
- <string name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=nl
- </string>
- <panel name="scroll_content_panel">
- <panel name="data_panel" >
- <panel name="lifes_images_panel">
- <panel name="second_life_image_panel">
- <text name="second_life_photo_title_text">
- [SECOND_LIFE]:
- </text>
- </panel>
- </panel>
- <text name="title_partner_text" value="Partner:"/>
- <panel name="partner_data_panel">
- <text name="partner_text" value="[FIRST] [LAST]"/>
- </panel>
- <text name="text_box3">
- Antwoord bij Niet Storen:
- </text>
- </panel>
- </panel>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="edit_profile_panel"> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string name="AcctTypeResident" + value="Inwoner" /> + <string name="AcctTypeTrial" + value="Proef" /> + <string name="AcctTypeCharterMember" + value="Charter lid" /> + <string name="AcctTypeEmployee" + value="Linden Lab werknemer" /> + <string name="PaymentInfoUsed" + value="Betalingsinformatie gebruikt" /> + <string name="PaymentInfoOnFile" + value="Betalingsinformatie aanwezig" /> + <string name="NoPaymentInfoOnFile" + value="Geen betalingsinfo aanwezig" /> + <string name="AgeVerified" + value="Leeftijd geverifieerd" /> + <string name="NotAgeVerified" + value="Leeftijd niet geverifieerd" /> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=nl + </string> + <panel name="scroll_content_panel"> + <panel name="data_panel" > + <panel name="lifes_images_panel"> + <panel name="second_life_image_panel"> + <text name="second_life_photo_title_text"> + [SECOND_LIFE]: + </text> + </panel> + </panel> + <text name="title_partner_text" value="Partner:"/> + <panel name="partner_data_panel"> + <text name="partner_text" value="[FIRST] [LAST]"/> + </panel> + <text name="text_box3"> + Antwoord bij Niet Storen: + </text> + </panel> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/pl/floater_about_land.xml b/indra/newview/skins/default/xui/pl/floater_about_land.xml index 83d4b717a7..d456ea26b4 100755 --- a/indra/newview/skins/default/xui/pl/floater_about_land.xml +++ b/indra/newview/skins/default/xui/pl/floater_about_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterland" title="O PosiadÅ‚oÅ›ci"> +<floater name="floaterland" title="O POSIADÅOÅšCI"> <tab_container name="landtab"> <panel label="Ogólne" name="land_general_panel"> <text name="Name:"> diff --git a/indra/newview/skins/default/xui/pl/floater_auction.xml b/indra/newview/skins/default/xui/pl/floater_auction.xml index 65a1bb85ea..37e35ed1e9 100755 --- a/indra/newview/skins/default/xui/pl/floater_auction.xml +++ b/indra/newview/skins/default/xui/pl/floater_auction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_auction" title="Rozpocznij Sprzedaż PosiadÅ‚oÅ›ci"> +<floater name="floater_auction" title="ROZPOCZNIJ SPRZEDAÅ» POSIADÅOÅšCI"> <check_box label="ZawierajÄ…c żółte ogrodzenie" name="fence_check" /> <button label="ZdjÄ™ce" label_selected="ZdjÄ™ce" name="snapshot_btn" /> <button label="OK" label_selected="OK" name="ok_btn" /> diff --git a/indra/newview/skins/default/xui/pl/floater_avatar_picker.xml b/indra/newview/skins/default/xui/pl/floater_avatar_picker.xml index cf4dcb91bf..8c09f7294c 100755 --- a/indra/newview/skins/default/xui/pl/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/pl/floater_avatar_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatarpicker" title="Wybierz Rezydenta"> +<floater name="avatarpicker" title="WYBIERZ REZYDENTA"> <tab_container name="ResidentChooserTabs"> <panel label="Znajdź" name="SearchPanel"> <text name="InstructSearchResidentName"> diff --git a/indra/newview/skins/default/xui/pl/floater_avatar_textures.xml b/indra/newview/skins/default/xui/pl/floater_avatar_textures.xml index b27c90b8f2..dce2330807 100755 --- a/indra/newview/skins/default/xui/pl/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/pl/floater_avatar_textures.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="avatar_texture_debug" title="Tekstury Awatara"> +<floater name="avatar_texture_debug" title="TEKSTURY AWATARA"> <text name="baked_label"> Tekstury Renderowane </text> diff --git a/indra/newview/skins/default/xui/pl/floater_beacons.xml b/indra/newview/skins/default/xui/pl/floater_beacons.xml index fd12d13595..6e7013f2d7 100644 --- a/indra/newview/skins/default/xui/pl/floater_beacons.xml +++ b/indra/newview/skins/default/xui/pl/floater_beacons.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="beacons" title="Emitery"> +<floater name="beacons" title="EMITERY"> <panel name="beacons_panel"> <check_box label="Obiekty Dotykalne" name="touch_only"/> <check_box label="Obiekty Skryptowane" name="scripted"/> diff --git a/indra/newview/skins/default/xui/pl/floater_build_options.xml b/indra/newview/skins/default/xui/pl/floater_build_options.xml index 7cbc410614..f538be218c 100755 --- a/indra/newview/skins/default/xui/pl/floater_build_options.xml +++ b/indra/newview/skins/default/xui/pl/floater_build_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="build options floater" title="Opcje Siatki"> +<floater name="build options floater" title="OPCJE SIATKI"> <spinner label="Jednostka Siatki (metry)" name="GridResolution" /> <spinner label="Rozmiary Siatki (metry)" name="GridDrawSize" /> <check_box label="UdostÄ™pnij Podjednostkowe Dopasowywanie" name="GridSubUnit" /> diff --git a/indra/newview/skins/default/xui/pl/floater_bulk_perms.xml b/indra/newview/skins/default/xui/pl/floater_bulk_perms.xml index a99acdb238..f06615642e 100644 --- a/indra/newview/skins/default/xui/pl/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/pl/floater_bulk_perms.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterbulkperms" title="Hurtowa zmiana praw zawartoÅ›ci"> +<floater name="floaterbulkperms" title="HURTOWA ZMIANA PRAW ZAWARTOÅšCI"> <text name="applyto"> Rodzaj ZawartoÅ›ci </text> diff --git a/indra/newview/skins/default/xui/pl/floater_bumps.xml b/indra/newview/skins/default/xui/pl/floater_bumps.xml index 365268dbd6..10f9d73284 100755 --- a/indra/newview/skins/default/xui/pl/floater_bumps.xml +++ b/indra/newview/skins/default/xui/pl/floater_bumps.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_bumps" title="Zderzenia, PopchniÄ™cia, Uderzenia"> +<floater name="floater_bumps" title="ZDERZENIA, POPCHNIĘCIA, UDERZENIA"> <string name="none_detected"> Brak </string> diff --git a/indra/newview/skins/default/xui/pl/floater_buy_contents.xml b/indra/newview/skins/default/xui/pl/floater_buy_contents.xml index 395bcb4ea9..ebe1c9dfd8 100755 --- a/indra/newview/skins/default/xui/pl/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/pl/floater_buy_contents.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_buy_contents" title="Kup Zawartość"> +<floater name="floater_buy_contents" title="KUP ZAWARTOŚĆ"> <text name="contains_text"> [NAME] zawiera: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml index a5c0a2498a..b0b8935433 100755 --- a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="buy currency" title="Kup $L"> +<floater name="buy currency" title="KUP $L"> <text name="info_buying"> Kup L$: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_buy_land.xml b/indra/newview/skins/default/xui/pl/floater_buy_land.xml index ff371b38c0..648888828b 100755 --- a/indra/newview/skins/default/xui/pl/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/pl/floater_buy_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy land" title="Buy Land"> +<floater name="buy land" title="BUY LAND"> <text name="region_name_label"> Region: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_buy_object.xml b/indra/newview/skins/default/xui/pl/floater_buy_object.xml index b0868a46a2..bad7982228 100755 --- a/indra/newview/skins/default/xui/pl/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/pl/floater_buy_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="contents" title="Kup kopiÄ™ obiektu"> +<floater name="contents" title="KUP KOPIĘ OBIEKTU"> <text name="contents_text"> i jej zawartość: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_choose_group.xml b/indra/newview/skins/default/xui/pl/floater_choose_group.xml index 789c40e48c..72b6617094 100755 --- a/indra/newview/skins/default/xui/pl/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/pl/floater_choose_group.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="groups" title="Grupy"> +<floater name="groups" title="GRUPY"> <text name="groupdesc"> Wybierz grupÄ™: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_color_picker.xml b/indra/newview/skins/default/xui/pl/floater_color_picker.xml index d6ffe1837a..904a2cc270 100755 --- a/indra/newview/skins/default/xui/pl/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/pl/floater_color_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="ColorPicker" title="Wybór Koloru"> +<floater name="ColorPicker" title="WYBÓR KOLORU"> <text name="r_val_text"> Czerwony: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_customize.xml b/indra/newview/skins/default/xui/pl/floater_customize.xml index 64d9300621..0c01d15faf 100755 --- a/indra/newview/skins/default/xui/pl/floater_customize.xml +++ b/indra/newview/skins/default/xui/pl/floater_customize.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater customize" title="WyglÄ…d"> +<floater name="floater customize" title="WYGLÄ„D"> <tab_container name="customize tab container"> <placeholder label="Części CiaÅ‚a" name="body_parts_placeholder"/> <panel label="KsztaÅ‚t" name="Shape"> diff --git a/indra/newview/skins/default/xui/pl/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/pl/floater_day_cycle_options.xml index ea8db99570..6671bb853e 100755 --- a/indra/newview/skins/default/xui/pl/floater_day_cycle_options.xml +++ b/indra/newview/skins/default/xui/pl/floater_day_cycle_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Day Cycle Floater" title="Edytor Cyklu Dnia"> +<floater name="Day Cycle Floater" title="EDYTOR CYKLU DNIA"> <tab_container name="Day Cycle Tabs"> <panel label="Cykl Dnia" name="Day Cycle"> <button label="?" name="WLDayCycleHelp" /> diff --git a/indra/newview/skins/default/xui/pl/floater_device_settings.xml b/indra/newview/skins/default/xui/pl/floater_device_settings.xml index 0122aa819e..e79478731d 100755 --- a/indra/newview/skins/default/xui/pl/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/pl/floater_device_settings.xml @@ -1,3 +1,3 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater name="floater_device_settings" - title="Ustawienia UrzÄ…dzeÅ„ Komunikacji GÅ‚osowej" /> + title="USTAWIENIA URZÄ„DZEŃ KOMUNIKACJI GÅOSOWEJ" /> diff --git a/indra/newview/skins/default/xui/pl/floater_env_settings.xml b/indra/newview/skins/default/xui/pl/floater_env_settings.xml index 3e0809b193..e197d94b27 100755 --- a/indra/newview/skins/default/xui/pl/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/pl/floater_env_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Environment Editor Floater" title="Edytor Åšrodowiska"> +<floater name="Environment Editor Floater" title="EDYTOR ÅšRODOWISKA"> <text name="EnvTimeText"> Czas </text> diff --git a/indra/newview/skins/default/xui/pl/floater_font_test.xml b/indra/newview/skins/default/xui/pl/floater_font_test.xml index 586d2690b3..019cee3e1e 100644 --- a/indra/newview/skins/default/xui/pl/floater_font_test.xml +++ b/indra/newview/skins/default/xui/pl/floater_font_test.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Czcionka Tekstu"> +<floater name="contents" title="CZCIONKA TEKSTU"> <text name="linea"> OverrideTest, powinno wyÅ›wietlać siÄ™ jako Times. (From default/xui/en-us) </text> diff --git a/indra/newview/skins/default/xui/pl/floater_gesture.xml b/indra/newview/skins/default/xui/pl/floater_gesture.xml index a05408dfc5..4685eb6afe 100755 --- a/indra/newview/skins/default/xui/pl/floater_gesture.xml +++ b/indra/newview/skins/default/xui/pl/floater_gesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="gestures" title="Aktywne Gesty"> +<floater name="gestures" title="AKTYWNE GESTY"> <text name="help_label"> Kliknij podwójnie by aktywować gÅ‚os i animacjÄ™ gestu. </text> diff --git a/indra/newview/skins/default/xui/pl/floater_god_tools.xml b/indra/newview/skins/default/xui/pl/floater_god_tools.xml index df821f3b6d..a3ccffac03 100755 --- a/indra/newview/skins/default/xui/pl/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/pl/floater_god_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="godtools floater" title="Boskie NarzÄ™dzia"> +<floater name="godtools floater" title="BOSKIE NARZĘDZIA"> <tab_container name="GodTools Tabs"> <panel label="Grid" name="grid"> <button width="205" label="UsuÅ„ wszystkich użytkowników" label_selected="UsuÅ„ wszystkich użytkowników" name="Kick all users"/> diff --git a/indra/newview/skins/default/xui/pl/floater_hardware_settings.xml b/indra/newview/skins/default/xui/pl/floater_hardware_settings.xml index f1e6e5ea9e..39695a67b6 100755 --- a/indra/newview/skins/default/xui/pl/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/pl/floater_hardware_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Hardware Settings Floater" title="Ustawienia SprzÄ™towe"> +<floater name="Hardware Settings Floater" title="USTAWIENIA SPRZĘTOWE"> <text name="Filtering:"> Filtrowanie: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_hud.xml b/indra/newview/skins/default/xui/pl/floater_hud.xml index 916473f063..ff2d702132 100755 --- a/indra/newview/skins/default/xui/pl/floater_hud.xml +++ b/indra/newview/skins/default/xui/pl/floater_hud.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_hud" title="Samouczek" /> +<floater name="floater_hud" title="SAMOUCZEK" /> diff --git a/indra/newview/skins/default/xui/pl/floater_inspect.xml b/indra/newview/skins/default/xui/pl/floater_inspect.xml index 1efdced527..c98e0541d8 100755 --- a/indra/newview/skins/default/xui/pl/floater_inspect.xml +++ b/indra/newview/skins/default/xui/pl/floater_inspect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="inspect" title="Inspekcja Obiektów"> +<floater name="inspect" title="INSPEKCJA OBIEKTÓW"> <scroll_list name="object_list" tool_tip=""> <column label="Nazwa" name="object_name" /> <column label="WÅ‚aÅ›ciciel" name="owner_name" /> diff --git a/indra/newview/skins/default/xui/pl/floater_inventory.xml b/indra/newview/skins/default/xui/pl/floater_inventory.xml index 6df978de69..157be76c4d 100755 --- a/indra/newview/skins/default/xui/pl/floater_inventory.xml +++ b/indra/newview/skins/default/xui/pl/floater_inventory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory" title="Moja Szafa"> +<floater name="Inventory" title="MOJA SZAFA"> <search_editor label="Wyszukiwarka" name="inventory search editor"/> <tab_container name="inventory filter tabs"> <inventory_panel label="Wszystkie Obiekty" name="All Items"/> diff --git a/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml index c32d1eeabf..665172dd49 100755 --- a/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="item properties" title="WÅ‚aÅ›ciwoÅ›ci Obiektów w Szafie"> +<floater name="item properties" title="WÅAÅšCIWOÅšCI OBIEKTÓW W SZAFIE"> <text name="LabelItemNameTitle"> Nazwa: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml index 2224c026ef..9204262304 100755 --- a/indra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Inventory Finder" title="Nowe Obiekty"> +<floater name="Inventory Finder" title="NOWE OBIEKTY"> <check_box label="Animacje" name="check_animation" /> <check_box label="Wizytówki" name="check_calling_card" /> <check_box label="Ubrania" name="check_clothing" /> diff --git a/indra/newview/skins/default/xui/pl/floater_joystick.xml b/indra/newview/skins/default/xui/pl/floater_joystick.xml index 2ab92dfbb7..22ac458b85 100755 --- a/indra/newview/skins/default/xui/pl/floater_joystick.xml +++ b/indra/newview/skins/default/xui/pl/floater_joystick.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Joystick" width="590" title="Konfiguracja Joysticka"> +<floater name="Joystick" width="590" title="KONFIGURACJA JOYSTICKA"> <check_box name="enable_joystick" label="Aktywuj Joystick:"/> <text left="130" name="joystick_type" width="360"/> <spinner label="Kalibracja Osi X" left="20" width="170" label_width="130" name="JoystickAxis1"/> @@ -116,4 +116,4 @@ <string name="NoDevice"> brak podÅ‚Ä…cznego urzÄ…dzenia </string> -</floater>
\ No newline at end of file +</floater> diff --git a/indra/newview/skins/default/xui/pl/floater_lagmeter.xml b/indra/newview/skins/default/xui/pl/floater_lagmeter.xml index 949289594e..69d563bdba 100755 --- a/indra/newview/skins/default/xui/pl/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/pl/floater_lagmeter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_lagmeter" title="Pomiar Lagów"> +<floater name="floater_lagmeter" title="POMIAR LAGÓW"> <button label="" label_selected="" name="client_lagmeter" tool_tip="Status lagów klienta" /> <text name="client"> diff --git a/indra/newview/skins/default/xui/pl/floater_land_holdings.xml b/indra/newview/skins/default/xui/pl/floater_land_holdings.xml index 29268f0e97..13e6a8b16d 100755 --- a/indra/newview/skins/default/xui/pl/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/pl/floater_land_holdings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="land holdings floater" title="Moja posiadÅ‚ość"> +<floater name="land holdings floater" title="MOJA POSIADÅOŚĆ"> <scroll_list name="parcel list"> <column label="Nazwa posiadÅ‚oÅ›ci" name="name"/> <column label="Region" name="location"/> diff --git a/indra/newview/skins/default/xui/pl/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/pl/floater_live_lsleditor.xml index 94efd7afcb..8120ff8c77 100755 --- a/indra/newview/skins/default/xui/pl/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/pl/floater_live_lsleditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="Skrypt: Nowy Skrypt"> +<floater name="script ed float" title="SKRYPT: NOWY SKRYPT"> <button label="Zresetuj" label_selected="Zresetuj" name="Reset" /> <check_box label="WÅ‚Ä…cz" name="running" /> <check_box label="Mono" name="mono" /> diff --git a/indra/newview/skins/default/xui/pl/floater_lsl_guide.xml b/indra/newview/skins/default/xui/pl/floater_lsl_guide.xml index a0fa00dffe..5601aa4464 100755 --- a/indra/newview/skins/default/xui/pl/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/pl/floater_lsl_guide.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="LSL Wiki"> +<floater name="script ed float" title="LSL WIKI"> <check_box label="Idź za kursorem" name="lock_check" /> <combo_box label="Zablokuj" name="history_combo" /> <button label="Wróć" name="back_btn" /> diff --git a/indra/newview/skins/default/xui/pl/floater_media_browser.xml b/indra/newview/skins/default/xui/pl/floater_media_browser.xml index 2fb4287d90..74210c75e5 100755 --- a/indra/newview/skins/default/xui/pl/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/pl/floater_media_browser.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_about" title="PrzeglÄ…darka Mediów"> +<floater name="floater_about" title="PRZEGLÄ„DARKA MEDIÓW"> <layout_stack name="stack1"> <layout_panel name="nav_controls"> <button label="Wróć" name="back" /> diff --git a/indra/newview/skins/default/xui/pl/floater_mem_leaking.xml b/indra/newview/skins/default/xui/pl/floater_mem_leaking.xml index fe977e96c5..88a878af72 100755 --- a/indra/newview/skins/default/xui/pl/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/pl/floater_mem_leaking.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="MemLeak" title="Symulacja Przecieków Alokacji PamiÄ™ci"> +<floater name="MemLeak" title="SYMULACJA PRZECIEKÓW ALOKACJI PAMIĘCI"> <spinner label="PrÄ™dkość Przecieków (byty na klatkÄ™):" name="leak_speed" /> <spinner label="Max Przecieki (MB):" name="max_leak" /> <text name="total_leaked_label"> diff --git a/indra/newview/skins/default/xui/pl/floater_mute_object.xml b/indra/newview/skins/default/xui/pl/floater_mute_object.xml index 310810db76..dd30f749e3 100755 --- a/indra/newview/skins/default/xui/pl/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/pl/floater_mute_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="mute by name" title="Wycisz Obiekt WedÅ‚ug Nazwy" height="160" min_height="160" > +<floater name="mute by name" title="WYCISZ OBIEKT WEDÅUG NAZWY" height="160" min_height="160" > <text name="message"> Wyciszenie obiektu jest skuteczne jedynie na czacie oraz w wiadomoÅ›ciach IM. Nie obejmuje natomiast dźwiÄ™ków. diff --git a/indra/newview/skins/default/xui/pl/floater_my_friends.xml b/indra/newview/skins/default/xui/pl/floater_my_friends.xml index cc5f1f2a01..0bcf6ba4d5 100755 --- a/indra/newview/skins/default/xui/pl/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/pl/floater_my_friends.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_my_friends" title="Kontakty"> +<floater name="floater_my_friends" title="KONTAKTY"> <tab_container name="friends_and_groups"> <panel label="Znajomi" name="friends_panel" /> <panel label="Grupy" name="groups_panel" /> diff --git a/indra/newview/skins/default/xui/pl/floater_openobject.xml b/indra/newview/skins/default/xui/pl/floater_openobject.xml index 0470f4d6dc..fbbed0f11d 100755 --- a/indra/newview/skins/default/xui/pl/floater_openobject.xml +++ b/indra/newview/skins/default/xui/pl/floater_openobject.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="objectcontents" title="Zawartość Obiektu"> +<floater name="objectcontents" title="ZAWARTOŚĆ OBIEKTU"> <text name="object_name"> [DESC]: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_perm_prefs.xml b/indra/newview/skins/default/xui/pl/floater_perm_prefs.xml index dd7cbe1f79..834552e2b0 100644 --- a/indra/newview/skins/default/xui/pl/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/pl/floater_perm_prefs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="perm prefs" title="Prawa DomyÅ›lne"> +<floater name="perm prefs" title="PRAWA DOMYÅšLNE"> <panel label="Prawa" name="permissions"> <button label="?" label_selected="?" name="help"/> <check_box label="UdostÄ™pnij grupie" name="share_with_group"/> diff --git a/indra/newview/skins/default/xui/pl/floater_post_process.xml b/indra/newview/skins/default/xui/pl/floater_post_process.xml index 0081d1d3a7..6bd91f97b1 100755 --- a/indra/newview/skins/default/xui/pl/floater_post_process.xml +++ b/indra/newview/skins/default/xui/pl/floater_post_process.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Post-Process Floater" title="Ustawienia Przetwarzania KoÅ„cowego"> +<floater name="Post-Process Floater" title="USTAWIENIA PRZETWARZANIA KOŃCOWEGO"> <tab_container name="Post-Process Tabs"> <panel label="Kolor Filtru" name="wmiColorFilterPanel"> <check_box label="UdostÄ™pnij" name="wmiColorFilterToggle" /> diff --git a/indra/newview/skins/default/xui/pl/floater_postcard.xml b/indra/newview/skins/default/xui/pl/floater_postcard.xml index e5bdaf2ba9..8f4018924d 100755 --- a/indra/newview/skins/default/xui/pl/floater_postcard.xml +++ b/indra/newview/skins/default/xui/pl/floater_postcard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Postcard" title="WyÅ›lij PocztówkÄ™"> +<floater name="Postcard" title="WYÅšLIJ POCZTÓWKĘ"> <text name="to_label"> Email Odbiorcy: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_preferences.xml b/indra/newview/skins/default/xui/pl/floater_preferences.xml index 380738425e..2be663283f 100755 --- a/indra/newview/skins/default/xui/pl/floater_preferences.xml +++ b/indra/newview/skins/default/xui/pl/floater_preferences.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Preferences" title="Ustawienia"> +<floater name="Preferences" title="USTAWIENIA"> <button label="OK" label_selected="OK" name="OK" /> <button label="Anuluj" label_selected="Anuluj" name="Cancel" /> <button label="Zastosuj" label_selected="Zastosuj" name="Apply" /> diff --git a/indra/newview/skins/default/xui/pl/floater_preview_classified.xml b/indra/newview/skins/default/xui/pl/floater_preview_classified.xml index cc7d276117..eae9ba2690 100755 --- a/indra/newview/skins/default/xui/pl/floater_preview_classified.xml +++ b/indra/newview/skins/default/xui/pl/floater_preview_classified.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="classified_preview" title="Reklama" /> +<floater name="classified_preview" title="REKLAMA" /> diff --git a/indra/newview/skins/default/xui/pl/floater_preview_event.xml b/indra/newview/skins/default/xui/pl/floater_preview_event.xml index 75e17f6fa2..9fc0ff4da6 100755 --- a/indra/newview/skins/default/xui/pl/floater_preview_event.xml +++ b/indra/newview/skins/default/xui/pl/floater_preview_event.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="event_preview" title="Informacje o Imprezie" /> +<floater name="event_preview" title="INFORMACJE O IMPREZIE" /> diff --git a/indra/newview/skins/default/xui/pl/floater_preview_notecard.xml b/indra/newview/skins/default/xui/pl/floater_preview_notecard.xml index 0b3b9063c4..b9f80490ab 100755 --- a/indra/newview/skins/default/xui/pl/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/pl/floater_preview_notecard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="preview notecard" title="Nota:"> +<floater name="preview notecard" title="NOTA:"> <button label="Zapisz" label_selected="Zapisz" name="Save" /> <text name="desc txt"> Opis: diff --git a/indra/newview/skins/default/xui/pl/floater_region_info.xml b/indra/newview/skins/default/xui/pl/floater_region_info.xml index 6e632fd9c3..ca3c1391db 100755 --- a/indra/newview/skins/default/xui/pl/floater_region_info.xml +++ b/indra/newview/skins/default/xui/pl/floater_region_info.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="regioninfo" title="Region/MajÄ…tek" /> +<floater name="regioninfo" title="REGION/MAJÄ„TEK" /> diff --git a/indra/newview/skins/default/xui/pl/floater_report_abuse.xml b/indra/newview/skins/default/xui/pl/floater_report_abuse.xml index 853c669ade..c1efcffb1e 100755 --- a/indra/newview/skins/default/xui/pl/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/pl/floater_report_abuse.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_report_abuse" title="Raport o Nadużyciu"> +<floater name="floater_report_abuse" title="RAPORT O NADUÅ»YCIU"> <texture_picker label="" name="screenshot"/> <check_box label="ZaÅ‚Ä…cz zdjÄ™cie ekranu" name="screen_check"/> <text name="reporter_title"> diff --git a/indra/newview/skins/default/xui/pl/floater_script_debug.xml b/indra/newview/skins/default/xui/pl/floater_script_debug.xml index b41add8246..714a600262 100755 --- a/indra/newview/skins/default/xui/pl/floater_script_debug.xml +++ b/indra/newview/skins/default/xui/pl/floater_script_debug.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <multi_floater name="script debug floater" title="Ostrzeżenie/BÅ‚Ä…d Skryptu"> <tab_container name="Preview Tabs"> - <floater label="Skrypt" name="all_scripts" title="[All scripts]" /> + <floater label="Skrypt" name="all_scripts" title="[ALL SCRIPTS]" /> </tab_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/pl/floater_script_preview.xml b/indra/newview/skins/default/xui/pl/floater_script_preview.xml index ca3fde33e7..e3e72e15a3 100755 --- a/indra/newview/skins/default/xui/pl/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/pl/floater_script_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="preview lsl text" title="Skrypt: Skrypt Obrotu"> +<floater name="preview lsl text" title="SKRYPT: SKRYPT OBROTU"> <text name="desc txt"> Opis: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_script_queue.xml b/indra/newview/skins/default/xui/pl/floater_script_queue.xml index 70d4669a07..7655f5fcac 100755 --- a/indra/newview/skins/default/xui/pl/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/pl/floater_script_queue.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="queue" title="Zresetuj PracÄ™ w Toku"> +<floater name="queue" title="ZRESETUJ PRACĘ W TOKU"> <button label="Zamknij" label_selected="Zamknij" name="close" /> </floater> diff --git a/indra/newview/skins/default/xui/pl/floater_script_search.xml b/indra/newview/skins/default/xui/pl/floater_script_search.xml index 50a9de1500..255ab4264c 100755 --- a/indra/newview/skins/default/xui/pl/floater_script_search.xml +++ b/indra/newview/skins/default/xui/pl/floater_script_search.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script search" title="Szukaj Skryptu"> +<floater name="script search" title="SZUKAJ SKRYPTU"> <check_box label="CapsLoock Nieaktywny" name="case_text" /> <button label="Szukaj" label_selected="Szukaj" name="search_btn" /> <button label="ZamieÅ„" label_selected="ZamieÅ„" name="replace_btn" /> diff --git a/indra/newview/skins/default/xui/pl/floater_sell_land.xml b/indra/newview/skins/default/xui/pl/floater_sell_land.xml index 579dcd6745..a306ec2c34 100755 --- a/indra/newview/skins/default/xui/pl/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/pl/floater_sell_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="sell land" title="Sell Land"> +<floater name="sell land" title="SELL LAND"> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> <text name="info_parcel_label"> diff --git a/indra/newview/skins/default/xui/pl/floater_settings_debug.xml b/indra/newview/skins/default/xui/pl/floater_settings_debug.xml index 99fa444a1b..f87e2edecc 100755 --- a/indra/newview/skins/default/xui/pl/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/pl/floater_settings_debug.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="settings_debug" title="Ustawienia Usuwania BÅ‚Ä™dów"> +<floater name="settings_debug" title="USTAWIENIA USUWANIA BÅĘDÓW"> <combo_box name="boolean_combo"> <combo_box.item name="TRUE" label="PRAWDA" /> <combo_box.item name="FALSE" label="NIEPRAWDA" /> diff --git a/indra/newview/skins/default/xui/pl/floater_snapshot.xml b/indra/newview/skins/default/xui/pl/floater_snapshot.xml index 4945cf6413..c807087170 100755 --- a/indra/newview/skins/default/xui/pl/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/pl/floater_snapshot.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Snapshot" title="WyglÄ…d ZdjÄ™cia"> +<floater name="Snapshot" title="WYGLÄ„D ZDJĘCIA"> <text name="type_label"> Lokacja zapisu </text> diff --git a/indra/newview/skins/default/xui/pl/floater_sound_preview.xml b/indra/newview/skins/default/xui/pl/floater_sound_preview.xml index 2461aebbcf..0826508fd6 100755 --- a/indra/newview/skins/default/xui/pl/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/pl/floater_sound_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Sound Preview" title="dźwiÄ™k.wav"> +<floater name="Sound Preview" title="DŹWIĘK.WAV"> <text name="name_label"> Opis: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_statistics.xml b/indra/newview/skins/default/xui/pl/floater_statistics.xml index 933801bbda..b7025e484d 100644 --- a/indra/newview/skins/default/xui/pl/floater_statistics.xml +++ b/indra/newview/skins/default/xui/pl/floater_statistics.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="stats floater" title="Statystyki"/> +<floater name="stats floater" title="STATYSTYKI"/> diff --git a/indra/newview/skins/default/xui/pl/floater_telehub.xml b/indra/newview/skins/default/xui/pl/floater_telehub.xml index 917ab95ecc..9f564452a9 100755 --- a/indra/newview/skins/default/xui/pl/floater_telehub.xml +++ b/indra/newview/skins/default/xui/pl/floater_telehub.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="telehub" title="ObsÅ‚uga Teleportera" min_height="300" height="300" > +<floater name="telehub" title="OBSÅUGA TELEPORTERA" min_height="300" height="300" > <text name="status_text_connected" width="250"> Teleporter poÅ‚Ä…czony z obiektem [OBJECT] </text> diff --git a/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml index 6d4df12e4b..48366e2b64 100755 --- a/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="texture picker" title="Wybór Tekstury"> +<floater name="texture picker" title="WYBÓR TEKSTURY"> <string name="choose_picture"> Kliknij by wybrać obraz </string> diff --git a/indra/newview/skins/default/xui/pl/floater_tools.xml b/indra/newview/skins/default/xui/pl/floater_tools.xml index c9e7a7e9eb..e898c283c5 100755 --- a/indra/newview/skins/default/xui/pl/floater_tools.xml +++ b/indra/newview/skins/default/xui/pl/floater_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="toolbox floater" title="" short_title="Buduj"> +<floater name="toolbox floater" title="" short_title="BUDUJ"> <button label="" label_selected="" name="button focus" tool_tip="Zbliżenie"/> <button label="" label_selected="" name="button move" tool_tip="PrzesuniÄ™cie"/> <button label="" label_selected="" name="button edit" tool_tip="Edycja"/> diff --git a/indra/newview/skins/default/xui/pl/floater_top_objects.xml b/indra/newview/skins/default/xui/pl/floater_top_objects.xml index 44d838035d..e7299b0abb 100755 --- a/indra/newview/skins/default/xui/pl/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/pl/floater_top_objects.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="top_objects" title="Åadowanie..."> +<floater name="top_objects" title="ÅADOWANIE..."> <text name="title_text"> Åadowanie... </text> diff --git a/indra/newview/skins/default/xui/pl/floater_water.xml b/indra/newview/skins/default/xui/pl/floater_water.xml index a22b5809dc..7333633c1d 100755 --- a/indra/newview/skins/default/xui/pl/floater_water.xml +++ b/indra/newview/skins/default/xui/pl/floater_water.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Water Floater" title="Zaawansowany Edytor Wody"> +<floater name="Water Floater" title="ZAAWANSOWANY EDYTOR WODY"> <text name="KeyFramePresetsText"> Ustawienia Wody: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_windlight_options.xml b/indra/newview/skins/default/xui/pl/floater_windlight_options.xml index 94c20c06f7..86ef9300da 100755 --- a/indra/newview/skins/default/xui/pl/floater_windlight_options.xml +++ b/indra/newview/skins/default/xui/pl/floater_windlight_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="WindLight floater" title="Zaawansowany Edytor Nieba"> +<floater name="WindLight floater" title="ZAAWANSOWANY EDYTOR NIEBA"> <text name="KeyFramePresetsText"> Ustawienia Nieba: </text> diff --git a/indra/newview/skins/default/xui/pl/floater_world_map.xml b/indra/newview/skins/default/xui/pl/floater_world_map.xml index 65f1c8ae59..36e3b0651b 100755 --- a/indra/newview/skins/default/xui/pl/floater_world_map.xml +++ b/indra/newview/skins/default/xui/pl/floater_world_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="worldmap" title="Mapa Åšwiata"> +<floater name="worldmap" title="MAPA ÅšWIATA"> <tab_container name="maptab"> <panel label="Obiekty" name="objects_mapview"/> <panel label="Teren" name="terrain_mapview"/> diff --git a/indra/newview/skins/default/xui/pl/panel_edit_profile.xml b/indra/newview/skins/default/xui/pl/panel_edit_profile.xml index e449a92d7e..97fa3118f8 100644 --- a/indra/newview/skins/default/xui/pl/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/pl/panel_edit_profile.xml @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="edit_profile_panel">
- <string name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
- </string>
- <string name="AcctTypeResident"
- value="Rezydent" />
- <string name="AcctTypeTrial"
- value="Próbne" />
- <string name="AcctTypeCharterMember"
- value="Członek-zalożyciel" />
- <string name="AcctTypeEmployee"
- value="Pracownik Linden Lab" />
- <string name="PaymentInfoUsed"
- value="Dane Konta Używane" />
- <string name="PaymentInfoOnFile"
- value="Dane Konta Dostępne" />
- <string name="NoPaymentInfoOnFile"
- value="Brak Danych Konta" />
- <string name="AgeVerified"
- value="Wiek Zweryfikowany" />
- <string name="NotAgeVerified"
- value="Brak Weryfikacji Wieku" />
- <string name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=pl
- </string>
- <panel name="scroll_content_panel">
- <panel name="data_panel" >
- <panel name="lifes_images_panel">
- <panel name="second_life_image_panel">
- <text name="second_life_photo_title_text">
- [SECOND_LIFE]:
- </text>
- </panel>
- </panel>
- <text name="title_partner_text" value="Partner:"/>
- <panel name="partner_data_panel">
- <text name="partner_text" value="[FIRST] [LAST]"/>
- </panel>
- <text name="text_box3">
- Pracuś Mówi:
- </text>
- </panel>
- </panel>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="edit_profile_panel"> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string name="AcctTypeResident" + value="Rezydent" /> + <string name="AcctTypeTrial" + value="Próbne" /> + <string name="AcctTypeCharterMember" + value="CzÅ‚onek-zalożyciel" /> + <string name="AcctTypeEmployee" + value="Pracownik Linden Lab" /> + <string name="PaymentInfoUsed" + value="Dane Konta Używane" /> + <string name="PaymentInfoOnFile" + value="Dane Konta DostÄ™pne" /> + <string name="NoPaymentInfoOnFile" + value="Brak Danych Konta" /> + <string name="AgeVerified" + value="Wiek Zweryfikowany" /> + <string name="NotAgeVerified" + value="Brak Weryfikacji Wieku" /> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=pl + </string> + <panel name="scroll_content_panel"> + <panel name="data_panel" > + <panel name="lifes_images_panel"> + <panel name="second_life_image_panel"> + <text name="second_life_photo_title_text"> + [SECOND_LIFE]: + </text> + </panel> + </panel> + <text name="title_partner_text" value="Partner:"/> + <panel name="partner_data_panel"> + <text name="partner_text" value="[FIRST] [LAST]"/> + </panel> + <text name="text_box3"> + PracuÅ› Mówi: + </text> + </panel> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml index 12cc879cbc..9c19b12893 100644 --- a/indra/newview/skins/default/xui/pt/floater_about.xml +++ b/indra/newview/skins/default/xui/pt/floater_about.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_about" title="Sobre o [APP_NAME]"> +<floater name="floater_about" title="SOBRE O [APP_NAME]"> <tab_container name="about_tab"> <panel name="credits_panel"> <text_editor name="credits_editor"> diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml index 417d24608e..19981cf48c 100644 --- a/indra/newview/skins/default/xui/pt/floater_about_land.xml +++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterland" title="Sobre o Terreno"> +<floater name="floaterland" title="SOBRE O TERRENO"> <tab_container name="landtab"> <panel label="Geral" name="land_general_panel"> <text name="Name:"> diff --git a/indra/newview/skins/default/xui/pt/floater_auction.xml b/indra/newview/skins/default/xui/pt/floater_auction.xml index 48e0b92400..34cd17d781 100644 --- a/indra/newview/skins/default/xui/pt/floater_auction.xml +++ b/indra/newview/skins/default/xui/pt/floater_auction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_auction" title="Iniciar a venda de terrenos da Linden"> +<floater name="floater_auction" title="INICIAR A VENDA DE TERRENOS DA LINDEN"> <check_box label="Incluir marcador de seleção amarelo" name="fence_check"/> <button label="Foto" label_selected="Foto" name="snapshot_btn"/> <button label="OK" label_selected="OK" name="ok_btn"/> diff --git a/indra/newview/skins/default/xui/pt/floater_avatar_picker.xml b/indra/newview/skins/default/xui/pt/floater_avatar_picker.xml index 4e1598c8fa..186ef30e1b 100644 --- a/indra/newview/skins/default/xui/pt/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/pt/floater_avatar_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatarpicker" title="Escolha o Residente" min_width="285" width="285"> +<floater name="avatarpicker" title="ESCOLHA O RESIDENTE" min_width="285" width="285"> <tab_container name="ResidentChooserTabs" width="275"> <panel label="Buscar" name="SearchPanel"> <text name="InstructSearchResidentName"> diff --git a/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml b/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml index db0023d748..04a78efb12 100644 --- a/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="avatar_texture_debug" title="Texturas do Avatar"> +<floater name="avatar_texture_debug" title="TEXTURAS DO AVATAR"> <text name="baked_label"> Texturas sobrepostas </text> diff --git a/indra/newview/skins/default/xui/pt/floater_beacons.xml b/indra/newview/skins/default/xui/pt/floater_beacons.xml index edd1e08094..82f055745f 100644 --- a/indra/newview/skins/default/xui/pt/floater_beacons.xml +++ b/indra/newview/skins/default/xui/pt/floater_beacons.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="beacons" title="Balizas"> +<floater name="beacons" title="BALIZAS"> <panel name="beacons_panel"> <check_box label="Objetos programados com toque apenas" name="touch_only"/> <check_box label="Objetos programados" name="scripted"/> diff --git a/indra/newview/skins/default/xui/pt/floater_build_options.xml b/indra/newview/skins/default/xui/pt/floater_build_options.xml index ebc9d0f0c8..bce78fad21 100644 --- a/indra/newview/skins/default/xui/pt/floater_build_options.xml +++ b/indra/newview/skins/default/xui/pt/floater_build_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="build options floater" title="Opções de grade"> +<floater name="build options floater" title="OPÇÕES DE GRADE"> <spinner label="Uni. Grade (metros)" name="GridResolution" width="180" label_width="122"/> <spinner label="Ext. da Grade (metros)" name="GridDrawSize" width="180" label_width="122"/> <check_box label="Habilitar ajuste de sub-grade" name="GridSubUnit"/> diff --git a/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml b/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml index c064d24f96..7443e19721 100644 --- a/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floaterbulkperms" title="Mudança conjunta das permissões de conteúdo"> +<floater name="floaterbulkperms" title="MUDANÇA CONJUNTA DAS PERMISSÕES DE CONTEÚDO"> <text name="applyto"> Tipos de Conteúdo </text> diff --git a/indra/newview/skins/default/xui/pt/floater_bumps.xml b/indra/newview/skins/default/xui/pt/floater_bumps.xml index 0bc2546275..1833cd4335 100644 --- a/indra/newview/skins/default/xui/pt/floater_bumps.xml +++ b/indra/newview/skins/default/xui/pt/floater_bumps.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_bumps" title="Colisões, impulsos e batidas"> +<floater name="floater_bumps" title="COLISÕES, IMPULSOS E BATIDAS"> <text name="none_detected"> Nada detectado </text> diff --git a/indra/newview/skins/default/xui/pt/floater_buy_contents.xml b/indra/newview/skins/default/xui/pt/floater_buy_contents.xml index 3e8713d59e..322a07575a 100644 --- a/indra/newview/skins/default/xui/pt/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/pt/floater_buy_contents.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_buy_contents" title="Comprar conteúdo"> +<floater name="floater_buy_contents" title="COMPRAR CONTEÚDO"> <text name="contains_text"> [NAME] contém: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml index 42ba205475..ceeb070c4e 100644 --- a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy currency" title="Comprar Dinheiro"> +<floater name="buy currency" title="COMPRAR DINHEIRO"> <text name="info_buying"> Comprando Dinheiro: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_buy_land.xml b/indra/newview/skins/default/xui/pt/floater_buy_land.xml index 2caf057283..6e502ad6e5 100644 --- a/indra/newview/skins/default/xui/pt/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/pt/floater_buy_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="buy land" title="Comprar terra"> +<floater name="buy land" title="COMPRAR TERRA"> <text name="region_name_label"> Região: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_buy_object.xml b/indra/newview/skins/default/xui/pt/floater_buy_object.xml index b8e1085471..e9968ed8f8 100644 --- a/indra/newview/skins/default/xui/pt/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/pt/floater_buy_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Comprar cópia do objeto"> +<floater name="contents" title="COMPRAR CÓPIA DO OBJETO"> <text name="contents_text"> e seus conteúdos: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_choose_group.xml b/indra/newview/skins/default/xui/pt/floater_choose_group.xml index 449d578716..ae395734e9 100644 --- a/indra/newview/skins/default/xui/pt/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/pt/floater_choose_group.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="groups" title="Grupos"> +<floater name="groups" title="GRUPOS"> <text name="groupdesc"> Escolha um grupo: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_color_picker.xml b/indra/newview/skins/default/xui/pt/floater_color_picker.xml index 76da972b5d..6a4263f4ff 100644 --- a/indra/newview/skins/default/xui/pt/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/pt/floater_color_picker.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="ColorPicker" title="Seletor de Cor"> +<floater name="ColorPicker" title="SELETOR DE COR"> <text name="r_val_text"> Vermelho: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_customize.xml b/indra/newview/skins/default/xui/pt/floater_customize.xml index 4bced69664..55946933e7 100644 --- a/indra/newview/skins/default/xui/pt/floater_customize.xml +++ b/indra/newview/skins/default/xui/pt/floater_customize.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater customize" title="Aparência" width="546"> +<floater name="floater customize" title="APARÊNCIA" width="546"> <tab_container name="customize tab container" tab_min_width="115" width="544"> <placeholder label="Partes de corpo" name="body_parts_placeholder"/> <panel label="Forma" name="Shape"> diff --git a/indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml index f02cca9c25..42f34a3d82 100644 --- a/indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml +++ b/indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Day Cycle Floater" title="Editor de ciclo de dia"> +<floater name="Day Cycle Floater" title="EDITOR DE CICLO DE DIA"> <tab_container name="Day Cycle Tabs"> <panel label="Ciclo do dia" name="Day Cycle"> <button label="?" name="WLDayCycleHelp"/> diff --git a/indra/newview/skins/default/xui/pt/floater_device_settings.xml b/indra/newview/skins/default/xui/pt/floater_device_settings.xml index 9ce773116c..fa4da834b8 100644 --- a/indra/newview/skins/default/xui/pt/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/pt/floater_device_settings.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_device_settings" title="Ajustes do Dispositivo de Conversa por Voz"/> +<floater name="floater_device_settings" title="AJUSTES DO DISPOSITIVO DE CONVERSA POR VOZ"/> diff --git a/indra/newview/skins/default/xui/pt/floater_env_settings.xml b/indra/newview/skins/default/xui/pt/floater_env_settings.xml index d3ed760551..4a43801b48 100644 --- a/indra/newview/skins/default/xui/pt/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/pt/floater_env_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Environment Editor Floater" title="Editor do Ambiente"> +<floater name="Environment Editor Floater" title="EDITOR DO AMBIENTE"> <text name="EnvTimeText"> Hora do Dia </text> diff --git a/indra/newview/skins/default/xui/pt/floater_font_test.xml b/indra/newview/skins/default/xui/pt/floater_font_test.xml index eb52d3341d..c506cdb12d 100644 --- a/indra/newview/skins/default/xui/pt/floater_font_test.xml +++ b/indra/newview/skins/default/xui/pt/floater_font_test.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="contents" title="Teste de Fonte"> +<floater name="contents" title="TESTE DE FONTE"> <text name="linea"> OverrideTest, deveria aparecer aqui como Times. (De default/xui/en-us) </text> diff --git a/indra/newview/skins/default/xui/pt/floater_gesture.xml b/indra/newview/skins/default/xui/pt/floater_gesture.xml index ac50f32dd1..b0bc42685d 100644 --- a/indra/newview/skins/default/xui/pt/floater_gesture.xml +++ b/indra/newview/skins/default/xui/pt/floater_gesture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="gestures" title="Gestos Ativos"> +<floater name="gestures" title="GESTOS ATIVOS"> <text name="help_label"> Clicar duas vezes no gesto para executar animações e sons. </text> diff --git a/indra/newview/skins/default/xui/pt/floater_god_tools.xml b/indra/newview/skins/default/xui/pt/floater_god_tools.xml index 9406658f62..4b7b2eb34e 100644 --- a/indra/newview/skins/default/xui/pt/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/pt/floater_god_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="godtools floater" title="Ferramentas de Deus"> +<floater name="godtools floater" title="FERRAMENTAS DE DEUS"> <tab_container name="GodTools Tabs"> <panel label="Grade" name="grid"> <button label="Desconectar todos os usuários" label_selected="Desconectar todos os usuários" name="Kick all users"/> diff --git a/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml b/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml index 0f9c1fd487..8921e6ea12 100644 --- a/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Hardware Settings Floater" title="Ajustes de Hardware"> +<floater name="Hardware Settings Floater" title="AJUSTES DE HARDWARE"> <text name="Filtering:"> Filtragem: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_hud.xml b/indra/newview/skins/default/xui/pt/floater_hud.xml index d31bcedf05..e458913452 100644 --- a/indra/newview/skins/default/xui/pt/floater_hud.xml +++ b/indra/newview/skins/default/xui/pt/floater_hud.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_hud" title="Tutorial"/> +<floater name="floater_hud" title="TUTORIAL"/> diff --git a/indra/newview/skins/default/xui/pt/floater_inspect.xml b/indra/newview/skins/default/xui/pt/floater_inspect.xml index f3c23f008e..97c2c6eaeb 100644 --- a/indra/newview/skins/default/xui/pt/floater_inspect.xml +++ b/indra/newview/skins/default/xui/pt/floater_inspect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="inspect" title="Inspecionar Objeto" min_width="450"> +<floater name="inspect" title="INSPECIONAR OBJETO" min_width="450"> <scroll_list name="object_list" tool_tip="Selecione um objeto nesta lista para destacá-lo in-world"> <column label="Nome do Objeto" name="object_name"/> <column label="Proprietário" name="owner_name"/> diff --git a/indra/newview/skins/default/xui/pt/floater_inventory.xml b/indra/newview/skins/default/xui/pt/floater_inventory.xml index 8a06fefe3c..1c2a3a9233 100644 --- a/indra/newview/skins/default/xui/pt/floater_inventory.xml +++ b/indra/newview/skins/default/xui/pt/floater_inventory.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory" title="Inventário"> +<floater name="Inventory" title="INVENTÃRIO"> <search_editor label="Escreva aqui para busca" name="inventory search editor"/> <tab_container name="inventory filter tabs"> <inventory_panel label="Todos os Itens" name="All Items"/> diff --git a/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml index 69752253b6..2a6b02f9c2 100644 --- a/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="item properties" title="Propriedades do Item de Inventário"> +<floater name="item properties" title="PROPRIEDADES DO ITEM DE INVENTÃRIO"> <text name="LabelItemNameTitle"> Nome: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml index 83df449ae6..57cdd50dcc 100644 --- a/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Inventory Finder" title="itens_de_inventário_recentes" width="165"> +<floater name="Inventory Finder" title="ITENS_DE_INVENTÃRIO_RECENTES" width="165"> <check_box label="Animação" name="check_animation"/> <check_box label="Cartões de chamadas" name="check_calling_card"/> <check_box label="Roupas" name="check_clothing"/> diff --git a/indra/newview/skins/default/xui/pt/floater_joystick.xml b/indra/newview/skins/default/xui/pt/floater_joystick.xml index ac7b7fd02a..0793a0b161 100644 --- a/indra/newview/skins/default/xui/pt/floater_joystick.xml +++ b/indra/newview/skins/default/xui/pt/floater_joystick.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Joystick" title="Configuração do Joystick"> +<floater name="Joystick" title="CONFIGURAÇÃO DO JOYSTICK"> <check_box name="enable_joystick" label="Habilitar Joystick:"/> <text left="135" name="joystick_type" width="360"/> <spinner label="Mapeamento: eixo X" name="JoystickAxis1" label_width="124" width="164"/> diff --git a/indra/newview/skins/default/xui/pt/floater_lagmeter.xml b/indra/newview/skins/default/xui/pt/floater_lagmeter.xml index 6657641992..2728633438 100644 --- a/indra/newview/skins/default/xui/pt/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/pt/floater_lagmeter.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="Medidor de Atraso"> +<floater name="floater_lagmeter" title="MEDIDOR DE ATRASO"> <button label="" label_selected="" name="client_lagmeter" tool_tip="Status de atraso no Cliente"/> <text left="30" name="client_lag_cause" right="-10" /> <text left="30" name="network_lag_cause" right="-10" /> diff --git a/indra/newview/skins/default/xui/pt/floater_land_holdings.xml b/indra/newview/skins/default/xui/pt/floater_land_holdings.xml index 4734d665ef..d8588e2f05 100644 --- a/indra/newview/skins/default/xui/pt/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/pt/floater_land_holdings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="land holdings floater" title="Meu terreno"> +<floater name="land holdings floater" title="MEU TERRENO"> <scroll_list name="parcel list"> <column label="Nome do Lote" name="name"/> <column label="Região" name="location"/> diff --git a/indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml index d2654de589..c0b726c476 100644 --- a/indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="script ed float" title="Script: Novo Script"> +<floater name="script ed float" title="SCRIPT: NOVO SCRIPT"> <button label="Resetar" label_selected="Resetar" name="Reset"/> <check_box label="Correndo" name="running"/> <check_box label="Mono" name="mono" left="86"/> diff --git a/indra/newview/skins/default/xui/pt/floater_lsl_guide.xml b/indra/newview/skins/default/xui/pt/floater_lsl_guide.xml index 4f60ef23a6..49a9e7fcf5 100644 --- a/indra/newview/skins/default/xui/pt/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/pt/floater_lsl_guide.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="script ed float" title="LSL Wiki"> +<floater name="script ed float" title="LSL WIKI"> <check_box label="Seguir o Cursor" name="lock_check" /> <combo_box label="Bloquear" name="history_combo" left_delta="120" width="70"/> <button label="Anterior" name="back_btn" left_delta="75"/> diff --git a/indra/newview/skins/default/xui/pt/floater_media_browser.xml b/indra/newview/skins/default/xui/pt/floater_media_browser.xml index cfaec5b410..3437dfcdba 100644 --- a/indra/newview/skins/default/xui/pt/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/pt/floater_media_browser.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater min_width="477" name="floater_about" title="Navegador de MÃdia" width="570"> +<floater min_width="477" name="floater_about" title="NAVEGADOR DE MÃDIA" width="570"> <layout_stack name="stack1" width="550"> <layout_panel name="nav_controls"> <button label="Para trás" name="back" width="75"/> diff --git a/indra/newview/skins/default/xui/pt/floater_mem_leaking.xml b/indra/newview/skins/default/xui/pt/floater_mem_leaking.xml index 374592f0e2..4f93eb90e5 100644 --- a/indra/newview/skins/default/xui/pt/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/pt/floater_mem_leaking.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="MemLeak" title="Simulação de Perda de Memória"> +<floater name="MemLeak" title="SIMULAÇÃO DE PERDA DE MEMÓRIA"> <spinner label="Velocidade da Perda (bytes por quadro):" name="leak_speed"/> <spinner label="Máximo de Memória Perdida (MB):" name="max_leak"/> <text name="total_leaked_label"> diff --git a/indra/newview/skins/default/xui/pt/floater_mute_object.xml b/indra/newview/skins/default/xui/pt/floater_mute_object.xml index 7ec0051a7d..cc669951c3 100644 --- a/indra/newview/skins/default/xui/pt/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/pt/floater_mute_object.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="mute by name" title="Silenciar objeto pelo nome"> +<floater name="mute by name" title="SILENCIAR OBJETO PELO NOME"> <text name="message"> Silenciar pelo nome afeta apenas conversa de objeto e MI, não sons. Você deve digitar o nome exato do objeto. diff --git a/indra/newview/skins/default/xui/pt/floater_my_friends.xml b/indra/newview/skins/default/xui/pt/floater_my_friends.xml index a78b255f8a..68f2a19998 100644 --- a/indra/newview/skins/default/xui/pt/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/pt/floater_my_friends.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_my_friends" title="Contatos"> +<floater name="floater_my_friends" title="CONTATOS"> <tab_container name="friends_and_groups"> <panel label="Amigos" name="friends_panel"/> <panel label="Grupos" name="groups_panel"/> diff --git a/indra/newview/skins/default/xui/pt/floater_openobject.xml b/indra/newview/skins/default/xui/pt/floater_openobject.xml index d3b72b4b18..0dc2852bac 100644 --- a/indra/newview/skins/default/xui/pt/floater_openobject.xml +++ b/indra/newview/skins/default/xui/pt/floater_openobject.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="objectcontents" title="Conteúdo do objeto"> +<floater name="objectcontents" title="CONTEÚDO DO OBJETO"> <text name="object_name"> [DESC]: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_perm_prefs.xml b/indra/newview/skins/default/xui/pt/floater_perm_prefs.xml index 9bb7f04256..33a0d6a456 100644 --- a/indra/newview/skins/default/xui/pt/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/pt/floater_perm_prefs.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="perm prefs" title="Permissões Padrão de Upload"> +<floater name="perm prefs" title="PERMISSÕES PADRÃO DE UPLOAD"> <panel label="Permissões" name="permissions"> <button label="?" label_selected="?" name="help"/> <check_box label="Compartilhar com o grupo" name="share_with_group"/> diff --git a/indra/newview/skins/default/xui/pt/floater_post_process.xml b/indra/newview/skins/default/xui/pt/floater_post_process.xml index 8f5f5db743..d4f2e96539 100644 --- a/indra/newview/skins/default/xui/pt/floater_post_process.xml +++ b/indra/newview/skins/default/xui/pt/floater_post_process.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="Ajustes de Pós-processamento"> +<floater name="Post-Process Floater" title="AJUSTES DE PÓS-PROCESSAMENTO"> <tab_container name="Post-Process Tabs"> <panel label="Filtro de Cor" name="wmiColorFilterPanel"> <check_box label="Habilitar" name="wmiColorFilterToggle"/> diff --git a/indra/newview/skins/default/xui/pt/floater_postcard.xml b/indra/newview/skins/default/xui/pt/floater_postcard.xml index 62fd050ea4..cf63726df2 100644 --- a/indra/newview/skins/default/xui/pt/floater_postcard.xml +++ b/indra/newview/skins/default/xui/pt/floater_postcard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Postcard" title="Foto por email"> +<floater name="Postcard" title="FOTO POR EMAIL"> <text name="to_label" width="135"> Email do Destinatário: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_preferences.xml b/indra/newview/skins/default/xui/pt/floater_preferences.xml index 0e9ef768b5..d2c3c79160 100644 --- a/indra/newview/skins/default/xui/pt/floater_preferences.xml +++ b/indra/newview/skins/default/xui/pt/floater_preferences.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Preferences" title="Preferências" min_width="332" width="628"> +<floater name="Preferences" title="PREFERÊNCIAS" min_width="332" width="628"> <button label="OK" label_selected="OK" name="OK"/> <button label="Cancelar" label_selected="Cancelar" name="Cancel"/> <button label="Aplicar" label_selected="Aplicar" name="Apply"/> diff --git a/indra/newview/skins/default/xui/pt/floater_preview_classified.xml b/indra/newview/skins/default/xui/pt/floater_preview_classified.xml index 4c583c28fb..0e8814b9f8 100644 --- a/indra/newview/skins/default/xui/pt/floater_preview_classified.xml +++ b/indra/newview/skins/default/xui/pt/floater_preview_classified.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="classified_preview" title="Informação do Anúncio Classificado"/> +<floater name="classified_preview" title="INFORMAÇÃO DO ANÚNCIO CLASSIFICADO"/> diff --git a/indra/newview/skins/default/xui/pt/floater_preview_event.xml b/indra/newview/skins/default/xui/pt/floater_preview_event.xml index 3c8ebcf95a..c03feacf0c 100644 --- a/indra/newview/skins/default/xui/pt/floater_preview_event.xml +++ b/indra/newview/skins/default/xui/pt/floater_preview_event.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="event_preview" title="Informação do Evento"/> +<floater name="event_preview" title="INFORMAÇÃO DO EVENTO"/> diff --git a/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml b/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml index e0a133d8ab..6f8944942a 100644 --- a/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="preview notecard" title="Nota:"> +<floater name="preview notecard" title="NOTA:"> <button label="Salvar" label_selected="Salvar" name="Save"/> <text name="desc txt"> Descrição: diff --git a/indra/newview/skins/default/xui/pt/floater_region_info.xml b/indra/newview/skins/default/xui/pt/floater_region_info.xml index fe228ab405..cc5e0d59d4 100644 --- a/indra/newview/skins/default/xui/pt/floater_region_info.xml +++ b/indra/newview/skins/default/xui/pt/floater_region_info.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="regioninfo" title="Região/Propriedade"/> +<floater name="regioninfo" title="REGIÃO/PROPRIEDADE"/> diff --git a/indra/newview/skins/default/xui/pt/floater_report_abuse.xml b/indra/newview/skins/default/xui/pt/floater_report_abuse.xml index 51d7ef8190..0d226a9502 100644 --- a/indra/newview/skins/default/xui/pt/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/pt/floater_report_abuse.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_report_abuse" title="Reportar abuso"> +<floater name="floater_report_abuse" title="REPORTAR ABUSO"> <check_box label="Incluir cópia da tela" name="screen_check"/> <text name="reporter_title"> Denunciador: diff --git a/indra/newview/skins/default/xui/pt/floater_script_debug.xml b/indra/newview/skins/default/xui/pt/floater_script_debug.xml index 48c73b93a3..6d1d981ca7 100644 --- a/indra/newview/skins/default/xui/pt/floater_script_debug.xml +++ b/indra/newview/skins/default/xui/pt/floater_script_debug.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <multi_floater name="script debug floater" title="Aviso de script/erro"> <tab_container name="Preview Tabs"> - <floater label="Script" name="all_scripts" title="[Todos os scripts]"/> + <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]"/> </tab_container> </multi_floater> diff --git a/indra/newview/skins/default/xui/pt/floater_script_preview.xml b/indra/newview/skins/default/xui/pt/floater_script_preview.xml index 2a7680565f..3c0570791c 100644 --- a/indra/newview/skins/default/xui/pt/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/pt/floater_script_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="preview lsl text" title="Script: Rotation Script"> +<floater name="preview lsl text" title="SCRIPT: ROTATION SCRIPT"> <text name="desc txt"> Descrição: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_script_queue.xml b/indra/newview/skins/default/xui/pt/floater_script_queue.xml index 7b35226bdb..6e0e174c07 100644 --- a/indra/newview/skins/default/xui/pt/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/pt/floater_script_queue.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="queue" title="Resetar Progresso"> +<floater name="queue" title="RESETAR PROGRESSO"> <button label="Fechar" label_selected="Fechar" name="close"/> </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_script_search.xml b/indra/newview/skins/default/xui/pt/floater_script_search.xml index c904c0f816..3a62f1711f 100644 --- a/indra/newview/skins/default/xui/pt/floater_script_search.xml +++ b/indra/newview/skins/default/xui/pt/floater_script_search.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="script search" title="Busca de Script" width="320"> +<floater name="script search" title="BUSCA DE SCRIPT" width="320"> <check_box label="Não diferenciar Maiúsculas de Minúsculas" name="case_text" left="75"/> <button label="Buscar" label_selected="Buscar" name="search_btn" width="85"/> <button label="Substituir" label_selected="Substituir" name="replace_btn" left="100" width="85"/> diff --git a/indra/newview/skins/default/xui/pt/floater_sell_land.xml b/indra/newview/skins/default/xui/pt/floater_sell_land.xml index d3581405ff..f58c4098ef 100644 --- a/indra/newview/skins/default/xui/pt/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/pt/floater_sell_land.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="sell land" title="Vender terreno"> +<floater name="sell land" title="VENDER TERRENO"> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> <text name="info_parcel_label"> diff --git a/indra/newview/skins/default/xui/pt/floater_settings_debug.xml b/indra/newview/skins/default/xui/pt/floater_settings_debug.xml index f7b468bb22..394a9771e0 100644 --- a/indra/newview/skins/default/xui/pt/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/pt/floater_settings_debug.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="settings_debug" title="Configurações de Debug"> +<floater name="settings_debug" title="CONFIGURAÇÕES DE DEBUG"> <combo_box name="boolean_combo"> <combo_box.item name="TRUE" label="VERDADEIRO" /> <combo_box.item name="FALSE" label="FALSO" /> diff --git a/indra/newview/skins/default/xui/pt/floater_snapshot.xml b/indra/newview/skins/default/xui/pt/floater_snapshot.xml index a924706cb9..c3c4c73a89 100644 --- a/indra/newview/skins/default/xui/pt/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/pt/floater_snapshot.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Snapshot" title="Prévia da foto"> +<floater name="Snapshot" title="PRÉVIA DA FOTO"> <text name="type_label"> Destino da foto </text> diff --git a/indra/newview/skins/default/xui/pt/floater_sound_preview.xml b/indra/newview/skins/default/xui/pt/floater_sound_preview.xml index df76499f42..d5d252c0dd 100644 --- a/indra/newview/skins/default/xui/pt/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/pt/floater_sound_preview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Sound Preview" title="sound.wav"> +<floater name="Sound Preview" title="SOUND.WAV"> <text name="name_label"> Nome: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_statistics.xml b/indra/newview/skins/default/xui/pt/floater_statistics.xml index d26c7081cc..c56c9fb2e0 100644 --- a/indra/newview/skins/default/xui/pt/floater_statistics.xml +++ b/indra/newview/skins/default/xui/pt/floater_statistics.xml @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="stats floater" title="StatÃstica"/> +<floater name="stats floater" title="STATÃSTICA"/> diff --git a/indra/newview/skins/default/xui/pt/floater_telehub.xml b/indra/newview/skins/default/xui/pt/floater_telehub.xml index 11886c7cab..5c775ab45d 100644 --- a/indra/newview/skins/default/xui/pt/floater_telehub.xml +++ b/indra/newview/skins/default/xui/pt/floater_telehub.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="telehub" title="Telehub" min_height="310" height="310" width="286"> +<floater name="telehub" title="TELEHUB" min_height="310" height="310" width="286"> <text name="status_text_connected"> Telehub conectado ao objeto [OBJECT] </text> diff --git a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml index 784540a48e..b63c4a9bbf 100644 --- a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="texture picker" title="Pegar: Textura"> +<floater name="texture picker" title="PEGAR: TEXTURA"> <string name="choose_picture"> Clique para escolher uma imagem </string> diff --git a/indra/newview/skins/default/xui/pt/floater_tools.xml b/indra/newview/skins/default/xui/pt/floater_tools.xml index d7227deacc..b9ab018606 100644 --- a/indra/newview/skins/default/xui/pt/floater_tools.xml +++ b/indra/newview/skins/default/xui/pt/floater_tools.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="toolbox floater" title="" short_title="Construir" width="288"> +<floater name="toolbox floater" title="" short_title="CONSTRUIR" width="288"> <button label="" label_selected="" name="button focus" tool_tip="Foco"/> <button label="" label_selected="" name="button move" tool_tip="Mover"/> <button label="" label_selected="" name="button edit" tool_tip="Editar"/> diff --git a/indra/newview/skins/default/xui/pt/floater_top_objects.xml b/indra/newview/skins/default/xui/pt/floater_top_objects.xml index cd94b51b16..15e69c450c 100644 --- a/indra/newview/skins/default/xui/pt/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/pt/floater_top_objects.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="top_objects" title="Carregando..."> +<floater name="top_objects" title="CARREGANDO..."> <text name="title_text"> Carregando... </text> diff --git a/indra/newview/skins/default/xui/pt/floater_water.xml b/indra/newview/skins/default/xui/pt/floater_water.xml index ceb4414058..bad9aa0943 100644 --- a/indra/newview/skins/default/xui/pt/floater_water.xml +++ b/indra/newview/skins/default/xui/pt/floater_water.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Water Floater" title="Editor de Ãgua Avançado"> +<floater name="Water Floater" title="EDITOR DE ÃGUA AVANÇADO"> <text name="KeyFramePresetsText" width="154"> Pré-configurações da Ãgua: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_windlight_options.xml b/indra/newview/skins/default/xui/pt/floater_windlight_options.xml index 0de8bd22f8..951e37a1a6 100644 --- a/indra/newview/skins/default/xui/pt/floater_windlight_options.xml +++ b/indra/newview/skins/default/xui/pt/floater_windlight_options.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="WindLight floater" title="Editor de Céu Avançado"> +<floater name="WindLight floater" title="EDITOR DE CÉU AVANÇADO"> <text name="KeyFramePresetsText" width="130"> Pré-definições de Céu: </text> diff --git a/indra/newview/skins/default/xui/pt/floater_world_map.xml b/indra/newview/skins/default/xui/pt/floater_world_map.xml index 056d121520..034602d6ea 100644 --- a/indra/newview/skins/default/xui/pt/floater_world_map.xml +++ b/indra/newview/skins/default/xui/pt/floater_world_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="worldmap" title="Mapa Mundi"> +<floater name="worldmap" title="MAPA MUNDI"> <tab_container name="maptab"> <panel label="Objetos" name="objects_mapview"/> <panel label="Terreno" name="terrain_mapview"/> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_profile.xml b/indra/newview/skins/default/xui/pt/panel_edit_profile.xml index e97e77cfe6..a989cab167 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_profile.xml @@ -1,45 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="edit_profile_panel">
- <string name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
- </string>
- <string name="AcctTypeResident"
- value="Residente" />
- <string name="AcctTypeTrial"
- value="Teste" />
- <string name="AcctTypeCharterMember"
- value="Estatuto do membro" />
- <string name="AcctTypeEmployee"
- value="Contratado da Linden Lab" />
- <string name="PaymentInfoUsed"
- value="Infor. de pagamento utilizadas" />
- <string name="PaymentInfoOnFile"
- value="Infor. de pagamento no arquivo" />
- <string name="NoPaymentInfoOnFile"
- value="Sem infor. de pagamento no arquivo" />
- <string name="AgeVerified"
- value="Idade Verificada" />
- <string name="NotAgeVerified"
- value="Idade não Verificada" />
- <string name="partner_edit_link_url">
- http://www.secondlife.com/account/partners.php?lang=pt
- </string>
- <panel name="scroll_content_panel">
- <panel name="data_panel" >
- <panel name="lifes_images_panel">
- <panel name="second_life_image_panel">
- <text name="second_life_photo_title_text">
- [SECOND_LIFE]:
- </text>
- </panel>
- </panel>
- <text name="title_partner_text" value="Parceiro:"/>
- <panel name="partner_data_panel">
- <text name="partner_text" value="[FIRST] [LAST]"/>
- </panel>
- <text name="text_box3">
- Resposta no Modo Ocupado:
- </text>
- </panel>
- </panel>
-</panel>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="edit_profile_panel"> + <string name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string name="AcctTypeResident" + value="Residente" /> + <string name="AcctTypeTrial" + value="Teste" /> + <string name="AcctTypeCharterMember" + value="Estatuto do membro" /> + <string name="AcctTypeEmployee" + value="Contratado da Linden Lab" /> + <string name="PaymentInfoUsed" + value="Infor. de pagamento utilizadas" /> + <string name="PaymentInfoOnFile" + value="Infor. de pagamento no arquivo" /> + <string name="NoPaymentInfoOnFile" + value="Sem infor. de pagamento no arquivo" /> + <string name="AgeVerified" + value="Idade Verificada" /> + <string name="NotAgeVerified" + value="Idade não Verificada" /> + <string name="partner_edit_link_url"> + http://www.secondlife.com/account/partners.php?lang=pt + </string> + <panel name="scroll_content_panel"> + <panel name="data_panel" > + <panel name="lifes_images_panel"> + <panel name="second_life_image_panel"> + <text name="second_life_photo_title_text"> + [SECOND_LIFE]: + </text> + </panel> + </panel> + <text name="title_partner_text" value="Parceiro:"/> + <panel name="partner_data_panel"> + <text name="partner_text" value="[FIRST] [LAST]"/> + </panel> + <text name="text_box3"> + Resposta no Modo Ocupado: + </text> + </panel> + </panel> +</panel> diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 009be35f64..d31a81e128 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -1,423 +1,423 @@ -/**
- * @file lllogininstance_test.cpp
- * @brief Test for lllogininstance.cpp.
- *
- * $LicenseInfo:firstyear=2008&license=internal$
- * Copyright (c) 2008, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-// Precompiled header
-#include "../llviewerprecompiledheaders.h"
-// Own header
-#include "../lllogininstance.h"
-// STL headers
-// std headers
-// external library headers
-// other Linden headers
-#include "../test/lltut.h"
-#include "llevents.h"
-
-#if defined(LL_WINDOWS)
-#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr
-#endif
-
-// Constants
-const std::string VIEWERLOGIN_URI("viewerlogin_uri");
-const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid");
-
-const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno");
-
-// Link seams.
-
-//-----------------------------------------------------------------------------
-static LLEventStream gTestPump("test_pump");
-
-#include "lllogin.h"
-static std::string gLoginURI;
-static LLSD gLoginCreds;
-static bool gDisconnectCalled = false;
-class LLLogin::Impl
-{
-};
-LLLogin::LLLogin() {}
-LLLogin::~LLLogin() {}
-LLEventPump& LLLogin::getEventPump() { return gTestPump; }
-void LLLogin::connect(const std::string& uri, const LLSD& credentials)
-{
- gLoginURI = uri;
- gLoginCreds = credentials;
-}
-
-void LLLogin::disconnect()
-{
- gDisconnectCalled = true;
-}
-
-//-----------------------------------------------------------------------------
-#include "../llviewernetwork.h"
-unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {'1','2','3','4','5','6'}; /* Flawfinder: ignore */
-
-LLViewerLogin::LLViewerLogin() {}
-LLViewerLogin::~LLViewerLogin() {}
-void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const
-{
- uris.push_back(VIEWERLOGIN_URI);
-}
-std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; }
-
-//-----------------------------------------------------------------------------
-#include "../llviewercontrol.h"
-LLControlGroup gSavedSettings("Global");
-std::string gCurrentVersion = "invalid_version";
-
-LLControlGroup::LLControlGroup(const std::string& name) :
- LLInstanceTracker<LLControlGroup, std::string>(name){}
-LLControlGroup::~LLControlGroup() {}
-void LLControlGroup::setBOOL(const std::string& name, BOOL val) {}
-BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; }
-U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; }
-void LLControlGroup::setString(const std::string& name, const std::string& val) {}
-std::string LLControlGroup::getString(const std::string& name) { return "test_string"; }
-BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; }
-BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; }
-
-#include "lluicolortable.h"
-void LLUIColorTable::saveUserSettings(void)const {}
-
-//-----------------------------------------------------------------------------
-#include "../llurlsimstring.h"
-LLURLSimString LLURLSimString::sInstance;
-bool LLURLSimString::parse() { return true; }
-
-//-----------------------------------------------------------------------------
-#include "llnotifications.h"
-#include "llfloaterreg.h"
-static std::string gTOSType;
-static LLEventPump * gTOSReplyPump = NULL;
-
-//static
-LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus)
-{
- gTOSType = name;
- gTOSReplyPump = &LLEventPumps::instance().obtain(key["reply_pump"]);
- return NULL;
-}
-
-//-----------------------------------------------------------------------------
-// LLNotifications
-class MockNotifications : public LLNotificationsInterface
-{
- boost::function<void (const LLSD&, const LLSD&)> mResponder;
- int mAddedCount;
-
-public:
- MockNotifications() :
- mResponder(0),
- mAddedCount(0)
- {
- }
-
- virtual ~MockNotifications() {}
-
- /* virtual */ LLNotificationPtr add(
- const std::string& name,
- const LLSD& substitutions,
- const LLSD& payload,
- LLNotificationFunctorRegistry::ResponseFunctor functor)
- {
- mResponder = functor;
- mAddedCount++;
- return LLNotificationPtr((LLNotification*)NULL);
- }
-
- void sendYesResponse()
- {
- LLSD notification;
- LLSD response;
- response = 1;
- mResponder(notification, response);
- }
-
- void sendNoResponse()
- {
- LLSD notification;
- LLSD response;
- response = 2;
- mResponder(notification, response);
- }
-
- void sendBogusResponse()
- {
- LLSD notification;
- LLSD response;
- response = 666;
- mResponder(notification, response);
- }
-
- int addedCount() { return mAddedCount; }
-};
-
-S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response)
-{
- return response.asInteger();
-}
-
-// misc
-std::string xml_escape_string(const std::string& in)
-{
- return in;
-}
-
-/*****************************************************************************
-* TUT
-*****************************************************************************/
-namespace tut
-{
- struct lllogininstance_data
- {
- lllogininstance_data() : logininstance(LLLoginInstance::getInstance())
- {
- // Global initialization
- gLoginURI.clear();
- gLoginCreds.clear();
- gDisconnectCalled = false;
-
- gTOSType = ""; // Set to invalid value.
- gTOSReplyPump = 0; // clear the callback.
-
-
- gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE);
- gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE);
- gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE);
- gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE);
- gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE);
- gSavedSettings.declareString("VersionChannelName", "test_version_string", "", FALSE);
- gSavedSettings.declareString("NextLoginLocation", "", "", FALSE);
- gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE);
-
- credentials["first"] = "testfirst";
- credentials["last"] = "testlast";
- credentials["passwd"] = "testpass";
-
- logininstance->setNotificationsInterface(¬ifications);
- }
-
- LLLoginInstance* logininstance;
- LLSD credentials;
- MockNotifications notifications;
- };
-
- typedef test_group<lllogininstance_data> lllogininstance_group;
- typedef lllogininstance_group::object lllogininstance_object;
- lllogininstance_group llsdmgr("lllogininstance");
-
- template<> template<>
- void lllogininstance_object::test<1>()
- {
- set_test_name("Test Simple Success And Disconnect");
-
- // Test default connect.
- logininstance->connect(credentials);
-
- ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
-
- // Dummy success response.
- LLSD response;
- response["state"] = "online";
- response["change"] = "connect";
- response["progress"] = 1.0;
- response["transfer_rate"] = 7;
- response["data"] = "test_data";
-
- gTestPump.post(response);
-
- ensure("Success response", logininstance->authSuccess());
- ensure_equals("Test Response Data", logininstance->getResponse().asString(), "test_data");
-
- logininstance->disconnect();
-
- ensure_equals("Called Login Module Disconnect", gDisconnectCalled, true);
-
- response.clear();
- response["state"] = "offline";
- response["change"] = "disconnect";
- response["progress"] = 0.0;
- response["transfer_rate"] = 0;
- response["data"] = "test_data";
-
- gTestPump.post(response);
-
- ensure("Disconnected", !(logininstance->authSuccess()));
- }
-
- template<> template<>
- void lllogininstance_object::test<2>()
- {
- set_test_name("Test User TOS/Critical message Interaction");
-
- const std::string test_uri = "testing-uri";
-
- // Test default connect.
- logininstance->connect(test_uri, credentials);
-
- // connect should call LLLogin::connect to init gLoginURI and gLoginCreds.
- ensure_equals("Default connect uri", gLoginURI, "testing-uri");
- ensure_equals("Default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
- ensure_equals("Default for read critical", gLoginCreds["params"]["read_critical"].asBoolean(), false);
-
- // TOS failure response.
- LLSD response;
- response["state"] = "offline";
- response["change"] = "fail.login";
- response["progress"] = 0.0;
- response["transfer_rate"] = 7;
- response["data"]["reason"] = "tos";
- gTestPump.post(response);
-
- ensure_equals("TOS Dialog type", gTOSType, "message_tos");
- ensure("TOS callback given", gTOSReplyPump != 0);
- gTOSReplyPump->post(false); // Call callback denying TOS.
- ensure("No TOS, failed auth", logininstance->authFailure());
-
- // Start again.
- logininstance->connect(test_uri, credentials);
- gTestPump.post(response); // Fail for tos again.
- gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos.
- ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true);
- ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess());
-
- // Fail connection, attempt connect again.
- // The new request should have reset agree to tos to default.
- response["data"]["reason"] = "key"; // bad creds.
- gTestPump.post(response);
- ensure("TOS auth failure", logininstance->authFailure());
-
- logininstance->connect(test_uri, credentials);
- ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
-
- // Critical Message failure response.
- logininstance->connect(test_uri, credentials);
- response["data"]["reason"] = "critical"; // Change response to "critical message"
- gTestPump.post(response);
-
- ensure_equals("TOS Dialog type", gTOSType, "message_critical");
- ensure("TOS callback given", gTOSReplyPump != 0);
- gTOSReplyPump->post(true);
- ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true);
- ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess());
-
- // Fail then attempt new connection
- response["data"]["reason"] = "key"; // bad creds.
- gTestPump.post(response);
- ensure("TOS auth failure", logininstance->authFailure());
- logininstance->connect(test_uri, credentials);
- ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false);
- }
-
- template<> template<>
- void lllogininstance_object::test<3>()
- {
- set_test_name("Test Mandatory Update User Accepts");
-
- // Part 1 - Mandatory Update, with User accepts response.
- // Test connect with update needed.
- logininstance->connect(credentials);
-
- ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
-
- // Update needed failure response.
- LLSD response;
- response["state"] = "offline";
- response["change"] = "fail.login";
- response["progress"] = 0.0;
- response["transfer_rate"] = 7;
- response["data"]["reason"] = "update";
- gTestPump.post(response);
-
- ensure_equals("Notification added", notifications.addedCount(), 1);
-
- notifications.sendYesResponse();
-
- ensure("Disconnected", !(logininstance->authSuccess()));
- }
-
- template<> template<>
- void lllogininstance_object::test<4>()
- {
- set_test_name("Test Mandatory Update User Decline");
-
- // Test connect with update needed.
- logininstance->connect(credentials);
-
- ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
-
- // Update needed failure response.
- LLSD response;
- response["state"] = "offline";
- response["change"] = "fail.login";
- response["progress"] = 0.0;
- response["transfer_rate"] = 7;
- response["data"]["reason"] = "update";
- gTestPump.post(response);
-
- ensure_equals("Notification added", notifications.addedCount(), 1);
- notifications.sendNoResponse();
-
- ensure("Disconnected", !(logininstance->authSuccess()));
- }
-
- template<> template<>
- void lllogininstance_object::test<6>()
- {
- set_test_name("Test Optional Update User Accept");
-
- // Part 3 - Mandatory Update, with bogus response.
- // Test connect with update needed.
- logininstance->connect(credentials);
-
- ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
-
- // Update needed failure response.
- LLSD response;
- response["state"] = "offline";
- response["change"] = "fail.login";
- response["progress"] = 0.0;
- response["transfer_rate"] = 7;
- response["data"]["reason"] = "optional";
- gTestPump.post(response);
-
- ensure_equals("Notification added", notifications.addedCount(), 1);
- notifications.sendYesResponse();
-
- ensure("Disconnected", !(logininstance->authSuccess()));
- }
-
- template<> template<>
- void lllogininstance_object::test<7>()
- {
- set_test_name("Test Optional Update User Denies");
-
- // Part 3 - Mandatory Update, with bogus response.
- // Test connect with update needed.
- logininstance->connect(credentials);
-
- ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
-
- // Update needed failure response.
- LLSD response;
- response["state"] = "offline";
- response["change"] = "fail.login";
- response["progress"] = 0.0;
- response["transfer_rate"] = 7;
- response["data"]["reason"] = "optional";
- gTestPump.post(response);
-
- ensure_equals("Notification added", notifications.addedCount(), 1);
- notifications.sendNoResponse();
-
- // User skips, should be reconnecting.
- ensure_equals("reconnect uri", gLoginURI, VIEWERLOGIN_URI);
- ensure_equals("skipping optional update", gLoginCreds["params"]["skipoptional"].asBoolean(), true);
- }
-}
+/** + * @file lllogininstance_test.cpp + * @brief Test for lllogininstance.cpp. + * + * $LicenseInfo:firstyear=2008&license=internal$ + * Copyright (c) 2008, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "../llviewerprecompiledheaders.h" +// Own header +#include "../lllogininstance.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "../test/lltut.h" +#include "llevents.h" + +#if defined(LL_WINDOWS) +#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr +#endif + +// Constants +const std::string VIEWERLOGIN_URI("viewerlogin_uri"); +const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid"); + +const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno"); + +// Link seams. + +//----------------------------------------------------------------------------- +static LLEventStream gTestPump("test_pump"); + +#include "lllogin.h" +static std::string gLoginURI; +static LLSD gLoginCreds; +static bool gDisconnectCalled = false; +class LLLogin::Impl +{ +}; +LLLogin::LLLogin() {} +LLLogin::~LLLogin() {} +LLEventPump& LLLogin::getEventPump() { return gTestPump; } +void LLLogin::connect(const std::string& uri, const LLSD& credentials) +{ + gLoginURI = uri; + gLoginCreds = credentials; +} + +void LLLogin::disconnect() +{ + gDisconnectCalled = true; +} + +//----------------------------------------------------------------------------- +#include "../llviewernetwork.h" +unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {'1','2','3','4','5','6'}; /* Flawfinder: ignore */ + +LLViewerLogin::LLViewerLogin() {} +LLViewerLogin::~LLViewerLogin() {} +void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const +{ + uris.push_back(VIEWERLOGIN_URI); +} +std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; } + +//----------------------------------------------------------------------------- +#include "../llviewercontrol.h" +LLControlGroup gSavedSettings("Global"); +std::string gCurrentVersion = "invalid_version"; + +LLControlGroup::LLControlGroup(const std::string& name) : + LLInstanceTracker<LLControlGroup, std::string>(name){} +LLControlGroup::~LLControlGroup() {} +void LLControlGroup::setBOOL(const std::string& name, BOOL val) {} +BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; } +U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; } +void LLControlGroup::setString(const std::string& name, const std::string& val) {} +std::string LLControlGroup::getString(const std::string& name) { return "test_string"; } +BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; } +BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; } + +#include "lluicolortable.h" +void LLUIColorTable::saveUserSettings(void)const {} + +//----------------------------------------------------------------------------- +#include "../llurlsimstring.h" +LLURLSimString LLURLSimString::sInstance; +bool LLURLSimString::parse() { return true; } + +//----------------------------------------------------------------------------- +#include "llnotifications.h" +#include "llfloaterreg.h" +static std::string gTOSType; +static LLEventPump * gTOSReplyPump = NULL; + +//static +LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) +{ + gTOSType = name; + gTOSReplyPump = &LLEventPumps::instance().obtain(key["reply_pump"]); + return NULL; +} + +//----------------------------------------------------------------------------- +// LLNotifications +class MockNotifications : public LLNotificationsInterface +{ + boost::function<void (const LLSD&, const LLSD&)> mResponder; + int mAddedCount; + +public: + MockNotifications() : + mResponder(0), + mAddedCount(0) + { + } + + virtual ~MockNotifications() {} + + /* virtual */ LLNotificationPtr add( + const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + LLNotificationFunctorRegistry::ResponseFunctor functor) + { + mResponder = functor; + mAddedCount++; + return LLNotificationPtr((LLNotification*)NULL); + } + + void sendYesResponse() + { + LLSD notification; + LLSD response; + response = 1; + mResponder(notification, response); + } + + void sendNoResponse() + { + LLSD notification; + LLSD response; + response = 2; + mResponder(notification, response); + } + + void sendBogusResponse() + { + LLSD notification; + LLSD response; + response = 666; + mResponder(notification, response); + } + + int addedCount() { return mAddedCount; } +}; + +S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response) +{ + return response.asInteger(); +} + +// misc +std::string xml_escape_string(const std::string& in) +{ + return in; +} + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct lllogininstance_data + { + lllogininstance_data() : logininstance(LLLoginInstance::getInstance()) + { + // Global initialization + gLoginURI.clear(); + gLoginCreds.clear(); + gDisconnectCalled = false; + + gTOSType = ""; // Set to invalid value. + gTOSReplyPump = 0; // clear the callback. + + + gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE); + gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE); + gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE); + gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE); + gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE); + gSavedSettings.declareString("VersionChannelName", "test_version_string", "", FALSE); + gSavedSettings.declareString("NextLoginLocation", "", "", FALSE); + gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE); + + credentials["first"] = "testfirst"; + credentials["last"] = "testlast"; + credentials["passwd"] = "testpass"; + + logininstance->setNotificationsInterface(¬ifications); + } + + LLLoginInstance* logininstance; + LLSD credentials; + MockNotifications notifications; + }; + + typedef test_group<lllogininstance_data> lllogininstance_group; + typedef lllogininstance_group::object lllogininstance_object; + lllogininstance_group llsdmgr("lllogininstance"); + + template<> template<> + void lllogininstance_object::test<1>() + { + set_test_name("Test Simple Success And Disconnect"); + + // Test default connect. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Dummy success response. + LLSD response; + response["state"] = "online"; + response["change"] = "connect"; + response["progress"] = 1.0; + response["transfer_rate"] = 7; + response["data"] = "test_data"; + + gTestPump.post(response); + + ensure("Success response", logininstance->authSuccess()); + ensure_equals("Test Response Data", logininstance->getResponse().asString(), "test_data"); + + logininstance->disconnect(); + + ensure_equals("Called Login Module Disconnect", gDisconnectCalled, true); + + response.clear(); + response["state"] = "offline"; + response["change"] = "disconnect"; + response["progress"] = 0.0; + response["transfer_rate"] = 0; + response["data"] = "test_data"; + + gTestPump.post(response); + + ensure("Disconnected", !(logininstance->authSuccess())); + } + + template<> template<> + void lllogininstance_object::test<2>() + { + set_test_name("Test User TOS/Critical message Interaction"); + + const std::string test_uri = "testing-uri"; + + // Test default connect. + logininstance->connect(test_uri, credentials); + + // connect should call LLLogin::connect to init gLoginURI and gLoginCreds. + ensure_equals("Default connect uri", gLoginURI, "testing-uri"); + ensure_equals("Default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false); + ensure_equals("Default for read critical", gLoginCreds["params"]["read_critical"].asBoolean(), false); + + // TOS failure response. + LLSD response; + response["state"] = "offline"; + response["change"] = "fail.login"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "tos"; + gTestPump.post(response); + + ensure_equals("TOS Dialog type", gTOSType, "message_tos"); + ensure("TOS callback given", gTOSReplyPump != 0); + gTOSReplyPump->post(false); // Call callback denying TOS. + ensure("No TOS, failed auth", logininstance->authFailure()); + + // Start again. + logininstance->connect(test_uri, credentials); + gTestPump.post(response); // Fail for tos again. + gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos. + ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true); + ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); + + // Fail connection, attempt connect again. + // The new request should have reset agree to tos to default. + response["data"]["reason"] = "key"; // bad creds. + gTestPump.post(response); + ensure("TOS auth failure", logininstance->authFailure()); + + logininstance->connect(test_uri, credentials); + ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false); + + // Critical Message failure response. + logininstance->connect(test_uri, credentials); + response["data"]["reason"] = "critical"; // Change response to "critical message" + gTestPump.post(response); + + ensure_equals("TOS Dialog type", gTOSType, "message_critical"); + ensure("TOS callback given", gTOSReplyPump != 0); + gTOSReplyPump->post(true); + ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true); + ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); + + // Fail then attempt new connection + response["data"]["reason"] = "key"; // bad creds. + gTestPump.post(response); + ensure("TOS auth failure", logininstance->authFailure()); + logininstance->connect(test_uri, credentials); + ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false); + } + + template<> template<> + void lllogininstance_object::test<3>() + { + set_test_name("Test Mandatory Update User Accepts"); + + // Part 1 - Mandatory Update, with User accepts response. + // Test connect with update needed. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Update needed failure response. + LLSD response; + response["state"] = "offline"; + response["change"] = "fail.login"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "update"; + gTestPump.post(response); + + ensure_equals("Notification added", notifications.addedCount(), 1); + + notifications.sendYesResponse(); + + ensure("Disconnected", !(logininstance->authSuccess())); + } + + template<> template<> + void lllogininstance_object::test<4>() + { + set_test_name("Test Mandatory Update User Decline"); + + // Test connect with update needed. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Update needed failure response. + LLSD response; + response["state"] = "offline"; + response["change"] = "fail.login"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "update"; + gTestPump.post(response); + + ensure_equals("Notification added", notifications.addedCount(), 1); + notifications.sendNoResponse(); + + ensure("Disconnected", !(logininstance->authSuccess())); + } + + template<> template<> + void lllogininstance_object::test<6>() + { + set_test_name("Test Optional Update User Accept"); + + // Part 3 - Mandatory Update, with bogus response. + // Test connect with update needed. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Update needed failure response. + LLSD response; + response["state"] = "offline"; + response["change"] = "fail.login"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "optional"; + gTestPump.post(response); + + ensure_equals("Notification added", notifications.addedCount(), 1); + notifications.sendYesResponse(); + + ensure("Disconnected", !(logininstance->authSuccess())); + } + + template<> template<> + void lllogininstance_object::test<7>() + { + set_test_name("Test Optional Update User Denies"); + + // Part 3 - Mandatory Update, with bogus response. + // Test connect with update needed. + logininstance->connect(credentials); + + ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); + + // Update needed failure response. + LLSD response; + response["state"] = "offline"; + response["change"] = "fail.login"; + response["progress"] = 0.0; + response["transfer_rate"] = 7; + response["data"]["reason"] = "optional"; + gTestPump.post(response); + + ensure_equals("Notification added", notifications.addedCount(), 1); + notifications.sendNoResponse(); + + // User skips, should be reconnecting. + ensure_equals("reconnect uri", gLoginURI, VIEWERLOGIN_URI); + ensure_equals("skipping optional update", gLoginCreds["params"]["skipoptional"].asBoolean(), true); + } +} diff --git a/indra/newview/tests/lltextureinfo_test.cpp b/indra/newview/tests/lltextureinfo_test.cpp new file mode 100644 index 0000000000..8dfba46262 --- /dev/null +++ b/indra/newview/tests/lltextureinfo_test.cpp @@ -0,0 +1,284 @@ +/** + * @file llwtextureinfo_test.cpp + * @author Si & Gabriel + * @date 2009-03-30 + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../lltextureinfo.h" +// Dependencies +#include "../lltextureinfodetails.cpp" + +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// 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. + + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- + +namespace tut +{ + // Test wrapper declarations + struct textureinfo_test + { + // Constructor and destructor of the test wrapper + textureinfo_test() + { + } + ~textureinfo_test() + { + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group<textureinfo_test> textureinfo_t; + typedef textureinfo_t::object textureinfo_object_t; + tut::textureinfo_t tut_textureinfo("textureinfo"); + + + // --------------------------------------------------------------------------------------- + // 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 LLTextureInfo + // --------------------------------------------------------------------------------------- + + + // Test instantiation + template<> template<> + void textureinfo_object_t::test<1>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + ensure("have we crashed?", true); + } + + // Check lltextureinfo does not contain UUIDs we haven't added + template<> template<> + void textureinfo_object_t::test<2>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + LLUUID nonExistant("3a0efa3b-84dc-4e17-9b8c-79ea028850c1"); + ensure(!tex_info.has(nonExistant)); + } + + // Check we can add a request time for a texture + template<> template<> + void textureinfo_object_t::test<3>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); + tex_info.setRequestStartTime(id, 200); + + ensure_equals(tex_info.getRequestStartTime(id), 200); + } + + // Check time for non-existant texture + template<> template<> + void textureinfo_object_t::test<4>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + LLUUID nonExistant("3a0efa3b-84dc-4e17-9b8c-79ea028850c1"); + ensure_equals(tex_info.getRequestStartTime(nonExistant), 0); + } + + // Check download complete time for non existant texture + template<> template<> + void textureinfo_object_t::test<5>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + LLUUID nonExistant("3a0efa3b-84dc-4e17-9b8c-79ea028850c1"); + ensure_equals(tex_info.getRequestCompleteTime(nonExistant), 0); + } + + // requested size is passed in correctly + template<> template<> + void textureinfo_object_t::test<6>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); + tex_info.setRequestSize(id, 600); + + ensure_equals(tex_info.getRequestSize(id), 600); + } + + // transport type is recorded correctly (http) + template<> template<> + void textureinfo_object_t::test<7>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); + tex_info.setRequestType(id, LLTextureInfoDetails::REQUEST_TYPE_HTTP); + + ensure_equals(tex_info.getRequestType(id), LLTextureInfoDetails::REQUEST_TYPE_HTTP); + } + + // transport type is recorded correctly (udp) + template<> template<> + void textureinfo_object_t::test<8>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); + tex_info.setRequestType(id, LLTextureInfoDetails::REQUEST_TYPE_UDP); + + ensure_equals(tex_info.getRequestType(id), LLTextureInfoDetails::REQUEST_TYPE_UDP); + } + + // request offset is recorded correctly + template<> template<> + void textureinfo_object_t::test<9>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3"); + tex_info.setRequestOffset(id, 1234); + + ensure_equals(tex_info.getRequestOffset(id), 1234); + } + + // ask for averages gives us correct figure + template<> template<> + void textureinfo_object_t::test<10>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + S32 requestStartTimeOne = 200; + S32 requestEndTimeOne = 400; + S32 requestSizeOne = 1024; + S32 requestSizeOneBits = requestSizeOne * 8; + LLUUID id1("10e65d70-46fd-429f-841a-bf698e9424d3"); + tex_info.setRequestStartTime(id1, requestStartTimeOne); + tex_info.setRequestSize(id1, requestSizeOne); + tex_info.setRequestType(id1, LLTextureInfoDetails::REQUEST_TYPE_HTTP); + tex_info.setRequestCompleteTimeAndLog(id1, requestEndTimeOne); + + U32 requestStartTimeTwo = 100; + U32 requestEndTimeTwo = 500; + U32 requestSizeTwo = 2048; + S32 requestSizeTwoBits = requestSizeTwo * 8; + LLUUID id2("10e65d70-46fd-429f-841a-bf698e9424d4"); + tex_info.setRequestStartTime(id2, requestStartTimeTwo); + tex_info.setRequestSize(id2, requestSizeTwo); + tex_info.setRequestType(id2, LLTextureInfoDetails::REQUEST_TYPE_HTTP); + tex_info.setRequestCompleteTimeAndLog(id2, requestEndTimeTwo); + + S32 averageBitRate = ((requestSizeOneBits/(requestEndTimeOne - requestStartTimeOne)) + + (requestSizeTwoBits/(requestEndTimeTwo - requestStartTimeTwo))) / 2; + + S32 totalBytes = requestSizeOne + requestSizeTwo; + + LLSD results = tex_info.getAverages(); + ensure_equals("is average bits per second correct", results["bits_per_second"].asInteger(), averageBitRate); + ensure_equals("is total bytes is correct", results["bytes_downloaded"].asInteger(), totalBytes); + ensure_equals("is transport correct", results["transport"].asString(), std::string("HTTP")); + } + + // make sure averages cleared when reset is called + template<> template<> + void textureinfo_object_t::test<11>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + S32 requestStartTimeOne = 200; + S32 requestEndTimeOne = 400; + S32 requestSizeOne = 1024; + LLUUID id1("10e65d70-46fd-429f-841a-bf698e9424d3"); + tex_info.setRequestStartTime(id1, requestStartTimeOne); + tex_info.setRequestSize(id1, requestSizeOne); + tex_info.setRequestType(id1, LLTextureInfoDetails::REQUEST_TYPE_HTTP); + tex_info.setRequestCompleteTimeAndLog(id1, requestEndTimeOne); + + tex_info.getAverages(); + tex_info.reset(); + LLSD results = tex_info.getAverages(); + ensure_equals("is average bits per second correct", results["bits_per_second"].asInteger(), 0); + ensure_equals("is total bytes is correct", results["bytes_downloaded"].asInteger(), 0); + ensure_equals("is transport correct", results["transport"].asString(), std::string("NONE")); + } + + // make sure map item removed when expired + template<> template<> + void textureinfo_object_t::test<12>() + { + LLTextureInfo tex_info; + tex_info.setUpLogging(true, true); + + S32 requestStartTimeOne = 200; + S32 requestEndTimeOne = 400; + S32 requestSizeOne = 1024; + LLUUID id1("10e65d70-46fd-429f-841a-bf698e9424d3"); + tex_info.setRequestStartTime(id1, requestStartTimeOne); + tex_info.setRequestSize(id1, requestSizeOne); + tex_info.setRequestType(id1, LLTextureInfoDetails::REQUEST_TYPE_HTTP); + + ensure_equals("map item created", tex_info.getTextureInfoMapSize(), 1); + + tex_info.setRequestCompleteTimeAndLog(id1, requestEndTimeOne); + + ensure_equals("map item removed when consumed", tex_info.getTextureInfoMapSize(), 0); + } +} + diff --git a/indra/newview/tests/lltextureinfodetails_test.cpp b/indra/newview/tests/lltextureinfodetails_test.cpp new file mode 100644 index 0000000000..aa2697fb8e --- /dev/null +++ b/indra/newview/tests/lltextureinfodetails_test.cpp @@ -0,0 +1,98 @@ +/** + * @file llwtextureinfodetails_test.cpp + * @author Si & Gabriel + * @date 2009-03-30 + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../lltextureinfodetails.h" +// Dependencies + +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// 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. + + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- + +namespace tut +{ + // Test wrapper declarations + struct textureinfodetails_test + { + // Constructor and destructor of the test wrapper + textureinfodetails_test() + { + } + ~textureinfodetails_test() + { + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group<textureinfodetails_test> textureinfodetails_t; + typedef textureinfodetails_t::object textureinfodetails_object_t; + tut::textureinfodetails_t tut_textureinfodetails("textureinfodetails"); + + + // --------------------------------------------------------------------------------------- + // 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 LLTextureInfo + // --------------------------------------------------------------------------------------- + + + // Test instantiation + template<> template<> + void textureinfodetails_object_t::test<1>() + { + ensure("have we crashed?", true); + } +} diff --git a/indra/newview/tests/lltexturestatsuploader_test.cpp b/indra/newview/tests/lltexturestatsuploader_test.cpp new file mode 100644 index 0000000000..77a3e2c3d8 --- /dev/null +++ b/indra/newview/tests/lltexturestatsuploader_test.cpp @@ -0,0 +1,156 @@ +/** + * @file lltexturestatsuploader_test.cpp + * @author Si + * @date 2009-05-27 + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../lltexturestatsuploader.h" +// Dependencies + +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// 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. + +#include "boost/intrusive_ptr.hpp" +void boost::intrusive_ptr_add_ref(LLCurl::Responder*){} +void boost::intrusive_ptr_release(LLCurl::Responder* p){} +const F32 HTTP_REQUEST_EXPIRY_SECS = 0.0f; + +static std::string most_recent_url; +static LLSD most_recent_body; + +void LLHTTPClient::post( + const std::string& url, + const LLSD& body, + ResponderPtr, + const LLSD& headers, + const F32 timeout) +{ + // set some sensor code + most_recent_url = url; + most_recent_body = body; + return; +} + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- + +namespace tut +{ + // Test wrapper declarations + struct texturestatsuploader_test + { + // Constructor and destructor of the test wrapper + texturestatsuploader_test() + { + most_recent_url = "some sort of default text that should never match anything the tests are expecting!"; + LLSD blank_llsd; + most_recent_body = blank_llsd; + } + ~texturestatsuploader_test() + { + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group<texturestatsuploader_test> texturestatsuploader_t; + typedef texturestatsuploader_t::object texturestatsuploader_object_t; + tut::texturestatsuploader_t tut_texturestatsuploader("texturestatsuploader"); + + + // --------------------------------------------------------------------------------------- + // 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 LLTextureInfo + // --------------------------------------------------------------------------------------- + + + // Test instantiation + template<> template<> + void texturestatsuploader_object_t::test<1>() + { + LLTextureStatsUploader tsu; + llinfos << &tsu << llendl; + ensure("have we crashed?", true); + } + + // does it call out to the provided url if we ask it to? + template<> template<> + void texturestatsuploader_object_t::test<2>() + { + LLTextureStatsUploader tsu; + std::string url = "http://blahblahblah"; + LLSD texture_stats; + tsu.uploadStatsToSimulator(url, texture_stats); + ensure_equals("did the right url get called?", most_recent_url, url); + ensure_equals("did the right body get sent?", most_recent_body, texture_stats); + } + + // does it not call out to the provided url if we send it an ungranted cap? + template<> template<> + void texturestatsuploader_object_t::test<3>() + { + LLTextureStatsUploader tsu; + + // this url left intentionally blank to mirror + // not getting a cap in the caller. + std::string url_for_ungranted_cap = ""; + + LLSD texture_stats; + std::string most_recent_url_before_test = most_recent_url; + tsu.uploadStatsToSimulator(url_for_ungranted_cap, texture_stats); + + ensure_equals("hopefully no url got called!", most_recent_url, most_recent_url_before_test); + } + + // does it call out if the data is empty? + // should it even do that? +} + diff --git a/indra/newview/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp new file mode 100644 index 0000000000..56cf86f6df --- /dev/null +++ b/indra/newview/tests/llworldmap_test.cpp @@ -0,0 +1,523 @@ +/** + * @file llworldmap_test.cpp + * @author Merov Linden + * @date 2009-03-09 + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../llworldmap.h" +// Dependencies +#include "../llviewerimagelist.h" +#include "../llworldmapmessage.h" +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// 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. + +// Stub image calls +LLViewerImageList::LLViewerImageList() { } +LLViewerImageList::~LLViewerImageList() { } +LLViewerImageList gImageList; +LLViewerImage* LLViewerImageList::getImage(const LLUUID &image_id, + BOOL usemipmaps, + BOOL level_immediate, + LLGLint internal_format, + LLGLenum primary_format, + LLHost request_from_host) +{ return NULL; } +void LLViewerImage::setBoostLevel(S32 level) { } +void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode) { } + +// Stub related map calls +LLWorldMapMessage::LLWorldMapMessage() { } +LLWorldMapMessage::~LLWorldMapMessage() { } +void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) { } +void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) { } +LLWorldMipmap::LLWorldMipmap() { } +LLWorldMipmap::~LLWorldMipmap() { } +void LLWorldMipmap::reset() { } +void LLWorldMipmap::dropBoostLevels() { } +void LLWorldMipmap::equalizeBoostLevels() { } +LLPointer<LLViewerImage> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load) +{ return NULL; } + +// Stub other stuff +BOOL gPacificDaylightTime; + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- + +const F32 X_WORLD_TEST = 1000.0f * REGION_WIDTH_METERS; +const F32 Y_WORLD_TEST = 2000.0f * REGION_WIDTH_METERS; +const F32 Z_WORLD_TEST = 240.0f; +const std::string ITEM_NAME_TEST = "Item Foo"; +const std::string TOOLTIP_TEST = "Tooltip Foo"; + +const std::string SIM_NAME_TEST = "Sim Foo"; + +namespace tut +{ + // Test wrapper declarations + struct iteminfo_test + { + // Instance to be tested + LLItemInfo* mItem; + + // Constructor and destructor of the test wrapper + iteminfo_test() + { + LLUUID id; + mItem = new LLItemInfo(X_WORLD_TEST, Y_WORLD_TEST, ITEM_NAME_TEST, id); + } + ~iteminfo_test() + { + delete mItem; + } + }; + + struct siminfo_test + { + // Instance to be tested + LLSimInfo* mSim; + + // Constructor and destructor of the test wrapper + siminfo_test() + { + U64 handle = to_region_handle_global(X_WORLD_TEST, Y_WORLD_TEST); + mSim = new LLSimInfo(handle); + } + ~siminfo_test() + { + delete mSim; + } + }; + + struct worldmap_test + { + // Instance to be tested + LLWorldMap* mWorld; + + // Constructor and destructor of the test wrapper + worldmap_test() + { + mWorld = LLWorldMap::getInstance(); + } + ~worldmap_test() + { + mWorld = NULL; + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group<iteminfo_test> iteminfo_t; + typedef iteminfo_t::object iteminfo_object_t; + tut::iteminfo_t tut_iteminfo("iteminfo"); + + typedef test_group<siminfo_test> siminfo_t; + typedef siminfo_t::object siminfo_object_t; + tut::siminfo_t tut_siminfo("siminfo"); + + typedef test_group<worldmap_test> worldmap_t; + typedef worldmap_t::object worldmap_object_t; + tut::worldmap_t tut_worldmap("worldmap"); + + // --------------------------------------------------------------------------------------- + // 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 LLItemInfo interface + // --------------------------------------------------------------------------------------- + template<> template<> + void iteminfo_object_t::test<1>() + { + // Test 1 : setCount() / getCount() + mItem->setCount(10); + ensure("LLItemInfo::setCount() test failed", mItem->getCount() == 10); + // Test 2 : setTooltip() / getToolTip() + std::string tooltip = TOOLTIP_TEST; + mItem->setTooltip(tooltip); + ensure("LLItemInfo::setTooltip() test failed", mItem->getToolTip() == TOOLTIP_TEST); + // Test 3 : setElevation() / getGlobalPosition() + mItem->setElevation(Z_WORLD_TEST); + LLVector3d pos = mItem->getGlobalPosition(); + LLVector3d ref(X_WORLD_TEST, Y_WORLD_TEST, Z_WORLD_TEST); + ensure("LLItemInfo::getGlobalPosition() test failed", pos == ref); + // Test 4 : getName() + std::string name = mItem->getName(); + ensure("LLItemInfo::getName() test failed", name == ITEM_NAME_TEST); + // Test 5 : isName() + ensure("LLItemInfo::isName() test failed", mItem->isName(name)); + // Test 6 : getUUID() + LLUUID id; + ensure("LLItemInfo::getUUID() test failed", mItem->getUUID() == id); + // Test 7 : getRegionHandle() + U64 handle = to_region_handle_global(X_WORLD_TEST, Y_WORLD_TEST); + ensure("LLItemInfo::getRegionHandle() test failed", mItem->getRegionHandle() == handle); + } + // --------------------------------------------------------------------------------------- + // Test the LLSimInfo interface + // --------------------------------------------------------------------------------------- + // Test Setters and Accessors methods + template<> template<> + void siminfo_object_t::test<1>() + { + // Test 1 : setName() / getName() + std::string name = SIM_NAME_TEST; + mSim->setName(name); + ensure("LLSimInfo::setName() test failed", mSim->getName() == SIM_NAME_TEST); + // Test 2 : isName() + ensure("LLSimInfo::isName() test failed", mSim->isName(name)); + // Test 3 : getGlobalPos() + LLVector3 local; + LLVector3d ref(X_WORLD_TEST, Y_WORLD_TEST, 0.0f); + LLVector3d pos = mSim->getGlobalPos(local); + ensure("LLSimInfo::getGlobalPos() test failed", pos == ref); + // Test 4 : getGlobalOrigin() + pos = mSim->getGlobalOrigin(); + ensure("LLSimInfo::getGlobalOrigin() test failed", pos == ref); + // Test 5 : clearImage() + try { + mSim->clearImage(); + } catch (...) { + fail("LLSimInfo::clearImage() test failed"); + } + // Test 6 : dropImagePriority() + try { + mSim->dropImagePriority(); + } catch (...) { + fail("LLSimInfo::dropImagePriority() test failed"); + } + // Test 7 : updateAgentCount() + try { + mSim->updateAgentCount(0.0f); + } catch (...) { + fail("LLSimInfo::updateAgentCount() test failed"); + } + // Test 8 : getAgentCount() + S32 agents = mSim->getAgentCount(); + ensure("LLSimInfo::getAgentCount() test failed", agents == 0); + // Test 9 : setLandForSaleImage() / getLandForSaleImage() + LLUUID id; + mSim->setLandForSaleImage(id); + LLPointer<LLViewerImage> image = mSim->getLandForSaleImage(); + ensure("LLSimInfo::getLandForSaleImage() test failed", image.isNull()); + // Test 10 : isPG() + mSim->setAccess(SIM_ACCESS_PG); + ensure("LLSimInfo::isPG() test failed", mSim->isPG()); + // Test 11 : isDown() + mSim->setAccess(SIM_ACCESS_DOWN); + ensure("LLSimInfo::isDown() test failed", mSim->isDown()); + // Test 12 : Access strings can't be accessed from unit test... + //ensure("LLSimInfo::getAccessString() test failed", mSim->getAccessString() == "Offline"); + // Test 13 : Region strings can't be accessed from unit test... + //mSim->setRegionFlags(REGION_FLAGS_SANDBOX); + //ensure("LLSimInfo::setRegionFlags() test failed", mSim->getFlagsString() == "Sandbox"); + } + // Test management of LLInfoItem lists + template<> template<> + void siminfo_object_t::test<2>() + { + // Test 14 : clearItems() + try { + mSim->clearItems(); + } catch (...) { + fail("LLSimInfo::clearItems() at init test failed"); + } + + // Test 15 : Verify that all the lists are empty + LLSimInfo::item_info_list_t list; + list = mSim->getTeleHub(); + ensure("LLSimInfo::getTeleHub() empty at init test failed", list.empty()); + list = mSim->getInfoHub(); + ensure("LLSimInfo::getInfoHub() empty at init test failed", list.empty()); + list = mSim->getPGEvent(); + ensure("LLSimInfo::getPGEvent() empty at init test failed", list.empty()); + list = mSim->getMatureEvent(); + ensure("LLSimInfo::getMatureEvent() empty at init test failed", list.empty()); + list = mSim->getLandForSale(); + ensure("LLSimInfo::getLandForSale() empty at init test failed", list.empty()); + list = mSim->getAgentLocation(); + ensure("LLSimInfo::getAgentLocation() empty at init test failed", list.empty()); + + // Create an item to be inserted + LLUUID id; + LLItemInfo item(X_WORLD_TEST, Y_WORLD_TEST, ITEM_NAME_TEST, id); + + // Insert the item in each list + mSim->insertTeleHub(item); + mSim->insertInfoHub(item); + mSim->insertPGEvent(item); + mSim->insertMatureEvent(item); + mSim->insertLandForSale(item); + mSim->insertAgentLocation(item); + + // Test 16 : Verify that the lists contain 1 item each + list = mSim->getTeleHub(); + ensure("LLSimInfo::insertTeleHub() test failed", list.size() == 1); + list = mSim->getInfoHub(); + ensure("LLSimInfo::insertInfoHub() test failed", list.size() == 1); + list = mSim->getPGEvent(); + ensure("LLSimInfo::insertPGEvent() test failed", list.size() == 1); + list = mSim->getMatureEvent(); + ensure("LLSimInfo::insertMatureEvent() test failed", list.size() == 1); + list = mSim->getLandForSale(); + ensure("LLSimInfo::insertLandForSale() test failed", list.size() == 1); + list = mSim->getAgentLocation(); + ensure("LLSimInfo::insertAgentLocation() test failed", list.size() == 1); + + // Test 17 : clearItems() + try { + mSim->clearItems(); + } catch (...) { + fail("LLSimInfo::clearItems() at end test failed"); + } + + // Test 18 : Verify that all the lists are empty again... *except* agent which is persisted!! (on purpose) + list = mSim->getTeleHub(); + ensure("LLSimInfo::getTeleHub() empty after clear test failed", list.empty()); + list = mSim->getInfoHub(); + ensure("LLSimInfo::getInfoHub() empty after clear test failed", list.empty()); + list = mSim->getPGEvent(); + ensure("LLSimInfo::getPGEvent() empty after clear test failed", list.empty()); + list = mSim->getMatureEvent(); + ensure("LLSimInfo::getMatureEvent() empty after clear test failed", list.empty()); + list = mSim->getLandForSale(); + ensure("LLSimInfo::getLandForSale() empty after clear test failed", list.empty()); + list = mSim->getAgentLocation(); + ensure("LLSimInfo::getAgentLocation() empty after clear test failed", list.size() == 1); + } + + // --------------------------------------------------------------------------------------- + // Test the LLWorldMap interface + // --------------------------------------------------------------------------------------- + // Test Setters and Accessors methods + template<> template<> + void worldmap_object_t::test<1>() + { + // Test 1 : reset() + try { + mWorld->reset(); + } catch (...) { + fail("LLWorldMap::reset() at init test failed"); + } + // Test 2 : clearImageRefs() + try { + mWorld->clearImageRefs(); + } catch (...) { + fail("LLWorldMap::clearImageRefs() test failed"); + } + // Test 3 : dropImagePriorities() + try { + mWorld->dropImagePriorities(); + } catch (...) { + fail("LLWorldMap::dropImagePriorities() test failed"); + } + // Test 4 : reloadItems() + try { + mWorld->reloadItems(true); + } catch (...) { + fail("LLWorldMap::reloadItems() test failed"); + } + // Test 5 : updateRegions() + try { + mWorld->updateRegions(1000, 1000, 1004, 1004); + } catch (...) { + fail("LLWorldMap::updateRegions() test failed"); + } + // Test 6 : equalizeBoostLevels() + try { + mWorld->equalizeBoostLevels(); + } catch (...) { + fail("LLWorldMap::equalizeBoostLevels() test failed"); + } + // Test 7 : getObjectsTile() + try { + LLPointer<LLViewerImage> image = mWorld->getObjectsTile((U32)(X_WORLD_TEST/REGION_WIDTH_METERS), (U32)(Y_WORLD_TEST/REGION_WIDTH_METERS), 1); + ensure("LLWorldMap::getObjectsTile() failed", image.isNull()); + } catch (...) { + fail("LLWorldMap::getObjectsTile() test failed with exception"); + } + } + // Test management of LLSimInfo lists + template<> template<> + void worldmap_object_t::test<2>() + { + // Test 8 : reset() + try { + mWorld->reset(); + } catch (...) { + fail("LLWorldMap::reset() at init test failed"); + } + + // Test 9 : Verify that all the region list is empty + LLWorldMap::sim_info_map_t list; + list = mWorld->getRegionMap(); + ensure("LLWorldMap::getRegionMap() empty at init test failed", list.empty()); + + // Test 10 : Insert a region + bool success; + LLUUID id; + std::string name_sim = SIM_NAME_TEST; + success = mWorld->insertRegion( U32(X_WORLD_TEST), + U32(Y_WORLD_TEST), + name_sim, + id, + SIM_ACCESS_PG, + REGION_FLAGS_SANDBOX); + list = mWorld->getRegionMap(); + ensure("LLWorldMap::insertRegion() failed", success && (list.size() == 1)); + + // Test 11 : Insert an item in the same region -> number of regions doesn't increase + std::string name_item = ITEM_NAME_TEST; + success = mWorld->insertItem( U32(X_WORLD_TEST + REGION_WIDTH_METERS/2), + U32(Y_WORLD_TEST + REGION_WIDTH_METERS/2), + name_item, + id, + MAP_ITEM_LAND_FOR_SALE, + 0, 0); + list = mWorld->getRegionMap(); + ensure("LLWorldMap::insertItem() in existing region failed", success && (list.size() == 1)); + + // Test 12 : Insert an item in another region -> number of regions increases + success = mWorld->insertItem( U32(X_WORLD_TEST + REGION_WIDTH_METERS*2), + U32(Y_WORLD_TEST + REGION_WIDTH_METERS*2), + name_item, + id, + MAP_ITEM_LAND_FOR_SALE, + 0, 0); + list = mWorld->getRegionMap(); + ensure("LLWorldMap::insertItem() in unexisting region failed", success && (list.size() == 2)); + + // Test 13 : simInfoFromPosGlobal() in region + LLVector3d pos1( X_WORLD_TEST + REGION_WIDTH_METERS*2 + REGION_WIDTH_METERS/2, + Y_WORLD_TEST + REGION_WIDTH_METERS*2 + REGION_WIDTH_METERS/2, + 0.0f); + LLSimInfo* sim; + sim = mWorld->simInfoFromPosGlobal(pos1); + ensure("LLWorldMap::simInfoFromPosGlobal() test on existing region failed", sim != NULL); + + // Test 14 : simInfoFromPosGlobal() outside region + LLVector3d pos2( X_WORLD_TEST + REGION_WIDTH_METERS*4 + REGION_WIDTH_METERS/2, + Y_WORLD_TEST + REGION_WIDTH_METERS*4 + REGION_WIDTH_METERS/2, + 0.0f); + sim = mWorld->simInfoFromPosGlobal(pos2); + ensure("LLWorldMap::simInfoFromPosGlobal() test outside region failed", sim == NULL); + + // Test 15 : simInfoFromName() + sim = mWorld->simInfoFromName(name_sim); + ensure("LLWorldMap::simInfoFromName() test on existing region failed", sim != NULL); + + // Test 16 : simInfoFromHandle() + U64 handle = to_region_handle_global(X_WORLD_TEST, Y_WORLD_TEST); + sim = mWorld->simInfoFromHandle(handle); + ensure("LLWorldMap::simInfoFromHandle() test on existing region failed", sim != NULL); + + // Test 17 : simNameFromPosGlobal() + LLVector3d pos3( X_WORLD_TEST + REGION_WIDTH_METERS/2, + Y_WORLD_TEST + REGION_WIDTH_METERS/2, + 0.0f); + success = mWorld->simNameFromPosGlobal(pos3, name_sim); + ensure("LLWorldMap::simNameFromPosGlobal() test on existing region failed", success && (name_sim == SIM_NAME_TEST)); + + // Test 18 : reset() + try { + mWorld->reset(); + } catch (...) { + fail("LLWorldMap::reset() at end test failed"); + } + + // Test 19 : Verify that all the region list is empty + list = mWorld->getRegionMap(); + ensure("LLWorldMap::getRegionMap() empty at end test failed", list.empty()); + } + // Test tracking + template<> template<> + void worldmap_object_t::test<3>() + { + // Point to track + LLVector3d pos( X_WORLD_TEST + REGION_WIDTH_METERS/2, Y_WORLD_TEST + REGION_WIDTH_METERS/2, Z_WORLD_TEST); + + // Test 20 : no tracking + mWorld->cancelTracking(); + ensure("LLWorldMap::cancelTracking() at begin test failed", mWorld->isTracking() == false); + + // Test 21 : set tracking + mWorld->setTracking(pos); + ensure("LLWorldMap::setTracking() failed", mWorld->isTracking() && !mWorld->isTrackingValidLocation()); + + // Test 22 : set click and commit flags + mWorld->setTrackingDoubleClick(); + ensure("LLWorldMap::setTrackingDoubleClick() failed", mWorld->isTrackingDoubleClick()); + mWorld->setTrackingCommit(); + ensure("LLWorldMap::setTrackingCommit() failed", mWorld->isTrackingCommit()); + + // Test 23 : in rectangle test + bool inRect = mWorld->isTrackingInRectangle( X_WORLD_TEST, Y_WORLD_TEST, + X_WORLD_TEST + REGION_WIDTH_METERS, + Y_WORLD_TEST + REGION_WIDTH_METERS); + ensure("LLWorldMap::isTrackingInRectangle() in rectangle failed", inRect); + inRect = mWorld->isTrackingInRectangle( X_WORLD_TEST + REGION_WIDTH_METERS, + Y_WORLD_TEST + REGION_WIDTH_METERS, + X_WORLD_TEST + 2 * REGION_WIDTH_METERS, + Y_WORLD_TEST + 2 * REGION_WIDTH_METERS); + ensure("LLWorldMap::isTrackingInRectangle() outside rectangle failed", !inRect); + + // Test 24 : set tracking to valid and invalid + mWorld->setTrackingValid(); + ensure("LLWorldMap::setTrackingValid() failed", mWorld->isTrackingValidLocation() && !mWorld->isTrackingInvalidLocation()); + mWorld->setTrackingInvalid(); + ensure("LLWorldMap::setTrackingInvalid() failed", !mWorld->isTrackingValidLocation() && mWorld->isTrackingInvalidLocation()); + + // Test 25 : getTrackedPositionGlobal() + LLVector3d res = mWorld->getTrackedPositionGlobal(); + ensure("LLWorldMap::getTrackedPositionGlobal() failed", res == pos); + + // Test 26 : reset tracking + mWorld->cancelTracking(); + ensure("LLWorldMap::cancelTracking() at end test failed", mWorld->isTracking() == false); + } +} diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp new file mode 100644 index 0000000000..9938175c55 --- /dev/null +++ b/indra/newview/tests/llworldmipmap_test.cpp @@ -0,0 +1,176 @@ +/** + * @file llworldmipmap_test.cpp + * @author Merov Linden + * @date 2009-02-03 + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Precompiled header: almost always required for newview cpp files +#include "../llviewerprecompiledheaders.h" +// Class to test +#include "../llworldmipmap.h" +// Dependencies +#include "../llviewerimagelist.h" +// Tut header +#include "../test/lltut.h" + +// ------------------------------------------------------------------------------------------- +// Stubbing: Declarations required to link and run the class being tested +// 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. + +LLViewerImageList::LLViewerImageList() { } +LLViewerImageList::~LLViewerImageList() { } + +LLViewerImageList gImageList; + +LLViewerImage* LLViewerImageList::getImageFromUrl(const std::string& url, + BOOL usemipmaps, + BOOL level_immediate, + LLGLint internal_format, + LLGLenum primary_format, + const LLUUID& force_id) +{ return NULL; } +void LLViewerImage::setBoostLevel(S32 level) { } + +// End Stubbing +// ------------------------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ + // Test wrapper declaration + struct worldmipmap_test + { + // Derived test class + class LLTestWorldMipmap : public LLWorldMipmap + { + // Put here stubbs of virtual methods we shouldn't call all the way down + }; + // Instance to be tested + LLTestWorldMipmap* mMap; + + // Constructor and destructor of the test wrapper + worldmipmap_test() + { + mMap = new LLTestWorldMipmap; + } + ~worldmipmap_test() + { + delete mMap; + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group<worldmipmap_test> worldmipmap_t; + typedef worldmipmap_t::object worldmipmap_object_t; + tut::worldmipmap_t tut_worldmipmap("worldmipmap"); + + // --------------------------------------------------------------------------------------- + // 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 static methods + // Test 1 : scaleToLevel() + template<> template<> + void worldmipmap_object_t::test<1>() + { + S32 level = mMap->scaleToLevel(0.0); + ensure("scaleToLevel() test 1 failed", level == LLWorldMipmap::MAP_LEVELS); + level = mMap->scaleToLevel(LLWorldMipmap::MAP_TILE_SIZE); + ensure("scaleToLevel() test 2 failed", level == 1); + level = mMap->scaleToLevel(10 * LLWorldMipmap::MAP_TILE_SIZE); + ensure("scaleToLevel() test 3 failed", level == 1); + } + // Test 2 : globalToMipmap() + template<> template<> + void worldmipmap_object_t::test<2>() + { + U32 grid_x, grid_y; + mMap->globalToMipmap(1000.f*REGION_WIDTH_METERS, 1000.f*REGION_WIDTH_METERS, 1, &grid_x, &grid_y); + ensure("globalToMipmap() test 1 failed", (grid_x == 1000) && (grid_y == 1000)); + mMap->globalToMipmap(0.0, 0.0, LLWorldMipmap::MAP_LEVELS, &grid_x, &grid_y); + ensure("globalToMipmap() test 2 failed", (grid_x == 0) && (grid_y == 0)); + } + // Test 3 : getObjectsTile() + template<> template<> + void worldmipmap_object_t::test<3>() + { + // Depends on some inline methods in LLViewerImage... Thinking about how to make this work + // LLPointer<LLViewerImage> img = mMap->getObjectsTile(0, 0, 1); + // ensure("getObjectsTile() test failed", img.isNull()); + } + // Test 4 : equalizeBoostLevels() + template<> template<> + void worldmipmap_object_t::test<4>() + { + try + { + mMap->equalizeBoostLevels(); + } + catch (...) + { + fail("equalizeBoostLevels() test failed"); + } + } + // Test 5 : dropBoostLevels() + template<> template<> + void worldmipmap_object_t::test<5>() + { + try + { + mMap->dropBoostLevels(); + } + catch (...) + { + fail("dropBoostLevels() test failed"); + } + } + // Test 6 : reset() + template<> template<> + void worldmipmap_object_t::test<6>() + { + try + { + mMap->reset(); + } + catch (...) + { + fail("reset() test failed"); + } + } +} diff --git a/indra/tools/vstool/README.txt b/indra/tools/vstool/README.txt index e419180031..6f64aa41df 100644 --- a/indra/tools/vstool/README.txt +++ b/indra/tools/vstool/README.txt @@ -1,9 +1,9 @@ -VSTool is a command line utility to manipulate VisualStudio settings.
-
-The windows cmake project configuration uses VSTool.exe
-
-A handy upgrade:
- figure out how to make cmake build this csharp app
- - or write the app using script (jscript?!?) so it doesn't need to be built.
-
-
+VSTool is a command line utility to manipulate VisualStudio settings. + +The windows cmake project configuration uses VSTool.exe + +A handy upgrade: + figure out how to make cmake build this csharp app + - or write the app using script (jscript?!?) so it doesn't need to be built. + + diff --git a/indra/tools/vstool/VSTool.csproj b/indra/tools/vstool/VSTool.csproj index 24f1031f81..5d8764b6bf 100644 --- a/indra/tools/vstool/VSTool.csproj +++ b/indra/tools/vstool/VSTool.csproj @@ -1,95 +1,95 @@ -<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <ProjectType>Local</ProjectType>
- <ProductVersion>8.0.50727</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{96943E2D-1373-4617-A117-D0F997A94919}</ProjectGuid>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ApplicationIcon>
- </ApplicationIcon>
- <AssemblyKeyContainerName>
- </AssemblyKeyContainerName>
- <AssemblyName>VSTool</AssemblyName>
- <AssemblyOriginatorKeyFile>
- </AssemblyOriginatorKeyFile>
- <DefaultClientScript>JScript</DefaultClientScript>
- <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
- <DefaultTargetSchema>IE50</DefaultTargetSchema>
- <DelaySign>false</DelaySign>
- <OutputType>Exe</OutputType>
- <RootNamespace>VSTool</RootNamespace>
- <RunPostBuildEvent>Always</RunPostBuildEvent>
- <StartupObject>VSTool.VSToolMain</StartupObject>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <UpgradeBackupLocation>
- </UpgradeBackupLocation>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <OutputPath>.\</OutputPath>
- <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
- <BaseAddress>285212672</BaseAddress>
- <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
- <ConfigurationOverrideFile>
- </ConfigurationOverrideFile>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DocumentationFile>
- </DocumentationFile>
- <DebugSymbols>true</DebugSymbols>
- <FileAlignment>4096</FileAlignment>
- <NoStdLib>false</NoStdLib>
- <NoWarn>
- </NoWarn>
- <Optimize>false</Optimize>
- <RegisterForComInterop>false</RegisterForComInterop>
- <RemoveIntegerChecks>false</RemoveIntegerChecks>
- <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
- <WarningLevel>4</WarningLevel>
- <DebugType>full</DebugType>
- <ErrorReport>prompt</ErrorReport>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <OutputPath>.\</OutputPath>
- <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
- <BaseAddress>285212672</BaseAddress>
- <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
- <ConfigurationOverrideFile>
- </ConfigurationOverrideFile>
- <DefineConstants>TRACE</DefineConstants>
- <DocumentationFile>
- </DocumentationFile>
- <DebugSymbols>false</DebugSymbols>
- <FileAlignment>4096</FileAlignment>
- <NoStdLib>false</NoStdLib>
- <NoWarn>
- </NoWarn>
- <Optimize>true</Optimize>
- <RegisterForComInterop>false</RegisterForComInterop>
- <RemoveIntegerChecks>false</RemoveIntegerChecks>
- <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
- <WarningLevel>4</WarningLevel>
- <DebugType>none</DebugType>
- <ErrorReport>prompt</ErrorReport>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System">
- <Name>System</Name>
- </Reference>
- <Reference Include="System.Data">
- <Name>System.Data</Name>
- </Reference>
- </ItemGroup>
- <ItemGroup>
- <Compile Include="main.cs">
- <SubType>Code</SubType>
- </Compile>
- </ItemGroup>
- <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
- <PropertyGroup>
- <PreBuildEvent>
- </PreBuildEvent>
- <PostBuildEvent>
- </PostBuildEvent>
- </PropertyGroup>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <ProjectType>Local</ProjectType> + <ProductVersion>8.0.50727</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{96943E2D-1373-4617-A117-D0F997A94919}</ProjectGuid> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ApplicationIcon> + </ApplicationIcon> + <AssemblyKeyContainerName> + </AssemblyKeyContainerName> + <AssemblyName>VSTool</AssemblyName> + <AssemblyOriginatorKeyFile> + </AssemblyOriginatorKeyFile> + <DefaultClientScript>JScript</DefaultClientScript> + <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout> + <DefaultTargetSchema>IE50</DefaultTargetSchema> + <DelaySign>false</DelaySign> + <OutputType>Exe</OutputType> + <RootNamespace>VSTool</RootNamespace> + <RunPostBuildEvent>Always</RunPostBuildEvent> + <StartupObject>VSTool.VSToolMain</StartupObject> + <FileUpgradeFlags> + </FileUpgradeFlags> + <UpgradeBackupLocation> + </UpgradeBackupLocation> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <OutputPath>.\</OutputPath> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + <BaseAddress>285212672</BaseAddress> + <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> + <ConfigurationOverrideFile> + </ConfigurationOverrideFile> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DocumentationFile> + </DocumentationFile> + <DebugSymbols>true</DebugSymbols> + <FileAlignment>4096</FileAlignment> + <NoStdLib>false</NoStdLib> + <NoWarn> + </NoWarn> + <Optimize>false</Optimize> + <RegisterForComInterop>false</RegisterForComInterop> + <RemoveIntegerChecks>false</RemoveIntegerChecks> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <WarningLevel>4</WarningLevel> + <DebugType>full</DebugType> + <ErrorReport>prompt</ErrorReport> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <OutputPath>.\</OutputPath> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + <BaseAddress>285212672</BaseAddress> + <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> + <ConfigurationOverrideFile> + </ConfigurationOverrideFile> + <DefineConstants>TRACE</DefineConstants> + <DocumentationFile> + </DocumentationFile> + <DebugSymbols>false</DebugSymbols> + <FileAlignment>4096</FileAlignment> + <NoStdLib>false</NoStdLib> + <NoWarn> + </NoWarn> + <Optimize>true</Optimize> + <RegisterForComInterop>false</RegisterForComInterop> + <RemoveIntegerChecks>false</RemoveIntegerChecks> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <WarningLevel>4</WarningLevel> + <DebugType>none</DebugType> + <ErrorReport>prompt</ErrorReport> + </PropertyGroup> + <ItemGroup> + <Reference Include="System"> + <Name>System</Name> + </Reference> + <Reference Include="System.Data"> + <Name>System.Data</Name> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="main.cs"> + <SubType>Code</SubType> + </Compile> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <PropertyGroup> + <PreBuildEvent> + </PreBuildEvent> + <PostBuildEvent> + </PostBuildEvent> + </PropertyGroup> </Project>
\ No newline at end of file diff --git a/indra/tools/vstool/VSTool.sln b/indra/tools/vstool/VSTool.sln index 8859671802..543a0a2efc 100644 --- a/indra/tools/vstool/VSTool.sln +++ b/indra/tools/vstool/VSTool.sln @@ -1,19 +1,19 @@ -Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTool", "VSTool.csproj", "{96943E2D-1373-4617-A117-D0F997A94919}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTool", "VSTool.csproj", "{96943E2D-1373-4617-A117-D0F997A94919}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/indra/tools/vstool/main.cs b/indra/tools/vstool/main.cs index cc268d59d9..5c41c916e2 100644 --- a/indra/tools/vstool/main.cs +++ b/indra/tools/vstool/main.cs @@ -1,711 +1,711 @@ -// Code about getting running instances visual studio
-// was borrowed from
-// http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx
-
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.ComTypes;
-using Microsoft.CSharp;
-
-namespace VSTool
-{
- // The MessageFilter class comes from:
- // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx
- // It allows vstool to get timing error messages from
- // visualstudio and handle them.
- public class MessageFilter : IOleMessageFilter
- {
- //
- // Class containing the IOleMessageFilter
- // thread error-handling functions.
-
- // Start the filter.
- public static void Register()
- {
- IOleMessageFilter newFilter = new MessageFilter();
- IOleMessageFilter oldFilter = null;
- CoRegisterMessageFilter(newFilter, out oldFilter);
- }
-
- // Done with the filter, close it.
- public static void Revoke()
- {
- IOleMessageFilter oldFilter = null;
- CoRegisterMessageFilter(null, out oldFilter);
- }
-
- //
- // IOleMessageFilter functions.
- // Handle incoming thread requests.
- int IOleMessageFilter.HandleInComingCall(int dwCallType,
- System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr
- lpInterfaceInfo)
- {
- //Return the flag SERVERCALL_ISHANDLED.
- return 0;
- }
-
- // Thread call was rejected, so try again.
- int IOleMessageFilter.RetryRejectedCall(System.IntPtr
- hTaskCallee, int dwTickCount, int dwRejectType)
- {
- if (dwRejectType == 2)
- // flag = SERVERCALL_RETRYLATER.
- {
- // Retry the thread call immediately if return >=0 &
- // <100.
- return 99;
- }
- // Too busy; cancel call.
- return -1;
- }
-
- int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
- int dwTickCount, int dwPendingType)
- {
- //Return the flag PENDINGMSG_WAITDEFPROCESS.
- return 2;
- }
-
- // Implement the IOleMessageFilter interface.
- [DllImport("Ole32.dll")]
- private static extern int
- CoRegisterMessageFilter(IOleMessageFilter newFilter, out
- IOleMessageFilter oldFilter);
- }
-
- [ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
- InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
- interface IOleMessageFilter
- {
- [PreserveSig]
- int HandleInComingCall(
- int dwCallType,
- IntPtr hTaskCaller,
- int dwTickCount,
- IntPtr lpInterfaceInfo);
-
- [PreserveSig]
- int RetryRejectedCall(
- IntPtr hTaskCallee,
- int dwTickCount,
- int dwRejectType);
-
- [PreserveSig]
- int MessagePending(
- IntPtr hTaskCallee,
- int dwTickCount,
- int dwPendingType);
- }
-
- class ViaCOM
- {
- public static object GetProperty(object from_obj, string prop_name)
- {
- try
- {
- Type objType = from_obj.GetType();
- return objType.InvokeMember(
- prop_name,
- BindingFlags.GetProperty, null,
- from_obj,
- null);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error getting property: \"{0}\"", prop_name);
- Console.WriteLine(e.Message);
- throw e;
- }
- }
-
- public static object SetProperty(object from_obj, string prop_name, object new_value)
- {
- try
- {
- object[] args = { new_value };
- Type objType = from_obj.GetType();
- return objType.InvokeMember(
- prop_name,
- BindingFlags.DeclaredOnly |
- BindingFlags.Public |
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.SetProperty,
- null,
- from_obj,
- args);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error setting property: \"{0}\"", prop_name);
- Console.WriteLine(e.Message);
- throw e;
- }
- }
-
- public static object CallMethod(object from_obj, string method_name, params object[] args)
- {
- try
- {
- Type objType = from_obj.GetType();
- return objType.InvokeMember(
- method_name,
- BindingFlags.DeclaredOnly |
- BindingFlags.Public |
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.InvokeMethod,
- null,
- from_obj,
- args);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error calling method \"{0}\"", method_name);
- Console.WriteLine(e.Message);
- throw e;
- }
- }
- };
-
- /// <summary>
- /// The main entry point class for VSTool.
- /// </summary>
- class VSToolMain
- {
- #region Interop imports
- [DllImport("ole32.dll")]
- public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
-
- [DllImport("ole32.dll")]
- public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);
- #endregion
-
- static System.Boolean ignore_case = true;
-
- static string solution_name = null;
- static bool use_new_vs = false;
- static Hashtable projectDict = new Hashtable();
- static string startup_project = null;
- static string config = null;
-
- static object dte = null;
- static object solution = null;
-
- /// <summary>
- /// The main entry point for the application.
- /// </summary>
- [STAThread]
- static int Main(string[] args)
- {
- int retVal = 0;
- bool need_save = false;
-
- try
- {
- parse_command_line(args);
-
- Console.WriteLine("Editing solution: {0}", solution_name);
-
- bool found_open_solution = GetDTEAndSolution();
-
- if (dte == null || solution == null)
- {
- retVal = 1;
- }
- else
- {
- MessageFilter.Register();
-
- // Walk through all of the projects in the solution
- // and list the type of each project.
- foreach (DictionaryEntry p in projectDict)
- {
- string project_name = (string)p.Key;
- string working_dir = (string)p.Value;
- if (SetProjectWorkingDir(solution, project_name, working_dir))
- {
- need_save = true;
- }
- }
-
- if (config != null)
- {
- need_save = SetActiveConfig(config);
- }
-
- if (startup_project != null)
- {
- need_save = SetStartupProject(startup_project);
- }
-
- if (need_save)
- {
- if (found_open_solution == false)
- {
- ViaCOM.CallMethod(solution, "Close", null);
- }
- }
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- retVal = 1;
- }
- finally
- {
- if (solution != null)
- {
- Marshal.ReleaseComObject(solution);
- solution = null;
- }
-
- if (dte != null)
- {
- Marshal.ReleaseComObject(dte);
- dte = null;
- }
-
- MessageFilter.Revoke();
- }
- return retVal;
- }
-
- public static bool parse_command_line(string[] args)
- {
- string options_desc =
- "--solution <solution_name> : MSVC solution name. (required)\n" +
- "--use_new_vs : Ignore running versions of visual studio.\n" +
- "--workingdir <project> <dir> : Set working dir of a VC project.\n" +
- "--config <config> : Set the active config for the solution.\n" +
- "--startup <project> : Set the startup project for the solution.\n";
-
- try
- {
- // Command line param parsing loop.
- int i = 0;
- for (; i < args.Length; ++i)
- {
- if ("--solution" == args[i])
- {
- if (solution_name != null)
- {
- throw new ApplicationException("Found second --solution option");
- }
- solution_name = args[++i];
- }
- else if ("--use_new_vs" == args[i])
- {
- use_new_vs = true;
- }
-
- else if ("--workingdir" == args[i])
- {
- string project_name = args[++i];
- string working_dir = args[++i];
- projectDict.Add(project_name, working_dir);
- }
- else if ("--config" == args[i])
- {
- if (config != null)
- {
- throw new ApplicationException("Found second --config option");
- }
- config = args[++i];
- }
- else if ("--startup" == args[i])
- {
- if (startup_project != null)
- {
- throw new ApplicationException("Found second --startup option");
- }
- startup_project = args[++i];
- }
- else
- {
- throw new ApplicationException("Found unrecognized token on command line: " + args[i]);
- }
- }
-
- if (solution_name == null)
- {
- throw new ApplicationException("The --solution option is required.");
- }
- }
- catch(ApplicationException e)
- {
-
- Console.WriteLine("Oops! " + e.Message);
- Console.Write("Command line:");
- foreach (string arg in args)
- {
- Console.Write(" " + arg);
- }
- Console.Write("\n\n");
- Console.WriteLine("VSTool command line usage");
- Console.Write(options_desc);
- throw e;
- }
- return true;
- }
-
- public static bool GetDTEAndSolution()
- {
- bool found_open_solution = true;
-
- Console.WriteLine("Looking for existing VisualStudio instance...");
-
- // Get an instance of the currently running Visual Studio .NET IDE.
- // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1");
- string full_solution_name = System.IO.Path.GetFullPath(solution_name);
- if (false == use_new_vs)
- {
- dte = GetIDEInstance(full_solution_name);
- }
-
- if (dte == null)
- {
- try
- {
- Console.WriteLine(" Didn't find open solution, starting new background VisualStudio instance...");
- Console.WriteLine(" Reading .sln file version...");
- string version = GetSolutionVersion(full_solution_name);
-
- Console.WriteLine(" Using version: {0}...", version);
- string progid = GetVSProgID(version);
-
- Type objType = Type.GetTypeFromProgID(progid);
- dte = System.Activator.CreateInstance(objType);
- Console.WriteLine(" Reading solution: \"{0}\"", full_solution_name);
-
- solution = ViaCOM.GetProperty(dte, "Solution");
- object[] openArgs = { full_solution_name };
- ViaCOM.CallMethod(solution, "Open", openArgs);
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- Console.WriteLine("Quitting do to error opening: {0}", full_solution_name);
- solution = null;
- dte = null;
- return found_open_solution;
- }
- found_open_solution = false;
- }
-
- if (solution == null)
- {
- solution = ViaCOM.GetProperty(dte, "Solution");
- }
-
- return found_open_solution;
- }
-
- /// <summary>
- /// Get the DTE object for the instance of Visual Studio IDE that has
- /// the specified solution open.
- /// </summary>
- /// <param name="solutionFile">The absolute filename of the solution</param>
- /// <returns>Corresponding DTE object or null if no such IDE is running</returns>
- public static object GetIDEInstance( string solutionFile )
- {
- Hashtable runningInstances = GetIDEInstances( true );
- IDictionaryEnumerator enumerator = runningInstances.GetEnumerator();
-
- while ( enumerator.MoveNext() )
- {
- try
- {
- object ide = enumerator.Value;
- if (ide != null)
- {
- object sol = ViaCOM.GetProperty(ide, "Solution");
- if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case))
- {
- return ide;
- }
- }
- }
- catch{}
- }
-
- return null;
- }
-
- /// <summary>
- /// Get a table of the currently running instances of the Visual Studio .NET IDE.
- /// </summary>
- /// <param name="openSolutionsOnly">Only return instances that have opened a solution</param>
- /// <returns>A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object</returns>
- public static Hashtable GetIDEInstances( bool openSolutionsOnly )
- {
- Hashtable runningIDEInstances = new Hashtable();
- Hashtable runningObjects = GetRunningObjectTable();
-
- IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
- while ( rotEnumerator.MoveNext() )
- {
- string candidateName = (string) rotEnumerator.Key;
- if (!candidateName.StartsWith("!VisualStudio.DTE"))
- continue;
-
- object ide = rotEnumerator.Value;
- if (ide == null)
- continue;
-
- if (openSolutionsOnly)
- {
- try
- {
- object sol = ViaCOM.GetProperty(ide, "Solution");
- string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName");
- if (solutionFile != String.Empty)
- {
- runningIDEInstances[ candidateName ] = ide;
- }
- }
- catch {}
- }
- else
- {
- runningIDEInstances[ candidateName ] = ide;
- }
- }
- return runningIDEInstances;
- }
-
- /// <summary>
- /// Get a snapshot of the running object table (ROT).
- /// </summary>
- /// <returns>A hashtable mapping the name of the object in the ROT to the corresponding object</returns>
- [STAThread]
- public static Hashtable GetRunningObjectTable()
- {
- Hashtable result = new Hashtable();
-
- int numFetched = 0;
- IRunningObjectTable runningObjectTable;
- IEnumMoniker monikerEnumerator;
- IMoniker[] monikers = new IMoniker[1];
-
- GetRunningObjectTable(0, out runningObjectTable);
- runningObjectTable.EnumRunning(out monikerEnumerator);
- monikerEnumerator.Reset();
-
- while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0)
- {
- IBindCtx ctx;
- CreateBindCtx(0, out ctx);
-
- string runningObjectName;
- monikers[0].GetDisplayName(ctx, null, out runningObjectName);
-
- object runningObjectVal;
- runningObjectTable.GetObject( monikers[0], out runningObjectVal);
-
- result[ runningObjectName ] = runningObjectVal;
- }
-
- return result;
- }
-
- public static string GetSolutionVersion(string solutionFullFileName)
- {
- string version;
- System.IO.StreamReader solutionStreamReader = null;
- string firstLine;
- string format;
-
- try
- {
- solutionStreamReader = new System.IO.StreamReader(solutionFullFileName);
- do
- {
- firstLine = solutionStreamReader.ReadLine();
- }
- while (firstLine == "");
-
- format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim();
-
- switch(format)
- {
- case "7.00":
- version = "VC70";
- break;
-
- case "8.00":
- version = "VC71";
- break;
-
- case "9.00":
- version = "VC80";
- break;
-
- case "10.00":
- version = "VC90";
- break;
- default:
- throw new ApplicationException("Unknown .sln version: " + format);
- }
- }
- finally
- {
- if(solutionStreamReader != null)
- {
- solutionStreamReader.Close();
- }
- }
-
- return version;
- }
-
- public static string GetVSProgID(string version)
- {
- string progid = null;
- switch(version)
- {
- case "VC70":
- progid = "VisualStudio.DTE.7";
- break;
-
- case "VC71":
- progid = "VisualStudio.DTE.7.1";
- break;
-
- case "VC80":
- progid = "VisualStudio.DTE.8.0";
- break;
-
- case "VC90":
- progid = "VisualStudio.DTE.9.0";
- break;
- default:
- throw new ApplicationException("Can't handle VS version: " + version);
- }
-
- return progid;
- }
-
- public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir)
- {
- bool made_change = false;
- Console.WriteLine("Looking for project {0}...", project_name);
- try
- {
- object prjs = ViaCOM.GetProperty(sol, "Projects");
- object count = ViaCOM.GetProperty(prjs, "Count");
- for(int i = 1; i <= (int)count; ++i)
- {
- object[] prjItemArgs = { (object)i };
- object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs);
- string name = (string)ViaCOM.GetProperty(prj, "Name");
- if (0 == string.Compare(name, project_name, ignore_case))
- {
- Console.WriteLine("Found project: {0}", project_name);
- Console.WriteLine("Setting working directory");
-
- string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName");
- Console.WriteLine(full_project_name);
-
- // *NOTE:Mani Thanks to incompatibilities between different versions of the
- // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to
- // the VCProjectEngine types from a different version than the one built
- // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built
- // in VS 8.0. To avoid this problem, we can use the com object interfaces directly,
- // without the type casting. Its tedious code, but it seems to work.
-
- // oCfgs should be assigned to a 'Project.Configurations' collection.
- object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations");
-
- // oCount will be assigned to the number of configs present in oCfgs.
- object oCount = ViaCOM.GetProperty(oCfgs, "Count");
-
- for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex)
- {
- object[] itemArgs = {(object)cfgIndex};
- object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs);
- object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings");
- ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir);
- }
-
- break;
- }
- }
- made_change = true;
- }
- catch( Exception e )
- {
- Console.WriteLine(e.Message);
- Console.WriteLine("Failed to set working dir for project, {0}.", project_name);
- }
-
- return made_change;
- }
-
- public static bool SetStartupProject(string startup_project)
- {
- bool result = false;
- try
- {
- // You need the 'unique name of the project to set StartupProjects.
- // find the project by generic name.
- Console.WriteLine("Trying to set \"{0}\" to the startup project", startup_project);
- object prjs = ViaCOM.GetProperty(solution, "Projects");
- object count = ViaCOM.GetProperty(prjs, "Count");
- for (int i = 1; i <= (int)count; ++i)
- {
- object[] itemArgs = { (object)i };
- object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs);
- object prjName = ViaCOM.GetProperty(prj, "Name");
- if (0 == string.Compare((string)prjName, startup_project, ignore_case))
- {
- object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
- ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName"));
- Console.WriteLine(" Success!");
- result = true;
- break;
- }
- }
-
- if (result == false)
- {
- Console.WriteLine(" Could not find project \"{0}\" in the solution.", startup_project);
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(" Failed to set the startup project!");
- Console.WriteLine(e.Message);
- }
- return result;
- }
-
- public static bool SetActiveConfig(string config)
- {
- bool result = false;
- try
- {
- Console.WriteLine("Trying to set active config to \"{0}\"", config);
- object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
- object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations");
- object[] itemArgs = { (object)config };
- object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs);
- ViaCOM.CallMethod(solCfg, "Activate", null);
- Console.WriteLine(" Success!");
- result = true;
- }
- catch (Exception e)
- {
- Console.WriteLine(" Failed to set \"{0}\" as the active config.", config);
- Console.WriteLine(e.Message);
- }
- return result;
- }
- }
-}
+// Code about getting running instances visual studio +// was borrowed from +// http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using Microsoft.CSharp; + +namespace VSTool +{ + // The MessageFilter class comes from: + // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx + // It allows vstool to get timing error messages from + // visualstudio and handle them. + public class MessageFilter : IOleMessageFilter + { + // + // Class containing the IOleMessageFilter + // thread error-handling functions. + + // Start the filter. + public static void Register() + { + IOleMessageFilter newFilter = new MessageFilter(); + IOleMessageFilter oldFilter = null; + CoRegisterMessageFilter(newFilter, out oldFilter); + } + + // Done with the filter, close it. + public static void Revoke() + { + IOleMessageFilter oldFilter = null; + CoRegisterMessageFilter(null, out oldFilter); + } + + // + // IOleMessageFilter functions. + // Handle incoming thread requests. + int IOleMessageFilter.HandleInComingCall(int dwCallType, + System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr + lpInterfaceInfo) + { + //Return the flag SERVERCALL_ISHANDLED. + return 0; + } + + // Thread call was rejected, so try again. + int IOleMessageFilter.RetryRejectedCall(System.IntPtr + hTaskCallee, int dwTickCount, int dwRejectType) + { + if (dwRejectType == 2) + // flag = SERVERCALL_RETRYLATER. + { + // Retry the thread call immediately if return >=0 & + // <100. + return 99; + } + // Too busy; cancel call. + return -1; + } + + int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee, + int dwTickCount, int dwPendingType) + { + //Return the flag PENDINGMSG_WAITDEFPROCESS. + return 2; + } + + // Implement the IOleMessageFilter interface. + [DllImport("Ole32.dll")] + private static extern int + CoRegisterMessageFilter(IOleMessageFilter newFilter, out + IOleMessageFilter oldFilter); + } + + [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + interface IOleMessageFilter + { + [PreserveSig] + int HandleInComingCall( + int dwCallType, + IntPtr hTaskCaller, + int dwTickCount, + IntPtr lpInterfaceInfo); + + [PreserveSig] + int RetryRejectedCall( + IntPtr hTaskCallee, + int dwTickCount, + int dwRejectType); + + [PreserveSig] + int MessagePending( + IntPtr hTaskCallee, + int dwTickCount, + int dwPendingType); + } + + class ViaCOM + { + public static object GetProperty(object from_obj, string prop_name) + { + try + { + Type objType = from_obj.GetType(); + return objType.InvokeMember( + prop_name, + BindingFlags.GetProperty, null, + from_obj, + null); + } + catch (Exception e) + { + Console.WriteLine("Error getting property: \"{0}\"", prop_name); + Console.WriteLine(e.Message); + throw e; + } + } + + public static object SetProperty(object from_obj, string prop_name, object new_value) + { + try + { + object[] args = { new_value }; + Type objType = from_obj.GetType(); + return objType.InvokeMember( + prop_name, + BindingFlags.DeclaredOnly | + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.SetProperty, + null, + from_obj, + args); + } + catch (Exception e) + { + Console.WriteLine("Error setting property: \"{0}\"", prop_name); + Console.WriteLine(e.Message); + throw e; + } + } + + public static object CallMethod(object from_obj, string method_name, params object[] args) + { + try + { + Type objType = from_obj.GetType(); + return objType.InvokeMember( + method_name, + BindingFlags.DeclaredOnly | + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.InvokeMethod, + null, + from_obj, + args); + } + catch (Exception e) + { + Console.WriteLine("Error calling method \"{0}\"", method_name); + Console.WriteLine(e.Message); + throw e; + } + } + }; + + /// <summary> + /// The main entry point class for VSTool. + /// </summary> + class VSToolMain + { + #region Interop imports + [DllImport("ole32.dll")] + public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot); + + [DllImport("ole32.dll")] + public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc); + #endregion + + static System.Boolean ignore_case = true; + + static string solution_name = null; + static bool use_new_vs = false; + static Hashtable projectDict = new Hashtable(); + static string startup_project = null; + static string config = null; + + static object dte = null; + static object solution = null; + + /// <summary> + /// The main entry point for the application. + /// </summary> + [STAThread] + static int Main(string[] args) + { + int retVal = 0; + bool need_save = false; + + try + { + parse_command_line(args); + + Console.WriteLine("Editing solution: {0}", solution_name); + + bool found_open_solution = GetDTEAndSolution(); + + if (dte == null || solution == null) + { + retVal = 1; + } + else + { + MessageFilter.Register(); + + // Walk through all of the projects in the solution + // and list the type of each project. + foreach (DictionaryEntry p in projectDict) + { + string project_name = (string)p.Key; + string working_dir = (string)p.Value; + if (SetProjectWorkingDir(solution, project_name, working_dir)) + { + need_save = true; + } + } + + if (config != null) + { + need_save = SetActiveConfig(config); + } + + if (startup_project != null) + { + need_save = SetStartupProject(startup_project); + } + + if (need_save) + { + if (found_open_solution == false) + { + ViaCOM.CallMethod(solution, "Close", null); + } + } + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + retVal = 1; + } + finally + { + if (solution != null) + { + Marshal.ReleaseComObject(solution); + solution = null; + } + + if (dte != null) + { + Marshal.ReleaseComObject(dte); + dte = null; + } + + MessageFilter.Revoke(); + } + return retVal; + } + + public static bool parse_command_line(string[] args) + { + string options_desc = + "--solution <solution_name> : MSVC solution name. (required)\n" + + "--use_new_vs : Ignore running versions of visual studio.\n" + + "--workingdir <project> <dir> : Set working dir of a VC project.\n" + + "--config <config> : Set the active config for the solution.\n" + + "--startup <project> : Set the startup project for the solution.\n"; + + try + { + // Command line param parsing loop. + int i = 0; + for (; i < args.Length; ++i) + { + if ("--solution" == args[i]) + { + if (solution_name != null) + { + throw new ApplicationException("Found second --solution option"); + } + solution_name = args[++i]; + } + else if ("--use_new_vs" == args[i]) + { + use_new_vs = true; + } + + else if ("--workingdir" == args[i]) + { + string project_name = args[++i]; + string working_dir = args[++i]; + projectDict.Add(project_name, working_dir); + } + else if ("--config" == args[i]) + { + if (config != null) + { + throw new ApplicationException("Found second --config option"); + } + config = args[++i]; + } + else if ("--startup" == args[i]) + { + if (startup_project != null) + { + throw new ApplicationException("Found second --startup option"); + } + startup_project = args[++i]; + } + else + { + throw new ApplicationException("Found unrecognized token on command line: " + args[i]); + } + } + + if (solution_name == null) + { + throw new ApplicationException("The --solution option is required."); + } + } + catch(ApplicationException e) + { + + Console.WriteLine("Oops! " + e.Message); + Console.Write("Command line:"); + foreach (string arg in args) + { + Console.Write(" " + arg); + } + Console.Write("\n\n"); + Console.WriteLine("VSTool command line usage"); + Console.Write(options_desc); + throw e; + } + return true; + } + + public static bool GetDTEAndSolution() + { + bool found_open_solution = true; + + Console.WriteLine("Looking for existing VisualStudio instance..."); + + // Get an instance of the currently running Visual Studio .NET IDE. + // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1"); + string full_solution_name = System.IO.Path.GetFullPath(solution_name); + if (false == use_new_vs) + { + dte = GetIDEInstance(full_solution_name); + } + + if (dte == null) + { + try + { + Console.WriteLine(" Didn't find open solution, starting new background VisualStudio instance..."); + Console.WriteLine(" Reading .sln file version..."); + string version = GetSolutionVersion(full_solution_name); + + Console.WriteLine(" Using version: {0}...", version); + string progid = GetVSProgID(version); + + Type objType = Type.GetTypeFromProgID(progid); + dte = System.Activator.CreateInstance(objType); + Console.WriteLine(" Reading solution: \"{0}\"", full_solution_name); + + solution = ViaCOM.GetProperty(dte, "Solution"); + object[] openArgs = { full_solution_name }; + ViaCOM.CallMethod(solution, "Open", openArgs); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + Console.WriteLine("Quitting do to error opening: {0}", full_solution_name); + solution = null; + dte = null; + return found_open_solution; + } + found_open_solution = false; + } + + if (solution == null) + { + solution = ViaCOM.GetProperty(dte, "Solution"); + } + + return found_open_solution; + } + + /// <summary> + /// Get the DTE object for the instance of Visual Studio IDE that has + /// the specified solution open. + /// </summary> + /// <param name="solutionFile">The absolute filename of the solution</param> + /// <returns>Corresponding DTE object or null if no such IDE is running</returns> + public static object GetIDEInstance( string solutionFile ) + { + Hashtable runningInstances = GetIDEInstances( true ); + IDictionaryEnumerator enumerator = runningInstances.GetEnumerator(); + + while ( enumerator.MoveNext() ) + { + try + { + object ide = enumerator.Value; + if (ide != null) + { + object sol = ViaCOM.GetProperty(ide, "Solution"); + if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case)) + { + return ide; + } + } + } + catch{} + } + + return null; + } + + /// <summary> + /// Get a table of the currently running instances of the Visual Studio .NET IDE. + /// </summary> + /// <param name="openSolutionsOnly">Only return instances that have opened a solution</param> + /// <returns>A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object</returns> + public static Hashtable GetIDEInstances( bool openSolutionsOnly ) + { + Hashtable runningIDEInstances = new Hashtable(); + Hashtable runningObjects = GetRunningObjectTable(); + + IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator(); + while ( rotEnumerator.MoveNext() ) + { + string candidateName = (string) rotEnumerator.Key; + if (!candidateName.StartsWith("!VisualStudio.DTE")) + continue; + + object ide = rotEnumerator.Value; + if (ide == null) + continue; + + if (openSolutionsOnly) + { + try + { + object sol = ViaCOM.GetProperty(ide, "Solution"); + string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName"); + if (solutionFile != String.Empty) + { + runningIDEInstances[ candidateName ] = ide; + } + } + catch {} + } + else + { + runningIDEInstances[ candidateName ] = ide; + } + } + return runningIDEInstances; + } + + /// <summary> + /// Get a snapshot of the running object table (ROT). + /// </summary> + /// <returns>A hashtable mapping the name of the object in the ROT to the corresponding object</returns> + [STAThread] + public static Hashtable GetRunningObjectTable() + { + Hashtable result = new Hashtable(); + + int numFetched = 0; + IRunningObjectTable runningObjectTable; + IEnumMoniker monikerEnumerator; + IMoniker[] monikers = new IMoniker[1]; + + GetRunningObjectTable(0, out runningObjectTable); + runningObjectTable.EnumRunning(out monikerEnumerator); + monikerEnumerator.Reset(); + + while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0) + { + IBindCtx ctx; + CreateBindCtx(0, out ctx); + + string runningObjectName; + monikers[0].GetDisplayName(ctx, null, out runningObjectName); + + object runningObjectVal; + runningObjectTable.GetObject( monikers[0], out runningObjectVal); + + result[ runningObjectName ] = runningObjectVal; + } + + return result; + } + + public static string GetSolutionVersion(string solutionFullFileName) + { + string version; + System.IO.StreamReader solutionStreamReader = null; + string firstLine; + string format; + + try + { + solutionStreamReader = new System.IO.StreamReader(solutionFullFileName); + do + { + firstLine = solutionStreamReader.ReadLine(); + } + while (firstLine == ""); + + format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim(); + + switch(format) + { + case "7.00": + version = "VC70"; + break; + + case "8.00": + version = "VC71"; + break; + + case "9.00": + version = "VC80"; + break; + + case "10.00": + version = "VC90"; + break; + default: + throw new ApplicationException("Unknown .sln version: " + format); + } + } + finally + { + if(solutionStreamReader != null) + { + solutionStreamReader.Close(); + } + } + + return version; + } + + public static string GetVSProgID(string version) + { + string progid = null; + switch(version) + { + case "VC70": + progid = "VisualStudio.DTE.7"; + break; + + case "VC71": + progid = "VisualStudio.DTE.7.1"; + break; + + case "VC80": + progid = "VisualStudio.DTE.8.0"; + break; + + case "VC90": + progid = "VisualStudio.DTE.9.0"; + break; + default: + throw new ApplicationException("Can't handle VS version: " + version); + } + + return progid; + } + + public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir) + { + bool made_change = false; + Console.WriteLine("Looking for project {0}...", project_name); + try + { + object prjs = ViaCOM.GetProperty(sol, "Projects"); + object count = ViaCOM.GetProperty(prjs, "Count"); + for(int i = 1; i <= (int)count; ++i) + { + object[] prjItemArgs = { (object)i }; + object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs); + string name = (string)ViaCOM.GetProperty(prj, "Name"); + if (0 == string.Compare(name, project_name, ignore_case)) + { + Console.WriteLine("Found project: {0}", project_name); + Console.WriteLine("Setting working directory"); + + string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName"); + Console.WriteLine(full_project_name); + + // *NOTE:Mani Thanks to incompatibilities between different versions of the + // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to + // the VCProjectEngine types from a different version than the one built + // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built + // in VS 8.0. To avoid this problem, we can use the com object interfaces directly, + // without the type casting. Its tedious code, but it seems to work. + + // oCfgs should be assigned to a 'Project.Configurations' collection. + object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations"); + + // oCount will be assigned to the number of configs present in oCfgs. + object oCount = ViaCOM.GetProperty(oCfgs, "Count"); + + for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex) + { + object[] itemArgs = {(object)cfgIndex}; + object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs); + object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings"); + ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir); + } + + break; + } + } + made_change = true; + } + catch( Exception e ) + { + Console.WriteLine(e.Message); + Console.WriteLine("Failed to set working dir for project, {0}.", project_name); + } + + return made_change; + } + + public static bool SetStartupProject(string startup_project) + { + bool result = false; + try + { + // You need the 'unique name of the project to set StartupProjects. + // find the project by generic name. + Console.WriteLine("Trying to set \"{0}\" to the startup project", startup_project); + object prjs = ViaCOM.GetProperty(solution, "Projects"); + object count = ViaCOM.GetProperty(prjs, "Count"); + for (int i = 1; i <= (int)count; ++i) + { + object[] itemArgs = { (object)i }; + object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs); + object prjName = ViaCOM.GetProperty(prj, "Name"); + if (0 == string.Compare((string)prjName, startup_project, ignore_case)) + { + object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); + ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName")); + Console.WriteLine(" Success!"); + result = true; + break; + } + } + + if (result == false) + { + Console.WriteLine(" Could not find project \"{0}\" in the solution.", startup_project); + } + } + catch (Exception e) + { + Console.WriteLine(" Failed to set the startup project!"); + Console.WriteLine(e.Message); + } + return result; + } + + public static bool SetActiveConfig(string config) + { + bool result = false; + try + { + Console.WriteLine("Trying to set active config to \"{0}\"", config); + object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild"); + object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations"); + object[] itemArgs = { (object)config }; + object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs); + ViaCOM.CallMethod(solCfg, "Activate", null); + Console.WriteLine(" Success!"); + result = true; + } + catch (Exception e) + { + Console.WriteLine(" Failed to set \"{0}\" as the active config.", config); + Console.WriteLine(e.Message); + } + return result; + } + } +} diff --git a/install.xml b/install.xml index 8e5c7e7ae4..6d40d6fe4e 100644 --- a/install.xml +++ b/install.xml @@ -132,9 +132,9 @@ <key>windows</key> <map> <key>md5sum</key> - <string>4e2d4de03dce8a991a5727c15a284e8d</string> + <string>70b51d0cc93c305026e4e2778cde6d19</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ares-1.3.0-windows-20090917.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ares-1.6.0-windows-20090722.tar.bz2</uri> </map> </map> </map> diff --git a/scripts/update_version_files.py b/scripts/update_version_files.py index ee1ce69a15..da60fd105a 100755 --- a/scripts/update_version_files.py +++ b/scripts/update_version_files.py @@ -47,6 +47,9 @@ def usage(): Options: --version Specify the version string to replace current version. + --revision + Specify the revision to replace the last digit of the version. + By default, revision is computed from the version control system. --skip-on-branch Specify a regular expression against which the current branch is matched. If it matches, then leave version strings alone. @@ -161,6 +164,7 @@ def main(): opts, args = getopt.getopt(sys.argv[1:], "", ['version=', + 'revision=', 'channel=', 'server_channel=', 'skip-on-branch=', @@ -171,12 +175,15 @@ def main(): update_server = False update_viewer = False new_version = None + new_revision = None new_viewer_channel = None new_server_channel = None skip_on_branch_re = None for o,a in opts: if o in ('--version'): new_version = a + if o in ('--revision'): + new_revision = a if o in ('--skip-on-branch'): skip_on_branch_re = re.compile(a) if o in ('--channel'): @@ -243,11 +250,20 @@ def main(): else: if llversion.using_svn(): - revision = llversion.get_svn_revision() + if new_revision: + revision = new_revision + else: + revision = llversion.get_svn_revision() branch = llversion.get_svn_branch() elif llversion.using_hg(): - revision = llversion.get_hg_changeset() + if new_revision: + revision = new_revision + else: + revision = llversion.get_hg_changeset() branch = llversion.get_hg_repo() + elif new_revision: + revision = new_revision + branch = "unknown" else: print >>sys.stderr, "ERROR: could not determine revision and branch" return -1 |