diff --git a/README b/README index 55c159679..a441bfedf 100644 --- a/README +++ b/README @@ -9,15 +9,30 @@ Sin-gu-la-ri-ty (noun) - a distinctive feature, a uniqueness; a point at which continuity breaks up; a point in history at which machine becomes smarter than humanity and/or fuses with it indivisively; or simply a cool sounding word with -my initials in it :) +the initials S.G. in it :) -Singularity Viewer is a Second Life protocol compatible client application. It -can be used to access Second LIfe service as well as a number of other such as -those based upon OpenSim plattform. It is directly based upon source code of -Ascent Viewer by Balseraph Software Group, which is in turn based upon source -code released by Linden Lab, with contributions from various sources. +Singularity Viewer is a SecondLife(tm) protocol compatible client application. +It can be used to access SecondLife services as well as a number of others such +as those based upon the OpenSim platform. + +Singulariy is maintained by a small group of volunteers who can be contacted +both, in-world (SingularityViewer group) as well on IRC (#SingularityViewer +@ FreeNode). Bug requests and features requests can be submitted through our +Issue Tracker (http://code.google.com/p/singularity-viewer/issues/list or from +the viewer menu: Help --> Bug Reporting --> Singularity Issue Tracker...) + As this Readme grows out of date, please refer to http://www.singularityviewer.org/about + +00000000011111111112222222222333333333344444444445555555555666666666677777777778 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 + +History + +The Singularity viewer was started by Siana Gearz in November 2010 by forking it +from the Ascent Viewer, by Balseraph Software Group, which in turn was based upon +source code modified from the snowglobe source code released by Linden Lab. + diff --git a/doc/contributions.txt b/doc/contributions.txt index 882dca18c..9eb4520cd 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -248,6 +248,7 @@ Celierra Darling VWR-6975 Cron Stardust VWR-10579 + STORM-1919 Cypren Christenson SNOW-129 SNOW-140 diff --git a/etc/message.xml b/etc/message.xml index 42bbef035..427a6ac40 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -378,6 +378,14 @@ true + WindLightRefresh + + flavor + llsd + trusted-sender + true + + ParcelVoiceInfo flavor @@ -386,7 +394,6 @@ true - ParcelNavigateMedia flavor diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake index 0a4bc0647..902af05fb 100644 --- a/indra/cmake/FMODEX.cmake +++ b/indra/cmake/FMODEX.cmake @@ -17,15 +17,25 @@ find_library(FMODEX_LIBRARY if (NOT FMODEX_LIBRARY) set(FMODEX_SDK_DIR CACHE PATH "Path to the FMOD Ex SDK.") if (FMODEX_SDK_DIR) - find_library(FMODEX_LIBRARY - fmodex_vc fmodexL_vc fmodex fmodexL fmodex64 fmodexL64 - PATHS - ${FMODEX_SDK_DIR}/api/lib - ${FMODEX_SDK_DIR}/api - ${FMODEX_SDK_DIR}/lib - ${FMODEX_SDK_DIR} - ) - + if(WORD_SIZE EQUAL 32) + find_library(FMODEX_LIBRARY + fmodex_vc fmodexL_vc fmodex fmodexL + PATHS + ${FMODEX_SDK_DIR}/api/lib + ${FMODEX_SDK_DIR}/api + ${FMODEX_SDK_DIR}/lib + ${FMODEX_SDK_DIR} + ) + elseif(WORD_SIZE EQUAL 64) + find_library(FMODEX_LIBRARY + fmodex64 fmodexL64 + PATHS + ${FMODEX_SDK_DIR}/api/lib + ${FMODEX_SDK_DIR}/api + ${FMODEX_SDK_DIR}/lib + ${FMODEX_SDK_DIR} + ) + endif(WORD_SIZE EQUAL 32) endif(FMODEX_SDK_DIR) if(WINDOWS AND NOT FMODEX_LIBRARY) set(FMODEX_PROG_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows") diff --git a/indra/cmake/FindJsonCpp.cmake b/indra/cmake/FindJsonCpp.cmake index 44ab0e769..a48c97396 100644 --- a/indra/cmake/FindJsonCpp.cmake +++ b/indra/cmake/FindJsonCpp.cmake @@ -3,16 +3,18 @@ # - Find JSONCpp # Find the JSONCpp includes and library # This module defines -# JSONCPP_INCLUDE_DIR, where to find json.h, etc. -# JSONCPP_LIBRARIES, the libraries needed to use jsoncpp. -# JSONCPP_FOUND, If false, do not try to use jsoncpp. -# also defined, but not for general use are -# JSONCPP_LIBRARY, where to find the jsoncpp library. +# JSONCPP_FOUND, System has libjsoncpp. +# JSONCPP_INCLUDE_DIRS - The libjsoncpp include directories. +# JSONCPP_LIBRARIES - The libraries needed to use libjsoncpp. +# JSONCPP_DEFINITIONS - Compiler switches required for using libjsoncpp. -FIND_PATH(JSONCPP_INCLUDE_DIR json/json.h -/usr/local/include -/usr/include -) +FIND_PACKAGE(PkgConfig) +PKG_CHECK_MODULES(PC_JSONCPP jsoncpp) +SET(JSONCPP_DEFINITIONS ${PC_JSONCPP_CFLAGS_OTHER}) + +FIND_PATH(JSONCPP_INCLUDE_DIR json/reader.h + HINTS ${PC_JSONCPP_INCLUDE_DIR} ${PC_JSONCPP_INCLUDE_DIRS} + PATH_SUFFIXES jsoncpp) # Get the GCC compiler version EXEC_PROGRAM(${CMAKE_CXX_COMPILER} @@ -22,39 +24,16 @@ EXEC_PROGRAM(${CMAKE_CXX_COMPILER} ) # Try to find a library that was compiled with the same compiler version as we currently use. -SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so) -IF (STANDALONE) - # On standalone, assume that the system installed library was compiled with the used compiler. - SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson.so) -ENDIF (STANDALONE) FIND_LIBRARY(JSONCPP_LIBRARY - NAMES ${JSONCPP_NAMES} - PATHS /usr/lib /usr/local/lib - ) + NAMES libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so libjsoncpp.so + HINTS ${PC_JSONCPP_LIBDIR} ${PC_JSONCPP_LIBRARY_DIRS} + PATHS /usr/lib /usr/local/lib) -IF (JSONCPP_LIBRARY AND JSONCPP_INCLUDE_DIR) - SET(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY}) - SET(JSONCPP_FOUND "YES") -ELSE (JSONCPP_LIBRARY AND JSONCPP_INCLUDE_DIR) - SET(JSONCPP_FOUND "NO") -ENDIF (JSONCPP_LIBRARY AND JSONCPP_INCLUDE_DIR) +SET(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY}) +SET(JSONCPP_INCLUDE_DIRS ${JSONCPP_INCLUDE_DIR}) +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(JSONCPP DEFAULT_MSG + JSONCPP_LIBRARY JSONCPP_INCLUDE_DIR) -IF (JSONCPP_FOUND) - IF (NOT JSONCPP_FIND_QUIETLY) - MESSAGE(STATUS "Found JSONCpp: ${JSONCPP_LIBRARIES}") - ENDIF (NOT JSONCPP_FIND_QUIETLY) -ELSE (JSONCPP_FOUND) - IF (JSONCPP_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find JSONCpp library") - ENDIF (JSONCPP_FIND_REQUIRED) -ENDIF (JSONCPP_FOUND) - -# Deprecated declarations. -SET (NATIVE_JSONCPP_INCLUDE_PATH ${JSONCPP_INCLUDE_DIR} ) -GET_FILENAME_COMPONENT (NATIVE_JSONCPP_LIB_PATH ${JSONCPP_LIBRARY} PATH) - -MARK_AS_ADVANCED( - JSONCPP_LIBRARY - JSONCPP_INCLUDE_DIR - ) +MARK_AS_ADVANCED(JSONCPP_LIBRARY JSONCPP_INCLUDE_DIR) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index c102542e0..3ad669c94 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -11,10 +11,10 @@ else (STANDALONE) if (LINUX OR WINDOWS AND NOT WORD_SIZE EQUAL 64) use_prebuilt_binary(gperftools) endif (LINUX OR WINDOWS AND NOT WORD_SIZE EQUAL 64) - if (WINDOWS) + if (WINDOWS AND NOT DISABLE_TCMALLOC) set(TCMALLOC_LIBRARIES libtcmalloc_minimal.lib) set(TCMALLOC_LINKER_FLAGS "/INCLUDE:\"__tcmalloc\"") - endif (WINDOWS) + endif (WINDOWS AND NOT DISABLE_TCMALLOC) if (LINUX) if(USE_GOOGLE_PERFTOOLS) set(TCMALLOC_LIBRARIES tcmalloc) diff --git a/indra/cmake/JsonCpp.cmake b/indra/cmake/JsonCpp.cmake index 241db3570..2d7c16939 100644 --- a/indra/cmake/JsonCpp.cmake +++ b/indra/cmake/JsonCpp.cmake @@ -2,7 +2,7 @@ include(Prebuilt) -set(JSONCPP_FIND_QUIETLY ON) +set(JSONCPP_FIND_QUIETLY OFF) set(JSONCPP_FIND_REQUIRED ON) if (STANDALONE) diff --git a/indra/cmake/OpenSSL.cmake b/indra/cmake/OpenSSL.cmake index 60cd40c8b..fffe868fd 100644 --- a/indra/cmake/OpenSSL.cmake +++ b/indra/cmake/OpenSSL.cmake @@ -4,9 +4,9 @@ include(Prebuilt) set(OpenSSL_FIND_QUIETLY ON) set(OpenSSL_FIND_REQUIRED ON) -if (STANDALONE) +if (STANDALONE OR USE_SYSTEM_OPENSSL) include(FindOpenSSL) -else (STANDALONE) +else (STANDALONE OR USE_SYSTEM_OPENSSL) use_prebuilt_binary(openSSL) if (WINDOWS) set(OPENSSL_LIBRARIES ssleay32 libeay32) @@ -14,7 +14,7 @@ else (STANDALONE) set(OPENSSL_LIBRARIES ssl) endif (WINDOWS) set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) -endif (STANDALONE) +endif (STANDALONE OR USE_SYSTEM_OPENSSL) if (LINUX OR DARWIN) set(CRYPTO_LIBRARIES crypto) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index c6035597f..9e7d411a2 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -30,6 +30,7 @@ set(LIBS_SERVER_DIR ${CMAKE_SOURCE_DIR}/${LIBS_SERVER_PREFIX}) set(SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/${SCRIPTS_PREFIX}) set(SERVER_DIR ${CMAKE_SOURCE_DIR}/${SERVER_PREFIX}) set(VIEWER_DIR ${CMAKE_SOURCE_DIR}/${VIEWER_PREFIX}) +set(DISABLE_TCMALLOC OFF CACHE BOOL "Disable linkage of TCMalloc. (64bit builds automatically disable TCMalloc)") set(LL_TESTS OFF CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation)") set(VISTA_ICON OFF CACHE BOOL "Allow vista icon with pre 2008 Visual Studio IDEs. (Assumes replacement old rcdll.dll with new rcdll.dll from win sdk 7.0 or later)") diff --git a/indra/cwdebug/debug.cc b/indra/cwdebug/debug.cc index de14fa99f..ed1384306 100644 --- a/indra/cwdebug/debug.cc +++ b/indra/cwdebug/debug.cc @@ -236,8 +236,9 @@ void stop_recording_backtraces(void) channel_ct backtrace DDCN("BACKTRACE"); //!< This debug channel is used for backtraces. channel_ct statemachine DDCN("STATEMACHINE"); //!< This debug channel is used for output related to class AIStateMachine. channel_ct caps DDCN("CAPS"); //!< This debug channel is used for output related to Capabilities. - channel_ct curl DDCN("CURL"); //!< This debug channel is used for output related to Curl. - channel_ct curlio DDCN("CURLIO"); //!< This debug channel is used to print debug output of libcurl. + channel_ct curl DDCN("CURL"); //!< This debug channel is used for output related to AICurl. + channel_ct curlio DDCN("CURLIO"); //!< This debug channel is used to print debug output of libcurl. This includes all HTTP network traffic. + channel_ct curltr DDCN("CURLTR"); //!< This debug channel is used to print libcurl API calls. } // namespace dc } // namespace DEBUGCHANNELS diff --git a/indra/cwdebug/debug.h b/indra/cwdebug/debug.h index 1deed2efb..c1b509946 100644 --- a/indra/cwdebug/debug.h +++ b/indra/cwdebug/debug.h @@ -207,6 +207,7 @@ extern CWD_API channel_ct statemachine; extern CWD_API channel_ct caps; extern CWD_API channel_ct curl; extern CWD_API channel_ct curlio; +extern CWD_API channel_ct curltr; #endif diff --git a/indra/develop.py b/indra/develop.py index 60bc7f387..91db5cb97 100755 --- a/indra/develop.py +++ b/indra/develop.py @@ -766,13 +766,14 @@ Commands: Command-options for "configure": We use cmake variables to change the build configuration. - -DSERVER:BOOL=OFF Don't configure simulator/dataserver/etc - -DVIEWER:BOOL=OFF Don't configure the viewer - -DPACKAGE:BOOL=ON Create "package" target to make installers - -DLOCALIZESETUP:BOOL=ON Create one win_setup target per supported language - -DLL_TESTS:BOOL=OFF Don't generate unit test projects - -DEXAMPLEPLUGIN:BOOL=OFF Don't generate example plugin project - -VISTA_ICON:BOOL=ON Allow pre-2008 VS to use vista-optimized resource file. (Requires updated rcdll.dll!) + -DSERVER:BOOL=OFF Don't configure simulator/dataserver/etc + -DVIEWER:BOOL=OFF Don't configure the viewer + -DPACKAGE:BOOL=ON Create "package" target to make installers + -DLOCALIZESETUP:BOOL=ON Create one win_setup target per supported language + -DLL_TESTS:BOOL=OFF Don't generate unit test projects + -DEXAMPLEPLUGIN:BOOL=OFF Don't generate example plugin project + -DDISABLE_TCMALLOC:BOOL=ON Disable linkage of TCMalloc. (64bit builds automatically disable TCMalloc) + -DVISTA_ICON:BOOL=ON Allow pre-2008 VS to use vista-optimized resource file. (Requires updated rcdll.dll!) Examples: Set up a viewer-only project for your system: diff --git a/indra/libopenjpeg/CMakeLists.txt b/indra/libopenjpeg/CMakeLists.txt index 4325c7cc0..9ccc55126 100644 --- a/indra/libopenjpeg/CMakeLists.txt +++ b/indra/libopenjpeg/CMakeLists.txt @@ -7,14 +7,15 @@ include(00-Common) # OPENJPEG version number, useful for packaging and doxygen doc: set(OPENJPEG_VERSION_MAJOR 1) -set(OPENJPEG_VERSION_MINOR 4) -set(OPENJPEG_VERSION_BUILD 0) +set(OPENJPEG_VERSION_MINOR 5) +set(OPENJPEG_VERSION_BUILD 2) set(OPENJPEG_VERSION "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}") set(openjpeg_SOURCE_FILES bio.c cio.c + cidx_manager.c dwt.c event.c image.c @@ -26,20 +27,26 @@ set(openjpeg_SOURCE_FILES mqc.c openjpeg.c pi.c + phix_manager.c + ppix_manager.c raw.c t1.c t2.c tcd.c tgt.c + thix_manager.c + tpix_manager.c ) set(openjpeg_HEADER_FILES bio.h cio.h + cidx_manager.h dwt.h - event.h + event.h fix.h image.h + indexbox_manager.h int.h j2k.h j2k_lib.h @@ -48,6 +55,7 @@ set(openjpeg_HEADER_FILES mct.h mqc.h openjpeg.h + opj_config.h opj_includes.h opj_malloc.h pi.h diff --git a/indra/libopenjpeg/cidx_manager.c b/indra/libopenjpeg/cidx_manager.c new file mode 100644 index 000000000..f3b251ffa --- /dev/null +++ b/indra/libopenjpeg/cidx_manager.c @@ -0,0 +1,211 @@ +/* + * $Id: cidx_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opj_includes.h" + + +/* + * Write CPTR Codestream finder box + * + * @param[in] coff offset of j2k codestream + * @param[in] clen length of j2k codestream + * @param[in] cio file output handle + */ +void write_cptr(int coff, int clen, opj_cio_t *cio); + + +/* + * Write main header index table (box) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] cio file output handle + * @return length of mainmhix box + */ +int write_mainmhix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio); + + +/* + * Check if EPH option is used + * + * @param[in] coff offset of j2k codestream + * @param[in] markers marker information + * @param[in] marknum number of markers + * @param[in] cio file output handle + * @return true if EPH is used + */ +opj_bool check_EPHuse( int coff, opj_marker_info_t *markers, int marknum, opj_cio_t *cio); + + +int write_cidx( int offset, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t cstr_info, int j2klen) +{ + int len, i, lenp; + opj_jp2_box_t *box; + int num_box = 0; + opj_bool EPHused; + (void)image; /* unused ? */ + + lenp = -1; + box = (opj_jp2_box_t *)opj_calloc( 32, sizeof(opj_jp2_box_t)); + + for (i=0;i<2;i++){ + + if(i) + cio_seek( cio, lenp); + + lenp = cio_tell( cio); + + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_CIDX, 4); /* CIDX */ + write_cptr( offset, cstr_info.codestream_size, cio); + + write_manf( i, num_box, box, cio); + + num_box = 0; + box[num_box].length = write_mainmhix( offset, cstr_info, cio); + box[num_box].type = JPIP_MHIX; + num_box++; + + box[num_box].length = write_tpix( offset, cstr_info, j2klen, cio); + box[num_box].type = JPIP_TPIX; + num_box++; + + box[num_box].length = write_thix( offset, cstr_info, cio); + box[num_box].type = JPIP_THIX; + num_box++; + + EPHused = check_EPHuse( offset, cstr_info.marker, cstr_info.marknum, cio); + + box[num_box].length = write_ppix( offset, cstr_info, EPHused, j2klen, cio); + box[num_box].type = JPIP_PPIX; + num_box++; + + box[num_box].length = write_phix( offset, cstr_info, EPHused, j2klen, cio); + box[num_box].type = JPIP_PHIX; + num_box++; + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + } + + opj_free( box); + + return len; +} + +void write_cptr(int coff, int clen, opj_cio_t *cio) +{ + int len, lenp; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_CPTR, 4); /* T */ + cio_write( cio, 0, 2); /* DR A PRECISER !! */ + cio_write( cio, 0, 2); /* CONT */ + cio_write( cio, coff, 8); /* COFF A PRECISER !! */ + cio_write( cio, clen, 8); /* CLEN */ + len = cio_tell( cio) - lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); +} + +void write_manf(int second, int v, opj_jp2_box_t *box, opj_cio_t *cio) +{ + int len, lenp, i; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_MANF,4); /* T */ + + if (second){ /* Write only during the second pass */ + for( i=0; i> 2) & 1)) + EPHused = OPJ_TRUE; + cio_seek( cio, org_pos); + + break; + } + } + return EPHused; +} diff --git a/indra/libopenjpeg/cidx_manager.h b/indra/libopenjpeg/cidx_manager.h new file mode 100644 index 000000000..23eebd52b --- /dev/null +++ b/indra/libopenjpeg/cidx_manager.h @@ -0,0 +1,56 @@ +/* + * $Id: cidx_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * \brief Modification of jpip.h from 2KAN indexer + */ + + +#ifndef CIDX_MANAGER_H_ +# define CIDX_MANAGER_H_ + +#include "openjpeg.h" + + +/* + * Write Codestream index box (superbox) + * + * @param[in] offset offset of j2k codestream + * @param[in] cio file output handle + * @param[in] image image data + * @param[in] cstr_info codestream information + * @param[in] j2klen length of j2k codestream + * @return length of cidx box + */ +int write_cidx( int offset, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t cstr_info, int j2klen); + + +#endif /* !CIDX_MANAGER_H_ */ diff --git a/indra/libopenjpeg/cio.c b/indra/libopenjpeg/cio.c index 2ac262a1f..c0cb02827 100644 --- a/indra/libopenjpeg/cio.c +++ b/indra/libopenjpeg/cio.c @@ -126,13 +126,13 @@ unsigned char *cio_getbp(opj_cio_t *cio) { /* * Write a byte. */ -bool cio_byteout(opj_cio_t *cio, unsigned char v) { +opj_bool cio_byteout(opj_cio_t *cio, unsigned char v) { if (cio->bp >= cio->end) { opj_event_msg(cio->cinfo, EVT_ERROR, "write error\n"); - return false; + return OPJ_FALSE; } *cio->bp++ = v; - return true; + return OPJ_TRUE; } /* @@ -152,7 +152,7 @@ unsigned char cio_bytein(opj_cio_t *cio) { * v : value to write * n : number of bytes to write */ -unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n) { +unsigned int cio_write(opj_cio_t *cio, unsigned int64 v, int n) { int i; for (i = n - 1; i >= 0; i--) { if( !cio_byteout(cio, (unsigned char) ((v >> (i << 3)) & 0xff)) ) diff --git a/indra/libopenjpeg/cio.h b/indra/libopenjpeg/cio.h index 580bf9c0d..e62743141 100644 --- a/indra/libopenjpeg/cio.h +++ b/indra/libopenjpeg/cio.h @@ -31,6 +31,13 @@ #ifndef __CIO_H #define __CIO_H + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define int64 __int64 +#else +#define int64 long long +#endif + /** @file cio.h @brief Implementation of a byte input-output process (CIO) @@ -63,7 +70,7 @@ Write some bytes @param n Number of bytes to write @return Returns the number of bytes written or 0 if an error occured */ -unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n); +unsigned int cio_write(opj_cio_t *cio, unsigned int64 v, int n); /** Read some bytes @param cio CIO handle diff --git a/indra/libopenjpeg/dwt.c b/indra/libopenjpeg/dwt.c index 1d952c608..0fbfc2033 100644 --- a/indra/libopenjpeg/dwt.c +++ b/indra/libopenjpeg/dwt.c @@ -64,12 +64,12 @@ typedef struct v4dwt_local { int cas ; } v4dwt_t ; -static const float dwt_alpha = 1.586134342f; // 12994 -static const float dwt_beta = 0.052980118f; // 434 -static const float dwt_gamma = -0.882911075f; // -7233 -static const float dwt_delta = -0.443506852f; // -3633 +static const float dwt_alpha = 1.586134342f; /* 12994 */ +static const float dwt_beta = 0.052980118f; /* 434 */ +static const float dwt_gamma = -0.882911075f; /* -7233 */ +static const float dwt_delta = -0.443506852f; /* -3633 */ -static const float K = 1.230174105f; // 10078 +static const float K = 1.230174105f; /* 10078 */ /* FIXME: What is this constant? */ static const float c13318 = 1.625732422f; @@ -527,7 +527,7 @@ static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1 int w = tilec->x1 - tilec->x0; - h.mem = (int *)opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int)); + h.mem = (int*)opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int)); v.mem = h.mem; while( --numres) { @@ -570,7 +570,7 @@ static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, in int count = w->sn; int i, k; for(k = 0; k < 2; ++k){ - if (count + 3 * x < size && ((long) a & 0x0f) == 0 && ((long) bi & 0x0f) == 0 && (x & 0x0f) == 0) { + if (count + 3 * x < size && ((size_t) a & 0x0f) == 0 && ((size_t) bi & 0x0f) == 0 && (x & 0x0f) == 0) { /* Fast code path */ for(i = 0; i < count; ++i){ int j = i; diff --git a/indra/libopenjpeg/event.c b/indra/libopenjpeg/event.c index 000b8a81c..38db33a94 100644 --- a/indra/libopenjpeg/event.c +++ b/indra/libopenjpeg/event.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,6 +26,42 @@ #include "opj_includes.h" +/* ========================================================== + Utility functions + ==========================================================*/ + +#ifdef OPJ_CODE_NOT_USED +#ifndef _WIN32 +static char* +i2a(unsigned i, char *a, unsigned r) { + if (i/r > 0) a = i2a(i/r,a,r); + *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r]; + return a+1; +} + +/** + Transforms integer i into an ascii string and stores the result in a; + string is encoded in the base indicated by r. + @param i Number to be converted + @param a String result + @param r Base of value; must be in the range 2 - 36 + @return Returns a +*/ +static char * +_itoa(int i, char *a, int r) { + r = ((r < 2) || (r > 36)) ? 10 : r; + if(i < 0) { + *a = '-'; + *i2a(-i, a+1, r) = 0; + } + else *i2a(i, a, r) = 0; + return a; +} + +#endif /* !_WIN32 */ +#endif +/* ----------------------------------------------------------------------- */ + opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context) { if(cinfo) { opj_event_mgr_t *previous = cinfo->event_mgr; @@ -37,7 +73,7 @@ opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_ return NULL; } -bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) { +opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) { #define MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */ opj_msg_callback msg_handler = NULL; @@ -57,30 +93,29 @@ bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) { break; } if(msg_handler == NULL) { - return false; + return OPJ_FALSE; } } else { - return false; + return OPJ_FALSE; } if ((fmt != NULL) && (event_mgr != NULL)) { va_list arg; int str_length/*, i, j*/; /* UniPG */ char message[MSG_SIZE]; - memset(message, 0, MSG_SIZE); /* initialize the optional parameter list */ va_start(arg, fmt); - /* check the length of the format string */ - str_length = (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt); /* parse the format string and put the result in 'message' */ - vsprintf(message, fmt, arg); /* UniPG */ + str_length = vsnprintf(message, MSG_SIZE, fmt, arg); /* UniPG */ /* deinitialize the optional parameter list */ va_end(arg); /* output the message to the user program */ - msg_handler(message, cinfo->client_data); + if( str_length > -1 && str_length < MSG_SIZE ) + msg_handler(message, cinfo->client_data); + else return OPJ_FALSE; } - return true; + return OPJ_TRUE; } diff --git a/indra/libopenjpeg/event.h b/indra/libopenjpeg/event.h index 11910b0e4..9c59787ca 100644 --- a/indra/libopenjpeg/event.h +++ b/indra/libopenjpeg/event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Herv Drolon, FreeImage Team + * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,7 +49,7 @@ Write formatted data to a string and send the string to a user callback. @param fmt Format-control string (plus optionnal arguments) @return Returns true if successful, returns false otherwise */ -bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...); +opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...); /* ----------------------------------------------------------------------- */ /*@}*/ diff --git a/indra/libopenjpeg/image.c b/indra/libopenjpeg/image.c index 5c89346f6..a4d2c010a 100644 --- a/indra/libopenjpeg/image.c +++ b/indra/libopenjpeg/image.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Herv Drolon, FreeImage Team + * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,6 @@ opj_image_t* opj_image_create0(void) { opj_image_t *image = (opj_image_t*)opj_calloc(1, sizeof(opj_image_t)); - image->comps=NULL; return image; } diff --git a/indra/libopenjpeg/image.h b/indra/libopenjpeg/image.h index 04c362eb8..f828b5b77 100644 --- a/indra/libopenjpeg/image.h +++ b/indra/libopenjpeg/image.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Herv Drolon, FreeImage Team + * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/indra/libopenjpeg/indexbox_manager.h b/indra/libopenjpeg/indexbox_manager.h new file mode 100644 index 000000000..7364df62c --- /dev/null +++ b/indra/libopenjpeg/indexbox_manager.h @@ -0,0 +1,118 @@ +/* + * $Id: indexbox_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#ifndef INDEXBOX_MANAGER_H_ +# define INDEXBOX_MANAGER_H_ + +#include "openjpeg.h" +#include "j2k.h" /* needed to use jp2.h */ +#include "jp2.h" + +#define JPIP_CIDX 0x63696478 /* Codestream index */ +#define JPIP_CPTR 0x63707472 /* Codestream Finder Box */ +#define JPIP_MANF 0x6d616e66 /* Manifest Box */ +#define JPIP_FAIX 0x66616978 /* Fragment array Index box */ +#define JPIP_MHIX 0x6d686978 /* Main Header Index Table */ +#define JPIP_TPIX 0x74706978 /* Tile-part Index Table box */ +#define JPIP_THIX 0x74686978 /* Tile header Index Table box */ +#define JPIP_PPIX 0x70706978 /* Precinct Packet Index Table box */ +#define JPIP_PHIX 0x70686978 /* Packet Header index Table */ +#define JPIP_FIDX 0x66696478 /* File Index */ +#define JPIP_FPTR 0x66707472 /* File Finder */ +#define JPIP_PRXY 0x70727879 /* Proxy boxes */ +#define JPIP_IPTR 0x69707472 /* Index finder box */ +#define JPIP_PHLD 0x70686c64 /* Place holder */ + + +/* + * Write tile-part Index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of tpix box + */ +int write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio); + + +/* + * Write tile header index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information pointer + * @param[in] cio file output handle + * @return length of thix box + */ +int write_thix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio); + + +/* + * Write precinct packet index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] EPHused true if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of ppix box + */ +int write_ppix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio); + + +/* + * Write packet header index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] EPHused true if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of ppix box + */ +int write_phix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio); + +/* + * Wriet manifest box (box) + * + * @param[in] second number to be visited + * @param[in] v number of boxes + * @param[in] box box to be manifested + * @param[in] cio file output handle + */ +void write_manf(int second, int v, opj_jp2_box_t *box, opj_cio_t *cio); + + +#endif /* !INDEXBOX_MANAGER_H_ */ diff --git a/indra/libopenjpeg/j2k.c b/indra/libopenjpeg/j2k.c index b4e9f5aba..b81bd579c 100644 --- a/indra/libopenjpeg/j2k.c +++ b/indra/libopenjpeg/j2k.c @@ -6,6 +6,7 @@ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2010-2011, Kaori Hagihara * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -228,6 +229,23 @@ Read an unknown marker @param j2k J2K handle */ static void j2k_read_unk(opj_j2k_t *j2k); +/** +Add main header marker information +@param cstr_info Codestream information structure +@param type marker type +@param pos byte offset of marker segment +@param len length of marker segment + */ +static void j2k_add_mhmarker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len); +/** +Add tile header marker information +@param tileno tile index number +@param cstr_info Codestream information structure +@param type marker type +@param pos byte offset of marker segment +@param len length of marker segment + */ +static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len); /*@}*/ @@ -258,80 +276,6 @@ char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order){ return po->str_prog; } -void j2k_dump_image(FILE *fd, opj_image_t * img) { - int compno; - fprintf(fd, "image {\n"); - fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d\n", img->x0, img->y0, img->x1, img->y1); - fprintf(fd, " numcomps=%d\n", img->numcomps); - for (compno = 0; compno < img->numcomps; compno++) { - opj_image_comp_t *comp = &img->comps[compno]; - fprintf(fd, " comp %d {\n", compno); - fprintf(fd, " dx=%d, dy=%d\n", comp->dx, comp->dy); - fprintf(fd, " prec=%d\n", comp->prec); - //fprintf(fd, " bpp=%d\n", comp->bpp); - fprintf(fd, " sgnd=%d\n", comp->sgnd); - fprintf(fd, " }\n"); - } - fprintf(fd, "}\n"); -} - -void j2k_dump_cp(FILE *fd, opj_image_t * img, opj_cp_t * cp) { - int tileno, compno, layno, bandno, resno, numbands; - fprintf(fd, "coding parameters {\n"); - fprintf(fd, " tx0=%d, ty0=%d\n", cp->tx0, cp->ty0); - fprintf(fd, " tdx=%d, tdy=%d\n", cp->tdx, cp->tdy); - fprintf(fd, " tw=%d, th=%d\n", cp->tw, cp->th); - for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { - opj_tcp_t *tcp = &cp->tcps[tileno]; - fprintf(fd, " tile %d {\n", tileno); - fprintf(fd, " csty=%x\n", tcp->csty); - fprintf(fd, " prg=%d\n", tcp->prg); - fprintf(fd, " numlayers=%d\n", tcp->numlayers); - fprintf(fd, " mct=%d\n", tcp->mct); - fprintf(fd, " rates="); - for (layno = 0; layno < tcp->numlayers; layno++) { - fprintf(fd, "%.1f ", tcp->rates[layno]); - } - fprintf(fd, "\n"); - for (compno = 0; compno < img->numcomps; compno++) { - opj_tccp_t *tccp = &tcp->tccps[compno]; - fprintf(fd, " comp %d {\n", compno); - fprintf(fd, " csty=%x\n", tccp->csty); - fprintf(fd, " numresolutions=%d\n", tccp->numresolutions); - fprintf(fd, " cblkw=%d\n", tccp->cblkw); - fprintf(fd, " cblkh=%d\n", tccp->cblkh); - fprintf(fd, " cblksty=%x\n", tccp->cblksty); - fprintf(fd, " qmfbid=%d\n", tccp->qmfbid); - fprintf(fd, " qntsty=%d\n", tccp->qntsty); - fprintf(fd, " numgbits=%d\n", tccp->numgbits); - fprintf(fd, " roishift=%d\n", tccp->roishift); - fprintf(fd, " stepsizes="); - numbands = tccp->qntsty == J2K_CCP_QNTSTY_SIQNT ? 1 : tccp->numresolutions * 3 - 2; - for (bandno = 0; bandno < numbands; bandno++) { - fprintf(fd, "(%d,%d) ", tccp->stepsizes[bandno].mant, - tccp->stepsizes[bandno].expn); - } - fprintf(fd, "\n"); - - if (tccp->csty & J2K_CCP_CSTY_PRT) { - fprintf(fd, " prcw="); - for (resno = 0; resno < tccp->numresolutions; resno++) { - fprintf(fd, "%d ", tccp->prcw[resno]); - } - fprintf(fd, "\n"); - fprintf(fd, " prch="); - for (resno = 0; resno < tccp->numresolutions; resno++) { - fprintf(fd, "%d ", tccp->prch[resno]); - } - fprintf(fd, "\n"); - } - fprintf(fd, " }\n"); - } - fprintf(fd, " }\n"); - } - fprintf(fd, "}\n"); -} - /* ----------------------------------------------------------------------- */ static int j2k_get_num_tp(opj_cp_t *cp,int pino,int tileno){ char *prog; @@ -371,6 +315,9 @@ static int j2k_get_num_tp(opj_cp_t *cp,int pino,int tileno){ /** mem allocation for TLM marker*/ int j2k_calculate_tp(opj_cp_t *cp,int img_numcomp,opj_image_t *image,opj_j2k_t *j2k ){ int pino,tileno,totnum_tp=0; + + OPJ_ARG_NOT_USED(img_numcomp); + j2k->cur_totnum_tp = (int *) opj_malloc(cp->tw * cp->th * sizeof(int)); for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { int cur_totnum_tp = 0; @@ -399,12 +346,14 @@ static void j2k_write_soc(opj_j2k_t *j2k) { opj_cio_t *cio = j2k->cio; cio_write(cio, J2K_MS_SOC, 2); + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_SOC, cio_tell(cio), 0); + /* UniPG>> */ #ifdef USE_JPWL /* update markers struct */ j2k_add_marker(j2k->cstr_info, J2K_MS_SOC, cio_tell(cio) - 2, 2); - #endif /* USE_JPWL */ /* <cio; opj_image_t *image = j2k->image; opj_cp_t *cp = j2k->cp; - + cio_write(cio, J2K_MS_SIZ, 2); /* SIZ */ lenp = cio_tell(cio); cio_skip(cio, 2); @@ -448,6 +397,9 @@ static void j2k_write_siz(opj_j2k_t *j2k) { cio_seek(cio, lenp); cio_write(cio, len, 2); /* Lsiz */ cio_seek(cio, lenp + len); + + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_SIZ, lenp, len); } static void j2k_read_siz(opj_j2k_t *j2k) { @@ -516,6 +468,12 @@ static void j2k_read_siz(opj_j2k_t *j2k) { } #endif /* USE_JPWL */ + /* prevent division by zero */ + if (!(cp->tdx * cp->tdy)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: invalid tile size (tdx: %d, tdy: %d)\n", cp->tdx, cp->tdy); + return; + } + image->comps = (opj_image_comp_t*) opj_calloc(image->numcomps, sizeof(opj_image_comp_t)); for (i = 0; i < image->numcomps; i++) { int tmp, w, h; @@ -554,6 +512,12 @@ static void j2k_read_siz(opj_j2k_t *j2k) { } #endif /* USE_JPWL */ + /* prevent division by zero */ + if (!(image->comps[i].dx * image->comps[i].dy)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: invalid component size (dx: %d, dy: %d)\n", image->comps[i].dx, image->comps[i].dy); + return; + } + /* TODO: unused ? */ w = int_ceildiv(image->x1 - image->x0, image->comps[i].dx); h = int_ceildiv(image->y1 - image->y0, image->comps[i].dy); @@ -606,7 +570,17 @@ static void j2k_read_siz(opj_j2k_t *j2k) { #endif /* USE_JPWL */ cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); + if (cp->tcps == NULL) + { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n"); + return; + } cp->tileno = (int*) opj_malloc(cp->tw * cp->th * sizeof(int)); + if (cp->tileno == NULL) + { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n"); + return; + } cp->tileno_size = 0; #ifdef USE_JPWL @@ -678,6 +652,11 @@ static void j2k_write_com(opj_j2k_t *j2k) { cio_seek(cio, lenp); cio_write(cio, len, 2); cio_seek(cio, lenp + len); + + + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_COM, lenp, len); + } } @@ -721,12 +700,18 @@ static void j2k_read_cox(opj_j2k_t *j2k, int compno) { tccp->numresolutions = cio_read(cio, 1) + 1; /* SPcox (D) */ - // If user wants to remove more resolutions than the codestream contains, return error + /* If user wants to remove more resolutions than the codestream contains, return error*/ if (cp->reduce >= tccp->numresolutions) { opj_event_msg(j2k->cinfo, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions to remove is higher than the number " "of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno); j2k->state |= J2K_STATE_ERR; } + if( tccp->numresolutions > J2K_MAXRLVLS ) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions is too big: %d vs max= %d. Truncating.\n\n", + compno, tccp->numresolutions, J2K_MAXRLVLS); + j2k->state |= J2K_STATE_ERR; + tccp->numresolutions = J2K_MAXRLVLS; + } tccp->cblkw = cio_read(cio, 1) + 2; /* SPcox (E) */ tccp->cblkh = cio_read(cio, 1) + 2; /* SPcox (F) */ @@ -781,6 +766,10 @@ static void j2k_write_cod(opj_j2k_t *j2k) { cio_seek(cio, lenp); cio_write(cio, len, 2); /* Lcod */ cio_seek(cio, lenp + len); + + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_COD, lenp, len); + } static void j2k_read_cod(opj_j2k_t *j2k) { @@ -846,6 +835,12 @@ static void j2k_read_coc(opj_j2k_t *j2k) { len = cio_read(cio, 2); /* Lcoc */ compno = cio_read(cio, image->numcomps <= 256 ? 1 : 2); /* Ccoc */ + if (compno >= image->numcomps) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "bad component number in COC (%d out of a maximum of %d)\n", + compno, image->numcomps); + return; + } tcp->tccps[compno].csty = cio_read(cio, 1); /* Scoc */ j2k_read_cox(j2k, compno); } @@ -909,6 +904,15 @@ static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len) { }; }; + +#else + /* We check whether there are too many subbands */ + if ((numbands < 0) || (numbands >= J2K_MAXBANDS)) { + opj_event_msg(j2k->cinfo, EVT_WARNING , + "bad number of subbands in Sqcx (%d) regarding to J2K_MAXBANDS (%d) \n" + "- limiting number of bands to J2K_MAXBANDS and try to move to the next markers\n", numbands, J2K_MAXBANDS); + } + #endif /* USE_JPWL */ for (bandno = 0; bandno < numbands; bandno++) { @@ -921,8 +925,10 @@ static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len) { expn = tmp >> 11; mant = tmp & 0x7ff; } - tccp->stepsizes[bandno].expn = expn; - tccp->stepsizes[bandno].mant = mant; + if (bandno < J2K_MAXBANDS){ + tccp->stepsizes[bandno].expn = expn; + tccp->stepsizes[bandno].mant = mant; + } } /* Add Antonin : if scalar_derived -> compute other stepsizes */ @@ -950,6 +956,9 @@ static void j2k_write_qcd(opj_j2k_t *j2k) { cio_seek(cio, lenp); cio_write(cio, len, 2); /* Lqcd */ cio_seek(cio, lenp + len); + + if(j2k->cstr_info) + j2k_add_mhmarker(j2k->cstr_info, J2K_MS_QCD, lenp, len); } static void j2k_read_qcd(opj_j2k_t *j2k) { @@ -986,7 +995,7 @@ static void j2k_read_qcc(opj_j2k_t *j2k) { int len, compno; int numcomp = j2k->image->numcomps; opj_cio_t *cio = j2k->cio; - + len = cio_read(cio, 2); /* Lqcc */ compno = cio_read(cio, numcomp <= 256 ? 1 : 2); /* Cqcc */ @@ -1013,9 +1022,16 @@ static void j2k_read_qcc(opj_j2k_t *j2k) { /* keep your private count of tiles */ backup_compno++; - }; + } #endif /* USE_JPWL */ + if ((compno < 0) || (compno >= numcomp)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "bad component number in QCC (%d out of a maximum of %d)\n", + compno, j2k->image->numcomps); + return; + } + j2k_read_qcx(j2k, compno, len - 2 - (numcomp <= 256 ? 1 : 2)); } @@ -1271,6 +1287,10 @@ static void j2k_write_sot(opj_j2k_t *j2k) { j2k_add_marker(j2k->cstr_info, J2K_MS_SOT, j2k->sot_start, len + 2); #endif /* USE_JPWL */ /* <cstr_info && j2k->cur_tp_num==0){ + j2k_add_tlmarker( j2k->curtileno, j2k->cstr_info, J2K_MS_SOT, lenp, len); + } } static void j2k_read_sot(opj_j2k_t *j2k) { @@ -1354,6 +1374,11 @@ static void j2k_read_sot(opj_j2k_t *j2k) { partno = cio_read(cio, 1); numparts = cio_read(cio, 1); + + if (partno >= numparts) { + opj_event_msg(j2k->cinfo, EVT_WARNING, "SOT marker inconsistency in tile %d: tile-part index greater (%d) than number of tile-parts (%d)\n", tileno, partno, numparts); + numparts = partno+1; + } j2k->curtileno = tileno; j2k->cur_tp_num = partno; @@ -1369,15 +1394,14 @@ static void j2k_read_sot(opj_j2k_t *j2k) { j2k->cstr_info->tile[tileno].tileno = tileno; j2k->cstr_info->tile[tileno].start_pos = cio_tell(cio) - 12; j2k->cstr_info->tile[tileno].end_pos = j2k->cstr_info->tile[tileno].start_pos + totlen - 1; - j2k->cstr_info->tile[tileno].num_tps = numparts; - if (numparts) - j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(numparts * sizeof(opj_tp_info_t)); - else - j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(10 * sizeof(opj_tp_info_t)); // Fixme (10) - } - else { + } else { j2k->cstr_info->tile[tileno].end_pos += totlen; - } + } + j2k->cstr_info->tile[tileno].num_tps = numparts; + if (numparts) + j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_realloc(j2k->cstr_info->tile[tileno].tp, numparts * sizeof(opj_tp_info_t)); + else + j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_realloc(j2k->cstr_info->tile[tileno].tp, 10 * sizeof(opj_tp_info_t)); /* Fixme (10)*/ j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = cio_tell(cio) - 12; j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos = j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1; @@ -1413,6 +1437,11 @@ static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder) { tcd->cur_tp_num = j2k->cur_tp_num; cio_write(cio, J2K_MS_SOD, 2); + + if( j2k->cstr_info && j2k->cur_tp_num==0){ + j2k_add_tlmarker( j2k->curtileno, j2k->cstr_info, J2K_MS_SOD, cio_tell(cio), 0); + } + if (j2k->curtileno == 0) { j2k->sod_start = cio_tell(cio) + j2k->pos_correction; } @@ -1489,6 +1518,24 @@ static void j2k_read_sod(opj_j2k_t *j2k) { truncate = 1; /* Case of a truncate codestream */ } + {/* chop padding bytes: */ + unsigned char *s, *e; + + s = cio_getbp(cio); + e = s + len; + + if(len > 8) s = e - 8; + + if(e[-2] == 0x00 && e[-1] == 0x00) /* padding bytes */ + { + while(e > s) + { + if(e[-2] == 0xff && e[-1] == 0xd9) break; + --len; --e; truncate = 1; + } + } + } + data = j2k->tile_data[curtileno]; data = (unsigned char*) opj_realloc(data, (j2k->tile_len[curtileno] + len) * sizeof(unsigned char)); @@ -1548,6 +1595,13 @@ static void j2k_read_rgn(opj_j2k_t *j2k) { }; #endif /* USE_JPWL */ + if (compno >= numcomps) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "bad component number in RGN (%d out of a maximum of %d)\n", + compno, j2k->image->numcomps); + return; + } + tcp->tccps[compno].roishift = cio_read(cio, 1); /* SPrgn */ } @@ -1566,7 +1620,7 @@ static void j2k_write_eoc(opj_j2k_t *j2k) { static void j2k_read_eoc(opj_j2k_t *j2k) { int i, tileno; - bool success; + opj_bool success = OPJ_FALSE; /* if packets should be decoded */ if (j2k->cp->limit_decoding != DECODE_ALL_BUT_PACKETS) { @@ -1574,12 +1628,17 @@ static void j2k_read_eoc(opj_j2k_t *j2k) { tcd_malloc_decode(tcd, j2k->image, j2k->cp); for (i = 0; i < j2k->cp->tileno_size; i++) { tcd_malloc_decode_tile(tcd, j2k->image, j2k->cp, i, j2k->cstr_info); - tileno = j2k->cp->tileno[i]; - success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info); - opj_free(j2k->tile_data[tileno]); - j2k->tile_data[tileno] = NULL; - tcd_free_decode_tile(tcd, i); - if (success == false) { + if (j2k->cp->tileno[i] != -1) + { + tileno = j2k->cp->tileno[i]; + success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info); + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + tcd_free_decode_tile(tcd, i); + } + else + success = OPJ_FALSE; + if (success == OPJ_FALSE) { j2k->state |= J2K_STATE_ERR; break; } @@ -1749,6 +1808,14 @@ void j2k_destroy_decompress(opj_j2k_t *j2k) { opj_free(j2k->tile_len); } if(j2k->tile_data != NULL) { + if(j2k->cp != NULL) { + for (i = 0; i < j2k->cp->tileno_size; i++) { + int tileno = j2k->cp->tileno[i]; + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + } + } + opj_free(j2k->tile_data); } if(j2k->default_tcp != NULL) { @@ -1834,7 +1901,7 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c if (j2k->cp->correct) { int orig_pos = cio_tell(cio); - bool status; + opj_bool status; /* call the corrector */ status = jpwl_correct(j2k); @@ -1868,18 +1935,24 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c #endif /* USE_JPWL */ if (id >> 8 != 0xff) { - opj_image_destroy(image); - opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); - return 0; + if(cio_numbytesleft(cio) != 0) /* not end of file reached and no EOC */ + { + opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + opj_image_destroy(image); + return 0; + } + opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + j2k->state = J2K_STATE_NEOC; + break; } e = j2k_dec_mstab_lookup(id); - // Check if the marker is known + /* Check if the marker is known*/ if (!(j2k->state & e->states)) { opj_image_destroy(image); opj_event_msg(cinfo, EVT_ERROR, "%.8x: unexpected marker %x\n", cio_tell(cio) - 2, id); return 0; } - // Check if the decoding is limited to the main header + /* Check if the decoding is limited to the main header*/ if (e->id == J2K_MS_SOT && j2k->cp->limit_decoding == LIMIT_TO_MAIN_HEADER) { opj_event_msg(cinfo, EVT_INFO, "Main Header decoded.\n"); return image; @@ -1889,7 +1962,10 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c (*e->handler)(j2k); } if (j2k->state & J2K_STATE_ERR) + { + opj_image_destroy(image); return NULL; + } if (j2k->state == J2K_STATE_MT) { break; @@ -1905,7 +1981,6 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c if (j2k->state != J2K_STATE_MT) { opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n"); } - return image; } @@ -1917,9 +1992,10 @@ opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestre opj_image_t *image = NULL; opj_jpt_msg_header_t header; int position; - opj_common_ptr cinfo = j2k->cinfo; - + + OPJ_ARG_NOT_USED(cstr_info); + j2k->cio = cio; /* create an empty image */ @@ -1961,9 +2037,15 @@ opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestre id = cio_read(cio, 2); if (id >> 8 != 0xff) { - opj_image_destroy(image); - opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); - return 0; + if(cio_numbytesleft(cio) != 0) /* no end of file reached and no EOC */ + { + opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + opj_image_destroy(image); + return 0; + } + opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + j2k->state = J2K_STATE_NEOC; + break; } e = j2k_dec_mstab_lookup(id); if (!(j2k->state & e->states)) { @@ -2110,12 +2192,12 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ int i; /* set JPWL on */ - cp->epc_on = true; - cp->info_on = false; /* no informative technique */ + cp->epc_on = OPJ_TRUE; + cp->info_on = OPJ_FALSE; /* no informative technique */ /* set EPB on */ if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) { - cp->epb_on = true; + cp->epb_on = OPJ_TRUE; cp->hprot_MH = parameters->jpwl_hprot_MH; for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { @@ -2136,7 +2218,7 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ /* set ESD writing */ if ((parameters->jpwl_sens_size == 1) || (parameters->jpwl_sens_size == 2)) { - cp->esd_on = true; + cp->esd_on = OPJ_TRUE; cp->sens_size = parameters->jpwl_sens_size; cp->sens_addr = parameters->jpwl_sens_addr; @@ -2150,10 +2232,10 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ } /* always set RED writing to false: we are at the encoder */ - cp->red_on = false; + cp->red_on = OPJ_FALSE; } else { - cp->epc_on = false; + cp->epc_on = OPJ_FALSE; } #endif /* USE_JPWL */ @@ -2226,10 +2308,10 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ if(parameters->cp_cinema) { - //Precinct size for lowest frequency subband=128 + /*Precinct size for lowest frequency subband=128*/ tccp->prcw[0] = 7; tccp->prch[0] = 7; - //Precinct size at all other resolutions = 256 + /*Precinct size at all other resolutions = 256*/ for (j = 1; j < tccp->numresolutions; j++) { tccp->prcw[j] = 8; tccp->prch[j] = 8; @@ -2271,7 +2353,7 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ } p++; /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */ - } //end for + } /*end for*/ } else { for (j = 0; j < tccp->numresolutions; j++) { tccp->prcw[j] = 15; @@ -2285,7 +2367,7 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ } } -bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { +opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { int tileno, compno; opj_cp_t *cp = NULL; @@ -2296,8 +2378,6 @@ bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestre cp = j2k->cp; - /* j2k_dump_cp(stdout, image, cp); */ - /* INDEX >> */ j2k->cstr_info = cstr_info; if (cstr_info) { @@ -2394,6 +2474,9 @@ bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestre /* INDEX >> */ if(cstr_info) { cstr_info->tile[j2k->curtileno].start_pos = cio_tell(cio) + j2k->pos_correction; + cstr_info->tile[j2k->curtileno].maxmarknum = 10; + cstr_info->tile[j2k->curtileno].marker = (opj_marker_info_t *) opj_malloc(cstr_info->tile[j2k->curtileno].maxmarknum * sizeof(opj_marker_info_t)); + cstr_info->tile[j2k->curtileno].marknum = 0; } /* << INDEX */ @@ -2500,11 +2583,46 @@ bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestre } #endif /* USE_JPWL */ - return true; + return OPJ_TRUE; } +static void j2k_add_mhmarker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) { + if (!cstr_info) + return; + /* expand the list? */ + if ((cstr_info->marknum + 1) > cstr_info->maxmarknum) { + cstr_info->maxmarknum = 100 + (int) ((float) cstr_info->maxmarknum * 1.0F); + cstr_info->marker = (opj_marker_info_t*)opj_realloc(cstr_info->marker, cstr_info->maxmarknum); + } + /* add the marker */ + cstr_info->marker[cstr_info->marknum].type = type; + cstr_info->marker[cstr_info->marknum].pos = pos; + cstr_info->marker[cstr_info->marknum].len = len; + cstr_info->marknum++; +} +static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) { + + opj_marker_info_t *marker; + + if (!cstr_info) + return; + + /* expand the list? */ + if ((cstr_info->tile[tileno].marknum + 1) > cstr_info->tile[tileno].maxmarknum) { + cstr_info->tile[tileno].maxmarknum = 100 + (int) ((float) cstr_info->tile[tileno].maxmarknum * 1.0F); + cstr_info->tile[tileno].marker = (opj_marker_info_t*)opj_realloc(cstr_info->tile[tileno].marker, cstr_info->maxmarknum); + } + + marker = &(cstr_info->tile[tileno].marker[cstr_info->tile[tileno].marknum]); + + /* add the marker */ + marker->type = type; + marker->pos = pos; + marker->len = len; + cstr_info->tile[tileno].marknum++; +} diff --git a/indra/libopenjpeg/j2k.h b/indra/libopenjpeg/j2k.h index bb86e348e..6338c290d 100644 --- a/indra/libopenjpeg/j2k.h +++ b/indra/libopenjpeg/j2k.h @@ -265,15 +265,15 @@ typedef struct opj_cp { /* UniPG>> */ #ifdef USE_JPWL /** enables writing of EPC in MH, thus activating JPWL */ - bool epc_on; + opj_bool epc_on; /** enables writing of EPB, in case of activated JPWL */ - bool epb_on; + opj_bool epb_on; /** enables writing of ESD, in case of activated JPWL */ - bool esd_on; + opj_bool esd_on; /** enables writing of informative techniques of ESD, in case of activated JPWL */ - bool info_on; + opj_bool info_on; /** enables writing of RED, in case of activated JPWL */ - bool red_on; + opj_bool red_on; /** error protection method for MH (0,1,16,32,37-128) */ int hprot_MH; /** tile number of header protection specification (>=0) */ @@ -299,7 +299,7 @@ typedef struct opj_cp { /** sensitivity methods for TPHs (-1,0-7) */ int sens_TPH[JPWL_MAX_NO_TILESPECS]; /** enables JPWL correction at the decoder */ - bool correct; + opj_bool correct; /** expected number of components at the decoder */ int exp_comps; /** maximum number of tiles at the decoder */ @@ -436,10 +436,8 @@ Encode an image into a JPEG-2000 codestream @param cstr_info Codestream information structure if required, NULL otherwise @return Returns true if successful, returns false otherwise */ -bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); +opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); -void j2k_dump_image(FILE *fd, opj_image_t * img); -void j2k_dump_cp(FILE *fd, opj_image_t * img, opj_cp_t * cp); /* ----------------------------------------------------------------------- */ /*@}*/ diff --git a/indra/libopenjpeg/j2k_lib.c b/indra/libopenjpeg/j2k_lib.c index 91aee0071..a66e31e9a 100644 --- a/indra/libopenjpeg/j2k_lib.c +++ b/indra/libopenjpeg/j2k_lib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Herv Drolon, FreeImage Team + * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,18 +24,18 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifdef WIN32 +#ifdef _WIN32 #include #else #include #include #include -#endif /* WIN32 */ +#endif /* _WIN32 */ #include "opj_includes.h" double opj_clock(void) { -#ifdef WIN32 - /* WIN32: use QueryPerformance (very accurate) */ +#ifdef _WIN32 + /* _WIN32: use QueryPerformance (very accurate) */ LARGE_INTEGER freq , t ; /* freq is the clock speed of the CPU */ QueryPerformanceFrequency(&freq) ; diff --git a/indra/libopenjpeg/j2k_lib.h b/indra/libopenjpeg/j2k_lib.h index 7df4d3677..5f3406e51 100644 --- a/indra/libopenjpeg/j2k_lib.h +++ b/indra/libopenjpeg/j2k_lib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Herv Drolon, FreeImage Team + * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/indra/libopenjpeg/jp2.c b/indra/libopenjpeg/jp2.c index b2831cfb0..531bbfc92 100644 --- a/indra/libopenjpeg/jp2.c +++ b/indra/libopenjpeg/jp2.c @@ -5,6 +5,7 @@ * Copyright (c) 2002-2003, Yannick Verschueren * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2010-2011, Kaori Hagihara * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - #include "opj_includes.h" /** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ @@ -44,7 +44,7 @@ Read box headers @param box @return Returns true if successful, returns false otherwise */ -static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box); +static opj_bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box); /*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/ /** Read the IHDR box - Image Header box @@ -52,12 +52,11 @@ Read the IHDR box - Image Header box @param cio Input buffer stream @return Returns true if successful, returns false otherwise */ -static bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); +static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); -static bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); +static opj_bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio); -static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio); /** Write the FTYP box - File type box @param jp2 JP2 handle @@ -70,9 +69,9 @@ Read the FTYP box - File type box @param cio Input buffer stream @return Returns true if successful, returns false otherwise */ -static bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio); +static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio); static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); -static bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset); +static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset); static void jp2_write_jp(opj_cio_t *cio); /** Read the JP box - JPEG 2000 signature @@ -80,29 +79,92 @@ Read the JP box - JPEG 2000 signature @param cio Input buffer stream @return Returns true if successful, returns false otherwise */ -static bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio); +static opj_bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio); /** Decode the structure of a JP2 file @param jp2 JP2 handle @param cio Input buffer stream +@param color Collector for profile, cdef and pclr data @return Returns true if successful, returns false otherwise */ -static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio); - +static opj_bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_color_t *color); +/** +Apply collected palette data +@param color Collector for profile, cdef and pclr data +@param image +*/ +static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo); +/** +Collect palette data +@param jp2 JP2 handle +@param cio Input buffer stream +@param box +@param color Collector for profile, cdef and pclr data +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color); +/** +Collect component mapping data +@param jp2 JP2 handle +@param cio Input buffer stream +@param box +@param color Collector for profile, cdef and pclr data +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color); +/** +Collect colour specification data +@param jp2 JP2 handle +@param cio Input buffer stream +@param box +@param color Collector for profile, cdef and pclr data +@return Returns true if successful, returns false otherwise +*/ +static opj_bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color); +/** +Write file Index (superbox) +@param[in] offset_jp2c offset of jp2c box +@param[in] length_jp2c length of jp2c box +@param[in] offset_idx offset of cidx box +@param[in] length_idx length of cidx box +@param[in] cio file output handle +@return length of fidx box +*/ +static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio); +/** +Write index Finder box +@param[in] offset offset of fidx box +@param[in] length length of fidx box +@param[in] cio file output handle +*/ +static void write_iptr( int offset, int length, opj_cio_t *cio); +/** +Write proxy box +@param[in] offset_jp2c offset of jp2c box +@param[in] length_jp2c length of jp2c box +@param[in] offset_idx offset of cidx box +@param[in] length_idx length of cidx box +@param[in] cio file output handle +*/ +static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio); /*@}*/ /*@}*/ /* ----------------------------------------------------------------------- */ -static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box) { +static opj_bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box) { box->init_pos = cio_tell(cio); box->length = cio_read(cio, 4); box->type = cio_read(cio, 4); if (box->length == 1) { if (cio_read(cio, 4) != 0) { opj_event_msg(cinfo, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n"); - return false; + return OPJ_FALSE; } box->length = cio_read(cio, 4); if (box->length == 0) @@ -111,8 +173,12 @@ static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t else if (box->length == 0) { box->length = cio_numbytesleft(cio) + 8; } + if (box->length < 0) { + opj_event_msg(cinfo, EVT_ERROR, "Integer overflow in box->length\n"); + return OPJ_FALSE; // TODO: actually check jp2_read_boxhdr's return value + } - return true; + return OPJ_TRUE; } #if 0 @@ -139,15 +205,18 @@ static void jp2_write_url(opj_cio_t *cio, char *Idx_file) { } #endif -static bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { +static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { opj_jp2_box_t box; opj_common_ptr cinfo = jp2->cinfo; - jp2_read_boxhdr(cinfo, cio, &box); + if(jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } if (JP2_IHDR != box.type) { opj_event_msg(cinfo, EVT_ERROR, "Expected IHDR Marker\n"); - return false; + return OPJ_FALSE; } jp2->h = cio_read(cio, 4); /* HEIGHT */ @@ -163,10 +232,10 @@ static bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { if (cio_tell(cio) - box.init_pos != box.length) { opj_event_msg(cinfo, EVT_ERROR, "Error with IHDR Box\n"); - return false; + return OPJ_FALSE; } - return true; + return OPJ_TRUE; } static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { @@ -211,16 +280,19 @@ static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { } -static bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { +static opj_bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { unsigned int i; opj_jp2_box_t box; opj_common_ptr cinfo = jp2->cinfo; - jp2_read_boxhdr(cinfo, cio, &box); + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } if (JP2_BPCC != box.type) { opj_event_msg(cinfo, EVT_ERROR, "Expected BPCC Marker\n"); - return false; + return OPJ_FALSE; } for (i = 0; i < jp2->numcomps; i++) { @@ -229,10 +301,10 @@ static bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { if (cio_tell(cio) - box.init_pos != box.length) { opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n"); - return false; + return OPJ_FALSE; } - return true; + return OPJ_TRUE; } static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio) { @@ -246,11 +318,10 @@ static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio) { cio_write(cio, jp2->precedence, 1); /* PRECEDENCE */ cio_write(cio, jp2->approx, 1); /* APPROX */ - if (jp2->meth == 1) { - cio_write(cio, jp2->enumcs, 4); /* EnumCS */ - } else { - cio_write(cio, 0, 1); /* PROFILE (??) */ - } + if(jp2->meth == 2) + jp2->enumcs = 0; + + cio_write(cio, jp2->enumcs, 4); /* EnumCS */ box.length = cio_tell(cio) - box.init_pos; cio_seek(cio, box.init_pos); @@ -258,42 +329,483 @@ static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio) { cio_seek(cio, box.init_pos + box.length); } -static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio) { - opj_jp2_box_t box; +static void jp2_free_pclr(opj_jp2_color_t *color) +{ + opj_free(color->jp2_pclr->channel_sign); + opj_free(color->jp2_pclr->channel_size); + opj_free(color->jp2_pclr->entries); + + if(color->jp2_pclr->cmap) opj_free(color->jp2_pclr->cmap); + + opj_free(color->jp2_pclr); color->jp2_pclr = NULL; +} + +static void free_color_data(opj_jp2_color_t *color) +{ + if(color->jp2_pclr) + { + jp2_free_pclr(color); + } + if(color->jp2_cdef) + { + if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); + opj_free(color->jp2_cdef); + } + if(color->icc_profile_buf) opj_free(color->icc_profile_buf); +} + +static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo) +{ + opj_image_comp_t *old_comps, *new_comps; + unsigned char *channel_size, *channel_sign; + unsigned int *entries; + opj_jp2_cmap_comp_t *cmap; + int *src, *dst; + unsigned int j, max; + unsigned short i, nr_channels, cmp, pcol; + int k, top_k; + + channel_size = color->jp2_pclr->channel_size; + channel_sign = color->jp2_pclr->channel_sign; + entries = color->jp2_pclr->entries; + cmap = color->jp2_pclr->cmap; + nr_channels = color->jp2_pclr->nr_channels; + + old_comps = image->comps; + new_comps = (opj_image_comp_t*) + opj_malloc(nr_channels * sizeof(opj_image_comp_t)); + + for(i = 0; i < nr_channels; ++i) + { + pcol = cmap[i].pcol; cmp = cmap[i].cmp; + + if( pcol < nr_channels ) + new_comps[pcol] = old_comps[cmp]; + else + { + opj_event_msg(cinfo, EVT_ERROR, "Error with pcol value %d (max: %d). skipping\n", pcol, nr_channels); + continue; + } + + if(cmap[i].mtyp == 0) /* Direct use */ + { + old_comps[cmp].data = NULL; continue; + } +/* Palette mapping: */ + new_comps[pcol].data = (int*) + opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int)); + new_comps[pcol].prec = channel_size[i]; + new_comps[pcol].sgnd = channel_sign[i]; + } + top_k = color->jp2_pclr->nr_entries - 1; + + for(i = 0; i < nr_channels; ++i) + { +/* Direct use: */ + if(cmap[i].mtyp == 0) continue; + +/* Palette mapping: */ + cmp = cmap[i].cmp; pcol = cmap[i].pcol; + src = old_comps[cmp].data; + dst = new_comps[pcol].data; + max = new_comps[pcol].w * new_comps[pcol].h; + + for(j = 0; j < max; ++j) + { +/* The index */ + if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k; +/* The colour */ + dst[j] = entries[k * nr_channels + pcol]; + } + } + max = image->numcomps; + for(i = 0; i < max; ++i) + { + if(old_comps[i].data) opj_free(old_comps[i].data); + } + opj_free(old_comps); + image->comps = new_comps; + image->numcomps = nr_channels; + + jp2_free_pclr(color); + +}/* apply_pclr() */ + +static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color) +{ + opj_jp2_pclr_t *jp2_pclr; + unsigned char *channel_size, *channel_sign; + unsigned int *entries; + unsigned short nr_entries, nr_channels; + unsigned short i, j; + unsigned char uc; + + OPJ_ARG_NOT_USED(box); + OPJ_ARG_NOT_USED(jp2); + +/* Part 1, I.5.3.4: 'There shall be at most one Palette box inside + * a JP2 Header box' : +*/ + if(color->jp2_pclr) return OPJ_FALSE; + + nr_entries = (unsigned short)cio_read(cio, 2); /* NE */ + nr_channels = (unsigned short)cio_read(cio, 1);/* NPC */ + + entries = (unsigned int*) + opj_malloc(nr_channels * nr_entries * sizeof(unsigned int)); + channel_size = (unsigned char*)opj_malloc(nr_channels); + channel_sign = (unsigned char*)opj_malloc(nr_channels); + + jp2_pclr = (opj_jp2_pclr_t*)opj_malloc(sizeof(opj_jp2_pclr_t)); + jp2_pclr->channel_sign = channel_sign; + jp2_pclr->channel_size = channel_size; + jp2_pclr->entries = entries; + jp2_pclr->nr_entries = nr_entries; + jp2_pclr->nr_channels = nr_channels; + jp2_pclr->cmap = NULL; + + color->jp2_pclr = jp2_pclr; + + for(i = 0; i < nr_channels; ++i) + { + uc = cio_read(cio, 1); /* Bi */ + channel_size[i] = (uc & 0x7f) + 1; + channel_sign[i] = (uc & 0x80)?1:0; + } + + for(j = 0; j < nr_entries; ++j) + { + for(i = 0; i < nr_channels; ++i) + { +/* Cji */ + *entries++ = cio_read(cio, (channel_size[i]+7)>>3); + } + } + + return OPJ_TRUE; +}/* jp2_read_pclr() */ + +static opj_bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color) +{ + opj_jp2_cmap_comp_t *cmap; + unsigned short i, nr_channels; + + OPJ_ARG_NOT_USED(box); + OPJ_ARG_NOT_USED(jp2); + +/* Need nr_channels: */ + if(color->jp2_pclr == NULL) return OPJ_FALSE; + +/* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box + * inside a JP2 Header box' : +*/ + if(color->jp2_pclr->cmap) return OPJ_FALSE; + + nr_channels = color->jp2_pclr->nr_channels; + cmap = (opj_jp2_cmap_comp_t*) + opj_malloc(nr_channels * sizeof(opj_jp2_cmap_comp_t)); + + for(i = 0; i < nr_channels; ++i) + { + cmap[i].cmp = (unsigned short)cio_read(cio, 2); + cmap[i].mtyp = cio_read(cio, 1); + cmap[i].pcol = cio_read(cio, 1); + + } + color->jp2_pclr->cmap = cmap; + + return OPJ_TRUE; +}/* jp2_read_cmap() */ + +static void jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color) +{ + opj_jp2_cdef_info_t *info; + int color_space; + unsigned short i, n, cn, typ, asoc, acn; + + color_space = image->color_space; + info = color->jp2_cdef->info; + n = color->jp2_cdef->n; + + for(i = 0; i < n; ++i) + { +/* WATCH: acn = asoc - 1 ! */ + if((asoc = info[i].asoc) == 0) continue; + + cn = info[i].cn; typ = info[i].typ; acn = asoc - 1; + + if(cn != acn) + { + opj_image_comp_t saved; + + memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t)); + + info[i].asoc = cn + 1; + info[acn].asoc = info[acn].cn + 1; + } + } + if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); + + opj_free(color->jp2_cdef); color->jp2_cdef = NULL; + +}/* jp2_apply_cdef() */ + +static opj_bool jp2_read_cdef(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color) +{ + opj_jp2_cdef_info_t *info; + unsigned short i, n; + + OPJ_ARG_NOT_USED(box); + OPJ_ARG_NOT_USED(jp2); + +/* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box + * inside a JP2 Header box.' +*/ + if(color->jp2_cdef) return OPJ_FALSE; + + if((n = (unsigned short)cio_read(cio, 2)) == 0) return OPJ_FALSE; /* szukw000: FIXME */ + + info = (opj_jp2_cdef_info_t*) + opj_malloc(n * sizeof(opj_jp2_cdef_info_t)); + + color->jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); + color->jp2_cdef->info = info; + color->jp2_cdef->n = n; + + for(i = 0; i < n; ++i) + { + info[i].cn = (unsigned short)cio_read(cio, 2); + info[i].typ = (unsigned short)cio_read(cio, 2); + info[i].asoc = (unsigned short)cio_read(cio, 2); + + } + return OPJ_TRUE; +}/* jp2_read_cdef() */ + +static opj_bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_box_t *box, opj_jp2_color_t *color) +{ int skip_len; + opj_common_ptr cinfo; - opj_common_ptr cinfo = jp2->cinfo; +/* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour + * Specification boxes after the first.' +*/ + if(color->jp2_has_colr) return OPJ_FALSE; - jp2_read_boxhdr(cinfo, cio, &box); - do { - if (JP2_COLR != box.type) { - cio_skip(cio, box.length - 8); - jp2_read_boxhdr(cinfo, cio, &box); - } - } while(JP2_COLR != box.type); + cinfo = jp2->cinfo; jp2->meth = cio_read(cio, 1); /* METH */ jp2->precedence = cio_read(cio, 1); /* PRECEDENCE */ jp2->approx = cio_read(cio, 1); /* APPROX */ - if (jp2->meth == 1) { - jp2->enumcs = cio_read(cio, 4); /* EnumCS */ - } else { - /* skip PROFILE */ - skip_len = box.init_pos + box.length - cio_tell(cio); - if (skip_len < 0) { - opj_event_msg(cinfo, EVT_ERROR, "Error with JP2H box size\n"); - return false; - } - cio_skip(cio, box.init_pos + box.length - cio_tell(cio)); - } + if (jp2->meth == 1) + { + jp2->enumcs = cio_read(cio, 4); /* EnumCS */ + } + else + if (jp2->meth == 2) + { +/* skip PROFILE */ + skip_len = box->init_pos + box->length - cio_tell(cio); + if (skip_len < 0) + { + opj_event_msg(cinfo, EVT_ERROR, "Error with COLR box size\n"); + return OPJ_FALSE; + } + if(skip_len > 0) + { + unsigned char *start; + + start = cio_getbp(cio); + color->icc_profile_buf = (unsigned char*)opj_malloc(skip_len); + color->icc_profile_len = skip_len; + + cio_skip(cio, box->init_pos + box->length - cio_tell(cio)); + + memcpy(color->icc_profile_buf, start, skip_len); + } + } + + if (cio_tell(cio) - box->init_pos != box->length) + { + opj_event_msg(cinfo, EVT_ERROR, "Error with COLR Box\n"); + return OPJ_FALSE; + } + color->jp2_has_colr = 1; + + return OPJ_TRUE; +}/* jp2_read_colr() */ + +opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color) +{ + opj_jp2_box_t box; + int jp2h_end; + + opj_common_ptr cinfo = jp2->cinfo; + + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + do { + if (JP2_JP2H != box.type) + { + if (box.type == JP2_JP2C) + { + opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n"); + return OPJ_FALSE; + } + if (box.length <= 8) return OPJ_FALSE; + cio_skip(cio, box.length - 8); + + if(cio->bp >= cio->end) return OPJ_FALSE; + + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + } + } while(JP2_JP2H != box.type); + + if (!jp2_read_ihdr(jp2, cio)) + return OPJ_FALSE; + jp2h_end = box.init_pos + box.length; + + if (jp2->bpc == 255) + { + if (!jp2_read_bpcc(jp2, cio)) + return OPJ_FALSE; + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + + while(cio_tell(cio) < jp2h_end) + { + if(box.type == JP2_COLR) + { + if( !jp2_read_colr(jp2, cio, &box, color)) + { + if (box.length <= 8) return OPJ_FALSE; + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + continue; + } + if(box.type == JP2_CDEF && !jp2->ignore_pclr_cmap_cdef) + { + if( !jp2_read_cdef(jp2, cio, &box, color)) + { + if (box.length <= 8) return OPJ_FALSE; + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + continue; + } + if(box.type == JP2_PCLR && !jp2->ignore_pclr_cmap_cdef) + { + if( !jp2_read_pclr(jp2, cio, &box, color)) + { + if (box.length <= 8) return OPJ_FALSE; + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + continue; + } + if(box.type == JP2_CMAP && !jp2->ignore_pclr_cmap_cdef) + { + if( !jp2_read_cmap(jp2, cio, &box, color)) + { + if (box.length <= 8) return OPJ_FALSE; + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + } + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + continue; + } + if (box.length <= 8) return OPJ_FALSE; + cio_seek(cio, box.init_pos + 8); + cio_skip(cio, box.length - 8); + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; + + }/* while(cio_tell(cio) < box_end) */ + + cio_seek(cio, jp2h_end); + + /* Part 1, I.5.3.3 : 'must contain at least one' */ + return (color->jp2_has_colr == 1); + +}/* jp2_read_jp2h() */ + +opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, + opj_codestream_info_t *cstr_info) +{ + opj_common_ptr cinfo; + opj_image_t *image = NULL; + opj_jp2_color_t color; + + if(!jp2 || !cio) + { + return NULL; + } + memset(&color, 0, sizeof(opj_jp2_color_t)); + cinfo = jp2->cinfo; + +/* JP2 decoding */ + if(!jp2_read_struct(jp2, cio, &color)) + { + free_color_data(&color); + opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n"); + return NULL; + } + +/* J2K decoding */ + image = j2k_decode(jp2->j2k, cio, cstr_info); + + if(!image) + { + free_color_data(&color); + opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n"); + return NULL; + } + + if (!jp2->ignore_pclr_cmap_cdef){ + + /* Set Image Color Space */ + if (jp2->enumcs == 16) + image->color_space = CLRSPC_SRGB; + else if (jp2->enumcs == 17) + image->color_space = CLRSPC_GRAY; + else if (jp2->enumcs == 18) + image->color_space = CLRSPC_SYCC; + else + image->color_space = CLRSPC_UNKNOWN; + + if(color.jp2_cdef) + { + jp2_apply_cdef(image, &color); + } + if(color.jp2_pclr) + { +/* Part 1, I.5.3.4: Either both or none : */ + if( !color.jp2_pclr->cmap) + jp2_free_pclr(&color); + else + jp2_apply_pclr(&color, image, cinfo); + } + if(color.icc_profile_buf) + { + image->icc_profile_buf = color.icc_profile_buf; + color.icc_profile_buf = NULL; + image->icc_profile_len = color.icc_profile_len; + } + } + + return image; + +}/* opj_jp2_decode() */ - if (cio_tell(cio) - box.init_pos != box.length) { - opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n"); - return false; - } - return true; -} void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) { opj_jp2_box_t box; @@ -315,44 +827,6 @@ void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) { cio_seek(cio, box.init_pos + box.length); } -bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) { - opj_jp2_box_t box; - int skip_len; - - opj_common_ptr cinfo = jp2->cinfo; - - jp2_read_boxhdr(cinfo, cio, &box); - do { - if (JP2_JP2H != box.type) { - if (box.type == JP2_JP2C) { - opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n"); - return false; - } - cio_skip(cio, box.length - 8); - jp2_read_boxhdr(cinfo, cio, &box); - } - } while(JP2_JP2H != box.type); - - if (!jp2_read_ihdr(jp2, cio)) - return false; - - if (jp2->bpc == 255) { - if (!jp2_read_bpcc(jp2, cio)) - return false; - } - if (!jp2_read_colr(jp2, cio)) - return false; - - skip_len = box.init_pos + box.length - cio_tell(cio); - if (skip_len < 0) { - opj_event_msg(cinfo, EVT_ERROR, "Error with JP2H Box\n"); - return false; - } - cio_skip(cio, box.init_pos + box.length - cio_tell(cio)); - - return true; -} - static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { unsigned int i; opj_jp2_box_t box; @@ -374,17 +848,19 @@ static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { cio_seek(cio, box.init_pos + box.length); } -static bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { +static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { int i; opj_jp2_box_t box; opj_common_ptr cinfo = jp2->cinfo; - jp2_read_boxhdr(cinfo, cio, &box); - + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } if (JP2_FTYP != box.type) { opj_event_msg(cinfo, EVT_ERROR, "Expected FTYP Marker\n"); - return false; + return OPJ_FALSE; } jp2->brand = cio_read(cio, 4); /* BR */ @@ -398,10 +874,10 @@ static bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { if (cio_tell(cio) - box.init_pos != box.length) { opj_event_msg(cinfo, EVT_ERROR, "Error with FTYP Box\n"); - return false; + return OPJ_FALSE; } - return true; + return OPJ_TRUE; } static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { @@ -433,23 +909,28 @@ static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, op return box.length; } -static bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset) { +static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset) { opj_jp2_box_t box; opj_common_ptr cinfo = jp2->cinfo; - jp2_read_boxhdr(cinfo, cio, &box); + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } do { if(JP2_JP2C != box.type) { + if (box.length <= 8) return OPJ_FALSE; cio_skip(cio, box.length - 8); - jp2_read_boxhdr(cinfo, cio, &box); + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE; } } while(JP2_JP2C != box.type); *j2k_codestream_offset = cio_tell(cio); + if (box.length <= 8) return OPJ_FALSE; *j2k_codestream_length = box.length - 8; - return true; + return OPJ_TRUE; } static void jp2_write_jp(opj_cio_t *cio) { @@ -466,42 +947,107 @@ static void jp2_write_jp(opj_cio_t *cio) { cio_seek(cio, box.init_pos + box.length); } -static bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio) { +static opj_bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio) { opj_jp2_box_t box; opj_common_ptr cinfo = jp2->cinfo; - jp2_read_boxhdr(cinfo, cio, &box); + if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n"); + return OPJ_FALSE; + } if (JP2_JP != box.type) { opj_event_msg(cinfo, EVT_ERROR, "Expected JP Marker\n"); - return false; + return OPJ_FALSE; } if (0x0d0a870a != cio_read(cio, 4)) { opj_event_msg(cinfo, EVT_ERROR, "Error with JP Marker\n"); - return false; + return OPJ_FALSE; } if (cio_tell(cio) - box.init_pos != box.length) { opj_event_msg(cinfo, EVT_ERROR, "Error with JP Box size\n"); - return false; + return OPJ_FALSE; } - return true; + return OPJ_TRUE; } -static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio) { +static opj_bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, + opj_jp2_color_t *color) { if (!jp2_read_jp(jp2, cio)) - return false; + return OPJ_FALSE; if (!jp2_read_ftyp(jp2, cio)) - return false; - if (!jp2_read_jp2h(jp2, cio)) - return false; + return OPJ_FALSE; + if (!jp2_read_jp2h(jp2, cio, color)) + return OPJ_FALSE; if (!jp2_read_jp2c(jp2, cio, &jp2->j2k_codestream_length, &jp2->j2k_codestream_offset)) - return false; + return OPJ_FALSE; - return true; + return OPJ_TRUE; } + +static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio) +{ + int len, lenp; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_FIDX, 4); /* IPTR */ + + write_prxy( offset_jp2c, length_jp2c, offset_idx, length_idx, cio); + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; +} + +static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio) +{ + int len, lenp; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_PRXY, 4); /* IPTR */ + + cio_write( cio, offset_jp2c, 8); /* OOFF */ + cio_write( cio, length_jp2c, 4); /* OBH part 1 */ + cio_write( cio, JP2_JP2C, 4); /* OBH part 2 */ + + cio_write( cio, 1,1); /* NI */ + + cio_write( cio, offset_idx, 8); /* IOFF */ + cio_write( cio, length_idx, 4); /* IBH part 1 */ + cio_write( cio, JPIP_CIDX, 4); /* IBH part 2 */ + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); +} + +static void write_iptr( int offset, int length, opj_cio_t *cio) +{ + int len, lenp; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_IPTR, 4); /* IPTR */ + + cio_write( cio, offset, 8); + cio_write( cio, length, 8); + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); +} + + /* ----------------------------------------------------------------------- */ /* JP2 decoder interface */ /* ----------------------------------------------------------------------- */ @@ -539,42 +1085,7 @@ void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) { /* setup the J2K codec */ j2k_setup_decoder(jp2->j2k, parameters); /* further JP2 initializations go here */ -} - -opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info) { - opj_common_ptr cinfo; - opj_image_t *image = NULL; - - if(!jp2 || !cio) { - return NULL; - } - - cinfo = jp2->cinfo; - - /* JP2 decoding */ - if(!jp2_read_struct(jp2, cio)) { - opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n"); - return NULL; - } - - /* J2K decoding */ - image = j2k_decode(jp2->j2k, cio, cstr_info); - if(!image) { - opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n"); - return NULL; - } - - /* Set Image Color Space */ - if (jp2->enumcs == 16) - image->color_space = CLRSPC_SRGB; - else if (jp2->enumcs == 17) - image->color_space = CLRSPC_GRAY; - else if (jp2->enumcs == 18) - image->color_space = CLRSPC_SYCC; - else - image->color_space = CLRSPC_UNKNOWN; - - return image; + jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; } /* ----------------------------------------------------------------------- */ @@ -664,30 +1175,23 @@ void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_ for (i = 0; i < image->numcomps; i++) { jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7); } - - /* Colour Specification box */ - - if ((image->numcomps == 1 || image->numcomps == 3) && (jp2->bpc != 255)) { - jp2->meth = 1; /* METH: Enumerated colourspace */ - } else { - jp2->meth = 2; /* METH: Restricted ICC profile */ - } - if (jp2->meth == 1) { - if (image->color_space == 1) - jp2->enumcs = 16; /* sRGB as defined by IEC 6196621 */ - else if (image->color_space == 2) - jp2->enumcs = 17; /* greyscale */ - else if (image->color_space == 3) - jp2->enumcs = 18; /* YUV */ - } else { - jp2->enumcs = 0; /* PROFILE (??) */ - } + jp2->meth = 1; + if (image->color_space == 1) + jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2.1 */ + else if (image->color_space == 2) + jp2->enumcs = 17; /* greyscale */ + else if (image->color_space == 3) + jp2->enumcs = 18; /* YUV */ jp2->precedence = 0; /* PRECEDENCE */ jp2->approx = 0; /* APPROX */ - + + jp2->jpip_on = parameters->jpip_on; } -bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { +opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { + + int pos_iptr, pos_cidx, pos_jp2c, len_jp2c, len_cidx, end_pos, pos_fidx, len_fidx; + pos_jp2c = pos_iptr = -1; /* remove a warning */ /* JP2 encoding */ @@ -698,14 +1202,34 @@ bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestre /* JP2 Header box */ jp2_write_jp2h(jp2, cio); - /* J2K encoding */ - - if(!jp2_write_jp2c(jp2, cio, image, cstr_info)) { - opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n"); - return false; + if( jp2->jpip_on){ + pos_iptr = cio_tell( cio); + cio_skip( cio, 24); /* IPTR further ! */ + + pos_jp2c = cio_tell( cio); } - return true; + /* J2K encoding */ + if(!(len_jp2c = jp2_write_jp2c( jp2, cio, image, cstr_info))){ + opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n"); + return OPJ_FALSE; + } + + if( jp2->jpip_on){ + pos_cidx = cio_tell( cio); + + len_cidx = write_cidx( pos_jp2c+8, cio, image, *cstr_info, len_jp2c-8); + + pos_fidx = cio_tell( cio); + len_fidx = write_fidx( pos_jp2c, len_jp2c, pos_cidx, len_cidx, cio); + + end_pos = cio_tell( cio); + + cio_seek( cio, pos_iptr); + write_iptr( pos_fidx, len_fidx, cio); + + cio_seek( cio, end_pos); + } + + return OPJ_TRUE; } - - diff --git a/indra/libopenjpeg/jp2.h b/indra/libopenjpeg/jp2.h index 7e363be2e..acb643cad 100644 --- a/indra/libopenjpeg/jp2.h +++ b/indra/libopenjpeg/jp2.h @@ -46,11 +46,64 @@ #define JP2_COLR 0x636f6c72 /**< Colour specification box */ #define JP2_JP2C 0x6a703263 /**< Contiguous codestream box */ #define JP2_URL 0x75726c20 /**< URL box */ -#define JP2_DBTL 0x6474626c /**< ??? */ +#define JP2_DTBL 0x6474626c /**< Data Reference box */ #define JP2_BPCC 0x62706363 /**< Bits per component box */ #define JP2_JP2 0x6a703220 /**< File type fields */ +#define JP2_PCLR 0x70636c72 /**< Palette box */ +#define JP2_CMAP 0x636d6170 /**< Component Mapping box */ +#define JP2_CDEF 0x63646566 /**< Channel Definition box */ /* ----------------------------------------------------------------------- */ +/** +Channel description: channel index, type, assocation +*/ +typedef struct opj_jp2_cdef_info +{ + unsigned short cn, typ, asoc; +} opj_jp2_cdef_info_t; + +/** +Channel descriptions and number of descriptions +*/ +typedef struct opj_jp2_cdef +{ + opj_jp2_cdef_info_t *info; + unsigned short n; +} opj_jp2_cdef_t; + +/** +Component mappings: channel index, mapping type, palette index +*/ +typedef struct opj_jp2_cmap_comp +{ + unsigned short cmp; + unsigned char mtyp, pcol; +} opj_jp2_cmap_comp_t; + +/** +Palette data: table entries, palette columns +*/ +typedef struct opj_jp2_pclr +{ + unsigned int *entries; + unsigned char *channel_sign; + unsigned char *channel_size; + opj_jp2_cmap_comp_t *cmap; + unsigned short nr_entries, nr_channels; +} opj_jp2_pclr_t; + +/** +Collector for ICC profile, palette, component mapping, channel description +*/ +typedef struct opj_jp2_color +{ + unsigned char *icc_profile_buf; + int icc_profile_len; + + opj_jp2_cdef_t *jp2_cdef; + opj_jp2_pclr_t *jp2_pclr; + unsigned char jp2_has_colr; +} opj_jp2_color_t; /** JP2 component @@ -87,6 +140,8 @@ typedef struct opj_jp2 { opj_jp2_comps_t *comps; unsigned int j2k_codestream_offset; unsigned int j2k_codestream_length; + opj_bool jpip_on; + opj_bool ignore_pclr_cmap_cdef; } opj_jp2_t; /** @@ -111,9 +166,10 @@ void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio); Read the JP2H box - JP2 Header box (used in MJ2) @param jp2 JP2 handle @param cio Input buffer stream +@param ext Collector for profile, cdef and pclr data @return Returns true if successful, returns false otherwise */ -bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio); +opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color); /** Creates a JP2 decompression structure @param cinfo Codec context info @@ -139,7 +195,7 @@ Decode an image from a JPEG-2000 file stream @param cstr_info Codestream information structure if required, NULL otherwise @return Returns a decoded image if successful, returns NULL otherwise */ -opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info); +opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info); /** Creates a JP2 compression structure @param cinfo Codec context info @@ -167,7 +223,8 @@ Encode an image into a JPEG-2000 file stream @param cstr_info Codestream information structure if required, NULL otherwise @return Returns true if successful, returns false otherwise */ -bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); +opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); + /* ----------------------------------------------------------------------- */ /*@}*/ diff --git a/indra/libopenjpeg/mqc.c b/indra/libopenjpeg/mqc.c index 5d25238ee..14129fbf4 100644 --- a/indra/libopenjpeg/mqc.c +++ b/indra/libopenjpeg/mqc.c @@ -521,22 +521,21 @@ void mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int len) { unsigned int c; unsigned int *ip; unsigned char *end = mqc->end - 1; - mqc->buffer = opj_realloc(mqc->buffer, (2 * len + 1) * sizeof(unsigned int)); + mqc->buffer = opj_realloc(mqc->buffer, (len + 1) * sizeof(unsigned int)); ip = (unsigned int *) mqc->buffer; - while (bp != end) { + while (bp < end) { c = *(bp + 1); if (*bp == 0xff) { if (c > 0x8f) { - *ip = 0x0000ff18; + break; } else { - bp++; *ip = 0x00000017 | (c << 9); } } else { - bp++; *ip = 0x00000018 | (c << 8); } + bp++; ip++; } diff --git a/indra/libopenjpeg/openjpeg.c b/indra/libopenjpeg/openjpeg.c index 565c5caa0..180cc844a 100644 --- a/indra/libopenjpeg/openjpeg.c +++ b/indra/libopenjpeg/openjpeg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Herv Drolon, FreeImage Team + * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,17 +24,22 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifdef WIN32 +#ifdef _WIN32 #include -#endif /* WIN32 */ +#endif /* _WIN32 */ +#include "opj_config.h" #include "opj_includes.h" /* ---------------------------------------------------------------------- */ -#ifdef WIN32 +#ifdef _WIN32 #ifndef OPJ_STATIC BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + + OPJ_ARG_NOT_USED(lpReserved); + OPJ_ARG_NOT_USED(hModule); + switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH : break; @@ -48,19 +53,19 @@ DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } #endif /* OPJ_STATIC */ -#endif /* WIN32 */ +#endif /* _WIN32 */ /* ---------------------------------------------------------------------- */ const char* OPJ_CALLCONV opj_version(void) { - return OPENJPEG_VERSION; + return PACKAGE_VERSION; } opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format) { opj_dinfo_t *dinfo = (opj_dinfo_t*)opj_calloc(1, sizeof(opj_dinfo_t)); if(!dinfo) return NULL; - dinfo->is_decompressor = true; + dinfo->is_decompressor = OPJ_TRUE; switch(format) { case CODEC_J2K: case CODEC_JPT: @@ -120,9 +125,10 @@ void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *paramete parameters->decod_format = -1; parameters->cod_format = -1; + parameters->flags = 0; /* UniPG>> */ #ifdef USE_JPWL - parameters->jpwl_correct = false; + parameters->jpwl_correct = OPJ_FALSE; parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS; parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES; #endif /* USE_JPWL */ @@ -159,7 +165,7 @@ opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_cio_t *ci case CODEC_JPT: return j2k_decode_jpt_stream((opj_j2k_t*)dinfo->j2k_handle, cio, cstr_info); case CODEC_JP2: - return jp2_decode((opj_jp2_t*)dinfo->jp2_handle, cio, cstr_info); + return opj_jp2_decode((opj_jp2_t*)dinfo->jp2_handle, cio, cstr_info); case CODEC_UNKNOWN: default: break; @@ -171,7 +177,7 @@ opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_cio_t *ci opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format) { opj_cinfo_t *cinfo = (opj_cinfo_t*)opj_calloc(1, sizeof(opj_cinfo_t)); if(!cinfo) return NULL; - cinfo->is_decompressor = false; + cinfo->is_decompressor = OPJ_FALSE; switch(format) { case CODEC_J2K: /* get a J2K coder handle */ @@ -243,10 +249,10 @@ void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *paramete parameters->cp_disto_alloc = 0; parameters->cp_fixed_alloc = 0; parameters->cp_fixed_quality = 0; - + parameters->jpip_on = OPJ_FALSE; /* UniPG>> */ #ifdef USE_JPWL - parameters->jpwl_epc_on = false; + parameters->jpwl_epc_on = OPJ_FALSE; parameters->jpwl_hprot_MH = -1; /* -1 means unassigned */ { int i; @@ -296,7 +302,7 @@ void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *param } } -bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index) { +opj_bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index) { if (index != NULL) opj_event_msg((opj_common_ptr)cinfo, EVT_WARNING, "Set index to NULL when calling the opj_encode function.\n" "To extract the index, use the opj_encode_with_info() function.\n" @@ -304,20 +310,20 @@ bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *im return opj_encode_with_info(cinfo, cio, image, NULL); } -bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { +opj_bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { if(cinfo && cio && image) { switch(cinfo->codec_format) { case CODEC_J2K: return j2k_encode((opj_j2k_t*)cinfo->j2k_handle, cio, image, cstr_info); case CODEC_JP2: - return jp2_encode((opj_jp2_t*)cinfo->jp2_handle, cio, image, cstr_info); + return opj_jp2_encode((opj_jp2_t*)cinfo->jp2_handle, cio, image, cstr_info); case CODEC_JPT: case CODEC_UNKNOWN: default: break; } } - return false; + return OPJ_FALSE; } void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) { @@ -328,6 +334,7 @@ void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) { opj_free(tile_info->thresh); opj_free(tile_info->packet); opj_free(tile_info->tp); + opj_free(tile_info->marker); } opj_free(cstr_info->tile); opj_free(cstr_info->marker); diff --git a/indra/libopenjpeg/openjpeg.h b/indra/libopenjpeg/openjpeg.h index e12bf0ae7..59147c8b3 100644 --- a/indra/libopenjpeg/openjpeg.h +++ b/indra/libopenjpeg/openjpeg.h @@ -6,6 +6,7 @@ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2010-2011, Kaori Hagihara * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,7 +33,6 @@ #ifndef OPENJPEG_H #define OPENJPEG_H -#define OPENJPEG_VERSION "1.4.0.635" /* ========================================================== @@ -40,7 +40,7 @@ ========================================================== */ -#if defined(OPJ_STATIC) || !(defined(WIN32) || defined(__WIN32__)) +#if defined(OPJ_STATIC) || !defined(_WIN32) #define OPJ_API #define OPJ_CALLCONV #else @@ -53,38 +53,19 @@ that uses this DLL. This way any other project whose source files include this f OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols defined with this macro as being exported. */ -#ifdef OPJ_EXPORTS +#if defined(OPJ_EXPORTS) || defined(DLL_EXPORT) #define OPJ_API __declspec(dllexport) #else #define OPJ_API __declspec(dllimport) #endif /* OPJ_EXPORTS */ -#endif /* !OPJ_STATIC || !WIN32 */ +#endif /* !OPJ_STATIC || !_WIN32 */ -#ifndef __cplusplus -#if defined(HAVE_STDBOOL_H) -/* -The C language implementation does correctly provide the standard header -file "stdbool.h". - */ -#include -#else -/* -The C language implementation does not provide the standard header file -"stdbool.h" as required by ISO/IEC 9899:1999. Try to compensate for this -braindamage below. -*/ -#if !defined(bool) -#define bool int -#endif -#if !defined(true) -#define true 1 -#endif -#if !defined(false) -#define false 0 -#endif -#endif -#endif /* __cplusplus */ +typedef int opj_bool; +#define OPJ_TRUE 1 +#define OPJ_FALSE 0 +/* Avoid compile-time warning because parameter is not used */ +#define OPJ_ARG_NOT_USED(x) (void)(x) /* ========================================================== Useful constant definitions @@ -154,14 +135,18 @@ typedef enum COLOR_SPACE { CLRSPC_SYCC = 3 /**< YUV */ } OPJ_COLOR_SPACE; +#define ENUMCS_SRGB 16 +#define ENUMCS_GRAY 17 +#define ENUMCS_SYCC 18 + /** Supported codec */ typedef enum CODEC_FORMAT { CODEC_UNKNOWN = -1, /**< place-holder */ - CODEC_J2K = 0, /**< JPEG-2000 codestream : read/write */ - CODEC_JPT = 1, /**< JPT-stream (JPEG 2000, JPIP) : read only */ - CODEC_JP2 = 2 /**< JPEG-2000 file format : read/write */ + CODEC_J2K = 0, /**< JPEG-2000 codestream : read/write */ + CODEC_JPT = 1, /**< JPT-stream (JPEG 2000, JPIP) : read only */ + CODEC_JP2 = 2 /**< JPEG-2000 file format : read/write */ } OPJ_CODEC_FORMAT; /** @@ -244,7 +229,7 @@ Compression parameters */ typedef struct opj_cparameters { /** size of tile: tile_size_on = false (not in argument) or = true (in argument) */ - bool tile_size_on; + opj_bool tile_size_on; /** XTOsiz */ int cp_tx0; /** YTOsiz */ @@ -326,7 +311,7 @@ typedef struct opj_cparameters { /**@name JPWL encoding parameters */ /*@{*/ /** enables writing of EPC in MH, thus activating JPWL */ - bool jpwl_epc_on; + opj_bool jpwl_epc_on; /** error protection method for MH (0,1,16,32,37-128) */ int jpwl_hprot_MH; /** tile number of header protection specification (>=0) */ @@ -366,8 +351,12 @@ typedef struct opj_cparameters { char tp_flag; /** MCT (multiple component transform) */ char tcp_mct; + /** Enable JPIP indexing*/ + opj_bool jpip_on; } opj_cparameters_t; +#define OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG 0x0001 + /** Decompression parameters */ @@ -404,7 +393,7 @@ typedef struct opj_dparameters { /**@name JPWL decoding parameters */ /*@{*/ /** activates the JPWL correction capabilities */ - bool jpwl_correct; + opj_bool jpwl_correct; /** expected number of components */ int jpwl_exp_comps; /** maximum number of tiles */ @@ -420,6 +409,7 @@ typedef struct opj_dparameters { */ OPJ_LIMIT_DECODING cp_limit_decoding; + unsigned int flags; } opj_dparameters_t; /** Common fields between JPEG-2000 compression and decompression master structs. */ @@ -427,7 +417,7 @@ typedef struct opj_dparameters { #define opj_common_fields \ opj_event_mgr_t *event_mgr; /**< pointer to the event manager */\ void * client_data; /**< Available for use by application */\ - bool is_decompressor; /**< So common code can tell which is which */\ + opj_bool is_decompressor; /**< So common code can tell which is which */\ OPJ_CODEC_FORMAT codec_format; /**< selected codec */\ void *j2k_handle; /**< pointer to the J2K codec */\ void *jp2_handle; /**< pointer to the JP2 codec */\ @@ -555,6 +545,10 @@ typedef struct opj_image { OPJ_COLOR_SPACE color_space; /** image components */ opj_image_comp_t *comps; + /** 'restricted' ICC profile */ + unsigned char *icc_profile_buf; + /** size of ICC profile */ + int icc_profile_len; } opj_image_t; /** @@ -601,6 +595,21 @@ typedef struct opj_packet_info { double disto; } opj_packet_info_t; + +/* UniPG>> */ +/** +Marker structure +*/ +typedef struct opj_marker_info_t { + /** marker type */ + unsigned short int type; + /** position in codestream */ + int pos; + /** length, marker val included */ + int len; +} opj_marker_info_t; +/* <> */ -/** -Marker structure -*/ -typedef struct opj_marker_info_t { - /** marker type */ - unsigned short int type; - /** position in codestream */ - int pos; - /** length, marker val included */ - int len; -} opj_marker_info_t; -/* < Set to NULL. To extract index, used opj_encode_wci() @return Returns true if successful, returns false otherwise */ -OPJ_API bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index); +OPJ_API opj_bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index); /** Encode an image into a JPEG-2000 codestream and extract the codestream information @param cinfo compressor handle @@ -898,13 +899,14 @@ Encode an image into a JPEG-2000 codestream and extract the codestream informati @param cstr_info Codestream information structure if needed afterwards, NULL otherwise @return Returns true if successful, returns false otherwise */ -OPJ_API bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); +OPJ_API opj_bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); /** Destroy Codestream information after compression or decompression @param cstr_info Codestream information structure */ OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info); + #ifdef __cplusplus } #endif diff --git a/indra/libopenjpeg/opj_config.h b/indra/libopenjpeg/opj_config.h new file mode 100644 index 000000000..f8148c629 --- /dev/null +++ b/indra/libopenjpeg/opj_config.h @@ -0,0 +1,36 @@ +/* create config.h for CMake */ +#define PACKAGE_VERSION "1.5.2" + +#define HAVE_INTTYPES_H +#define HAVE_MEMORY_H +#define HAVE_STDINT_H +#define HAVE_STDLIB_H +#define HAVE_STRINGS_H +#define HAVE_STRING_H +#define HAVE_SYS_STAT_H +#define HAVE_SYS_TYPES_H +#define HAVE_UNISTD_H +/* #define HAVE_LIBPNG */ +/* #define HAVE_PNG_H */ +/* #define HAVE_LIBTIFF */ +/* #define HAVE_TIFF_H */ + +/* #undef HAVE_LIBLCMS1 */ +/* #undef HAVE_LIBLCMS2 */ +/* #undef HAVE_LCMS1_H */ +/* #undef HAVE_LCMS2_H */ + +/* Byte order. */ +/* All compilers that support Mac OS X define either __BIG_ENDIAN__ or + * __LITTLE_ENDIAN__ to match the endianness of the architecture being + * compiled for. This is not necessarily the same as the architecture of the + * machine doing the building. In order to support Universal Binaries on + * Mac OS X, we prefer those defines to decide the endianness. + * On other platforms we use the result of the TRY_RUN. */ +#if !defined(__APPLE__) +/* #undef OPJ_BIG_ENDIAN */ +#elif defined(__BIG_ENDIAN__) +# define OPJ_BIG_ENDIAN +#endif + + diff --git a/indra/libopenjpeg/opj_includes.h b/indra/libopenjpeg/opj_includes.h index 80d617e31..2b5866a99 100644 --- a/indra/libopenjpeg/opj_includes.h +++ b/indra/libopenjpeg/opj_includes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Herv Drolon, FreeImage Team + * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,20 +89,25 @@ Most compilers implement their own version of this keyword ... /* MSVC and Borland C do not have lrintf */ #if defined(_MSC_VER) || defined(__BORLANDC__) static INLINE long lrintf(float f){ - int i; - - _asm{ - fld f - fistp i - }; - - return i; +#ifdef _M_X64 + return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f)); +#else + int i; + + _asm{ + fld f + fistp i + }; + + return i; +#endif } #endif #include "j2k_lib.h" #include "opj_malloc.h" #include "event.h" +#include "bio.h" #include "cio.h" #include "image.h" @@ -123,9 +128,12 @@ static INLINE long lrintf(float f){ #include "int.h" #include "fix.h" +#include "cidx_manager.h" +#include "indexbox_manager.h" + /* JPWL>> */ #ifdef USE_JPWL -#include "../jpwl/jpwl.h" +#include "./jpwl/jpwl.h" #endif /* USE_JPWL */ /* < * All rights reserved. * @@ -69,7 +69,7 @@ Allocate memory aligned to a 16 byte boundry @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available */ /* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */ -#ifdef WIN32 +#ifdef _WIN32 /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */ #ifdef __GNUC__ #include @@ -80,11 +80,13 @@ Allocate memory aligned to a 16 byte boundry #define HAVE_MM_MALLOC #endif #endif -#else /* Not WIN32 */ +#else /* Not _WIN32 */ #if defined(__sun) #define HAVE_MEMALIGN + #elif defined(__FreeBSD__) + #define HAVE_POSIX_MEMALIGN /* Linux x86_64 and OSX always align allocations to 16 bytes */ - #elif !defined(__amd64__) && !defined(__APPLE__) + #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(_AIX) #define HAVE_MEMALIGN #include #endif @@ -130,22 +132,22 @@ Allocate memory aligned to a 16 byte boundry /** Reallocate memory blocks. -@param memblock Pointer to previously allocated memory block -@param size New size in bytes +@param m Pointer to previously allocated memory block +@param s New size in bytes @return Returns a void pointer to the reallocated (and possibly moved) memory block */ #ifdef ALLOC_PERF_OPT -void * OPJ_CALLCONV opj_realloc(void * _Memory, size_t NewSize); +void * OPJ_CALLCONV opj_realloc(void * m, size_t s); #else #define opj_realloc(m, s) realloc(m, s) #endif /** Deallocates or frees a memory block. -@param memblock Previously allocated memory block to be freed +@param m Previously allocated memory block to be freed */ #ifdef ALLOC_PERF_OPT -void OPJ_CALLCONV opj_free(void * _Memory); +void OPJ_CALLCONV opj_free(void * m); #else #define opj_free(m) free(m) #endif diff --git a/indra/libopenjpeg/phix_manager.c b/indra/libopenjpeg/phix_manager.c new file mode 100644 index 000000000..a04584785 --- /dev/null +++ b/indra/libopenjpeg/phix_manager.c @@ -0,0 +1,170 @@ +/* + * $Id: phix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include +#include +#include "opj_includes.h" + +/* + * Write faix box of phix + * + * @param[in] coff offset of j2k codestream + * @param[in] compno component number + * @param[in] cstr_info codestream information + * @param[in] EPHused true if if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of faix box + */ +int write_phixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio); + +int write_phix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio) +{ + int len, lenp=0, compno, i; + opj_jp2_box_t *box; + + box = (opj_jp2_box_t *)opj_calloc( cstr_info.numcomps, sizeof(opj_jp2_box_t)); + + for( i=0;i<2;i++){ + if (i) cio_seek( cio, lenp); + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_PHIX, 4); /* PHIX */ + + write_manf( i, cstr_info.numcomps, box, cio); + + for( compno=0; compno pow( 2.0, 32)){ + size_of_coding = 8; + version = 1; + } + else{ + size_of_coding = 4; + version = 0; + } + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_FAIX, 4); /* FAIX */ + cio_write( cio, version,1); /* Version 0 = 4 bytes */ + + nmax = 0; + for( i=0; i<=cstr_info.numdecompos[compno]; i++) + nmax += cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * cstr_info.numlayers; + + cio_write( cio, nmax, size_of_coding); /* NMAX */ + cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */ + + for( tileno=0; tilenopw[resno]*tile_Idx->ph[resno]; + for( precno=0; precnopacket[ ((layno*numOfres+resno)*cstr_info.numcomps+compno)*numOfprec+precno]; + break; + case RLCP: + packet = tile_Idx->packet[ ((resno*numOflayers+layno)*cstr_info.numcomps+compno)*numOfprec+precno]; + break; + case RPCL: + packet = tile_Idx->packet[ ((resno*numOfprec+precno)*cstr_info.numcomps+compno)*numOflayers+layno]; + break; + case PCRL: + packet = tile_Idx->packet[ ((precno*cstr_info.numcomps+compno)*numOfres+resno)*numOflayers + layno]; + break; + case CPRL: + packet = tile_Idx->packet[ ((compno*numOfprec+precno)*numOfres+resno)*numOflayers + layno]; + break; + default: + fprintf( stderr, "failed to ppix indexing\n"); + } + + cio_write( cio, packet.start_pos-coff, size_of_coding); /* start position */ + cio_write( cio, packet.end_ph_pos-packet.start_pos+1, size_of_coding); /* length */ + + num_packet++; + } + } + } + + /* PADDING */ + while( num_packet < nmax){ + cio_write( cio, 0, size_of_coding); /* start position */ + cio_write( cio, 0, size_of_coding); /* length */ + num_packet++; + } + } + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; +} diff --git a/indra/libopenjpeg/pi.c b/indra/libopenjpeg/pi.c index 06e76af76..e8e33bfe6 100644 --- a/indra/libopenjpeg/pi.c +++ b/indra/libopenjpeg/pi.c @@ -43,31 +43,31 @@ Get next packet in layer-resolution-component-precinct order. @param pi packet iterator to modify @return returns false if pi pointed to the last packet or else returns true */ -static bool pi_next_lrcp(opj_pi_iterator_t * pi); +static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi); /** Get next packet in resolution-layer-component-precinct order. @param pi packet iterator to modify @return returns false if pi pointed to the last packet or else returns true */ -static bool pi_next_rlcp(opj_pi_iterator_t * pi); +static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi); /** Get next packet in resolution-precinct-component-layer order. @param pi packet iterator to modify @return returns false if pi pointed to the last packet or else returns true */ -static bool pi_next_rpcl(opj_pi_iterator_t * pi); +static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi); /** Get next packet in precinct-component-resolution-layer order. @param pi packet iterator to modify @return returns false if pi pointed to the last packet or else returns true */ -static bool pi_next_pcrl(opj_pi_iterator_t * pi); +static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi); /** Get next packet in component-precinct-resolution-layer order. @param pi packet iterator to modify @return returns false if pi pointed to the last packet or else returns true */ -static bool pi_next_cprl(opj_pi_iterator_t * pi); +static opj_bool pi_next_cprl(opj_pi_iterator_t * pi); /*@}*/ @@ -79,7 +79,7 @@ static bool pi_next_cprl(opj_pi_iterator_t * pi); ========================================================== */ -static bool pi_next_lrcp(opj_pi_iterator_t * pi) { +static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi) { opj_pi_comp_t *comp = NULL; opj_pi_resolution_t *res = NULL; long index = 0; @@ -108,7 +108,7 @@ static bool pi_next_lrcp(opj_pi_iterator_t * pi) { index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; if (!pi->include[index]) { pi->include[index] = 1; - return true; + return OPJ_TRUE; } LABEL_SKIP:; } @@ -116,10 +116,10 @@ LABEL_SKIP:; } } - return false; + return OPJ_FALSE; } -static bool pi_next_rlcp(opj_pi_iterator_t * pi) { +static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi) { opj_pi_comp_t *comp = NULL; opj_pi_resolution_t *res = NULL; long index = 0; @@ -147,7 +147,7 @@ static bool pi_next_rlcp(opj_pi_iterator_t * pi) { index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; if (!pi->include[index]) { pi->include[index] = 1; - return true; + return OPJ_TRUE; } LABEL_SKIP:; } @@ -155,10 +155,10 @@ LABEL_SKIP:; } } - return false; + return OPJ_FALSE; } -static bool pi_next_rpcl(opj_pi_iterator_t * pi) { +static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi) { opj_pi_comp_t *comp = NULL; opj_pi_resolution_t *res = NULL; long index = 0; @@ -229,7 +229,7 @@ if (!pi->tp_on){ index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; if (!pi->include[index]) { pi->include[index] = 1; - return true; + return OPJ_TRUE; } LABEL_SKIP:; } @@ -238,10 +238,10 @@ LABEL_SKIP:; } } - return false; + return OPJ_FALSE; } -static bool pi_next_pcrl(opj_pi_iterator_t * pi) { +static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi) { opj_pi_comp_t *comp = NULL; opj_pi_resolution_t *res = NULL; long index = 0; @@ -310,7 +310,7 @@ static bool pi_next_pcrl(opj_pi_iterator_t * pi) { index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; if (!pi->include[index]) { pi->include[index] = 1; - return true; + return OPJ_TRUE; } LABEL_SKIP:; } @@ -319,10 +319,10 @@ LABEL_SKIP:; } } - return false; + return OPJ_FALSE; } -static bool pi_next_cprl(opj_pi_iterator_t * pi) { +static opj_bool pi_next_cprl(opj_pi_iterator_t * pi) { opj_pi_comp_t *comp = NULL; opj_pi_resolution_t *res = NULL; long index = 0; @@ -389,7 +389,7 @@ static bool pi_next_cprl(opj_pi_iterator_t * pi) { index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; if (!pi->include[index]) { pi->include[index] = 1; - return true; + return OPJ_TRUE; } LABEL_SKIP:; } @@ -398,7 +398,7 @@ LABEL_SKIP:; } } - return false; + return OPJ_FALSE; } /* @@ -707,7 +707,7 @@ void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno) { } } -bool pi_next(opj_pi_iterator_t * pi) { +opj_bool pi_next(opj_pi_iterator_t * pi) { switch (pi->poc.prg) { case LRCP: return pi_next_lrcp(pi); @@ -720,13 +720,13 @@ bool pi_next(opj_pi_iterator_t * pi) { case CPRL: return pi_next_cprl(pi); case PROG_UNKNOWN: - return false; + return OPJ_FALSE; } - return false; + return OPJ_FALSE; } -bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp){ +opj_bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp){ char prog[4]; int i; int incr_top=1,resetX=0; @@ -748,7 +748,7 @@ bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino, case RPCL: strncpy(prog, "RPCL",4); break; case PROG_UNKNOWN: - return true; + return OPJ_TRUE; } if(!(cp->tp_on && ((!cp->cinema && (t2_mode == FINAL_PASS)) || cp->cinema))){ @@ -958,6 +958,6 @@ bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino, } } } - return false; + return OPJ_FALSE; } diff --git a/indra/libopenjpeg/pi.h b/indra/libopenjpeg/pi.h index b5e0f6a4d..cf9135fd1 100644 --- a/indra/libopenjpeg/pi.h +++ b/indra/libopenjpeg/pi.h @@ -115,12 +115,14 @@ Modify the packet iterator for enabling tile part generation @param pi Handle to the packet iterator generated in pi_initialise_encode @param cp Coding parameters @param tileno Number that identifies the tile for which to list the packets +@param pino Iterator index for pi @param tpnum Tile part number of the current tile @param tppos The position of the tile part flag in the progression order +@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass @param cur_totnum_tp The total number of tile parts in the current tile @return Returns true if an error is detected */ -bool pi_create_encode(opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp); +opj_bool pi_create_encode(opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp); /** Create a packet iterator for Decoder @param image Raw image for which the packets will be listed @@ -145,7 +147,7 @@ Modify the packet iterator to point to the next packet @param pi Packet iterator to modify @return Returns false if pi pointed to the last packet or else returns true */ -bool pi_next(opj_pi_iterator_t * pi); +opj_bool pi_next(opj_pi_iterator_t * pi); /* ----------------------------------------------------------------------- */ /*@}*/ diff --git a/indra/libopenjpeg/ppix_manager.c b/indra/libopenjpeg/ppix_manager.c new file mode 100644 index 000000000..0e9326024 --- /dev/null +++ b/indra/libopenjpeg/ppix_manager.c @@ -0,0 +1,173 @@ +/* + * $Id: ppix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include +#include +#include +#include "opj_includes.h" + +/* + * Write faix box of ppix + * + * @param[in] coff offset of j2k codestream + * @param[in] compno component number + * @param[in] cstr_info codestream information + * @param[in] EPHused true if if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of faix box + */ +int write_ppixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio); + +int write_ppix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio) +{ + int len, lenp, compno, i; + opj_jp2_box_t *box; + + /* printf("cstr_info.packno %d\n", cstr_info.packno); //NMAX? */ + + lenp = -1; + box = (opj_jp2_box_t *)opj_calloc( cstr_info.numcomps, sizeof(opj_jp2_box_t)); + + for (i=0;i<2;i++){ + if (i) cio_seek( cio, lenp); + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_PPIX, 4); /* PPIX */ + + write_manf( i, cstr_info.numcomps, box, cio); + + for (compno=0; compno pow( 2.0, 32)){ + size_of_coding = 8; + version = 1; + } + else{ + size_of_coding = 4; + version = 0; + } + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_FAIX, 4); /* FAIX */ + cio_write( cio, version, 1); /* Version 0 = 4 bytes */ + + nmax = 0; + for( i=0; i<=cstr_info.numdecompos[compno]; i++) + nmax += cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * cstr_info.numlayers; + + cio_write( cio, nmax, size_of_coding); /* NMAX */ + cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */ + + for( tileno=0; tilenopw[resno]*tile_Idx->ph[resno]; + for( precno=0; precnopacket[ ((layno*numOfres+resno)*cstr_info.numcomps+compno)*numOfprec+precno]; + break; + case RLCP: + packet = tile_Idx->packet[ ((resno*numOflayers+layno)*cstr_info.numcomps+compno)*numOfprec+precno]; + break; + case RPCL: + packet = tile_Idx->packet[ ((resno*numOfprec+precno)*cstr_info.numcomps+compno)*numOflayers+layno]; + break; + case PCRL: + packet = tile_Idx->packet[ ((precno*cstr_info.numcomps+compno)*numOfres+resno)*numOflayers + layno]; + break; + case CPRL: + packet = tile_Idx->packet[ ((compno*numOfprec+precno)*numOfres+resno)*numOflayers + layno]; + break; + default: + fprintf( stderr, "failed to ppix indexing\n"); + } + + cio_write( cio, packet.start_pos-coff, size_of_coding); /* start position */ + cio_write( cio, packet.end_pos-packet.start_pos+1, size_of_coding); /* length */ + + num_packet++; + } + } + } + + while( num_packet < nmax){ /* PADDING */ + cio_write( cio, 0, size_of_coding); /* start position */ + cio_write( cio, 0, size_of_coding); /* length */ + num_packet++; + } + } + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; +} diff --git a/indra/libopenjpeg/t1.c b/indra/libopenjpeg/t1.c index 884f9f633..ed9cdc3fe 100644 --- a/indra/libopenjpeg/t1.c +++ b/indra/libopenjpeg/t1.c @@ -123,20 +123,20 @@ static void t1_enc_refpass_step( /** Decode refinement pass */ -static void INLINE t1_dec_refpass_step_raw( +static INLINE void t1_dec_refpass_step_raw( opj_t1_t *t1, flag_t *flagsp, int *datap, int poshalf, int neghalf, int vsc); -static void INLINE t1_dec_refpass_step_mqc( +static INLINE void t1_dec_refpass_step_mqc( opj_t1_t *t1, flag_t *flagsp, int *datap, int poshalf, int neghalf); -static void INLINE t1_dec_refpass_step_mqc_vsc( +static INLINE void t1_dec_refpass_step_mqc_vsc( opj_t1_t *t1, flag_t *flagsp, int *datap, @@ -240,6 +240,7 @@ Encode 1 code-block @param stepsize @param cblksty Code-block style @param numcomps +@param mct @param tile */ static void t1_encode_cblk( @@ -381,9 +382,10 @@ static INLINE void t1_dec_sigpass_step_raw( int vsc) { int v, flag; - opj_raw_t *raw = t1->raw; /* RAW component */ + OPJ_ARG_NOT_USED(orient); + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { if (raw_decode(raw)) { @@ -822,9 +824,10 @@ static void t1_dec_clnpass_step_partial( int oneplushalf) { int v, flag; - opj_mqc_t *mqc = t1->mqc; /* MQC component */ + OPJ_ARG_NOT_USED(orient); + flag = *flagsp; mqc_setcurctx(mqc, t1_getctxno_sc(flag)); v = mqc_decode(mqc) ^ t1_getspb(flag); @@ -1088,34 +1091,21 @@ static double t1_getwmsedec( int numcomps, int mct) { - double w1 = 1, w2, wmsedec; - - // Prevent running an MCT on more than 3 components. NB openjpeg v2.0 will support this via - // custom MCT tables that can be passed as encode parameters, 1.3 cannot support this as it - // uses a static table of 3 entries and there for can only cope with 3 components with out an - // array overflow - - if(numcomps==3) { - if (qmfbid == 1) { - w1 = (numcomps > 1) ? mct_getnorm(compno) : 1.0; - } else { - w1 = (numcomps > 1) ? mct_getnorm_real(compno) : 1.0; - } - } - + double w1, w2, wmsedec; if (qmfbid == 1) { + w1 = (mct && numcomps==3) ? mct_getnorm(compno) : 1.0; w2 = dwt_getnorm(level, orient); } else { /* if (qmfbid == 0) */ + w1 = (mct && numcomps==3) ? mct_getnorm_real(compno) : 1.0; w2 = dwt_getnorm_real(level, orient); } - wmsedec = w1 * w2 * stepsize * (1 << bpno); wmsedec *= wmsedec * nmsedec / 8192.0; return wmsedec; } -static bool allocate_buffers( +static opj_bool allocate_buffers( opj_t1_t *t1, int w, int h) @@ -1127,7 +1117,7 @@ static bool allocate_buffers( opj_aligned_free(t1->data); t1->data = (int*) opj_aligned_malloc(datasize * sizeof(int)); if(!t1->data){ - return false; + return OPJ_FALSE; } t1->datasize=datasize; } @@ -1140,7 +1130,7 @@ static bool allocate_buffers( opj_aligned_free(t1->flags); t1->flags = (flag_t*) opj_aligned_malloc(flagssize * sizeof(flag_t)); if(!t1->flags){ - return false; + return OPJ_FALSE; } t1->flagssize=flagssize; } @@ -1149,7 +1139,7 @@ static bool allocate_buffers( t1->w=w; t1->h=h; - return true; + return OPJ_TRUE; } /** mod fixed_quality */ @@ -1425,6 +1415,7 @@ void t1_encode_cblks( for (bandno = 0; bandno < res->numbands; ++bandno) { opj_tcd_band_t* restrict band = &res->bands[bandno]; + int bandconst = 8192 * 8192 / ((int) floor(band->stepsize * 8192)); for (precno = 0; precno < res->pw * res->ph; ++precno) { opj_tcd_precinct_t *prc = &band->precincts[precno]; @@ -1475,7 +1466,7 @@ void t1_encode_cblks( datap[(j * cblk_w) + i] = fix_mul( tmp, - 8192 * 8192 / ((int) floor(band->stepsize * 8192))) >> (11 - T1_NMSEDEC_FRACBITS); + bandconst) >> (11 - T1_NMSEDEC_FRACBITS); } } } @@ -1586,6 +1577,7 @@ void t1_decode_cblks( opj_free(cblk->segs); } /* cblkno */ opj_free(precinct->cblks.dec); + precinct->cblks.dec = NULL; } /* precno */ } /* bandno */ } /* resno */ diff --git a/indra/libopenjpeg/t1.h b/indra/libopenjpeg/t1.h index 0b4294e1d..572ec88d2 100644 --- a/indra/libopenjpeg/t1.h +++ b/indra/libopenjpeg/t1.h @@ -135,8 +135,8 @@ void t1_encode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp); /** Decode the code-blocks of a tile @param t1 T1 handle -@param tile The tile to decode -@param tcp Tile coding parameters +@param tilec The tile to decode +@param tccp Tile coding parameters */ void t1_decode_cblks(opj_t1_t* t1, opj_tcd_tilecomp_t* tilec, opj_tccp_t* tccp); /* ----------------------------------------------------------------------- */ diff --git a/indra/libopenjpeg/t2.c b/indra/libopenjpeg/t2.c index a76f4ed26..cae29f09b 100644 --- a/indra/libopenjpeg/t2.c +++ b/indra/libopenjpeg/t2.c @@ -59,11 +59,12 @@ Encode a packet of a tile to a destination buffer */ static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi, unsigned char *dest, int len, opj_codestream_info_t *cstr_info, int tileno); /** -@param seg +@param cblk +@param index @param cblksty @param first */ -static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first); +static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first); /** Decode a packet of a tile from a source buffer @param t2 T2 handle @@ -72,6 +73,7 @@ Decode a packet of a tile from a source buffer @param tile Tile for which to write the packets @param tcp Tile coding parameters @param pi Packet identity +@param pack_info Packet information @return */ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, @@ -147,8 +149,8 @@ static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_itera c[1] = 145; c[2] = 0; c[3] = 4; - c[4] = (tile->packno % 65536) / 256; - c[5] = (tile->packno % 65536) % 256; + c[4] = (unsigned char)((tile->packno % 65536) / 256); + c[5] = (unsigned char)((tile->packno % 65536) % 256); c += 6; } /* */ @@ -253,8 +255,8 @@ static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_itera /* */ /* << INDEX */ - // End of packet header position. Currently only represents the distance to start of packet - // Will be updated later by incrementing with packet start value + /* End of packet header position. Currently only represents the distance to start of packet + // Will be updated later by incrementing with packet start value */ if(cstr_info && cstr_info->index_write) { opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; info_PK->end_ph_pos = (int)(c - dest); @@ -294,9 +296,17 @@ static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_itera return (c - dest); } -static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) { +static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) { opj_tcd_seg_t* seg; - cblk->segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t)); + opj_tcd_seg_t* segs; + segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t)); + + if (segs == NULL) + { + return OPJ_FALSE; + } + cblk->segs = segs; + seg = &cblk->segs[index]; seg->data = NULL; seg->dataindex = 0; @@ -314,6 +324,8 @@ static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int fi } else { seg->maxpasses = 109; } + + return OPJ_TRUE; } static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, @@ -401,8 +413,8 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t } /* << INDEX */ - // End of packet header position. Currently only represents the distance to start of packet - // Will be updated later by incrementing with packet start value + /* End of packet header position. Currently only represents the distance to start of packet + // Will be updated later by incrementing with packet start value*/ if(pack_info) { pack_info->end_ph_pos = (int)(c - src); } @@ -460,12 +472,22 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t cblk->numlenbits += increment; segno = 0; if (!cblk->numsegs) { - t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1); + if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1)) + { + opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n"); + bio_destroy(bio); + return -999; + } } else { segno = cblk->numsegs - 1; if (cblk->segs[segno].numpasses == cblk->segs[segno].maxpasses) { ++segno; - t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0); + if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0)) + { + opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n"); + bio_destroy(bio); + return -999; + } } } n = cblk->numnewpasses; @@ -476,7 +498,12 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t n -= cblk->segs[segno].numnewpasses; if (n > 0) { ++segno; - t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0); + if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0)) + { + opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n"); + bio_destroy(bio); + return -999; + } } } while (n > 0); } @@ -494,14 +521,15 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t if (tcp->csty & J2K_CP_CSTY_EPH) { if ((*hd) != 0xff || (*(hd + 1) != 0x92)) { opj_event_msg(t2->cinfo, EVT_ERROR, "Expected EPH marker\n"); + return -999; } else { hd += 2; } } /* << INDEX */ - // End of packet header position. Currently only represents the distance to start of packet - // Will be updated later by incrementing with packet start value + /* End of packet header position. Currently only represents the distance to start of packet + // Will be updated later by incrementing with packet start value*/ if(pack_info) { pack_info->end_ph_pos = (int)(hd - src); } @@ -565,7 +593,7 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t #endif /* USE_JPWL */ - cblk->data = (unsigned char*) opj_realloc(cblk->data, (cblk->len + seg->newlen) * sizeof(unsigned char*)); + cblk->data = (unsigned char*) opj_realloc(cblk->data, (cblk->len + seg->newlen) * sizeof(unsigned char)); memcpy(cblk->data + cblk->len, c, seg->newlen); if (seg->numpasses == 0) { seg->data = &cblk->data; @@ -659,8 +687,8 @@ int t2_encode_packets(opj_t2_t* t2,int tileno, opj_tcd_tile_t *tile, int maxlaye info_PK->start_pos = ((cp->tp_on | tcp->POC)&& info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1; } info_PK->end_pos = info_PK->start_pos + e - 1; - info_PK->end_ph_pos += info_PK->start_pos - 1; // End of packet header which now only represents the distance - // to start of packet is incremented by value of start of packet + info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance + // to start of packet is incremented by value of start of packet*/ } cstr_info->packno++; @@ -711,7 +739,11 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj } else { e = 0; } - + if(e == -999) + { + pi_destroy(pi, cp, tileno); + return -999; + } /* progression in resolution */ image->comps[pi[pino].compno].resno_decoded = (e > 0) ? @@ -725,8 +757,9 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno]; if (!cstr_info->packno) { info_PK->start_pos = info_TL->end_header + 1; - } else if (info_TL->packet[cstr_info->packno-1].end_pos >= (int)cstr_info->tile[tileno].tp[curtp].tp_end_pos){ // New tile part - info_TL->tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; // Number of packets in previous tile-part + } else if (info_TL->packet[cstr_info->packno-1].end_pos >= (int)cstr_info->tile[tileno].tp[curtp].tp_end_pos){ /* New tile part*/ + info_TL->tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; /* Number of packets in previous tile-part*/ + info_TL->tp[curtp].tp_start_pack = tp_start_packno; tp_start_packno = cstr_info->packno; curtp++; info_PK->start_pos = cstr_info->tile[tileno].tp[curtp].tp_end_header+1; @@ -734,8 +767,8 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj info_PK->start_pos = (cp->tp_on && info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1; } info_PK->end_pos = info_PK->start_pos + e - 1; - info_PK->end_ph_pos += info_PK->start_pos - 1; // End of packet header which now only represents the distance - // to start of packet is incremented by value of start of packet + info_PK->end_ph_pos += info_PK->start_pos - 1; /* End of packet header which now only represents the distance + // to start of packet is incremented by value of start of packet*/ cstr_info->packno++; } /* << INDEX */ @@ -749,7 +782,8 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj } /* INDEX >> */ if(cstr_info) { - cstr_info->tile[tileno].tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; // Number of packets in last tile-part + cstr_info->tile[tileno].tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; /* Number of packets in last tile-part*/ + cstr_info->tile[tileno].tp[curtp].tp_start_pack = tp_start_packno; } /* << INDEX */ diff --git a/indra/libopenjpeg/t2.h b/indra/libopenjpeg/t2.h index b15b75200..2151ba67f 100644 --- a/indra/libopenjpeg/t2.h +++ b/indra/libopenjpeg/t2.h @@ -67,6 +67,7 @@ Encode the packets of a tile to a destination buffer @param cstr_info Codestream information structure @param tpnum Tile part number of the current tile @param tppos The position of the tile part flag in the progression order +@param pino @param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass @param cur_totnum_tp The total number of tile parts in the current tile */ @@ -78,6 +79,7 @@ Decode the packets of a tile from a source buffer @param len length of the source buffer @param tileno number that identifies the tile for which to decode the packets @param tile tile for which to decode the packets +@param cstr_info Codestream information structure */ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile, opj_codestream_info_t *cstr_info); diff --git a/indra/libopenjpeg/tcd.c b/indra/libopenjpeg/tcd.c index d29a0157b..ee0520556 100644 --- a/indra/libopenjpeg/tcd.c +++ b/indra/libopenjpeg/tcd.c @@ -30,10 +30,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#define _ISOC99_SOURCE /* lrintf is C99 */ #include "opj_includes.h" void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) { - int tileno, compno, resno, bandno, precno;//, cblkno; + int tileno, compno, resno, bandno, precno;/*, cblkno;*/ fprintf(fd, "image {\n"); fprintf(fd, " tw=%d, th=%d x0=%d x1=%d y0=%d y1=%d\n", @@ -290,6 +291,7 @@ void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int c for (i = 0; i < res->pw * res->ph * 3; i++) { band->precincts[i].imsbtree = NULL; band->precincts[i].incltree = NULL; + band->precincts[i].cblks.enc = NULL; } for (precno = 0; precno < res->pw * res->ph; precno++) { @@ -332,8 +334,10 @@ void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int c cblk->y0 = int_max(cblkystart, prc->y0); cblk->x1 = int_min(cblkxend, prc->x1); cblk->y1 = int_min(cblkyend, prc->y1); - cblk->data = (unsigned char*) opj_calloc(8192+2, sizeof(unsigned char)); + cblk->data = (unsigned char*) opj_calloc(9728+2, sizeof(unsigned char)); /* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */ + cblk->data[0] = 0; + cblk->data[1] = 0; cblk->data += 2; cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t)); cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t)); @@ -593,6 +597,8 @@ void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int cur cblk->y1 = int_min(cblkyend, prc->y1); cblk->data = (unsigned char*) opj_calloc(8192+2, sizeof(unsigned char)); /* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */ + cblk->data[0] = 0; + cblk->data[1] = 0; cblk->data += 2; cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t)); cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t)); @@ -613,7 +619,7 @@ void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) { tcd->image = image; tcd->tcd_image->tw = cp->tw; tcd->tcd_image->th = cp->th; - tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tcd_tile_t)); + tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_calloc(cp->tw * cp->th, sizeof(opj_tcd_tile_t)); /* Allocate place to store the decoded data = final image @@ -656,7 +662,7 @@ void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) { tilec->y1 = int_ceildiv(tile->y1, image->comps[i].dy); x0 = j == 0 ? tilec->x0 : int_min(x0, (unsigned int) tilec->x0); - y0 = j == 0 ? tilec->y0 : int_min(y0, (unsigned int) tilec->x0); + y0 = j == 0 ? tilec->y0 : int_min(y0, (unsigned int) tilec->y0); x1 = j == 0 ? tilec->x1 : int_max(x1, (unsigned int) tilec->x1); y1 = j == 0 ? tilec->y1 : int_max(y1, (unsigned int) tilec->y1); } @@ -676,6 +682,8 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, opj_tcp_t *tcp; opj_tcd_tile_t *tile; + OPJ_ARG_NOT_USED(cstr_info); + tcd->cp = cp; tcp = &(cp->tcps[cp->tileno[tileno]]); @@ -687,6 +695,12 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, opj_tccp_t *tccp = &tcp->tccps[compno]; opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + if (tccp->numresolutions <= 0) + { + cp->tileno[tileno] = -1; + return; + } + /* border of each tile component (global) */ tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx); tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy); @@ -997,7 +1011,7 @@ void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final) { } } -bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) { +opj_bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) { int compno, resno, bandno, precno, cblkno, passno, layno; double min, max; double cumdisto[100]; /* fixed_quality */ @@ -1149,7 +1163,7 @@ bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestre } if (!success) { - return false; + return OPJ_FALSE; } if(cstr_info) { /* Threshold for Marcela Index */ @@ -1161,7 +1175,7 @@ bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestre cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); } - return true; + return OPJ_TRUE; } int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) { @@ -1313,7 +1327,7 @@ int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, op return l; } -bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info) { +opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info) { int l; int compno; int eof = 0; @@ -1349,7 +1363,7 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op } else { cstr_info->tile[tileno].pdx[resno] = 15; - cstr_info->tile[tileno].pdx[resno] = 15; + cstr_info->tile[tileno].pdy[resno] = 15; } } } @@ -1373,14 +1387,24 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op t1_time = opj_clock(); /* time needed to decode a tile */ t1 = t1_create(tcd->cinfo); + if (t1 == NULL) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n"); + t1_destroy(t1); + return OPJ_FALSE; + } + for (compno = 0; compno < tile->numcomps; ++compno) { opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; /* The +3 is headroom required by the vectorized DWT */ tilec->data = (int*) opj_aligned_malloc((((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0))+3) * sizeof(int)); - if(tilec->data) - t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]); - else - opj_event_msg(tcd->cinfo, EVT_ERROR, "tcd_decode: tile size invalid\n"); + if (tilec->data == NULL) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n"); + return OPJ_FALSE; + } + + t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]); } t1_destroy(t1); t1_time = opj_clock() - t1_time; @@ -1394,18 +1418,15 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op int numres2decode; if (tcd->cp->reduce != 0) { - tcd->image->comps[compno].resno_decoded = - tile->comps[compno].numresolutions - tcd->cp->reduce - 1; - if (tcd->image->comps[compno].resno_decoded < 0) { + if ( tile->comps[compno].numresolutions < ( tcd->cp->reduce - 1 ) ) { opj_event_msg(tcd->cinfo, EVT_ERROR, "Error decoding tile. The number of resolutions to remove [%d+1] is higher than the number " " of resolutions in the original codestream [%d]\nModify the cp_reduce parameter.\n", tcd->cp->reduce, tile->comps[compno].numresolutions); - return false; + return OPJ_FALSE; } - } - - if(!tilec->data) { - opj_event_msg(tcd->cinfo, EVT_ERROR, "Error decoding tile. null data\n"); - return false; + else { + tcd->image->comps[compno].resno_decoded = + tile->comps[compno].numresolutions - tcd->cp->reduce - 1; + } } numres2decode = tcd->image->comps[compno].resno_decoded + 1; @@ -1424,18 +1445,23 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op if (tcd->tcp->mct) { int n = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0); - if (tcd->tcp->tccps[0].qmfbid == 1) { - mct_decode( - tile->comps[0].data, - tile->comps[1].data, - tile->comps[2].data, - n); - } else { - mct_decode_real( - (float*)tile->comps[0].data, - (float*)tile->comps[1].data, - (float*)tile->comps[2].data, - n); + + if (tile->numcomps >= 3 ){ + if (tcd->tcp->tccps[0].qmfbid == 1) { + mct_decode( + tile->comps[0].data, + tile->comps[1].data, + tile->comps[2].data, + n); + } else { + mct_decode_real( + (float*)tile->comps[0].data, + (float*)tile->comps[1].data, + (float*)tile->comps[2].data, + n); + } + } else{ + opj_event_msg(tcd->cinfo, EVT_WARNING,"Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n",tile->numcomps); } } @@ -1459,6 +1485,11 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op if(!imagec->data){ imagec->data = (int*) opj_malloc(imagec->w * imagec->h * sizeof(int)); } + if (!imagec->data) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n"); + return OPJ_FALSE; + } if(tcd->tcp->tccps[compno].qmfbid == 1) { for(j = res->y0; j < res->y1; ++j) { for(i = res->x0; i < res->x1; ++i) { @@ -1484,40 +1515,59 @@ bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, op opj_event_msg(tcd->cinfo, EVT_INFO, "- tile decoded in %f s\n", tile_time); if (eof) { - return false; + return OPJ_FALSE; } - return true; + return OPJ_TRUE; } void tcd_free_decode(opj_tcd_t *tcd) { opj_tcd_image_t *tcd_image = tcd->tcd_image; + int i = 0; + for (i = 0; i < tcd_image->tw * tcd_image->th; i++) + { + tcd_free_decode_tile(tcd, i); + } + opj_free(tcd_image->tiles); } void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno) { - int compno,resno,bandno,precno; + int compno,resno,bandno,precno,cblkno; opj_tcd_image_t *tcd_image = tcd->tcd_image; opj_tcd_tile_t *tile = &tcd_image->tiles[tileno]; - for (compno = 0; compno < tile->numcomps; compno++) { - opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; - for (resno = 0; resno < tilec->numresolutions; resno++) { - opj_tcd_resolution_t *res = &tilec->resolutions[resno]; - for (bandno = 0; bandno < res->numbands; bandno++) { - opj_tcd_band_t *band = &res->bands[bandno]; - for (precno = 0; precno < res->ph * res->pw; precno++) { - opj_tcd_precinct_t *prec = &band->precincts[precno]; - if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree); - if (prec->incltree != NULL) tgt_destroy(prec->incltree); + if (tile->comps != NULL) { + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + for (precno = 0; precno < res->ph * res->pw; precno++) { + opj_tcd_precinct_t *prec = &band->precincts[precno]; + if (prec->cblks.dec != NULL) { + for (cblkno = 0; cblkno < prec->cw * prec->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &prec->cblks.dec[cblkno]; + opj_free(cblk->data); + opj_free(cblk->segs); + } + opj_free(prec->cblks.dec); + } + if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree); + if (prec->incltree != NULL) tgt_destroy(prec->incltree); + + + } + opj_free(band->precincts); } - opj_free(band->precincts); } + opj_free(tilec->resolutions); } - opj_free(tilec->resolutions); + opj_free(tile->comps); + tile->comps = NULL; } - opj_free(tile->comps); } diff --git a/indra/libopenjpeg/tcd.h b/indra/libopenjpeg/tcd.h index f0ac5619f..e3f93adc3 100644 --- a/indra/libopenjpeg/tcd.h +++ b/indra/libopenjpeg/tcd.h @@ -251,7 +251,7 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final); void tcd_rateallocate_fixed(opj_tcd_t *tcd); void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final); -bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info); +opj_bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info); /** Encode a tile from the raw image into a buffer @param tcd TCD handle @@ -268,8 +268,9 @@ Decode a tile from a buffer into a raw image @param src Source buffer @param len Length of source buffer @param tileno Number that identifies one of the tiles to be decoded +@param cstr_info Codestream information structure */ -bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info); +opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info); /** Free the memory allocated for decoding @param tcd TCD handle diff --git a/indra/libopenjpeg/thix_manager.c b/indra/libopenjpeg/thix_manager.c new file mode 100644 index 000000000..aa55f217c --- /dev/null +++ b/indra/libopenjpeg/thix_manager.c @@ -0,0 +1,120 @@ +/* + * $Id: thix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include +#include +#include +#include "opj_includes.h" + +/* + * Write tile-part headers mhix box + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] tileno tile number + * @param[in] cio file output handle + * @return length of mhix box + */ +int write_tilemhix( int coff, opj_codestream_info_t cstr_info, int tileno, opj_cio_t *cio); + +int write_thix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio) +{ + int len, lenp, i; + int tileno; + opj_jp2_box_t *box; + + lenp = 0; + box = (opj_jp2_box_t *)opj_calloc( cstr_info.tw*cstr_info.th, sizeof(opj_jp2_box_t)); + + for ( i = 0; i < 2 ; i++ ){ + if (i) + cio_seek( cio, lenp); + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_THIX, 4); /* THIX */ + write_manf( i, cstr_info.tw*cstr_info.th, box, cio); + + for (tileno = 0; tileno < cstr_info.tw*cstr_info.th; tileno++){ + box[tileno].length = write_tilemhix( coff, cstr_info, tileno, cio); + box[tileno].type = JPIP_MHIX; + } + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + } + + opj_free(box); + + return len; +} + +int write_tilemhix( int coff, opj_codestream_info_t cstr_info, int tileno, opj_cio_t *cio) +{ + int i; + opj_tile_info_t tile; + opj_tp_info_t tp; + int len, lenp; + opj_marker_info_t *marker; + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_MHIX, 4); /* MHIX */ + + tile = cstr_info.tile[tileno]; + tp = tile.tp[0]; + + cio_write( cio, tp.tp_end_header-tp.tp_start_pos+1, 8); /* TLEN */ + + marker = cstr_info.tile[tileno].marker; + + for( i=0; i +#include "opj_includes.h" + +#define MAX(a,b) ((a)>(b)?(a):(b)) + + +/* + * Write faix box of tpix + * + * @param[in] coff offset of j2k codestream + * @param[in] compno component number + * @param[in] cstr_info codestream information + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of faix box + */ +int write_tpixfaix( int coff, int compno, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio); + + +int write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio) +{ + int len, lenp; + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_TPIX, 4); /* TPIX */ + + write_tpixfaix( coff, 0, cstr_info, j2klen, cio); + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; +} + + +/* + * Get number of maximum tile parts per tile + * + * @param[in] cstr_info codestream information + * @return number of maximum tile parts per tile + */ +int get_num_max_tile_parts( opj_codestream_info_t cstr_info); + +int write_tpixfaix( int coff, int compno, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio) +{ + int len, lenp; + int i, j; + int Aux; + int num_max_tile_parts; + int size_of_coding; /* 4 or 8 */ + opj_tp_info_t tp; + int version; + + num_max_tile_parts = get_num_max_tile_parts( cstr_info); + + if( j2klen > pow( 2.0, 32)){ + size_of_coding = 8; + version = num_max_tile_parts == 1 ? 1:3; + } + else{ + size_of_coding = 4; + version = num_max_tile_parts == 1 ? 0:2; + } + + lenp = cio_tell( cio); + cio_skip( cio, 4); /* L [at the end] */ + cio_write( cio, JPIP_FAIX, 4); /* FAIX */ + cio_write( cio, version, 1); /* Version 0 = 4 bytes */ + + cio_write( cio, num_max_tile_parts, size_of_coding); /* NMAX */ + cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */ + for (i = 0; i < cstr_info.tw*cstr_info.th; i++){ + for (j = 0; j < cstr_info.tile[i].num_tps; j++){ + tp = cstr_info.tile[i].tp[j]; + cio_write( cio, tp.tp_start_pos-coff, size_of_coding); /* start position */ + cio_write( cio, tp.tp_end_pos-tp.tp_start_pos+1, size_of_coding); /* length */ + if (version & 0x02){ + if( cstr_info.tile[i].num_tps == 1 && cstr_info.numdecompos[compno] > 1) + Aux = cstr_info.numdecompos[compno] + 1; + else + Aux = j + 1; + + cio_write( cio, Aux,4); + /*cio_write(img.tile[i].tile_parts[j].num_reso_AUX,4);*/ /* Aux_i,j : Auxiliary value */ + /* fprintf(stderr,"AUX value %d\n",Aux);*/ + } + /*cio_write(0,4);*/ + } + /* PADDING */ + while (j < num_max_tile_parts){ + cio_write( cio, 0, size_of_coding); /* start position */ + cio_write( cio, 0, size_of_coding); /* length */ + if (version & 0x02) + cio_write( cio, 0,4); /* Aux_i,j : Auxiliary value */ + j++; + } + } + + len = cio_tell( cio)-lenp; + cio_seek( cio, lenp); + cio_write( cio, len, 4); /* L */ + cio_seek( cio, lenp+len); + + return len; + +} + +int get_num_max_tile_parts( opj_codestream_info_t cstr_info) +{ + int num_max_tp = 0, i; + + for( i=0; i mDoneCallback; // Animations that we requested to start std::set mRequestedAnimIDs; diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp index 6f6abefc6..87654b5b9 100644 --- a/indra/llcommon/llallocator.cpp +++ b/indra/llcommon/llallocator.cpp @@ -27,7 +27,7 @@ #include "linden_common.h" #include "llallocator.h" -#if LL_USE_TCMALLOC +#if (LL_USE_TCMALLOC && LL_USE_HEAP_PROFILER) #include "google/heap-profiler.h" #include "google/commandlineflags_public.h" diff --git a/indra/llcommon/lldarray.h b/indra/llcommon/lldarray.h index 5433e8d72..15e200186 100644 --- a/indra/llcommon/lldarray.h +++ b/indra/llcommon/lldarray.h @@ -56,6 +56,7 @@ public: }; LLDynamicArray(S32 size=0) : std::vector(size) { if (size < BlockSize) std::vector::reserve(BlockSize); } + LLDynamicArray(const std::vector& copy) : std::vector(copy) {} void reset() { std::vector::clear(); } diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 9bc61ccb5..480e94e43 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -444,13 +444,13 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL { // The new node isn't last. Place it between the previous node and // the successor. - newNode = (myprev + mydmi->second)/2.0; + newNode = (myprev + mydmi->second)/2.f; } else { // The new node is last. Bump myprev up to the next integer, add // 1.0 and use that. - newNode = std::ceil(myprev) + 1.0; + newNode = std::ceil(myprev) + 1.f; } // Now that newNode has a value that places it appropriately in mSignal, // connect it. diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 446946ac4..c5dbfcb62 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -67,6 +67,17 @@ BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE; LLPrivateMemoryPoolManager::mem_allocation_info_t LLPrivateMemoryPoolManager::sMemAllocationTracker; #endif +void ll_assert_aligned_func(uintptr_t ptr,U32 alignment) +{ +#ifdef SHOW_ASSERT + // Redundant, place to set breakpoints. + if (ptr%alignment!=0) + { + llwarns << "alignment check failed" << llendl; + } + llassert(ptr%alignment==0); +#endif +} //static void LLMemory::initClass() { @@ -246,21 +257,6 @@ U32 LLMemory::getAllocatedMemKB() return sAllocatedMemInKB ; } -void* ll_allocate (size_t size) -{ - if (size == 0) - { - llwarns << "Null allocation" << llendl; - } - void *p = malloc(size); - if (p == NULL) - { - LLMemory::freeReserve(); - llerrs << "Out of memory Error" << llendl; - } - return p; -} - //---------------------------------------------------------------------------- #if defined(LL_WINDOWS) @@ -1358,7 +1354,7 @@ char* LLPrivateMemoryPool::allocate(U32 size) //if the asked size larger than MAX_BLOCK_SIZE, fetch from heap directly, the pool does not manage it if(size >= CHUNK_SIZE) { - return (char*)malloc(size) ; + return (char*)ll_aligned_malloc_16(size) ; } char* p = NULL ; @@ -1415,7 +1411,7 @@ char* LLPrivateMemoryPool::allocate(U32 size) to_log = false ; } - return (char*)malloc(size) ; + return (char*)ll_aligned_malloc_16(size) ; } return p ; @@ -1434,7 +1430,7 @@ void LLPrivateMemoryPool::freeMem(void* addr) if(!chunk) { - free(addr) ; //release from heap + ll_aligned_free_16(addr) ; //release from heap } else { @@ -1558,7 +1554,7 @@ LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_inde mReservedPoolSize += preferred_size + overhead ; - char* buffer = (char*)malloc(preferred_size + overhead) ; + char* buffer = (char*)ll_aligned_malloc_16(preferred_size + overhead) ; if(!buffer) { return NULL ; @@ -1626,7 +1622,7 @@ void LLPrivateMemoryPool::removeChunk(LLMemoryChunk* chunk) mReservedPoolSize -= chunk->getBufferSize() ; //release memory - free(chunk->getBuffer()) ; + ll_aligned_free_16(chunk->getBuffer()) ; } U16 LLPrivateMemoryPool::findHashKey(const char* addr) @@ -1970,7 +1966,7 @@ char* LLPrivateMemoryPoolManager::allocate(LLPrivateMemoryPool* poolp, U32 size, if(!poolp) { - p = (char*)malloc(size) ; + p = (char*)ll_aligned_malloc_16(size) ; } else { @@ -1999,7 +1995,7 @@ char* LLPrivateMemoryPoolManager::allocate(LLPrivateMemoryPool* poolp, U32 size) } else { - return (char*)malloc(size) ; + return (char*)ll_aligned_malloc_16(size) ; } } #endif @@ -2024,7 +2020,7 @@ void LLPrivateMemoryPoolManager::freeMem(LLPrivateMemoryPool* poolp, void* addr { if(!sPrivatePoolEnabled) { - free(addr) ; //private pool is disabled. + ll_aligned_free_16(addr) ; //private pool is disabled. } else if(!sInstance) //the private memory manager is destroyed, try the dangling list { diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 19cc720b0..329ce0c5d 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -39,9 +39,14 @@ #include // uintptr_t #endif -#include "llerror.h" #include "llmemtype.h" -#if LL_DEBUG + +#if LL_WINDOWS && LL_DEBUG +#define LL_CHECK_MEMORY llassert(_CrtCheckMemory()); +#else +#define LL_CHECK_MEMORY +#endif + inline void* ll_aligned_malloc( size_t size, int align ) { void* mem = malloc( size + (align - 1) + sizeof(void*) ); @@ -57,10 +62,11 @@ inline void ll_aligned_free( void* ptr ) free( ((void**)ptr)[-1] ); } +#if !LL_USE_TCMALLOC inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). { #if defined(LL_WINDOWS) - return _mm_malloc(size, 16); + return _aligned_malloc(size, 16); #elif defined(LL_DARWIN) return malloc(size); // default osx malloc is 16 byte aligned. #else @@ -75,7 +81,7 @@ inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed wi inline void ll_aligned_free_16(void *p) { #if defined(LL_WINDOWS) - _mm_free(p); + _aligned_free(p); #elif defined(LL_DARWIN) return free(p); #else @@ -83,10 +89,39 @@ inline void ll_aligned_free_16(void *p) #endif } +inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // returned hunk MUST be freed with ll_aligned_free_16(). +{ +#if defined(LL_WINDOWS) + return _aligned_realloc(ptr, size, 16); +#elif defined(LL_DARWIN) + return realloc(ptr,size); // default osx malloc is 16 byte aligned. +#else + //FIXME: memcpy is SLOW + void* ret = ll_aligned_malloc_16(size); + if (ptr) + { + if (ret) + { + // Only copy the size of the smallest memory block to avoid memory corruption. + memcpy(ret, ptr, llmin(old_size, size)); + } + ll_aligned_free_16(ptr); + } + return ret; +#endif +} + +#else // USE_TCMALLOC +// ll_aligned_foo_16 are not needed with tcmalloc +#define ll_aligned_malloc_16 malloc +#define ll_aligned_realloc_16(a,b,c) realloc(a,b) +#define ll_aligned_free_16 free +#endif // USE_TCMALLOC + inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32(). { #if defined(LL_WINDOWS) - return _mm_malloc(size, 32); + return _aligned_malloc(size, 32); #elif defined(LL_DARWIN) return ll_aligned_malloc( size, 32 ); #else @@ -101,22 +136,13 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi inline void ll_aligned_free_32(void *p) { #if defined(LL_WINDOWS) - _mm_free(p); + _aligned_free(p); #elif defined(LL_DARWIN) ll_aligned_free( p ); #else free(p); // posix_memalign() is compatible with heap deallocator #endif } -#else // LL_DEBUG -// ll_aligned_foo are noops now that we use tcmalloc everywhere (tcmalloc aligns automatically at appropriate intervals) -#define ll_aligned_malloc( size, align ) malloc(size) -#define ll_aligned_free( ptr ) free(ptr) -#define ll_aligned_malloc_16 malloc -#define ll_aligned_free_16 free -#define ll_aligned_malloc_32 malloc -#define ll_aligned_free_32 free -#endif // LL_DEBUG #ifndef __DEBUG_PRIVATE_MEM__ #define __DEBUG_PRIVATE_MEM__ 0 @@ -521,6 +547,14 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr) #endif #endif +LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); + +#ifdef SHOW_ASSERT +#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast(ptr),((U32)alignment)) +#else +#define ll_assert_aligned(ptr,alignment) +#endif + //EVENTUALLY REMOVE THESE: #include "llpointer.h" #include "llsingleton.h" diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 007ee2816..2d515c212 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -262,11 +262,6 @@ U64 totalTime() // No wrapping, we're all okay. gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount; } - else if((gLastTotalTimeClockCount - current_clock_count)<0xFFFF) - { - //clock is glitching and walking backwards - ignore it - gTotalTimeClockCount = gLastTotalTimeClockCount; - } else { // We've wrapped. Compensate correctly diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 66217f902..2d919dc17 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -206,6 +206,19 @@ U8* LLImageBase::allocateData(S32 size) // virtual U8* LLImageBase::reallocateData(S32 size) { + if (size == -1) + { + size = mWidth * mHeight * mComponents; + if (size <= 0) + { + llerrs << llformat("LLImageBase::reallocateData called with bad dimensions: %dx%dx%d", mWidth, mHeight, (S32)mComponents) << llendl; + } + } + else if (size <= 0 || (size > 4096 * 4096 * 16 && !mAllowOverSize)) + { + llerrs << "LLImageBase::reallocateData: bad size: " << size << llendl; + } + if(mData && (mDataSize == size)) return mData; @@ -300,6 +313,32 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components) ++sRawImageCount; } +LLImageRaw::LLImageRaw(LLImageRaw const* src, U16 width, U16 height, U16 crop_offset, bool crop_vertically) : mCacheEntries(0) +{ + mMemType = LLMemType::MTYPE_IMAGERAW; + llassert_always(src); + S8 const components = src->getComponents(); + U8 const* const data = src->getData(); + if (allocateDataSize(width, height, components)) + { + if (crop_vertically) + { + llassert_always(width == src->getWidth()); + memcpy(getData(), data + width * crop_offset * components, width * height * components); + } + else + { + llassert_always(height == src->getHeight()); + U16 const src_width = src->getWidth(); + for (U16 row = 0; row < height; ++row) + { + memcpy(getData() + width * row * components, data + (src_width * row + crop_offset) * components, width * components); + } + } + } + ++sRawImageCount; +} + /*LLImageRaw::LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only) : LLImageBase(), mCacheEntries(0) { @@ -516,7 +555,7 @@ void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image) scale( new_width, new_height, scale_image ); } -void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim) +void LLImageRaw::biasedScaleToPowerOfTwo(S32 target_width, S32 target_height, S32 max_dim) { // Strong bias towards rounding down (to save bandwidth) // No bias would mean THRESHOLD == 1.5f; @@ -525,22 +564,22 @@ void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim) // Find new sizes S32 larger_w = max_dim; // 2^n >= mWidth S32 smaller_w = max_dim; // 2^(n-1) <= mWidth - while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) ) + while( (smaller_w > target_width) && (smaller_w > MIN_IMAGE_SIZE) ) { larger_w = smaller_w; smaller_w >>= 1; } - S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w; + S32 new_width = ( (F32)target_width / smaller_w > THRESHOLD ) ? larger_w : smaller_w; S32 larger_h = max_dim; // 2^m >= mHeight S32 smaller_h = max_dim; // 2^(m-1) <= mHeight - while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) ) + while( (smaller_h > target_height) && (smaller_h > MIN_IMAGE_SIZE) ) { larger_h = smaller_h; smaller_h >>= 1; } - S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h; + S32 new_height = ( (F32)target_height / smaller_h > THRESHOLD ) ? larger_h : smaller_h; scale( new_width, new_height ); @@ -943,76 +982,66 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) return TRUE; // Nothing to do. } - // Reallocate the data buffer. + U8* old_buffer = NULL; + U8* new_buffer; + S32 const old_width_bytes = old_width * getComponents(); + S32 const new_width_bytes = new_width * getComponents(); + S32 const min_height = llmin(old_height, new_height); + S32 const min_width_bytes = llmin(old_width_bytes, new_width_bytes); if (scale_image_data) { - // Vertical - S32 temp_data_size = old_width * new_height * getComponents(); - llassert_always(temp_data_size > 0); - U8* temp_buffer = new (std::nothrow) U8[ temp_data_size ]; - if (!temp_buffer ) + if (new_height != old_height) { - llerrs << "Out of memory in LLImageRaw::scale()" << llendl; - return FALSE; + // Resize vertically. + old_buffer = LLImageBase::release(); + new_buffer = allocateDataSize(old_width, new_height, getComponents()); + for (S32 col = 0; col < old_width; ++col) + { + copyLineScaled(old_buffer + getComponents() * col, new_buffer + getComponents() * col, old_height, new_height, old_width, old_width); + } + LLImageBase::deleteData(old_buffer); } - for( S32 col = 0; col < old_width; col++ ) + if (new_width != old_width) { - copyLineScaled( getData() + (getComponents() * col), temp_buffer + (getComponents() * col), old_height, new_height, old_width, old_width ); + // Resize horizontally. + old_buffer = LLImageBase::release(); + new_buffer = allocateDataSize(new_width, new_height, getComponents()); + for (S32 row = 0; row < new_height; ++row) + { + copyLineScaled(old_buffer + old_width_bytes * row, new_buffer + new_width_bytes * row, old_width, new_width, 1, 1); + } + LLImageBase::deleteData(old_buffer); } - - deleteData(); - - U8* new_buffer = allocateDataSize(new_width, new_height, getComponents()); - - // Horizontal - for( S32 row = 0; row < new_height; row++ ) - { - copyLineScaled( temp_buffer + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 ); - } - - // Clean up - delete[] temp_buffer; } else { - // copy out existing image data - S32 temp_data_size = old_width * old_height * getComponents(); - U8* temp_buffer = new (std::nothrow) U8[ temp_data_size ]; - if (!temp_buffer) + if (new_width == old_width) { - llwarns << "Out of memory in LLImageRaw::scale: old (w, h, c) = (" << old_width << ", " << old_height << ", " << (S32)getComponents() << - ") ; new (w, h, c) = (" << new_width << ", " << new_height << ", " << (S32)getComponents() << ")" << llendl; - - return FALSE ; + setSize(new_width, new_height, getComponents()); + new_buffer = reallocateData(); } - memcpy(temp_buffer, getData(), temp_data_size); /* Flawfinder: ignore */ - - // allocate new image data, will delete old data - U8* new_buffer = allocateDataSize(new_width, new_height, getComponents()); - - for( S32 row = 0; row < new_height; row++ ) + else { - if (row < old_height) + old_buffer = LLImageBase::release(); + new_buffer = allocateDataSize(new_width, new_height, getComponents()); + for (S32 row = 0; row < min_height; ++row) { - memcpy(new_buffer + (new_width * row * getComponents()), temp_buffer + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width)); /* Flawfinder: ignore */ - if (old_width < new_width) + memcpy(new_buffer + row * new_width_bytes, old_buffer + row * old_width_bytes, min_width_bytes); + if (new_width_bytes > old_width_bytes) { - // pad out rest of row with black - memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width)); + // Pad out rest of row with black. + memset(new_buffer + new_width_bytes * row + old_width_bytes, 0, new_width_bytes - old_width_bytes); } } - else - { - // pad remaining rows with black - memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents()); - } + LLImageBase::deleteData(old_buffer); + } + if (new_height > old_height) + { + // Pad remaining rows with black. + memset(new_buffer + new_width_bytes * min_height, 0, new_width_bytes * (new_height - old_height)); } - - // Clean up - delete[] temp_buffer; } - return TRUE ; } @@ -1690,6 +1719,12 @@ static void avg4_colors2(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2); } +void LLImageBase::setDataAndSize(U8 *data, S32 size) +{ + ll_assert_aligned(data, 16); + mData = data; mDataSize = size; +} + //static void LLImageBase::generateMip(const U8* indata, U8* mipdata, S32 width, S32 height, S32 nchannels) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 3782ff1cf..afc129382 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -114,6 +114,8 @@ public: virtual void deleteData(); virtual U8* allocateData(S32 size = -1); virtual U8* reallocateData(S32 size = -1); + static void deleteData(U8* data) { FREE_MEM(sPrivatePoolp, data); } + U8* release() { U8* data = mData; mData = NULL; mDataSize = 0; return data; } // Same as deleteData(), but returns old data. Call deleteData(old_data) to free it. virtual void dump(); virtual void sanityCheck(); @@ -134,7 +136,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); public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -175,12 +177,13 @@ public: LLImageRaw(); LLImageRaw(U16 width, U16 height, S8 components); LLImageRaw(U8 *data, U16 width, U16 height, S8 components); + LLImageRaw(LLImageRaw const* src, U16 width, U16 height, U16 crop_offset, bool crop_vertically); // Construct using createFromFile (used by tools) //LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false); /*virtual*/ void deleteData(); /*virtual*/ U8* allocateData(S32 size = -1); - /*virtual*/ U8* reallocateData(S32 size); + /*virtual*/ U8* reallocateData(S32 size = -1); BOOL resize(U16 width, U16 height, S8 components); @@ -194,7 +197,8 @@ public: void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE); void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE); - void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE); + void biasedScaleToPowerOfTwo(S32 target_width, S32 target_height, S32 max_dim = MAX_IMAGE_SIZE); + void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE) { biasedScaleToPowerOfTwo(getWidth(), getHeight(), max_dim); } BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE ); //BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ; @@ -287,7 +291,7 @@ public: // LLImageBase /*virtual*/ void deleteData(); /*virtual*/ U8* allocateData(S32 size = -1); - /*virtual*/ U8* reallocateData(S32 size); + /*virtual*/ U8* reallocateData(S32 size = -1); /*virtual*/ void dump(); /*virtual*/ void sanityCheck(); diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index bf7acc6d1..7de5ba69d 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llimagej2coj.cpp * @brief This is an implementation of JPEG2000 encode/decode using OpenJPEG. * @@ -35,9 +35,7 @@ const char* fallbackEngineInfoLLImageJ2CImpl() { - static std::string version_string = - std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ") - + opj_version(); + static std::string version_string = std::string("OpenJPEG: ") + opj_version(); return version_string.c_str(); } @@ -186,7 +184,15 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod { opj_image_destroy(image); } - +#if 0 + std::stringstream filename; + filename << "err" << (int)base.getRawDiscardLevel() << "_" << rand() << ".jp2"; + FILE* file = fopen(filename.str().c_str(), "wb"); + if (file) { + fwrite(base.getData(), base.getDataSize(), 1, file); + fclose(file); + } +#endif base.decodeFailed(); return TRUE; // done } diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index 0459f797c..97e56b2a2 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -66,7 +66,7 @@ static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD; // roll(), pitch(), yaw() // etc... - +LL_ALIGN_PREFIX(16) class LLCamera : public LLCoordFrame { @@ -114,7 +114,7 @@ public: }; private: - LLPlane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP + LL_ALIGN_16(LLPlane mAgentPlanes[7]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP U8 mPlaneMask[8]; // 8 for alignment F32 mView; // angle between top and bottom frustum planes in radians. @@ -122,13 +122,13 @@ private: S32 mViewHeightInPixels; // for ViewHeightInPixels() only F32 mNearPlane; F32 mFarPlane; - LLPlane mLocalPlanes[4]; + LL_ALIGN_16(LLPlane mLocalPlanes[4]); F32 mFixedDistance; // Always return this distance, unless < 0 LLVector3 mFrustCenter; // center of frustum and radius squared for ultra-quick exclusion test F32 mFrustRadiusSquared; - LLPlane mWorldPlanes[PLANE_NUM]; - LLPlane mHorizPlanes[HORIZ_PLANE_NUM]; + LL_ALIGN_16(LLPlane mWorldPlanes[PLANE_NUM]); + LL_ALIGN_16(LLPlane mHorizPlanes[HORIZ_PLANE_NUM]); U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in @@ -214,7 +214,7 @@ protected: void calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom); void calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2); void calculateWorldFrustumPlanes(); -}; +} LL_ALIGN_POSTFIX(16); #endif diff --git a/indra/llmath/llmatrix3a.h b/indra/llmath/llmatrix3a.h index adb7e3389..9916cfd2d 100644 --- a/indra/llmath/llmatrix3a.h +++ b/indra/llmath/llmatrix3a.h @@ -111,7 +111,7 @@ public: protected: - LLVector4a mColumns[3]; + LL_ALIGN_16(LLVector4a mColumns[3]); }; diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index 0c61fc96f..94e5e54af 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -34,7 +34,7 @@ class LLMatrix4a { public: - LLVector4a mMatrix[4]; + LL_ALIGN_16(LLVector4a mMatrix[4]); inline void clear() { diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index b642c6317..9a541f008 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -37,6 +37,7 @@ #include "v3math.h" #include "llvector4a.h" #include +#include #if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG #define OCT_ERRS LL_ERRS("OctreeErrors") @@ -46,6 +47,7 @@ #endif extern U32 gOctreeMaxCapacity; +extern U32 gOctreeReserveCapacity; #if LL_DEBUG #define LL_OCTREE_PARANOIA_CHECK 0 #else @@ -56,6 +58,106 @@ extern U32 gOctreeMaxCapacity; template class LLOctreeNode; +#include "lltimer.h" + +//#define LL_OCTREE_STATS +#define LL_OCTREE_POOLS +#ifdef LL_OCTREE_STATS +class OctreeStats : public LLSingleton +{ +public: + OctreeStats() : + mPeriodNodesCreated(0), + mPeriodNodesDestroyed(0), + mPeriodAllocs(0), + mPeriodFrees(0), + mPeriodLargestSize(0), + mTotalNodes(0), + mTotalAllocs(0), + mTotalFrees(0), + mLargestSize(0), + mTotalSize(0) + { + mTotalTimer.reset(); + mPeriodTimer.reset(); + } + void addNode() + { + ++mTotalNodes; + ++mPeriodNodesCreated; + } + void removeNode() + { + --mTotalNodes; + ++mPeriodNodesDestroyed; + } + void realloc(U32 old_count, U32 new_count) + { + if(new_count >= old_count) + mTotalSize+=new_count-old_count; + else + mTotalSize-=old_count-new_count; + if(mLargestSize < new_count) + mLargestSize = new_count; + if(mPeriodLargestSize < new_count) + mPeriodLargestSize = new_count; + ++mTotalAllocs; + ++mPeriodAllocs; + } + void free(U32 count) + { + mTotalSize-=count; + ++mTotalFrees; + ++mPeriodFrees; + } + void dump() + { + llinfos << llformat("Lifetime: Allocs:(+%u|-%u) Allocs/s: (+%lf|-%lf) Nodes: %u AccumSize: %llubytes Avg: %lf LargestSize: %u", + mTotalAllocs, + mTotalFrees, + F64(mTotalAllocs)/mTotalTimer.getElapsedTimeF64(), + F64(mTotalFrees)/mTotalTimer.getElapsedTimeF64(), + mTotalNodes, + mTotalSize*sizeof(LLPointer), + F64(mTotalSize)/F64(mTotalNodes), + mLargestSize + ) << llendl; + llinfos << llformat("Timeslice: Allocs:(+%u|-%u) Allocs/s: (+%lf|-%lf) Nodes:(+%u|-%u) LargestSize: %u", + mPeriodAllocs, + mPeriodFrees, + F64(mPeriodAllocs)/mPeriodTimer.getElapsedTimeF64(), + F64(mPeriodFrees)/mPeriodTimer.getElapsedTimeF64(), + mPeriodNodesCreated, + mPeriodNodesDestroyed, + mPeriodLargestSize + ) << llendl; + + mPeriodNodesCreated=0; + mPeriodNodesDestroyed=0; + mPeriodAllocs=0; + mPeriodFrees=0; + mPeriodLargestSize=0; + mPeriodTimer.reset(); + } +private: + //Accumulate per timer update + U32 mPeriodNodesCreated; + U32 mPeriodNodesDestroyed; + U32 mPeriodAllocs; + U32 mPeriodFrees; + U32 mPeriodLargestSize; + LLTimer mPeriodTimer; + + //Accumulate through entire app lifetime: + U32 mTotalNodes; + U32 mTotalAllocs; + U32 mTotalFrees; + U32 mLargestSize; + U64 mTotalSize; + LLTimer mTotalTimer; +}; +#endif //LL_OCTREE_STATS + template class LLOctreeListener: public LLTreeListener { @@ -129,25 +231,52 @@ public: typedef LLOctreeTraveler oct_traveler; typedef LLTreeTraveler tree_traveler; - typedef LLPointer* element_list; - typedef LLPointer* element_iter; - typedef const LLPointer* const_element_iter; + typedef std::vector > element_list; + typedef typename element_list::iterator element_iter; + typedef typename element_list::const_iterator const_element_iter; typedef typename std::vector*>::iterator tree_listener_iter; typedef LLOctreeNode** child_list; typedef LLOctreeNode** child_iter; + typedef LLTreeNode BaseType; typedef LLOctreeNode oct_node; typedef LLOctreeListener oct_listener; - /*void* operator new(size_t size) +#ifdef LL_OCTREE_POOLS + struct octree_pool_alloc + { + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + static char * malloc(const std::size_t bytes) + { return (char *)ll_aligned_malloc_16(bytes); } + static void free(char * const block) + { ll_aligned_free_16(block); } + }; + static boost::pool& getPool(const std::size_t& size) + { + static boost::pool sPool((std::size_t)LL_NEXT_ALIGNED_ADDRESS((char*)size),1200); + llassert_always((std::size_t)LL_NEXT_ALIGNED_ADDRESS((char*)size) == sPool.get_requested_size()); + return sPool; + } + void* operator new(size_t size) + { + return getPool(size).malloc(); + } + void operator delete(void* ptr) + { + getPool(sizeof(LLOctreeNode)).free(ptr); + } +#else + void* operator new(size_t size) { return ll_aligned_malloc_16(size); } - void operator delete(void* ptr) { ll_aligned_free_16(ptr); - }*/ + } +#endif LLOctreeNode( const LLVector4a& center, const LLVector4a& size, @@ -156,8 +285,16 @@ public: : mParent((oct_node*)parent), mOctant(octant) { - mData = NULL; - mDataEnd = NULL; +#ifdef LL_OCTREE_STATS + OctreeStats::getInstance()->addNode(); +#endif + if(gOctreeReserveCapacity) + mData.reserve(gOctreeReserveCapacity); +#ifdef LL_OCTREE_STATS + OctreeStats::getInstance()->realloc(0,mData.capacity()); +#endif + //mData = NULL; + //mDataEnd = NULL; mCenter = center; mSize = size; @@ -168,24 +305,31 @@ public: mOctant = ((oct_node*) mParent)->getOctant(mCenter); } - mElementCount = 0; + //mElementCount = 0; clearChildren(); } virtual ~LLOctreeNode() - { + { +#ifdef LL_OCTREE_STATS + OctreeStats::getInstance()->removeNode(); +#endif BaseType::destroyListeners(); - for (U32 i = 0; i < mElementCount; ++i) + //for (U32 i = 0; i < mElementCount; ++i) + for (U32 i = 0; i < mData.size(); ++i) { mData[i]->setBinIndex(-1); mData[i] = NULL; } - free(mData); - mData = NULL; - mDataEnd = NULL; +#ifdef LL_OCTREE_STATS + OctreeStats::getInstance()->free(mData.capacity()); +#endif + //free(mData); + //mData = NULL; + //mDataEnd = NULL; for (U32 i = 0; i < getChildCount(); i++) { @@ -285,14 +429,14 @@ public: void accept(oct_traveler* visitor) { visitor->visit(this); } virtual bool isLeaf() const { return mChildCount == 0; } - U32 getElementCount() const { return mElementCount; } - bool isEmpty() const { return mElementCount == 0; } + U32 getElementCount() const { return mData.size(); } + bool isEmpty() const { return mData.size() == 0; } //element_list& getData() { return mData; } //const element_list& getData() const { return mData; } - element_iter getDataBegin() { return mData; } - element_iter getDataEnd() { return mDataEnd; } - const_element_iter getDataBegin() const { return mData; } - const_element_iter getDataEnd() const { return mDataEnd; } + element_iter getDataBegin() { return mData.begin(); } + element_iter getDataEnd() { return mData.end(); } + const_element_iter getDataBegin() const { return mData.begin(); } + const_element_iter getDataEnd() const { return mData.end(); } U32 getChildCount() const { return mChildCount; } oct_node* getChild(U32 index) { return mChild[index]; } @@ -372,7 +516,10 @@ public: if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) || (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { //it belongs here - mElementCount++; + /*mElementCount++; +#ifdef LL_OCTREE_STATS + OctreeStats::getInstance()->realloc(mElementCount-1,mElementCount); +#endif mData = (element_list) realloc(mData, sizeof(LLPointer)*mElementCount); //avoid unref on uninitialized memory @@ -380,7 +527,18 @@ public: mData[mElementCount-1] = data; mDataEnd = mData + mElementCount; - data->setBinIndex(mElementCount-1); + data->setBinIndex(mElementCount-1);*/ + +#ifdef LL_OCTREE_STATS + U32 old_cap = mData.capacity(); +#endif + data->setBinIndex(mData.size()); + mData.push_back(data); +#ifdef LL_OCTREE_STATS + if(old_cap != mData.capacity()) + OctreeStats::getInstance()->realloc(old_cap,mData.capacity()); +#endif + BaseType::insert(data); return true; } @@ -415,7 +573,10 @@ public: if( lt == 0x7 ) { - mElementCount++; + /*mElementCount++; +#ifdef LL_OCTREE_STATS + OctreeStats::getInstance()->realloc(mElementCount-1,mElementCount); +#endif mData = (element_list) realloc(mData, sizeof(LLPointer)*mElementCount); //avoid unref on uninitialized memory @@ -423,7 +584,17 @@ public: mData[mElementCount-1] = data; mDataEnd = mData + mElementCount; - data->setBinIndex(mElementCount-1); + data->setBinIndex(mElementCount-1);*/ +#ifdef LL_OCTREE_STATS + U32 old_cap = mData.capacity(); +#endif + data->setBinIndex(mData.size()); + mData.push_back(data); +#ifdef LL_OCTREE_STATS + if(old_cap != mData.capacity()) + OctreeStats::getInstance()->realloc(old_cap,mData.capacity()); +#endif + BaseType::insert(data); return true; } @@ -476,10 +647,10 @@ public: void _remove(T* data, S32 i) { //precondition -- mElementCount > 0, idx is in range [0, mElementCount) OctreeGuard::checkGuarded(this); - mElementCount--; + //mElementCount--; data->setBinIndex(-1); - - if (mElementCount > 0) + +/* if (mElementCount > 0) { if (mElementCount != i) { @@ -488,15 +659,51 @@ public: } mData[mElementCount] = NULL; //needed for unref +#ifdef LL_OCTREE_STATS + OctreeStats::getInstance()->realloc(mElementCount+1,mElementCount); +#endif mData = (element_list) realloc(mData, sizeof(LLPointer)*mElementCount); mDataEnd = mData+mElementCount; } else { mData[0] = NULL; //needed for unref +#ifdef LL_OCTREE_STATS + OctreeStats::getInstance()->free(1); +#endif free(mData); mData = NULL; mDataEnd = NULL; + }*/ + + if(mData.size()) + { + if((mData.size()-1)!=i) + { + mData[i] = mData[mData.size()-1]; + mData[i]->setBinIndex(i); + } +#ifdef LL_OCTREE_STATS + U32 old_cap = mData.capacity(); +#endif + mData.pop_back(); + if( mData.size() == gOctreeReserveCapacity || + (mData.size() > gOctreeReserveCapacity && mData.capacity() > gOctreeReserveCapacity + mData.size() - 1 - (mData.size() - gOctreeReserveCapacity - 1) % 4)) + { + //Shrink to lowest possible (reserve)+4*i size.. Say reserve is 5, here are [size,capacity] pairs. [10,13],[9,9],[8,9],[7,9],[6,9],[5,5],[4,5],[3,5],[2,5],[1,5],[0,5] + //For Windows: We always assume vs2010 or later, which support this c++11 feature with no configuration needed. + //For GCC: __cplusplus >= 201103L indicates C++11 support. __GXX_EXPERIMENTAL_CXX0X being set indicates experimental c++0x support. C++11 support replaces C++0x support. + // std::vector::shrink_to_fit was added to GCCs C++0x implementation in version 4.5.0. +#if defined(LL_WINDOWS) || __cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X) && __GNUC_MINOR__ >= 5) + mData.shrink_to_fit(); +#else + std::vector >(mData.begin(), mData.end()).swap(mData); //Need to confirm this works on OSX.. +#endif + } +#ifdef LL_OCTREE_STATS + if(old_cap != mData.capacity()) + OctreeStats::getInstance()->realloc(old_cap,mData.capacity()); +#endif } this->notifyRemoval(data); @@ -508,7 +715,8 @@ public: OctreeGuard::checkGuarded(this); S32 i = data->getBinIndex(); - if (i >= 0 && i < (S32)mElementCount) + //if (i >= 0 && i < mElementCount) + if (i >= 0 && i < (S32)mData.size()) { if (mData[i] == data) { //found it @@ -552,7 +760,8 @@ public: void removeByAddress(T* data) { OctreeGuard::checkGuarded(this); - for (U32 i = 0; i < mElementCount; ++i) + //for (U32 i = 0; i < mElementCount; ++i) + for (U32 i = 0; i < mData.size(); ++i) { if (mData[i] == data) { //we have data @@ -660,8 +869,6 @@ public: listener->handleChildRemoval(this, getChild(index)); } - - if (destroy) { mChild[index]->destroy(); @@ -733,8 +940,8 @@ protected: U32 mChildCount; element_list mData; - element_iter mDataEnd; - U32 mElementCount; + //element_iter mDataEnd; + //U32 mElementCount; }; diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h index a18f63a0d..44c8327f5 100644 --- a/indra/llmath/llplane.h +++ b/indra/llmath/llplane.h @@ -42,6 +42,8 @@ // The plane normal = [A, B, C] // The closest approach = D / sqrt(A*A + B*B + C*C) + +LL_ALIGN_PREFIX(16) class LLPlane { public: @@ -100,7 +102,7 @@ public: private: LLVector4a mV; -}; +} LL_ALIGN_POSTFIX(16); diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h index d7595dcee..d476ad3e6 100644 --- a/indra/llmath/llrect.h +++ b/indra/llmath/llrect.h @@ -124,8 +124,8 @@ public: if (end_y < mBottom) clip_y = end_y - mBottom; // clip_? and delta_? should have same sign, since starting point is in rect // so ratios will be positive - F32 ratio_x = ((F32)clip_x / (F32)delta_x); - F32 ratio_y = ((F32)clip_y / (F32)delta_y); + F32 ratio_x = delta_x ? ((F32)clip_x / (F32)delta_x) : 0.f; + F32 ratio_y = delta_y ? ((F32)clip_y / (F32)delta_y) : 0.f; if (ratio_x > ratio_y) { // clip along x direction diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h index c7cdf7b32..01458521e 100644 --- a/indra/llmath/llsimdmath.h +++ b/indra/llmath/llsimdmath.h @@ -67,11 +67,10 @@ template T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) #define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) - - #include #include +#include "llmemory.h" #include "llsimdtypes.h" #include "llsimdtypes.inl" diff --git a/indra/llmath/llsimdtypes.inl b/indra/llmath/llsimdtypes.inl index 712239e42..e905c8495 100644 --- a/indra/llmath/llsimdtypes.inl +++ b/indra/llmath/llsimdtypes.inl @@ -62,6 +62,7 @@ inline LLSimdScalar operator/(const LLSimdScalar& a, const LLSimdScalar& b) inline LLSimdScalar operator-(const LLSimdScalar& a) { static LL_ALIGN_16(const U32 signMask[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + ll_assert_aligned(signMask,16); return _mm_xor_ps(*reinterpret_cast(signMask), a); } @@ -146,6 +147,7 @@ inline LLSimdScalar& LLSimdScalar::operator/=(const LLSimdScalar& rhs) inline LLSimdScalar LLSimdScalar::getAbs() const { static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; + ll_assert_aligned(F_ABS_MASK_4A,16); return _mm_and_ps( mQ, *reinterpret_cast(F_ABS_MASK_4A)); } diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp index b66b7a707..6edeb0fef 100644 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp @@ -24,6 +24,7 @@ * $/LicenseInfo$ */ +#include "llmemory.h" #include "llmath.h" #include "llquantize.h" @@ -44,7 +45,10 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast ( F assert(dst != NULL); assert(bytes > 0); assert((bytes % sizeof(F32))== 0); - + ll_assert_aligned(src,16); + ll_assert_aligned(dst,16); + assert(bytes%16==0); + F32* end = dst + (bytes / sizeof(F32) ); if (bytes > 64) @@ -189,6 +193,8 @@ void LLVector4a::quantize16( const LLVector4a& low, const LLVector4a& high ) LLVector4a oneOverDelta; { static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; + ll_assert_aligned(F_TWO_4A,16); + LLVector4a two; two.load4a( F_TWO_4A ); // Here we use _mm_rcp_ps plus one round of newton-raphson diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 596082509..9de0e6677 100644 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -32,6 +32,7 @@ class LLRotation; #include #include "llpreprocessor.h" +#include "llmemory.h" /////////////////////////////////// // FIRST TIME USERS PLEASE READ @@ -46,6 +47,7 @@ class LLRotation; // LLVector3/LLVector4. ///////////////////////////////// +LL_ALIGN_PREFIX(16) class LLVector4a { public: @@ -90,6 +92,7 @@ public: LLVector4a() { //DO NOT INITIALIZE -- The overhead is completely unnecessary + ll_assert_aligned(this,16); } LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f) @@ -313,7 +316,7 @@ public: private: LLQuad mQ; -}; +} LL_ALIGN_POSTFIX(16); inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p) { diff --git a/indra/llmath/llvector4logical.h b/indra/llmath/llvector4logical.h index dd66b09d4..c5698f7ce 100644 --- a/indra/llmath/llvector4logical.h +++ b/indra/llmath/llvector4logical.h @@ -27,6 +27,7 @@ #ifndef LL_VECTOR4LOGICAL_H #define LL_VECTOR4LOGICAL_H +#include "llmemory.h" //////////////////////////// // LLVector4Logical @@ -77,6 +78,7 @@ public: inline LLVector4Logical& invert() { static const LL_ALIGN_16(U32 allOnes[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + ll_assert_aligned(allOnes,16); mQ = _mm_andnot_ps( mQ, *(LLQuad*)(allOnes) ); return *this; } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 54a88a570..d090b8429 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -29,6 +29,10 @@ #include "llmath.h" #include +#if !LL_WINDOWS +#include +#endif +#include #include "llerror.h" #include "llmemtype.h" @@ -91,17 +95,6 @@ const S32 SCULPT_MIN_AREA_DETAIL = 1; extern BOOL gDebugGL; -void assert_aligned(void* ptr, uintptr_t alignment) -{ -#if 0 - uintptr_t t = (uintptr_t) ptr; - if (t%alignment != 0) - { - llerrs << "Alignment check failed." << llendl; - } -#endif -} - BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) { LLVector3 test = (pt2-pt1)%(pt3-pt2); @@ -6963,14 +6956,14 @@ void LLVolumeFace::resizeVertices(S32 num_verts) if (num_verts) { mPositions = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); - assert_aligned(mPositions, 16); + ll_assert_aligned(mPositions, 16); mNormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); - assert_aligned(mNormals, 16); + ll_assert_aligned(mNormals, 16); //pad texture coordinate block end to allow for QWORD reads S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; mTexCoords = (LLVector2*) ll_aligned_malloc_16(size); - assert_aligned(mTexCoords, 16); + ll_assert_aligned(mTexCoords, 16); } else { @@ -6991,17 +6984,21 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con { S32 new_verts = mNumVertices+1; S32 new_size = new_verts*16; -// S32 old_size = mNumVertices*16; + S32 old_size = mNumVertices*16; //positions - mPositions = (LLVector4a*) realloc(mPositions, new_size); + mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_size, old_size); + ll_assert_aligned(mPositions,16); //normals - mNormals = (LLVector4a*) realloc(mNormals, new_size); - + mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_size, old_size); + ll_assert_aligned(mNormals,16); + //tex coords new_size = ((new_verts*8)+0xF) & ~0xF; - mTexCoords = (LLVector2*) realloc(mTexCoords, new_size); + old_size = ((mNumVertices*8)+0xF) & ~0xF; + mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, new_size, old_size); + ll_assert_aligned(mTexCoords,16); //just clear binormals @@ -7054,7 +7051,8 @@ void LLVolumeFace::pushIndex(const U16& idx) S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; if (new_size != old_size) { - mIndices = (U16*) realloc(mIndices, new_size); + mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size, old_size); + ll_assert_aligned(mIndices,16); } mIndices[mNumIndices++] = idx; @@ -7095,12 +7093,12 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat } //allocate new buffer space - mPositions = (LLVector4a*) realloc(mPositions, new_count*sizeof(LLVector4a)); - assert_aligned(mPositions, 16); - mNormals = (LLVector4a*) realloc(mNormals, new_count*sizeof(LLVector4a)); - assert_aligned(mNormals, 16); - mTexCoords = (LLVector2*) realloc(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); - assert_aligned(mTexCoords, 16); + mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_count*sizeof(LLVector4a), mNumVertices*sizeof(LLVector4a)); + ll_assert_aligned(mPositions, 16); + mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_count*sizeof(LLVector4a), mNumVertices*sizeof(LLVector4a)); + ll_assert_aligned(mNormals, 16); + mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF, (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF); + ll_assert_aligned(mTexCoords, 16); mNumVertices = new_count; @@ -7146,7 +7144,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat new_count = mNumIndices + face.mNumIndices; //allocate new index buffer - mIndices = (U16*) realloc(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); + mIndices = (U16*) ll_aligned_realloc_16(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF, (mNumIndices*sizeof(U16)+0xF) & ~0xF); //get destination address into new index buffer U16* dst_idx = mIndices+mNumIndices; diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index c25e37f1a..03f10814e 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -37,6 +37,15 @@ class LLVolumeTriangle : public LLRefCount { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } LLVolumeTriangle() { mBinIndex = -1; @@ -58,7 +67,7 @@ public: } - LLVector4a mPositionGroup; + LL_ALIGN_16(LLVector4a mPositionGroup); const LLVector4a* mV[3]; U16 mIndex[3]; @@ -78,6 +87,16 @@ class LLVolumeOctreeListener : public LLOctreeListener { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVolumeOctreeListener(LLOctreeNode* node); ~LLVolumeOctreeListener(); @@ -104,8 +123,8 @@ public: public: - LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) - LLVector4a mExtents[2]; // extents (min, max) of this node and all its children + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children }; class LLOctreeTriangleRayIntersect : public LLOctreeTraveler diff --git a/indra/llmessage/aicurl.cpp b/indra/llmessage/aicurl.cpp index bfd2a2243..cbb5fcc45 100644 --- a/indra/llmessage/aicurl.cpp +++ b/indra/llmessage/aicurl.cpp @@ -308,9 +308,10 @@ LLAtomicU32 Stats::llsd_body_count; LLAtomicU32 Stats::llsd_body_parse_error; LLAtomicU32 Stats::raw_body_count; +// Called from BufferedCurlEasyRequest::setStatusAndReason. +// The only allowed values for 'status' are S <= status < S+20, where S={100,200,300,400,500}. U32 Stats::status2index(U32 status) { - llassert_always(status >= 100 && status < 600 && (status % 100) < 20); // Max value 519. return (status - 100) / 100 * 20 + status % 100; // Returns 0..99 (for status 100..519). } @@ -418,6 +419,7 @@ void cleanupCurl(void) if (CurlMultiHandle::getTotalMultiHandles() != 0) llwarns << "Not all CurlMultiHandle objects were destroyed!" << llendl; AIStateMachine::flush(); + clearCommandQueue(); Stats::print(); ssl_cleanup(); @@ -491,12 +493,10 @@ void Stats::print(void) // Even more strict, BufferedCurlEasyRequest may not be created directly either, only as // base class of ThreadSafeBufferedCurlEasyRequest. llassert(BufferedCurlEasyRequest_count == ThreadSafeBufferedCurlEasyRequest_count); - // Each AICurlEasyRequestStateMachine is responsible for exactly one easy handle. - llassert(easy_handles >= AICurlEasyRequest_count); // Each AICurlEasyRequestStateMachine has one AICurlEasyRequest member. llassert(AICurlEasyRequest_count >= AICurlEasyRequestStateMachine_count); // AIFIXME: is this really always the case? And why? - llassert(easy_handles <= ResponderBase_count); + llassert(easy_handles <= S32(ResponderBase_count)); } } // namespace AICurlInterface @@ -546,6 +546,9 @@ void CurlEasyHandle::handle_easy_error(CURLcode code) // Throws AICurlNoEasyHandle. CurlEasyHandle::CurlEasyHandle(void) : mActiveMultiHandle(NULL), mErrorBuffer(NULL), mQueuedForRemoval(false) +#ifdef DEBUG_CURLIO + , mDebug(false) +#endif #ifdef SHOW_ASSERT , mRemovedPerCommand(true) #endif @@ -589,6 +592,12 @@ CurlEasyHandle::~CurlEasyHandle() llassert(!mActiveMultiHandle); curl_easy_cleanup(mEasyHandle); Stats::easy_cleanup_calls++; +#ifdef DEBUG_CURLIO + if (mDebug) + { + debug_curl_remove_easy(mEasyHandle); + } +#endif } //static @@ -761,17 +770,17 @@ void CurlEasyRequest::setoptString(CURLoption option, std::string const& value) setopt(option, value.c_str()); } -void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size) +void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive) { llassert_always(postdata->data()); DoutCurl("POST size is " << size << " bytes: \"" << libcwd::buf2str(postdata->data(), size) << "\"."); setPostField(postdata); // Make sure the data stays around until we don't need it anymore. - setPost_raw(size, postdata->data()); + setPost_raw(size, postdata->data(), keepalive); } -void CurlEasyRequest::setPost_raw(U32 size, char const* data) +void CurlEasyRequest::setPost_raw(U32 size, char const* data, bool keepalive) { if (!data) { @@ -781,7 +790,7 @@ void CurlEasyRequest::setPost_raw(U32 size, char const* data) // The server never replies with 100-continue, so suppress the "Expect: 100-continue" header that libcurl adds by default. addHeader("Expect:"); - if (size > 0) + if (size > 0 && keepalive) { addHeader("Connection: keep-alive"); addHeader("Keep-alive: 300"); @@ -1006,6 +1015,8 @@ CURLcode CurlEasyRequest::curlCtxCallback(CURL* curl, void* sslctx, void* parm) options |= SSL_OP_NO_TLSv1_1; } #else + // This is expected when you compile against the headers of a version < 1.0.1 and then link at runtime with version >= 1.0.1. + // Don't do that. llassert_always(!need_renegotiation_hack); #endif SSL_CTX_set_options(ctx, options); @@ -1226,6 +1237,20 @@ void CurlEasyRequest::removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy mHandleEventsTarget->removed_from_multi_handle(curl_easy_request_w); } +void CurlEasyRequest::bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w) +{ + if (mHandleEventsTarget) + mHandleEventsTarget->bad_file_descriptor(curl_easy_request_w); +} + +#ifdef SHOW_ASSERT +void CurlEasyRequest::queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w) +{ + if (mHandleEventsTarget) + mHandleEventsTarget->queued_for_removal(curl_easy_request_w); +} +#endif + PerHostRequestQueuePtr CurlEasyRequest::getPerHostPtr(void) { if (!mPerHostPtr) @@ -1289,7 +1314,17 @@ void BufferedCurlEasyRequest::timed_out(void) mResponder->finished(CURLE_OK, HTTP_INTERNAL_ERROR, "Request timeout, aborted.", sChannels, mOutput); if (mResponder->needsHeaders()) { - send_buffer_events_to(NULL); // Revoke buffer events: we sent them to the responder. + send_buffer_events_to(NULL); // Revoke buffer events: we send them to the responder. + } + mResponder = NULL; +} + +void BufferedCurlEasyRequest::bad_socket(void) +{ + mResponder->finished(CURLE_OK, HTTP_INTERNAL_ERROR, "File descriptor went bad! Aborted.", sChannels, mOutput); + if (mResponder->needsHeaders()) + { + send_buffer_events_to(NULL); // Revoke buffer events: we send them to the responder. } mResponder = NULL; } @@ -1348,11 +1383,22 @@ void BufferedCurlEasyRequest::prepRequest(AICurlEasyRequest_wat& curl_easy_reque curl_easy_request_w->setReadCallback(&curlReadCallback, lockobj); curl_easy_request_w->setHeaderCallback(&curlHeaderCallback, lockobj); + bool allow_cookies = headers.hasHeader("Cookie"); // Allow up to ten redirects. if (responder->followRedir()) { curl_easy_request_w->setopt(CURLOPT_FOLLOWLOCATION, 1); curl_easy_request_w->setopt(CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT); + // This is needed (at least) for authentication after temporary redirection + // to id.secondlife.com for marketplace.secondlife.com. + allow_cookies = true; + } + if (allow_cookies) + { + // Given an empty or non-existing file or by passing the empty string (""), + // this option will enable cookies for this curl handle, making it understand + // and parse received cookies and then use matching cookies in future requests. + curl_easy_request_w->setopt(CURLOPT_COOKIEFILE, ""); } // Keep responder alive. @@ -1398,3 +1444,18 @@ CurlMultiHandle::~CurlMultiHandle() } } // namespace AICurlPrivate + +#if LL_LINUX +extern "C" { + +// Keep linker happy. +const SSL_METHOD *SSLv2_client_method(void) +{ + // Never used. + llassert_always(false); + return NULL; +} + +} +#endif + diff --git a/indra/llmessage/aicurl.h b/indra/llmessage/aicurl.h index b7599c817..16d1b14fd 100644 --- a/indra/llmessage/aicurl.h +++ b/indra/llmessage/aicurl.h @@ -208,6 +208,10 @@ struct AICurlEasyHandleEvents { virtual void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0; virtual void finished(AICurlEasyRequest_wat& curl_easy_request_w) = 0; virtual void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0; + virtual void bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w) = 0; +#ifdef SHOW_ASSERT + virtual void queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w) = 0; +#endif // Avoid compiler warning. virtual ~AICurlEasyHandleEvents() { } }; @@ -271,6 +275,11 @@ class AICurlEasyRequest { // Queue a command to remove this request from the multi session (or cancel a queued command to add it). void removeRequest(void); +#ifdef DEBUG_CURLIO + // Turn on/off debug output. + void debug(bool debug) { AICurlEasyRequest_wat(*mBufferedCurlEasyRequest)->debug(debug); } +#endif + private: // The actual pointer to the ThreadSafeBufferedCurlEasyRequest instance. AICurlPrivate::BufferedCurlEasyRequestPtr mBufferedCurlEasyRequest; diff --git a/indra/llmessage/aicurleasyrequeststatemachine.cpp b/indra/llmessage/aicurleasyrequeststatemachine.cpp index d7babe6f3..b9f486d67 100644 --- a/indra/llmessage/aicurleasyrequeststatemachine.cpp +++ b/indra/llmessage/aicurleasyrequeststatemachine.cpp @@ -40,7 +40,8 @@ enum curleasyrequeststatemachine_state_type { AICurlEasyRequestStateMachine_timedOut, // This must be smaller than the rest, so they always overrule. AICurlEasyRequestStateMachine_finished, AICurlEasyRequestStateMachine_removed, // The removed states must be largest two, so they are never ignored. - AICurlEasyRequestStateMachine_removed_after_finished + AICurlEasyRequestStateMachine_removed_after_finished, + AICurlEasyRequestStateMachine_bad_file_descriptor }; char const* AICurlEasyRequestStateMachine::state_str_impl(state_type run_state) const @@ -54,6 +55,7 @@ char const* AICurlEasyRequestStateMachine::state_str_impl(state_type run_state) AI_CASE_RETURN(AICurlEasyRequestStateMachine_finished); AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed); AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed_after_finished); + AI_CASE_RETURN(AICurlEasyRequestStateMachine_bad_file_descriptor); } return "UNKNOWN STATE"; } @@ -94,6 +96,24 @@ void AICurlEasyRequestStateMachine::removed_from_multi_handle(AICurlEasyRequest_ set_state(mFinished ? AICurlEasyRequestStateMachine_removed_after_finished : AICurlEasyRequestStateMachine_removed); } +// CURL-THREAD +void AICurlEasyRequestStateMachine::bad_file_descriptor(AICurlEasyRequest_wat&) +{ + if (!mFinished) + { + mFinished = true; + set_state(AICurlEasyRequestStateMachine_bad_file_descriptor); + } +} + +#ifdef SHOW_ASSERT +// CURL-THREAD +void AICurlEasyRequestStateMachine::queued_for_removal(AICurlEasyRequest_wat&) +{ + llassert(mFinished || mTimedOut); // See AICurlEasyRequestStateMachine::removed_from_multi_handle +} +#endif + void AICurlEasyRequestStateMachine::multiplex_impl(void) { mSetStateLock.lock(); @@ -207,6 +227,11 @@ void AICurlEasyRequestStateMachine::multiplex_impl(void) break; } + case AICurlEasyRequestStateMachine_bad_file_descriptor: + { + AICurlEasyRequest_wat(*mCurlEasyRequest)->bad_socket(); + abort(); + } } } diff --git a/indra/llmessage/aicurleasyrequeststatemachine.h b/indra/llmessage/aicurleasyrequeststatemachine.h index 8ece6fc26..8a6441874 100644 --- a/indra/llmessage/aicurleasyrequeststatemachine.h +++ b/indra/llmessage/aicurleasyrequeststatemachine.h @@ -81,6 +81,14 @@ class AICurlEasyRequestStateMachine : public AIStateMachine, public AICurlEasyHa // Called after this curl easy handle was removed from a multi handle. /*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat&); + // Called when the curl thread detected that the socket of this handle has become unusable. + /*virtual*/ void bad_file_descriptor(AICurlEasyRequest_wat&); + +#ifdef SHOW_ASSERT + // Called when a command was added to remove this easy handle. + /*virtual*/ void queued_for_removal(AICurlEasyRequest_wat&); +#endif + protected: // AIStateMachine implementations. diff --git a/indra/llmessage/aicurlperhost.cpp b/indra/llmessage/aicurlperhost.cpp index 724d5bccd..b444ba6df 100644 --- a/indra/llmessage/aicurlperhost.cpp +++ b/indra/llmessage/aicurlperhost.cpp @@ -56,12 +56,17 @@ PerHostRequestQueuePtr PerHostRequestQueue::instance(std::string const& hostname //static void PerHostRequestQueue::release(PerHostRequestQueuePtr& instance) { - if (instance->lastone()) + if (instance->exactly_two_left()) // Being 'instance' and the one in sInstanceMap. { + // The viewer can be have left main() we can't access the global sInstanceMap anymore. + if (LLApp::isStopped()) + { + return; + } instance_map_wat instance_map_w(sInstanceMap); - // It is possible that 'lastone' is not up to date anymore. + // It is possible that 'exactly_two_left' is not up to date anymore. // Therefore, recheck the condition now that we have locked sInstanceMap. - if (!instance->lastone()) + if (!instance->exactly_two_left()) { // Some other thread added this host in the meantime. return; @@ -87,13 +92,13 @@ void PerHostRequestQueue::release(PerHostRequestQueuePtr& instance) bool PerHostRequestQueue::throttled() const { - llassert(mAdded <= curl_concurrent_connections_per_host); - return mAdded == curl_concurrent_connections_per_host; + llassert(mAdded <= int(curl_concurrent_connections_per_host)); + return mAdded == int(curl_concurrent_connections_per_host); } void PerHostRequestQueue::added_to_multi_handle(void) { - llassert(mAdded < curl_concurrent_connections_per_host); + llassert(mAdded < int(curl_concurrent_connections_per_host)); ++mAdded; } diff --git a/indra/llmessage/aicurlperhost.h b/indra/llmessage/aicurlperhost.h index dac9d70c0..c464d490c 100644 --- a/indra/llmessage/aicurlperhost.h +++ b/indra/llmessage/aicurlperhost.h @@ -118,7 +118,7 @@ class PerHostRequestQueue { class RefCountedThreadSafePerHostRequestQueue : public threadsafe_PerHostRequestQueue { public: RefCountedThreadSafePerHostRequestQueue(void) : mReferenceCount(0) { } - bool lastone(void) const { llassert(mReferenceCount >= 2); return mReferenceCount == 2; } + bool exactly_two_left(void) const { return mReferenceCount == 2; } private: // Used by PerHostRequestQueuePtr. Object is deleted when reference count reaches zero. diff --git a/indra/llmessage/aicurlprivate.h b/indra/llmessage/aicurlprivate.h index abb663d4a..bd6207e2d 100644 --- a/indra/llmessage/aicurlprivate.h +++ b/indra/llmessage/aicurlprivate.h @@ -119,6 +119,7 @@ inline CURLMcode check_multi_code(CURLMcode code) { AICurlInterface::Stats::mult bool curlThreadIsRunning(void); void wakeUpCurlThread(void); void stopCurlThread(void); +void clearCommandQueue(void); #define DECLARE_SETOPT(param_type) \ CURLcode setopt(CURLoption option, param_type parameter) @@ -200,12 +201,19 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven // In case it's added after being removed. void add_queued(void) { mQueuedForRemoval = false; } +#ifdef DEBUG_CURLIO + void debug(bool debug) { if (mDebug) debug_curl_remove_easy(mEasyHandle); if (debug) debug_curl_add_easy(mEasyHandle); mDebug = debug; } +#endif + private: CURL* mEasyHandle; CURLM* mActiveMultiHandle; mutable char* mErrorBuffer; AIPostFieldPtr mPostField; // This keeps the POSTFIELD data alive for as long as the easy handle exists. bool mQueuedForRemoval; // Set if the easy handle is (probably) added to the multi handle, but is queued for removal. +#ifdef DEBUG_CURLIO + bool mDebug; +#endif #ifdef SHOW_ASSERT public: bool mRemovedPerCommand; // Set if mActiveMultiHandle was reset as per command from the main thread. @@ -269,11 +277,11 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven // and the CurlEasyRequest destructed. class CurlEasyRequest : public CurlEasyHandle { private: - void setPost_raw(U32 size, char const* data); + void setPost_raw(U32 size, char const* data, bool keepalive); public: - void setPost(U32 size) { setPost_raw(size, NULL); } - void setPost(AIPostFieldPtr const& postdata, U32 size); - void setPost(char const* data, U32 size) { setPost(new AIPostField(data), size); } + void setPost(U32 size, bool keepalive = true) { setPost_raw(size, NULL, keepalive); } + void setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive = true); + void setPost(char const* data, U32 size, bool keepalive = true) { setPost(new AIPostField(data), size, keepalive); } void setoptString(CURLoption option, std::string const& value); void addHeader(char const* str); void addHeaders(AIHTTPHeaders const& headers); @@ -412,6 +420,11 @@ class CurlEasyRequest : public CurlEasyHandle { /*virtual*/ void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w); /*virtual*/ void finished(AICurlEasyRequest_wat& curl_easy_request_w); /*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w); + public: + /*virtual*/ void bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w); +#ifdef SHOW_ASSERT + /*virtual*/ void queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w); +#endif }; // This class adds input/output buffers to the request and hooks up the libcurl callbacks to use those buffers. @@ -430,6 +443,9 @@ class BufferedCurlEasyRequest : public CurlEasyRequest { // Called if libcurl doesn't deliver within AIHTTPTimeoutPolicy::mMaximumTotalDelay seconds. void timed_out(void); + // Called if the underlaying socket went bad (ie, when accidently closed by a buggy library). + void bad_socket(void); + // Called after removed_from_multi_handle was called. void processOutput(void); diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index 1fbe57d3e..3dc3bd3e2 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -286,14 +286,36 @@ enum refresh_t { empty_and_complete = complete|empty }; +// A class with info for each socket that is in use by curl. +class CurlSocketInfo +{ + public: + CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj); + ~CurlSocketInfo(); + + void set_action(int action); + void mark_dead(void) { set_action(CURL_POLL_NONE); mDead = true; } + curl_socket_t getSocketFd(void) const { return mSocketFd; } + AICurlEasyRequest& getEasyRequest(void) { return mEasyRequest; } + + private: + MultiHandle& mMultiHandle; + CURL const* mEasy; + curl_socket_t mSocketFd; + int mAction; + bool mDead; + AICurlEasyRequest mEasyRequest; + LLPointer mTimeout; +}; + class PollSet { public: PollSet(void); // Add/remove a filedescriptor to/from mFileDescriptors. - void add(curl_socket_t s); - void remove(curl_socket_t s); + void add(CurlSocketInfo* sp); + void remove(CurlSocketInfo* sp); // Copy mFileDescriptors to an internal fd_set that is returned by access(). // Returns if all fds could be copied (complete) and/or if the resulting fd_set is empty. @@ -307,8 +329,8 @@ class PollSet curl_socket_t get_max_fd(void) const { return mMaxFdSet; } #endif - // Return true if a filedescriptor is set in mFileDescriptors (used for debugging). - bool contains(curl_socket_t s) const; + // Return a pointer to the corresponding CurlSocketInfo if a filedescriptor is set in mFileDescriptors, or NULL if s is not set. + CurlSocketInfo* contains(curl_socket_t s) const; // Return true if a filedescriptor is set in mFdSet. bool is_set(curl_socket_t s) const; @@ -323,7 +345,7 @@ class PollSet void next(void); // Advance to next filedescriptor. private: - curl_socket_t* mFileDescriptors; + CurlSocketInfo** mFileDescriptors; int mNrFds; // The number of filedescriptors in the array. int mNext; // The index of the first file descriptor to start copying, the next call to refresh(). @@ -332,8 +354,8 @@ class PollSet #if !WINDOWS_CODE curl_socket_t mMaxFd; // The largest filedescriptor in the array, or CURL_SOCKET_BAD when it is empty. curl_socket_t mMaxFdSet; // The largest filedescriptor set in mFdSet by refresh(), or CURL_SOCKET_BAD when it was empty. - std::vector mCopiedFileDescriptors; // Filedescriptors copied by refresh to mFdSet. - std::vector::iterator mIter; // Index into mCopiedFileDescriptors for next(); loop variable. + std::vector mCopiedFileDescriptors; // Filedescriptors copied by refresh to mFdSet. + std::vector::iterator mIter; // Index into mCopiedFileDescriptors for next(); loop variable. #else unsigned int mIter; // Index into fd_set::fd_array. #endif @@ -359,7 +381,7 @@ class PollSet static size_t const MAXSIZE = llmax(1024, FD_SETSIZE); // Create an empty PollSet. -PollSet::PollSet(void) : mFileDescriptors(new curl_socket_t [MAXSIZE]), +PollSet::PollSet(void) : mFileDescriptors(new CurlSocketInfo* [MAXSIZE]), mNrFds(0), mNext(0) #if !WINDOWS_CODE , mMaxFd(-1), mMaxFdSet(-1) @@ -369,17 +391,17 @@ PollSet::PollSet(void) : mFileDescriptors(new curl_socket_t [MAXSIZE]), } // Add filedescriptor s to the PollSet. -void PollSet::add(curl_socket_t s) +void PollSet::add(CurlSocketInfo* sp) { llassert_always(mNrFds < (int)MAXSIZE); - mFileDescriptors[mNrFds++] = s; + mFileDescriptors[mNrFds++] = sp; #if !WINDOWS_CODE - mMaxFd = llmax(mMaxFd, s); + mMaxFd = llmax(mMaxFd, sp->getSocketFd()); #endif } // Remove filedescriptor s from the PollSet. -void PollSet::remove(curl_socket_t s) +void PollSet::remove(CurlSocketInfo* sp) { // The number of open filedescriptors is relatively small, // and on top of that we rather do something CPU intensive @@ -391,15 +413,15 @@ void PollSet::remove(curl_socket_t s) // back, keeping it compact and keeping the filedescriptors // in the same order (which is supposedly their priority). // - // The general case is where mFileDescriptors contains s at an index + // The general case is where mFileDescriptors contains sp at an index // between 0 and mNrFds: // mNrFds = 6 // v // index: 0 1 2 3 4 5 // a b c s d e - // This function should never be called unless s is actually in mFileDescriptors, - // as a result of a previous call to PollSet::add(). + // This function should never be called unless sp is actually in mFileDescriptors, + // as a result of a previous call to PollSet::add(sp). llassert(mNrFds > 0); // Correct mNrFds for when the descriptor is removed. @@ -409,17 +431,18 @@ void PollSet::remove(curl_socket_t s) // v // index: 0 1 2 3 4 5 // a b c s d e - curl_socket_t cur = mFileDescriptors[i]; // cur = 'e' + curl_socket_t const s = sp->getSocketFd(); + CurlSocketInfo* cur = mFileDescriptors[i]; // cur = 'e' #if !WINDOWS_CODE curl_socket_t max = -1; #endif - while (cur != s) + while (cur != sp) { llassert(i > 0); - curl_socket_t next = mFileDescriptors[--i]; // next = 'd' + CurlSocketInfo* next = mFileDescriptors[--i]; // next = 'd' mFileDescriptors[i] = cur; // Overwrite 'd' with 'e'. #if !WINDOWS_CODE - max = llmax(max, cur); // max is the maximum value in 'i' or higher. + max = llmax(max, cur->getSocketFd()); // max is the maximum value in 'i' or higher. #endif cur = next; // cur = 'd' // i NrFds = 5 @@ -427,21 +450,21 @@ void PollSet::remove(curl_socket_t s) // index: 0 1 2 3 4 // a b c s e // cur = 'd' // - // Next loop iteration: next = 's', overwrite 's' with 'd', cur = 's'; loop terminates. + // Next loop iteration: next = 'sp', overwrite 'sp' with 'd', cur = 'sp'; loop terminates. // i NrFds = 5 // v v // index: 0 1 2 3 4 - // a b c d e // cur = 's' + // a b c d e // cur = 'sp' } - llassert(cur == s); + llassert(cur == sp); // At this point i was decremented once more and points to the element before the old s. // i NrFds = 5 // v v // index: 0 1 2 3 4 // a b c d e // max = llmax('d', 'e') - // If mNext pointed to an element before s, it should be left alone. Otherwise, if mNext pointed - // to s it must now point to 'd', or if it pointed beyond 's' it must be decremented by 1. + // If mNext pointed to an element before sp, it should be left alone. Otherwise, if mNext pointed + // to sp it must now point to 'd', or if it pointed beyond 'sp' it must be decremented by 1. if (mNext > i) // i is where s was. --mNext; @@ -451,8 +474,8 @@ void PollSet::remove(curl_socket_t s) { while (i > 0) { - curl_socket_t next = mFileDescriptors[--i]; - max = llmax(max, next); + CurlSocketInfo* next = mFileDescriptors[--i]; + max = llmax(max, next->getSocketFd()); } mMaxFd = max; llassert(mMaxFd < s); @@ -487,12 +510,12 @@ void PollSet::remove(curl_socket_t s) #endif } -bool PollSet::contains(curl_socket_t fd) const +CurlSocketInfo* PollSet::contains(curl_socket_t fd) const { for (int i = 0; i < mNrFds; ++i) - if (mFileDescriptors[i] == fd) - return true; - return false; + if (mFileDescriptors[i]->getSocketFd() == fd) + return mFileDescriptors[i]; + return NULL; } inline bool PollSet::is_set(curl_socket_t fd) const @@ -536,7 +559,7 @@ refresh_t PollSet::refresh(void) // Calculate mMaxFdSet. // Run over FD_SETSIZE - 1 elements, starting at mNext, wrapping to 0 when we reach the end. int max = -1, i = mNext, count = 0; - while (++count < FD_SETSIZE) { max = llmax(max, mFileDescriptors[i]); if (++i == mNrFds) i = 0; } + while (++count < FD_SETSIZE) { max = llmax(max, mFileDescriptors[i]->getSocketFd()); if (++i == mNrFds) i = 0; } mMaxFdSet = max; #endif } @@ -556,7 +579,7 @@ refresh_t PollSet::refresh(void) mNext = i; return not_complete_not_empty; } - FD_SET(mFileDescriptors[i], &mFdSet); + FD_SET(mFileDescriptors[i]->getSocketFd(), &mFdSet); #if !WINDOWS_CODE mCopiedFileDescriptors.push_back(mFileDescriptors[i]); #endif @@ -603,7 +626,7 @@ void PollSet::reset(void) else { mIter = mCopiedFileDescriptors.begin(); - if (!FD_ISSET(*mIter, &mFdSet)) + if (!FD_ISSET((*mIter)->getSocketFd(), &mFdSet)) next(); } #endif @@ -614,7 +637,7 @@ inline curl_socket_t PollSet::get(void) const #if WINDOWS_CODE return (mIter >= mFdSet.fd_count) ? CURL_SOCKET_BAD : mFdSet.fd_array[mIter]; #else - return (mIter == mCopiedFileDescriptors.end()) ? CURL_SOCKET_BAD : *mIter; + return (mIter == mCopiedFileDescriptors.end()) ? CURL_SOCKET_BAD : (*mIter)->getSocketFd(); #endif } @@ -625,7 +648,7 @@ void PollSet::next(void) ++mIter; #else llassert(mIter != mCopiedFileDescriptors.end()); // Only call next() if the last call to get() didn't return -1. - while (++mIter != mCopiedFileDescriptors.end() && !FD_ISSET(*mIter, &mFdSet)); + while (++mIter != mCopiedFileDescriptors.end() && !FD_ISSET((*mIter)->getSocketFd(), &mFdSet)); #endif } @@ -743,26 +766,8 @@ std::ostream& operator<<(std::ostream& os, DebugFdSet const& s) } #endif -// A class with info for each socket that is in use by curl. -class CurlSocketInfo -{ - public: - CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj); - ~CurlSocketInfo(); - - void set_action(int action); - - private: - MultiHandle& mMultiHandle; - CURL const* mEasy; - curl_socket_t mSocketFd; - int mAction; - AICurlEasyRequest mEasyRequest; - LLPointer mTimeout; -}; - CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj) : - mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mEasyRequest(lockobj) + mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mDead(false), mEasyRequest(lockobj) { llassert(*AICurlEasyRequest_wat(*mEasyRequest) == easy); mMultiHandle.assign(s, this); @@ -785,23 +790,28 @@ CurlSocketInfo::~CurlSocketInfo() void CurlSocketInfo::set_action(int action) { + if (mDead) + { + return; + } + Dout(dc::curl, "CurlSocketInfo::set_action(" << action_str(mAction) << " --> " << action_str(action) << ") [" << (void*)mEasyRequest.get_ptr().get() << "]"); int toggle_action = mAction ^ action; mAction = action; if ((toggle_action & CURL_POLL_IN)) { if ((action & CURL_POLL_IN)) - mMultiHandle.mReadPollSet->add(mSocketFd); + mMultiHandle.mReadPollSet->add(this); else - mMultiHandle.mReadPollSet->remove(mSocketFd); + mMultiHandle.mReadPollSet->remove(this); } if ((toggle_action & CURL_POLL_OUT)) { if ((action & CURL_POLL_OUT)) - mMultiHandle.mWritePollSet->add(mSocketFd); + mMultiHandle.mWritePollSet->add(this); else { - mMultiHandle.mWritePollSet->remove(mSocketFd); + mMultiHandle.mWritePollSet->remove(this); // The following is a bit of a hack, needed because of the lack of proper timeout callbacks in libcurl. // The removal of CURL_POLL_OUT could be part of the SSL handshake, therefore check if we're already connected: @@ -838,6 +848,9 @@ class AICurlThread : public LLThread // MAIN-THREAD void stop_thread(void) { mRunning = false; wakeup_thread(); } + // MAIN-THREAD + apr_status_t join_thread(void); + protected: virtual void run(void); void wakeup(AICurlMultiHandle_wat const& multi_handle_w); @@ -1065,6 +1078,10 @@ void AICurlThread::wakeup_thread(void) DoutEntering(dc::curl, "AICurlThread::wakeup_thread"); llassert(is_main_thread()); + // If we are already exiting the viewer then return immediately. + if (!mRunning) + return; + // Try if curl thread is still awake and if so, pass the new commands directly. if (mWakeUpMutex.tryLock()) { @@ -1106,6 +1123,17 @@ void AICurlThread::wakeup_thread(void) #endif } +apr_status_t AICurlThread::join_thread(void) +{ + apr_status_t retval = APR_SUCCESS; + if (sInstance) + { + apr_thread_join(&retval, sInstance->mAPRThreadp); + delete sInstance; + } + return retval; +} + void AICurlThread::wakeup(AICurlMultiHandle_wat const& multi_handle_w) { DoutEntering(dc::curl, "AICurlThread::wakeup"); @@ -1251,6 +1279,26 @@ void AICurlThread::process_commands(AICurlMultiHandle_wat const& multi_handle_w) } } +// Return true if fd is a 'bad' socket. +static bool is_bad(curl_socket_t fd, bool for_writing) +{ + fd_set tmp; + FD_ZERO(&tmp); + FD_SET(fd, &tmp); + fd_set* readfds = for_writing ? NULL : &tmp; + fd_set* writefds = for_writing ? &tmp : NULL; +#if !WINDOWS_CODE + int nfds = fd + 1; +#else + int nfds = 64; +#endif + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 10; + int ret = select(nfds, readfds, writefds, NULL, &timeout); + return ret == -1; +} + // The main loop of the curl thread. void AICurlThread::run(void) { @@ -1262,7 +1310,7 @@ void AICurlThread::run(void) { // If mRunning is true then we can only get here if mWakeUpFd != CURL_SOCKET_BAD. llassert(mWakeUpFd != CURL_SOCKET_BAD); - // Copy the next batch of file descriptors from the PollSets mFiledescriptors into their mFdSet. + // Copy the next batch of file descriptors from the PollSets mFileDescriptors into their mFdSet. multi_handle_w->mReadPollSet->refresh(); refresh_t wres = multi_handle_w->mWritePollSet->refresh(); // Add wake up fd if any, and pass NULL to select() if a set is empty. @@ -1379,6 +1427,51 @@ void AICurlThread::run(void) if (ready == -1) { llwarns << "select() failed: " << errno << ", " << strerror(errno) << llendl; + if (errno == EBADF) + { + // Somewhere (fmodex?) one of our file descriptors was closed. Try to recover by finding out which. + llassert_always(!is_bad(mWakeUpFd, false)); // We can't recover from this. + PollSet* found = NULL; + // Run over all read file descriptors. + multi_handle_w->mReadPollSet->refresh(); + multi_handle_w->mReadPollSet->reset(); + curl_socket_t fd; + while ((fd = multi_handle_w->mReadPollSet->get()) != CURL_SOCKET_BAD) + { + if (is_bad(fd, false)) + { + found = multi_handle_w->mReadPollSet; + break; + } + multi_handle_w->mReadPollSet->next(); + } + if (!found) + { + // Try all write file descriptors. + refresh_t wres = multi_handle_w->mWritePollSet->refresh(); + if (!(wres & empty)) + { + multi_handle_w->mWritePollSet->reset(); + while ((fd = multi_handle_w->mWritePollSet->get()) != CURL_SOCKET_BAD) + { + if (is_bad(fd, true)) + { + found = multi_handle_w->mWritePollSet; + break; + } + multi_handle_w->mWritePollSet->next(); + } + } + } + llassert_always(found); // It makes no sense to continue if we can't recover. + // Find the corresponding CurlSocketInfo + CurlSocketInfo* sp = found->contains(fd); + llassert_always(sp); // fd was just *read* from this sp. + sp->mark_dead(); // Make sure it's never used again. + AICurlEasyRequest_wat curl_easy_request_w(*sp->getEasyRequest()); + curl_easy_request_w->pause(CURLPAUSE_ALL); // Keep libcurl at bay. + curl_easy_request_w->bad_file_descriptor(curl_easy_request_w); // Make the main thread cleanly terminate this transaction. + } continue; } // Clock count used for timeouts. @@ -1609,7 +1702,9 @@ CURLMcode MultiHandle::remove_easy_request(addedEasyRequests_type::iterator cons ThreadSafeBufferedCurlEasyRequest* lockobj = iter->get_ptr().get(); #endif mAddedEasyRequests.erase(iter); +#if CWDEBUG Dout(dc::curl, "MultiHandle::remove_easy_request: Removed AICurlEasyRequest " << (void*)lockobj << "; now processing " << mAddedEasyRequests.size() << " easy handles."); +#endif // Attempt to add a queued request, if any. PerHostRequestQueue_wat(*per_host)->add_queued_to(this); @@ -1816,7 +1911,7 @@ bool HTTPTimeout::data_received(size_t n) // | | | | | | | | | | | | | | bool HTTPTimeout::lowspeed(size_t bytes) { - DoutCurlEntering("HTTPTimeout::lowspeed(" << bytes << ")"); + //DoutCurlEntering("HTTPTimeout::lowspeed(" << bytes << ")"); commented out... too spammy for normal use. // The algorithm to determine if we timed out if different from how libcurls CURLOPT_LOW_SPEED_TIME works. // @@ -1994,12 +2089,11 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch #if LOWRESTIMER llinfos << "Hostname seems to have been still in the DNS cache." << llendl; #else - llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but DNS lookup did not occur according to timings. Expected CURLE_COULDNT_RESOLVE_PROXY or CURLE_COULDNT_RESOLVE_HOST!" << llendl; + llwarns << "Curl returned CURLE_OPERATION_TIMEDOUT and DNS lookup did not occur according to timings. Apparently the resolve attempt timed out (bad network?)" << llendl; llassert(connect_time == 0); llassert(appconnect_time == 0); llassert(pretransfer_time == 0); llassert(starttransfer_time == 0); - // Fatal error for diagnostics. return; #endif } @@ -2022,11 +2116,10 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch #endif ) { - llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but connection did not occur according to timings. Expected CURLE_COULDNT_CONNECT!" << llendl; + llwarns << "Curl returned CURLE_OPERATION_TIMEDOUT and connection did not occur according to timings: apparently the connect attempt timed out (bad network?)" << llendl; llassert(appconnect_time == 0); llassert(pretransfer_time == 0); llassert(starttransfer_time == 0); - // Fatal error for diagnostics. return; } // If connect_time is almost equal to namelookup_time, then it was just set because it was already connected. @@ -2142,16 +2235,30 @@ void stopCurlThread(void) if (AICurlThread::sInstance) { AICurlThread::sInstance->stop_thread(); - int count = 101; + int count = 401; while(--count && !AICurlThread::sInstance->isStopped()) { ms_sleep(10); } - Dout(dc::curl, "Curl thread" << (curlThreadIsRunning() ? " not" : "") << " stopped after " << ((100 - count) * 10) << "ms."); - // Clear the command queue, for a cleaner cleanup. + if (AICurlThread::sInstance->isStopped()) + { + // isStopped() returns true somewhere at the end of run(), + // but that doesn't mean the thread really stopped: it still + // needs to destroy it's static variables. + // If we don't join here, then there is a chance that the + // curl thread will crash when using globals that we (the + // main thread) will have destroyed before it REALLY finished. + AICurlThread::sInstance->join_thread(); // Wait till it is REALLY done. + } + llinfos << "Curl thread" << (curlThreadIsRunning() ? " not" : "") << " stopped after " << ((400 - count) * 10) << "ms." << llendl; + } +} + +void clearCommandQueue(void) +{ + // Clear the command queue now in order to avoid the global deinitialization order fiasco. command_queue_wat command_queue_w(command_queue); command_queue_w->clear(); - } } //----------------------------------------------------------------------------- @@ -2161,7 +2268,17 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const& { mStatus = status; mReason = reason; - AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++; + if (status >= 100 && status < 600 && (status % 100) < 20) + { + // Only count statistic for sane values. + AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++; + } + + // Sanity check. If the server replies with a redirect status then we better have that option turned on! + if ((status >= 300 && status < 400) && mResponder && !mResponder->redirect_status_ok()) + { + llerrs << "Received " << status << " (" << reason << ") for responder \"" << mTimeoutPolicy->name() << "\" which has no followRedir()!" << llendl; + } } void BufferedCurlEasyRequest::processOutput(void) @@ -2172,7 +2289,7 @@ void BufferedCurlEasyRequest::processOutput(void) CURLcode code; AITransferInfo info; getResult(&code, &info); - if (code == CURLE_OK) + if (code == CURLE_OK && mStatus != HTTP_INTERNAL_ERROR) { getinfo(CURLINFO_RESPONSE_CODE, &responseCode); // If getResult code is CURLE_OK then we should have decoded the first header line ourselves. @@ -2185,7 +2302,7 @@ void BufferedCurlEasyRequest::processOutput(void) else { responseCode = HTTP_INTERNAL_ERROR; - responseReason = curl_easy_strerror(code); + responseReason = (code == CURLE_OK) ? mReason : std::string(curl_easy_strerror(code)); setopt(CURLOPT_FRESH_CONNECT, TRUE); } @@ -2306,23 +2423,31 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size std::string::iterator pos2 = std::find(pos1, end, ' '); if (pos2 != end) ++pos2; std::string::iterator pos3 = std::find(pos2, end, '\r'); - U32 status; + U32 status = 0; std::string reason; if (pos3 != end && std::isdigit(*pos1)) { status = atoi(&header_line[pos1 - begin]); reason.assign(pos2, pos3); } - else + if (!(status >= 100 && status < 600 && (status % 100) < 20)) // Sanity check on the decoded status. { + if (status == 0) + { + reason = "Header parse error."; + llwarns << "Received broken header line from server: \"" << header << "\"" << llendl; + } + else + { + reason = "Unexpected HTTP status."; + llwarns << "Received unexpected status value from server (" << status << "): \"" << header << "\"" << llendl; + } + // Either way, this status value is not understood (or taken into account). + // Set it to internal error so that the rest of code treats it as an error. status = HTTP_INTERNAL_ERROR; - reason = "Header parse error."; - llwarns << "Received broken header line from server: \"" << header << "\"" << llendl; - } - { - self_w->received_HTTP_header(); - self_w->setStatusAndReason(status, reason); } + self_w->received_HTTP_header(); + self_w->setStatusAndReason(status, reason); return header_len; } @@ -2351,14 +2476,25 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size } #if defined(CWDEBUG) || defined(DEBUG_CURLIO) -int debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void* user_ptr) +int debug_callback(CURL* handle, curl_infotype infotype, char* buf, size_t size, void* user_ptr) { + BufferedCurlEasyRequest* request = (BufferedCurlEasyRequest*)user_ptr; + if (infotype == CURLINFO_HEADER_OUT && size >= 5 && (strncmp(buf, "GET ", 4) == 0 || strncmp(buf, "HEAD ", 5) == 0)) + { + request->mDebugIsHeadOrGetMethod = true; + } + +#ifdef DEBUG_CURLIO + if (!debug_curl_print_debug(handle)) + { + return 0; + } +#endif + #ifdef CWDEBUG using namespace ::libcwd; - - BufferedCurlEasyRequest* request = (BufferedCurlEasyRequest*)user_ptr; std::ostringstream marker; - marker << (void*)request->get_lockobj(); + marker << (void*)request->get_lockobj() << ' '; libcw_do.push_marker(); libcw_do.marker().assign(marker.str().data(), marker.str().size()); if (!debug::channels::dc::curlio.is_on()) @@ -2382,8 +2518,6 @@ int debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void* break; case CURLINFO_HEADER_OUT: LibcwDoutStream << "H< "; - if (size >= 5 && (strncmp(buf, "GET ", 4) == 0 || strncmp(buf, "HEAD ", 5) == 0)) - request->mDebugIsHeadOrGetMethod = true; break; case CURLINFO_DATA_IN: LibcwDoutStream << "D> "; @@ -2557,6 +2691,14 @@ void AICurlEasyRequest::removeRequest(void) } } } + { + AICurlEasyRequest_wat curl_easy_request_w(*get()); + // As soon as the lock on the command queue is released, it could be picked up by + // the curl thread and executed. At that point it (already) demands that the easy + // request either timed out or is finished. So, to avoid race conditions that already + // has to be true right now. The call to queued_for_removal() checks this. + curl_easy_request_w->queued_for_removal(curl_easy_request_w); + } #endif // Add a command to remove this request from the multi session to the command queue. command_queue_w->push_back(Command(*this, cmd_remove)); diff --git a/indra/llmessage/aihttpheaders.cpp b/indra/llmessage/aihttpheaders.cpp index 0c6009cad..f019e05ac 100644 --- a/indra/llmessage/aihttpheaders.cpp +++ b/indra/llmessage/aihttpheaders.cpp @@ -107,6 +107,20 @@ void AIHTTPReceivedHeaders::addHeader(std::string const& key, std::string const& { mContainer = new Container; } + else if (equal(key, "set-cookie")) + { + // If a cookie with this name already exists, replace it. + std::string const name = value.substr(0, value.find('=')); + container_t::iterator const end = mContainer->mKeyValuePairs.end(); + for (container_t::iterator header = mContainer->mKeyValuePairs.begin(); header != end; ++header) + { + if (equal(header->first, "set-cookie") && header->second.substr(0, header->second.find('=')) == name) + { + header->second = value; + return; + } + } + } mContainer->mKeyValuePairs.insert(container_t::value_type(key, value)); } @@ -151,3 +165,20 @@ std::ostream& operator<<(std::ostream& os, AIHTTPReceivedHeaders const& headers) return os; } +//static +bool AIHTTPReceivedHeaders::equal(std::string const& key1, std::string const& key2) +{ + if (key1.length() != key2.length()) + { + return false; + } + for (std::string::const_iterator i1 = key1.begin(), i2 = key2.begin(); i1 != key1.end(); ++i1, ++i2) + { + if ((*i1 ^ *i2) & 0xdf != 0) + { + return false; + } + } + return true; +} + diff --git a/indra/llmessage/aihttpheaders.h b/indra/llmessage/aihttpheaders.h index da40ed7f9..637390660 100644 --- a/indra/llmessage/aihttpheaders.h +++ b/indra/llmessage/aihttpheaders.h @@ -132,6 +132,9 @@ class AIHTTPReceivedHeaders { // Add a header. void addHeader(std::string const& key, std::string const& value); + // Swap headers with another container. + void swap(AIHTTPReceivedHeaders& headers) { LLPointer::swap(mContainer, headers.mContainer); } + // Return true if there are no headers associated with this object. bool empty(void) const { return !mContainer || mContainer->mKeyValuePairs.empty(); } @@ -147,6 +150,9 @@ class AIHTTPReceivedHeaders { // For debug purposes. friend std::ostream& operator<<(std::ostream& os, AIHTTPReceivedHeaders const& headers); + // Returns true if the two keys compare equal (ie, "Set-Cookie" == "set-cookie"). + static bool equal(std::string const& key1, std::string const& key2); + private: struct Container : public LLThreadSafeRefCount { container_t mKeyValuePairs; diff --git a/indra/llmessage/aihttptimeoutpolicy.cpp b/indra/llmessage/aihttptimeoutpolicy.cpp index 4acd41267..354ec4625 100644 --- a/indra/llmessage/aihttptimeoutpolicy.cpp +++ b/indra/llmessage/aihttptimeoutpolicy.cpp @@ -646,6 +646,12 @@ AIHTTPTimeoutPolicyBase transfer_18s(AIHTTPTimeoutPolicyBase::getDebugSettingsCu transactionOp18s ); +// This used to be '30 seconds'. +Transaction transactionOp30s(30); +AIHTTPTimeoutPolicyBase transfer_30s(AIHTTPTimeoutPolicyBase::getDebugSettingsCurlTimeout(), + transactionOp30s + ); + // This used to be '300 seconds'. We derive this from the hardcoded result so users can't mess with it. Transaction transactionOp300s(300); AIHTTPTimeoutPolicyBase transfer_300s(HTTPTimeoutPolicy_default, @@ -820,6 +826,7 @@ P(accountingCostResponder); P(agentStateResponder); P(assetUploadResponder); P(asyncConsoleResponder); +P(avatarPickerResponder); P(authHandler); P(avatarNameResponder); P2(baseCapabilitiesComplete, transfer_18s); @@ -838,6 +845,7 @@ P(estateChangeInfoResponder); P(eventPollResponder); P(fetchInventoryResponder); P(fnPtrResponder); +P2(groupMemberDataResponder, transfer_300s); P2(groupProposalBallotResponder, transfer_300s); P(homeLocationResponder); P(HTTPGetResponder); @@ -850,6 +858,7 @@ P(lcl_responder); P(MPImportGetResponder); P(MPImportPostResponder); P(mapLayerResponder); +P2(maturityPreferences, transfer_30s); P(mediaTypeResponder); P(meshDecompositionResponder); P(meshHeaderResponder); @@ -889,6 +898,7 @@ P(viewerStatsResponder); P(viewerVoiceAccountProvisionResponder); P(voiceCallCapResponder); P(voiceClientCapResponder); +P(webProfileResponders); P(wholeModelFeeResponder); P(wholeModelUploadResponder); P2(XMLRPCResponder, connect_40s); diff --git a/indra/llmessage/debug_libcurl.cpp b/indra/llmessage/debug_libcurl.cpp index 512bc696c..0a302e601 100644 --- a/indra/llmessage/debug_libcurl.cpp +++ b/indra/llmessage/debug_libcurl.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "llpreprocessor.h" #include #define COMPILING_DEBUG_LIBCURL_CC @@ -528,19 +529,66 @@ std::ostream& operator<<(std::ostream& os, EvBitmask const& bitmask) return os; } +// Set this to limit the curl debug output to specific easy handles. +bool gDebugCurlTerse = false; + +namespace { + +std::vector handles; + +inline bool print_debug(CURL* handle) +{ + if (!gDebugCurlTerse) + return true; + return std::find(handles.begin(), handles.end(), handle) != handles.end(); +} + +} // namespace + +void debug_curl_add_easy(CURL* handle) +{ + std::vector::iterator iter = std::find(handles.begin(), handles.end(), handle); + if (iter == handles.end()) + { + handles.push_back(handle); + Dout(dc::warning, "debug_curl_add_easy(" << (void*)handle << "): added"); + } + llassert(print_debug(handle)); +} + +void debug_curl_remove_easy(CURL* handle) +{ + std::vector::iterator iter = std::find(handles.begin(), handles.end(), handle); + if (iter != handles.end()) + { + handles.erase(iter); + Dout(dc::warning, "debug_curl_remove_easy(" << (void*)handle << "): removed"); + } + llassert(!print_debug(handle)); +} + +bool debug_curl_print_debug(CURL* handle) +{ + return print_debug(handle); +} + extern "C" { void debug_curl_easy_cleanup(CURL* handle) { curl_easy_cleanup(handle); - Dout(dc::curl, "curl_easy_cleanup(" << (AICURL*)handle << ")"); + if (print_debug(handle)) + { + Dout(dc::curltr, "curl_easy_cleanup(" << (AICURL*)handle << ")"); + } } CURL* debug_curl_easy_duphandle(CURL* handle) { CURL* ret; ret = curl_easy_duphandle(handle); - Dout(dc::curl, "curl_easy_duphandle(" << (AICURL*)handle << ") = " << (AICURL*)ret); + if (!print_debug(handle)) return ret; + Dout(dc::curltr, "curl_easy_duphandle(" << (AICURL*)handle << ") = " << (AICURL*)ret); return ret; } @@ -548,11 +596,12 @@ char* debug_curl_easy_escape(CURL* curl, char* url, int length) { char* ret; ret = curl_easy_escape(curl, url, length); - Dout(dc::curl, "curl_easy_escape(" << (AICURL*)curl << ", \"" << url << "\", " << length << ") = \"" << ret << '"'); + if (!print_debug(curl)) return ret; + Dout(dc::curltr, "curl_easy_escape(" << (AICURL*)curl << ", \"" << url << "\", " << length << ") = \"" << ret << '"'); return ret; } -CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...) +CURLcode debug_curl_easy_getinfo(CURL* handle, CURLINFO info, ...) { CURLcode ret; va_list ap; @@ -566,26 +615,27 @@ CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...) va_start(ap, info); param.some_ptr = va_arg(ap, void*); va_end(ap); - ret = curl_easy_getinfo(curl, info, param.some_ptr); + ret = curl_easy_getinfo(handle, info, param.some_ptr); + if (!print_debug(handle)) return ret; if (info == CURLINFO_PRIVATE) { - Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", 0x" << std::hex << (size_t)param.some_ptr << std::dec << ") = " << ret); + Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", 0x" << std::hex << (size_t)param.some_ptr << std::dec << ") = " << ret); } else { switch((info & CURLINFO_TYPEMASK)) { case CURLINFO_STRING: - Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (char**){ \"" << (ret == CURLE_OK ? *param.char_ptr : " ") << "\" }) = " << ret); + Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (char**){ \"" << (ret == CURLE_OK ? *param.char_ptr : " ") << "\" }) = " << ret); break; case CURLINFO_LONG: - Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (long*){ " << (ret == CURLE_OK ? *param.long_ptr : 0L) << "L }) = " << ret); + Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (long*){ " << (ret == CURLE_OK ? *param.long_ptr : 0L) << "L }) = " << ret); break; case CURLINFO_DOUBLE: - Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (double*){" << (ret == CURLE_OK ? *param.double_ptr : 0.) << "}) = " << ret); + Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (double*){" << (ret == CURLE_OK ? *param.double_ptr : 0.) << "}) = " << ret); break; case CURLINFO_SLIST: - Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (curl_slist**){ " << (ret == CURLE_OK ? **param.curl_slist_ptr : unchanged_slist) << " }) = " << ret); + Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (curl_slist**){ " << (ret == CURLE_OK ? **param.curl_slist_ptr : unchanged_slist) << " }) = " << ret); break; } } @@ -596,7 +646,8 @@ CURL* debug_curl_easy_init(void) { CURL* ret; ret = curl_easy_init(); - Dout(dc::curl, "curl_easy_init() = " << (AICURL*)ret); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_easy_init() = " << (AICURL*)ret); return ret; } @@ -604,7 +655,8 @@ CURLcode debug_curl_easy_pause(CURL* handle, int bitmask) { CURLcode ret; ret = curl_easy_pause(handle, bitmask); - Dout(dc::curl, "curl_easy_pause(" << (AICURL*)handle << ", 0x" << std::hex << bitmask << std::dec << ") = " << ret); + if (!print_debug(handle)) return ret; + Dout(dc::curltr, "curl_easy_pause(" << (AICURL*)handle << ", 0x" << std::hex << bitmask << std::dec << ") = " << ret); return ret; } @@ -612,19 +664,21 @@ CURLcode debug_curl_easy_perform(CURL* handle) { CURLcode ret; ret = curl_easy_perform(handle); - Dout(dc::curl, "curl_easy_perform(" << (AICURL*)handle << ") = " << ret); + if (!print_debug(handle)) return ret; + Dout(dc::curltr, "curl_easy_perform(" << (AICURL*)handle << ") = " << ret); return ret; } void debug_curl_easy_reset(CURL* handle) { curl_easy_reset(handle); - Dout(dc::curl, "curl_easy_reset(" << (AICURL*)handle << ")"); + if (!print_debug(handle)) return; + Dout(dc::curltr, "curl_easy_reset(" << (AICURL*)handle << ")"); } CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...) { - CURLcode ret; + CURLcode ret = CURLE_OBSOLETE50; // Suppress compiler warning. va_list ap; union param_type { long along; @@ -656,7 +710,10 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...) case CURLOPTTYPE_LONG: { ret = curl_easy_setopt(handle, option, param.along); - Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", " << param.along << "L) = " << ret); + if (print_debug(handle)) + { + Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", " << param.along << "L) = " << ret); + } if (option == CURLOPT_POSTFIELDSIZE) { postfieldsize = param.along; @@ -666,7 +723,8 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...) case CURLOPTTYPE_OBJECTPOINT: { ret = curl_easy_setopt(handle, option, param.ptr); - LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcwd::libcw_do, dc::curl) + if (!print_debug(handle)) break; + LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcwd::libcw_do, dc::curltr) LibcwDoutStream << "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", "; // For a subset of all options that take a char*, print the string passed. if (option == CURLOPT_PROXY || // Set HTTP proxy to use. The parameter should be a char* to a zero terminated string holding the host name or dotted IP address. @@ -717,11 +775,11 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...) if (option == CURLOPT_HTTPHEADER && param.ptr) { debug::Indent indent(2); - Dout(dc::curl, "HTTP Headers:"); + Dout(dc::curltr, "HTTP Headers:"); struct curl_slist* list = (struct curl_slist*)param.ptr; while (list) { - Dout(dc::curl, '"' << list->data << '"'); + Dout(dc::curltr, '"' << list->data << '"'); list = list->next; } } @@ -729,12 +787,18 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...) } case CURLOPTTYPE_FUNCTIONPOINT: ret = curl_easy_setopt(handle, option, param.ptr); - Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret); + if (print_debug(handle)) + { + Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret); + } break; case CURLOPTTYPE_OFF_T: { ret = curl_easy_setopt(handle, option, param.offset); - Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret); + if (print_debug(handle)) + { + Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret); + } if (option == CURLOPT_POSTFIELDSIZE_LARGE) { postfieldsize = (long)param.offset; @@ -751,7 +815,8 @@ char const* debug_curl_easy_strerror(CURLcode errornum) { char const* ret; ret = curl_easy_strerror(errornum); - Dout(dc::curl, "curl_easy_strerror(" << errornum << ") = \"" << ret << '"'); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_easy_strerror(" << errornum << ") = \"" << ret << '"'); return ret; } @@ -759,35 +824,38 @@ char* debug_curl_easy_unescape(CURL* curl, char* url, int inlength, int* outleng { char* ret; ret = curl_easy_unescape(curl, url, inlength, outlength); - Dout(dc::curl, "curl_easy_unescape(" << (AICURL*)curl << ", \"" << url << "\", " << inlength << ", " << ((ret && outlength) ? *outlength : 1) << ") = \"" << ret << '"'); + if (!print_debug(curl)) return ret; + Dout(dc::curltr, "curl_easy_unescape(" << (AICURL*)curl << ", \"" << url << "\", " << inlength << ", " << ((ret && outlength) ? *outlength : 1) << ") = \"" << ret << '"'); return ret; } void debug_curl_free(char* ptr) { curl_free(ptr); - Dout(dc::curl, "curl_free(0x" << std::hex << (size_t)ptr << std::dec << ")"); + if (gDebugCurlTerse) return; + Dout(dc::curltr, "curl_free(0x" << std::hex << (size_t)ptr << std::dec << ")"); } time_t debug_curl_getdate(char const* datestring, time_t* now) { time_t ret; ret = curl_getdate(datestring, now); - Dout(dc::curl, "curl_getdate(\"" << datestring << "\", " << (now == NULL ? "NULL" : "") << ") = " << ret); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_getdate(\"" << datestring << "\", " << (now == NULL ? "NULL" : "") << ") = " << ret); return ret; } void debug_curl_global_cleanup(void) { curl_global_cleanup(); - Dout(dc::curl, "curl_global_cleanup()"); + Dout(dc::curltr, "curl_global_cleanup()"); } CURLcode debug_curl_global_init(long flags) { CURLcode ret; ret = curl_global_init(flags); - Dout(dc::curl, "curl_global_init(0x" << std::hex << flags << std::dec << ") = " << ret); + Dout(dc::curltr, "curl_global_init(0x" << std::hex << flags << std::dec << ") = " << ret); return ret; } @@ -795,7 +863,8 @@ CURLMcode debug_curl_multi_add_handle(CURLM* multi_handle, CURL* easy_handle) { CURLMcode ret; ret = curl_multi_add_handle(multi_handle, easy_handle); - Dout(dc::curl, "curl_multi_add_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_multi_add_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret); return ret; } @@ -803,7 +872,8 @@ CURLMcode debug_curl_multi_assign(CURLM* multi_handle, curl_socket_t sockfd, voi { CURLMcode ret; ret = curl_multi_assign(multi_handle, sockfd, sockptr); - Dout(dc::curl, "curl_multi_assign(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << ", " << sockptr << ") = " << ret); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_multi_assign(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << ", " << sockptr << ") = " << ret); return ret; } @@ -811,7 +881,8 @@ CURLMcode debug_curl_multi_cleanup(CURLM* multi_handle) { CURLMcode ret; ret = curl_multi_cleanup(multi_handle); - Dout(dc::curl, "curl_multi_cleanup(" << (AICURLM*)multi_handle << ") = " << ret); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_multi_cleanup(" << (AICURLM*)multi_handle << ") = " << ret); return ret; } @@ -819,7 +890,8 @@ CURLMsg* debug_curl_multi_info_read(CURLM* multi_handle, int* msgs_in_queue) { CURLMsg* ret; ret = curl_multi_info_read(multi_handle, msgs_in_queue); - Dout(dc::curl, "curl_multi_info_read(" << (AICURLM*)multi_handle << ", {" << *msgs_in_queue << "}) = " << ret); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_multi_info_read(" << (AICURLM*)multi_handle << ", {" << *msgs_in_queue << "}) = " << ret); return ret; } @@ -827,7 +899,8 @@ CURLM* debug_curl_multi_init(void) { CURLM* ret; ret = curl_multi_init(); - Dout(dc::curl, "curl_multi_init() = " << (AICURLM*)ret); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_multi_init() = " << (AICURLM*)ret); return ret; } @@ -835,13 +908,14 @@ CURLMcode debug_curl_multi_remove_handle(CURLM* multi_handle, CURL* easy_handle) { CURLMcode ret; ret = curl_multi_remove_handle(multi_handle, easy_handle); - Dout(dc::curl, "curl_multi_remove_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret); + if (!print_debug(easy_handle)) return ret; + Dout(dc::curltr, "curl_multi_remove_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret); return ret; } CURLMcode debug_curl_multi_setopt(CURLM* multi_handle, CURLMoption option, ...) { - CURLMcode ret; + CURLMcode ret = CURLM_UNKNOWN_OPTION; // Suppress compiler warning. va_list ap; union param_type { long along; @@ -871,19 +945,23 @@ CURLMcode debug_curl_multi_setopt(CURLM* multi_handle, CURLMoption option, ...) { case CURLOPTTYPE_LONG: ret = curl_multi_setopt(multi_handle, option, param.along); - Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", " << param.along << "L) = " << ret); + if (gDebugCurlTerse) break; + Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", " << param.along << "L) = " << ret); break; case CURLOPTTYPE_OBJECTPOINT: ret = curl_multi_setopt(multi_handle, option, param.ptr); - Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret); + if (gDebugCurlTerse) break; + Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret); break; case CURLOPTTYPE_FUNCTIONPOINT: ret = curl_multi_setopt(multi_handle, option, param.ptr); - Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret); + if (gDebugCurlTerse) break; + Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret); break; case CURLOPTTYPE_OFF_T: ret = curl_multi_setopt(multi_handle, option, param.offset); - Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret); + if (gDebugCurlTerse) break; + Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret); break; default: // Stop compiler complaining about no default. break; @@ -895,7 +973,8 @@ CURLMcode debug_curl_multi_socket_action(CURLM* multi_handle, curl_socket_t sock { CURLMcode ret; ret = curl_multi_socket_action(multi_handle, sockfd, ev_bitmask, running_handles); - Dout(dc::curl, "curl_multi_socket_action(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_multi_socket_action(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << ", " << EvBitmask(ev_bitmask) << ", {" << (ret == CURLM_OK ? *running_handles : 0) << "}) = " << ret); return ret; } @@ -904,7 +983,8 @@ char const* debug_curl_multi_strerror(CURLMcode errornum) { char const* ret; ret = curl_multi_strerror(errornum); - Dout(dc::curl, "curl_multi_strerror(" << errornum << ") = \"" << ret << '"'); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_multi_strerror(" << errornum << ") = \"" << ret << '"'); return ret; } @@ -912,21 +992,24 @@ struct curl_slist* debug_curl_slist_append(struct curl_slist* list, char const* { struct curl_slist* ret; ret = curl_slist_append(list, string); - Dout(dc::curl, "curl_slist_append((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ", \"" << string << "\") = " << *ret); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_slist_append((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ", \"" << string << "\") = " << *ret); return ret; } void debug_curl_slist_free_all(struct curl_slist* list) { curl_slist_free_all(list); - Dout(dc::curl, "curl_slist_free_all((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ")"); + if (gDebugCurlTerse) return; + Dout(dc::curltr, "curl_slist_free_all((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ")"); } char* debug_curl_unescape(char const* url, int length) { char* ret; ret = curl_unescape(url, length); - Dout(dc::curl, "curl_unescape(\"" << url << "\", " << length << ") = \"" << ret << '"'); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_unescape(\"" << url << "\", " << length << ") = \"" << ret << '"'); return ret; } @@ -934,7 +1017,8 @@ char* debug_curl_version(void) { char* ret; ret = curl_version(); - Dout(dc::curl, "curl_version() = \"" << ret << '"'); + if (gDebugCurlTerse) return ret; + Dout(dc::curltr, "curl_version() = \"" << ret << '"'); return ret; } diff --git a/indra/llmessage/debug_libcurl.h b/indra/llmessage/debug_libcurl.h index 27becb1c6..49105aa1d 100644 --- a/indra/llmessage/debug_libcurl.h +++ b/indra/llmessage/debug_libcurl.h @@ -86,4 +86,9 @@ extern char* debug_curl_version(void); #endif // !COMPILING_DEBUG_LIBCURL_CC +extern bool gDebugCurlTerse; // With this set, +void debug_curl_add_easy(CURL* handle); // only output debug output for easy handles added with this function. +void debug_curl_remove_easy(CURL* handle); +bool debug_curl_print_debug(CURL* handle); + #endif // DEBUG_LIBCURL diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index ae04a8105..48b6e4f63 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -24,12 +24,12 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - #include "linden_common.h" #include "llavatarnamecache.h" #include "llcachename.h" // we wrap this system +#include "llcontrol.h" // For LLCachedControl #include "llframetimer.h" #include "llhttpclient.h" #include "llsd.h" @@ -93,6 +93,9 @@ namespace LLAvatarNameCache /// Time when unrefreshed cached names were checked last static F64 sLastExpireCheck; + /// Time-to-live for a temp cache entry. + const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0; + //----------------------------------------------------------------------- // Internal methods //----------------------------------------------------------------------- @@ -291,13 +294,14 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) // Clear this agent from the pending list LLAvatarNameCache::sPendingQueue.erase(agent_id); - const LLAvatarName& av_name = existing->second; + LLAvatarName& av_name = existing->second; LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " << agent_id << "user '" << av_name.mUsername << "' " << "display '" << av_name.mDisplayName << "' " << "expires in " << av_name.mExpires - LLFrameTimer::getTotalSeconds() << " seconds" << LL_ENDL; + av_name.mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; // reset expiry time so we don't constantly rerequest. } } @@ -342,19 +346,23 @@ void LLAvatarNameCache::requestNamesViaCapability() // http://pdp60.lindenlab.com:8000/agents/?ids=3941037e-78ab-45f0-b421-bd6e77c1804d&ids=0012809d-7d2d-4c24-9609-af1230a37715&ids=0019aaba-24af-4f0a-aa72-6457953cf7f0 // // Apache can handle URLs of 4096 chars, but let's be conservative - const U32 NAME_URL_MAX = 4096; - const U32 NAME_URL_SEND_THRESHOLD = 3000; + static const U32 NAME_URL_MAX = 4096; + static const U32 NAME_URL_SEND_THRESHOLD = 3500; + std::string url; url.reserve(NAME_URL_MAX); std::vector agent_ids; agent_ids.reserve(128); + U32 id_total = sAskQueue.size(); U32 ids = 0; - ask_queue_t::const_iterator it = sAskQueue.begin(); - for ( ; it != sAskQueue.end(); ++it) + ask_queue_t::const_iterator it; + while(!sAskQueue.empty()) { + it = sAskQueue.begin(); const LLUUID& agent_id = *it; + sAskQueue.erase(it); if (url.empty()) { @@ -377,27 +385,17 @@ void LLAvatarNameCache::requestNamesViaCapability() if (url.size() > NAME_URL_SEND_THRESHOLD) { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability first " - << ids << " ids" - << LL_ENDL; - LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids)); - url.clear(); - agent_ids.clear(); + break; } } if (!url.empty()) { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability all " - << ids << " ids" + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested " + << ids << "/" << id_total << "ids " << LL_ENDL; LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids)); - url.clear(); - agent_ids.clear(); } - - // We've moved all asks to the pending request queue - sAskQueue.clear(); } void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id, @@ -414,20 +412,25 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id, << LL_ENDL; buildLegacyName(full_name, &av_name); - // Don't add to cache, the data already exists in the legacy name system - // cache and we don't want or need duplicate storage, because keeping the - // two copies in sync is complex. - processName(agent_id, av_name, false); + // Add to cache, because if we don't we'll keep rerequesting the + // same record forever. buildLegacyName should always guarantee + // that these records expire reasonably soon + // (in TEMP_CACHE_ENTRY_LIFETIME seconds), so if the failure was due + // to something temporary we will eventually request and get the right data. + processName(agent_id, av_name, true); } void LLAvatarNameCache::requestNamesViaLegacy() { + static const S32 MAX_REQUESTS = 100; F64 now = LLFrameTimer::getTotalSeconds(); std::string full_name; - ask_queue_t::const_iterator it = sAskQueue.begin(); - for (; it != sAskQueue.end(); ++it) + ask_queue_t::const_iterator it; + for (S32 requests = 0; !sAskQueue.empty() && requests < MAX_REQUESTS; ++requests) { + it = sAskQueue.begin(); const LLUUID& agent_id = *it; + sAskQueue.erase(it); // Mark as pending first, just in case the callback is immediately // invoked below. This should never happen in practice. @@ -439,10 +442,6 @@ void LLAvatarNameCache::requestNamesViaLegacy() boost::bind(&LLAvatarNameCache::legacyNameCallback, _1, _2, _3)); } - - // We've either answered immediately or moved all asks to the - // pending queue - sAskQueue.clear(); } void LLAvatarNameCache::initClass(bool running) @@ -519,11 +518,11 @@ void LLAvatarNameCache::idle() // *TODO: Possibly re-enabled this based on People API load measurements // 100 ms is the threshold for "user speed" operations, so we can // stall for about that long to batch up requests. - //const F32 SECS_BETWEEN_REQUESTS = 0.1f; - //if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) - //{ - // return; - //} + const F32 SECS_BETWEEN_REQUESTS = 0.1f; + if (!sRequestTimer.hasExpired()) + { + return; + } if (!sAskQueue.empty()) { @@ -538,6 +537,12 @@ void LLAvatarNameCache::idle() } } + if (sAskQueue.empty()) + { + // cleared the list, reset the request timer. + sRequestTimer.reset(SECS_BETWEEN_REQUESTS); + } + // erase anything that has not been refreshed for more than MAX_UNREFRESHED_TIME eraseUnrefreshed(); } @@ -595,7 +600,7 @@ void LLAvatarNameCache::buildLegacyName(const std::string& full_name, av_name->mDisplayName = full_name; av_name->mIsDisplayNameDefault = true; av_name->mIsTemporaryName = true; - av_name->mExpires = F64_MAX; // not used because these are not cached + av_name->mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::buildLegacyName " << full_name << LL_ENDL; @@ -619,7 +624,6 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) // ...only do immediate lookups when cache is running if (useDisplayNames()) { - // ...use display names cache std::map::iterator it = sCache.find(agent_id); if (it != sCache.end()) @@ -664,6 +668,29 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name) return false; } +// Return true when name has been set to Phoenix Name System Name, if not return false. +bool LLAvatarNameCache::getPNSName(const LLUUID& agent_id, std::string& name) +{ + LLAvatarName avatar_name; + if (get(agent_id, &avatar_name)) + getPNSName(avatar_name, name); + else return false; + return true; +} + +// get() with callback compatible version of getPNSName +void LLAvatarNameCache::getPNSName(const LLAvatarName& avatar_name, std::string& name) +{ + static LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); + switch (phoenix_name_system) + { + case 0 : name = avatar_name.getLegacyName(); break; + case 1 : name = avatar_name.getCompleteName(); break; + case 2 : name = avatar_name.mDisplayName; break; + default : name = avatar_name.getLegacyName(); break; + } +} + void LLAvatarNameCache::fireSignal(const LLUUID& agent_id, const callback_slot_t& slot, const LLAvatarName& av_name) @@ -673,8 +700,10 @@ void LLAvatarNameCache::fireSignal(const LLUUID& agent_id, signal(agent_id, av_name); } -void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot) +LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot) { + callback_connection_t connection; + if (sRunning) { // ...only do immediate lookups when cache is running @@ -690,7 +719,7 @@ void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot) { // ...name already exists in cache, fire callback now fireSignal(agent_id, slot, av_name); - return; + return connection; } } } @@ -703,7 +732,7 @@ void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot) LLAvatarName av_name; buildLegacyName(full_name, &av_name); fireSignal(agent_id, slot, av_name); - return; + return connection; } } } @@ -720,15 +749,17 @@ void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot) { // ...new callback for this id callback_signal_t* signal = new callback_signal_t(); - signal->connect(slot); + connection = signal->connect(slot); sSignalMap[agent_id] = signal; } else { // ...existing callback, bind additional slot callback_signal_t* signal = sig_it->second; - signal->connect(slot); + connection = signal->connect(slot); } + + return connection; } // [RLVa:KB] - Checked: 2010-12-08 (RLVa-1.4.0a) | Added: RLVa-1.2.2c @@ -774,12 +805,6 @@ void LLAvatarNameCache::erase(const LLUUID& agent_id) sCache.erase(agent_id); } -void LLAvatarNameCache::fetch(const LLUUID& agent_id) -{ - // re-request, even if request is already pending - sAskQueue.insert(agent_id); -} - void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_name) { // *TODO: update timestamp if zero? @@ -788,26 +813,35 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na F64 LLAvatarNameCache::nameExpirationFromHeaders(AIHTTPReceivedHeaders const& headers) { - F64 expires; - expirationFromCacheControl(headers, &expires); - return expires; + F64 expires = 0.0; + if (expirationFromCacheControl(headers, &expires)) + { + return expires; + } + else + { + // With no expiration info, default to an hour + const F64 DEFAULT_EXPIRES = 60.0 * 60.0; + F64 now = LLFrameTimer::getTotalSeconds(); + return now + DEFAULT_EXPIRES; + } } bool LLAvatarNameCache::expirationFromCacheControl(AIHTTPReceivedHeaders const& headers, F64* expires) { bool fromCacheControl = false; - S32 max_age = 3600; // With no expiration info, default to an hour. F64 now = LLFrameTimer::getTotalSeconds(); // Allow the header to override the default std::string cache_control; if (headers.getFirstValue("cache-control", cache_control)) { + S32 max_age = 0; if (max_age_from_cache_control(cache_control, &max_age)) { + *expires = now + (F64)max_age; fromCacheControl = true; } } - *expires = now + (F64)max_age; LL_DEBUGS("AvNameCache") << ( fromCacheControl ? "expires based on cache control " : "default expiration " ) << "in " << *expires - now << " seconds" diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index 75f613e74..99e3fba57 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -65,16 +65,23 @@ namespace LLAvatarNameCache // If name is in cache, returns true and fills in provided LLAvatarName // otherwise returns false bool get(const LLUUID& agent_id, LLAvatarName *av_name); + // If get() succeeds, returns true and fills in name string + // via void function below, otherwise returns false + bool getPNSName(const LLUUID& agent_id, std::string& name); + // Perform a filling of name string according to Phoenix Name System, + // when we have an LLAvatarName already. + void getPNSName(const LLAvatarName& avatar_name, std::string& name); // Callback types for get() below typedef boost::signals2::signal< void (const LLUUID& agent_id, const LLAvatarName& av_name)> callback_signal_t; typedef callback_signal_t::slot_type callback_slot_t; + typedef boost::signals2::connection callback_connection_t; // Fetches name information and calls callback. // If name information is in cache, callback will be called immediately. - void get(const LLUUID& agent_id, callback_slot_t slot); + callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot); // Allow display names to be explicitly disabled for testing. void setUseDisplayNames(bool use); @@ -90,10 +97,6 @@ namespace LLAvatarNameCache /// Provide some fallback for agents that return errors void handleAgentError(const LLUUID& agent_id); - // Force a re-fetch of the most recent data, but keep the current - // data in cache - void fetch(const LLUUID& agent_id); - void insert(const LLUUID& agent_id, const LLAvatarName& av_name); // Compute name expiration time from HTTP Cache-Control header, diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index b7871556e..4021850a5 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -200,7 +200,9 @@ static void request( LLURLRequest::ERequestAction method, Injector* body_injector, LLHTTPClient::ResponderPtr responder, - AIHTTPHeaders& headers, + AIHTTPHeaders& headers/*,*/ + DEBUG_CURLIO_PARAM(EDebugCurl debug), + EKeepAlive keepalive = keep_alive, bool is_auth = false, bool no_compression = false) { @@ -213,7 +215,10 @@ static void request( LLURLRequest* req; try { - req = new LLURLRequest(method, url, body_injector, responder, headers, is_auth, no_compression); + req = new LLURLRequest(method, url, body_injector, responder, headers, keepalive, is_auth, no_compression); +#ifdef DEBUG_CURLIO + req->mCurlEasyRequest.debug(debug); +#endif } catch(AICurlNoEasyHandle& error) { @@ -225,36 +230,36 @@ static void request( req->run(); } -void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { if(offset > 0 || bytes > 0) { headers.addHeader("Range", llformat("bytes=%d-%d", offset, offset + bytes - 1)); } - request(url, LLURLRequest::HTTP_GET, NULL, responder, headers); + request(url, LLURLRequest::HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } -void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers) +void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { - request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers); + request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } -void LLHTTPClient::get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { - request(url, LLURLRequest::HTTP_GET, NULL, responder, headers); + request(url, LLURLRequest::HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } -void LLHTTPClient::getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers) +void LLHTTPClient::getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { - request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers); + request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } -void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { LLURI uri; uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query); - get(uri.asString(), responder, headers); + get(uri.asString(), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } //============================================================================= @@ -362,6 +367,22 @@ void LLHTTPClient::ResponderBase::decode_raw_body(U32 status, std::string const& } } +std::string const& LLHTTPClient::ResponderBase::get_cookie(std::string const& key) +{ + AIHTTPReceivedHeaders::range_type cookies; + mReceivedHeaders.getValues("set-cookie", cookies); + for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie) + { + if (key == cookie->second.substr(0, cookie->second.find('='))) + { + return cookie->second; + } + } + // Not found. + static std::string empty_dummy; + return empty_dummy; +} + // Called with HTML body. // virtual void LLHTTPClient::ResponderWithCompleted::completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) @@ -554,7 +575,8 @@ enum EBlockingRequestAction { static LLSD blocking_request( std::string const& url, EBlockingRequestAction method, - LLSD const& body) // Only used for HTTP_LLSD_POST + LLSD const& body/*,*/ // Only used for HTTP_LLSD_POST + DEBUG_CURLIO_PARAM(EDebugCurl debug)) { lldebugs << "blockingRequest of " << url << llendl; @@ -563,17 +585,17 @@ static LLSD blocking_request( if (method == HTTP_LLSD_POST) { responder = new BlockingLLSDPostResponder; - LLHTTPClient::post(url, body, responder, headers); + LLHTTPClient::post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } else if (method == HTTP_LLSD_GET) { responder = new BlockingLLSDGetResponder; - LLHTTPClient::get(url, responder, headers); + LLHTTPClient::get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } else // method == HTTP_RAW_GET { responder = new BlockingRawGetResponder; - LLHTTPClient::get(url, responder, headers); + LLHTTPClient::get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } responder->wait(); @@ -635,39 +657,39 @@ static LLSD blocking_request( return response; } -LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body) +LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { - return blocking_request(url, HTTP_LLSD_POST, body); + return blocking_request(url, HTTP_LLSD_POST, body/*,*/ DEBUG_CURLIO_PARAM(debug)); } -LLSD LLHTTPClient::blockingGet(const std::string& url) +LLSD LLHTTPClient::blockingGet(const std::string& url/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { - return blocking_request(url, HTTP_LLSD_GET, LLSD()); + return blocking_request(url, HTTP_LLSD_GET, LLSD()/*,*/ DEBUG_CURLIO_PARAM(debug)); } -U32 LLHTTPClient::blockingGetRaw(const std::string& url, std::string& body) +U32 LLHTTPClient::blockingGetRaw(const std::string& url, std::string& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { - LLSD result = blocking_request(url, HTTP_RAW_GET, LLSD()); + LLSD result = blocking_request(url, HTTP_RAW_GET, LLSD()/*,*/ DEBUG_CURLIO_PARAM(debug)); body = result["body"].asString(); return result["status"].asInteger(); } -void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { - request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers); + request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } -void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive) { - request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers); + request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } -void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive) { - request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, false); // Does use compression. + request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, true, false); // Does use compression. } -void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive) { XMLRPC_REQUEST xmlrpc_request = XMLRPC_RequestNew(); XMLRPC_RequestSetMethodName(xmlrpc_request, method); @@ -675,33 +697,33 @@ void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC XMLRPC_RequestSetData(xmlrpc_request, value); // XMLRPCInjector takes ownership of xmlrpc_request and will free it when done. // LLURLRequest takes ownership of the XMLRPCInjector object and will free it when done. - request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, true); // Does not use compression. + request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, true, true); // Does not use compression. } -void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive) { - request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers); + request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } -void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive) { - request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers); + request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } -void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive) { - request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers); + request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } // static -void LLHTTPClient::del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { - request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers); + request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } // static -void LLHTTPClient::move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers) +void LLHTTPClient::move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug)) { headers.addHeader("Destination", destination); - request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers); + request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index 3e491de82..934d5b137 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -66,6 +66,21 @@ struct AIBufferedCurlEasyRequestEvents { virtual void completed_headers(U32 status, std::string const& reason, AITransferInfo* info) = 0; // Transaction completed. }; +enum EKeepAlive { + no_keep_alive = 0, + keep_alive +}; + +#ifdef DEBUG_CURLIO +enum EDebugCurl { + debug_off = 0, + debug_on +}; +#define DEBUG_CURLIO_PARAM(p) ,p +#else +#define DEBUG_CURLIO_PARAM(p) +#endif + class LLHTTPClient { public: @@ -140,7 +155,16 @@ public: { // It's possible that this page was moved (302), so we already saw headers // from the 302 page and are starting over on the new page now. - mReceivedHeaders.clear(); + // Erase all headers EXCEPT the cookies. + AIHTTPReceivedHeaders set_cookie_headers; + AIHTTPReceivedHeaders::range_type cookies; + mReceivedHeaders.getValues("set-cookie", cookies); + for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie) + { + set_cookie_headers.addHeader(cookie->first, cookie->second); + } + // Replace headers with just the cookie headers. + mReceivedHeaders.swap(set_cookie_headers); } // Called for all remaining headers. @@ -155,13 +179,19 @@ public: completedHeaders(status, reason, mReceivedHeaders); } + // Extract cookie 'key' from mReceivedHeaders and return the string 'key=value', or an empty string if key does not exists. + std::string const& get_cookie(std::string const& key); + public: // Derived classes that implement completed_headers()/completedHeaders() should return true here. virtual bool needsHeaders(void) const { return false; } // A derived class should return true if curl should follow redirections. // The default is not to follow redirections. - virtual bool followRedir(void) { return false; } + virtual bool followRedir(void) const { return false; } + + // If this function returns false then we generate an error when a redirect status (300..399) is received. + virtual bool redirect_status_ok(void) const { return followRedir(); } // Timeout policy to use. virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0; @@ -188,6 +218,7 @@ public: class ResponderHeadersOnly : public ResponderBase { private: /*virtual*/ bool needsHeaders(void) const { return true; } + /*virtual*/ bool followRedir(void) const { return true; } protected: // ResponderBase event @@ -357,59 +388,59 @@ public: /** @name non-blocking API */ //@{ - static void head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers); - static void head(std::string const& url, ResponderHeadersOnly* responder) - { AIHTTPHeaders headers; head(url, responder, headers); } + static void head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); + static void head(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) + { AIHTTPHeaders headers; head(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } - static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers); - static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder) - { AIHTTPHeaders headers; getByteRange(url, offset, bytes, responder, headers); } + static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); + static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) + { AIHTTPHeaders headers; getByteRange(url, offset, bytes, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } - static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers); - static void get(std::string const& url, ResponderPtr responder) - { AIHTTPHeaders headers; get(url, responder, headers); } + static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); + static void get(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) + { AIHTTPHeaders headers; get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } - static void get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers); - static void get(std::string const& url, LLSD const& query, ResponderPtr responder) - { AIHTTPHeaders headers; get(url, query, responder, headers); } + static void get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); + static void get(std::string const& url, LLSD const& query, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) + { AIHTTPHeaders headers; get(url, query, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } - static void put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers); - static void put(std::string const& url, LLSD const& body, ResponderPtr responder) - { AIHTTPHeaders headers; put(url, body, responder, headers); } + static void put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); + static void put(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) + { AIHTTPHeaders headers; put(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } - static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers); - static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder) - { AIHTTPHeaders headers; getHeaderOnly(url, responder, headers); } + static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); + static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) + { AIHTTPHeaders headers; getHeaderOnly(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } - static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers); - static void post(std::string const& url, LLSD const& body, ResponderPtr responder) - { AIHTTPHeaders headers; post(url, body, responder, headers); } + static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); + static void post(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) + { AIHTTPHeaders headers; post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } /** Takes ownership of request and deletes it when sent */ - static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers); - static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder) - { AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers); } + static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); + static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) + { AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } - static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers); - static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder) - { AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers); } + static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); + static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) + { AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } /** Takes ownership of data and deletes it when sent */ - static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers); - static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder) - { AIHTTPHeaders headers; postRaw(url, data, size, responder, headers); } + static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); + static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) + { AIHTTPHeaders headers; postRaw(url, data, size, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } - static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers); - static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder) - { AIHTTPHeaders headers; postFile(url, filename, responder, headers); } + static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); + static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) + { AIHTTPHeaders headers; postFile(url, filename, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } - static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers); - static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder) - { AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers); } + static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); + static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) + { AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } - static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers); - static void del(std::string const& url, ResponderPtr responder) - { AIHTTPHeaders headers; del(url, responder, headers); } + static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); + static void del(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) + { AIHTTPHeaders headers; del(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } ///< sends a DELETE method, but we can't call it delete in c++ @@ -422,9 +453,9 @@ public: * @param headers A map of key:value headers to pass to the request * @param timeout The number of seconds to give the server to respond. */ - static void move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers); - static void move(std::string const& url, std::string const& destination, ResponderPtr responder) - { AIHTTPHeaders headers; move(url, destination, responder, headers); } + static void move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); + static void move(std::string const& url, std::string const& destination, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) + { AIHTTPHeaders headers; move(url, destination, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } //@} @@ -434,7 +465,7 @@ public: * @param url the complete serialized (and escaped) url to get * @return An LLSD of { 'status':status, 'body':payload } */ - static LLSD blockingGet(std::string const& url); + static LLSD blockingGet(std::string const& url/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); /** * @brief Blocking HTTP GET that returns the raw body. @@ -443,7 +474,7 @@ public: * @param result the target string to write the body to * @return HTTP status */ - static U32 blockingGetRaw(const std::string& url, std::string& result); + static U32 blockingGetRaw(const std::string& url, std::string& result/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); /** * @brief Blocking HTTP POST that returns an LLSD map of status and body. @@ -452,7 +483,7 @@ public: * @param body the LLSD post body * @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) } */ - static LLSD blockingPost(std::string const& url, LLSD const& body); + static LLSD blockingPost(std::string const& url, LLSD const& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); }; #endif // LL_LLHTTPCLIENT_H diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 927b64b7a..429a93627 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -77,19 +77,14 @@ std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action) // This might throw AICurlNoEasyHandle. LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string const& url, Injector* body, - LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression) : - mAction(action), mURL(url), mIsAuth(is_auth), mNoCompression(no_compression), + LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression) : + mAction(action), mURL(url), mKeepAlive(keepalive), mIsAuth(is_auth), mNoCompression(no_compression), mBody(body), mResponder(responder), mHeaders(headers) { } void LLURLRequest::initialize_impl(void) { - if (mHeaders.hasHeader("Cookie")) - { - allowCookies(); - } - // If the header is "Pragma" with no value, the caller intends to // force libcurl to drop the Pragma header it so gratuitously inserts. // Before inserting the header, force libcurl to not use the proxy. @@ -105,7 +100,7 @@ void LLURLRequest::initialize_impl(void) // but if they did not specify a Content-Type, then ask the injector. mHeaders.addHeader("Content-Type", mBody->contentType(), AIHTTPHeaders::keep_existing_header); } - else + else if (mAction != HTTP_HEAD) { // Check to see if we have already set Accept or not. If no one // set it, set it to application/llsd+xml since that's what we @@ -199,12 +194,6 @@ void LLURLRequest::useProxy(const std::string &proxy) } #endif -void LLURLRequest::allowCookies() -{ - AICurlEasyRequest_wat curlEasyRequest_w(*mCurlEasyRequest); - curlEasyRequest_w->setoptString(CURLOPT_COOKIEFILE, ""); -} - bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w) { bool rv = false; @@ -213,13 +202,11 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w) { case HTTP_HEAD: curlEasyRequest_w->setopt(CURLOPT_NOBODY, 1); - curlEasyRequest_w->setopt(CURLOPT_FOLLOWLOCATION, 1); rv = true; break; case HTTP_GET: curlEasyRequest_w->setopt(CURLOPT_HTTPGET, 1); - curlEasyRequest_w->setopt(CURLOPT_FOLLOWLOCATION, 1); // Set Accept-Encoding to allow response compression curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : ""); @@ -239,7 +226,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w) case HTTP_POST: { // Set the handle for an http post - curlEasyRequest_w->setPost(mBodySize); + curlEasyRequest_w->setPost(mBodySize, mKeepAlive); // Set Accept-Encoding to allow response compression curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : ""); diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index 8f019310f..9cdb132bb 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -77,18 +77,13 @@ class LLURLRequest : public AICurlEasyRequestStateMachine { * @param action One of the ERequestAction enumerations. * @param url The url of the request. It should already be encoded. */ - LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression); + LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression); protected: // Call abort(), not delete. /*virtual*/ ~LLURLRequest() { } public: - /** - * @brief Turn on cookie handling for this request with CURLOPT_COOKIEFILE. - */ - void allowCookies(void); - /** * @ brief Turn off (or on) the CURLOPT_PROXY header. */ @@ -116,6 +111,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine { private: ERequestAction mAction; std::string mURL; + bool mKeepAlive; // Set to false only when explicitely requested. bool mIsAuth; // Set for authentication messages (login, buy land, buy currency). bool mNoCompression; // Set to disable using gzip. Injector* mBody; // Non-zero iff the action is HTTP_POST and HTTP_PUT. diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 7d4b34ead..b3b5145c5 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1027,7 +1027,8 @@ void LLModel::setVolumeFaceData( if (tc.get()) { - LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32)); + U32 tex_size = (num_verts*2*sizeof(F32)+0xF)&~0xF; + LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), tex_size); } else { diff --git a/indra/llqtwebkit/llstyle.cpp b/indra/llqtwebkit/llstyle.cpp index ecd2b3eb8..8822d481a 100644 --- a/indra/llqtwebkit/llstyle.cpp +++ b/indra/llqtwebkit/llstyle.cpp @@ -71,7 +71,7 @@ void LLStyle::drawControl(ControlElement element, const QStyleOption *option, QP QPlastiqueStyle::drawControl(element, &localOption, painter, widget); return; } - + default: break; } diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index eba807ece..8ea13d362 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -935,7 +935,7 @@ void LLGLManager::initExtensions() mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts); mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts); - mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE; + mHasTransformFeedback = mGLVersion >= 4.f || ExtensionExists("GL_EXT_transform_feedback", gGLHExts.mSysExts); #if !LL_DARWIN mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); #endif diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 03eddae8d..bd5d4a58e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1329,6 +1329,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ llassert(mCurrentDiscardLevel >= 0); discard_level = mCurrentDiscardLevel; } + discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); if (mTexName != 0 && discard_level == mCurrentDiscardLevel) { @@ -1586,7 +1587,18 @@ void LLImageGL::destroyGLTexture() } } - +//force to invalidate the gl texture, most likely a sculpty texture +void LLImageGL::forceToInvalidateGLTexture() +{ + if (mTexName != 0) + { + destroyGLTexture(); + } + else + { + mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. + } +} //---------------------------------------------------------------------------- diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index ef9a2ec09..4ec1905cc 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -119,6 +119,7 @@ public: // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok); void destroyGLTexture(); + void forceToInvalidateGLTexture(); void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); void setComponents(S8 ncomponents) { mComponents = ncomponents; } diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index c1415e3f6..0ab80bf68 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -49,12 +49,63 @@ extern LLGLSLShader gPostNightVisionProgram; extern LLGLSLShader gPostGaussianBlurProgram; extern LLGLSLShader gPostPosterizeProgram; extern LLGLSLShader gPostMotionBlurProgram; +extern LLGLSLShader gPostVignetteProgram; static const unsigned int NOISE_SIZE = 512; static const char * const XML_FILENAME = "postprocesseffects.xml"; -template<> LLSD LLPostProcessShader::LLShaderSetting::getDefaultValue() +class LLPostProcessShader : public IPostProcessShader, public LLRefCount +{ +public: + LLPostProcessShader(const std::string& enable_name, LLGLSLShader& shader, bool enabled = false) : + mShader(shader), mEnabled(enable_name,enabled) + { + addSetting(mEnabled); + } + /*virtual*/ bool isEnabled() const {return mShader.mProgramObject && mEnabled;} + /*virtual*/ void bindShader() {mShader.bind();} + /*virtual*/ void unbindShader() {mShader.unbind();} + /*virtual*/ LLGLSLShader& getShader() {return mShader;} + + /*virtual*/ LLSD getDefaults(); //See IPostProcessShader::getDefaults + /*virtual*/ void loadSettings(const LLSD& settings); //See IPostProcessShader::loadSettings + /*virtual*/ void addSetting(IShaderSettingBase& setting) { mSettings.push_back(&setting); } +protected: + template + struct LLShaderSetting : public IShaderSettingBase + { + LLShaderSetting(const std::string& name, T def) : + mValue(def), mDefault(def), mSettingName(name) {} + operator T() const { return mValue; } + T get() const { return mValue; } + /*virtual*/ const std::string& getName() const { return mSettingName; } //See LLShaderSettingBase::getName + /*virtual*/ LLSD getDefaultValue() const { return mDefault; } //See LLShaderSettingBase::getDefaultValue + /*virtual*/ void setValue(const LLSD& value) { mValue = value; } //See LLShaderSettingBase::setValue + private: + const std::string mSettingName; //LLSD key names as found in postprocesseffects.xml. eg 'contrast_base' + T mValue; //The member variable mentioned above. + T mDefault; //Set via ctor. Value is inserted into the defaults LLSD list if absent from postprocesseffects.xml + }; +private: + std::vector mSettings; //Contains a list of all the 'settings' this shader uses. Manually add via push_back in ctor. + LLGLSLShader& mShader; + LLShaderSetting mEnabled; +}; + +//helpers +class LLPostProcessSinglePassColorShader : public LLPostProcessShader +{ +public: + LLPostProcessSinglePassColorShader(const std::string& enable_name, LLGLSLShader& shader, bool enabled = false) : + LLPostProcessShader(enable_name, shader, enabled) {} + /*virtual*/ S32 getColorChannel() const {return 0;} + /*virtual*/ S32 getDepthChannel() const {return -1;} + /*virtual*/ bool draw(U32 pass) {return pass == 1;} + /*virtual*/ void postDraw() {} +}; + +template<> LLSD LLPostProcessShader::LLShaderSetting::getDefaultValue() const { return mDefault.getValue(); } @@ -66,223 +117,175 @@ template<> void LLPostProcessShader::LLShaderSetting::setValue(const LLSD LLPostProcessShader::getDefaults() { LLSD defaults; - for(std::vector::iterator it=mSettings.begin();it!=mSettings.end();++it) + for(std::vector::iterator it=mSettings.begin();it!=mSettings.end();++it) { - defaults[(*it)->mSettingName]=(*it)->getDefaultValue(); + defaults[(*it)->getName()]=(*it)->getDefaultValue(); } return defaults; } void LLPostProcessShader::loadSettings(const LLSD& settings) { - for(std::vector::iterator it=mSettings.begin();it!=mSettings.end();++it) + for(std::vector::iterator it=mSettings.begin();it!=mSettings.end();++it) { - LLSD value = settings[(*it)->mSettingName]; + LLSD value = settings[(*it)->getName()]; (*it)->setValue(value); } } -class LLColorFilterShader : public LLPostProcessShader +class LLColorFilterShader : public LLPostProcessSinglePassColorShader { private: - LLShaderSetting mEnabled; LLShaderSetting mGamma, mBrightness, mContrast, mSaturation; LLShaderSetting mContrastBase; public: - LLColorFilterShader() : - mEnabled("enable_color_filter",false), + LLColorFilterShader() : + LLPostProcessSinglePassColorShader("enable_color_filter",gPostColorFilterProgram), mGamma("gamma",1.f), mBrightness("brightness",1.f), mContrast("contrast",1.f), mSaturation("saturation",1.f), mContrastBase("contrast_base",LLVector4(1.f,1.f,1.f,0.5f)) { - mSettings.push_back(&mEnabled); - mSettings.push_back(&mGamma); - mSettings.push_back(&mBrightness); - mSettings.push_back(&mContrast); - mSettings.push_back(&mSaturation); - mSettings.push_back(&mContrastBase); + addSetting(mGamma); + addSetting(mBrightness); + addSetting(mContrast); + addSetting(mSaturation); + addSetting(mContrastBase); } - bool isEnabled() { return mEnabled && gPostColorFilterProgram.mProgramObject; } - S32 getColorChannel() { return 0; } - S32 getDepthChannel() { return -1; } - - QuadType bind() + /*virtual*/ QuadType preDraw() { - if(!isEnabled()) - return QUAD_NONE; + getShader().uniform1f("gamma", mGamma); + getShader().uniform1f("brightness", mBrightness); + getShader().uniform1f("contrast", mContrast); + float baseI = (mContrastBase.get()[VX] + mContrastBase.get()[VY] + mContrastBase.get()[VZ]) / 3.0f; + baseI = mContrastBase.get()[VW] / llmax(baseI,0.001f); + float baseR = mContrastBase.get()[VX] * baseI; + float baseG = mContrastBase.get()[VY] * baseI; + float baseB = mContrastBase.get()[VZ] * baseI; + getShader().uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV); + getShader().uniform1f("saturation", mSaturation); - /// CALCULATING LUMINANCE (Using NTSC lum weights) - /// http://en.wikipedia.org/wiki/Luma_%28video%29 - static const float LUMINANCE_R = 0.299f; - static const float LUMINANCE_G = 0.587f; - static const float LUMINANCE_B = 0.114f; - - gPostColorFilterProgram.bind(); - - gPostColorFilterProgram.uniform1f("gamma", mGamma); - gPostColorFilterProgram.uniform1f("brightness", mBrightness); - gPostColorFilterProgram.uniform1f("contrast", mContrast); - float baseI = (mContrastBase.mValue[VX] + mContrastBase.mValue[VY] + mContrastBase.mValue[VZ]) / 3.0f; - baseI = mContrastBase.mValue[VW] / ((baseI < 0.001f) ? 0.001f : baseI); - float baseR = mContrastBase.mValue[VX] * baseI; - float baseG = mContrastBase.mValue[VY] * baseI; - float baseB = mContrastBase.mValue[VZ] * baseI; - gPostColorFilterProgram.uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV); - gPostColorFilterProgram.uniform1f("saturation", mSaturation); - gPostColorFilterProgram.uniform3fv("lumWeights", 1, LLVector3(LUMINANCE_R, LUMINANCE_G, LUMINANCE_B).mV); return QUAD_NORMAL; } - bool draw(U32 pass) {return pass == 1;} - void unbind() - { - gPostColorFilterProgram.unbind(); - } }; -class LLNightVisionShader : public LLPostProcessShader +class LLNightVisionShader : public LLPostProcessSinglePassColorShader { private: - LLShaderSetting mEnabled; LLShaderSetting mBrightnessMult, mNoiseStrength; public: LLNightVisionShader() : - mEnabled("enable_night_vision",false), + LLPostProcessSinglePassColorShader("enable_night_vision",gPostNightVisionProgram), mBrightnessMult("brightness_multiplier",3.f), mNoiseStrength("noise_strength",.4f) { - mSettings.push_back(&mEnabled); - mSettings.push_back(&mBrightnessMult); - mSettings.push_back(&mNoiseStrength); + addSetting(mBrightnessMult); + addSetting(mNoiseStrength); } - bool isEnabled() { return mEnabled && gPostNightVisionProgram.mProgramObject; } - S32 getColorChannel() { return 0; } - S32 getDepthChannel() { return -1; } - QuadType bind() + /*virtual*/ QuadType preDraw() { - if(!isEnabled()) - return QUAD_NONE; - - gPostNightVisionProgram.bind(); - LLPostProcess::getInstance()->bindNoise(1); - - gPostNightVisionProgram.uniform1f("brightMult", mBrightnessMult); - gPostNightVisionProgram.uniform1f("noiseStrength", mNoiseStrength); - + + getShader().uniform1f("brightMult", mBrightnessMult); + getShader().uniform1f("noiseStrength", mNoiseStrength); + return QUAD_NOISE; - } - bool draw(U32 pass) {return pass == 1;} - void unbind() +}; + +class LLPosterizeShader : public LLPostProcessSinglePassColorShader +{ +private: + LLShaderSetting mNumLayers; +public: + LLPosterizeShader() : LLPostProcessSinglePassColorShader("enable_posterize",gPostPosterizeProgram), + mNumLayers("posterize_layers",2) { - gPostNightVisionProgram.unbind(); + addSetting(mNumLayers); + } + /*virtual*/ QuadType preDraw() + { + getShader().uniform1i("layerCount", mNumLayers); + return QUAD_NORMAL; + } +}; + +class LLVignetteShader : public LLPostProcessSinglePassColorShader +{ +private: + LLShaderSetting mStrength, mRadius, mDarkness, mDesaturation, mChromaticAberration; +public: + LLVignetteShader() : LLPostProcessSinglePassColorShader("enable_vignette",gPostVignetteProgram), + mStrength("vignette_strength",.85f), + mRadius("vignette_radius",.7f), + mDarkness("vignette_darkness",1.f), + mDesaturation("vignette_desaturation",1.5f), + mChromaticAberration("vignette_chromatic_aberration",.05f) + { + addSetting(mStrength); + addSetting(mRadius); + addSetting(mDarkness); + addSetting(mDesaturation); + addSetting(mChromaticAberration); + } + /*virtual*/ QuadType preDraw() + { + LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions(); + getShader().uniform1f("vignette_strength", mStrength); + getShader().uniform1f("vignette_radius", mRadius); + getShader().uniform1f("vignette_darkness", mDarkness); + getShader().uniform1f("vignette_desaturation", mDesaturation); + getShader().uniform1f("vignette_chromatic_aberration", mChromaticAberration); + getShader().uniform2fv("screen_res", 1, screen_rect.mV); + return QUAD_NORMAL; } }; class LLGaussBlurShader : public LLPostProcessShader { private: - LLShaderSetting mEnabled; LLShaderSetting mNumPasses; GLint mPassLoc; public: - LLGaussBlurShader() : - mEnabled("enable_gauss_blur",false), + LLGaussBlurShader() : LLPostProcessShader("enable_gauss_blur",gPostGaussianBlurProgram), mNumPasses("gauss_blur_passes",2), mPassLoc(0) { - mSettings.push_back(&mEnabled); - mSettings.push_back(&mNumPasses); + addSetting(mNumPasses); } - bool isEnabled() { return mEnabled && mNumPasses && gPostGaussianBlurProgram.mProgramObject; } - S32 getColorChannel() { return 0; } - S32 getDepthChannel() { return -1; } - QuadType bind() + /*virtual*/ bool isEnabled() const { return LLPostProcessShader::isEnabled() && mNumPasses.get(); } + /*virtual*/ S32 getColorChannel() const { return 0; } + /*virtual*/ S32 getDepthChannel() const { return -1; } + /*virtual*/ QuadType preDraw() { - if(!isEnabled()) - return QUAD_NONE; - - gPostGaussianBlurProgram.bind(); - - mPassLoc = gPostGaussianBlurProgram.getUniformLocation("horizontalPass"); - + mPassLoc = getShader().getUniformLocation("horizontalPass"); return QUAD_NORMAL; } - bool draw(U32 pass) + /*virtual*/ bool draw(U32 pass) { if((S32)pass > mNumPasses*2) return false; glUniform1iARB(mPassLoc, (pass-1) % 2); return true; } - void unbind() - { - gPostGaussianBlurProgram.unbind(); - } -}; - -class LLPosterizeShader : public LLPostProcessShader -{ -private: - LLShaderSetting mEnabled; - LLShaderSetting mNumLayers; -public: - LLPosterizeShader() : - mEnabled("enable_posterize",false), - mNumLayers("posterize_layers",2) - { - mSettings.push_back(&mEnabled); - mSettings.push_back(&mNumLayers); - } - bool isEnabled() { return mEnabled && gPostPosterizeProgram.mProgramObject; } - S32 getColorChannel() { return 0; } - S32 getDepthChannel() { return -1; } - QuadType bind() - { - if(!isEnabled()) - return QUAD_NONE; - - gPostPosterizeProgram.bind(); - - gPostPosterizeProgram.uniform1i("layerCount", mNumLayers); - - return QUAD_NORMAL; - } - bool draw(U32 pass) - { - return pass == 1; - } - void unbind() - { - gPostPosterizeProgram.unbind(); - } + /*virtual*/ void postDraw() {} }; class LLMotionShader : public LLPostProcessShader { private: - LLShaderSetting mEnabled; LLShaderSetting mStrength; public: - LLMotionShader() : - mEnabled("enable_motionblur",false), - mStrength("blur_strength",false) + LLMotionShader() : LLPostProcessShader("enable_motionblur",gPostMotionBlurProgram), + mStrength("blur_strength",1) { - mSettings.push_back(&mEnabled); - mSettings.push_back(&mStrength); + addSetting(mStrength); } - bool isEnabled() { return mEnabled && gPostMotionBlurProgram.mProgramObject; } - S32 getColorChannel() { return 0; } - S32 getDepthChannel() { return 1; } - QuadType bind() + /*virtual*/ S32 getColorChannel() const { return 0; } + /*virtual*/ S32 getDepthChannel() const { return 1; } + /*virtual*/ QuadType preDraw() { - if(!isEnabled()) - { - return QUAD_NONE; - } - glh::matrix4f inv_proj(gGLModelView); inv_proj.mult_left(gGLProjection); inv_proj = inv_proj.inverse(); @@ -291,22 +294,18 @@ public: LLVector2 screen_rect = LLPostProcess::getInstance()->getDimensions(); - gPostMotionBlurProgram.bind(); - gPostMotionBlurProgram.uniformMatrix4fv("prev_proj", 1, GL_FALSE, prev_proj.m); - gPostMotionBlurProgram.uniformMatrix4fv("inv_proj", 1, GL_FALSE, inv_proj.m); - gPostMotionBlurProgram.uniform2fv("screen_res", 1, screen_rect.mV); - gPostMotionBlurProgram.uniform1i("blur_strength", mStrength); + getShader().uniformMatrix4fv("prev_proj", 1, GL_FALSE, prev_proj.m); + getShader().uniformMatrix4fv("inv_proj", 1, GL_FALSE, inv_proj.m); + getShader().uniform2fv("screen_res", 1, screen_rect.mV); + getShader().uniform1i("blur_strength", mStrength); return QUAD_NORMAL; } - bool draw(U32 pass) + /*virtual*/ bool draw(U32 pass) { return pass == 1; } - void unbind() - { - gPostMotionBlurProgram.unbind(); - } + /*virtual*/ void postDraw() {} }; LLPostProcess::LLPostProcess(void) : @@ -320,12 +319,12 @@ LLPostProcess::LLPostProcess(void) : mAllEffectInfo(LLSD::emptyMap()) { mShaders.push_back(new LLMotionShader()); + mShaders.push_back(new LLVignetteShader()); mShaders.push_back(new LLColorFilterShader()); mShaders.push_back(new LLNightVisionShader()); mShaders.push_back(new LLGaussBlurShader()); mShaders.push_back(new LLPosterizeShader()); - /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.*/ std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); LL_DEBUGS2("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL; @@ -547,20 +546,19 @@ void LLPostProcess::doEffects(void) void LLPostProcess::applyShaders(void) { - QuadType quad; bool primary_rendertarget = 1; for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) { - if((quad = (*it)->bind()) != QUAD_NONE) + if((*it)->isEnabled()) { S32 color_channel = (*it)->getColorChannel(); S32 depth_channel = (*it)->getDepthChannel(); - if(depth_channel >= 0) gGL.getTexUnit(depth_channel)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mDepthTexture); - U32 pass = 1; + (*it)->bindShader(); + QuadType quad = (*it)->preDraw(); while((*it)->draw(pass++)) { mRenderTarget[!primary_rendertarget].bindTarget(); @@ -573,7 +571,8 @@ void LLPostProcess::applyShaders(void) if(mRenderTarget[0].getFBO()) primary_rendertarget = !primary_rendertarget; } - (*it)->unbind(); + (*it)->postDraw(); + (*it)->unbindShader(); } } //Only need to copy to framebuffer if FBOs are supported, else we've already been drawing to the framebuffer to begin with. diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h index 9ecd9e293..6c3da675e 100644 --- a/indra/llrender/llpostprocess.h +++ b/indra/llrender/llpostprocess.h @@ -38,57 +38,48 @@ #include "llrendertarget.h" class LLSD; +class LLGLSLShader; typedef enum _QuadType { - QUAD_NONE, QUAD_NORMAL, QUAD_NOISE } QuadType; //LLPostProcessShader is an attempt to encapsulate the shaders a little better. -class LLPostProcessShader : public LLRefCount //Abstract. PostProcess shaders derive off of this common base. +class IPostProcessShader //Abstract. PostProcess shaders derive off of this common base. { protected: //LLShaderSetting is used to associate key names to member variables to avoid LLSD lookups when drawing. //It also facilitates automating the assigning of defaults to, as well as parsing from, the effects LLSD list. //This replaces the entire old PostProcessTweaks structure. More will be done in the future to move into a more //xml-driven configuration. - struct LLShaderSettingBase + struct IShaderSettingBase { - LLShaderSettingBase(const char* name) : mSettingName(name) {} - const char* mSettingName; //LLSD key names as found in postprocesseffects.xml. eg 'contrast_base' - virtual LLSD getDefaultValue() = 0; //Converts the member variable as an LLSD. Used to set defaults absent in postprocesseffects.xml + virtual ~IShaderSettingBase() {} //virtual dtor. + virtual const std::string& getName() const = 0; //Returns the name of this setting + virtual LLSD getDefaultValue() const = 0; //Converts the member variable as an LLSD. Used to set defaults absent in postprocesseffects.xml virtual void setValue(const LLSD& value) = 0; //Connects the LLSD element to the member variable. Used when loading effects (such as default) }; - template - struct LLShaderSetting : public LLShaderSettingBase - { - LLShaderSetting(const char* setting_name, T def) : LLShaderSettingBase(setting_name), mValue(def), mDefault(def) {} - T mValue; //The member variable mentioned above. - T mDefault; //Set via ctor. Value is inserted into the defaults LLSD list if absent from postprocesseffects.xml - LLSD getDefaultValue() { return mDefault; } //See LLShaderSettingBase::getDefaultValue - void setValue(const LLSD& value) { mValue = value; } //See LLShaderSettingBase::setValue - operator T() { return mValue; } //Typecast operator overload so this object can be handled as if it was whatever T represents. - }; - std::vector mSettings; //Contains a list of all the 'settings' this shader uses. Manually add via push_back in ctor. public: - virtual ~LLPostProcessShader() {}; - virtual bool isEnabled() = 0; //Returning false avoids bind/draw/unbind calls. If no shaders are enabled, framebuffer copying is skipped. - virtual S32 getColorChannel() = 0; //If color buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer. - virtual S32 getDepthChannel() = 0; //If depth buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer. - virtual QuadType bind() = 0; //Bind shader and textures, set up attribs. Returns the 'type' of quad to be drawn. + virtual ~IPostProcessShader() {} //virtual dtor. + virtual bool isEnabled() const = 0; //Returning false avoids bind/draw/unbind calls. If no shaders are enabled, framebuffer copying is skipped. + virtual S32 getColorChannel() const = 0; //If color buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer. + virtual S32 getDepthChannel() const = 0; //If depth buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer. + virtual void bindShader() = 0; + virtual void unbindShader() = 0; + virtual LLGLSLShader& getShader() = 0; + + virtual QuadType preDraw() = 0; //Bind shader and textures, set up attribs. Returns the 'type' of quad to be drawn. virtual bool draw(U32 pass) = 0; //returning false means finished. Used to update per-pass attributes and such. LLPostProcess will call //drawOrthoQuad when this returns true, increment pass, then call this again, and keep repeating this until false is returned. - virtual void unbind() = 0; //Unbind shader and textures. + virtual void postDraw() = 0; //Done drawing.. - LLSD getDefaults(); //Returns a full LLSD kvp list filled with default values. - void loadSettings(const LLSD& settings); //Parses the effects LLSD list and sets the member variables linked to them (via LLShaderSetting::setValue()) + virtual LLSD getDefaults() = 0; //Returns a full LLSD kvp list filled with default values. + virtual void loadSettings(const LLSD& settings) = 0; //Parses the effects LLSD list and sets the member variables linked to them (via LLShaderSetting::setValue()) + virtual void addSetting(IShaderSettingBase& setting) = 0; }; -//LLVector4 does not implicitly convert to and from LLSD, so template specilizations are necessary. -template<> LLSD LLPostProcessShader::LLShaderSetting::getDefaultValue(); -template<> void LLPostProcessShader::LLShaderSetting::setValue(const LLSD& value); - +class LLPostProcessShader; class LLPostProcess : public LLSingleton { private: diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 366f506a7..590fdc757 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -229,8 +229,6 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) stop_glerror(); if (mIndex < 0) return false; - gGL.flush(); - LLImageGL* gl_tex = NULL ; if (texture == NULL || !(gl_tex = texture->getGLTexture())) { @@ -258,6 +256,7 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) } if ((mCurrTexture != gl_tex->getTexName()) || forceBind) { + gGL.flush(); activate(); enable(gl_tex->getTarget()); mCurrTexture = gl_tex->getTexName(); @@ -1120,6 +1119,9 @@ void LLRender::refreshState(void) setAlphaRejectSettings(mCurrAlphaFunc, mCurrAlphaFuncVal); + //Singu note: Also reset glBlendFunc + blendFunc(mCurrBlendColorSFactor,mCurrBlendColorDFactor,mCurrBlendAlphaSFactor,mCurrBlendAlphaDFactor); + mDirty = false; } @@ -1510,20 +1512,26 @@ void LLRender::pushUIMatrix() { if (mUIOffset.empty()) { - mUIOffset.push_back(new LLVector4a(0.f)); + mUIOffset.push_back(static_cast(ll_aligned_malloc_16(sizeof(LLVector4a)))); + mUIOffset.back()->splat(0.f); } else { - mUIOffset.push_back(new LLVector4a(*mUIOffset.back())); + const LLVector4a* last_entry = mUIOffset.back(); + mUIOffset.push_back(static_cast(ll_aligned_malloc_16(sizeof(LLVector4a)))); + *mUIOffset.back() = *last_entry; } if (mUIScale.empty()) { - mUIScale.push_back(new LLVector4a(1.f)); + mUIScale.push_back(static_cast(ll_aligned_malloc_16(sizeof(LLVector4a)))); + mUIScale.back()->splat(1.f); } else { - mUIScale.push_back(new LLVector4a(*mUIScale.back())); + const LLVector4a* last_entry = mUIScale.back(); + mUIScale.push_back(static_cast(ll_aligned_malloc_16(sizeof(LLVector4a)))); + *mUIScale.back() = *last_entry; } } @@ -1533,9 +1541,9 @@ void LLRender::popUIMatrix() { llerrs << "UI offset stack blown." << llendl; } - delete mUIOffset.back(); + ll_aligned_free_16(mUIOffset.back()); mUIOffset.pop_back(); - delete mUIScale.back(); + ll_aligned_free_16(mUIScale.back()); mUIScale.pop_back(); } @@ -1580,7 +1588,7 @@ void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB if (mCurrColorMask[0] != writeColorR || mCurrColorMask[1] != writeColorG || mCurrColorMask[2] != writeColorB || - mCurrColorMask[3] != writeAlpha) + mCurrColorMask[3] != writeAlpha || mDirty) { mCurrColorMask[0] = writeColorR; mCurrColorMask[1] = writeColorG; @@ -1635,7 +1643,7 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) } if (mCurrAlphaFunc != func || - mCurrAlphaFuncVal != value) + mCurrAlphaFuncVal != value || mDirty) { mCurrAlphaFunc = func; mCurrAlphaFuncVal = value; @@ -1679,7 +1687,7 @@ void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor) llassert(sfactor < BF_UNDEF); llassert(dfactor < BF_UNDEF); if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor || - mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor) + mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor || mDirty) { mCurrBlendColorSFactor = sfactor; mCurrBlendAlphaSFactor = sfactor; @@ -1704,7 +1712,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, return; } if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor || - mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor) + mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor || mDirty) { mCurrBlendColorSFactor = color_sfactor; mCurrBlendAlphaSFactor = alpha_sfactor; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index d770e67c9..4509958a9 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -813,7 +813,6 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); } - check_framebuffer_status(); } stop_glerror(); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 234d2e141..65a7fda5e 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -25,6 +25,7 @@ */ #include "linden_common.h" +#include //First, because glh_linear #defines equivalent.. which boost uses internally #include "llshadermgr.h" @@ -53,6 +54,17 @@ LLShaderMgr * LLShaderMgr::sInstance = NULL; LLShaderMgr::LLShaderMgr() { + { + const std::string dumpdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"shader_dump")+gDirUtilp->getDirDelimiter(); + try + { + boost::filesystem::remove_all(dumpdir); + } + catch(const boost::filesystem::filesystem_error& e) + { + llinfos << "boost::filesystem::remove_all(\""+dumpdir+"\") failed: '" + e.code().message() + "'" << llendl; + } + } } @@ -660,6 +672,10 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } } + static const LLCachedControl SHPackDeferredNormals("SHPackDeferredNormals",false); + if(SHPackDeferredNormals) + text[count++] = strdup("#define PACK_NORMALS\n"); + //copy preprocessor definitions into buffer for (std::map::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter) { @@ -1116,7 +1132,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("ssao_max_radius"); mReservedUniforms.push_back("ssao_factor"); mReservedUniforms.push_back("ssao_factor_inv"); - mReservedUniforms.push_back("ssao_effect_mat"); + mReservedUniforms.push_back("ssao_effect"); mReservedUniforms.push_back("screen_res"); mReservedUniforms.push_back("near_clip"); mReservedUniforms.push_back("shadow_offset"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index fc9242f7c..7e30e75f0 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -120,7 +120,7 @@ public: DEFERRED_SSAO_MAX_RADIUS, DEFERRED_SSAO_FACTOR, DEFERRED_SSAO_FACTOR_INV, - DEFERRED_SSAO_EFFECT_MAT, + DEFERRED_SSAO_EFFECT, DEFERRED_SCREEN_RES, DEFERRED_NEAR_CLIP, DEFERRED_SHADOW_OFFSET, diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index bc4c201d9..d10a9c6bb 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -2083,6 +2083,16 @@ void LLVertexBuffer::flush() } } +// bind for transform feedback (quick 'n dirty) +void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count) +{ +#ifdef GL_TRANSFORM_FEEDBACK_BUFFER + U32 offset = mOffsets[type] + sTypeSize[type]*index; + U32 size= (sTypeSize[type]*count); + glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size); +#endif +} + // Set for rendering void LLVertexBuffer::setBuffer(U32 data_mask) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 469acfcef..3762d956b 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -202,16 +202,18 @@ protected: void destroyGLIndices(); void updateNumVerts(S32 nverts); void updateNumIndices(S32 nindices); - bool useVBOs() const; void unmapBuffer(); public: + LLVertexBuffer(U32 typemask, S32 usage); // map for data access volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range); + void bindForFeedback(U32 channel, U32 type, U32 index, U32 count); + // set for rendering virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 void flush(); //flush pending data to GL memory @@ -240,6 +242,7 @@ public: bool getClothWeightStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool useVBOs() const; bool isEmpty() const { return mEmpty; } bool isLocked() const { return mVertexLocked || mIndexLocked; } S32 getNumVerts() const { return mNumVerts; } diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index b1b8f42e4..7401d97f8 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -615,7 +615,7 @@ void LLComboBox::showList() S32 min_width = getRect().getWidth(); S32 max_width = llmax(min_width, MAX_COMBO_WIDTH); // make sure we have up to date content width metrics - mList->calcColumnWidths(); + mList->updateColumnWidths(); S32 list_width = llclamp(mList->getMaxContentWidth(), min_width, max_width); if (mListPosition == BELOW) @@ -707,7 +707,7 @@ void LLComboBox::hideList() mButton->setToggleState(FALSE); mList->setVisible(FALSE); - mList->highlightNthItem(-1); + mList->mouseOverHighlightNthItem(-1); setUseBoundingRect(FALSE); if( gFocusMgr.getTopCtrl() == this ) @@ -731,7 +731,7 @@ void LLComboBox::onButtonDown(void *userdata) if (last_selected_item) { // highlight the original selection before potentially selecting a new item - self->mList->highlightNthItem(self->mList->getItemIndex(last_selected_item)); + self->mList->mouseOverHighlightNthItem(self->mList->getItemIndex(last_selected_item)); } if( self->mPrearrangeCallback ) @@ -839,7 +839,7 @@ BOOL LLComboBox::handleKeyHere(KEY key, MASK mask) if (last_selected_item) { // highlight the original selection before potentially selecting a new item - mList->highlightNthItem(mList->getItemIndex(last_selected_item)); + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); } result = mList->handleKeyHere(key, mask); @@ -873,7 +873,7 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char) if (last_selected_item) { // highlight the original selection before potentially selecting a new item - mList->highlightNthItem(mList->getItemIndex(last_selected_item)); + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); } result = mList->handleUnicodeCharHere(uni_char); if (mList->getLastSelectedItem() != last_selected_item) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 114cabc0c..25370f739 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -148,7 +148,6 @@ LLFloater::LLFloater() : mResizeHandle[i] = NULL; } mDragHandle = NULL; - mHandle.bind(this); mNotificationContext = new LLFloaterNotificationContext(getHandle()); } @@ -222,7 +221,6 @@ void LLFloater::initFloater(const std::string& title, BOOL resizable, S32 min_width, S32 min_height, BOOL drag_on_left, BOOL minimizable, BOOL close_btn) { - mHandle.bind(this); mNotificationContext = new LLFloaterNotificationContext(getHandle()); // Init function can be called more than once, so clear out old data. @@ -422,7 +420,7 @@ void LLFloater::initFloater(const std::string& title, setVisible(FALSE); // add self to handle->floater map - sFloaterMap[mHandle] = this; + sFloaterMap[getHandle()] = this; if (!getParent()) { @@ -483,7 +481,7 @@ LLFloater::~LLFloater() // correct, non-minimized positions. setMinimized( FALSE ); - sFloaterMap.erase(mHandle); + sFloaterMap.erase(getHandle()); delete mDragHandle; for (S32 i = 0; i < 4; i++) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index e710fa6dc..1cfb4635a 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -227,7 +227,7 @@ public: void clearSnapTarget() { mSnappedTo.markDead(); } LLHandle getSnapTarget() const { return mSnappedTo; } - LLHandle getHandle() const { return mHandle; } + LLHandle getHandle() const { return getDerivedHandle(); } // Return a closeable floater, if any, given the current focus. static LLFloater* getClosableFloaterFromFocus(); @@ -331,7 +331,6 @@ private: S32 mPreviousMinimizedLeft; LLFloaterNotificationContext* mNotificationContext; - LLRootHandle mHandle; }; ///////////////////////////////////////////////////////////// diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h index 8c000eee4..6af5e198d 100644 --- a/indra/llui/llhandle.h +++ b/indra/llui/llhandle.h @@ -28,38 +28,67 @@ #define LLHANDLE_H #include "llpointer.h" +#include +#include -template +/** + * Helper object for LLHandle. Don't instantiate these directly, used + * exclusively by LLHandle. + */ class LLTombStone : public LLRefCount { public: - LLTombStone(T* target = NULL) : mTarget(target) {} + LLTombStone(void* target = NULL) : mTarget(target) {} - void setTarget(T* target) { mTarget = target; } - T* getTarget() const { return mTarget; } + void setTarget(void* target) { mTarget = target; } + void* getTarget() const { return mTarget; } private: - T* mTarget; + mutable void* mTarget; }; -// LLHandles are used to refer to objects whose lifetime you do not control or influence. -// Calling get() on a handle will return a pointer to the referenced object or NULL, -// if the object no longer exists. Note that during the lifetime of the returned pointer, -// you are assuming that the object will not be deleted by any action you perform, -// or any other thread, as normal when using pointers, so avoid using that pointer outside of -// the local code block. -// -// https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669 - +/** + * LLHandles are used to refer to objects whose lifetime you do not control or influence. + * Calling get() on a handle will return a pointer to the referenced object or NULL, + * if the object no longer exists. Note that during the lifetime of the returned pointer, + * you are assuming that the object will not be deleted by any action you perform, + * or any other thread, as normal when using pointers, so avoid using that pointer outside of + * the local code block. + * + * https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669 + * + * The implementation is like some "weak pointer" implementations. When we + * can't control the lifespan of the referenced object of interest, we can + * still instantiate a proxy object whose lifespan we DO control, and store in + * the proxy object a dumb pointer to the actual target. Then we just have to + * ensure that on destruction of the target object, the proxy's dumb pointer + * is set NULL. + * + * LLTombStone is our proxy object. LLHandle contains an LLPointer to the + * LLTombStone, so every copy of an LLHandle increments the LLTombStone's ref + * count as usual. + * + * One copy of the LLHandle, specifically the LLRootHandle, must be stored in + * the referenced object. Destroying the LLRootHandle is what NULLs the + * proxy's target pointer. + * + * Minor optimization: we want LLHandle's mTombStone to always be a valid + * LLPointer, saving some conditionals in dereferencing. That's the + * getDefaultTombStone() mechanism. The default LLTombStone object's target + * pointer is always NULL, so it's semantically identical to allowing + * mTombStone to be invalid. + */ template class LLHandle { + template friend class LLHandle; + template friend class LLHandleProvider; public: LLHandle() : mTombStone(getDefaultTombStone()) {} - const LLHandle& operator =(const LLHandle& other) - { - mTombStone = other.mTombStone; - return *this; - } + + template + LLHandle(const LLHandle& other, typename boost::enable_if< typename boost::is_convertible >::type* dummy = 0) + : mTombStone(other.mTombStone) + {} bool isDead() const { @@ -73,7 +102,7 @@ public: T* get() const { - return mTombStone->getTarget(); + return reinterpret_cast(mTombStone->getTarget()); } friend bool operator== (const LLHandle& lhs, const LLHandle& rhs) @@ -94,37 +123,49 @@ public: } protected: - LLPointer > mTombStone; + LLPointer mTombStone; private: - static LLPointer >& getDefaultTombStone() + typedef T* pointer_t; + static LLPointer& getDefaultTombStone() { - static LLPointer > sDefaultTombStone = new LLTombStone; + static LLPointer sDefaultTombStone = new LLTombStone; return sDefaultTombStone; } }; +/** + * LLRootHandle isa LLHandle which must be stored in the referenced object. + * You can either store it directly and explicitly bind(this), or derive from + * LLHandleProvider (q.v.) which automates that for you. The essential point + * is that destroying the LLRootHandle (as a consequence of destroying the + * referenced object) calls unbind(), setting the LLTombStone's target pointer + * NULL. + */ template class LLRootHandle : public LLHandle { public: + typedef LLRootHandle self_t; + typedef LLHandle base_t; + LLRootHandle(T* object) { bind(object); } LLRootHandle() {}; ~LLRootHandle() { unbind(); } - // this is redundant, since a LLRootHandle *is* an LLHandle - LLHandle getHandle() { return LLHandle(*this); } + // this is redundant, since an LLRootHandle *is* an LLHandle + //LLHandle getHandle() { return LLHandle(*this); } void bind(T* object) { // unbind existing tombstone if (LLHandle::mTombStone.notNull()) { - if (LLHandle::mTombStone->getTarget() == object) return; + if (LLHandle::mTombStone->getTarget() == (void*)object) return; LLHandle::mTombStone->setTarget(NULL); } // tombstone reference counted, so no paired delete - LLHandle::mTombStone = new LLTombStone(object); + LLHandle::mTombStone = new LLTombStone((void*)object); } void unbind() @@ -137,11 +178,22 @@ private: LLRootHandle(const LLRootHandle& other) {}; }; -// Use this as a mixin for simple classes that need handles and when you don't -// want handles at multiple points of the inheritance hierarchy +/** + * Use this as a mixin for simple classes that need handles and when you don't + * want handles at multiple points of the inheritance hierarchy + */ template class LLHandleProvider { +public: + LLHandle getHandle() const + { + // perform lazy binding to avoid small tombstone allocations for handle + // providers whose handles are never referenced + mHandle.bind(static_cast(const_cast* >(this))); + return mHandle; + } + protected: typedef LLHandle handle_type_t; LLHandleProvider() @@ -149,16 +201,17 @@ protected: // provided here to enforce T deriving from LLHandleProvider } - LLHandle getHandle() - { - // perform lazy binding to avoid small tombstone allocations for handle - // providers whose handles are never referenced - mHandle.bind(static_cast(this)); - return mHandle; + template + LLHandle getDerivedHandle(typename boost::enable_if< typename boost::is_convertible >::type* dummy = 0) const + { + LLHandle downcast_handle; + downcast_handle.mTombStone = getHandle().mTombStone; + return downcast_handle; } + private: - LLRootHandle mHandle; + mutable LLRootHandle mHandle; }; #endif diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 136dcf524..588a36a0f 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -80,7 +80,6 @@ void LLPanel::init() mDefaultBtn = NULL; setIsChrome(FALSE); //is this a decorator to a live window or a form? - mPanelHandle.bind(this); setTabStop(FALSE); mVisibleSignal = NULL; } @@ -766,19 +765,6 @@ void LLPanel::childSetCommitCallback(const std::string& id, void (*cb)(LLUICtrl* } } -void LLPanel::childSetDoubleClickCallback(const std::string& id, void (*cb)(void*), void *userdata ) -{ - LLUICtrl* child = getChild(id, true); - if (child) - { - child->setDoubleClickCallback(cb); - if (userdata) - { - child->setCallbackUserData(userdata); - } - } -} - void LLPanel::childSetValidate(const std::string& id, BOOL (*cb)(LLUICtrl*, void*)) { LLUICtrl* child = getChild(id, true); @@ -963,7 +949,7 @@ void LLPanel::childSetWrappedText(const std::string& id, const std::string& text } } -void LLPanel::childSetAction(const std::string& id, void(*function)(void*), void* value) +void LLPanel::childSetAction(const std::string& id, boost::function function, void* value) { LLButton* button = getChild(id); if (button) @@ -972,6 +958,15 @@ void LLPanel::childSetAction(const std::string& id, void(*function)(void*), void } } +void LLPanel::childSetAction(const std::string& id, const commit_signal_t::slot_type& function) +{ + LLButton* button = getChild(id); + if (button) + { + button->setClickedCallback(function); + } +} + void LLPanel::childSetActionTextbox(const std::string& id, void(*function)(void*), void* value) { LLTextBox* textbox = getChild(id); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index ad721cbf5..330378da0 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -57,7 +57,7 @@ const BOOL BORDER_NO = FALSE; * With or without border, * Can contain LLUICtrls. */ -class LLPanel : public LLUICtrl, public boost::signals2::trackable +class LLPanel : public LLUICtrl { public: @@ -136,7 +136,7 @@ public: void setCtrlsEnabled(BOOL b); - LLHandle getHandle() const { return mPanelHandle; } + LLHandle getHandle() const { return getDerivedHandle(); } const LLCallbackMap::map_t& getFactoryMap() const { return mFactoryMap; } @@ -170,7 +170,6 @@ public: BOOL childHasFocus(const std::string& id); void childSetCommitCallback(const std::string& id, void (*cb)(LLUICtrl*, void*), void* userdata = NULL ); - void childSetDoubleClickCallback(const std::string& id, void (*cb)(void*), void* userdata = NULL ); void childSetValidate(const std::string& id, BOOL (*cb)(LLUICtrl*, void*) ); void childSetUserData(const std::string& id, void* userdata); @@ -211,7 +210,8 @@ public: void childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) ); // LLButton - void childSetAction(const std::string& id, void(*function)(void*), void* value); + void childSetAction(const std::string& id, boost::function function, void* value); + void childSetAction(const std::string& id, const commit_signal_t::slot_type& function); void childSetActionTextbox(const std::string& id, void(*function)(void*), void* value = NULL); void childSetControlName(const std::string& id, const std::string& control_name); @@ -246,7 +246,6 @@ private: LLViewBorder* mBorder; LLButton* mDefaultBtn; std::string mLabel; - LLRootHandle mPanelHandle; typedef std::map ui_string_map_t; ui_string_map_t mUIStrings; diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index a0a9b36b9..bd99e6c73 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -54,6 +54,7 @@ LLResizeBar::LLResizeBar( const std::string& name, LLView* resizing_view, const mAllowDoubleClickSnapping(TRUE), mResizingView(resizing_view) { + setFollowsNone(); // set up some generically good follow code. switch( side ) { @@ -87,6 +88,8 @@ LLResizeBar::LLResizeBar( const std::string& name, LLView* resizing_view, const BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask) { + if (!canResize()) return FALSE; + // Route future Mouse messages here preemptively. (Release on mouse up.) // No handler needed for focus lost since this clas has no state that depends on it. gFocusMgr.setMouseCapture( this ); @@ -240,7 +243,7 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) handled = TRUE; } - if( handled ) + if( handled && canResize() ) { switch( mSide ) { diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index b9fc40593..14bdd8d16 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -52,6 +52,7 @@ public: void setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; } void setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; } void setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; } + bool canResize() { return getEnabled() && mMaxSize > mMinSize; } private: S32 mDragLastScreenX; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index ea168a35c..f676eb7fe 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -66,8 +66,9 @@ static LLRegisterWidget r("scroll_list"); // local structures & classes. struct SortScrollListItem { - SortScrollListItem(const std::vector >& sort_orders) + SortScrollListItem(const std::vector >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal) : mSortOrders(sort_orders) + , mSortSignal(sort_signal) {} bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2) @@ -80,12 +81,20 @@ struct SortScrollListItem S32 col_idx = it->first; BOOL sort_ascending = it->second; + S32 order = sort_ascending ? 1 : -1; // ascending or descending sort for this column? + const LLScrollListCell *cell1 = i1->getColumn(col_idx); const LLScrollListCell *cell2 = i2->getColumn(col_idx); - S32 order = sort_ascending ? 1 : -1; // ascending or descending sort for this column? if (cell1 && cell2) { - sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString()); + if(mSortSignal) + { + sort_result = order * (*mSortSignal)(col_idx,i1, i2); + } + else + { + sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString()); + } if (sort_result != 0) { break; // we have a sort order! @@ -95,8 +104,10 @@ struct SortScrollListItem return sort_result < 0; } + typedef std::vector > sort_order_t; + const LLScrollListCtrl::sort_signal_t* mSortSignal; const sort_order_t& mSortOrders; }; @@ -109,7 +120,6 @@ LLScrollListIcon::LLScrollListIcon(LLUIImagePtr icon, S32 width) mIcon(icon), // mCallback(NULL), - mUserData(NULL), // mColor(LLColor4::white) { @@ -119,7 +129,6 @@ LLScrollListIcon::LLScrollListIcon(const LLSD& value, S32 width) : LLScrollListCell(width), // mCallback(NULL), - mUserData(NULL), // mColor(LLColor4::white) { @@ -131,6 +140,14 @@ LLScrollListIcon::~LLScrollListIcon() { } +/*virtual*/ +S32 LLScrollListIcon::getHeight() const +{ return mIcon ? mIcon->getHeight() : 0; } + +/*virtual*/ +const LLSD LLScrollListIcon::getValue() const +{ return mIcon.isNull() ? LLStringUtil::null : mIcon->getName(); } + void LLScrollListIcon::setValue(const LLSD& value) { if (value.isUUID()) @@ -174,15 +191,14 @@ S32 LLScrollListIcon::getWidth() const } // -void LLScrollListIcon::setClickCallback(BOOL (*callback)(void*), void* user_data) +void LLScrollListIcon::setClickCallback(boost::function cb) { - mCallback = callback; - mUserData = user_data; + mCallback = cb; } BOOL LLScrollListIcon::handleClick() { - if(mCallback) return mCallback(mUserData); + if(mCallback) return mCallback(); return FALSE; } // @@ -195,46 +211,6 @@ void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_col } } -// -// LLScrollListCheck -// -LLScrollListCheck::LLScrollListCheck(LLCheckBoxCtrl* check_box, S32 width) -{ - mCheckBox = check_box; - LLRect rect(mCheckBox->getRect()); - if (width) - { - - rect.mRight = rect.mLeft + width; - mCheckBox->setRect(rect); - setWidth(width); - } - else - { - setWidth(rect.getWidth()); //check_box->getWidth(); - } -} - -LLScrollListCheck::~LLScrollListCheck() -{ - delete mCheckBox; -} - -void LLScrollListCheck::draw(const LLColor4& color, const LLColor4& highlight_color) const -{ - mCheckBox->draw(); -} - -BOOL LLScrollListCheck::handleClick() -{ - if (mCheckBox->getEnabled()) - { - mCheckBox->toggle(); - } - // don't change selection when clicking on embedded checkbox - return TRUE; -} - // // // LLScrollListLineEditor @@ -288,25 +264,6 @@ BOOL LLScrollListLineEditor::handleUnicodeCharHere(llwchar uni_char ) } // -// -// LLScrollListSeparator -// -LLScrollListSeparator::LLScrollListSeparator(S32 width) : LLScrollListCell(width) -{ -} - -//virtual -S32 LLScrollListSeparator::getHeight() const -{ - return 5; -} - - -void LLScrollListSeparator::draw(const LLColor4& color, const LLColor4& highlight_color) const -{ - // *FIXME: use dynamic item heights and make separators narrow, and inactive - gl_line_2d(5, 8, llmax(5, getWidth() - 5), 8, color); -} // // LLScrollListText @@ -327,6 +284,8 @@ LLScrollListText::LLScrollListText( const std::string& text, const LLFontGL* fon { sCount++; + mTextWidth = getWidth(); + // initialize rounded rect image if (!mRoundedRectImage) { @@ -381,6 +340,11 @@ void LLScrollListText::setText(const LLStringExplicit& text) mText = text; } +void LLScrollListText::setFontStyle(const U8 font_style) +{ + mFontStyle = font_style; +} + //virtual void LLScrollListText::setValue(const LLSD& text) { @@ -452,12 +416,77 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col mFontStyle, LLFontGL::NO_SHADOW, string_chars, - getWidth(), + getTextWidth(), &right_x, FALSE, TRUE); } +// +// LLScrollListCheck +// +LLScrollListCheck::LLScrollListCheck(LLCheckBoxCtrl* check_box, S32 width) +{ + mCheckBox = check_box; + LLRect rect(mCheckBox->getRect()); + if (width) + { + + rect.mRight = rect.mLeft + width; + mCheckBox->setRect(rect); + setWidth(width); + } + else + { + setWidth(rect.getWidth()); //check_box->getWidth(); + } +} + +LLScrollListCheck::~LLScrollListCheck() +{ + delete mCheckBox; + mCheckBox = NULL; +} + +void LLScrollListCheck::draw(const LLColor4& color, const LLColor4& highlight_color) const +{ + mCheckBox->draw(); +} + +BOOL LLScrollListCheck::handleClick() +{ + if (mCheckBox->getEnabled()) + { + mCheckBox->toggle(); + } + // don't change selection when clicking on embedded checkbox + return TRUE; +} + +/*virtual*/ +const LLSD LLScrollListCheck::getValue() const +{ + return mCheckBox->getValue(); +} + +/*virtual*/ +void LLScrollListCheck::setValue(const LLSD& value) +{ + mCheckBox->setValue(value); +} + +/*virtual*/ +void LLScrollListCheck::onCommit() +{ + mCheckBox->onCommit(); +} + +/*virtual*/ +void LLScrollListCheck::setEnabled(BOOL enable) +{ + mCheckBox->setEnabled(enable); +} + LLScrollListDate::LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible) : LLScrollListText(date.asRFC1123(), font, width, font_style, font_alignment, color, use_color, visible), mDate(date) @@ -509,6 +538,21 @@ void LLScrollListItem::setColumn( S32 column, LLScrollListCell *cell ) } } + +S32 LLScrollListItem::getNumColumns() const +{ + return mColumns.size(); +} + +LLScrollListCell* LLScrollListItem::getColumn(const S32 i) const +{ + if (0 <= i && i < (S32)mColumns.size()) + { + return mColumns[i]; + } + return NULL; +} + std::string LLScrollListItem::getContentsCSV() const { std::string ret; @@ -529,12 +573,9 @@ std::string LLScrollListItem::getContentsCSV() const void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) { // draw background rect + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLRect bg_rect = rect; - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv(bg_color.mV); - gl_rect_2d( bg_rect ); - } + gl_rect_2d( bg_rect, bg_color ); S32 cur_x = rect.mLeft; S32 num_cols = getNumColumns(); @@ -548,7 +589,7 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLUI::pushMatrix(); { - LLUI::translate((F32) cur_x, (F32) rect.mBottom, 0.0f); + LLUI::translate((F32) cur_x, (F32) rect.mBottom); cell->draw( fg_color, highlight_color ); } @@ -559,74 +600,62 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const } -void LLScrollListItem::setEnabled(BOOL b) +// +// LLScrollListSeparator +// +/* + * Draws a horizontal line. + */ +class LLScrollListSeparator : public LLScrollListCell { - mEnabled = b; -} - -//--------------------------------------------------------------------------- -// LLScrollListItemComment -//--------------------------------------------------------------------------- -LLScrollListItemComment::LLScrollListItemComment(const std::string& comment_string, const LLColor4& color) -: LLScrollListItem(FALSE), - mColor(color) -{ - addColumn( comment_string, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ) ); -} - -void LLScrollListItemComment::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) -{ - LLScrollListCell* cell = getColumn(0); - if (cell) +public: + LLScrollListSeparator(S32 width) : LLScrollListCell(width) {} + virtual ~LLScrollListSeparator() {}; + virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const { - // Two ways a cell could be hidden - if (cell->getWidth() < 0 - || !cell->getVisible()) return; - - LLUI::pushMatrix(); - { - LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f); - - // force first cell to be width of entire item - cell->setWidth(rect.getWidth()); - cell->draw( mColor, highlight_color ); - } - LLUI::popMatrix(); + // *FIXME: use dynamic item heights and make separators narrow, and inactive + gl_line_2d(5, 8, llmax(5, getWidth() - 5), 8, color); } -} + virtual S32 getHeight() const { return 5; }; + virtual BOOL isText() const { return FALSE; } +}; //--------------------------------------------------------------------------- // LLScrollListItemSeparator //--------------------------------------------------------------------------- -LLScrollListItemSeparator::LLScrollListItemSeparator() -: LLScrollListItem(FALSE) -{ - LLScrollListSeparator* cell = new LLScrollListSeparator(0); - setNumColumns(1); - setColumn(0, cell); -} -void LLScrollListItemSeparator::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) +class LLScrollListItemSeparator : public LLScrollListItem { - //TODO* move LLScrollListSeparator::draw into here and get rid of it - LLScrollListCell* cell = getColumn(0); - if (cell) +public: + LLScrollListItemSeparator() : LLScrollListItem(FALSE) { - // Two ways a cell could be hidden - if (cell->getWidth() < 0 - || !cell->getVisible()) return; - - LLUI::pushMatrix(); - { - LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f); - - // force first cell to be width of entire item - cell->setWidth(rect.getWidth()); - cell->draw( fg_color, highlight_color ); - } - LLUI::popMatrix(); + LLScrollListSeparator* cell = new LLScrollListSeparator(0); + setNumColumns(1); + setColumn(0, cell); } -} + + /*virtual*/ void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) + { + //TODO* move LLScrollListSeparator::draw into here and get rid of it + LLScrollListCell* cell = getColumn(0); + if (cell) + { + // Two ways a cell could be hidden + if (cell->getWidth() < 0 + || !cell->getVisible()) return; + + LLUI::pushMatrix(); + { + LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f); + + // force first cell to be width of entire item + cell->setWidth(rect.getWidth()); + cell->draw( fg_color, highlight_color ); + } + LLUI::popMatrix(); + } + } +}; //--------------------------------------------------------------------------- // LLScrollListCtrl @@ -636,36 +665,24 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, void (*commit_callback)(LLUICtrl* ctrl, void* userdata), void* callback_user_data, BOOL allow_multiple_selection, - BOOL show_border + BOOL show_border, + bool draw_heading ) : LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data), mLineHeight(0), mScrollLines(0), mMouseWheelOpaque(true), mPageLines(0), - mHeadingHeight(20), mMaxSelectable(0), - mAllowMultipleSelection( allow_multiple_selection ), - mAllowKeyboardMovement(TRUE), - mCommitOnKeyboardMovement(TRUE), - mCommitOnSelectionChange(FALSE), - mSelectionChanged(FALSE), - mNeedsScroll(FALSE), - mCanSelect(TRUE), - mDisplayColumnHeaders(FALSE), - mColumnsDirty(FALSE), + mAllowKeyboardMovement(true), + mCommitOnKeyboardMovement(true), + mCommitOnSelectionChange(false), + mSelectionChanged(false), + mNeedsScroll(false), + mCanSelect(true), + mColumnsDirty(false), mMaxItemCount(INT_MAX), mMaxContentWidth(0), - mBackgroundVisible( TRUE ), - mDrawStripes(TRUE), - mBgWriteableColor( LLUI::sColorsGroup->getColor( "ScrollBgWriteableColor" ) ), - mBgReadOnlyColor( LLUI::sColorsGroup->getColor( "ScrollBgReadOnlyColor" ) ), - mBgSelectedColor( LLUI::sColorsGroup->getColor("ScrollSelectedBGColor") ), - mBgStripeColor( LLUI::sColorsGroup->getColor("ScrollBGStripeColor") ), - mFgSelectedColor( LLUI::sColorsGroup->getColor("ScrollSelectedFGColor") ), - mFgUnselectedColor( LLUI::sColorsGroup->getColor("ScrollUnselectedColor") ), - mFgDisabledColor( LLUI::sColorsGroup->getColor("ScrollDisabledColor") ), - mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ), mDefaultListTextColor( LLUI::sColorsGroup->getColor("DefaultListText") ), mBorderThickness( 2 ), mOnDoubleClickCallback( NULL ), @@ -673,14 +690,30 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, mOnSortChangedCallback( NULL ), mHighlightedItem(-1), mBorder(NULL), - mSearchColumn(0), + mSortCallback(NULL), + mCommentTextView(NULL), mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), mTotalColumnPadding(0), - mSorted(TRUE), - mDirty(FALSE), + mSorted(true), + mDirty(false), mOriginalSelection(-1), - mDrewSelected(FALSE) + mLastSelected(NULL), + mHeadingHeight(20), + mAllowMultipleSelection( allow_multiple_selection ), + mDisplayColumnHeaders(draw_heading), + mBackgroundVisible(true), + mDrawStripes(true), + mBgWriteableColor( LLUI::sColorsGroup->getColor( "ScrollBgWriteableColor" ) ), + mBgReadOnlyColor( LLUI::sColorsGroup->getColor( "ScrollBgReadOnlyColor" ) ), + mBgSelectedColor( LLUI::sColorsGroup->getColor("ScrollSelectedBGColor") ), + mBgStripeColor( LLUI::sColorsGroup->getColor("ScrollBGStripeColor") ), + mFgSelectedColor( LLUI::sColorsGroup->getColor("ScrollSelectedFGColor") ), + mFgUnselectedColor( LLUI::sColorsGroup->getColor("ScrollUnselectedColor") ), + mFgDisabledColor( LLUI::sColorsGroup->getColor("ScrollDisabledColor") ), + mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ), + mSearchColumn(0), + mColumnPadding(5) { mItemListRect.setOriginAndSize( mBorderThickness, @@ -690,8 +723,6 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, updateLineHeight(); - mPageLines = mLineHeight? (mItemListRect.getHeight()) / mLineHeight : 0; - // Init the scrollbar LLRect scroll_rect; scroll_rect.setOriginAndSize( @@ -703,7 +734,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, LLScrollbar::VERTICAL, getItemCount(), mScrollLines, - mPageLines, + getLinesPerPage(), &LLScrollListCtrl::onScrollChange, this ); mScrollbar->setFollowsRight(); mScrollbar->setFollowsTop(); @@ -721,9 +752,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, addChild(mBorder); } - mColumnPadding = 5; - mLastSelected = NULL; } S32 LLScrollListCtrl::getSearchColumn() @@ -750,7 +779,10 @@ S32 LLScrollListCtrl::getSearchColumn() LLScrollListCtrl::~LLScrollListCtrl() { + delete mSortCallback; + std::for_each(mItemList.begin(), mItemList.end(), DeletePointer()); + std::for_each(mColumns.begin(), mColumns.end(), DeletePairedPointer()); } @@ -786,7 +818,7 @@ void LLScrollListCtrl::clearRows() mScrollLines = 0; mLastSelected = NULL; updateLayout(); - mDirty = FALSE; + mDirty = false; } @@ -831,10 +863,10 @@ std::vector LLScrollListCtrl::getAllSelected() const return ret; } -LLDynamicArray LLScrollListCtrl::getSelectedIDs() +uuid_vec_t LLScrollListCtrl::getSelectedIDs() { LLUUID selected_id; - LLDynamicArray ids; + uuid_vec_t ids; std::vector selected = this->getAllSelected(); for(std::vector::iterator itr = selected.begin(); itr != selected.end(); ++itr) { @@ -843,6 +875,27 @@ LLDynamicArray LLScrollListCtrl::getSelectedIDs() return ids; } +S32 LLScrollListCtrl::getNumSelected() const +{ + if (!getCanSelect()) + { + return 0; + } + + S32 numSelected = 0; + + for(item_list::const_iterator iter = mItemList.begin(); iter != mItemList.end(); ++iter) + { + LLScrollListItem* item = *iter; + if (item->getSelected()) + { + ++numSelected; + } + } + + return numSelected; +} + S32 LLScrollListCtrl::getFirstSelectedIndex() const { if (!getCanSelect()) @@ -852,6 +905,10 @@ S32 LLScrollListCtrl::getFirstSelectedIndex() const S32 CurSelectedIndex = 0; + + // make sure sort is up to date before returning an index + updateSort(); + item_list::const_iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { @@ -887,6 +944,7 @@ LLScrollListItem* LLScrollListCtrl::getLastData() const std::vector LLScrollListCtrl::getAllData() const { std::vector ret; + ret.reserve(mItemList.size()); //Optimization item_list::const_iterator iter; for(iter = mItemList.begin(); iter != mItemList.end(); iter++) { @@ -932,17 +990,26 @@ void LLScrollListCtrl::updateLayout() getRect().getWidth() - 2 * mBorderThickness, getRect().getHeight() - (2 * mBorderThickness ) - heading_size ); + if (mCommentTextView == NULL) + { + mCommentTextView = getChildView("comment_text"); + } + + mCommentTextView->setShape(mItemListRect); + // how many lines of content in a single "page" - mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0; - BOOL scrollbar_visible = getItemCount() > mPageLines; + S32 page_lines = getLinesPerPage(); + + BOOL scrollbar_visible = mLineHeight * getItemCount() > mItemListRect.getHeight(); if (scrollbar_visible) { // provide space on the right for scrollbar mItemListRect.mRight = getRect().getWidth() - mBorderThickness - SCROLLBAR_SIZE; } + mScrollbar->setOrigin(getRect().getWidth() - mBorderThickness - SCROLLBAR_SIZE, mItemListRect.mBottom); mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0)); - mScrollbar->setPageSize( mPageLines ); + mScrollbar->setPageSize(page_lines); mScrollbar->setDocSize( getItemCount() ); mScrollbar->setVisible(scrollbar_visible); @@ -954,6 +1021,9 @@ void LLScrollListCtrl::updateLayout() void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height) { S32 height = llmin( getRequiredRect().getHeight(), max_height ); + if(mPageLines) + height = llmin( mPageLines * mLineHeight + 2*mBorderThickness + (mDisplayColumnHeaders ? mHeadingHeight : 0), height ); + S32 width = getRect().getWidth(); reshape( width, height ); @@ -981,7 +1051,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r { case ADD_TOP: mItemList.push_front(item); - setSorted(FALSE); + setNeedsSort(); break; case ADD_SORTED: @@ -994,22 +1064,22 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r std::stable_sort( mItemList.begin(), mItemList.end(), - SortScrollListItem(single_sort_column)); + SortScrollListItem(single_sort_column,mSortCallback)); // ADD_SORTED just sorts by first column... // this might not match user sort criteria, so flag list as being in unsorted state - setSorted(FALSE); + setNeedsSort(); break; - } + } case ADD_BOTTOM: mItemList.push_back(item); - setSorted(FALSE); + setNeedsSort(); break; default: llassert(0); mItemList.push_back(item); - setSorted(FALSE); + setNeedsSort(); break; } @@ -1023,6 +1093,15 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r addColumn(new_column); } + S32 num_cols = item->getNumColumns(); + S32 i = 0; + for (LLScrollListCell* cell = item->getColumn(i); i < num_cols; cell = item->getColumn(++i)) + { + if (i >= (S32)mColumnsIndexed.size()) break; + + cell->setWidth(mColumnsIndexed[i]->getWidth()); + } + updateLineHeightInsert(item); updateLayout(); @@ -1034,15 +1113,43 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r // NOTE: This is *very* expensive for large lists, especially when we are dirtying the list every frame // while receiving a long list of names. // *TODO: Use bookkeeping to make this an incramental cost with item additions -void LLScrollListCtrl::calcColumnWidths() +S32 LLScrollListCtrl::calcMaxContentWidth() { const S32 HEADING_TEXT_PADDING = 25; const S32 COLUMN_TEXT_PADDING = 10; - mMaxContentWidth = 0; - S32 max_item_width = 0; + ordered_columns_t::iterator column_itor; + for (column_itor = mColumnsIndexed.begin(); column_itor != mColumnsIndexed.end(); ++column_itor) + { + LLScrollListColumn* column = *column_itor; + if (!column) continue; + + if (mColumnWidthsDirty) + { + mColumnWidthsDirty = false; + // update max content width for this column, by looking at all items + column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; + item_list::iterator iter; + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + { + LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); + if (!cellp) continue; + + column->mMaxContentWidth = llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); + } + } + max_item_width += column->mMaxContentWidth; + } + + mMaxContentWidth = max_item_width; + return max_item_width; +} + +bool LLScrollListCtrl::updateColumnWidths() +{ + bool width_changed = false; ordered_columns_t::iterator column_itor; for (column_itor = mColumnsIndexed.begin(); column_itor != mColumnsIndexed.end(); ++column_itor) { @@ -1060,23 +1167,14 @@ void LLScrollListCtrl::calcColumnWidths() new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns; } - column->setWidth(new_width); - - // update max content width for this column, by looking at all items - column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + if (column->getWidth() != new_width) { - LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); - if (!cellp) continue; - - column->mMaxContentWidth = llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); + column->setWidth(new_width); + width_changed = true; } - - max_item_width += column->mMaxContentWidth; } - - mMaxContentWidth = max_item_width; + calcMaxContentWidth(); + return width_changed; } const S32 SCROLL_LIST_ROW_PAD = 2; @@ -1112,12 +1210,17 @@ void LLScrollListCtrl::updateLineHeightInsert(LLScrollListItem* itemp) void LLScrollListCtrl::updateColumns() { - calcColumnWidths(); + if (!mColumnsDirty) + return; + + mColumnsDirty = false; + + bool columns_changed_width = updateColumnWidths(); // update column headers std::vector::iterator column_ordered_it; S32 left = mItemListRect.mLeft; - LLColumnHeader* last_header = NULL; + LLScrollColumnHeader* last_header = NULL; for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it) { if ((*column_ordered_it)->getWidth() < 0) @@ -1161,20 +1264,22 @@ void LLScrollListCtrl::updateColumns() } // propagate column widths to individual cells - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + if (columns_changed_width) { - LLScrollListItem *itemp = *iter; - S32 num_cols = itemp->getNumColumns(); - S32 i = 0; - for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i)) + item_list::iterator iter; + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { - if (i >= (S32)mColumnsIndexed.size()) break; + LLScrollListItem *itemp = *iter; + S32 num_cols = itemp->getNumColumns(); + S32 i = 0; + for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i)) + { + if (i >= (S32)mColumnsIndexed.size()) break; - cell->setWidth(mColumnsIndexed[i]->getWidth()); + cell->setWidth(mColumnsIndexed[i]->getWidth()); + } } } - } void LLScrollListCtrl::setDisplayHeading(BOOL display) @@ -1191,6 +1296,12 @@ void LLScrollListCtrl::setHeadingHeight(S32 heading_height) updateLayout(); } +void LLScrollListCtrl::setPageLines(S32 new_page_lines) +{ + mPageLines = new_page_lines; + + updateLayout(); +} BOOL LLScrollListCtrl::selectFirstItem() { @@ -1216,7 +1327,7 @@ BOOL LLScrollListCtrl::selectFirstItem() { deselectItem(itemp); } - first_item = FALSE; + first_item = false; } if (mCommitOnSelectionChange) { @@ -1240,6 +1351,9 @@ BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index ) return FALSE; } + // make sure sort is up to date + updateSort(); + S32 listlen = (S32)mItemList.size(); first_index = llclamp(first_index, 0, listlen-1); @@ -1293,6 +1407,7 @@ void LLScrollListCtrl::swapWithNext(S32 index) // At end of list, doesn't do anything return; } + updateSort(); LLScrollListItem *cur_itemp = mItemList[index]; mItemList[index] = mItemList[index + 1]; mItemList[index + 1] = cur_itemp; @@ -1307,6 +1422,7 @@ void LLScrollListCtrl::swapWithPrevious(S32 index) return; } + updateSort(); LLScrollListItem *cur_itemp = mItemList[index]; mItemList[index] = mItemList[index - 1]; mItemList[index - 1] = cur_itemp; @@ -1332,6 +1448,8 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index) return; } + updateSort(); + LLScrollListItem *itemp; itemp = mItemList[target_index]; if (itemp == mLastSelected) @@ -1388,7 +1506,7 @@ void LLScrollListCtrl::deleteSelectedItems() dirtyColumns(); } -void LLScrollListCtrl::highlightNthItem(S32 target_index) +void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index) { if (mHighlightedItem != target_index) { @@ -1396,14 +1514,14 @@ void LLScrollListCtrl::highlightNthItem(S32 target_index) } } -S32 LLScrollListCtrl::selectMultiple( LLDynamicArray ids ) +S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids ) { item_list::iterator iter; S32 count = 0; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; - LLDynamicArray::iterator iditr; + uuid_vec_t::iterator iditr; for(iditr = ids.begin(); iditr != ids.end(); ++iditr) { if (item->getEnabled() && (item->getUUID() == (*iditr))) @@ -1425,6 +1543,8 @@ S32 LLScrollListCtrl::selectMultiple( LLDynamicArray ids ) S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item ) const { + updateSort(); + S32 index = 0; item_list::const_iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) @@ -1441,6 +1561,8 @@ S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item ) const S32 LLScrollListCtrl::getItemIndex( const LLUUID& target_id ) const { + updateSort(); + S32 index = 0; item_list::const_iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) @@ -1466,6 +1588,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection) } else { + updateSort(); + item_list::iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { @@ -1508,6 +1632,8 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection) } else { + updateSort(); + item_list::reverse_iterator iter; for (iter = mItemList.rbegin(); iter != mItemList.rend(); iter++) { @@ -1559,16 +1685,10 @@ void LLScrollListCtrl::deselectAllItems(BOOL no_commit_on_change) /////////////////////////////////////////////////////////////////////////////////////////////////// // Use this to add comment text such as "Searching", which ignores column settings of list -LLScrollListItem* LLScrollListCtrl::addCommentText(const std::string& comment_text, EAddPosition pos) + +void LLScrollListCtrl::setCommentText(const std::string& comment_text) { - LLScrollListItem* item = NULL; - if (getItemCount() < mMaxItemCount) - { - // always draw comment text with "enabled" color - item = new LLScrollListItemComment( comment_text, mFgUnselectedColor ); - addItem( item, pos, FALSE ); - } - return item; + getChild("comment_text")->setValue(comment_text); } LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos) @@ -1582,40 +1702,13 @@ LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos) // Returns false if item not found. BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive) { - // ensure that no stale items are selected, even if we don't find a match - deselectAllItems(TRUE); - //RN: assume no empty items - if (label.empty()) - { - return FALSE; - } + deselectAllItems(TRUE); // ensure that no stale items are selected, even if we don't find a match + LLScrollListItem* item = getItemByLabel(label, case_sensitive); - std::string target_text = label; - if (!case_sensitive) + bool found = NULL != item; + if(found) { - LLStringUtil::toLower(target_text); - } - - BOOL found = FALSE; - - item_list::iterator iter; - S32 index = 0; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) - { - LLScrollListItem* item = *iter; - // Only select enabled items with matching names - std::string item_text = item->getColumn(0)->getValue().asString(); - if (!case_sensitive) - { - LLStringUtil::toLower(item_text); - } - BOOL select = !found && item->getEnabled() && item_text == target_text; - if (select) - { - selectItem(item); - } - found = found || select; - index++; + selectItem(item); } if (mCommitOnSelectionChange) @@ -1626,6 +1719,36 @@ BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sen return found; } +LLScrollListItem* LLScrollListCtrl::getItemByLabel(const std::string& label, BOOL case_sensitive, S32 column) +{ + if (label.empty()) //RN: assume no empty items + { + return NULL; + } + + std::string target_text = label; + if (!case_sensitive) + { + LLStringUtil::toLower(target_text); + } + + item_list::iterator iter; + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + { + LLScrollListItem* item = *iter; + std::string item_text = item->getColumn(column)->getValue().asString(); // Only select enabled items with matching names + if (!case_sensitive) + { + LLStringUtil::toLower(item_text); + } + if(item_text == target_text) + { + return item; + } + } + return NULL; +} + BOOL LLScrollListCtrl::selectItemByPrefix(const std::string& target, BOOL case_sensitive) { @@ -1822,7 +1945,7 @@ void LLScrollListCtrl::drawItems() S32 y = mItemListRect.mTop - mLineHeight; // allow for partial line at bottom - S32 num_page_lines = mPageLines + 1; + S32 num_page_lines = getLinesPerPage(); LLRect item_rect; @@ -1832,34 +1955,34 @@ void LLScrollListCtrl::drawItems() LLLocalClipRect clip(mItemListRect); S32 cur_y = y; - - mDrewSelected = FALSE; - S32 line = 0; S32 max_columns = 0; LLColor4 highlight_color = LLColor4::white; F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout"); highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f); - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + S32 first_line = mScrollLines; + S32 last_line = llmin((S32)mItemList.size() - 1, mScrollLines + getLinesPerPage()); + + if ((item_list::size_type)first_line >= mItemList.size()) { - LLScrollListItem* item = *iter; + return; + } + item_list::iterator iter; + for (S32 line = first_line; line <= last_line; line++) + { + LLScrollListItem* item = mItemList[line]; item_rect.setOriginAndSize( x, cur_y, mItemListRect.getWidth(), mLineHeight ); + item->setRect(item_rect); //llinfos << item_rect.getWidth() << llendl; - if (item->getSelected()) - { - mDrewSelected = TRUE; - } - max_columns = llmax(max_columns, item->getNumColumns()); LLColor4 fg_color; @@ -1894,7 +2017,6 @@ void LLScrollListCtrl::drawItems() cur_y -= mLineHeight; } - line++; } } } @@ -1905,15 +2027,12 @@ void LLScrollListCtrl::draw() LLLocalClipRect clip(getLocalRect()); // if user specifies sort, make sure it is maintained - if (needsSorting() && !isSorted()) - { - sortItems(); - } + updateSort(); if (mNeedsScroll) { scrollToShowSelected(); - mNeedsScroll = FALSE; + mNeedsScroll = false; } LLRect background(0, getRect().getHeight(), getRect().getWidth(), 0); // Draw background @@ -1924,17 +2043,14 @@ void LLScrollListCtrl::draw() gl_rect_2d(background); } - if (mColumnsDirty) - { - updateColumns(); - mColumnsDirty = FALSE; - } + updateColumns(); + drawItems(); if (mBorder) { - mBorder->setKeyboardFocusHighlight(gFocusMgr.getKeyboardFocus() == this); + mBorder->setKeyboardFocusHighlight(hasFocus()); } LLUICtrl::draw(); @@ -1961,6 +2077,18 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks) return handled; } +// *NOTE: Requires a valid row_index and column_index +LLRect LLScrollListCtrl::getCellRect(S32 row_index, S32 column_index) +{ + LLRect cell_rect; + S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft; + S32 rect_bottom = getRowOffsetFromIndex(row_index); + LLScrollListColumn* columnp = getColumn(column_index); + cell_rect.setOriginAndSize(rect_left, rect_bottom, + /*rect_left + */columnp->getWidth(), mLineHeight); + return cell_rect; +} + BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) { S32 column_index = getColumnIndexFromOffset(x); @@ -1988,18 +2116,11 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti if (hit_cell && hit_cell->isText()) { - - S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft; - S32 rect_bottom = getRowOffsetFromIndex(getItemIndex(hit_item)); - LLRect cell_rect; - cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->getWidth(), mLineHeight); + S32 row_index = getItemIndex(hit_item); + LLRect cell_rect = getCellRect(row_index, column_index); // Convert rect local to screen coordinates - localPointToScreen( - cell_rect.mLeft, cell_rect.mBottom, - &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); - localPointToScreen( - cell_rect.mRight, cell_rect.mTop, - &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) ); + LLRect sticky_rect; + localRectToScreen(cell_rect, sticky_rect_screen); msg = hit_cell->getValue().asString(); } @@ -2007,7 +2128,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti } // otherwise, look for a tooltip associated with this column - LLColumnHeader* headerp = columnp->mHeader; + LLScrollColumnHeader* headerp = columnp->mHeader; if (headerp && !handled) { headerp->handleToolTip(x, y, msg, sticky_rect_screen); @@ -2050,7 +2171,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { if(mOnMaximumSelectCallback) { - mOnMaximumSelectCallback(mCallbackUserData); + mOnMaximumSelectCallback(); } break; } @@ -2088,7 +2209,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { if(mOnMaximumSelectCallback) { - mOnMaximumSelectCallback(mCallbackUserData); + mOnMaximumSelectCallback(); } } } @@ -2133,7 +2254,7 @@ BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask) setFocus(TRUE); // clear selection changed flag because user is starting a selection operation - mSelectionChanged = FALSE; + mSelectionChanged = false; handleClick(x, y, mask); @@ -2153,15 +2274,15 @@ BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask) if(mask == MASK_NONE) { selectItemAt(x, y, mask); - mNeedsScroll = TRUE; + mNeedsScroll = true; } } // always commit when mouse operation is completed inside list if (mItemListRect.pointInRect(x,y)) { - mDirty |= mSelectionChanged; - mSelectionChanged = FALSE; + mDirty = mDirty || mSelectionChanged; + mSelectionChanged = false; onCommit(); } @@ -2179,9 +2300,10 @@ BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask) // so the scroll bars will work. if (NULL == LLView::childrenHandleDoubleClick(x, y, mask)) { - if( mCanSelect && mOnDoubleClickCallback ) + // Run the callback only if an item is being double-clicked. + if( mCanSelect && hitItem(x, y) && mOnDoubleClickCallback ) { - mOnDoubleClickCallback( mCallbackUserData ); + mOnDoubleClickCallback(); } } } @@ -2208,7 +2330,7 @@ BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask) { selectItemAt(x, y, mask); gFocusMgr.setMouseCapture(this); - mNeedsScroll = TRUE; + mNeedsScroll = true; } // propagate state of cell to rest of selected column @@ -2237,7 +2359,7 @@ BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask) // treat this as a normal single item selection selectItemAt(x, y, mask); gFocusMgr.setMouseCapture(this); - mNeedsScroll = TRUE; + mNeedsScroll = true; // do not eat click (allow double click callback) return FALSE; } @@ -2248,6 +2370,8 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y ) // Excludes disabled items. LLScrollListItem* hit_item = NULL; + updateSort(); + LLRect item_rect; item_rect.setLeftTopAndSize( mItemListRect.mLeft, @@ -2256,7 +2380,7 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y ) mLineHeight ); // allow for partial line at bottom - S32 num_page_lines = mPageLines + 1; + S32 num_page_lines = getLinesPerPage(); S32 line = 0; item_list::iterator iter; @@ -2327,8 +2451,7 @@ S32 LLScrollListCtrl::getColumnOffsetFromIndex(S32 index) S32 LLScrollListCtrl::getRowOffsetFromIndex(S32 index) { - S32 row_bottom = ((mItemListRect.mTop - (index - mScrollLines)) * mLineHeight) - - mLineHeight; + S32 row_bottom = (mItemListRect.mTop - ((index - mScrollLines + 1) * mLineHeight) ); return row_bottom; } @@ -2342,7 +2465,7 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) if(mask == MASK_NONE) { selectItemAt(x, y, mask); - mNeedsScroll = TRUE; + mNeedsScroll = true; } } else @@ -2351,11 +2474,11 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) LLScrollListItem* item = hitItem(x, y); if (item) { - highlightNthItem(getItemIndex(item)); + mouseOverHighlightNthItem(getItemIndex(item)); } else { - highlightNthItem(-1); + mouseOverHighlightNthItem(-1); } } @@ -2384,7 +2507,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) { // commit implicit in call selectPrevItem(FALSE); - mNeedsScroll = TRUE; + mNeedsScroll = true; handled = TRUE; } break; @@ -2393,7 +2516,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) { // commit implicit in call selectNextItem(FALSE); - mNeedsScroll = TRUE; + mNeedsScroll = true; handled = TRUE; } break; @@ -2401,7 +2524,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getFirstSelectedIndex() - (mScrollbar->getPageSize() - 1)); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2414,7 +2537,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getFirstSelectedIndex() + (mScrollbar->getPageSize() - 1)); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2427,7 +2550,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectFirstItem(); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2440,7 +2563,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getItemCount() - 1); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2479,7 +2602,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) } else if (selectItemByPrefix(wstring_to_utf8str(mSearchString), FALSE)) { - mNeedsScroll = TRUE; + mNeedsScroll = true; // update search string only on successful match mSearchTimer.reset(); @@ -2519,7 +2642,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char) if (selectItemByPrefix(wstring_to_utf8str(mSearchString + (llwchar)uni_char), FALSE)) { // update search string only on successful match - mNeedsScroll = TRUE; + mNeedsScroll = true; mSearchString += uni_char; mSearchTimer.reset(); @@ -2565,7 +2688,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char) if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char) { selectItem(item); - mNeedsScroll = TRUE; + mNeedsScroll = true; cellp->highlightText(0, 1); mSearchTimer.reset(); @@ -2636,7 +2759,7 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it } itemp->setSelected(TRUE); mLastSelected = itemp; - mSelectionChanged = TRUE; + mSelectionChanged = true; } } @@ -2657,7 +2780,7 @@ void LLScrollListCtrl::deselectItem(LLScrollListItem* itemp) { cellp->highlightText(0, 0); } - mSelectionChanged = TRUE; + mSelectionChanged = true; } } @@ -2665,7 +2788,7 @@ void LLScrollListCtrl::commitIfChanged() { if (mSelectionChanged) { - mDirty = TRUE; + mDirty = true; mSelectionChanged = FALSE; onCommit(); } @@ -2684,9 +2807,11 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending) LLScrollListColumn* sort_column = getColumn(column_idx); if (!sort_column) return FALSE; - sort_column->mSortAscending = ascending; + sort_column->mSortDirection = ascending ? LLScrollListColumn::ASCENDING : LLScrollListColumn::DESCENDING; sort_column_t new_sort_column(column_idx, ascending); + + setNeedsSort(); if (mSortColumns.empty()) { @@ -2708,6 +2833,19 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending) } } +S32 LLScrollListCtrl::getLinesPerPage() +{ + //if mPageLines is NOT provided display all item + if(mPageLines) + { + return mPageLines; + } + else + { + return mLineHeight ? mItemListRect.getHeight() / mLineHeight : getItemCount(); + } +} + // Called by scrollbar //static void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata ) @@ -2719,31 +2857,32 @@ void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void void LLScrollListCtrl::sortByColumn(const std::string& name, BOOL ascending) { - std::map::iterator itor = mColumns.find(name); + column_map_t::iterator itor = mColumns.find(name); if (itor != mColumns.end()) { - sortByColumnIndex((*itor).second.mIndex, ascending); + sortByColumnIndex((*itor).second->mIndex, ascending); } } // First column is column 0 void LLScrollListCtrl::sortByColumnIndex(U32 column, BOOL ascending) { - if (setSort(column, ascending)) - { - sortItems(); - } + setSort(column, ascending); + updateSort(); } -void LLScrollListCtrl::sortItems() +void LLScrollListCtrl::updateSort() const { - // do stable sort to preserve any previous sorts - std::stable_sort( - mItemList.begin(), - mItemList.end(), - SortScrollListItem(mSortColumns)); + if (hasSortOrder() && !isSorted()) + { + // do stable sort to preserve any previous sorts + std::stable_sort( + mItemList.begin(), + mItemList.end(), + SortScrollListItem(mSortColumns,mSortCallback)); - setSorted(TRUE); + mSorted = true; + } } // for one-shot sorts, does not save sort column/order @@ -2756,22 +2895,23 @@ void LLScrollListCtrl::sortOnce(S32 column, BOOL ascending) std::stable_sort( mItemList.begin(), mItemList.end(), - SortScrollListItem(sort_column)); + SortScrollListItem(sort_column,mSortCallback)); } void LLScrollListCtrl::dirtyColumns() { - mColumnsDirty = TRUE; + mColumnsDirty = true; + mColumnWidthsDirty = true; // need to keep mColumnsIndexed up to date // just in case someone indexes into it immediately mColumnsIndexed.resize(mColumns.size()); - std::map::iterator column_itor; + column_map_t::iterator column_itor; for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor) { - LLScrollListColumn *column = &column_itor->second; - mColumnsIndexed[column_itor->second.mIndex] = column; + LLScrollListColumn *column = column_itor->second; + mColumnsIndexed[column_itor->second->mIndex] = column; } } @@ -2799,6 +2939,8 @@ void LLScrollListCtrl::scrollToShowSelected() return; } + updateSort(); + S32 index = getFirstSelectedIndex(); if (index < 0) { @@ -2813,7 +2955,8 @@ void LLScrollListCtrl::scrollToShowSelected() } S32 lowest = mScrollLines; - S32 highest = mScrollLines + mPageLines; + S32 page_lines = getLinesPerPage(); + S32 highest = mScrollLines + page_lines; if (index < lowest) { @@ -2822,7 +2965,7 @@ void LLScrollListCtrl::scrollToShowSelected() } else if (highest <= index) { - setScrollPos(index - mPageLines + 1); + setScrollPos(index - page_lines + 1); } } @@ -2869,9 +3012,9 @@ LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const std::map::const_iterator itor; std::vector sorted_list; sorted_list.resize(mColumns.size()); - for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) + for (column_map_t::const_iterator itor = mColumns.begin(); itor != mColumns.end(); ++itor) { - sorted_list[itor->second.mIndex] = &itor->second; + sorted_list[itor->second->mIndex] = itor->second; } std::vector::iterator itor2; @@ -2993,9 +3136,9 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac callback, NULL, multi_select, - draw_border); + draw_border, + draw_heading); - scroll_list->setDisplayHeading(draw_heading); if (node->hasAttribute("heading_height")) { S32 heading_height; @@ -3217,8 +3360,8 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) if (mColumns.find(name) == mColumns.end()) { // Add column - mColumns[name] = LLScrollListColumn(column, this); - LLScrollListColumn* new_column = &mColumns[name]; + LLScrollListColumn* new_column = new LLScrollListColumn(column, this); + mColumns[name] = new_column; new_column->mParentCtrl = this; new_column->mIndex = mColumns.size()-1; @@ -3239,18 +3382,19 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) new_column->setWidth((mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns); } S32 top = mItemListRect.mTop; + S32 left = mItemListRect.mLeft; + for (column_map_t::iterator itor = mColumns.begin(); + itor != mColumns.end(); + ++itor) { - std::map::iterator itor; - for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) + if (itor->second->mIndex < new_column->mIndex && + itor->second->getWidth() > 0) { - if (itor->second.mIndex < new_column->mIndex && - itor->second.getWidth() > 0) - { - left += itor->second.getWidth() + mColumnPadding; - } + left += itor->second->getWidth() + mColumnPadding; } } + std::string button_name = "btn_" + name; S32 right = left+new_column->getWidth(); if (new_column->mIndex != (S32)mColumns.size()-1) @@ -3258,7 +3402,7 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) right += mColumnPadding; } LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top); - new_column->mHeader = new LLColumnHeader(button_name, temp_rect, new_column); + new_column->mHeader = new LLScrollColumnHeader(button_name, temp_rect, new_column); if(column["image"].asString() != "") { //new_column->mHeader->setScaleImage(false); @@ -3301,12 +3445,12 @@ void LLScrollListCtrl::onClickColumn(void *userdata) S32 column_index = info->mIndex; LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex]; - bool ascending = column->mSortAscending; + bool ascending = column->mSortDirection == LLScrollListColumn::ASCENDING; if (column->mSortingColumn != column->mName && parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end()) { - LLScrollListColumn& info_redir = parent->mColumns[column->mSortingColumn]; - column_index = info_redir.mIndex; + LLScrollListColumn* info_redir = parent->mColumns[column->mSortingColumn]; + column_index = info_redir->mIndex; } // if this column is the primary sort key, reverse the direction @@ -3320,7 +3464,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata) if (parent->mOnSortChangedCallback) { - parent->mOnSortChangedCallback(parent->getCallbackUserData()); + parent->mOnSortChangedCallback(); } } @@ -3332,23 +3476,29 @@ std::string LLScrollListCtrl::getSortColumnName() else return ""; } -BOOL LLScrollListCtrl::needsSorting() +BOOL LLScrollListCtrl::hasSortOrder() const { return !mSortColumns.empty(); } +void LLScrollListCtrl::clearSortOrder() +{ + mSortColumns.clear(); +} + void LLScrollListCtrl::clearColumns() { - std::map::iterator itor; + column_map_t::iterator itor; for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) { - LLColumnHeader *header = itor->second.mHeader; + LLScrollColumnHeader *header = itor->second->mHeader; if (header) { removeChild(header); delete header; } } + std::for_each(mColumns.begin(), mColumns.end(), DeletePairedPointer()); mColumns.clear(); mSortColumns.clear(); mTotalStaticColumnWidth = 0; @@ -3357,13 +3507,13 @@ void LLScrollListCtrl::clearColumns() void LLScrollListCtrl::setColumnLabel(const std::string& column, const std::string& label) { - std::map::iterator itor = mColumns.find(column); - if (itor != mColumns.end()) + LLScrollListColumn* columnp = getColumn(column); + if (columnp) { - itor->second.mLabel = label; - if (itor->second.mHeader) + columnp->mLabel = label; + if (columnp->mHeader) { - itor->second.mHeader->setLabel(label); + columnp->mHeader->setLabel(label); } } } @@ -3377,6 +3527,16 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(S32 index) return mColumnsIndexed[index]; } +LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name) +{ + column_map_t::iterator column_itor = mColumns.find(name); + if (column_itor != mColumns.end()) + { + return column_itor->second; + } + return NULL; +} + void LLScrollListCtrl::setColumnHeadings(LLSD headings) { mColumns.clear(); @@ -3387,6 +3547,15 @@ void LLScrollListCtrl::setColumnHeadings(LLSD headings) } } +/* "id" + "enabled" + "columns" + "column" + "name" + "label" + "width" + "dynamic_width" +*/ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition pos, void* userdata) { // ID @@ -3423,11 +3592,10 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p column = new_name.str(); } - std::map::iterator column_itor; - column_itor = mColumns.find(column); + column_map_t::iterator column_itor = mColumns.find(column); if (column_itor != mColumns.end()) { - columnp = &column_itor->second; + columnp = column_itor->second; } // create new column on demand @@ -3447,7 +3615,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p new_column["dynamicwidth"] = true; } addColumn(new_column); - columnp = &mColumns[column]; + columnp = mColumns[column]; new_item->setNumColumns(mColumns.size()); } @@ -3561,10 +3729,10 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p // add dummy cells for missing columns for (column_map_t::iterator column_it = mColumns.begin(); column_it != mColumns.end(); ++column_it) { - S32 column_idx = column_it->second.mIndex; + S32 column_idx = column_it->second->mIndex; if (new_item->getColumn(column_idx) == NULL) { - LLScrollListColumn* column_ptr = &column_it->second; + LLScrollListColumn* column_ptr = column_it->second; new_item->setColumn(column_idx, new LLScrollListText(LLStringUtil::null, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->getWidth(), LLFontGL::NORMAL)); } } @@ -3643,7 +3811,6 @@ BOOL LLScrollListCtrl::operateOnAll(EOperation op) //virtual void LLScrollListCtrl::setFocus(BOOL b) { - mSearchString.clear(); // for tabbing into pristine scroll lists (Finder) if (!getFirstSelected()) { @@ -3677,7 +3844,7 @@ void LLScrollListCtrl::resetDirty() void LLScrollListCtrl::onFocusReceived() { // forget latent selection changes when getting focus - mSelectionChanged = FALSE; + mSelectionChanged = false; LLUICtrl::onFocusReceived(); } @@ -3688,10 +3855,13 @@ void LLScrollListCtrl::onFocusLost() { gFocusMgr.setMouseCapture(NULL); } + + mSearchString.clear(); + LLUICtrl::onFocusLost(); } -LLColumnHeader::LLColumnHeader(const std::string& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL* fontp) : +LLScrollColumnHeader::LLScrollColumnHeader(const std::string& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL* fontp) : LLComboBox(label, rect, label, NULL, NULL), mColumn(column), mOrigLabel(label), @@ -3704,9 +3874,9 @@ LLColumnHeader::LLColumnHeader(const std::string& label, const LLRect &rect, LLS mButton->setTabStop(FALSE); // require at least two frames between mouse down and mouse up event to capture intentional "hold" not just bad framerate mButton->setHeldDownDelay(LLUI::sConfigGroup->getF32("ColumnHeaderDropDownDelay"), 2); - mButton->setHeldDownCallback(boost::bind(&LLColumnHeader::onHeldDown, this)); - mButton->setClickedCallback(boost::bind(&LLColumnHeader::onClick, this)); - mButton->setMouseDownCallback(boost::bind(&LLColumnHeader::onMouseDown, this)); + mButton->setHeldDownCallback(boost::bind(&LLScrollColumnHeader::onHeldDown, this)); + mButton->setClickedCallback(boost::bind(&LLScrollColumnHeader::onClick, this)); + mButton->setMouseDownCallback(boost::bind(&LLScrollColumnHeader::onMouseDown, this)); mButton->setCallbackUserData(this); mButton->setToolTip(label); @@ -3731,13 +3901,17 @@ LLColumnHeader::LLColumnHeader(const std::string& label, const LLRect &rect, LLS mImageOverlayColor = LLColor4::white; } -LLColumnHeader::~LLColumnHeader() +LLScrollColumnHeader::~LLScrollColumnHeader() { } -void LLColumnHeader::draw() +void LLScrollColumnHeader::draw() { - BOOL draw_arrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn; + std::string sort_column = mColumn->mParentCtrl->getSortColumnName(); + BOOL draw_arrow = !mColumn->mLabel.empty() + && mColumn->mParentCtrl->isSorted() + // check for indirect sorting column as well as column's sorting name + && (sort_column == mColumn->mSortingColumn || sort_column == mColumn->mName); BOOL is_ascending = mColumn->mParentCtrl->getSortAscending(); mButton->setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, draw_arrow ? LLColor4::white : LLColor4::transparent); @@ -3848,11 +4022,12 @@ void LLColumnHeader::draw() } } -BOOL LLColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask) +BOOL LLScrollColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask) { if (canResize() && mResizeBar->getRect().pointInRect(x, y)) { // reshape column to max content width + mColumn->mParentCtrl->calcMaxContentWidth(); LLRect column_rect = getRect(); column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth; setShape(column_rect,true); @@ -3864,7 +4039,7 @@ BOOL LLColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask) return TRUE; } -void LLColumnHeader::setImage(const std::string &image_name) +void LLScrollColumnHeader::setImage(const std::string &image_name) { if (mButton) { @@ -3873,7 +4048,7 @@ void LLColumnHeader::setImage(const std::string &image_name) } } -void LLColumnHeader::setImageOverlay(const std::string &image_name, LLFontGL::HAlign alignment, const LLColor4& color) +void LLScrollColumnHeader::setImageOverlay(const std::string &image_name, LLFontGL::HAlign alignment, const LLColor4& color) { if (image_name.empty()) { @@ -3888,9 +4063,9 @@ void LLColumnHeader::setImageOverlay(const std::string &image_name, LLFontGL::HA } //static -void LLColumnHeader::onClick(void* user_data) +void LLScrollColumnHeader::onClick(void* user_data) { - LLColumnHeader* headerp = (LLColumnHeader*)user_data; + LLScrollColumnHeader* headerp = (LLScrollColumnHeader*)user_data; if (!headerp) return; LLScrollListColumn* column = headerp->mColumn; @@ -3910,20 +4085,20 @@ void LLColumnHeader::onClick(void* user_data) } //static -void LLColumnHeader::onMouseDown(void* user_data) +void LLScrollColumnHeader::onMouseDown(void* user_data) { // for now, do nothing but block the normal showList() behavior return; } //static -void LLColumnHeader::onHeldDown(void* user_data) +void LLScrollColumnHeader::onHeldDown(void* user_data) { - LLColumnHeader* headerp = (LLColumnHeader*)user_data; + LLScrollColumnHeader* headerp = (LLScrollColumnHeader*)user_data; headerp->showList(); } -void LLColumnHeader::showList() +void LLScrollColumnHeader::showList() { if (mShowSortOptions) { @@ -3996,8 +4171,8 @@ void LLColumnHeader::showList() text_width = llmax(text_width, getRect().getWidth() - 30); mList->getColumn(0)->setWidth(text_width); - ((LLScrollListText*)mList->getFirstData()->getColumn(0))->setText(ascending_string); - ((LLScrollListText*)mList->getLastData()->getColumn(0))->setText(descending_string); + mList->getFirstData()->getColumn(0)->setValue(ascending_string); + mList->getLastData()->getColumn(0)->setValue(descending_string); mList->reshape(llmax(text_width + 30, 110, getRect().getWidth()), mList->getRect().getHeight()); @@ -4006,9 +4181,9 @@ void LLColumnHeader::showList() } //static -void LLColumnHeader::onSelectSort(LLUICtrl* ctrl, void* user_data) +void LLScrollColumnHeader::onSelectSort(LLUICtrl* ctrl, void* user_data) { - LLColumnHeader* headerp = (LLColumnHeader*)user_data; + LLScrollColumnHeader* headerp = (LLScrollColumnHeader*)user_data; if (!headerp) return; LLScrollListColumn* column = headerp->mColumn; @@ -4031,7 +4206,7 @@ void LLColumnHeader::onSelectSort(LLUICtrl* ctrl, void* user_data) headerp->setLabel(headerp->mOrigLabel); } -LLView* LLColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding) +LLView* LLScrollColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding) { // this logic assumes dragging on right llassert(snap_edge == SNAP_RIGHT); @@ -4069,7 +4244,7 @@ LLView* LLColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_d return this; } -void LLColumnHeader::handleReshape(const LLRect& new_rect, bool by_user) +void LLScrollColumnHeader::handleReshape(const LLRect& new_rect, bool by_user) { S32 new_width = new_rect.getWidth(); S32 delta_width = new_width - (getRect().getWidth() /*+ mColumn->mParentCtrl->getColumnPadding()*/); @@ -4147,11 +4322,12 @@ void LLColumnHeader::handleReshape(const LLRect& new_rect, bool by_user) // tell scroll list to layout columns again // do immediate update to get proper feedback to resize handle // which needs to know how far the resize actually went + mColumn->mParentCtrl->dirtyColumns(); //Must flag as dirty, else updateColumns will probably be a noop. mColumn->mParentCtrl->updateColumns(); } } -void LLColumnHeader::setHasResizableElement(BOOL resizable) +void LLScrollColumnHeader::setHasResizableElement(BOOL resizable) { // for now, dynamically spaced columns can't be resized // if (mColumn->mDynamicWidth) return; @@ -4163,7 +4339,7 @@ void LLColumnHeader::setHasResizableElement(BOOL resizable) } } -void LLColumnHeader::updateResizeBars() +void LLScrollColumnHeader::updateResizeBars() { S32 num_resizable_columns = 0; S32 col; @@ -4192,7 +4368,7 @@ void LLColumnHeader::updateResizeBars() } } -void LLColumnHeader::enableResizeBar(BOOL enable) +void LLScrollColumnHeader::enableResizeBar(BOOL enable) { // for now, dynamically spaced columns can't be resized //if (!mColumn->mDynamicWidth) @@ -4201,25 +4377,16 @@ void LLColumnHeader::enableResizeBar(BOOL enable) } } -BOOL LLColumnHeader::canResize() +BOOL LLScrollColumnHeader::canResize() { return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth); } -void LLScrollListColumn::setWidth(S32 width) -{ - if (!mDynamicWidth && mRelWidth <= 0.f) - { - mParentCtrl->updateStaticColumnWidth(this, width); - } - mWidth = width; -} - // Default constructor LLScrollListColumn::LLScrollListColumn() : mName(), mSortingColumn(), - mSortAscending(TRUE), + mSortDirection(ASCENDING), mLabel(), mWidth(-1), mRelWidth(-1.0), @@ -4246,10 +4413,13 @@ LLScrollListColumn::LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent) { mSortingColumn = sd.get("sort").asString(); } - mSortAscending = TRUE; if (sd.has("sort_ascending")) { - mSortAscending = sd.get("sort_ascending").asBoolean(); + mSortDirection = sd.get("sort_ascending").asBoolean() ? ASCENDING : DESCENDING; + } + else + { + mSortDirection = ASCENDING; } mLabel = sd.get("label").asString(); if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0) @@ -4266,7 +4436,6 @@ LLScrollListColumn::LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent) } else { - setWidth(sd.get("width").asInteger()); } @@ -4280,3 +4449,12 @@ LLScrollListColumn::LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent) } } + +void LLScrollListColumn::setWidth(S32 width) +{ + if (!mDynamicWidth && mRelWidth <= 0.f) + { + mParentCtrl->updateStaticColumnWidth(this, width); + } + mWidth = width; +} diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 4060c1466..30a8aba11 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -51,6 +51,7 @@ #include "lldate.h" // #include "lllineeditor.h" +#include // /* @@ -69,13 +70,13 @@ public: virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const = 0; // truncate to given width, if possible virtual S32 getWidth() const {return mWidth;} virtual S32 getContentWidth() const { return 0; } - virtual S32 getHeight() const = 0; + virtual S32 getHeight() const { return 0; } virtual const LLSD getValue() const { return LLStringUtil::null; } virtual void setValue(const LLSD& value) { } virtual BOOL getVisible() const { return TRUE; } virtual void setWidth(S32 width) { mWidth = width; } virtual void highlightText(S32 offset, S32 num_chars) {} - virtual BOOL isText() const = 0; + virtual BOOL isText() const { return FALSE; } virtual void setColor(const LLColor4&) {} virtual void onCommit() {}; @@ -86,19 +87,6 @@ private: S32 mWidth; }; -/* - * Draws a horizontal line. - */ -class LLScrollListSeparator : public LLScrollListCell -{ -public: - LLScrollListSeparator(S32 width); - virtual ~LLScrollListSeparator() {}; - virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const; // truncate to given width, if possible - virtual S32 getHeight() const; - virtual BOOL isText() const { return FALSE; } -}; - /* * Cell displaying a text label. */ @@ -108,22 +96,27 @@ public: LLScrollListText( const std::string& text, const LLFontGL* font, S32 width = 0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE); /*virtual*/ ~LLScrollListText(); - virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const; - virtual S32 getContentWidth() const; - virtual S32 getHeight() const; - virtual void setValue(const LLSD& value); - virtual const LLSD getValue() const; - virtual BOOL getVisible() const; - virtual void highlightText(S32 offset, S32 num_chars); + /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const; + /*virtual*/ S32 getContentWidth() const; + /*virtual*/ S32 getHeight() const; + /*virtual*/ void setValue(const LLSD& value); + /*virtual*/ const LLSD getValue() const; + /*virtual*/ BOOL getVisible() const; + /*virtual*/ void highlightText(S32 offset, S32 num_chars); - virtual void setColor(const LLColor4&); - virtual BOOL isText() const; + /*virtual*/ void setColor(const LLColor4&); + /*virtual*/ BOOL isText() const; + + S32 getTextWidth() const { return mTextWidth;} + void setTextWidth(S32 value) { mTextWidth = value;} + virtual void setWidth(S32 width) { LLScrollListCell::setWidth(width); mTextWidth = width; } void setText(const LLStringExplicit& text); - void setFontStyle(const U8 font_style) { mFontStyle = font_style; } + void setFontStyle(const U8 font_style); private: LLUIString mText; + S32 mTextWidth; const LLFontGL* mFont; LLColor4 mColor; U8 mUseColor; @@ -138,18 +131,6 @@ private: static U32 sCount; }; - -class LLScrollListDate : public LLScrollListText -{ -public: - LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width=0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE); - virtual void setValue(const LLSD& value); - virtual const LLSD getValue() const; - -private: - LLDate mDate; -}; - /* * Cell displaying an image. */ @@ -159,24 +140,22 @@ public: LLScrollListIcon( LLUIImagePtr icon, S32 width = 0); LLScrollListIcon(const LLSD& value, S32 width = 0); /*virtual*/ ~LLScrollListIcon(); - virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const; - virtual S32 getWidth() const; - virtual S32 getHeight() const { return mIcon ? mIcon->getHeight() : 0; } - virtual const LLSD getValue() const { return mIcon.isNull() ? LLStringUtil::null : mIcon->getName(); } - virtual void setColor(const LLColor4&); - virtual BOOL isText()const { return FALSE; } - virtual void setValue(const LLSD& value); + /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const; + /*virtual*/ S32 getWidth() const; + /*virtual*/ S32 getHeight() const; + /*virtual*/ const LLSD getValue() const; + /*virtual*/ void setColor(const LLColor4&); + /*virtual*/ void setValue(const LLSD& value); // - void setClickCallback(BOOL (*callback)(void*), void* user_data); + void setClickCallback(boost::function cb); virtual BOOL handleClick(); // private: - LLUIImagePtr mIcon; + LLPointer mIcon; LLColor4 mColor; // - BOOL (*mCallback)(void*); - void* mUserData; + boost::function mCallback; // }; @@ -188,22 +167,33 @@ class LLScrollListCheck : public LLScrollListCell public: LLScrollListCheck( LLCheckBoxCtrl* check_box, S32 width = 0); /*virtual*/ ~LLScrollListCheck(); - virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const; - virtual S32 getHeight() const { return 0; } - virtual const LLSD getValue() const { return mCheckBox->getValue(); } - virtual void setValue(const LLSD& value) { mCheckBox->setValue(value); } - virtual void onCommit() { mCheckBox->onCommit(); } + /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const; + /*virtual*/ S32 getHeight() const { return 0; } + /*virtual*/ const LLSD getValue() const; + /*virtual*/ void setValue(const LLSD& value); + /*virtual*/ void onCommit(); - virtual BOOL handleClick(); - virtual void setEnabled(BOOL enable) { mCheckBox->setEnabled(enable); } + /*virtual*/ BOOL handleClick(); + /*virtual*/ void setEnabled(BOOL enable); LLCheckBoxCtrl* getCheckBox() { return mCheckBox; } - virtual BOOL isText() const { return FALSE; } private: LLCheckBoxCtrl* mCheckBox; }; + +class LLScrollListDate : public LLScrollListText +{ +public: + LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width=0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE); + virtual void setValue(const LLSD& value); + virtual const LLSD getValue() const; + +private: + LLDate mDate; +}; + // class LLScrollListLineEditor : public LLScrollListCell { @@ -228,43 +218,12 @@ private: }; // -/* - * A simple data class describing a column within a scroll list. - */ -class LLScrollListColumn +class LLScrollListColumn; +class LLScrollColumnHeader : public LLComboBox { public: - LLScrollListColumn(); - LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent); - - void setWidth(S32 width); - S32 getWidth() const { return mWidth; } - - // Public data is fine so long as this remains a simple struct-like data class. - // If it ever gets any smarter than that, these should all become private - // with protected or public accessor methods added as needed. -MG - std::string mName; - std::string mSortingColumn; - BOOL mSortAscending; - std::string mLabel; - F32 mRelWidth; - BOOL mDynamicWidth; - S32 mMaxContentWidth; - S32 mIndex; - LLScrollListCtrl* mParentCtrl; - class LLColumnHeader* mHeader; - LLFontGL::HAlign mFontAlignment; - -private: - S32 mWidth; - -}; - -class LLColumnHeader : public LLComboBox -{ -public: - LLColumnHeader(const std::string& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL *font = NULL); - ~LLColumnHeader(); + LLScrollColumnHeader(const std::string& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL *font = NULL); + ~LLScrollColumnHeader(); /*virtual*/ void draw(); /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); @@ -301,7 +260,44 @@ private: LLColor4 mImageOverlayColor; }; -class LLScrollListItem +/* + * A simple data class describing a column within a scroll list. + */ +class LLScrollListColumn +{ +public: + typedef enum e_sort_direction + { + DESCENDING, + ASCENDING + } ESortDirection; + LLScrollListColumn(); + LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent); + + void setWidth(S32 width); + S32 getWidth() const { return mWidth; } + + // Public data is fine so long as this remains a simple struct-like data class. + // If it ever gets any smarter than that, these should all become private + // with protected or public accessor methods added as needed. -MG + std::string mName; + std::string mSortingColumn; + ESortDirection mSortDirection; + std::string mLabel; + F32 mRelWidth; + BOOL mDynamicWidth; + S32 mMaxContentWidth; + S32 mIndex; + LLScrollListCtrl* mParentCtrl; + LLScrollColumnHeader* mHeader; + LLFontGL::HAlign mFontAlignment; + +private: + S32 mWidth; + +}; + +class LLScrollListItem : public LLHandleProvider { public: LLScrollListItem( BOOL enabled = TRUE, void* userdata = NULL, const LLUUID& uuid = LLUUID::null ) @@ -314,7 +310,7 @@ public: void setSelected( BOOL b ) { mSelected = b; } BOOL getSelected() const { return mSelected; } - void setEnabled( BOOL b ); + void setEnabled( BOOL b ) { mEnabled = b; } BOOL getEnabled() const { return mEnabled; } void setUserdata( void* userdata ) { mUserdata = userdata; } @@ -323,9 +319,12 @@ public: void setToolTip(const std::string tool_tip) { mToolTip=tool_tip; } std::string getToolTip() { return mToolTip; } - LLUUID getUUID() const { return mItemValue.asUUID(); } + virtual LLUUID getUUID() const { return mItemValue.asUUID(); } LLSD getValue() const { return mItemValue; } + void setRect(LLRect rect) { mRectangle = rect; } + LLRect getRect() const { return mRectangle; } + // If width = 0, just use the width of the text. Otherwise override with // specified width in pixels. void addColumn( const std::string& text, const LLFontGL* font, S32 width = 0 , U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, BOOL visible = TRUE) @@ -341,9 +340,9 @@ public: void setColumn( S32 column, LLScrollListCell *cell ); - S32 getNumColumns() const { return mColumns.size(); } + S32 getNumColumns() const; - LLScrollListCell *getColumn(const S32 i) const { if (0 <= i && i < (S32)mColumns.size()) { return mColumns[i]; } return NULL; } + LLScrollListCell *getColumn(const S32 i) const; std::string getContentsCSV() const; @@ -356,42 +355,45 @@ private: LLSD mItemValue; std::string mToolTip; std::vector mColumns; -}; - -/* - * A graphical control representing a scrollable table. - * Cells in the table can be simple text or more complicated things - * such as icons or even interactive elements like check boxes. - */ -class LLScrollListItemComment : public LLScrollListItem -{ -public: - LLScrollListItemComment(const std::string& comment_string, const LLColor4& color); - - /*virtual*/ void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding); -private: - LLColor4 mColor; -}; - -class LLScrollListItemSeparator : public LLScrollListItem -{ -public: - LLScrollListItemSeparator(); - - /*virtual*/ void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding); + LLRect mRectangle; }; class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, public LLCtrlListInterface, public LLCtrlScrollInterface { public: + typedef boost::function callback_t; + + template struct maximum + { + typedef T result_type; + + template + T operator()(InputIterator first, InputIterator last) const + { + // If there are no slots to call, just return the + // default-constructed value + if(first == last ) return T(); + T max_value = *first++; + while (first != last) { + if (max_value < *first) + max_value = *first; + ++first; + } + + return max_value; + } + }; + + + typedef boost::signals2::signal > sort_signal_t; LLScrollListCtrl( const std::string& name, const LLRect& rect, void (*commit_callback)(LLUICtrl*, void*), void* callback_userdata, BOOL allow_multiple_selection, - BOOL draw_border = TRUE); + BOOL draw_border = TRUE, bool draw_heading = false); virtual ~LLScrollListCtrl(); @@ -415,6 +417,7 @@ public: virtual void setColumnLabel(const std::string& column, const std::string& label); virtual LLScrollListColumn* getColumn(S32 index); + virtual LLScrollListColumn* getColumn(const std::string& name); virtual S32 getNumColumns() const { return mColumnsIndexed.size(); } // Adds a single element, from an array of: @@ -465,10 +468,17 @@ public: void deleteSelectedItems(); void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change - void highlightNthItem( S32 index ); - void setDoubleClickCallback( void (*cb)(void*) ) { mOnDoubleClickCallback = cb; } - void setMaximumSelectCallback( void (*cb)(void*) ) { mOnMaximumSelectCallback = cb; } - void setSortChangedCallback( void (*cb)(void*) ) { mOnSortChangedCallback = cb; } + void clearHighlightedItems(); + + virtual void mouseOverHighlightNthItem( S32 index ); + + S32 getHighlightedItemInx() const { return mHighlightedItem; } + + void setDoubleClickCallback( callback_t cb ) { mOnDoubleClickCallback = cb; } + void setMaximumSelectCallback( callback_t cb ) { mOnMaximumSelectCallback = cb; } + void setSortChangedCallback( callback_t cb ) { mOnSortChangedCallback = cb; } + // Convenience function; *TODO: replace with setter above + boost::bind() in calling code + void setDoubleClickCallback( boost::function cb, void* userdata) { mOnDoubleClickCallback = boost::bind(cb, userdata); } void swapWithNext(S32 index); void swapWithPrevious(S32 index); @@ -480,7 +490,7 @@ public: S32 getItemIndex( LLScrollListItem* item ) const; S32 getItemIndex( const LLUUID& item_id ) const; - LLScrollListItem* addCommentText( const std::string& comment_text, EAddPosition pos = ADD_BOTTOM); + void setCommentText( const std::string& comment_text); LLScrollListItem* addSeparator(EAddPosition pos); // "Simple" interface: use this when you're creating a list that contains only unique strings, only @@ -491,6 +501,7 @@ public: BOOL selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE ); // FALSE if item not found BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE); BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE); + LLScrollListItem* getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); const std::string getSelectedItemLabel(S32 column = 0) const; LLSD getSelectedValue(); @@ -503,7 +514,8 @@ public: LLScrollListItem* getFirstSelected() const; virtual S32 getFirstSelectedIndex() const; std::vector getAllSelected() const; - LLDynamicArray getSelectedIDs(); + uuid_vec_t getSelectedIDs(); //Helper. Much like getAllSelected, but just provides a LLUUID vec + S32 getNumSelected() const; LLScrollListItem* getLastSelectedItem() const { return mLastSelected; } // iterate over all items @@ -578,17 +590,26 @@ public: LLRect getItemListRect() { return mItemListRect; } + /// Returns rect, in local coords, of a given row/column + LLRect getCellRect(S32 row_index, S32 column_index); + // Used "internally" by the scroll bar. static void onScrollChange( S32 new_pos, LLScrollbar* src, void* userdata ); static void onClickColumn(void *userdata); - void updateColumns(); - void calcColumnWidths(); + virtual void updateColumns(); + S32 calcMaxContentWidth(); + bool updateColumnWidths(); S32 getMaxContentWidth() { return mMaxContentWidth; } void setDisplayHeading(BOOL display); void setHeadingHeight(S32 heading_height); + /** + * Sets max visible lines without scroolbar, if this value equals to 0, + * then display all items. + */ + void setPageLines(S32 page_lines ); void setCollapseEmptyColumns(BOOL collapse); LLScrollListItem* hitItem(S32 x,S32 y); @@ -610,17 +631,37 @@ public: std::string getSortColumnName(); BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; } - BOOL needsSorting(); + BOOL hasSortOrder() const; + void clearSortOrder(); - S32 selectMultiple( LLDynamicArray ids ); - void sortItems(); + S32 selectMultiple( uuid_vec_t ids ); + // conceptually const, but mutates mItemList + void updateSort() const; // sorts a list without affecting the permanent sort order (so further list insertions can be unsorted, for example) void sortOnce(S32 column, BOOL ascending); // manually call this whenever editing list items in place to flag need for resorting - void setSorted(BOOL sorted) { mSorted = sorted; } + void setNeedsSort(bool val = true) { mSorted = !val; } + void setNeedsSortColumn(S32 col) + { + if(!isSorted())return; + for(std::vector >::iterator it=mSortColumns.begin();it!=mSortColumns.end();++it) + { + if((*it).first == col) + { + setNeedsSort(); + break; + } + } + } void dirtyColumns(); // some operation has potentially affected column layout or ordering + boost::signals2::connection setSortCallback(sort_signal_t::slot_type cb ) + { + if (!mSortCallback) mSortCallback = new sort_signal_t(); + return mSortCallback->connect(cb); + } + protected: // "Full" interface: use this when you're creating a list that has one or more of the following: // * contains icons @@ -642,11 +683,13 @@ protected: typedef std::deque item_list; item_list& getItemList() { return mItemList; } + void updateLineHeight(); + private: void selectPrevItem(BOOL extend_selection); void selectNextItem(BOOL extend_selection); void drawItems(); - void updateLineHeight(); + void updateLineHeightInsert(LLScrollListItem* item); void reportInvalidInput(); BOOL isRepeatedChars(const LLWString& string) const; @@ -654,10 +697,7 @@ private: void deselectItem(LLScrollListItem* itemp); void commitIfChanged(); BOOL setSort(S32 column, BOOL ascending); - - - S32 mCurIndex; // For get[First/Next]Data - S32 mCurSelectedIndex; // For get[First/Next]Selected + S32 getLinesPerPage(); S32 mLineHeight; // the max height of a single line S32 mScrollLines; // how many lines we've scrolled down @@ -665,18 +705,19 @@ private: S32 mHeadingHeight; // the height of the column header buttons, if visible U32 mMaxSelectable; LLScrollbar* mScrollbar; - BOOL mAllowMultipleSelection; - BOOL mAllowKeyboardMovement; - BOOL mCommitOnKeyboardMovement; - BOOL mCommitOnSelectionChange; - BOOL mSelectionChanged; - BOOL mNeedsScroll; - BOOL mMouseWheelOpaque; - BOOL mCanSelect; - BOOL mDisplayColumnHeaders; - BOOL mColumnsDirty; + bool mAllowMultipleSelection; + bool mAllowKeyboardMovement; + bool mCommitOnKeyboardMovement; + bool mCommitOnSelectionChange; + bool mSelectionChanged; + bool mNeedsScroll; + bool mMouseWheelOpaque; + bool mCanSelect; + bool mDisplayColumnHeaders; + bool mColumnsDirty; + bool mColumnWidthsDirty; - item_list mItemList; + mutable item_list mItemList; LLScrollListItem *mLastSelected; @@ -700,12 +741,14 @@ private: LLColor4 mDefaultListTextColor; S32 mBorderThickness; - void (*mOnDoubleClickCallback)(void* userdata); - void (*mOnMaximumSelectCallback)(void* userdata ); - void (*mOnSortChangedCallback)(void* userdata); + callback_t mOnDoubleClickCallback; + callback_t mOnMaximumSelectCallback; + callback_t mOnSortChangedCallback; S32 mHighlightedItem; class LLViewBorder* mBorder; + + LLView *mCommentTextView; LLWString mSearchString; LLFrameTimer mSearchTimer; @@ -715,12 +758,12 @@ private: S32 mTotalStaticColumnWidth; S32 mTotalColumnPadding; - BOOL mSorted; + mutable bool mSorted; - typedef std::map column_map_t; + typedef std::map column_map_t; column_map_t mColumns; - BOOL mDirty; + bool mDirty; S32 mOriginalSelection; typedef std::vector ordered_columns_t; @@ -729,8 +772,7 @@ private: typedef std::pair sort_column_t; std::vector mSortColumns; - // HACK: Did we draw one selected item this frame? - BOOL mDrewSelected; + sort_signal_t* mSortCallback; }; // end class LLScrollListCtrl diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index c5cf582e5..e34d1a852 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -201,15 +201,13 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled ) gGL.begin( LLRender::LINES ); // Verticals - gGL.vertex2i(left + 1, top); - gGL.vertex2i(left + 1, bottom); + gGL.vertex2i(left + 1, top + 1); + gGL.vertex2i(left + 1, bottom + 1); - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); + gGL.vertex2i(right + 1, bottom + 1); + gGL.vertex2i(right + 1, top + 1); // Horizontals - top--; - right--; gGL.vertex2i(left, bottom); gGL.vertex2i(right, bottom); @@ -219,8 +217,6 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled ) } else { - top--; - right--; gGL.begin( LLRender::LINE_STRIP ); gGL.vertex2i(left, top); gGL.vertex2i(left, bottom); diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 23d4290b5..58cb3e5fa 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -527,10 +527,6 @@ BOOL LLUICtrl::getTentative() const return mTentative; } -// virtual -void LLUICtrl::setDoubleClickCallback( void (*cb)(void*) ) -{ -} // virtual void LLUICtrl::setColor(const LLColor4& color) diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index c8f9b4b85..69841a042 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -37,11 +37,13 @@ #include "llview.h" #include "llrect.h" #include "llsd.h" +#include +#include #include "llviewmodel.h" // *TODO move dependency to .cpp file class LLUICtrl -: public LLView +: public LLView, public boost::signals2::trackable { public: typedef boost::function commit_callback_t; @@ -103,7 +105,6 @@ public: // Default to no-op: virtual void onTabInto(); virtual void clear(); - virtual void setDoubleClickCallback( void (*cb)(void*) ); virtual void setColor(const LLColor4& color); virtual void setAlpha(F32 alpha); virtual void setMinValue(LLSD min_value); diff --git a/indra/llui/llview.h b/indra/llui/llview.h index a742b2c56..233e56bbc 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -132,8 +132,8 @@ public: class LLView : public LLMouseHandler, // handles mouse events public LLFocusableElement, // handles keyboard events - public LLMortician // lazy deletion - //public LLHandleProvider // passes out weak references to self + public LLMortician, // lazy deletion + public LLHandleProvider // passes out weak references to self { public: struct Follows : public LLInitParam::ChoiceBlock @@ -344,8 +344,6 @@ public: void popVisible() { setVisible(mLastVisible); } BOOL getLastVisible() const { return mLastVisible; } - LLHandle getHandle() { mHandle.bind(this); return mHandle; } - U32 getFollows() const { return mReshapeFlags; } BOOL followsLeft() const { return mReshapeFlags & FOLLOWS_LEFT; } BOOL followsRight() const { return mReshapeFlags & FOLLOWS_RIGHT; } @@ -679,7 +677,6 @@ private: BOOL mIsFocusRoot; BOOL mUseBoundingRect; // hit test against bounding rectangle that includes all child elements - LLRootHandle mHandle; BOOL mLastVisible; S32 mNextInsertionOrdinal; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 53ba137d0..dd9fbeb00 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -866,7 +866,9 @@ BOOL LLWindowWin32::setPosition(const LLCoordScreen position) return FALSE; } getSize(&size); + moveWindow(position, size); + return TRUE; } @@ -881,6 +883,7 @@ BOOL LLWindowWin32::setSize(const LLCoordScreen size) } moveWindow(position, size); + return TRUE; } @@ -1655,6 +1658,23 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre // THIS CAUSES DEV-15484 and DEV-15949 //ShowWindow(mWindowHandle, SW_RESTORE); + + // Singu note: Attempt at fixing this in a different way. Keep an eye out for regression. DEV-15484 showed graphical corruption, especially on impostors. + LLCoordScreen old_pos; + LLCoordScreen old_size; + getSize(&old_size); + getPosition(&old_pos); + if(position != old_pos || size != old_size) + { + WINDOWPLACEMENT placement; + placement.length = sizeof(WINDOWPLACEMENT); + if(GetWindowPlacement(mWindowHandle, &placement)) + { + placement.showCmd = SW_NORMAL; + SetWindowPlacement(mWindowHandle, &placement); + } + } + // NOW we can call MoveWindow MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE); } diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 86dd63f37..26a170dd0 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -1513,7 +1513,6 @@ DECL_LLCC(S32, (S32)-666); DECL_LLCC(F32, (F32)-666.666); DECL_LLCC(bool, true); DECL_LLCC(BOOL, FALSE); -static LLCachedControl mySetting_string("TestCachedControlstring", "Default String Value"); DECL_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f)); DECL_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f)); DECL_LLCC(LLRect, LLRect(0, 0, 100, 500)); @@ -1523,10 +1522,11 @@ DECL_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f)); LLSD test_llsd = LLSD()["testing1"] = LLSD()["testing2"]; DECL_LLCC(LLSD, test_llsd); -static LLCachedControl test_BrowserHomePage("BrowserHomePage", "hahahahahha", "Not the real comment"); - void test_cached_control() { + static const LLCachedControl mySetting_string("TestCachedControlstring", "Default String Value"); + static const LLCachedControl test_BrowserHomePage("BrowserHomePage", "hahahahahha", "Not the real comment"); + #define TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl; \ mySetting_##T = V;\ if((T)mySetting_##T != V) llerrs << "Fail "#T << "Pass # 2" << llendl; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3ef620b2b..4af7e8632 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -17,7 +17,7 @@ endif(FMOD) include(OPENAL) include(FindOpenGL) include(Hunspell) -#include(JsonCpp) +include(JsonCpp) include(LLAddBuildTest) include(LLAudio) include(LLCharacter) @@ -196,8 +196,9 @@ set(viewer_SOURCE_FILES llfloaterevent.cpp llfloaterexploreanimations.cpp llfloaterexploresounds.cpp - llfloaterfriends.cpp + llfloaterfeed.cpp llfloaterfonttest.cpp + llfloaterfriends.cpp llfloatergesture.cpp llfloatergodtools.cpp llfloatergroupinfo.cpp @@ -301,6 +302,7 @@ set(viewer_SOURCE_FILES lllogchat.cpp llloginhandler.cpp llmainlooprepeater.cpp + llmakeoutfitdialog.cpp llmanip.cpp llmaniprotate.cpp llmanipscale.cpp @@ -312,6 +314,7 @@ set(viewer_SOURCE_FILES llmediaremotectrl.cpp llmemoryview.cpp llmenucommands.cpp + llmenuoptionpathfindingrebakenavmesh.cpp llmeshrepository.cpp llmimetypes.cpp llmorphview.cpp @@ -366,10 +369,10 @@ set(viewer_SOURCE_FILES llpanelnetwork.cpp llpanelobject.cpp llpanelobjectinventory.cpp - llpanelpathfindingrebakenavmesh.cpp llpanelpermissions.cpp llpanelpick.cpp llpanelplace.cpp + llpanelprofile.cpp llpanelskins.cpp llpanelvolume.cpp llpanelweb.cpp @@ -538,6 +541,7 @@ set(viewer_SOURCE_FILES llwearablelist.cpp llwearabletype.cpp llweb.cpp + llwebprofile.cpp llwind.cpp llwlanimator.cpp llwldaycycle.cpp @@ -546,6 +550,7 @@ set(viewer_SOURCE_FILES llwlparamset.cpp llworld.cpp llworldmap.cpp + llworldmapmessage.cpp llworldmipmap.cpp llworldmapview.cpp llxmlrpcresponder.cpp @@ -700,6 +705,7 @@ set(viewer_HEADER_FILES llfloaterexploreanimations.h llfloaterexploresounds.h llfloaterevent.h + llfloaterfeed.h llfloaterfonttest.h llfloaterfriends.h llfloatergesture.h @@ -805,6 +811,7 @@ set(viewer_HEADER_FILES lllogchat.h llloginhandler.h llmainlooprepeater.h + llmakeoutfitdialog.h llmanip.h llmaniprotate.h llmanipscale.h @@ -815,6 +822,7 @@ set(viewer_HEADER_FILES llmediactrl.h llmediaremotectrl.h llmemoryview.h + llmenuoptionpathfindingrebakenavmesh.h llmenucommands.h llmeshrepository.h llmimetypes.h @@ -870,10 +878,10 @@ set(viewer_HEADER_FILES llpanelnetwork.h llpanelobject.h llpanelobjectinventory.h - llpanelpathfindingrebakenavmesh.h llpanelpermissions.h llpanelpick.h llpanelplace.h + llpanelprofile.h llpanelskins.h llpanelvolume.h llpanelweb.h @@ -1047,6 +1055,7 @@ set(viewer_HEADER_FILES llwearablelist.h llwearabletype.h llweb.h + llwebprofile.h llwind.h llwindebug.h llwlanimator.h @@ -1056,6 +1065,7 @@ set(viewer_HEADER_FILES llwlparamset.h llworld.h llworldmap.h + llworldmapmessage.h llworldmipmap.h llworldmapview.h llxmlrpcresponder.h diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index dd50567cd..0cc3d6693 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -701,7 +701,23 @@ CHARACTER_MAX_TURN_RADIUS TODO: add documentation # --- OpenSim and Aurora-Sim constants Below --- # OpenSim Constants (\OpenSim\Region\ScriptEngine\Shared\Api\Runtime\LSL_Constants.cs) # Constants for cmWindlight (\OpenSim\Region\ScriptEngine\Shared\Api\Runtime\CM_Constants.cs) -CHANGED_ANIMATION OpenSim change event animation change detection. +CHANGED_ANIMATION OpenSim change event animation change detection. +CAMERA_FOCUS_OFFSET_X OpenSim enhancement for llSetCameraParams(), adjusts the camera focus x position relative to the target. (float) +CAMERA_FOCUS_OFFSET_Y OpenSim enhancement for llSetCameraParams(), adjusts the camera focus y position relative to the target. (float) +CAMERA_FOCUS_OFFSET_Z OpenSim enhancement for llSetCameraParams(), adjusts the camera focus z position relative to the target. (float) +CAMERA_POSITION_X OpenSim enhancement for llSetCameraParams(), sets camera x position in region coordinates. (float) +CAMERA_POSITION_Y OpenSim enhancement for llSetCameraParams(), sets camera y position in region coordinates. (float) +CAMERA_POSITION_Z OpenSim enhancement for llSetCameraParams(), sets camera z position in region coordinates. (float) +CAMERA_FOCUS_X OpenSim enhancement for llSetCameraParams(), sets camera x focus (target position) in region coordinates. (float) +CAMERA_FOCUS_Y OpenSim enhancement for llSetCameraParams(), sets camera y focus (target position) in region coordinates. (float) +CAMERA_FOCUS_Z OpenSim enhancement for llSetCameraParams(), sets camera z focus (target position) in region coordinates. (float) +OS_LISTEN_REGEX_NAME Value 0x1, process name parameter as regex +OS_LISTEN_REGEX_MESSAGE Value 0x2, process name parameter as regex +OS_ATTACH_MSG_ALL Used with osMessageAttachements +OS_ATTACH_MSG_INVERT_POINTS Used with osMessageAttachements +OS_ATTACH_MSG_OBJECT_CREATOR Used with osMessageAttachements +OS_ATTACH_MSG_SCRIPT_CREATOR Used with osMessageAttachements +PARCEL_DETAILS_CLAIMDATE Used with osSetParcelDetails # osGetRegionStats STATS_TIME_DILATION returned value from osGetRegionStats(), 1st of 21 items in returned list. STATS_SIM_FPS returned value from osGetRegionStats(), 2nd of 21 items in returned list. @@ -725,14 +741,15 @@ STATS_PENDING_UPLOADS returned value from osGetRegionStats(), 19th of 21 items STATS_ACTIVE_SCRIPTS returned value from osGetRegionStats(), 20th of 21 items in returned list. STATS_SCRIPT_LPS returned value from osGetRegionStats(), 21st of 21 items in returned list. # OpenSim NPC -OS_NPC_FLY used by osNPC. -OS_NPC_NO_FLY used by osNPC. -OS_NPC_LAND_AT_TARGET used by osNPC. -OS_NPC_SIT_NOW used by osNPC. -OS_NPC_CREATOR_OWNED used by osNPC. -OS_NPC_NOT_OWNED used by osNPC. -OS_NPC_SENSE_AS_AGENT used by osNPC. -OS_NPC_RUNNING used by osNPC. +OS_NPC used by osNPC. Value 0x01000000 +OS_NPC_FLY used by osNPC. Value 0 +OS_NPC_NO_FLY used by osNPC. Value 1 +OS_NPC_LAND_AT_TARGET used by osNPC. Value 2 +OS_NPC_SIT_NOW used by osNPC. Value 0 +OS_NPC_CREATOR_OWNED used by osNPC. Value 0x1 +OS_NPC_NOT_OWNED used by osNPC. Value 0x2 +OS_NPC_SENSE_AS_AGENT used by osNPC. Value 0x4 +OS_NPC_RUNNING used by osNPC. Value 4 # Windlight/Lightshare WL_WATER_COLOR Windlight Water Colour WL_WATER_FOG_DENSITY_EXPONENT Windlight Water Fog Density Exponent @@ -771,7 +788,15 @@ WL_CLOUD_SCROLL_Y Windlight Cloud Scroll Y WL_CLOUD_SCROLL_Y_LOCK Windlight Cloud Scroll Y Lock WL_CLOUD_SCROLL_X_LOCK Windlight Cloud Scroll X Lock WL_DRAW_CLASSIC_CLOUDS Windlight Draw Classic Clouds -# Aurora-Sim Constants (\Aurora\AuroraDotNetEngine\APIs\AA_Constants.cs) --> +# WL Constants added unique to Aurora-Sim +WL_OK Value -1 +WL_ERROR Value -2 +WL_ERROR_NO_SCENE_SET Value -3 +WL_ERROR_SCENE_MUST_BE_STATIC Value -4 +WL_ERROR_SCENE_MUST_NOT_BE_STATIC Value -5 +WL_ERROR_BAD_SETTING Value -6 +WL_ERROR_NO_PRESET_FOUND Value -7 +# Aurora-Sim Constants (\Aurora\AuroraDotNetEngine\APIs\AA_Constants.cs) ENABLE_GRAVITY enable_gravity. GRAVITY_FORCE_X gravity_force_x. GRAVITY_FORCE_Y gravity_force_y. diff --git a/indra/newview/app_settings/lsl_functions_os.xml b/indra/newview/app_settings/lsl_functions_os.xml index 05e1c94f8..f7f0ab1e8 100644 --- a/indra/newview/app_settings/lsl_functions_os.xml +++ b/indra/newview/app_settings/lsl_functions_os.xml @@ -247,6 +247,46 @@ osNpcWhisper + osForceAttachToAvatar + + osForceAttachToAvatarFromInventory + + osForceAttachToOtherAvatarFromInventory + + osNpcTouch + + osNpcTouch + + osIsUUID + + osMin + + osMax + + osMax + + osGetRezzingObject + + osGetHealth + + osSetContentType + + osGetNumberOfAttachments + + osMessageAttachments + + osDropAttachment + + osDropAttachmentAt + + osForceDropAttachment + + osForceDropAttachmentAt + + osListenRegex + + osRegexIsMatch + osReturnObject @@ -334,6 +374,24 @@ aaGetIsInfiniteRegion + aaSetCharacterStat + + aaAllRegionInstanceSay + + aaWindlightGetDayCycle + + aaWindlightAddDayCycleFrame + + aaWindlightRemoveDayCycleFrame + + aaWindlightSetScene + + aaWindlightGetScene + + aaWindlightGetSceneIsStatic + + aaWindlightGetSceneDayCycleKeyFrameCount + botGetWaitingTime @@ -370,4 +428,4 @@ botRemoveBotsWithTag - \ No newline at end of file + diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6bae8e6ed..2850f52ee 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9,6 +9,17 @@ settings_rlv.xml + UseNewTargetOmegaCode + + Comment + Enable target omega code from Viewer 3.4 + Persist + 1 + Type + Boolean + Value + 0 + SGIgnoreSimulatorCameraConstraints Comment @@ -692,11 +703,55 @@ Boolean Value 0 - + + LiruAddNotReplace + + Comment + Add clothing and attachments instead of having them replace the currently worn or attached item at their destination. + Persist + 1 + Type + Boolean + Value + 0 + + LiruContinueFlyingOnUnsit + + Comment + Fly after standing up, if you were flying when you sat down + Persist + 1 + Type + Boolean + Value + 0 + + LiruFlyAfterTeleport + + Comment + Fly after teleports + Persist + 1 + Type + Boolean + Value + 0 + + LiruNoTransactionClutter + + Comment + Use notifytips for transactions instead of notifys, this way they do not collect in the top right of the screen. + Persist + 1 + Type + Boolean + Value + 0 + LiruSensibleARC Comment - Use the old-style way to calculate Avatar Render Cost. + Use the old-style way to calculate Avatar Render Cost. Found in Advanced->Rendering->Info Displays Persist 1 @@ -704,7 +759,29 @@ Found in Advanced->Rendering->Info Displays Boolean Value 1 - + + OtherChatsTornOff + + Comment + When true, chats other than local chat open torn off of the Communicate window. + Persist + 1 + Type + Boolean + Value + 0 + + OtherChatsTornOffAndMinimized + + Comment + When this and OtherChatsTornOff are true, new chats open torn off and minimized. + Persist + 1 + Type + Boolean + Value + 0 + MarketImporterUpdateFreq Comment @@ -799,6 +876,28 @@ This should be as low as possible, but too low may break functionality Value 1 + AnnounceSnapshots + + Comment + Announce if someone nearby has taken a snapshot in chat (Won't work on people who hide/quiet snapshots) + Persist + 1 + Type + Boolean + Value + 0 + + AnnounceStreamMetadata + + Comment + Announce the metadata of the track playing, in chat, during streams. + Persist + 1 + Type + Boolean + Value + 0 + InventorySortOrder Comment @@ -865,6 +964,17 @@ This should be as low as possible, but too low may break functionality Value 0 + TurnAroundWhenWalkingBackwards + + Comment + Turn your avatar around to face the camera while walking backwards. + Persist + 1 + Type + Boolean + Value + 1 + EmeraldBoobMass Comment @@ -5758,6 +5868,17 @@ This should be as low as possible, but too low may break functionality Value 0 + SecondsInLog + + Comment + TRUE to add seconds to timestamps for Log + Persist + 1 + Type + Boolean + Value + 0 + FloaterAboutRect Comment @@ -6274,6 +6395,149 @@ This should be as low as possible, but too low may break functionality 0 + RadarColumnMarkWidth + + Comment + Width for radar's mark column + Persist + 1 + Type + S32 + Value + 12 + + RadarColumnPositionWidth + + Comment + Width for radar's position column + Persist + 1 + Type + S32 + Value + 60 + + RadarColumnAltitudeWidth + + Comment + Width for radar's altitude column + Persist + 1 + Type + S32 + Value + 48 + + RadarColumnActivityWidth + + Comment + Width for radar's activity column + Persist + 1 + Type + S32 + Value + 24 + + RadarColumnAgeWidth + + Comment + Width for radar's age column + Persist + 1 + Type + S32 + Value + 45 + + RadarColumnTimeWidth + + Comment + Width for radar's time column + Persist + 1 + Type + S32 + Value + 52 + + RadarColumnMarkHidden + + Comment + Hide radar's mark column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnPositionHidden + + Comment + Hide radar's position column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnAltitudeHidden + + Comment + Hide radar's altitude column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnActivityHidden + + Comment + Hide radar's activity column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnAgeHidden + + Comment + Hide radar's age column + Persist + 1 + Type + Boolean + Value + 0 + + RadarColumnTimeHidden + + Comment + Hide radar's time column + Persist + 1 + Type + Boolean + Value + 1 + + RadarColumnClientHidden + + Comment + Hide radar's client column + Persist + 1 + Type + Boolean + Value + 0 + RadarKeepOpen Comment @@ -6340,6 +6604,28 @@ This should be as low as possible, but too low may break functionality Value 1 + RadarAlertAge + + Comment + Whether the radar emits chat alerts for avatars younger than AvatarAgeAlertDays appearing. + Persist + 1 + Type + Boolean + Value + 0 + + AvatarAgeAlertDays + + Comment + Age below which avatars will be made known to you + Persist + 1 + Type + U32 + Value + 3 + RadarChatAlerts Comment @@ -6490,6 +6776,22 @@ This should be as low as possible, but too low may break functionality 0 + FloaterOutboxRect + + Comment + Rectangle for merchant outbox window + Persist + 1 + Type + Rect + Value + + 0 + 342 + 310 + 52 + + FloaterPayRectB Comment @@ -6570,6 +6872,38 @@ This should be as low as possible, but too low may break functionality 400 + FloaterSnapshotFeedRect + + Comment + Rectangle for snapshot feed window + Persist + 1 + Type + Rect + Value + + 0 + 200 + 200 + 400 + + + FloaterSnapshotPostcardRect + + Comment + Rectangle for snapshot postcard window + Persist + 1 + Type + Rect + Value + + 0 + 346 + 450 + 400 + + FloaterSoundsRect Comment @@ -7414,7 +7748,7 @@ This should be as low as possible, but too low may break functionality WebProfileURL Comment - URL for Web Profiles + URL for SL Web Profiles Persist 0 Type @@ -7422,6 +7756,17 @@ This should be as low as possible, but too low may break functionality Value https://my.secondlife.com/[AGENT_NAME] + WebProfileNonProductionURL + + Comment + URL for SL Web Profiles on Non-Production grids + Persist + 0 + Type + String + Value + https://my-demo.secondlife.com/[AGENT_NAME] + HighResSnapshot Comment @@ -7866,17 +8211,6 @@ This should be as low as possible, but too low may break functionality Value 64 - KeepAspectForSnapshot - - Comment - Use full window when taking snapshot, regardless of requested image size - Persist - 1 - Type - Boolean - Value - 1 - LandBrushSize Comment @@ -8047,6 +8381,50 @@ This should be as low as possible, but too low may break functionality Value 0.0.0 + LastSnapshotToFeedAspect + + Comment + The aspect ratio spinner value for snapshots uploaded to my.secondlife.com + Persist + 0 + Type + F32 + Value + 1.33333 + + LastSnapshotToFeedHeight + + Comment + The height of the last my.secondlife.com feed snapshot, in px + Persist + 1 + Type + S32 + Value + 525 + + LastSnapshotToFeedWidth + + Comment + The width of the last my.secondlife.com feed snapshot, in px + Persist + 1 + Type + S32 + Value + 700 + + LastSnapshotToEmailAspect + + Comment + The aspect ratio spinner value for snapshots sent by email + Persist + 0 + Type + F32 + Value + 0 + LastSnapshotToEmailHeight Comment @@ -8069,6 +8447,17 @@ This should be as low as possible, but too low may break functionality Value 1024 + LastSnapshotToDiskAspect + + Comment + The aspect ratio spinner value for snapshots written to disk + Persist + 0 + Type + F32 + Value + 0 + LastSnapshotToDiskHeight Comment @@ -8091,6 +8480,17 @@ This should be as low as possible, but too low may break functionality Value 1024 + LastSnapshotToInventoryAspect + + Comment + The aspect ratio spinner value for snapshots uploaded to inventory + Persist + 0 + Type + F32 + Value + 0 + LastSnapshotToInventoryHeight Comment @@ -8124,6 +8524,17 @@ This should be as low as possible, but too low may break functionality Value 0 + SnapshotFeedAddLocation + + Comment + Include your location in your uploads to profile feed. + Persist + 1 + Type + Boolean + Value + 0 + LeftClickShowMenu Comment @@ -9894,17 +10305,6 @@ This should be as low as possible, but too low may break functionality 0 - SaveScriptsAsMono - - Comment - When set to TRUE, save scripts in inventory as Mono scripts instead of LSL2 - Persist - 1 - Type - Boolean - Value - 1 - PreviewSoundRect Comment @@ -10163,6 +10563,18 @@ This should be as low as possible, but too low may break functionality 128 + OctreeReserveNodeCapacity + + Comment + Default number of elements to pre-allocate for in a single octree node + Persist + 1 + Type + U32 + Value + 4 + + OctreeStaticObjectSizeFactor Comment @@ -10536,7 +10948,7 @@ This should be as low as possible, but too low may break functionality Type F32 Value - 500.0 + 1500.0 RenderSSAOMaxScale @@ -10547,7 +10959,7 @@ This should be as low as possible, but too low may break functionality Type U32 Value - 200 + 250 RenderSSAOFactor @@ -10558,19 +10970,19 @@ This should be as low as possible, but too low may break functionality Type F32 Value - 0.30 + 5.0 RenderSSAOEffect Comment - Multiplier for (1) value and (2) saturation (HSV definition), for areas which are totally occluded. Blends with original color for partly-occluded areas. (Third component is unused.) + Multiplier for (1) value for areas which are totally occluded. Blends with original color for partly-occluded areas. (Third component is unused.) Persist 1 Type Vector3 Value - 0.80 + 0.50 1.00 0.00 @@ -11157,7 +11569,7 @@ This should be as low as possible, but too low may break functionality Vector3 Value - 3.0 + 1.0 2.0 0.0 @@ -11172,7 +11584,7 @@ This should be as low as possible, but too low may break functionality Type F32 Value - 1.4 + 3.0 RenderShadowBlurSamples @@ -13388,6 +13800,28 @@ This should be as low as possible, but too low may break functionality Value 0 + SnapshotFeedLastAspect + + Comment + Take next feed snapshot at this aspect + Persist + 0 + Type + S32 + Value + 0 + + SnapshotFeedLastResolution + + Comment + Take next feed snapshot at this resolution + Persist + 1 + Type + S32 + Value + 0 + SnapshotFormat Comment @@ -13399,6 +13833,28 @@ This should be as low as possible, but too low may break functionality Value 0 + SnapshotLayerType + + Comment + Save snapshots in this format (0 = Colors, 1 = Depth) + Persist + 1 + Type + S32 + Value + 0 + + SnapshotLocalLastAspect + + Comment + Take next local snapshot at this aspect + Persist + 0 + Type + S32 + Value + 0 + SnapshotLocalLastResolution Comment @@ -13410,6 +13866,17 @@ This should be as low as possible, but too low may break functionality Value 0 + SnapshotPostcardLastAspect + + Comment + Take next postcard snapshot at this aspect + Persist + 0 + Type + S32 + Value + 0 + SnapshotPostcardLastResolution Comment @@ -13432,6 +13899,17 @@ This should be as low as possible, but too low may break functionality Value 75 + SnapshotTextureLastAspect + + Comment + Take next texture snapshot at this aspect + Persist + 0 + Type + S32 + Value + 0 + SnapshotTextureLastResolution Comment @@ -13443,6 +13921,17 @@ This should be as low as possible, but too low may break functionality Value 0 + SnapshotOpenFreezeTime + + Comment + When opening the snapshot floater, immediately freeze time. + Persist + 1 + Type + Boolean + Value + 0 + SpeakingColor Comment @@ -14155,12 +14644,12 @@ This should be as low as possible, but too low may break functionality Value 0 - UseFreezeFrame + UseFreezeTime Comment Freeze time when taking snapshots. Persist - 1 + 0 Type Boolean Value diff --git a/indra/newview/app_settings/settings_ascent_coa.xml b/indra/newview/app_settings/settings_ascent_coa.xml index 792c600e7..2cb809679 100644 --- a/indra/newview/app_settings/settings_ascent_coa.xml +++ b/indra/newview/app_settings/settings_ascent_coa.xml @@ -31,7 +31,7 @@ 1 - MoyMiniMapCustomColor + MoyMiniMapCustomColor Comment Custom minimap color you wish to have. @@ -135,7 +135,7 @@ AscentFriendColor Comment - Color of chat messages from other residents + Special color to distinguish friends from other residents Persist 1 Type @@ -153,7 +153,7 @@ AscentLindenColor Comment - Color of chat messages from other residents + Special color to distinguish Lindens(/grid operators) from other residents Persist 1 Type @@ -171,7 +171,7 @@ AscentMutedColor Comment - Color of chat messages from other residents + Special color to distinguish those who have been muted from other residents Persist 1 Type @@ -189,7 +189,7 @@ AscentEstateOwnerColor Comment - Color of chat messages from other residents + Special color to distinguish estate owners from other residents Persist 1 Type @@ -204,7 +204,73 @@ IsCOA 1 - AscentReportClientUUID + ColorFriendChat + + Comment + Color chat from friends using AscentFriendColor + Persist + 1 + Type + Boolean + Value + 0 + IsCOA + 1 + + ColorLindenChat + + Comment + Color chat from Lindens(/grid operators) using AscentLindenColor + Persist + 1 + Type + Boolean + Value + 0 + IsCOA + 1 + + ColorMutedChat + + Comment + Color chat from muted residents using AscentMutedColor + Persist + 1 + Type + Boolean + Value + 0 + IsCOA + 1 + + ColorEstateOwnerChat + + Comment + Color chat from estate owners using AscentEstateOwnerColor + Persist + 1 + Type + Boolean + Value + 0 + IsCOA + 1 + + + AscentReportClientUUID Comment Broadcasted Client Key diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index b422fae32..d30cb4343 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -357,22 +357,6 @@ This is an autoresponse! - MoyMiniMapCustomColor - - Comment - Custom minimap color you wish to have. - Persist - 1 - Type - Color4 - Value - - 0.375 - 1.0 - 1.0 - 1.0 - - rkeastInventoryPreviousCount diff --git a/indra/newview/app_settings/settings_sh.xml b/indra/newview/app_settings/settings_sh.xml index 81659467c..411bc1e36 100644 --- a/indra/newview/app_settings/settings_sh.xml +++ b/indra/newview/app_settings/settings_sh.xml @@ -174,5 +174,38 @@ Value 0 + SHPackDeferredNormals + + Comment + Pack deferred normals into two components. + Persist + 1 + Type + Boolean + Value + 0 + + SHPrecisionDeferredNormals + + Comment + Enable usage of RGB10A2 for the deferred normalMap format. Reduces normalmapping artifacts. + Persist + 1 + Type + Boolean + Value + 0 + + SHOcclusionFudge + + Comment + Padding added to occlusion bounds. Larger = less aggressive occlusion/less pop-in. + Persist + 1 + Type + F32 + Value + 0.25 + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 46d2aa487..cf57a33d9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -34,6 +34,17 @@ uniform sampler2D diffuseMap; VARYING vec3 vary_normal; VARYING vec2 vary_texcoord0; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { vec4 diff = texture2D(diffuseMap, vary_texcoord0.xy); @@ -46,6 +57,6 @@ void main() frag_data[0] = vec4(diff.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(pack(nvn), 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index f400eb7a5..9a9b889da 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -64,32 +64,45 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} + void main() { vec2 tc = vary_fragcoord.xy; - vec3 norm = texture2DRect(normalMap, tc).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + vec3 norm = unpack(tc); // unpack norm + vec3 pos = getPosition(tc).xyz; vec4 ccol = texture2DRect(lightMap, tc).rgba; - vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); + vec2 dlt = kern_scale * delta / (vec2(1.0)+norm.xy*norm.xy); dlt /= max(-pos.z*dist_factor, 1.0); vec2 defined_weight = getKern(0).xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' vec4 col = defined_weight.xyxx * ccol; // relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances - float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005; + float pointplanedist_tolerance_pow2 = pos.z*-0.001; // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large - float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2) - tc_mod -= floor(tc_mod); - tc_mod *= 2.0; + vec2 tc_v = fract(0.5 * tc.xy); // we now have floor(mod(tc,2.0))*0.5 + float tc_mod = 2.0 * abs(tc_v.x - tc_v.y); // diff of x,y makes checkerboard tc += ( (tc_mod - 0.5) * getKern(1).z * dlt * 0.5 ); for (int i = 1; i < 4; i++) { - vec2 samptc = tc + getKern(i).z*dlt; + vec2 samptc = (tc + getKern(i).z * dlt); vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane if (d*d <= pointplanedist_tolerance_pow2) @@ -100,7 +113,7 @@ void main() } for (int i = 1; i < 4; i++) { - vec2 samptc = tc - getKern(i).z*dlt; + vec2 samptc = (tc - getKern(i).z * dlt); vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane if (d*d <= pointplanedist_tolerance_pow2) @@ -111,7 +124,7 @@ void main() } col /= defined_weight.xyxx; - col.y *= col.y; + col.y *= col.y; // delinearize SSAO effect post-blur frag_color = col; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 680eadb85..db80a8e87 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -39,6 +39,17 @@ VARYING vec3 vary_mat2; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb; @@ -52,5 +63,5 @@ void main() frag_data[1] = vertex_color.aaaa; // spec //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(tnorm); - frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(pack(nvn), 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl index 1d8ca04cc..9f6b1ea1f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl @@ -102,6 +102,11 @@ void main() /// Gamma correct for WL (soft clip effect). frag_data[0] = vec4(scaleSoftClip(color.rgb), alpha1); frag_data[1] = vec4(0.0,0.0,0.0,0.0); - frag_data[2] = vec4(0,0,1,0); +//#define PACK_NORMALS +#ifdef PACK_NORMALS + frag_data[2] = vec4(0.5,0.5,0.0,0.0); +#else + frag_data[2] = vec4(0.0,0.0,1.0,0.0); +#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl index b2027d3a5..d31cbfa28 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -37,6 +37,17 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { vec4 col = texture2D(diffuseMap, vary_texcoord0.xy) * vertex_color; @@ -49,6 +60,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(pack(nvn),0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl index ead384b07..c65539d43 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -36,6 +36,17 @@ uniform float minimum_alpha; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { vec4 col = diffuseLookup(vary_texcoord0.xy) * vertex_color; @@ -48,5 +59,5 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(pack(nvn), 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl index f73fa6f23..252975aad 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl @@ -37,6 +37,17 @@ uniform sampler2D diffuseMap; VARYING vec3 vary_normal; VARYING vec2 vary_texcoord0; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { vec4 col = texture2D(diffuseMap, vary_texcoord0.xy); @@ -49,6 +60,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(pack(nvn),0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 227aa2aae..ac33fd261 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -35,6 +35,17 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb; @@ -42,6 +53,6 @@ void main() frag_data[1] = vertex_color.aaaa; // spec //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(pack(nvn),0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl index d442e5403..b97cd060d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -33,6 +33,17 @@ VARYING vec3 vary_normal; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; @@ -41,5 +52,5 @@ void main() frag_data[1] = vertex_color.aaaa; // spec //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(pack(nvn),0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 4d01eeb64..26aa34107 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -69,6 +69,20 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} + void main() { vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res; @@ -78,9 +92,8 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm - norm = normalize(norm); + vec3 norm = unpack(frag.xy); // unpack norm + //norm = normalize(norm); // may be superfluous vec4 spec = texture2DRect(specularRect, frag.xy); vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; float noise = texture2D(noiseMap, frag.xy/128.0).b; diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index bff87cb6a..a82ba899a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -125,6 +125,20 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} + void main() { vec4 frag = vary_fragcoord; @@ -141,10 +155,9 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - norm = vec3((norm.xy-0.5)*2.0, norm.z); + vec3 norm = unpack(frag.xy); // unpack norm - norm = normalize(norm); + //norm = normalize(norm); // may be superfluous float l_dist = -dot(lv, proj_n); vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index f671d5b75..6c1ff1660 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -67,6 +67,20 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} + void main() { vec4 frag = vary_fragcoord; @@ -83,15 +97,14 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + vec3 norm = unpack(frag.xy); // unpack norm float da = dot(norm, lv); if (da < 0.0) { discard; } - norm = normalize(norm); + //norm = normalize(norm); // may be superfluous lv = normalize(lv); da = dot(norm, lv); diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index faa54a316..4eefdd8b6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -60,7 +60,12 @@ void main() /// Gamma correct for WL (soft clip effect). frag_data[0] = vec4(scaleSoftClip(color.rgb), 1.0); - frag_data[1] = vec4(0.0,0.0,0.0,0.0); - frag_data[2] = vec4(0,0,1,0); + frag_data[1] = vec4(vary_HazeColor.a,0.0,0.0,0.0); +//#define PACK_NORMALS +#ifdef PACK_NORMALS + frag_data[2] = vec4(0.5,0.5,0.0,0.0); +#else + frag_data[2] = vec4(0.0,0.0,1.0,0.0); +#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index 7c02d31d4..f5a0bfec6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -53,6 +53,13 @@ uniform vec4 glow; uniform vec4 cloud_color; +float luminance(vec3 color) +{ + /// CALCULATING LUMINANCE (Using NTSC lum weights) + /// http://en.wikipedia.org/wiki/Luma_%28video%29 + return dot(color, vec3(0.299, 0.587, 0.114)); +} + void main() { @@ -151,6 +158,7 @@ void main() // At horizon, blend high altitude sky color towards the darker color below the clouds vary_HazeColor += (additiveColorBelowCloud - vary_HazeColor) * (1. - sqrt(temp1)); + vary_HazeColor.a = pow(clamp(luminance(vary_HazeColor.rgb)-.5,0,1),2); // won't compile on mac without this being set //vary_AtmosAttenuation = vec3(0.0,0.0,0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 66e3cf6d1..066cdd348 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -62,7 +62,7 @@ uniform float max_y; uniform vec4 glow; uniform float scene_light_strength; uniform mat3 env_mat; -uniform mat3 ssao_effect_mat; +uniform float ssao_effect; uniform vec3 sun_dir; VARYING vec2 vary_fragcoord; @@ -203,22 +203,15 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { //increase ambient when there are more clouds vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5; - /* decrease value and saturation (that in HSV, not HSL) for occluded areas - * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html - * // The following line of code performs the equivalent of: - * float ambAlpha = tmpAmbient.a; - * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis - * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); - * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); - */ - tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); - //haze color setAdditiveColor( vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x + tmpAmbient))); + // decrease value for occluded areas + tmpAmbient = vec4(mix(ssao_effect * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + //brightness of surface both sunlight and ambient setSunlitColor(vec3(sunlight * .5)); setAmblitColor(vec3(tmpAmbient * .25)); @@ -271,13 +264,33 @@ vec3 scaleSoftClip(vec3 light) return light; } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} + +float luminance(vec3 color) +{ + /// CALCULATING LUMINANCE (Using NTSC lum weights) + /// http://en.wikipedia.org/wiki/Luma_%28video%29 + return dot(color, vec3(0.299, 0.587, 0.114)); +} + void main() { vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).r; vec3 pos = getPosition_d(tc, depth).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + vec3 norm = unpack(tc); // unpack norm float da = max(dot(norm.xyz, sun_dir.xyz), 0.0); @@ -310,17 +323,20 @@ void main() //add environmentmap vec3 env_vec = env_mat * refnormpersp; - col = mix(col.rgb, textureCube(environmentMap, env_vec).rgb, - max(spec.a-diffuse.a*2.0, 0.0)); + vec3 env = textureCube(environmentMap, env_vec).rgb; + bloom = (luminance(env) - .45)*.25; + col = mix(col.rgb, env, + max(spec.a-diffuse.a*2.0, 0.0)); } col = atmosLighting(col); col = scaleSoftClip(col); - col = mix(col.rgb, diffuse.rgb, diffuse.a); + col = mix(col, diffuse.rgb, diffuse.a); } else { + bloom = spec.r; col = diffuse.rgb; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index cca63872d..ae64d8937 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -127,6 +127,20 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} + void main() { vec4 frag = vary_fragcoord; @@ -143,10 +157,9 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - norm = vec3((norm.xy-0.5)*2.0, norm.z); + vec3 norm = unpack(frag.xy); // unpack norm - norm = normalize(norm); + //norm = normalize(norm); // may be superfluous float l_dist = -dot(lv, proj_n); vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl index 821058804..2e4b416c4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl @@ -29,6 +29,8 @@ out vec4 frag_data[3]; #define frag_data gl_FragData #endif +uniform float custom_alpha; + VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; @@ -38,7 +40,12 @@ void main() { vec4 col = vertex_color * texture2D(diffuseMap, vary_texcoord0.xy); - frag_data[0] = col; + frag_data[0] = vec4(col.rgb,col.a*custom_alpha); frag_data[1] = vec4(0,0,0,0); - frag_data[2] = vec4(0,0,1,0); +//#define PACK_NORMALS +#ifdef PACK_NORMALS + frag_data[2] = vec4(0.5,0.5,0.0,0.0); +#else + frag_data[2] = vec4(0.0,0.0,1.0,0.0); +#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl index 2422d73a3..24a827e91 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -65,8 +65,6 @@ vec4 getPosition(vec2 pos_screen) //calculate decreases in ambient lighting when crowded out (SSAO) float calcAmbientOcclusion(vec4 pos, vec3 norm) { - float ret = 1.0; - vec2 kern[8]; // exponentially (^2) distant occlusion samples spread around origin kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; @@ -82,38 +80,54 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) vec3 pos_world = pos.xyz; vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; + // We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place. + float points = 1.0; float angle_hidden = 0.0; - int points = 0; - - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - - // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?) + + // use a kernel scale that diminishes with distance. + // a scale of less than 32 is just wasting good samples, though. + float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius)); + + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) for (int i = 0; i < 8; i++) { vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; - - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); - - // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area - // --> solid angle shrinking by the square of distance - //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 - //(k should vary inversely with # of samples, but this is taken care of later) - - angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); - - // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" - points = points + int(diff.z > -1.0); + vec3 samppos_world = getPosition(samppos_screen).xyz; + + vec3 diff = samppos_world - pos.xyz; + + if (diff.z < ssao_factor && diff.z != 0.0) + { + float dist = length(diff); + float angrel = max(0.0, dot(norm.xyz, diff/dist)); + float distrel = 1.0/(1.0+dist*dist); + float samplehidden = min(angrel, distrel); + + angle_hidden += (samplehidden); + points += 1.0; + } } - angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - - ret = (1.0 - (float(points != 0) * angle_hidden)); - - return min(ret, 1.0); + angle_hidden /= points; + + float rtn = (1.0 - angle_hidden); + + return (rtn * rtn); } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} void main() { vec2 pos_screen = vary_fragcoord.xy; @@ -122,8 +136,7 @@ void main() vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + vec3 norm = unpack(pos_screen); // unpack norm frag_color[0] = 1.0; frag_color[1] = calcAmbientOcclusion(pos, norm); diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 8a5e482e8..3e4c5fc9c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -39,6 +39,17 @@ VARYING vec3 vary_normal; VARYING vec4 vary_texcoord0; VARYING vec4 vary_texcoord1; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { /// Note: This should duplicate the blending functionality currently used for the terrain rendering. @@ -56,6 +67,6 @@ void main() frag_data[0] = vec4(outColor.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(pack(nvn),0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 6cf6106b5..6cd309fdb 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -37,6 +37,17 @@ VARYING vec2 vary_texcoord0; uniform float minimum_alpha; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { vec4 col = texture2D(diffuseMap, vary_texcoord0.xy); @@ -48,5 +59,5 @@ void main() frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); + frag_data[2] = vec4(pack(nvn),0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 42dc7c098..b27822814 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -67,6 +67,17 @@ VARYING vec4 littleWave; VARYING vec4 view; VARYING vec4 vary_position; +vec3 pack(vec3 norm) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + float p = sqrt(8.0*norm.z+8.0); + return vec3(norm.xy/p + 0.5, 0.0); +#else + return norm.xyz*0.5+0.5; +#endif +} + void main() { vec4 color; @@ -151,8 +162,9 @@ void main() //spec *= shadow; //color.rgb += spec * specular; - //color.rgb = atmosTransport(color.rgb); - //color.rgb = scaleSoftClip(color.rgb); + color.rgb = atmosTransport(color.rgb); + color.rgb = scaleSoftClip(color.rgb); + //color.a = spec * sunAngle2; //wavef.z *= 0.1f; @@ -161,5 +173,5 @@ void main() frag_data[0] = vec4(color.rgb, 0.5); // diffuse frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec - frag_data[2] = vec4(screenspacewavef.xy*0.5+0.5, screenspacewavef.z, screenspacewavef.z*0.5); // normalxyz, displace + frag_data[2] = vec4(pack(screenspacewavef), 0.5); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl index 9734acf00..ece34dcc4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl @@ -85,7 +85,7 @@ void main() pos.w = 1.0; pos = modelview_matrix*pos; - calcAtmospherics(pos.xyz); + calcAtmospherics(view.xyz); //pass wave parameters to pixel shader vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055; diff --git a/indra/newview/app_settings/shaders/class1/effects/VignetteF.glsl b/indra/newview/app_settings/shaders/class1/effects/VignetteF.glsl new file mode 100644 index 000000000..ad989e1a0 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/effects/VignetteF.glsl @@ -0,0 +1,54 @@ +/** + * @file colorFilterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform sampler2DRect tex0; +uniform float vignette_strength; //0 - 1 +uniform float vignette_radius; //0 - 8 +uniform float vignette_darkness; //0 - 1 +uniform float vignette_desaturation; //0 - 10 +uniform float vignette_chromatic_aberration; //0 - .1 +uniform vec2 screen_res; + +VARYING vec2 vary_texcoord0; + +float luminance(vec3 color) +{ + /// CALCULATING LUMINANCE (Using NTSC lum weights) + /// http://en.wikipedia.org/wiki/Luma_%28video%29 + return dot(color, vec3(0.299, 0.587, 0.114)); +} + +void main(void) +{ + vec3 color = texture2DRect(tex0, vary_texcoord0).rgb; + vec2 norm_texcood = (vary_texcoord0/screen_res); + vec2 offset = norm_texcood-vec2(.5); + float vignette = clamp(pow(1 - dot(offset,offset),vignette_radius) + 1-vignette_strength, 0.0, 1.0); + float inv_vignette = 1-vignette; + + //vignette chromatic aberration (g + vec2 shift = screen_res * offset * vignette_chromatic_aberration * inv_vignette; + float g = texture2DRect(tex0,vary_texcoord0-shift).g; + float b = texture2DRect(tex0,vary_texcoord0-2*shift).b; + color.gb = vec2(g,b); + + //vignette 'black' overlay. + color = mix(color * vignette, color, 1-vignette_darkness); + + //vignette desaturation + color = mix(vec3(luminance(color)), color, clamp(1-inv_vignette*vignette_desaturation,0,1)); + + frag_color = vec4(color,1.0); +} diff --git a/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl b/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl index e03b83113..6acd277bb 100644 --- a/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl @@ -25,6 +25,13 @@ uniform float gamma; VARYING vec2 vary_texcoord0; +float luminance(vec3 color) +{ + /// CALCULATING LUMINANCE (Using NTSC lum weights) + /// http://en.wikipedia.org/wiki/Luma_%28video%29 + return dot(color, vec3(0.299, 0.587, 0.114)); +} + void main(void) { vec3 color = vec3(texture2DRect(tex0, vary_texcoord0.st)); @@ -39,7 +46,7 @@ void main(void) color = mix(contrastBase, color, contrast); /// Modulate saturation - color = mix(vec3(dot(color, lumWeights)), color, saturation); + color = mix(vec3(luminance(color)), color, saturation); frag_color = vec4(color, 1.0); } diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl index f66ba1d2d..f77edde70 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl @@ -81,7 +81,7 @@ void main() pos.w = 1.0; pos = modelview_matrix*pos; - calcAtmospherics(pos.xyz); + calcAtmospherics(view.xyz); //pass wave parameters to pixel shader diff --git a/indra/newview/app_settings/shaders/class1/transform/positionV.glsl b/indra/newview/app_settings/shaders/class1/transform/positionV.glsl index 01eed18de..4c8d1b2d1 100644 --- a/indra/newview/app_settings/shaders/class1/transform/positionV.glsl +++ b/indra/newview/app_settings/shaders/class1/transform/positionV.glsl @@ -30,7 +30,7 @@ uniform int texture_index_in; ATTRIBUTE vec3 position; VARYING vec3 position_out; -VARYING int texture_index_out; +VARYING_FLAT int texture_index_out; void main() { diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index f7f1f649c..7f6a31ef7 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -126,6 +126,20 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} + void main() { vec4 frag = vary_fragcoord; @@ -153,10 +167,9 @@ void main() shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + vec3 norm = unpack(frag.xy); // unpack norm - norm = normalize(norm); + //norm = normalize(norm); // may be superfluous float l_dist = -dot(lv, proj_n); vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index a137bea30..d490b5d46 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -63,7 +63,7 @@ uniform vec4 glow; uniform float scene_light_strength; uniform mat3 env_mat; uniform vec4 shadow_clip; -uniform mat3 ssao_effect_mat; +uniform float ssao_effect; uniform mat4 inv_proj; uniform vec2 screen_res; @@ -79,6 +79,13 @@ vec3 vary_AmblitColor; vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; +float luminance(vec3 color) +{ + /// CALCULATING LUMINANCE (Using NTSC lum weights) + /// http://en.wikipedia.org/wiki/Luma_%28video%29 + return dot(color, vec3(0.299, 0.587, 0.114)); +} + vec4 getPosition_d(vec2 pos_screen, float depth) { vec2 sc = pos_screen.xy*2.0; @@ -205,22 +212,15 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { //increase ambient when there are more clouds vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5; - /* decrease value and saturation (that in HSV, not HSL) for occluded areas - * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html - * // The following line of code performs the equivalent of: - * float ambAlpha = tmpAmbient.a; - * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis - * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); - * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); - */ - tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); - //haze color setAdditiveColor( vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x + tmpAmbient))); + // decrease ambient value for occluded areas + tmpAmbient *= mix(ssao_effect, 1.0, ambFactor); + //brightness of surface both sunlight and ambient setSunlitColor(vec3(sunlight * .5)); setAmblitColor(vec3(tmpAmbient * .25)); @@ -273,25 +273,37 @@ vec3 scaleSoftClip(vec3 light) return light; } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} + void main() { vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).r; vec3 pos = getPosition_d(tc, depth).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + vec3 norm = unpack(tc); // unpack norm float da = max(dot(norm.xyz, sun_dir.xyz), 0.0); vec4 diffuse = texture2DRect(diffuseRect, tc); + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); vec3 col; float bloom = 0.0; if (diffuse.a < 0.9) { - vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; float scol = max(scol_ambocc.r, diffuse.a); float ambocc = scol_ambocc.g; @@ -318,7 +330,9 @@ void main() //add environmentmap vec3 env_vec = env_mat * refnormpersp; - col = mix(col.rgb, textureCube(environmentMap, env_vec).rgb, + vec3 env = textureCube(environmentMap, env_vec).rgb; + bloom = (luminance(env) - .45)*.25; + col = mix(col.rgb, env, max(spec.a-diffuse.a*2.0, 0.0)); } @@ -329,6 +343,7 @@ void main() } else { + bloom = spec.r; col = diffuse.rgb; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index ab077d9e0..3a556e913 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -126,6 +126,20 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec3 unpack(vec2 tc) +{ +//#define PACK_NORMALS +#ifdef PACK_NORMALS + vec2 enc = texture2DRect(normalMap, tc).xy; + enc = enc*4.0-2.0; + float prod = dot(enc,enc); + return vec3(enc*sqrt(1.0-prod*.25),1.0-prod*.5); +#else + vec3 norm = texture2DRect(normalMap, tc).xyz; + return norm*2.0-1.0; +#endif +} + void main() { vec4 frag = vary_fragcoord; @@ -153,10 +167,9 @@ void main() shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + vec3 norm = unpack(frag.xy); // unpack norm - norm = normalize(norm); + //norm = normalize(norm); // may be superfluous float l_dist = -dot(lv, proj_n); vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index db3d76035..f8f57e5e7 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -116,6 +116,22 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) return shadow*0.2; } +vec4 unpack(vec2 tc) +{ + vec4 norm = texture2DRect(normalMap, tc).xyzw; +//#define PACK_NORMALS +#ifdef PACK_NORMALS + norm.xy = (norm.xy*4.0)-2.0; + float prod = dot(norm.xy,norm.xy); + norm.xy *= sqrt(1.0-prod*.25); + norm.z = 1.0-prod*.5; +#else + norm.xyz = norm.xyz*2.0-1.0; +#endif + norm.w *= norm.z; + return norm; +} + void main() { vec2 pos_screen = vary_fragcoord.xy; @@ -124,8 +140,7 @@ void main() vec4 pos = getPosition(pos_screen); - vec4 nmap4 = texture2DRect(normalMap, pos_screen); - nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm + vec4 nmap4 = unpack(pos_screen); // unpack norm float displace = nmap4.w; vec3 norm = nmap4.xyz; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index 32b206e63..ddcb024a9 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -97,46 +97,40 @@ vec2 getKern(int i) //calculate decreases in ambient lighting when crowded out (SSAO) float calcAmbientOcclusion(vec4 pos, vec3 norm) { - float ret = 1.0; - vec2 pos_screen = vary_fragcoord.xy; - vec3 pos_world = pos.xyz; vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; - + + // We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place. + float points = 1.0; float angle_hidden = 0.0; - float points = 0; - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + // use a kernel scale that diminishes with distance. + // a scale of less than 32 is just wasting good samples, though. + float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius)); // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) for (int i = 0; i < 8; i++) { vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect); vec3 samppos_world = getPosition(samppos_screen).xyz; - - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); - - // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area - // --> solid angle shrinking by the square of distance - //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 - //(k should vary inversely with # of samples, but this is taken care of later) - - float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0; - angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv); - - // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" - float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0; - points = points + diffz_val; - } - - angle_hidden = min(ssao_factor*angle_hidden/points, 1.0); - - float points_val = (points > 0.0) ? 1.0 : 0.0; - ret = (1.0 - (points_val * angle_hidden)); - ret = max(ret, 0.0); - return min(ret, 1.0); + vec3 diff = samppos_world - pos.xyz; + + if (diff.z < ssao_factor && diff.z != 0.0) + { + float dist = length(diff); + float angrel = max(0.0, dot(norm.xyz, diff/dist)); + float distrel = 1.0/(1.0+dist*dist); + float samplehidden = min(angrel, distrel); + + angle_hidden += (samplehidden); + points += 1.0; + } + } + + angle_hidden /= points; + float rtn = (1.0 - angle_hidden); + return (rtn * rtn); } float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) @@ -177,6 +171,22 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen) return shadow*0.2; } +vec4 unpack(vec2 tc) +{ + vec4 norm = texture2DRect(normalMap, tc).xyzw; +//#define PACK_NORMALS +#ifdef PACK_NORMALS + norm.xy = (norm.xy*4.0)-2.0; + float prod = dot(norm.xy,norm.xy); + norm.xy *= sqrt(1.0-prod*.25); + norm.z = 1.0-prod*.5; +#else + norm.xyz = norm.xyz*2.0-1.0; +#endif + norm.w *= norm.z; + return norm; +} + void main() { vec2 pos_screen = vary_fragcoord.xy; @@ -185,8 +195,7 @@ void main() vec4 pos = getPosition(pos_screen); - vec4 nmap4 = texture2DRect(normalMap, pos_screen); - nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm + vec4 nmap4 = unpack(pos_screen); // unpack norm float displace = nmap4.w; vec3 norm = nmap4.xyz; diff --git a/indra/newview/app_settings/windlight/postprocesseffects.xml b/indra/newview/app_settings/windlight/postprocesseffects.xml index b5b173b40..5a498009c 100644 --- a/indra/newview/app_settings/windlight/postprocesseffects.xml +++ b/indra/newview/app_settings/windlight/postprocesseffects.xml @@ -177,6 +177,8 @@ enable_posterize 0 enable_motionblur + 0 + enable_vignette 0 gauss_blur_passes 2 @@ -194,6 +196,16 @@ 10 blur_strength 10 + vignette_strength + 0.85 + vignette_radius + 0.7 + vignette_darkness + 1.0 + vignette_desaturation + 1.0 + vignette_chromatic_aberration + 0.01 \ No newline at end of file diff --git a/indra/newview/ascentfloatercontactgroups.cpp b/indra/newview/ascentfloatercontactgroups.cpp index d4097493d..f1d867fca 100644 --- a/indra/newview/ascentfloatercontactgroups.cpp +++ b/indra/newview/ascentfloatercontactgroups.cpp @@ -30,7 +30,7 @@ #include "llfloaterchat.h" ASFloaterContactGroups* ASFloaterContactGroups::sInstance = NULL; -LLDynamicArray ASFloaterContactGroups::mSelectedUUIDs; +uuid_vec_t ASFloaterContactGroups::mSelectedUUIDs; LLSD ASFloaterContactGroups::mContactGroupData; ASFloaterContactGroups::ASFloaterContactGroups() @@ -40,7 +40,7 @@ ASFloaterContactGroups::ASFloaterContactGroups() } // static -void ASFloaterContactGroups::show(LLDynamicArray ids) +void ASFloaterContactGroups::show(const uuid_vec_t& ids) { if (!sInstance) sInstance = new ASFloaterContactGroups(); @@ -84,7 +84,8 @@ void ASFloaterContactGroups::onBtnAdd(void* userdata) self->createContactGroup(name); combo->selectByValue(name); } - for (S32 i = (self->mSelectedUUIDs.count() - 1); i >= 0; --i) + uuid_vec_t::reverse_iterator it = self->mSelectedUUIDs.rbegin(); + for (;it != self->mSelectedUUIDs.rend();++it) { //self->addContactMember(combo->getSimple(), self->mSelectedUUIDs.get(i)); } @@ -98,19 +99,21 @@ void ASFloaterContactGroups::onBtnRemove(void* userdata) if(self) { - if (self->mSelectedUUIDs.count() > 0) + if (!self->mSelectedUUIDs.empty()) { LLScrollListCtrl* scroller = self->getChild("group_scroll_list"); if(scroller != NULL) { - for (S32 i = (self->mSelectedUUIDs.count() - 1); i >= 0; --i) + uuid_vec_t::size_type i = self->mSelectedUUIDs.size(); + uuid_vec_t::reverse_iterator it = self->mSelectedUUIDs.rbegin(); + for (;it != self->mSelectedUUIDs.rend();++it) { std::string i_str; - LLResMgr::getInstance()->getIntegerString(i_str, i); - LLChat msg("Adding index " + i_str + ": " + self->mSelectedUUIDs.get(i).asString()); + LLResMgr::getInstance()->getIntegerString(i_str, --i); + LLChat msg("Adding index " + i_str + ": " + it->asString()); LLFloaterChat::addChat(msg); - self->addContactMember(scroller->getValue().asString(), self->mSelectedUUIDs.get(i)); + self->addContactMember(scroller->getValue().asString(), *it); } } } diff --git a/indra/newview/ascentfloatercontactgroups.h b/indra/newview/ascentfloatercontactgroups.h index 809dce781..e20a67d38 100644 --- a/indra/newview/ascentfloatercontactgroups.h +++ b/indra/newview/ascentfloatercontactgroups.h @@ -29,7 +29,7 @@ public: virtual ~ASFloaterContactGroups(); // by convention, this shows the floater and does instance management - static void show(LLDynamicArray ids); + static void show(const uuid_vec_t& ids); void populateGroupList(); void populateActiveGroupList(LLUUID to_add); @@ -47,7 +47,7 @@ public: private: //assuming we just need one, which is typical static ASFloaterContactGroups* sInstance; - static LLDynamicArray mSelectedUUIDs; + static uuid_vec_t mSelectedUUIDs; static LLSD mContactGroupData; }; diff --git a/indra/newview/ascentprefschat.cpp b/indra/newview/ascentprefschat.cpp index f937571c3..d4b8c3407 100644 --- a/indra/newview/ascentprefschat.cpp +++ b/indra/newview/ascentprefschat.cpp @@ -335,6 +335,8 @@ void LLPrefsAscentChat::refreshValues() mEnableOOCAutoClose = gSavedSettings.getBOOL("AscentAutoCloseOOC"); mLinksForChattingObjects = gSavedSettings.getU32("LinksForChattingObjects"); mSecondsInChatAndIMs = gSavedSettings.getBOOL("SecondsInChatAndIMs"); + mSecondsInLog = gSavedSettings.getBOOL("SecondsInLog"); + mOtherChatsTornOff = gSavedSettings.getBOOL("OtherChatsTornOff"); std::string format = gSavedSettings.getString("ShortTimeFormat"); if (format.find("%p") == -1) @@ -390,6 +392,7 @@ void LLPrefsAscentChat::refreshValues() mSoundMulti = gSavedSettings.getU32("_NACL_AntiSpamSoundMulti"); mNewLines = gSavedSettings.getU32("_NACL_AntiSpamNewlines"); mPreloadMulti = gSavedSettings.getU32("_NACL_AntiSpamSoundPreloadMulti"); + mEnableGestureSounds = gSavedSettings.getBOOL("EnableGestureSounds"); //Text Options ------------------------------------------------------------------------ mSpellDisplay = gSavedSettings.getBOOL("SpellDisplay"); @@ -539,6 +542,8 @@ void LLPrefsAscentChat::cancel() gSavedSettings.setBOOL("AscentAutoCloseOOC", mEnableOOCAutoClose); gSavedSettings.setU32("LinksForChattingObjects", mLinksForChattingObjects); gSavedSettings.setBOOL("SecondsInChatAndIMs", mSecondsInChatAndIMs); + gSavedSettings.setBOOL("SecondsInLog", mSecondsInLog); + gSavedSettings.setBOOL("OtherChatsTornOff", mOtherChatsTornOff); std::string short_date, long_date, short_time, long_time, timestamp; @@ -607,6 +612,7 @@ void LLPrefsAscentChat::cancel() gSavedSettings.setU32("_NACL_AntiSpamSoundMulti", mSoundMulti); gSavedSettings.setU32("_NACL_AntiSpamNewlines", mNewLines); gSavedSettings.setU32("_NACL_AntiSpamSoundPreloadMulti", mPreloadMulti); + gSavedSettings.setBOOL("EnableGestureSounds", mEnableGestureSounds); //Text Options ------------------------------------------------------------------------ gSavedSettings.setBOOL("SpellDisplay", mSpellDisplay); diff --git a/indra/newview/ascentprefschat.h b/indra/newview/ascentprefschat.h index 8bbfad0c0..03e980c3f 100644 --- a/indra/newview/ascentprefschat.h +++ b/indra/newview/ascentprefschat.h @@ -76,6 +76,8 @@ protected: U32 tempTimeFormat; U32 tempDateFormat; BOOL mSecondsInChatAndIMs; + BOOL mSecondsInLog; + BOOL mOtherChatsTornOff; BOOL mIMResponseAnyone; BOOL mIMResponseFriends; @@ -104,6 +106,7 @@ protected: BOOL mSoundMulti; U32 mNewLines; U32 mPreloadMulti; + bool mEnableGestureSounds; //Text Options ------------------------------------------------------------------------ BOOL mSpellDisplay; diff --git a/indra/newview/ascentprefssys.cpp b/indra/newview/ascentprefssys.cpp index 8b90011f2..ba835d7ac 100644 --- a/indra/newview/ascentprefssys.cpp +++ b/indra/newview/ascentprefssys.cpp @@ -267,8 +267,10 @@ void LLPrefsAscentSys::refreshValues() mDoubleClickTeleport = gSavedSettings.getBOOL("DoubleClickTeleport"); mResetCameraAfterTP = gSavedSettings.getBOOL("OptionRotateCamAfterLocalTP"); mOffsetTPByUserHeight = gSavedSettings.getBOOL("OptionOffsetTPByAgentHeight"); + mLiruFlyAfterTeleport = gSavedSettings.getBOOL("LiruFlyAfterTeleport"); + mLiruContinueFlying = gSavedSettings.getBOOL("LiruContinueFlyingOnUnsit"); mPreviewAnimInWorld = gSavedSettings.getBOOL("PreviewAnimInWorld"); -// mSaveScriptsAsMono = gSavedSettings.getBOOL("SaveScriptsAsMono"); + mSaveScriptsAsMono = gSavedSettings.getBOOL("SaveInventoryScriptsAsMono"); mAlwaysRezInGroup = gSavedSettings.getBOOL("AscentAlwaysRezInGroup"); mBuildAlwaysEnabled = gSavedSettings.getBOOL("AscentBuildAlwaysEnabled"); mAlwaysShowFly = gSavedSettings.getBOOL("AscentFlyAlwaysEnabled"); @@ -416,8 +418,10 @@ void LLPrefsAscentSys::cancel() gSavedSettings.setBOOL("DoubleClickTeleport", mDoubleClickTeleport); gSavedSettings.setBOOL("OptionRotateCamAfterLocalTP", mResetCameraAfterTP); gSavedSettings.setBOOL("OptionOffsetTPByAgentHeight", mOffsetTPByUserHeight); + gSavedSettings.setBOOL("LiruFlyAfterTeleport", mLiruFlyAfterTeleport); + gSavedSettings.setBOOL("LiruContinueFlyingOnUnsit", mLiruContinueFlying); gSavedSettings.setBOOL("PreviewAnimInWorld", mPreviewAnimInWorld); -// gSavedSettings.setBOOL("SaveScriptsAsMono", mSaveScriptsAsMono); + gSavedSettings.setBOOL("SaveInventoryScriptsAsMono", mSaveScriptsAsMono); gSavedSettings.setBOOL("AscentAlwaysRezInGroup", mAlwaysRezInGroup); gSavedSettings.setBOOL("AscentBuildAlwaysEnabled", mBuildAlwaysEnabled); gSavedSettings.setBOOL("AscentFlyAlwaysEnabled", mAlwaysShowFly); diff --git a/indra/newview/ascentprefssys.h b/indra/newview/ascentprefssys.h index 3b233bb28..73765ee39 100644 --- a/indra/newview/ascentprefssys.h +++ b/indra/newview/ascentprefssys.h @@ -58,8 +58,10 @@ protected: BOOL mDoubleClickTeleport; BOOL mResetCameraAfterTP; BOOL mOffsetTPByUserHeight; + bool mLiruFlyAfterTeleport; + bool mLiruContinueFlying; BOOL mPreviewAnimInWorld; -// BOOL mSaveScriptsAsMono; + BOOL mSaveScriptsAsMono; BOOL mAlwaysRezInGroup; BOOL mBuildAlwaysEnabled; BOOL mAlwaysShowFly; diff --git a/indra/newview/ascentprefsvan.cpp b/indra/newview/ascentprefsvan.cpp index 53f0d5751..824566c78 100644 --- a/indra/newview/ascentprefsvan.cpp +++ b/indra/newview/ascentprefsvan.cpp @@ -36,6 +36,8 @@ #include "ascentprefsvan.h" //project includes +#include "llaudioengine.h" //For gAudiop +#include "llstreamingaudio.h" //For LLStreamingAudioInterface #include "llcolorswatch.h" #include "llvoavatarself.h" #include "llagent.h" @@ -54,6 +56,8 @@ LLPrefsAscentVan::LLPrefsAscentVan() { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_ascent_vanity.xml"); + childSetVisible("announce_streaming_metadata", gAudiop && gAudiop->getStreamingAudioImpl() && gAudiop->getStreamingAudioImpl()->supportsMetaData()); + childSetCommitCallback("tag_spoofing_combobox", onCommitClientTag, this); childSetCommitCallback("show_my_tag_check", onCommitCheckBox, this); @@ -152,12 +156,16 @@ void LLPrefsAscentVan::onCommitCheckBox(LLUICtrl* ctrl, void* user_data) if (ctrl->getName() == "use_status_check") { - BOOL showCustomColors = gSavedSettings.getBOOL("AscentUseStatusColors"); - self->childSetEnabled("friends_color_textbox", showCustomColors); - self->childSetEnabled("friend_color_swatch", showCustomColors); - self->childSetEnabled("estate_owner_color_swatch", showCustomColors); - self->childSetEnabled("linden_color_swatch", showCustomColors); - self->childSetEnabled("muted_color_swatch", showCustomColors); + bool showCustomColors = gSavedSettings.getBOOL("AscentUseStatusColors"); + self->childSetEnabled("friends_color_textbox", showCustomColors); + bool frColors = gSavedSettings.getBOOL("ColorFriendChat"); + self->childSetEnabled("friend_color_swatch", showCustomColors || frColors); + bool eoColors = gSavedSettings.getBOOL("ColorEstateOwnerChat"); + self->childSetEnabled("estate_owner_color_swatch", showCustomColors || eoColors); + bool lindColors = gSavedSettings.getBOOL("ColorLindenChat"); + self->childSetEnabled("linden_color_swatch", showCustomColors || lindColors); + bool muteColors = gSavedSettings.getBOOL("ColorMutedChat"); + self->childSetEnabled("muted_color_swatch", showCustomColors || muteColors); } else if (ctrl->getName() == "customize_own_tag_check") { @@ -172,12 +180,16 @@ void LLPrefsAscentVan::onCommitCheckBox(LLUICtrl* ctrl, void* user_data) // Store current settings for cancel void LLPrefsAscentVan::refreshValues() { - //General -------------------------------------------------------------------------------- + //Main ----------------------------------------------------------------------------------- mUseAccountSettings = gSavedSettings.getBOOL("AscentStoreSettingsPerAccount"); mShowTPScreen = !gSavedSettings.getBOOL("AscentDisableTeleportScreens"); mPlayTPSound = gSavedSettings.getBOOL("OptionPlayTpSound"); mShowLogScreens = !gSavedSettings.getBOOL("AscentDisableLogoutScreens"); mDisableChatAnimation = gSavedSettings.getBOOL("SGDisableChatAnimation"); + mAddNotReplace = gSavedSettings.getBOOL("LiruAddNotReplace"); + mTurnAround = gSavedSettings.getBOOL("TurnAroundWhenWalkingBackwards"); + mAnnounceSnapshots = gSavedSettings.getBOOL("AnnounceSnapshots"); + mAnnounceStreamMetadata = gSavedSettings.getBOOL("AnnounceStreamMetadata"); //Tags\Colors ---------------------------------------------------------------------------- mAscentUseTag = gSavedSettings.getBOOL("AscentUseTag"); @@ -199,7 +211,12 @@ void LLPrefsAscentVan::refreshValues() mEstateOwnerColor = gSavedSettings.getColor4("AscentEstateOwnerColor"); mLindenColor = gSavedSettings.getColor4("AscentLindenColor"); mMutedColor = gSavedSettings.getColor4("AscentMutedColor"); - //mCustomColor = gSavedSettings.getColor4("MoyMiniMapCustomColor"); + mCustomColor = gSavedSettings.getColor4("MoyMiniMapCustomColor"); + mColorFriendChat = gSavedSettings.getBOOL("ColorFriendChat"); + mColorEOChat = gSavedSettings.getBOOL("ColorEstateOwnerChat"); + mColorLindenChat = gSavedSettings.getBOOL("ColorLindenChat"); + mColorMutedChat = gSavedSettings.getBOOL("ColorMutedChat"); +// mColorCustomChat = gSavedSettings.getBOOL("ColorCustomChat"); //Body Dynamics -------------------------------------------------------------------------- mBreastPhysicsToggle = gSavedSettings.getBOOL("EmeraldBreastPhysicsToggle"); @@ -217,17 +234,17 @@ void LLPrefsAscentVan::refreshValues() // Update controls based on current settings void LLPrefsAscentVan::refresh() { - //General -------------------------------------------------------------------------------- + //Main ----------------------------------------------------------------------------------- //Tags\Colors ---------------------------------------------------------------------------- LLComboBox* combo = getChild("tag_spoofing_combobox"); combo->setCurrentByIndex(mSelectedClient); childSetEnabled("friends_color_textbox", mUseStatusColors); - childSetEnabled("friend_color_swatch", mUseStatusColors); - childSetEnabled("estate_owner_color_swatch", mUseStatusColors); - childSetEnabled("linden_color_swatch", mUseStatusColors); - childSetEnabled("muted_color_swatch", mUseStatusColors); + childSetEnabled("friend_color_swatch", mUseStatusColors || mColorFriendChat); + childSetEnabled("estate_owner_color_swatch", mUseStatusColors || mColorEOChat); + childSetEnabled("linden_color_swatch", mUseStatusColors || mColorLindenChat); + childSetEnabled("muted_color_swatch", mUseStatusColors || mColorMutedChat); childSetEnabled("custom_tag_label_text", mCustomTagOn); childSetEnabled("custom_tag_label_box", mCustomTagOn); @@ -246,12 +263,16 @@ void LLPrefsAscentVan::refresh() // Reset settings to local copy void LLPrefsAscentVan::cancel() { - //General -------------------------------------------------------------------------------- + //Main ----------------------------------------------------------------------------------- gSavedSettings.setBOOL("AscentStoreSettingsPerAccount", mUseAccountSettings); gSavedSettings.setBOOL("AscentDisableTeleportScreens", !mShowTPScreen); gSavedSettings.setBOOL("OptionPlayTpSound", mPlayTPSound); gSavedSettings.setBOOL("AscentDisableLogoutScreens", !mShowLogScreens); gSavedSettings.setBOOL("SGDisableChatAnimation", mDisableChatAnimation); + gSavedSettings.setBOOL("LiruAddNotReplace", mAddNotReplace); + gSavedSettings.setBOOL("TurnAroundWhenWalkingBackwards", mTurnAround); + gSavedSettings.setBOOL("AnnounceSnapshots", mAnnounceSnapshots); + gSavedSettings.setBOOL("AnnounceStreamMetadata", mAnnounceStreamMetadata); //Tags\Colors ---------------------------------------------------------------------------- gSavedSettings.setBOOL("AscentUseTag", mAscentUseTag); @@ -273,7 +294,12 @@ void LLPrefsAscentVan::cancel() gSavedSettings.setColor4("AscentEstateOwnerColor", mEstateOwnerColor); gSavedSettings.setColor4("AscentLindenColor", mLindenColor); gSavedSettings.setColor4("AscentMutedColor", mMutedColor); -// gSavedSettings.setColor4("MoyMiniMapCustomColor", mCustomColor); + gSavedSettings.setColor4("MoyMiniMapCustomColor", mCustomColor); + gSavedSettings.setBOOL("ColorFriendChat", mColorFriendChat); + gSavedSettings.setBOOL("ColorEstateOwnerChat", mColorEOChat); + gSavedSettings.setBOOL("ColorLindenChat", mColorLindenChat); + gSavedSettings.setBOOL("ColorMutedChat", mColorMutedChat); +// gSavedSettings.setBOOL("ColorCustomChat", mColorCustomChat); //Body Dynamics -------------------------------------------------------------------------- gSavedSettings.setBOOL("EmeraldBreastPhysicsToggle", mBreastPhysicsToggle); diff --git a/indra/newview/ascentprefsvan.h b/indra/newview/ascentprefsvan.h index 115b1c206..62600a264 100644 --- a/indra/newview/ascentprefsvan.h +++ b/indra/newview/ascentprefsvan.h @@ -52,12 +52,16 @@ protected: static void onCommitCheckBox(LLUICtrl* ctrl, void* user_data); static void onCommitTextModified(LLUICtrl* ctrl, void* userdata); static void onManualClientUpdate(void* data); - //General + //Main BOOL mUseAccountSettings; BOOL mShowTPScreen; BOOL mPlayTPSound; BOOL mShowLogScreens; bool mDisableChatAnimation; + bool mAddNotReplace; + bool mTurnAround; + bool mAnnounceSnapshots; + bool mAnnounceStreamMetadata; //Tags\Colors BOOL mAscentUseTag; std::string mReportClientUUID; @@ -78,6 +82,12 @@ protected: LLColor4 mEstateOwnerColor; LLColor4 mLindenColor; LLColor4 mMutedColor; + LLColor4 mCustomColor; + bool mColorFriendChat; + bool mColorEOChat; + bool mColorLindenChat; + bool mColorMutedChat; +// bool mColorCustomChat; //Body Dynamics BOOL mBreastPhysicsToggle; F32 mBoobMass; diff --git a/indra/newview/chatbar_as_cmdline.cpp b/indra/newview/chatbar_as_cmdline.cpp index 5f416241c..7dcd34a59 100644 --- a/indra/newview/chatbar_as_cmdline.cpp +++ b/indra/newview/chatbar_as_cmdline.cpp @@ -300,8 +300,6 @@ bool cmd_line_chat(std::string revised_text, EChatType type) if(LLUUID::parseUUID(avatarKey, &tempUUID)) { char buffer[DB_IM_MSG_BUF_SIZE * 2]; /* Flawfinder: ignore */ - LLDynamicArray ids; - ids.push_back(tempUUID); std::string tpMsg="Join me!"; LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_StartLure); @@ -312,11 +310,8 @@ bool cmd_line_chat(std::string revised_text, EChatType type) msg->addU8Fast(_PREHASH_LureType, (U8)0); msg->addStringFast(_PREHASH_Message, tpMsg); - for(LLDynamicArray::iterator itr = ids.begin(); itr != ids.end(); ++itr) - { - msg->nextBlockFast(_PREHASH_TargetData); - msg->addUUIDFast(_PREHASH_TargetID, *itr); - } + msg->nextBlockFast(_PREHASH_TargetData); + msg->addUUIDFast(_PREHASH_TargetID, tempUUID); gAgent.sendReliableMessage(); snprintf(buffer,sizeof(buffer),"Offered TP to key %s",tempUUID.asString().c_str()); cmdline_printchat(std::string(buffer)); diff --git a/indra/newview/floaterao.cpp b/indra/newview/floaterao.cpp index f7bdf090f..59f922cca 100644 --- a/indra/newview/floaterao.cpp +++ b/indra/newview/floaterao.cpp @@ -356,9 +356,9 @@ BOOL LLFloaterAO::postBuild() childSetAction("newcard",onClickNewCard,this); childSetAction("prevstand",onClickPrevStand,this); childSetAction("nextstand",onClickNextStand,this); - childSetCommitCallback("AOEnabled",onClickToggleAO); - childSetCommitCallback("AOSitsEnabled",onClickToggleSits); - childSetCommitCallback("standtime",onSpinnerCommit); + getChild("AOEnabled")->setCommitCallback(boost::bind(&LLFloaterAO::onClickToggleAO)); + getChild("AOSitsEnabled")->setCommitCallback(boost::bind(&LLFloaterAO::onClickToggleSits)); + getChild("standtime")->setCommitCallback(boost::bind(&LLFloaterAO::onSpinnerCommit,_1)); mcomboBox_stands = getChild("stands"); mcomboBox_walks = getChild("walks"); mcomboBox_runs = getChild("runs"); @@ -376,28 +376,28 @@ BOOL LLFloaterAO::postBuild() mcomboBox_lands = getChild("lands"); mcomboBox_standups = getChild("standups"); mcomboBox_prejumps = getChild("prejumps"); - getChild("stands")->setCommitCallback(onComboBoxCommit); - getChild("walks")->setCommitCallback(onComboBoxCommit); - getChild("runs")->setCommitCallback(onComboBoxCommit); - getChild("jumps")->setCommitCallback(onComboBoxCommit); - getChild("sits")->setCommitCallback(onComboBoxCommit); - getChild("gsits")->setCommitCallback(onComboBoxCommit); - getChild("crouchs")->setCommitCallback(onComboBoxCommit); - getChild("cwalks")->setCommitCallback(onComboBoxCommit); - getChild("falls")->setCommitCallback(onComboBoxCommit); - getChild("hovers")->setCommitCallback(onComboBoxCommit); - getChild("flys")->setCommitCallback(onComboBoxCommit); - getChild("flyslows")->setCommitCallback(onComboBoxCommit); - getChild("flyups")->setCommitCallback(onComboBoxCommit); - getChild("flydowns")->setCommitCallback(onComboBoxCommit); - getChild("lands")->setCommitCallback(onComboBoxCommit); - getChild("standups")->setCommitCallback(onComboBoxCommit); - getChild("prejumps")->setCommitCallback(onComboBoxCommit); + getChild("stands")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("walks")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("runs")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("jumps")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("sits")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("gsits")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("crouchs")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("cwalks")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("falls")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("hovers")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("flys")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("flyslows")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("flyups")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("flydowns")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("lands")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("standups")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); + getChild("prejumps")->setCommitCallback(boost::bind(&LLFloaterAO::onComboBoxCommit,_1)); return TRUE; } -void LLFloaterAO::onSpinnerCommit(LLUICtrl* ctrl, void* userdata) +void LLFloaterAO::onSpinnerCommit(LLUICtrl* ctrl) { LLSpinCtrl* spin = (LLSpinCtrl*) ctrl; if(spin) @@ -409,7 +409,7 @@ void LLFloaterAO::onSpinnerCommit(LLUICtrl* ctrl, void* userdata) } } -void LLFloaterAO::onComboBoxCommit(LLUICtrl* ctrl, void* userdata) +void LLFloaterAO::onComboBoxCommit(LLUICtrl* ctrl) { LLComboBox* box = (LLComboBox*)ctrl; if(box) @@ -727,12 +727,12 @@ void LLFloaterAO::onClickLess(void* data) updateLayout(sInstance); } -void LLFloaterAO::onClickToggleAO(LLUICtrl *, void*) +void LLFloaterAO::onClickToggleAO() { run(); } -void LLFloaterAO::onClickToggleSits(LLUICtrl *, void*) +void LLFloaterAO::onClickToggleSits() { run(); } diff --git a/indra/newview/floaterao.h b/indra/newview/floaterao.h index 55cc7c052..72bdf2903 100644 --- a/indra/newview/floaterao.h +++ b/indra/newview/floaterao.h @@ -68,8 +68,8 @@ public: static void show(void*); static void init(); - static void onClickToggleAO(LLUICtrl *, void*); - static void onClickToggleSits(LLUICtrl *, void*); + static void onClickToggleAO(); + static void onClickToggleSits(); static void run(); static void updateLayout(LLFloaterAO* floater); @@ -115,8 +115,8 @@ private: static AONoteCardDropTarget* mAOItemDropTarget; static void AOItemDrop(LLViewerInventoryItem* item); - static void onSpinnerCommit(LLUICtrl* ctrl, void* userdata); - static void onComboBoxCommit(LLUICtrl* ctrl, void* userdata); + static void onSpinnerCommit(LLUICtrl* ctrl); + static void onComboBoxCommit(LLUICtrl* ctrl); static BOOL SetDefault(void *userdata, LLUUID ao_id, std::string defaultanim); BOOL mDirty; diff --git a/indra/newview/floaterlocalassetbrowse.cpp b/indra/newview/floaterlocalassetbrowse.cpp index eeb1ebfd4..ef6de943d 100644 --- a/indra/newview/floaterlocalassetbrowse.cpp +++ b/indra/newview/floaterlocalassetbrowse.cpp @@ -800,13 +800,13 @@ FloaterLocalAssetBrowser::FloaterLocalAssetBrowser() mUploadBtn->setClickedCallback( onClickUpload, this); // combo callback - mTypeComboBox->setCommitCallback(onCommitTypeCombo); + mTypeComboBox->setCommitCallback(boost::bind(&FloaterLocalAssetBrowser::onCommitTypeCombo,this)); // scrolllist callbacks - mBitmapList->setCommitCallback(onChooseBitmapList); + mBitmapList->setCommitCallback(boost::bind(&FloaterLocalAssetBrowser::onChooseBitmapList,this)); // checkbox callbacks - mUpdateChkBox->setCommitCallback(onClickUpdateChkbox); + mUpdateChkBox->setCommitCallback(boost::bind(&FloaterLocalAssetBrowser::onClickUpdateChkbox,this)); } @@ -857,34 +857,33 @@ void FloaterLocalAssetBrowser::onClickUpload(void* userdata) } } -void FloaterLocalAssetBrowser::onChooseBitmapList(LLUICtrl* ctrl, void *userdata) +void FloaterLocalAssetBrowser::onChooseBitmapList() { - bool button_status = sLFInstance->mBitmapList->isEmpty(); - sLFInstance->mDelBtn->setEnabled(!button_status); - sLFInstance->mUploadBtn->setEnabled(!button_status); + bool button_status = mBitmapList->isEmpty(); + mDelBtn->setEnabled(!button_status); + mUploadBtn->setEnabled(!button_status); - sLFInstance->UpdateRightSide(); + UpdateRightSide(); } -void FloaterLocalAssetBrowser::onClickUpdateChkbox(LLUICtrl *ctrl, void *userdata) +void FloaterLocalAssetBrowser::onClickUpdateChkbox() { - std::string temp_str = sLFInstance->mBitmapList->getSelectedItemLabel(BITMAPLIST_COL_ID); + std::string temp_str = mBitmapList->getSelectedItemLabel(BITMAPLIST_COL_ID); if ( !temp_str.empty() ) { gLocalBrowser->onUpdateBool( (LLUUID)temp_str ); - sLFInstance->UpdateRightSide(); + UpdateRightSide(); } } -void FloaterLocalAssetBrowser::onCommitTypeCombo(LLUICtrl* ctrl, void *userdata) +void FloaterLocalAssetBrowser::onCommitTypeCombo() { - std::string temp_str = sLFInstance->mBitmapList->getSelectedItemLabel(BITMAPLIST_COL_ID); + std::string temp_str = mBitmapList->getSelectedItemLabel(BITMAPLIST_COL_ID); if ( !temp_str.empty() ) { S32 selection = sLFInstance->mTypeComboBox->getCurrentIndex(); gLocalBrowser->onSetType( (LLUUID)temp_str, selection ); - } } diff --git a/indra/newview/floaterlocalassetbrowse.h b/indra/newview/floaterlocalassetbrowse.h index fb26cdccc..b95845710 100644 --- a/indra/newview/floaterlocalassetbrowse.h +++ b/indra/newview/floaterlocalassetbrowse.h @@ -236,13 +236,13 @@ private: static void onClickUpload(void* userdata); // ScrollList callback declarations - static void onChooseBitmapList(LLUICtrl* ctrl, void* userdata); + void onChooseBitmapList(); // Checkbox callback declarations - static void onClickUpdateChkbox(LLUICtrl* ctrl, void* userdata); + void onClickUpdateChkbox(); // Combobox type select - static void onCommitTypeCombo(LLUICtrl* ctrl, void* userdata); + void onCommitTypeCombo(); // Widgets LLButton* mAddBtn; diff --git a/indra/newview/hbfloatergrouptitles.cpp b/indra/newview/hbfloatergrouptitles.cpp index bd6de9efd..9ebdae508 100644 --- a/indra/newview/hbfloatergrouptitles.cpp +++ b/indra/newview/hbfloatergrouptitles.cpp @@ -127,8 +127,7 @@ BOOL HBFloaterGroupTitles::postBuild() { return FALSE; } - mTitlesList->setCallbackUserData(this); - mTitlesList->setDoubleClickCallback(onActivate); + mTitlesList->setDoubleClickCallback(boost::bind(&HBFloaterGroupTitles::onActivate,this)); childSetAction("activate", onActivate, this); update_titles_list(this); return TRUE; diff --git a/indra/newview/hippogridmanager.cpp b/indra/newview/hippogridmanager.cpp index c0ceef71d..222969450 100644 --- a/indra/newview/hippogridmanager.cpp +++ b/indra/newview/hippogridmanager.cpp @@ -51,6 +51,7 @@ HippoGridInfo::HippoGridInfo(const std::string& gridName) : mGridMessage(""), mXmlState(XML_VOID), mVoiceConnector("SLVoice"), + mIsInProductionGrid(false), mRenderCompat(true), mInvLinks(false), mAutoUpdate(false), @@ -75,21 +76,36 @@ bool HippoGridInfo::isOpenSimulator() const return (mPlatform == HippoGridInfo::PLATFORM_OPENSIM); } +bool HippoGridInfo::isAurora() const +{ + return (mPlatform == HippoGridInfo::PLATFORM_AURORA); +} + bool HippoGridInfo::isSecondLife() const { return (mPlatform == HippoGridInfo::PLATFORM_SECONDLIFE); } +bool HippoGridInfo::isInProductionGrid() const +{ + llassert(mPlatform == HippoGridInfo::PLATFORM_SECONDLIFE); + return mIsInProductionGrid; +} + const std::string& HippoGridInfo::getGridName() const { return mGridName; } -const std::string& HippoGridInfo::getGridOwner() const { - if(isSecondLife()) { +const std::string& HippoGridInfo::getGridOwner() const +{ + if(isSecondLife()) + { static const std::string ll = "Linden Lab"; return ll; - } else { + } + else + { return this->getGridName(); } } @@ -220,12 +236,20 @@ void HippoGridInfo::setGridNick(std::string gridNick) { setGridName(gridNick); } + if(gridNick == "secondlife") + { + mIsInProductionGrid = true; + } } void HippoGridInfo::setLoginUri(const std::string& loginUri) { std::string uri = loginUri; mLoginUri = sanitizeUri(uri); + if (utf8str_tolower(LLURI(uri).hostName()) == "login.agni.lindenlab.com") + { + mIsInProductionGrid = true; + } } void HippoGridInfo::setLoginPage(const std::string& loginPage) diff --git a/indra/newview/hippogridmanager.h b/indra/newview/hippogridmanager.h index 4f3ef634e..310033af7 100644 --- a/indra/newview/hippogridmanager.h +++ b/indra/newview/hippogridmanager.h @@ -38,7 +38,9 @@ public: Platform getPlatform(); bool isOpenSimulator() const; + bool isAurora() const; bool isSecondLife() const; + bool isInProductionGrid() const; // Should only be called if isSecondLife() returns true. const std::string& getGridName() const; const std::string& getGridOwner() const; const std::string& getLoginUri() const; @@ -110,6 +112,7 @@ private: std::string mPasswordUrl; std::string mSearchUrl; std::string mVoiceConnector; + bool mIsInProductionGrid; bool mRenderCompat; bool mInvLinks; bool mAutoUpdate; diff --git a/indra/newview/hippolimits.cpp b/indra/newview/hippolimits.cpp index 3bdec44d3..c5aa2c7b1 100644 --- a/indra/newview/hippolimits.cpp +++ b/indra/newview/hippolimits.cpp @@ -21,6 +21,8 @@ void HippoLimits::setLimits() { if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_SECONDLIFE) { setSecondLifeLimits(); + } else if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_AURORA) { + setAuroraLimits(); } else { setOpenSimLimits(); } @@ -46,6 +48,17 @@ void HippoLimits::setOpenSimLimits() } } +void HippoLimits::setAuroraLimits() +{ + mMaxAgentGroups = gHippoGridManager->getConnectedGrid()->getMaxAgentGroups(); + if (mMaxAgentGroups < 0) mMaxAgentGroups = 50; + mMaxPrimScale = 256.0f; + mMinPrimScale = 0.001f; + mMaxHeight = 8192.0f; + mMinHoleSize = 0.001f; + mMaxHollow = 99.0f; +} + void HippoLimits::setSecondLifeLimits() { llinfos << "Using Second Life limits." << llendl; diff --git a/indra/newview/hippolimits.h b/indra/newview/hippolimits.h index 78d42a7df..91625276b 100644 --- a/indra/newview/hippolimits.h +++ b/indra/newview/hippolimits.h @@ -26,6 +26,7 @@ private: float mMinPrimScale; void setOpenSimLimits(); + void setAuroraLimits(); void setSecondLifeLimits(); }; diff --git a/indra/newview/jcfloaterareasearch.cpp b/indra/newview/jcfloaterareasearch.cpp index 3cb15b052..8479b9a3b 100644 --- a/indra/newview/jcfloaterareasearch.cpp +++ b/indra/newview/jcfloaterareasearch.cpp @@ -88,8 +88,7 @@ void JCFloaterAreaSearch::close(bool app) BOOL JCFloaterAreaSearch::postBuild() { mResultList = getChild("result_list"); - mResultList->setCallbackUserData(this); - mResultList->setDoubleClickCallback(onDoubleClick); + mResultList->setDoubleClickCallback(onDoubleClick,this); mResultList->sortByColumn("Name", TRUE); mCounterText = getChild("counter"); @@ -235,7 +234,7 @@ void JCFloaterAreaSearch::results() if (!(sInstance->getVisible())) return; if (sRequested > 0 && sInstance->mLastUpdateTimer.getElapsedTimeF32() < min_refresh_interval) return; //llinfos << "results()" << llendl; - LLDynamicArray selected = sInstance->mResultList->getSelectedIDs(); + uuid_vec_t selected = sInstance->mResultList->getSelectedIDs(); S32 scrollpos = sInstance->mResultList->getScrollPos(); sInstance->mResultList->deleteAllItems(); S32 i; @@ -303,7 +302,7 @@ void JCFloaterAreaSearch::results() } } - sInstance->mResultList->sortItems(); + sInstance->mResultList->updateSort(); sInstance->mResultList->selectMultiple(selected); sInstance->mResultList->setScrollPos(scrollpos); sInstance->mCounterText->setText(llformat("%d listed/%d pending/%d total", sInstance->mResultList->getItemCount(), sRequested, sObjectDetails.size())); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 4cb74f011..61b771ea2 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -50,7 +50,6 @@ #include "llmoveview.h" #include "llchatbar.h" #include "llnotificationsutil.h" -#include "llpanelpathfindingrebakenavmesh.h" #include "llparcel.h" #include "llrendersphere.h" #include "llsdmessage.h" @@ -77,6 +76,7 @@ #include "llvoavatarself.h" #include "llworld.h" #include "llworldmap.h" +#include "llworldmapmessage.h" //Misc non-standard includes #include "llurldispatcher.h" @@ -130,6 +130,104 @@ std::string gAuthString; LLUUID gReSitTargetID; LLVector3 gReSitOffset; // +class LLTeleportRequest +{ +public: + enum EStatus + { + kPending, + kStarted, + kFailed, + kRestartPending + }; + + LLTeleportRequest(); + virtual ~LLTeleportRequest(); + + EStatus getStatus() const {return mStatus;}; + void setStatus(EStatus pStatus) {mStatus = pStatus;}; + + virtual bool canRestartTeleport(); + + virtual void startTeleport() = 0; + virtual void restartTeleport(); + +protected: + +private: + EStatus mStatus; +}; + +class LLTeleportRequestViaLandmark : public LLTeleportRequest +{ +public: + LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId); + virtual ~LLTeleportRequestViaLandmark(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + virtual void restartTeleport(); + +protected: + inline const LLUUID &getLandmarkId() const {return mLandmarkId;}; + +private: + LLUUID mLandmarkId; +}; + +class LLTeleportRequestViaLure : public LLTeleportRequestViaLandmark +{ +public: + LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike); + virtual ~LLTeleportRequestViaLure(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + +protected: + inline BOOL isLureGodLike() const {return mIsLureGodLike;}; + +private: + BOOL mIsLureGodLike; +}; + +class LLTeleportRequestViaLocation : public LLTeleportRequest +{ +public: + LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal); + virtual ~LLTeleportRequestViaLocation(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + virtual void restartTeleport(); + +protected: + inline const LLVector3d &getPosGlobal() const {return mPosGlobal;}; + +private: + LLVector3d mPosGlobal; +}; + + +class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation +{ +public: + LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal); + virtual ~LLTeleportRequestViaLocationLookAt(); + + virtual bool canRestartTeleport(); + + virtual void startTeleport(); + virtual void restartTeleport(); + +protected: + +private: + +}; //-------------------------------------------------------------------- // Statics // @@ -200,6 +298,19 @@ LLAgent::LLAgent() : mbTeleportKeepsLookAt(false), mAgentAccess(new LLAgentAccess(gSavedSettings)), + mGodLevelChangeSignal(), + mCanEditParcel(false), + mTeleportRequest(), + mTeleportFinishedSlot(), + mTeleportFailedSlot(), + mIsMaturityRatingChangingDuringTeleport(false), + mMaturityRatingChange(0U), + mIsDoSendMaturityPreferenceToServer(false), + mMaturityPreferenceRequestId(0U), + mMaturityPreferenceResponseId(0U), + mMaturityPreferenceNumRetries(0U), + mLastKnownRequestMaturity(SIM_ACCESS_MIN), + mLastKnownResponseMaturity(SIM_ACCESS_MIN), mTeleportState( TELEPORT_NONE ), mRegionp(NULL), @@ -276,9 +387,21 @@ void LLAgent::init() gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2)); gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2)); + mLastKnownResponseMaturity = static_cast(gSavedSettings.getU32("PreferredMaturity")); + mLastKnownRequestMaturity = mLastKnownResponseMaturity; + mIsDoSendMaturityPreferenceToServer = true; LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLAgent::parcelChangedCallback)); + if (!mTeleportFinishedSlot.connected()) + { + mTeleportFinishedSlot = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(boost::bind(&LLAgent::handleTeleportFinished, this)); + } + if (!mTeleportFailedSlot.connected()) + { + mTeleportFailedSlot = LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&LLAgent::handleTeleportFailed, this)); + } + mInitialized = TRUE; } @@ -291,6 +414,14 @@ void LLAgent::cleanup() if(mPendingLure) delete mPendingLure; mPendingLure = NULL; + if (mTeleportFinishedSlot.connected()) + { + mTeleportFinishedSlot.disconnect(); + } + if (mTeleportFailedSlot.connected()) + { + mTeleportFailedSlot.disconnect(); + } } //----------------------------------------------------------------------------- @@ -1421,7 +1552,7 @@ void LLAgent::setAutoPilotTargetGlobal(const LLVector3d &target_global) LLViewerObject *obj; LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, traceEndPt, targetOnGround, groundNorm, &obj); - F64 target_height = llmax((F64)gAgentAvatarp->getPelvisToFoot(), target_global.mdV[VZ] - targetOnGround.mdV[VZ]); + F64 target_height = llmax((F64)(isAgentAvatarValid() ? gAgentAvatarp->getPelvisToFoot() : 0.0), target_global.mdV[VZ] - targetOnGround.mdV[VZ]); // clamp z value of target to minimum height above ground mAutoPilotTargetGlobal.mdV[VZ] = targetOnGround.mdV[VZ] + target_height; @@ -1865,7 +1996,6 @@ void LLAgent::endAnimationUpdateUI() gMenuBarView->setVisible(TRUE); gStatusBar->setVisibleForMouselook(true); - LLPanelPathfindingRebakeNavmesh::getInstance()->setVisible(TRUE); LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); @@ -1959,7 +2089,6 @@ void LLAgent::endAnimationUpdateUI() gMenuBarView->setVisible(FALSE); gStatusBar->setVisibleForMouselook(false); - LLPanelPathfindingRebakeNavmesh::getInstance()->setVisible(FALSE); // clear out camera lag effect gAgentCamera.clearCameraLag(); @@ -2376,38 +2505,271 @@ int LLAgent::convertTextToMaturity(char text) return LLAgentAccess::convertTextToMaturity(text); } -bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity) +extern AIHTTPTimeoutPolicy maturityPreferences_timeout; +class LLMaturityPreferencesResponder : public LLHTTPClient::ResponderWithResult { - if (!getRegion()) - return false; - - // Update agent access preference on the server - std::string url = getRegion()->getCapability("UpdateAgentInformation"); - if (!url.empty()) - { - // Set new access preference - LLSD access_prefs = LLSD::emptyMap(); - if (preferredMaturity == SIM_ACCESS_PG) - { - access_prefs["max"] = "PG"; - } - else if (preferredMaturity == SIM_ACCESS_MATURE) - { - access_prefs["max"] = "M"; - } - if (preferredMaturity == SIM_ACCESS_ADULT) - { - access_prefs["max"] = "A"; - } +public: + LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity); + virtual ~LLMaturityPreferencesResponder(); - LLSD body = LLSD::emptyMap(); - body["access_prefs"] = access_prefs; - llinfos << "Sending access prefs update to " << (access_prefs["max"].asString()) << " via capability to: " - << url << llendl; - LLHTTPClient::post(url, body, new LLHTTPClient::ResponderIgnore); // Ignore response - return true; + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string& pReason); + + virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return maturityPreferences_timeout; } + +private: + U8 parseMaturityFromServerResponse(const LLSD &pContent); + + LLAgent *mAgent; + U8 mPreferredMaturity; + U8 mPreviousMaturity; +}; + +LLMaturityPreferencesResponder::LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity) : + mAgent(pAgent), + mPreferredMaturity(pPreferredMaturity), + mPreviousMaturity(pPreviousMaturity) +{ +} + +LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder() +{ +} + +void LLMaturityPreferencesResponder::result(const LLSD &pContent) +{ + U8 actualMaturity = parseMaturityFromServerResponse(pContent); + + if (actualMaturity != mPreferredMaturity) + { + llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', the server responded with '" + << LLViewerRegion::accessToString(actualMaturity) << "' [value:" << static_cast(actualMaturity) << ", llsd:" + << pContent << "]" << llendl; + } + mAgent->handlePreferredMaturityResult(actualMaturity); +} + +void LLMaturityPreferencesResponder::error(U32 pStatus, const std::string& pReason) +{ + llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error because '" + << pReason << "' [status:" << pStatus << "]" << llendl; + mAgent->handlePreferredMaturityError(); +} + +U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) +{ + // stinson 05/24/2012 Pathfinding regions have re-defined the response behavior. In the old server code, + // if you attempted to change the preferred maturity to the same value, the response content would be an + // undefined LLSD block. In the new server code with pathfinding, the response content should always be + // defined. Thus, the check for isUndefined() can be replaced with an assert after pathfinding is merged + // into server trunk and fully deployed. + U8 maturity = SIM_ACCESS_MIN; + if (pContent.isUndefined()) + { + maturity = mPreferredMaturity; + } + else + { + llassert(!pContent.isUndefined()); + llassert(pContent.isMap()); + + if (!pContent.isUndefined() && pContent.isMap()) + { + // stinson 05/24/2012 Pathfinding regions have re-defined the response syntax. The if statement catches + // the new syntax, and the else statement catches the old syntax. After pathfinding is merged into + // server trunk and fully deployed, we can remove the else statement. + if (pContent.has("access_prefs")) + { + llassert(pContent.has("access_prefs")); + llassert(pContent.get("access_prefs").isMap()); + llassert(pContent.get("access_prefs").has("max")); + llassert(pContent.get("access_prefs").get("max").isString()); + if (pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max") && + pContent.get("access_prefs").get("max").isString()) + { + LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString(); + LLStringUtil::trim(actualPreference); + maturity = LLViewerRegion::shortStringToAccess(actualPreference); + } + } + else if (pContent.has("max")) + { + llassert(pContent.get("max").isString()); + if (pContent.get("max").isString()) + { + LLSD::String actualPreference = pContent.get("max").asString(); + LLStringUtil::trim(actualPreference); + maturity = LLViewerRegion::shortStringToAccess(actualPreference); + } + } + } + } + + return maturity; +} + +void LLAgent::handlePreferredMaturityResult(U8 pServerMaturity) +{ + // Update the number of responses received + ++mMaturityPreferenceResponseId; + llassert(mMaturityPreferenceResponseId <= mMaturityPreferenceRequestId); + + // Update the last known server maturity response + mLastKnownResponseMaturity = pServerMaturity; + + // Ignore all responses if we know there are more unanswered requests that are expected + if (mMaturityPreferenceResponseId == mMaturityPreferenceRequestId) + { + // If we received a response that matches the last known request, then we are good + if (mLastKnownRequestMaturity == mLastKnownResponseMaturity) + { + mMaturityPreferenceNumRetries = 0; + reportPreferredMaturitySuccess(); + llassert(static_cast(gSavedSettings.getU32("PreferredMaturity")) == mLastKnownResponseMaturity); + } + // Else, the viewer is out of sync with the server, so let's try to re-sync with the + // server by re-sending our last known request. Cap the re-tries at 3 just to be safe. + else if (++mMaturityPreferenceNumRetries <= 3) + { + llinfos << "Retrying attempt #" << mMaturityPreferenceNumRetries << " to set viewer preferred maturity to '" + << LLViewerRegion::accessToString(mLastKnownRequestMaturity) << "'" << llendl; + sendMaturityPreferenceToServer(mLastKnownRequestMaturity); + } + // Else, the viewer is style out of sync with the server after 3 retries, so inform the user + else + { + mMaturityPreferenceNumRetries = 0; + reportPreferredMaturityError(); + } + } +} + +void LLAgent::handlePreferredMaturityError() +{ + // Update the number of responses received + ++mMaturityPreferenceResponseId; + llassert(mMaturityPreferenceResponseId <= mMaturityPreferenceRequestId); + + // Ignore all responses if we know there are more unanswered requests that are expected + if (mMaturityPreferenceResponseId == mMaturityPreferenceRequestId) + { + mMaturityPreferenceNumRetries = 0; + + // If we received a response that matches the last known request, then we are synced with + // the server, but not quite sure why we are + if (mLastKnownRequestMaturity == mLastKnownResponseMaturity) + { + llwarns << "Got an error but maturity preference '" << LLViewerRegion::accessToString(mLastKnownRequestMaturity) + << "' seems to be in sync with the server" << llendl; + reportPreferredMaturitySuccess(); + } + // Else, the more likely case is that the last request does not match the last response, + // so inform the user + else + { + reportPreferredMaturityError(); + } + } +} + +void LLAgent::reportPreferredMaturitySuccess() +{ + // If there is a pending teleport request waiting for the maturity preference to be synced with + // the server, let's start the pending request + if (hasPendingTeleportRequest()) + { + startTeleportRequest(); + } +} + +void LLAgent::reportPreferredMaturityError() +{ + // If there is a pending teleport request waiting for the maturity preference to be synced with + // the server, we were unable to successfully sync with the server on maturity preference, so let's + // just raise the screen. + mIsMaturityRatingChangingDuringTeleport = false; + if (hasPendingTeleportRequest()) + { + setTeleportState(LLAgent::TELEPORT_NONE); + } + + // Get the last known maturity request from the user activity + std::string preferredMaturity = LLViewerRegion::accessToString(mLastKnownRequestMaturity); + LLStringUtil::toLower(preferredMaturity); + + // Get the last known maturity response from the server + std::string actualMaturity = LLViewerRegion::accessToString(mLastKnownResponseMaturity); + LLStringUtil::toLower(actualMaturity); + + // Notify the user + LLSD args = LLSD::emptyMap(); + args["PREFERRED_MATURITY"] = preferredMaturity; + args["ACTUAL_MATURITY"] = actualMaturity; + LLNotificationsUtil::add("MaturityChangeError", args); + + // Check the saved settings to ensure that we are consistent. If we are not consistent, update + // the viewer, but do not send anything to server + U8 localMaturity = static_cast(gSavedSettings.getU32("PreferredMaturity")); + if (localMaturity != mLastKnownResponseMaturity) + { + bool tmpIsDoSendMaturityPreferenceToServer = mIsDoSendMaturityPreferenceToServer; + mIsDoSendMaturityPreferenceToServer = false; + llinfos << "Setting viewer preferred maturity to '" << LLViewerRegion::accessToString(mLastKnownResponseMaturity) << "'" << llendl; + gSavedSettings.setU32("PreferredMaturity", static_cast(mLastKnownResponseMaturity)); + mIsDoSendMaturityPreferenceToServer = tmpIsDoSendMaturityPreferenceToServer; + } +} + +bool LLAgent::isMaturityPreferenceSyncedWithServer() const +{ + return (mMaturityPreferenceRequestId == mMaturityPreferenceResponseId); +} + +void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) +{ + // Only send maturity preference to the server if enabled + if (mIsDoSendMaturityPreferenceToServer) + { + // Increment the number of requests. The handlers manage a separate count of responses. + ++mMaturityPreferenceRequestId; + + // Update the last know maturity request + mLastKnownRequestMaturity = pPreferredMaturity; + + // Create a response handler + boost::intrusive_ptr responderPtr = new LLMaturityPreferencesResponder(this, pPreferredMaturity, mLastKnownResponseMaturity); + + // If we don't have a region, report it as an error + if (getRegion() == NULL) + { + responderPtr->error(0U, "region is not defined"); + } + else + { + // Find the capability to send maturity preference + std::string url = getRegion()->getCapability("UpdateAgentInformation"); + + // If the capability is not defined, report it as an error + if (url.empty()) + { + responderPtr->error(0U, "capability 'UpdateAgentInformation' is not defined for region"); + } + else + { + // Set new access preference + LLSD access_prefs = LLSD::emptyMap(); + access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity); + + LLSD body = LLSD::emptyMap(); + body["access_prefs"] = access_prefs; + llinfos << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) + << "' via capability to: " << url << llendl; + LLHTTPClient::post(url, body, responderPtr); + } + } } - return false; } BOOL LLAgent::getAdminOverride() const @@ -2428,6 +2790,12 @@ void LLAgent::setAdminOverride(BOOL b) void LLAgent::setGodLevel(U8 god_level) { mAgentAccess->setGodLevel(god_level); + mGodLevelChangeSignal(god_level); +} + +LLAgent::god_level_change_slot_t LLAgent::registerGodLevelChanageListener(god_level_change_callback_t pGodLevelChangeCallback) +{ + return mGodLevelChangeSignal.connect(pGodLevelChangeCallback); } void LLAgent::setAOTransition() @@ -2445,9 +2813,9 @@ bool LLAgent::validateMaturity(const LLSD& newvalue) return mAgentAccess->canSetMaturity(newvalue.asInteger()); } -void LLAgent::handleMaturity(const LLSD& newvalue) +void LLAgent::handleMaturity(const LLSD &pNewValue) { - sendMaturityPreferenceToServer(newvalue.asInteger()); + sendMaturityPreferenceToServer(static_cast(pNewValue.asInteger())); } void LLAgent::buildFullname(std::string& name) const @@ -3459,7 +3827,7 @@ void LLAgent::clearVisualParams(void *data) // protected bool LLAgent::teleportCore(bool is_local) { - if(TELEPORT_NONE != mTeleportState) + if ((TELEPORT_NONE != mTeleportState) && (mTeleportState != TELEPORT_PENDING)) { llwarns << "Attempt to teleport when already teleporting." << llendl; // @@ -3518,8 +3886,12 @@ bool LLAgent::teleportCore(bool is_local) gTeleportDisplay = TRUE; gAgent.setTeleportState( LLAgent::TELEPORT_START ); - //release geometry from old location - gPipeline.resetVertexBuffers(); + /*static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); + if(!hide_tp_screen) + { + //release geometry from old location + gPipeline.resetVertexBuffers(); + }*/ if (gSavedSettings.getBOOL("SpeedRez")) { @@ -3542,6 +3914,102 @@ bool LLAgent::teleportCore(bool is_local) return true; } +bool LLAgent::hasRestartableFailedTeleportRequest() +{ + return ((mTeleportRequest != NULL) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed) && + mTeleportRequest->canRestartTeleport()); +} + +void LLAgent::restartFailedTeleportRequest() +{ + if (hasRestartableFailedTeleportRequest()) + { + mTeleportRequest->setStatus(LLTeleportRequest::kRestartPending); + startTeleportRequest(); + } +} + +void LLAgent::clearTeleportRequest() +{ + mTeleportRequest.reset(); +} + +void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange) +{ + mIsMaturityRatingChangingDuringTeleport = true; + mMaturityRatingChange = pMaturityRatingChange; +} + +bool LLAgent::hasPendingTeleportRequest() +{ + return ((mTeleportRequest != NULL) && + ((mTeleportRequest->getStatus() == LLTeleportRequest::kPending) || + (mTeleportRequest->getStatus() == LLTeleportRequest::kRestartPending))); +} + +void LLAgent::startTeleportRequest() +{ + if (hasPendingTeleportRequest()) + { + if (!isMaturityPreferenceSyncedWithServer()) + { + gTeleportDisplay = TRUE; + setTeleportState(TELEPORT_PENDING); + } + else + { + switch (mTeleportRequest->getStatus()) + { + case LLTeleportRequest::kPending : + mTeleportRequest->setStatus(LLTeleportRequest::kStarted); + mTeleportRequest->startTeleport(); + break; + case LLTeleportRequest::kRestartPending : + llassert(mTeleportRequest->canRestartTeleport()); + mTeleportRequest->setStatus(LLTeleportRequest::kStarted); + mTeleportRequest->restartTeleport(); + break; + default : + llassert(0); + break; + } + } + } +} + +void LLAgent::handleTeleportFinished() +{ + clearTeleportRequest(); + if (mIsMaturityRatingChangingDuringTeleport) + { + // notify user that the maturity preference has been changed + std::string maturityRating = LLViewerRegion::accessToString(mMaturityRatingChange); + LLStringUtil::toLower(maturityRating); + LLSD args; + args["RATING"] = maturityRating; + LLNotificationsUtil::add("PreferredMaturityChanged", args); + mIsMaturityRatingChangingDuringTeleport = false; + } +} + +void LLAgent::handleTeleportFailed() +{ + if (mTeleportRequest != NULL) + { + mTeleportRequest->setStatus(LLTeleportRequest::kFailed); + } + if (mIsMaturityRatingChangingDuringTeleport) + { + // notify user that the maturity preference has been changed + std::string maturityRating = LLViewerRegion::accessToString(mMaturityRatingChange); + LLStringUtil::toLower(maturityRating); + LLSD args; + args["RATING"] = maturityRating; + LLNotificationsUtil::add("PreferredMaturityChanged", args); + mIsMaturityRatingChangingDuringTeleport = false; + } +} + void LLAgent::teleportRequest( const U64& region_handle, const LLVector3& pos_local, @@ -3588,7 +4056,12 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) return; } // [/RLVa:KB] + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLandmark(landmark_asset_id)); + startTeleportRequest(); +} +void LLAgent::doTeleportViaLandmark(const LLUUID& landmark_asset_id) +{ LLViewerRegion *regionp = getRegion(); if(regionp && teleportCore()) { @@ -3603,6 +4076,12 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) } void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike) +{ + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLure(lure_id, godlike)); + startTeleportRequest(); +} + +void LLAgent::doTeleportViaLure(const LLUUID& lure_id, BOOL godlike) { LLViewerRegion* regionp = getRegion(); if(regionp && teleportCore()) @@ -3635,18 +4114,21 @@ void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike) // James Cook, July 28, 2005 void LLAgent::teleportCancel() { - LLViewerRegion* regionp = getRegion(); - if(regionp) + if (!hasPendingTeleportRequest()) { - // send the message - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("TeleportCancel"); - msg->nextBlockFast(_PREHASH_Info); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - sendReliableMessage(); - } - gTeleportDisplay = FALSE; + LLViewerRegion* regionp = getRegion(); + if(regionp) + { + // send the message + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("TeleportCancel"); + msg->nextBlockFast(_PREHASH_Info); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + sendReliableMessage(); + } + } + clearTeleportRequest(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } @@ -3671,13 +4153,24 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) } } // [/RLVa:KB] + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocation(pos_global)); + startTeleportRequest(); +} +void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global) +{ LLViewerRegion* regionp = getRegion(); + + if (!regionp) + { + return; + } + U64 handle = to_region_handle(pos_global); LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); bool calc = gSavedSettings.getBOOL("OptionOffsetTPByAgentHeight"); LLVector3 offset = LLVector3(0.f,0.f,0.f); - if(calc) + if(calc && isAgentAvatarValid()) offset += LLVector3(0.f,0.f,gAgentAvatarp->getScale().mV[2] / 2.0); if(regionp && info) { @@ -3687,7 +4180,7 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) (F32)(pos_global.mdV[VY] - region_origin.mdV[VY]), (F32)(pos_global.mdV[VZ])); pos_local += offset; - teleportRequest(info->getHandle(), 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]))) @@ -3732,14 +4225,15 @@ void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) return; } // [/RLVa:KB] + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocationLookAt(pos_global)); + startTeleportRequest(); +} +void LLAgent::doTeleportViaLocationLookAt(const LLVector3d& pos_global) +{ mbTeleportKeepsLookAt = true; gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction U64 region_handle = to_region_handle(pos_global); - LLSimInfo* simInfo = LLWorldMap::instance().simInfoFromHandle(region_handle); - if(simInfo) - region_handle = simInfo->getHandle(); - LLVector3 pos_local = (LLVector3)(pos_global - from_region_handle(region_handle)); teleportRequest(region_handle, pos_local, getTeleportKeepsLookAt()); } @@ -4179,7 +4673,7 @@ void LLAgent::showLureDestination(const std::string fromname, const int global_x { U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); - LLWorldMap::getInstance()->sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); //Will call onFoundLureDestination on response + LLWorldMapMessage::getInstance()->sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); //Will call onFoundLureDestination on response } } @@ -4232,4 +4726,148 @@ LLAgentQueryManager::~LLAgentQueryManager() { } +//----------------------------------------------------------------------------- +// LLTeleportRequest +//----------------------------------------------------------------------------- + +LLTeleportRequest::LLTeleportRequest() + : mStatus(kPending) +{ +} + +LLTeleportRequest::~LLTeleportRequest() +{ +} + +bool LLTeleportRequest::canRestartTeleport() +{ + return false; +} + +void LLTeleportRequest::restartTeleport() +{ + llassert(0); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLandmark +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLandmark::LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId) + : LLTeleportRequest(), + mLandmarkId(pLandmarkId) +{ +} + +LLTeleportRequestViaLandmark::~LLTeleportRequestViaLandmark() +{ +} + +bool LLTeleportRequestViaLandmark::canRestartTeleport() +{ + return true; +} + +void LLTeleportRequestViaLandmark::startTeleport() +{ + gAgent.doTeleportViaLandmark(getLandmarkId()); +} + +void LLTeleportRequestViaLandmark::restartTeleport() +{ + gAgent.doTeleportViaLandmark(getLandmarkId()); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLure +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLure::LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike) + : LLTeleportRequestViaLandmark(pLureId), + mIsLureGodLike(pIsLureGodLike) +{ +} + +LLTeleportRequestViaLure::~LLTeleportRequestViaLure() +{ +} + +bool LLTeleportRequestViaLure::canRestartTeleport() +{ + // stinson 05/17/2012 : cannot restart a teleport via lure because of server-side restrictions + // The current scenario is as follows: + // 1. User A initializes a request for User B to teleport via lure + // 2. User B accepts the teleport via lure request + // 3. The server sees the init request from User A and the accept request from User B and matches them up + // 4. The server then removes the paired requests up from the "queue" + // 5. The server then fails User B's teleport for reason of maturity level (for example) + // 6. User B's viewer prompts user to increase their maturity level profile value. + // 7. User B confirms and accepts increase in maturity level + // 8. User B's viewer then attempts to teleport via lure again + // 9. This request will time-out on the viewer-side because User A's initial request has been removed from the "queue" in step 4 + + return false; +} + +void LLTeleportRequestViaLure::startTeleport() +{ + gAgent.doTeleportViaLure(getLandmarkId(), isLureGodLike()); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLocation +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLocation::LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal) + : LLTeleportRequest(), + mPosGlobal(pPosGlobal) +{ +} + +LLTeleportRequestViaLocation::~LLTeleportRequestViaLocation() +{ +} + +bool LLTeleportRequestViaLocation::canRestartTeleport() +{ + return true; +} + +void LLTeleportRequestViaLocation::startTeleport() +{ + gAgent.doTeleportViaLocation(getPosGlobal()); +} + +void LLTeleportRequestViaLocation::restartTeleport() +{ + gAgent.doTeleportViaLocation(getPosGlobal()); +} + +//----------------------------------------------------------------------------- +// LLTeleportRequestViaLocationLookAt +//----------------------------------------------------------------------------- + +LLTeleportRequestViaLocationLookAt::LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal) + : LLTeleportRequestViaLocation(pPosGlobal) +{ +} + +LLTeleportRequestViaLocationLookAt::~LLTeleportRequestViaLocationLookAt() +{ +} + +bool LLTeleportRequestViaLocationLookAt::canRestartTeleport() +{ + return true; +} + +void LLTeleportRequestViaLocationLookAt::startTeleport() +{ + gAgent.doTeleportViaLocationLookAt(getPosGlobal()); +} + +void LLTeleportRequestViaLocationLookAt::restartTeleport() +{ + gAgent.doTeleportViaLocationLookAt(getPosGlobal()); +} // EOF diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 82513766e..67dd6a3ff 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -47,6 +47,8 @@ #include "llinventorymodel.h" #include "v3dmath.h" +#include +#include #include extern const BOOL ANIMATE; @@ -67,8 +69,10 @@ class LLViewerObject; class LLAgentDropGroupViewerNode; class LLAgentAccess; class LLSimInfo; +class LLTeleportRequest; typedef std::vector llvo_vec_t; +typedef boost::shared_ptr LLTeleportRequestPtr; enum EAnimRequest { @@ -557,7 +561,8 @@ public: TELEPORT_MOVING = 3, // Viewer has received destination location from source simulator TELEPORT_START_ARRIVAL = 4, // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator TELEPORT_ARRIVING = 5, // Make the user wait while content "pre-caches" - TELEPORT_LOCAL = 6 // Teleporting in-sim without showing the progress screen + TELEPORT_LOCAL = 6, // Teleporting in-sim without showing the progress screen + TELEPORT_PENDING = 7 }; public: @@ -573,9 +578,6 @@ public: // Teleport Actions //-------------------------------------------------------------------- public: - void teleportRequest(const U64& region_handle, - const LLVector3& pos_local, // Go to a named location home - bool look_at_from_camera = false); void teleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark void teleportHome() { teleportViaLandmark(LLUUID::null); } // Go home void teleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location @@ -586,6 +588,44 @@ public: protected: bool teleportCore(bool is_local = false); // Stuff for all teleports; returns true if the teleport can proceed + //-------------------------------------------------------------------- + // Teleport State + //-------------------------------------------------------------------- + +public: + bool hasRestartableFailedTeleportRequest(); + void restartFailedTeleportRequest(); + void clearTeleportRequest(); + void setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange); + +private: + friend class LLTeleportRequest; + friend class LLTeleportRequestViaLandmark; + friend class LLTeleportRequestViaLure; + friend class LLTeleportRequestViaLocation; + friend class LLTeleportRequestViaLocationLookAt; + + LLTeleportRequestPtr mTeleportRequest; + boost::signals2::connection mTeleportFinishedSlot; + boost::signals2::connection mTeleportFailedSlot; + + bool mIsMaturityRatingChangingDuringTeleport; + U8 mMaturityRatingChange; + + bool hasPendingTeleportRequest(); + void startTeleportRequest(); + + void teleportRequest(const U64& region_handle, + const LLVector3& pos_local, // Go to a named location home + bool look_at_from_camera = false); + void doTeleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark + void doTeleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location + void doTeleportViaLocation(const LLVector3d& pos_global); // To a global location - this will probably need to be deprecated + void doTeleportViaLocationLookAt(const LLVector3d& pos_global);// To a global location, preserving camera rotation + + void handleTeleportFinished(); + void handleTeleportFailed(); + //-------------------------------------------------------------------- // Teleport State //-------------------------------------------------------------------- @@ -648,6 +688,16 @@ public: void requestEnterGodMode(); void requestLeaveGodMode(); + typedef boost::function god_level_change_callback_t; + typedef boost::signals2::signal god_level_change_signal_t; + typedef boost::signals2::connection god_level_change_slot_t; + + god_level_change_slot_t registerGodLevelChanageListener(god_level_change_callback_t pGodLevelChangeCallback); + +private: + god_level_change_signal_t mGodLevelChangeSignal; + + //-------------------------------------------------------------------- // Maturity //-------------------------------------------------------------------- @@ -670,10 +720,25 @@ public: void setTeen(bool teen); void setMaturity(char text); static int convertTextToMaturity(char text); - bool sendMaturityPreferenceToServer(int preferredMaturity); // ! "U8" instead of "int"? +private: + bool mIsDoSendMaturityPreferenceToServer; + unsigned int mMaturityPreferenceRequestId; + unsigned int mMaturityPreferenceResponseId; + unsigned int mMaturityPreferenceNumRetries; + U8 mLastKnownRequestMaturity; + U8 mLastKnownResponseMaturity; + + bool isMaturityPreferenceSyncedWithServer() const; + void sendMaturityPreferenceToServer(U8 pPreferredMaturity); + + friend class LLMaturityPreferencesResponder; + void handlePreferredMaturityResult(U8 pServerMaturity); + void handlePreferredMaturityError(); + void reportPreferredMaturitySuccess(); + void reportPreferredMaturityError(); // Maturity callbacks for PreferredMaturity control variable - void handleMaturity(const LLSD& newvalue); + void handleMaturity(const LLSD &pNewValue); bool validateMaturity(const LLSD& newvalue); diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 93390e1e5..24eea1733 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -410,11 +410,7 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi } LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation - LLVector3 object_extents = object->getScale(); - //this stuff just seems to make camera snapping worse... - //const LLVector4a* oe4 = object->mDrawable->getSpatialExtents(); - //object_extents.set( oe4[1][0], oe4[1][1], oe4[1][2] ); - + LLVector3 object_extents = object->getScale(); // make sure they object extents are non-zero object_extents.clamp(0.001f, F32_MAX); @@ -1637,7 +1633,7 @@ LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal() { gPipeline.updateMoveNormalAsync(drawablep); } - else + else if(!drawablep->isState(LLDrawable::ON_MOVE_LIST)) { if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) { @@ -1844,8 +1840,9 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) local_camera_offset = gAgent.getFrameAgent().rotateToAbsolute( local_camera_offset ); } + static const LLCachedControl sg_ignore_sim_cam_consts("SGIgnoreSimulatorCameraConstraints",false); if ( !mCameraCollidePlane.isExactlyZero() - && !gSavedSettings.getBOOL("SGIgnoreSimulatorCameraConstraints") + && !sg_ignore_sim_cam_consts && isAgentAvatarValid() && !gAgentAvatarp->isSitting()) { @@ -2311,12 +2308,7 @@ void LLAgentCamera::changeCameraToThirdPerson(BOOL animate) } updateLastCamera(); mCameraMode = CAMERA_MODE_THIRD_PERSON; - U32 old_flags = gAgent.getControlFlags(); gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != gAgent.getControlFlags()) - { - gAgent.setFlagsDirty(); - } } // Remove any pitch from the avatar @@ -2522,9 +2514,10 @@ void LLAgentCamera::setFocusObject(LLViewerObject* object) //----------------------------------------------------------------------------- void LLAgentCamera::setFocusGlobal(const LLPickInfo& pick) { + static const LLCachedControl freeze_time("FreezeTime",false); LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); - if (objectp) + if (objectp && !freeze_time) { // focus on object plus designated offset // which may or may not be same as pick.mPosGlobal @@ -2802,18 +2795,18 @@ void LLAgentCamera::lookAtLastChat() } //Pulled implementation out of lookAtLastChat and adapted to work for for general objects -void LLAgentCamera::lookAtObject(const LLUUID &object_id, bool self) +bool LLAgentCamera::lookAtObject(const LLUUID &object_id, bool self) { // Block if camera is animating or not in normal third person camera mode if (mCameraAnimating || !cameraThirdPerson()) { - return; + return false; } LLViewerObject *chatter = gObjectList.findObject(object_id); if (!chatter) { - return; + return false; } LLVector3 delta_pos; @@ -2844,7 +2837,7 @@ void LLAgentCamera::lookAtObject(const LLUUID &object_id, bool self) new_camera_pos += left * 0.3f; new_camera_pos += up * 0.2f; - //setFocusOnAvatar(FALSE, FALSE); + setFocusOnAvatar(FALSE, FALSE); if (chatter_av->mHeadp) { @@ -2862,7 +2855,6 @@ void LLAgentCamera::lookAtObject(const LLUUID &object_id, bool self) else mCameraFocusOffsetTarget.setVec(radius, radius, 0.f); } - setFocusOnAvatar(FALSE, TRUE); } else { @@ -2882,17 +2874,15 @@ void LLAgentCamera::lookAtObject(const LLUUID &object_id, bool self) new_camera_pos += left * 0.3f; new_camera_pos += up * 0.2f; - //setFocusOnAvatar(FALSE, FALSE); - + setFocusOnAvatar(FALSE, FALSE); setFocusGlobal(chatter->getPositionGlobal(), object_id); if(self) mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); else mCameraFocusOffsetTarget.setVec(radius, radius, 0.f); - - setFocusOnAvatar(FALSE, TRUE); } + return true; } diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h index 663742751..c18b493c2 100644 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -234,7 +234,7 @@ public: BOOL setLookAt(ELookAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero); ELookAtType getLookAtType(); void lookAtLastChat(); - void lookAtObject(const LLUUID &object_id, bool self=true); + bool lookAtObject(const LLUUID &object_id, bool self=true); void slamLookAt(const LLVector3 &look_at); // Set the physics data BOOL setPointAt(EPointAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero); EPointAtType getPointAtType(); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4cab987ae..a3439995e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -56,7 +56,10 @@ std::string self_av_string() { - return gAgentAvatarp->avString(); + if(isAgentAvatarValid()) + return gAgentAvatarp->avString(); + else + return std::string(); } // RAII thingy to guarantee that a variable gets reset when the Setter diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4ce4f662d..a25086e04 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -507,7 +507,7 @@ static void settings_to_globals() gAllowIdleAFK = gSavedSettings.getBOOL("AllowIdleAFK"); gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun"); gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); - LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale"); + LLWorldMapView::sMapScale = llmax(.1f,gSavedSettings.getF32("MapScale")); LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips"); } @@ -848,8 +848,10 @@ bool LLAppViewer::init() { // can't use an alert here since we're exiting and // all hell breaks lose. + std::string msg = LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"); + LLStringUtil::format(msg,LLTrans::getDefaultArgs()); OSMessageBox( - LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"), + msg, LLStringUtil::null, OSMB_OK); return 0; @@ -861,8 +863,10 @@ bool LLAppViewer::init() { // can't use an alert here since we're exiting and // all hell breaks lose. + std::string msg = LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"); + LLStringUtil::format(msg,LLTrans::getDefaultArgs()); OSMessageBox( - LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"), + msg, LLStringUtil::null, OSMB_OK); return 0; @@ -873,8 +877,10 @@ bool LLAppViewer::init() { // can't use an alert here since we're exiting and // all hell breaks lose. + std::string msg = LNotifications::instance().getGlobalString("UnsupportedCPUSSE2"); + LLStringUtil::format(msg,LLTrans::getDefaultArgs()); OSMessageBox( - LLNotifications::instance().getGlobalString("UnsupportedCPUSSE"), + msg, LLStringUtil::null, OSMB_OK); return 0; @@ -3952,6 +3958,13 @@ void LLAppViewer::idle() return; } + static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); + LLAgent::ETeleportState tp_state = gAgent.getTeleportState(); + if (!hide_tp_screen && tp_state != LLAgent::TELEPORT_NONE && tp_state != LLAgent::TELEPORT_LOCAL && tp_state != LLAgent::TELEPORT_PENDING) + { + return; + } + gViewerWindow->updateUI(); /////////////////////////////////////// diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 12dd4a4b9..34b8785c9 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -638,22 +638,11 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) { if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS) { - std::string first, last; std::string fullname; LLSD args; - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(agent_id, &avatar_name)) - { - switch (gSavedSettings.getS32("PhoenixNameSystem")) - { - case 0 : fullname = avatar_name.getLegacyName(); break; - case 1 : fullname = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : fullname = avatar_name.mDisplayName; break; - default : fullname = avatar_name.getCompleteName(); break; - } + if (LLAvatarNameCache::getPNSName(agent_id, fullname)) args["NAME"] = fullname; - } - + LLSD payload; payload["from_id"] = agent_id; if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights) @@ -740,15 +729,11 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, { // Popup a notify box with online status of this agent // Use display name only because this user is your friend + std::string name; + LLAvatarNameCache::getPNSName(av_name, name); LLSD args; - switch (gSavedSettings.getS32("PhoenixNameSystem")) - { - case 0 : args["NAME"] = av_name.getLegacyName(); break; - case 1 : args["NAME"] = (av_name.mIsDisplayNameDefault ? av_name.mDisplayName : av_name.getCompleteName()); break; - case 2 : args["NAME"] = av_name.mDisplayName; break; - default : args["NAME"] = av_name.getCompleteName(); break; - } - + args["NAME"] = name; + // Popup a notify box with online status of this agent LLNotificationPtr notification = LLNotificationsUtil::add(online ? "FriendOnline" : "FriendOffline", args, payload); diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 874299df3..26d3aa0a9 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -55,6 +55,7 @@ #include "llviewerobject.h" #include "llviewerregion.h" #include "llresmgr.h" + #include "llbutton.h" #include "lldir.h" #include "llnotificationsutil.h" @@ -207,8 +208,7 @@ BOOL LLFloaterScriptQueue::start() args["[COUNT]"] = llformat ("%d", mObjectIDs.count()); buffer = getString ("Starting", args); - LLScrollListCtrl* list = getChild("queue output"); - list->addCommentText(buffer); + getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); return nextObject(); } @@ -240,12 +240,9 @@ BOOL LLFloaterScriptQueue::nextObject() } while((mObjectIDs.count() > 0) && !successful_start); if(isDone() && !mDone) { - - LLScrollListCtrl* list = getChild("queue output"); - - mDone = TRUE; - list->addCommentText(getString("Done")); - childSetEnabled("close",TRUE); + mDone = true; + getChild("queue output")->addSimpleElement(getString("Done"), ADD_BOTTOM); + getChildView("close")->setEnabled(TRUE); } return successful_start; } @@ -283,6 +280,40 @@ BOOL LLFloaterScriptQueue::popNext() /// Class LLFloaterCompileQueue ///---------------------------------------------------------------------------- +class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier +{ +public: + + LLCompileFloaterUploadQueueSupplier(const LLUUID& queue_id) : + mQueueId(queue_id) + { + } + + virtual LLAssetUploadQueue* get() const + { + LLFloaterCompileQueue* queue = (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId); + if(NULL == queue) + { + return NULL; + } + return queue->getUploadQueue(); + } + + virtual void log(std::string message) const + { + LLFloaterCompileQueue* queue = (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId); + if(NULL == queue) + { + return; + } + + queue->getChild("queue output")->addSimpleElement(message, ADD_BOTTOM); + } + +private: + LLUUID mQueueId; +}; + // static LLFloaterCompileQueue* LLFloaterCompileQueue::create(BOOL mono) { @@ -291,48 +322,8 @@ LLFloaterCompileQueue* LLFloaterCompileQueue::create(BOOL mono) LLRect rect = gSavedSettings.getRect("CompileOutputRect"); rect.translate(left - rect.mLeft, top - rect.mTop); LLFloaterCompileQueue* new_queue = new LLFloaterCompileQueue("queue", rect); - - class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier - { - public: - - LLCompileFloaterUploadQueueSupplier(const LLUUID& queue_id) : - mQueueId(queue_id) - { - } - - virtual LLAssetUploadQueue* get() const - { - LLFloaterCompileQueue* queue = - (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId); - - if(NULL == queue) - { - return NULL; - } - - return queue->mUploadQueue; - } - virtual void log(std::string message) const - { - LLFloaterCompileQueue* queue = - (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId); - - if(NULL == queue) - { - return; - } - - LLScrollListCtrl* list = queue->getChild("queue output"); - list->addCommentText(message.c_str()); - } - - private: - LLUUID mQueueId; - }; - - new_queue->mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(new_queue->getID())); + new_queue->mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(new_queue->getID())); new_queue->mMono = mono; new_queue->open(); return new_queue; @@ -414,8 +405,8 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, llinfos << "LLFloaterCompileQueue::scriptArrived()" << llendl; LLScriptQueueData* data = (LLScriptQueueData*)user_data; if(!data) return; - LLFloaterCompileQueue* queue = static_cast - (LLFloaterScriptQueue::findInstance(data->mQueueID)); + LLFloaterCompileQueue* queue = static_cast (LLFloaterScriptQueue::findInstance(data->mQueueID)); + std::string buffer; if(queue && (0 == status)) { @@ -519,8 +510,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, } if(queue && (buffer.size() > 0)) { - LLScrollListCtrl* list = queue->getChild("queue output"); - list->addCommentText(buffer); + queue->getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); } delete data; } @@ -543,8 +533,7 @@ void LLFloaterCompileQueue::onSaveBytecodeComplete(const LLUUID& asset_id, void* { llinfos << "LLFloaterCompileQueue::onSaveBytecodeComplete()" << llendl; LLCompileQueueData* data = (LLCompileQueueData*)user_data; - LLFloaterCompileQueue* queue = static_cast - (LLFloaterScriptQueue::findInstance(data->mQueueID)); + LLFloaterCompileQueue* queue = static_cast (LLFloaterScriptQueue::findInstance(data->mQueueID)); if(queue && (0 == status) && data) { queue->saveItemByItemID(data->mItemId); @@ -692,7 +681,7 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj, // find all of the lsl, leaving off duplicates. We'll remove // all matching asset uuids on compilation success. LLDynamicArray names; - + LLInventoryObject::object_list_t::const_iterator it = inv->begin(); LLInventoryObject::object_list_t::const_iterator end = inv->end(); for ( ; it != end; ++it) @@ -704,10 +693,9 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj, if (object) { LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); - LLScrollListCtrl* list = getChild("queue output"); std::string buffer; buffer = getString("Resetting") + LLTrans::getString(":") + " " + item->getName(); - list->addCommentText(buffer); + getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_ScriptReset); msg->nextBlockFast(_PREHASH_AgentData); @@ -754,7 +742,7 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj, // find all of the lsl, leaving off duplicates. We'll remove // all matching asset uuids on compilation success. LLDynamicArray names; - + LLInventoryObject::object_list_t::const_iterator it = inv->begin(); LLInventoryObject::object_list_t::const_iterator end = inv->end(); for ( ; it != end; ++it) @@ -769,7 +757,7 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj, LLScrollListCtrl* list = getChild("queue output"); std::string buffer; buffer = getString("Running") + LLTrans::getString(":") + " " + item->getName(); - list->addCommentText(buffer); + list->addSimpleElement(buffer, ADD_BOTTOM); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_SetScriptRunning); @@ -818,7 +806,7 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj, // find all of the lsl, leaving off duplicates. We'll remove // all matching asset uuids on compilation success. LLDynamicArray names; - + LLInventoryObject::object_list_t::const_iterator it = inv->begin(); LLInventoryObject::object_list_t::const_iterator end = inv->end(); for ( ; it != end; ++it) @@ -833,8 +821,8 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj, LLScrollListCtrl* list = getChild("queue output"); std::string buffer; buffer = getString("NotRunning") + LLTrans::getString(":") + " " + item->getName(); - list->addCommentText(buffer); - + list->addSimpleElement(buffer, ADD_BOTTOM); + LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_SetScriptRunning); msg->nextBlockFast(_PREHASH_AgentData); diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h index e4bccff52..ee49ac574 100644 --- a/indra/newview/llcompilequeue.h +++ b/indra/newview/llcompilequeue.h @@ -79,7 +79,7 @@ protected: LLInventoryObject::object_list_t* inv, S32 serial_num, void* queue); - + // This is called by inventoryChanged virtual void handleInventory(LLViewerObject* viewer_obj, LLInventoryObject::object_list_t* inv) = 0; @@ -105,7 +105,7 @@ protected: // Object Queue LLDynamicArray mObjectIDs; LLUUID mCurrentObjectID; - BOOL mDone; + bool mDone; LLUUID mID; static LLMap sInstances; @@ -143,6 +143,8 @@ public: // remove any object in mScriptScripts with the matching uuid. void removeItemByItemID(const LLUUID& item_id); + LLAssetUploadQueue* getUploadQueue() { return mUploadQueue; } + protected: LLFloaterCompileQueue(const std::string& name, const LLRect& rect); virtual ~LLFloaterCompileQueue(); @@ -200,12 +202,10 @@ public: protected: LLFloaterResetQueue(const std::string& name, const LLRect& rect); virtual ~LLFloaterResetQueue(); - + // This is called by inventoryChanged virtual void handleInventory(LLViewerObject* viewer_obj, - LLInventoryObject::object_list_t* inv); - -protected: + LLInventoryObject::object_list_t* inv); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -224,12 +224,10 @@ public: protected: LLFloaterRunQueue(const std::string& name, const LLRect& rect); virtual ~LLFloaterRunQueue(); - + // This is called by inventoryChanged virtual void handleInventory(LLViewerObject* viewer_obj, LLInventoryObject::object_list_t* inv); - -protected: }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -252,8 +250,6 @@ protected: // This is called by inventoryChanged virtual void handleInventory(LLViewerObject* viewer_obj, LLInventoryObject::object_list_t* inv); - -protected: }; #endif // LL_LLCOMPILEQUEUE_H diff --git a/indra/newview/lldebugmessagebox.cpp b/indra/newview/lldebugmessagebox.cpp index 4188ecc0e..ab5ddf18b 100644 --- a/indra/newview/lldebugmessagebox.cpp +++ b/indra/newview/lldebugmessagebox.cpp @@ -112,7 +112,7 @@ void LLDebugVarMessageBox::show(const std::string& title, F32 *var, F32 max_valu { box->mSlider1->setValue(*var); } - box->mSlider1->setCommitCallback(slider_changed); + box->mSlider1->setCommitCallback(boost::bind(&LLDebugVarMessageBox::slider_changed,_1,box)); box->mSlider1->setCallbackUserData(box); #endif } @@ -129,8 +129,7 @@ void LLDebugVarMessageBox::show(const std::string& title, S32 *var, S32 max_valu { box->mSlider1->setValue((F32)*var); } - box->mSlider1->setCommitCallback(slider_changed); - box->mSlider1->setCallbackUserData(box); + box->mSlider1->setCommitCallback(boost::bind(&LLDebugVarMessageBox::slider_changed,_1,box)); #endif } @@ -142,20 +141,17 @@ void LLDebugVarMessageBox::show(const std::string& title, LLVector3 *var, LLVect box->mSlider1->setMaxValue(max_value.mV[VX]); box->mSlider1->setMinValue(-max_value.mV[VX]); box->mSlider1->setIncrement(increment.mV[VX]); - box->mSlider1->setCommitCallback(slider_changed); - box->mSlider1->setCallbackUserData(box); + box->mSlider1->setCommitCallback(boost::bind(&LLDebugVarMessageBox::slider_changed,_1,box)); box->mSlider2->setMaxValue(max_value.mV[VX]); box->mSlider2->setMinValue(-max_value.mV[VX]); box->mSlider2->setIncrement(increment.mV[VX]); - box->mSlider2->setCommitCallback(slider_changed); - box->mSlider2->setCallbackUserData(box); + box->mSlider2->setCommitCallback(boost::bind(&LLDebugVarMessageBox::slider_changed,_1,box)); box->mSlider3->setMaxValue(max_value.mV[VX]); box->mSlider3->setMinValue(-max_value.mV[VX]); box->mSlider3->setIncrement(increment.mV[VX]); - box->mSlider3->setCommitCallback(slider_changed); - box->mSlider3->setCallbackUserData(box); + box->mSlider3->setCommitCallback(boost::bind(&LLDebugVarMessageBox::slider_changed,_1,box)); #endif } diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 97b9764ab..616f6b58a 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -63,6 +63,8 @@ const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f; static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); +extern bool gShiftFrame; + //////////////////////// // @@ -102,7 +104,6 @@ void LLDrawable::init() mPositionGroup.clear(); mExtents[0].clear(); mExtents[1].clear(); - mQuietCount = 0; mState = 0; mVObjp = NULL; @@ -410,6 +411,8 @@ void LLDrawable::makeActive() if (!isRoot() && !mParent->isActive()) { mParent->makeActive(); + //NOTE: linked set will now NEVER become static + mParent->setState(LLDrawable::ACTIVE_CHILD); } //all child objects must also be active @@ -427,14 +430,6 @@ void LLDrawable::makeActive() } } - if (mVObjp->getPCode() == LL_PCODE_VOLUME) - { - if (mVObjp->isFlexible()) - { - return; - } - } - if (mVObjp->getPCode() == LL_PCODE_VOLUME) { gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE); @@ -442,28 +437,22 @@ void LLDrawable::makeActive() updatePartition(); } - if (isRoot()) - { - mQuietCount = 0; - } - else - { - getParent()->mQuietCount = 0; - } + llassert(isAvatar() || isRoot() || mParent->isActive()); } void LLDrawable::makeStatic(BOOL warning_enabled) { - if (isState(ACTIVE)) + if (isState(ACTIVE) && + !isState(ACTIVE_CHILD) && + !mVObjp->isAttachment() && + !mVObjp->isFlexible()) { clearState(ACTIVE | ANIMATED_CHILD); - if (mParent.notNull() && mParent->isActive() && warning_enabled) - { - LL_WARNS_ONCE("Drawable") << "Drawable becomes static with active parent!" << LL_ENDL; - } - + //drawable became static with active parent, not acceptable + llassert(mParent.isNull() || !mParent->isActive() || !warning_enabled); + LLViewerObject::const_child_list_t& child_list = mVObjp->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) @@ -490,8 +479,8 @@ void LLDrawable::makeStatic(BOOL warning_enabled) mSpatialBridge->markDead(); setSpatialBridge(NULL); } + updatePartition(); } - updatePartition(); } // Returns "distance" between target destination and resulting xfrom @@ -642,7 +631,7 @@ BOOL LLDrawable::updateMove() } makeActive(); - + BOOL done; if (isState(MOVE_UNDAMPED)) @@ -722,6 +711,11 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) return; } + if (gShiftFrame) + { + return; + } + //switch LOD with the spatial group to avoid artifacts //LLSpatialGroup* sg = getSpatialGroup(); @@ -820,14 +814,19 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) mXform.setPosition(mVObjp->getPositionAgent()); } - mXform.setRotation(mVObjp->getRotation()); - mXform.setScale(1,1,1); mXform.updateMatrix(); if (isStatic()) { LLVOVolume* volume = getVOVolume(); - if (!volume) + + bool rebuild = (!volume && + getRenderType() != LLPipeline::RENDER_TYPE_TREE && + getRenderType() != LLPipeline::RENDER_TYPE_TERRAIN && + getRenderType() != LLPipeline::RENDER_TYPE_SKY && + getRenderType() != LLPipeline::RENDER_TYPE_GROUND); + + if (rebuild) { gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); } @@ -841,7 +840,7 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) facep->mExtents[0].add(shift_vector); facep->mExtents[1].add(shift_vector); - if (!volume && facep->hasGeometry()) + if (rebuild && facep->hasGeometry()) { facep->clearVertexBuffer(); } @@ -960,6 +959,12 @@ LLSpatialGroup* LLDrawable::getSpatialGroup() const void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) { + //precondition: mSpatialGroupp MUST be null or DEAD or mSpatialGroupp MUST NOT contain this + llassert(!mSpatialGroupp || mSpatialGroupp->isDead() || !mSpatialGroupp->hasElement(this)); + + //precondition: groupp MUST be null or groupp MUST contain this + llassert(!groupp || groupp->hasElement(this)); + /*if (mSpatialGroupp && (groupp != mSpatialGroupp)) { mSpatialGroupp->setState(LLSpatialGroup::GEOM_DIRTY); @@ -979,9 +984,12 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) } } - mSpatialGroupp = groupp; + //postcondition: if next group is NULL, previous group must be dead OR NULL OR binIndex must be -1 + //postcondition: if next group is NOT NULL, binIndex must not be -1 + llassert(groupp == NULL ? (mSpatialGroupp == NULL || mSpatialGroupp->isDead()) || getBinIndex() == -1 : + getBinIndex() != -1); - llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); + mSpatialGroupp = groupp; } LLSpatialPartition* LLDrawable::getSpatialPartition() @@ -1416,6 +1424,11 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) return; } + if (gShiftFrame) + { + return; + } + if (mDrawable->getVObj()) { if (mDrawable->getVObj()->isAttachment()) @@ -1499,13 +1512,11 @@ void LLSpatialBridge::cleanupReferences() LLDrawable::cleanupReferences(); if (mDrawable) { - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->mOctreeNode->remove(mDrawable); - mDrawable->setSpatialGroup(NULL); - } + /* + DON'T DO THIS -- this should happen through octree destruction + + mDrawable->setSpatialGroup(NULL); if (mDrawable->getVObj()) { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); @@ -1516,15 +1527,10 @@ void LLSpatialBridge::cleanupReferences() LLDrawable* drawable = child->mDrawable; if (drawable) { - LLSpatialGroup* group = drawable->getSpatialGroup(); - if (group) - { - group->mOctreeNode->remove(drawable); - drawable->setSpatialGroup(NULL); - } + drawable->setSpatialGroup(NULL); } } - } + }*/ LLDrawable* drawablep = mDrawable; mDrawable = NULL; diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index bd2d23c5f..e2ea0140f 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -65,6 +65,7 @@ class LLViewerTexture; const U32 SILHOUETTE_HIGHLIGHT = 0; // All data for new renderer goes into this class. +LL_ALIGN_PREFIX(16) class LLDrawable : public LLRefCount { public: @@ -81,6 +82,16 @@ public: static void initClass(); + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLDrawable() { init(); } MEM_TYPE_NEW(LLMemType::MTYPE_DRAWABLE); @@ -287,11 +298,12 @@ public: RIGGED = 0x08000000, PARTITION_MOVE = 0x10000000, ANIMATED_CHILD = 0x20000000, + ACTIVE_CHILD = 0x40000000, } EDrawableFlags; private: //aligned members - LLVector4a mExtents[2]; - LLVector4a mPositionGroup; + LL_ALIGN_16(LLVector4a mExtents[2]); + LL_ALIGN_16(LLVector4a mPositionGroup); public: LLXformMatrix mXform; @@ -300,8 +312,6 @@ public: LLPointer mParent; F32 mDistanceWRTCamera; - - S32 mQuietCount; static S32 getCurrentFrame() { return sCurVisible; } static S32 getMinVisFrameRange(); @@ -333,7 +343,7 @@ private: static U32 sNumZombieDrawables; static LLDynamicArrayPtr > sDeadList; -}; +} LL_ALIGN_POSTFIX(16); inline LLFace* LLDrawable::getFace(const S32 i) const diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 69a3cf419..d433fe3a6 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -257,48 +257,6 @@ void LLFacePool::dirtyTextures(const std::set& textures { } -// static -S32 LLFacePool::drawLoop(face_array_t& face_list) -{ - S32 res = 0; - if (!face_list.empty()) - { - for (std::vector::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - res += facep->renderIndexed(); - } - } - return res; -} - -// static -S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage) -{ - S32 res = 0; - if (!face_list.empty()) - { - for (std::vector::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - gGL.getTexUnit(stage)->bind(facep->getTexture(), TRUE); - gGL.getTexUnit(0)->activate(); - res += facep->renderIndexed(); - } - } - return res; -} - -void LLFacePool::drawLoop() -{ - if (!mDrawFace.empty()) - { - drawLoop(mDrawFace); - } -} - void LLFacePool::enqueue(LLFace* facep) { mDrawFace.push_back(facep); @@ -464,6 +422,7 @@ void LLRenderPass::applyModelMatrix(LLDrawInfo& params) gGL.loadMatrix(gGLModelView); if (params.mModelMatrix) { + llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); gGL.multMatrix((GLfloat*) params.mModelMatrix->mMatrix); } gPipeline.mMatrixOpCount++; diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 341583996..890536ba2 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -192,10 +192,6 @@ public: void buildEdges(); - static S32 drawLoop(face_array_t& face_list); - static S32 drawLoopSetTex(face_array_t& face_list, S32 stage); - void drawLoop(); - void addFaceReference(LLFace *facep); void removeFaceReference(LLFace *facep); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 865e89f89..aad2a8acb 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -205,7 +205,7 @@ void LLDrawPoolAlpha::endRenderPass( S32 pass ) LLFastTimer t(FTM_RENDER_ALPHA); LLRenderPass::endRenderPass(pass); - if(gPipeline.canUseWindLightShaders()) + if(mVertexShaderLevel > 0) { LLGLSLShader::bindNoShader(); } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index dd8b4e80c..28a1acaab 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1572,16 +1572,21 @@ void LLDrawPoolInvisible::render(S32 pass) gOcclusionProgram.unbind(); } - if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + /*if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) // invisible (deprecated) { beginShiny(true); renderShiny(true); endShiny(true); - } + }*/ } void LLDrawPoolInvisible::beginDeferredPass(S32 pass) { + static const LLCachedControl enable("SianaRenderDeferredInvisiprim"); + if (!enable) + { + return; + } beginRenderPass(pass); } @@ -1593,7 +1598,8 @@ void LLDrawPoolInvisible::endDeferredPass( S32 pass ) void LLDrawPoolInvisible::renderDeferred( S32 pass ) { //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff static const LLCachedControl enable("SianaRenderDeferredInvisiprim"); - if (!enable) { + if (!enable) + { return; } @@ -1610,10 +1616,10 @@ void LLDrawPoolInvisible::renderDeferred( S32 pass ) gOcclusionProgram.unbind(); - if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + /*if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) // invisible (deprecated) { beginShiny(true); renderShiny(true); endShiny(true); - } + }*/ } diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 6e0ea78af..4bc06580f 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -351,16 +351,20 @@ void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass) void LLDrawPoolFullbright::renderPostDeferred(S32 pass) { LLFastTimer t(FTM_RENDER_FULLBRIGHT); - + gGL.setColorMask(true, true); gGL.setSceneBlendType(LLRender::BT_ALPHA); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE); + + gGL.setColorMask(true, false); } void LLDrawPoolFullbright::endPostDeferredPass(S32 pass) { gDeferredFullbrightProgram.unbind(); LLRenderPass::endRenderPass(pass); + } void LLDrawPoolFullbright::beginRenderPass(S32 pass) diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index b98cc84e8..81a3c99ea 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -302,6 +302,35 @@ void LLDrawPoolTerrain::renderShadow(S32 pass) //glCullFace(GL_BACK); } + +void LLDrawPoolTerrain::drawLoop() +{ + if (!mDrawFace.empty()) + { + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *facep = *iter; + + LLMatrix4* model_matrix = &(facep->getDrawable()->getRegion()->mRenderMatrix); + + if (model_matrix != gGLLastMatrix) + { + llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); + gGLLastMatrix = model_matrix; + gGL.loadMatrix(gGLModelView); + if (model_matrix) + { + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); + } + gPipeline.mMatrixOpCount++; + } + + facep->renderIndexed(); + } + } +} + void LLDrawPoolTerrain::renderFullShader() { // Hack! Get the region that this draw pool is rendering from! @@ -765,6 +794,7 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.loadIdentity(); gGL.translatef(-2.f, 0.f, 0.f); gGL.matrixMode(LLRender::MM_MODELVIEW); + // Care about alpha only gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 24ed06500..a9fb48bac 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -89,6 +89,7 @@ protected: void renderFull2TU(); void renderFull4TU(); void renderFullShader(); + void drawLoop(); }; #endif // LL_LLDRAWPOOLSIMPLE_H diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 9500f5aff..d2faca835 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -43,6 +43,7 @@ #include "llviewershadermgr.h" #include "llrender.h" #include "llviewercontrol.h" +#include "llviewerregion.h" S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; @@ -116,8 +117,23 @@ void LLDrawPoolTree::render(S32 pass) { LLFace *face = *iter; LLVertexBuffer* buff = face->getVertexBuffer(); + if(buff) { + LLMatrix4* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix); + + if (model_matrix != gGLLastMatrix) + { + gGLLastMatrix = model_matrix; + gGL.loadMatrix(gGLModelView); + if (model_matrix) + { + llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); + } + gPipeline.mMatrixOpCount++; + } + buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); gPipeline.addTrianglesDrawn(buff->getNumIndices()); diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 371f979a0..5c06fb1c7 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -53,6 +53,8 @@ #include "pipeline.h" #include "llviewershadermgr.h" #include "llwaterparammanager.h" +#include "llappviewer.h" +#include "lltexturecache.h" const LLUUID TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004"); const LLUUID OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055"); @@ -235,7 +237,10 @@ void LLDrawPoolWater::render(S32 pass) glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // Slowly move over time. - F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f); + static const LLCachedControl freeze_time("FreezeTime",false); + static F32 frame_time; + if (!freeze_time) frame_time = gFrameTimeSeconds; + F32 offset = fmod(frame_time*2.f, 100.f); F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f}; F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f}; glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); @@ -260,8 +265,11 @@ void LLDrawPoolWater::render(S32 pass) { continue; } - gGL.getTexUnit(0)->bind(face->getTexture()); - face->renderIndexed(); + if(face->getTexture() && face->getTexture()->hasGLTexture()) + { + gGL.getTexUnit(0)->bind(face->getTexture()); + face->renderIndexed(); + } } // Now, disable texture coord generation on texture state 1 @@ -367,6 +375,32 @@ void LLDrawPoolWater::renderOpaqueLegacyWater() gPipeline.disableLights(); + //Singu note: This is a hack around bizarre opensim behavior. The opaque water texture we get is pure white and only has one channel. + // This behavior is clearly incorrect, so we try to detect that case, purge it from the cache, and try to re-fetch the texture. + // If the re-fetched texture is still invalid, or doesn't exist, we use transparent water, which is fine since alphablend is unset. + // The current logic for refetching is crude here, and probably wont work if, say, a prim were to also have the texture for some reason, + // however it works well enough otherwise, and is much cleaner than diving into LLTextureList, LLViewerFetchedTexture, and LLViewerTexture. + // Perhaps a proper reload mechanism could be done if we ever add user-level texture reloading, but until then it's not a huge priority. + // Failing to fully refetch will just give us the same invalid texture we started with, which will result in the fallback texture being used. + if(mOpaqueWaterImagep != mWaterImagep) + { + if(mOpaqueWaterImagep->isMissingAsset()) + { + mOpaqueWaterImagep = mWaterImagep; + } + else if(mOpaqueWaterImagep->hasGLTexture() && mOpaqueWaterImagep->getComponents() < 3) + { + LLAppViewer::getTextureCache()->removeFromCache(mOpaqueWaterImagep->getID()); + static bool sRefetch = true; + if(sRefetch) + { + sRefetch = false; + ((LLViewerFetchedTexture*)mOpaqueWaterImagep.get())->forceRefetch(); + } + else + mOpaqueWaterImagep = mWaterImagep; + } + } mOpaqueWaterImagep->addTextureStats(1024.f*1024.f); // Activate the texture binding and bind one @@ -380,18 +414,21 @@ void LLDrawPoolWater::renderOpaqueLegacyWater() { glEnable(GL_TEXTURE_GEN_S); //texture unit 0 glEnable(GL_TEXTURE_GEN_T); //texture unit 0 - glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); } // Use the fact that we know all water faces are the same size // to save some computation - // Slowly move texture coordinates over time so the watter appears + // Slowly move texture coordinates over time so the water appears // to be moving. F32 movement_period_secs = 50.f; - F32 offset = fmod(gFrameTimeSeconds, movement_period_secs); + static const LLCachedControl freeze_time("FreezeTime",false); + static F32 frame_time; + if (!freeze_time) frame_time = gFrameTimeSeconds; + F32 offset = fmod(frame_time, movement_period_secs); if (movement_period_secs != 0) { @@ -549,7 +586,11 @@ void LLDrawPoolWater::shade() shader->bind(); } - sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; + static const LLCachedControl freeze_time("FreezeTime",false); + if (!freeze_time) + { + sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; + } S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX); @@ -674,7 +715,7 @@ void LLDrawPoolWater::shade() } LLVOWater* water = (LLVOWater*) face->getViewerObject(); - if(diffTex > -1 && face->getTexture()->hasGLTexture()) + if(diffTex > -1 && face->getTexture() && face->getTexture()->hasGLTexture()) gGL.getTexUnit(diffTex)->bind(face->getTexture()); sNeedsReflectionUpdate = TRUE; diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index df9895906..d119f247f 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -54,7 +54,7 @@ LLPointer LLDrawPoolWLSky::sCloudNoiseRawImage = NULL; static LLGLSLShader* cloud_shader = NULL; static LLGLSLShader* sky_shader = NULL; - +static LLGLSLShader* star_shader = NULL; LLDrawPoolWLSky::LLDrawPoolWLSky(void) : LLDrawPool(POOL_WL_SKY) @@ -113,6 +113,8 @@ void LLDrawPoolWLSky::beginRenderPass( S32 pass ) LLPipeline::sUnderWaterRender ? &gObjectFullbrightNoColorWaterProgram : &gWLCloudProgram; + + star_shader = &gCustomAlphaProgram; } void LLDrawPoolWLSky::endRenderPass( S32 pass ) @@ -123,6 +125,7 @@ void LLDrawPoolWLSky::beginDeferredPass(S32 pass) { sky_shader = &gDeferredWLSkyProgram; cloud_shader = &gDeferredWLCloudProgram; + star_shader = &gDeferredStarProgram; } void LLDrawPoolWLSky::endDeferredPass(S32 pass) @@ -182,6 +185,15 @@ void LLDrawPoolWLSky::renderSkyHaze(F32 camHeightLocal) const void LLDrawPoolWLSky::renderStars(void) const { + // *NOTE: we divide by two here and GL_ALPHA_SCALE by two below to avoid + // clamping and allow the star_alpha param to brighten the stars. + bool error; + LLColor4 star_alpha(LLColor4::black); + star_alpha.mV[3] = LLWLParamManager::getInstance()->mCurParams.getFloat("star_brightness", error) / 2.f; + llassert_always(!error); + if(star_alpha.mV[3] <= 0) + return; + LLGLSPipelineSkyBox gls_sky; LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -198,26 +210,16 @@ void LLDrawPoolWLSky::renderStars(void) const glPointSize(2.f); }*/ - // *NOTE: we divide by two here and GL_ALPHA_SCALE by two below to avoid - // clamping and allow the star_alpha param to brighten the stars. - bool error; - LLColor4 star_alpha(LLColor4::black); - star_alpha.mV[3] = LLWLParamManager::getInstance()->mCurParams.getFloat("star_brightness", error) / 2.f; - llassert_always(!error); - + gGL.pushMatrix(); + gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); // gl_FragColor.rgb = gl_Color.rgb; // gl_FragColor.a = gl_Color.a * star_alpha.a; //New gGL.getTexUnit(0)->bind(gSky.mVOSkyp->getBloomTex()); - gGL.pushMatrix(); - gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); - // gl_FragColor.rgb = gl_Color.rgb; - // gl_FragColor.a = gl_Color.a * star_alpha.a; - if (LLGLSLShader::sNoFixedFunction) + if (gPipeline.canUseVertexShaders()) { - gCustomAlphaProgram.bind(); - gCustomAlphaProgram.uniform1f("custom_alpha", star_alpha.mV[3]); + star_shader->uniform1f("custom_alpha", star_alpha.mV[3]); } else { @@ -230,11 +232,7 @@ void LLDrawPoolWLSky::renderStars(void) const gGL.popMatrix(); - if (LLGLSLShader::sNoFixedFunction) - { - gCustomAlphaProgram.unbind(); - } - else + if (!gPipeline.canUseVertexShaders()) { // and disable the combiner states gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); @@ -261,8 +259,15 @@ void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const void LLDrawPoolWLSky::renderHeavenlyBodies() { + LLColor4 color(gSky.mVOSkyp->getMoon().getInterpColor(), gSky.mVOSkyp->getMoon().getDirection().mV[2]); + if (color.mV[VW] <= 0.f) + return; + + color.mV[VW] = llclamp(color.mV[VW]*color.mV[VW]*4.f,0.f,1.f); + LLGLSPipelineSkyBox gls_skybox; LLGLEnable blend_on(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); gPipeline.disableLights(); #if 0 // when we want to re-add a texture sun disc, here's where to do it. @@ -279,33 +284,31 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]; - if (gSky.mVOSkyp->getMoon().getDraw() && face->getGeomCount()) + if (gSky.mVOSkyp->getMoon().getDraw() && face->getGeomCount() && face->getVertexBuffer()) { // *NOTE: even though we already bound this texture above for the // stars register combiners, we bind again here for defensive reasons, // since LLImageGL::bind detects that it's a noop, and optimizes it out. gGL.getTexUnit(0)->bind(face->getTexture()); - LLColor4 color(gSky.mVOSkyp->getMoon().getInterpColor()); - F32 a = gSky.mVOSkyp->getMoon().getDirection().mV[2]; - if (a > 0.f) - { - a = a*a*4.f; - } - - color.mV[3] = llclamp(a, 0.f, 1.f); if (gPipeline.canUseVertexShaders()) { - gHighlightProgram.bind(); + // Okay, so the moon isn't a star, but it's close enough. + star_shader->uniform1f("custom_alpha", color.mV[VW]); + } + else + { + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color.mV); } - LLFacePool::LLOverrideFaceColor color_override(this, color); + face->getVertexBuffer()->setBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK); + face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getVertexBuffer()->getNumIndices(), 0); - face->renderIndexed(); - - if (gPipeline.canUseVertexShaders()) + if (!gPipeline.canUseVertexShaders()) { - gHighlightProgram.unbind(); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } } } @@ -324,7 +327,7 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass) LLGLDepthTest depth(GL_TRUE, GL_FALSE); LLGLDisable clip(GL_CLIP_PLANE0); - gGL.setColorMask(true, false); + gGL.setColorMask(true, false); //Just in case. LLGLSquashToFarClip far_clip(glh_get_current_projection()); @@ -336,7 +339,7 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass) gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]); - gDeferredStarProgram.bind(); + star_shader->bind(); // *NOTE: have to bind a texture here since register combiners blending in // renderStars() requires something to be bound and we might as well only // bind the moon's texture once. @@ -346,13 +349,12 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass) renderStars(); - gDeferredStarProgram.unbind(); + star_shader->unbind(); gGL.popMatrix(); renderSkyClouds(camHeightLocal); - gGL.setColorMask(true, true); //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } @@ -373,6 +375,8 @@ void LLDrawPoolWLSky::render(S32 pass) LLGLSquashToFarClip far_clip(glh_get_current_projection()); + gGL.setColorMask(true, false); //Just in case. + renderSkyHaze(camHeightLocal); LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin(); @@ -380,6 +384,8 @@ void LLDrawPoolWLSky::render(S32 pass) gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]); + if(gPipeline.canUseVertexShaders()) + star_shader->bind(); // *NOTE: have to bind a texture here since register combiners blending in // renderStars() requires something to be bound and we might as well only // bind the moon's texture once. @@ -388,6 +394,9 @@ void LLDrawPoolWLSky::render(S32 pass) renderHeavenlyBodies(); renderStars(); + + if(gPipeline.canUseVertexShaders()) + star_shader->unbind(); gGL.popMatrix(); diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h index 7a4d711d4..c0976d1d4 100644 --- a/indra/newview/lldriverparam.h +++ b/indra/newview/lldriverparam.h @@ -83,6 +83,16 @@ public: LLDriverParam(LLWearable *wearablep); ~LLDriverParam(); + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + // Special: These functions are overridden by child classes LLDriverParamInfo* getInfo() const { return (LLDriverParamInfo*)mInfo; } // This sets mInfo and calls initialization functions diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index 398a41cef..33287ae1a 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -36,6 +36,16 @@ class LLViewerDynamicTexture : public LLViewerTexture { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + enum { LL_VIEWER_DYNAMIC_TEXTURE = LLViewerTexture::DYNAMIC_TEXTURE, @@ -85,7 +95,7 @@ protected: protected: BOOL mClamp; LLCoordGL mOrigin; - LLCamera mCamera; + LL_ALIGN_16(LLCamera mCamera); typedef std::set instance_list_t; static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ]; diff --git a/indra/newview/llenvmanager.cpp b/indra/newview/llenvmanager.cpp index 7e5377bd1..3033d4e07 100644 --- a/indra/newview/llenvmanager.cpp +++ b/indra/newview/llenvmanager.cpp @@ -47,6 +47,8 @@ #include "rlvhandler.h" // [/RLVa:KB] +#include "hippogridmanager.h" + std::string LLEnvPrefs::getWaterPresetName() const { if (mWaterPresetName.empty()) @@ -509,7 +511,8 @@ void LLEnvManagerNew::onRegionSettingsResponse(const LLSD& content) mRegionSettingsChangeSignal(); // reset - mInterpNextChangeMessage = false; + if (!gHippoGridManager->getConnectedGrid()->isAurora()) // On Aurora, the region says when to refresh + mInterpNextChangeMessage = false; } void LLEnvManagerNew::onRegionSettingsApplyResponse(bool ok) @@ -698,3 +701,36 @@ void LLEnvManagerNew::onRegionChange(bool interpolate) // Let interested parties know agent region has been changed. mRegionChangeSignal(); } + +// Aurora-sim windlight refresh +class WindLightRefresh : public LLHTTPNode +{ + /*virtual*/ void post(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const + { + if (!input || !context || !input.isMap() || !input.has("body")) + { + llinfos << "malformed WindLightRefresh!" << llendl; + return; + } + + //std::string dump = input["body"].asString(); + //llwarns << dump << llendl; + + LLSD body = input["body"]; + LLEnvManagerNew *env = &LLEnvManagerNew::instance(); + + LLViewerRegion* regionp = gAgent.getRegion(); + LLUUID region_uuid = regionp ? regionp->getRegionID() : LLUUID::null; + + env->mNewRegionPrefs.clear(); + env->mCurRegionUUID = region_uuid; + + env->mInterpNextChangeMessage = !body.has("Interpolate") || body["Interpolate"].asInteger() == 1; + + llinfos << "Windlight Refresh, interpolate:" << env->mInterpNextChangeMessage << llendl; + env->requestRegionSettings(); + env->mRegionChangeSignal(); + } +}; + +LLHTTPRegistration gHTTPRegistrationWindLightRefresh("/message/WindLightRefresh"); diff --git a/indra/newview/llenvmanager.h b/indra/newview/llenvmanager.h index ad7550aff..8d5317996 100644 --- a/indra/newview/llenvmanager.h +++ b/indra/newview/llenvmanager.h @@ -35,11 +35,11 @@ #include "llmemory.h" #include "llsd.h" -#include class LLWLParamManager; class LLWaterParamManager; class LLWLAnimator; +class WindLightRefresh; // generic key struct LLEnvKey @@ -257,6 +257,7 @@ public: bool useRegionWater(); private: + friend class WindLightRefresh; bool useDefaultSky(); bool useDefaultWater(); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index c42846b6f..277f1bb34 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1374,7 +1374,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, static LLCachedControl use_transform_feedback("RenderUseTransformFeedback", false); -#if 0//#ifdef GL_TRANSFORM_FEEDBACK_BUFFER +#ifdef GL_TRANSFORM_FEEDBACK_BUFFER if (use_transform_feedback && gTransformPositionProgram.mProgramObject && //transform shaders are loaded mVertexBuffer->useVBOs() && //target buffer is in VRAM @@ -1639,7 +1639,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (!do_xform) { LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); - LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); + S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, tc_size); } else { diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 4cab49205..b59dff8f0 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -64,6 +64,17 @@ class LLFace { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + + LLFace(const LLFace& rhs) { *this = rhs; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 9f1cbca6c..22539595e 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -971,7 +971,7 @@ void LLFastTimerView::draw() gGL.color4f(col[0], col[1], col[2], alpha); gGL.begin(LLRender::TRIANGLE_STRIP); for (U32 j = llmax(0, LLFastTimer::NamedTimer::HISTORY_NUM - LLFastTimer::getLastFrameIndex()); - j < LLFastTimer::NamedTimer::HISTORY_NUM; + j < (U32)LLFastTimer::NamedTimer::HISTORY_NUM; j++) { U64 ticks = idp->getHistoricalCount(j); diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 8b0fd109f..413398cf1 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -44,6 +44,8 @@ #include "llvoavatar.h" /*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f; +std::vector LLVolumeImplFlexible::sInstanceList; +std::vector LLVolumeImplFlexible::sUpdateDelay; static LLFastTimer::DeclareTimer FTM_FLEXIBLE_REBUILD("Rebuild"); static LLFastTimer::DeclareTimer FTM_DO_FLEXIBLE_UPDATE("Update"); @@ -70,8 +72,44 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectD { mVO->mDrawable->makeActive() ; } + + mInstanceIndex = sInstanceList.size(); + sInstanceList.push_back(this); + sUpdateDelay.push_back(0); }//----------------------------------------------- +LLVolumeImplFlexible::~LLVolumeImplFlexible() +{ + S32 end_idx = sInstanceList.size()-1; + + if (end_idx != mInstanceIndex) + { + sInstanceList[mInstanceIndex] = sInstanceList[end_idx]; + sInstanceList[mInstanceIndex]->mInstanceIndex = mInstanceIndex; + sUpdateDelay[mInstanceIndex] = sUpdateDelay[end_idx]; + } + + sInstanceList.pop_back(); + sUpdateDelay.pop_back(); +} + +//static +void LLVolumeImplFlexible::updateClass() +{ + std::vector::iterator delay_iter = sUpdateDelay.begin(); + + for (std::vector::iterator iter = sInstanceList.begin(); + iter != sInstanceList.end(); + ++iter) + { + if(!*delay_iter || !--*delay_iter) + { + (*iter)->doIdleUpdate(); + } + ++delay_iter; + } +} + LLVector3 LLVolumeImplFlexible::getFramePosition() const { return mVO->getRenderPosition(); @@ -296,22 +334,17 @@ void LLVolumeImplFlexible::updateRenderRes() // optimization similar to what Havok does for objects that are stationary. //--------------------------------------------------------------------------------- static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); -void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVolumeImplFlexible::doIdleUpdate() { LLDrawable* drawablep = mVO->mDrawable; if (drawablep) { //LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); - - //flexible objects never go static - drawablep->mQuietCount = 0; - if (!drawablep->isRoot()) - { - LLViewerObject* parent = (LLViewerObject*) mVO->getParent(); - parent->mDrawable->mQuietCount = 0; - } - + + //ensure drawable is active + drawablep->makeActive(); + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) { bool visible = drawablep->isVisible(); @@ -321,32 +354,46 @@ void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6 updateRenderRes(); gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); } - else if (visible && - !drawablep->isState(LLDrawable::IN_REBUILD_Q1) && - mVO->getPixelArea() > 256.f) + else { - U32 id; F32 pixel_area = mVO->getPixelArea(); - if (mVO->isRootEdit()) + U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; + update_period = llclamp(update_period,1U,(U32)llmax((U32)llceil(gFPSClamped*2.f),32U)); + + if (visible) { - id = mID; + if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1) && + mVO->getPixelArea() > 256.f) + { + U32 id; + + if (mVO->isRootEdit()) + { + id = mID; + } + else + { + LLVOVolume* parent = (LLVOVolume*) mVO->getParent(); + id = parent->getVolumeInterfaceID(); + } + + if ((LLDrawable::getCurrentFrame()+id)%update_period == 0) + { + sUpdateDelay[mInstanceIndex] = update_period-1; + + updateRenderRes(); + + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + } + } } else { - LLVOVolume* parent = (LLVOVolume*) mVO->getParent(); - id = parent->getVolumeInterfaceID(); - } - - U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; - - if ((LLDrawable::getCurrentFrame()+id)%update_period == 0) - { - updateRenderRes(); - gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + sUpdateDelay[mInstanceIndex] = update_period; } } - } + } if(!mInitialized) updateRenderRes(); } @@ -372,7 +419,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate() { BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE; - doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0); + doIdleUpdate(); if (!force_update || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) { diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h index 7d68a67da..d8b322546 100644 --- a/indra/newview/llflexibleobject.h +++ b/indra/newview/llflexibleobject.h @@ -3,31 +3,25 @@ * @author JJ Ventrella, Andrew Meadows, Tom Yedwab * @brief Flexible object definition * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -76,8 +70,17 @@ struct LLFlexibleObjectSection //--------------------------------------------------------- class LLVolumeImplFlexible : public LLVolumeInterface { +private: + static std::vector sInstanceList; + static std::vector sUpdateDelay; + S32 mInstanceIndex; + public: + static void resetTimers() { sUpdateDelay.assign(sUpdateDelay.size(),0); } + static void updateClass(); + LLVolumeImplFlexible(LLViewerObject* volume, LLFlexibleObjectData* attributes); + ~LLVolumeImplFlexible(); // Implements LLVolumeInterface U32 getID() const { return mID; } @@ -85,7 +88,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface LLQuaternion getFrameRotation() const; LLVolumeInterfaceType getInterfaceType() const { return INTERFACE_FLEXIBLE; } void updateRenderRes(); - void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + void doIdleUpdate(); BOOL doUpdateGeometry(LLDrawable *drawable); LLVector3 getPivotPosition() const; void onSetVolume(const LLVolumeParams &volume_params, const S32 detail); diff --git a/indra/newview/llfloateractivespeakers.cpp b/indra/newview/llfloateractivespeakers.cpp index 9aa5a7adf..5eb9afa32 100644 --- a/indra/newview/llfloateractivespeakers.cpp +++ b/indra/newview/llfloateractivespeakers.cpp @@ -70,6 +70,8 @@ const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f); const F32 TYPING_ANIMATION_FPS = 2.5f; +static void on_avatar_name_lookup(const LLUUID&, const LLAvatarName& avatar_name, std::string& mDisplayName); + LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerType type) : mStatus(LLSpeaker::STATUS_TEXT_ONLY), mLastSpokeTime(0.f), @@ -102,41 +104,22 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy void LLSpeaker::lookupName() { - // [Ansariel: Display name support] - LLAvatarNameCache::get(mID, boost::bind(&LLSpeaker::onAvatarNameLookup, _1, _2, new LLHandle(getHandle()))); - // [/Ansariel: Display name support] + LLAvatarNameCache::get(mID, boost::bind(&on_avatar_name_lookup, _1, _2, boost::ref(mDisplayName))); + + // Also set the legacy name. We will need it to initiate a new + // IM session. + gCacheName->getFullName(mID, mLegacyName); + mLegacyName = LLCacheName::cleanFullName(mLegacyName); } -//static -// [Ansariel: Display name support] -void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const LLAvatarName& avatar_name, void* user_data) -// [/Ansariel: Display name support] +static void on_avatar_name_lookup(const LLUUID&, const LLAvatarName& avatar_name, std::string& mDisplayName) { - LLSpeaker* speaker_ptr = ((LLHandle*)user_data)->get(); - delete (LLHandle*)user_data; - - if (speaker_ptr) - { - // [Ansariel: Display name support] - switch (gSavedSettings.getS32("PhoenixNameSystem")) - { - case 0 : speaker_ptr->mDisplayName = avatar_name.getLegacyName(); break; - case 1 : speaker_ptr->mDisplayName = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : speaker_ptr->mDisplayName = avatar_name.mDisplayName; break; - default : speaker_ptr->mDisplayName = avatar_name.getLegacyName(); break; - } - - // Also set the legacy name. We will need it to initiate a new - // IM session. - speaker_ptr->mLegacyName = LLCacheName::cleanFullName(avatar_name.getLegacyName()); - // [/Ansariel: Display name support] - + LLAvatarNameCache::getPNSName(avatar_name, mDisplayName); // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-1.0.0g - // TODO-RLVa: this seems to get called per frame which is very likely an LL bug that will eventuall get fixed - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - speaker_ptr->mDisplayName = RlvStrings::getAnonym(speaker_ptr->mDisplayName); + // TODO-RLVa: this seems to get called per frame which is very likely an LL bug that will eventually get fixed + if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) + mDisplayName = RlvStrings::getAnonym(mDisplayName); // [/RLVa:KB] - } } LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source) @@ -333,10 +316,10 @@ BOOL LLPanelActiveSpeakers::postBuild() mSpeakerList = getChild("speakers_list"); mSpeakerList->sortByColumn(sort_column, sort_ascending); - mSpeakerList->setDoubleClickCallback(onDoubleClickSpeaker); + mSpeakerList->setDoubleClickCallback(boost::bind(&onDoubleClickSpeaker,this)); mSpeakerList->setCommitOnSelectionChange(TRUE); - mSpeakerList->setCommitCallback(onSelectSpeaker); - mSpeakerList->setSortChangedCallback(onSortChanged); + mSpeakerList->setCommitCallback(boost::bind(&LLPanelActiveSpeakers::handleSpeakerSelect,this)); + mSpeakerList->setSortChangedCallback(boost::bind(&LLPanelActiveSpeakers::onSortChanged,this)); mSpeakerList->setCallbackUserData(this); mMuteTextCtrl = getChild("mute_text_btn"); @@ -610,7 +593,7 @@ void LLPanelActiveSpeakers::refreshSpeakers() } // we potentially modified the sort order by touching the list items - mSpeakerList->setSorted(FALSE); + mSpeakerList->setNeedsSort(); LLPointer selected_speakerp = mSpeakerMgr->findSpeaker(selected_id); // update UI for selected participant @@ -813,14 +796,6 @@ void LLPanelActiveSpeakers::onDoubleClickSpeaker(void* user_data) } } -//static -void LLPanelActiveSpeakers::onSelectSpeaker(LLUICtrl* source, void* user_data) -{ - LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; - panelp->handleSpeakerSelect(); -} - - //static void LLPanelActiveSpeakers::onSortChanged(void* user_data) { diff --git a/indra/newview/llfloateractivespeakers.h b/indra/newview/llfloateractivespeakers.h index b8a9ece01..757c00bc7 100644 --- a/indra/newview/llfloateractivespeakers.h +++ b/indra/newview/llfloateractivespeakers.h @@ -77,11 +77,6 @@ public: ~LLSpeaker() {}; void lookupName(); - // [Ansariel: Display name support] - //static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data); - static void onAvatarNameLookup(const LLUUID& id, const LLAvatarName& avatar_name, void* user_data); - // [/Ansariel: Display name support] - ESpeakerStatus mStatus; // current activity status in speech group F32 mLastSpokeTime; // timestamp when this speaker last spoke F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?) @@ -232,7 +227,6 @@ public: static void onVolumeChange(LLUICtrl* source, void* user_data); static void onClickProfile(void* user_data); static void onDoubleClickSpeaker(void* user_data); - static void onSelectSpeaker(LLUICtrl* source, void* user_data); static void onSortChanged(void* user_data); static void onModeratorMuteVoice(LLUICtrl* ctrl, void* user_data); static void onModeratorMuteText(LLUICtrl* ctrl, void* user_data); diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index c4121fae9..37ebd6f16 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -180,7 +180,7 @@ void LLFloaterAuction::onClickSnapshot(void* data) BOOL success = gViewerWindow->rawSnapshot(raw, gViewerWindow->getWindowWidth(), gViewerWindow->getWindowHeight(), - TRUE, FALSE, + (F32)gViewerWindow->getWindowWidth() / gViewerWindow->getWindowHeight(), FALSE, FALSE); gForceRenderLandFence = FALSE; diff --git a/indra/newview/llfloateravatarinfo.cpp b/indra/newview/llfloateravatarinfo.cpp index f60e24623..224099794 100644 --- a/indra/newview/llfloateravatarinfo.cpp +++ b/indra/newview/llfloateravatarinfo.cpp @@ -294,13 +294,3 @@ LLPreview::EAssetStatus LLFloaterAvatarInfo::getAssetStatus() } return mAssetStatus; } - -std::string getProfileURL(const std::string& agent_name) -{ - std::string url = gSavedSettings.getString("WebProfileURL"); - LLSD subs; - subs["AGENT_NAME"] = agent_name; - url = LLWeb::expandURLSubstitutions(url,subs); - LLStringUtil::toLower(url); - return url; -} diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index c214f3480..e12b95156 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -52,7 +52,9 @@ #include #include - +#include +#include +#include #include "llworld.h" #include "llsdutil.h" @@ -79,20 +81,24 @@ typedef enum e_radar_alert_type ALERT_TYPE_DRAW = 2, ALERT_TYPE_SHOUTRANGE = 4, ALERT_TYPE_CHATRANGE = 8, + ALERT_TYPE_AGE = 16, } ERadarAlertType; void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool entering) { + if(gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) return; //RLVa:LF Don't announce people are around when blind, that cheats the system. static LLCachedControl radar_chat_alerts(gSavedSettings, "RadarChatAlerts"); if (!radar_chat_alerts) return; static LLCachedControl radar_alert_sim(gSavedSettings, "RadarAlertSim"); static LLCachedControl radar_alert_draw(gSavedSettings, "RadarAlertDraw"); static LLCachedControl radar_alert_shout_range(gSavedSettings, "RadarAlertShoutRange"); static LLCachedControl radar_alert_chat_range(gSavedSettings, "RadarAlertChatRange"); + static LLCachedControl radar_alert_age(gSavedSettings, "RadarAlertAge"); static LLCachedControl radar_chat_keys(gSavedSettings, "RadarChatKeys"); LLFloaterAvatarList* self = LLFloaterAvatarList::getInstance(); LLStringUtil::format_map_t args; + args["[NAME]"] = name; switch(type) { case ALERT_TYPE_SIM: @@ -122,10 +128,21 @@ void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool args["[RANGE]"] = self->getString("chat_range"); } break; + + case ALERT_TYPE_AGE: + if (radar_alert_age) + { + LLChat chat; + chat.mFromName = name; + chat.mText = name + " " + self->getString("has_triggered_your_avatar_age_alert") + "."; + chat.mURL = llformat("secondlife:///app/agent/%s/about",key.asString().c_str()); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::addChat(chat); + } + break; } if (args.find("[RANGE]") != args.end()) { - args["[NAME]"] = name; args["[ACTION]"] = self->getString(entering ? "has_entered" : "has_left"); LLChat chat; chat.mText = self->getString("template", args); @@ -137,11 +154,41 @@ void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool } LLAvatarListEntry::LLAvatarListEntry(const LLUUID& id, const std::string &name, const LLVector3d &position) : - mID(id), mName(name), mPosition(position), mDrawPosition(), mMarked(FALSE), mFocused(FALSE), + mID(id), mName(name), mPosition(position), mDrawPosition(), mMarked(false), mFocused(false), mUpdateTimer(), mFrame(gFrameCount), mInSimFrame(U32_MAX), mInDrawFrame(U32_MAX), mInChatFrame(U32_MAX), mInShoutFrame(U32_MAX), - mActivityType(ACTIVITY_NEW), mActivityTimer() + mActivityType(ACTIVITY_NEW), mActivityTimer(), + mIsInList(false), mAge(-1), mAgeAlert(false), mTime(time(NULL)) { + if (mID.notNull()) + { + LLAvatarPropertiesProcessor::getInstance()->addObserver(mID, this); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(mID); + } +} + +LLAvatarListEntry::~LLAvatarListEntry() +{ + if (mID.notNull()) + LLAvatarPropertiesProcessor::getInstance()->removeObserver(mID, this); +} + +// virtual +void LLAvatarListEntry::processProperties(void* data, EAvatarProcessorType type) +{ + if(type == APT_PROPERTIES) + { + LLAvatarPropertiesProcessor::getInstance()->removeObserver(mID, this); + const LLAvatarData* pAvatarData = static_cast(data); + if (pAvatarData && (pAvatarData->avatar_id != LLUUID::null)) + { + using namespace boost::gregorian; + int year, month, day; + sscanf(pAvatarData->born_on.c_str(),"%d/%d/%d",&month,&day,&year); + mAge = (day_clock::local_day() - date(year, month, day)).days(); + // If one wanted more information that gets displayed on profiles to be displayed, here would be the place to do it. + } + } } void LLAvatarListEntry::setPosition(LLVector3d position, bool this_sim, bool drawn, bool chatrange, bool shoutrange) @@ -220,12 +267,12 @@ bool LLAvatarListEntry::getAlive() return ((current - mFrame) <= 2); } -F32 LLAvatarListEntry::getEntryAgeSeconds() +F32 LLAvatarListEntry::getEntryAgeSeconds() const { return mUpdateTimer.getElapsedTimeF32(); } -BOOL LLAvatarListEntry::isDead() +bool LLAvatarListEntry::isDead() const { return getEntryAgeSeconds() > DEAD_KEEP_TIME; } @@ -239,7 +286,7 @@ void LLAvatarListEntry::setActivity(ACTIVITY_TYPE activity) } } -LLAvatarListEntry::ACTIVITY_TYPE LLAvatarListEntry::getActivity() +const LLAvatarListEntry::ACTIVITY_TYPE LLAvatarListEntry::getActivity() { if ( mActivityTimer.getElapsedTimeF32() > ACTIVITY_TIMEOUT ) { @@ -250,10 +297,14 @@ LLAvatarListEntry::ACTIVITY_TYPE LLAvatarListEntry::getActivity() return mActivityType; } -LLFloaterAvatarList::LLFloaterAvatarList() : LLFloater(std::string("radar")) +LLFloaterAvatarList::LLFloaterAvatarList() : LLFloater(std::string("radar")), + mTracking(false), + mUpdate(true), + mDirtyAvatarSorting(false), + mUpdateRate(gSavedSettings.getU32("RadarUpdateRate") * 3 + 3), + mAvatarList(NULL) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_radar.xml"); - mUpdateRate = gSavedSettings.getU32("RadarUpdateRate") * 3 + 3; } LLFloaterAvatarList::~LLFloaterAvatarList() @@ -315,64 +366,120 @@ void LLFloaterAvatarList::onClose(bool app_quitting) } } +static void cmd_profile(const LLAvatarListEntry* entry); +static void cmd_toggle_mark(LLAvatarListEntry* entry); +static void cmd_ar(const LLAvatarListEntry* entry); +static void cmd_teleport(const LLAvatarListEntry* entry); BOOL LLFloaterAvatarList::postBuild() { - // Default values - mTracking = FALSE; - mUpdate = TRUE; - // Set callbacks - childSetAction("profile_btn", onClickProfile, this); - childSetAction("im_btn", onClickIM, this); - childSetAction("offer_btn", onClickTeleportOffer, this); - childSetAction("track_btn", onClickTrack, this); - childSetAction("mark_btn", onClickMark, this); - childSetAction("focus_btn", onClickFocus, this); - childSetAction("prev_in_list_btn", onClickPrevInList, this); - childSetAction("next_in_list_btn", onClickNextInList, this); - childSetAction("prev_marked_btn", onClickPrevMarked, this); - childSetAction("next_marked_btn", onClickNextMarked, this); + childSetAction("profile_btn", boost::bind(&LLFloaterAvatarList::doCommand, this, &cmd_profile, false)); + childSetAction("im_btn", boost::bind(&LLFloaterAvatarList::onClickIM, this)); + childSetAction("offer_btn", boost::bind(&LLFloaterAvatarList::onClickTeleportOffer, this)); + childSetAction("track_btn", boost::bind(&LLFloaterAvatarList::onClickTrack, this)); + childSetAction("mark_btn", boost::bind(&LLFloaterAvatarList::doCommand, this, &cmd_toggle_mark, false)); + childSetAction("focus_btn", boost::bind(&LLFloaterAvatarList::onClickFocus, this)); + childSetAction("prev_in_list_btn", boost::bind(&LLFloaterAvatarList::focusOnPrev, this, FALSE)); + childSetAction("next_in_list_btn", boost::bind(&LLFloaterAvatarList::focusOnNext, this, FALSE)); + childSetAction("prev_marked_btn", boost::bind(&LLFloaterAvatarList::focusOnPrev, this, TRUE)); + childSetAction("next_marked_btn", boost::bind(&LLFloaterAvatarList::focusOnNext, this, TRUE)); - childSetAction("get_key_btn", onClickGetKey, this); + childSetAction("get_key_btn", boost::bind(&LLFloaterAvatarList::onClickGetKey, this)); - childSetAction("freeze_btn", onClickFreeze, this); - childSetAction("eject_btn", onClickEject, this); - childSetAction("mute_btn", onClickMute, this); - childSetAction("ar_btn", onClickAR, this); - childSetAction("teleport_btn", onClickTeleport, this); - childSetAction("estate_eject_btn", onClickEjectFromEstate, this); - childSetAction("estate_ban_btn", onClickBanFromEstate, this); + childSetAction("freeze_btn", boost::bind(&LLFloaterAvatarList::onClickFreeze, this)); + childSetAction("eject_btn", boost::bind(&LLFloaterAvatarList::onClickEject, this)); + childSetAction("mute_btn", boost::bind(&LLFloaterAvatarList::onClickMute, this)); + childSetAction("ar_btn", boost::bind(&LLFloaterAvatarList::doCommand, this, &cmd_ar, true)); + childSetAction("teleport_btn", boost::bind(&LLFloaterAvatarList::doCommand, this, &cmd_teleport, true)); + childSetAction("estate_eject_btn", boost::bind(&LLFloaterAvatarList::onClickEjectFromEstate, this)); + childSetAction("estate_ban_btn",boost::bind(&LLFloaterAvatarList:: onClickBanFromEstate, this)); - childSetAction("send_keys_btn", onClickSendKeys, this); + childSetAction("send_keys_btn", boost::bind(&LLFloaterAvatarList::sendKeys, this)); getChild("update_rate")->setSelectedIndex(gSavedSettings.getU32("RadarUpdateRate")); - childSetCommitCallback("update_rate", onCommitUpdateRate, this); + getChild("update_rate")->setCommitCallback(boost::bind(&LLFloaterAvatarList::onCommitUpdateRate, this)); + + getChild("hide_mark")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_pos")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_alt")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_act")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_age")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); + getChild("hide_time")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); // Get a pointer to the scroll list from the interface mAvatarList = getChild("avatar_list"); mAvatarList->sortByColumn("distance", TRUE); mAvatarList->setCommitOnSelectionChange(TRUE); - mAvatarList->setCallbackUserData(this); - mAvatarList->setCommitCallback(onSelectName); - mAvatarList->setDoubleClickCallback(onClickFocus); + mAvatarList->setCommitCallback(boost::bind(&LLFloaterAvatarList::onSelectName,this)); + mAvatarList->setDoubleClickCallback(boost::bind(&LLFloaterAvatarList::onClickFocus,this)); + mAvatarList->setSortChangedCallback(boost::bind(&LLFloaterAvatarList::onAvatarSortingChanged,this)); refreshAvatarList(); gIdleCallbacks.addFunction(LLFloaterAvatarList::callbackIdle); - if(gHippoGridManager->getConnectedGrid()->isSecondLife()){ - LLScrollListCtrl* list = getChild("avatar_list"); - list->getColumn(LIST_AVATAR_NAME)->setWidth(0); - list->getColumn(LIST_CLIENT)->setWidth(0); - list->getColumn(LIST_CLIENT)->mDynamicWidth = FALSE; - list->getColumn(LIST_CLIENT)->mRelWidth = 0; - list->getColumn(LIST_AVATAR_NAME)->mDynamicWidth = TRUE; - list->getColumn(LIST_AVATAR_NAME)->mRelWidth = -1; - list->updateLayout(); - } + assessColumns(); + + if(gHippoGridManager->getConnectedGrid()->isSecondLife()) + childSetVisible("hide_client", false); + else + getChild("hide_client")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this)); return TRUE; } +void col_helper(const bool hide, const std::string width_ctrl_name, LLScrollListColumn* col) +{ + // Brief Explanation: + // Check if we want the column hidden, and if it's still showing. If so, hide it, but save its width. + // Otherwise, if we don't want it hidden, but it is, unhide it to the saved width. + // We only store width of columns when hiding here for the purpose of hiding and unhiding. + const int width = col->getWidth(); + + if (hide && width) + { + gSavedSettings.setS32(width_ctrl_name, width); + col->setWidth(0); + } + else if(!hide && !width) + { + llinfos << "We got into the setter!!" << llendl; + col->setWidth(gSavedSettings.getS32(width_ctrl_name)); + } +} + +void LLFloaterAvatarList::assessColumns() +{ + static LLCachedControl hide_mark(gSavedSettings, "RadarColumnMarkHidden"); + col_helper(hide_mark, "RadarColumnMarkWidth", mAvatarList->getColumn(LIST_MARK)); + + static LLCachedControl hide_pos(gSavedSettings, "RadarColumnPositionHidden"); + col_helper(hide_pos, "RadarColumnPositionWidth", mAvatarList->getColumn(LIST_POSITION)); + + static LLCachedControl hide_alt(gSavedSettings, "RadarColumnAltitudeHidden"); + col_helper(hide_alt, "RadarColumnAltitudeWidth", mAvatarList->getColumn(LIST_ALTITUDE)); + + static LLCachedControl hide_act(gSavedSettings, "RadarColumnActivityHidden"); + col_helper(hide_act, "RadarColumnActivityWidth", mAvatarList->getColumn(LIST_ACTIVITY)); + + static LLCachedControl hide_age(gSavedSettings, "RadarColumnAgeHidden"); + col_helper(hide_age, "RadarColumnAgeWidth", mAvatarList->getColumn(LIST_AGE)); + + static LLCachedControl hide_time(gSavedSettings, "RadarColumnTimeHidden"); + col_helper(hide_time, "RadarColumnTimeWidth", mAvatarList->getColumn(LIST_TIME)); + + static LLCachedControl hide_client(gSavedSettings, "RadarColumnClientHidden"); + if (gHippoGridManager->getConnectedGrid()->isSecondLife() || hide_client){ + mAvatarList->getColumn(LIST_AVATAR_NAME)->setWidth(0); + mAvatarList->getColumn(LIST_CLIENT)->setWidth(0); + mAvatarList->getColumn(LIST_CLIENT)->mDynamicWidth = FALSE; + mAvatarList->getColumn(LIST_CLIENT)->mRelWidth = 0; + mAvatarList->getColumn(LIST_AVATAR_NAME)->mDynamicWidth = TRUE; + mAvatarList->getColumn(LIST_AVATAR_NAME)->mRelWidth = -1; + } + + mAvatarList->updateLayout(); +} + void updateParticleActivity(LLDrawable *drawablep) { if (LLFloaterAvatarList::instanceExists()) @@ -438,9 +545,9 @@ void LLFloaterAvatarList::updateAvatarList() sorted_avatar_ids = avatar_ids; std::sort(sorted_avatar_ids.begin(), sorted_avatar_ids.end()); - for (std::vector::const_iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) + BOOST_FOREACH(std::vector::value_type& iter, LLCharacter::sInstances) { - LLUUID avid = (*iter)->getID(); + LLUUID avid = iter->getID(); if (!std::binary_search(sorted_avatar_ids.begin(), sorted_avatar_ids.end(), avid)) { @@ -457,8 +564,6 @@ void LLFloaterAvatarList::updateAvatarList() for (i = 0; i < count; ++i) { std::string name; - std::string first; - std::string last; const LLUUID &avid = avatar_ids[i]; LLVector3d position; @@ -478,29 +583,13 @@ void LLFloaterAvatarList::updateAvatarList() position = gAgent.getPosGlobalFromAgent(avatarp->getCharacterPosition()); name = avatarp->getFullname(); - // [Ansariel: Display name support] - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(avatarp->getID(), &avatar_name)) - { - static LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - switch (phoenix_name_system) - { - case 0 : name = avatar_name.getLegacyName(); break; - case 1 : name = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : name = avatar_name.mDisplayName; break; - default : name = avatar_name.getLegacyName(); break; - } - - first = avatar_name.mLegacyFirstName; - last = avatar_name.mLegacyLastName; - } - else continue; - // [/Ansariel: Display name support] + if (!LLAvatarNameCache::getPNSName(avatarp->getID(), name)) + continue; //duped for lower section if (name.empty() || (name.compare(" ") == 0))// || (name.compare(gCacheName->getDefaultName()) == 0)) { - if (!gCacheName->getFullName(avid, name)) //seems redudant with LLAvatarNameCache::get above... + if (!gCacheName->getFullName(avid, name)) //seems redudant with LLAvatarNameCache::getPNSName above... { continue; } @@ -512,20 +601,20 @@ void LLFloaterAvatarList::updateAvatarList() continue; } - if (mAvatars.count(avid) > 0) + LLAvatarListEntry* entry = getAvatarEntry(avid); + if (entry) { // Avatar already in list, update position F32 dist = (F32)(position - mypos).magVec(); - mAvatars[avid].setPosition(position, (avatarp->getRegion() == gAgent.getRegion()), true, dist < 20.0, dist < 100.0); - if(avatarp->isTyping())mAvatars[avid].setActivity(LLAvatarListEntry::ACTIVITY_TYPING); + entry->setPosition(position, (avatarp->getRegion() == gAgent.getRegion()), true, dist < 20.0, dist < 100.0); + if(avatarp->isTyping())entry->setActivity(LLAvatarListEntry::ACTIVITY_TYPING); } else { // Avatar not there yet, add it - LLAvatarListEntry entry(avid, name, position); if(announce && avatarp->getRegion() == gAgent.getRegion()) announce_keys.push(avid); - mAvatars[avid] = entry; + mAvatars.push_back(LLAvatarListEntryPtr(new LLAvatarListEntry(avid, name, position))); } } else @@ -539,24 +628,24 @@ void LLFloaterAvatarList::updateAvatarList() continue; } - if (!gCacheName->getFullName(avid, name)) + if (!LLAvatarNameCache::getPNSName(avid, name)) { //name = gCacheName->getDefaultName(); continue; //prevent (Loading...) } - if (mAvatars.count(avid) > 0) + LLAvatarListEntry* entry = getAvatarEntry(avid); + if (entry) { // Avatar already in list, update position F32 dist = (F32)(position - mypos).magVec(); - mAvatars[avid].setPosition(position, gAgent.getRegion()->pointInRegionGlobal(position), false, dist < 20.0, dist < 100.0); + entry->setPosition(position, gAgent.getRegion()->pointInRegionGlobal(position), false, dist < 20.0, dist < 100.0); } else { - LLAvatarListEntry entry(avid, name, position); if(announce && gAgent.getRegion()->pointInRegionGlobal(position)) announce_keys.push(avid); - mAvatars[avid] = entry; + mAvatars.push_back(LLAvatarListEntryPtr(new LLAvatarListEntry(avid, name, position))); } } } @@ -618,28 +707,48 @@ void LLFloaterAvatarList::updateAvatarList() void LLFloaterAvatarList::expireAvatarList() { // llinfos << "radar: expiring" << llendl; - std::map::iterator iter; - std::queue delete_queue; - bool alive; - - for (iter = mAvatars.begin(); iter != mAvatars.end(); iter++) + for(av_list_t::iterator it = mAvatars.begin(); it != mAvatars.end();) { - LLAvatarListEntry *entry = &iter->second; - - alive = entry->getAlive(); - - if (entry->isDead()) + LLAvatarListEntry* entry = it->get(); + if(!entry->isDead()) { - //llinfos << "radar: expiring avatar " << entry->getName() << llendl; - LLUUID av_id = entry->getID(); - delete_queue.push(av_id); + entry->getAlive(); + ++it; + } + else + { + if(mAvatars.back() == *it) + { + mAvatars.pop_back(); + return; + } + *it = mAvatars.back(); + mAvatars.pop_back(); + if(mAvatars.empty()) + return; } } +} - while (!delete_queue.empty()) +void LLFloaterAvatarList::updateAvatarSorting() +{ + if(mDirtyAvatarSorting) { - mAvatars.erase(delete_queue.front()); - delete_queue.pop(); + mDirtyAvatarSorting = false; + if(mAvatars.size() <= 1) //Nothing to sort. + return; + const std::vector list = mAvatarList->getAllData(); + av_list_t::iterator insert_it = mAvatars.begin(); + for(std::vector::const_iterator it=list.begin();it!=list.end();++it) + { + av_list_t::iterator av_it = std::find_if(mAvatars.begin(),mAvatars.end(),LLAvatarListEntry::uuidMatch((*it)->getUUID())); + if(av_it!=mAvatars.end()) + { + std::iter_swap(insert_it++,av_it); + if(insert_it+1 == mAvatars.end()) //We've ran out of elements to sort + return; + } + } } } @@ -656,7 +765,7 @@ void LLFloaterAvatarList::refreshAvatarList() // We rebuild the list fully each time it's refreshed // The assumption is that it's faster to refill it and sort than // to rebuild the whole list. - LLDynamicArray selected = mAvatarList->getSelectedIDs(); + uuid_vec_t selected = mAvatarList->getSelectedIDs(); S32 scrollpos = mAvatarList->getScrollPos(); mAvatarList->deleteAllItems(); @@ -666,21 +775,20 @@ void LLFloaterAvatarList::refreshAvatarList() posagent.setVec(gAgent.getPositionAgent()); LLVector3d simpos = mypos - posagent; - std::map::iterator iter; - for (iter = mAvatars.begin(); iter != mAvatars.end(); iter++) + BOOST_FOREACH(av_list_t::value_type& entry, mAvatars) { LLSD element; LLUUID av_id; std::string av_name; - LLAvatarListEntry* entry = &iter->second; - // Skip if avatar hasn't been around if (entry->isDead()) { continue; } + entry->setInList(); + av_id = entry->getID(); av_name = entry->getName().c_str(); @@ -716,6 +824,7 @@ void LLFloaterAvatarList::refreshAvatarList() continue; } + element["id"] = av_id; element["columns"][LIST_MARK]["column"] = "marked"; @@ -755,6 +864,7 @@ void LLFloaterAvatarList::refreshAvatarList() static LLCachedControl sRadarTextChatRange(gColors, "RadarTextChatRange"); static LLCachedControl sRadarTextShoutRange(gColors, "RadarTextShoutRange"); static LLCachedControl sRadarTextDrawDist(gColors, "RadarTextDrawDist"); + static LLCachedControl sRadarTextYoung(gColors, "RadarTextYoung"); LLColor4 name_color = sDefaultListText; //Lindens are always more Linden than your friend, make that take precedence @@ -872,28 +982,50 @@ void LLFloaterAvatarList::refreshAvatarList() element["columns"][LIST_ACTIVITY]["type"] = "icon"; std::string activity_icon = ""; + std::string activity_tip = ""; switch(entry->getActivity()) { case LLAvatarListEntry::ACTIVITY_MOVING: - activity_icon = "inv_item_animation.tga"; + { + activity_icon = "inv_item_animation.tga"; + activity_tip = getString("Moving"); + } break; case LLAvatarListEntry::ACTIVITY_GESTURING: - activity_icon = "inv_item_gesture.tga"; + { + activity_icon = "inv_item_gesture.tga"; + activity_tip = getString("Playing a gesture"); + } break; case LLAvatarListEntry::ACTIVITY_SOUND: - activity_icon = "inv_item_sound.tga"; + { + activity_icon = "inv_item_sound.tga"; + activity_tip = getString("Playing a sound"); + } break; case LLAvatarListEntry::ACTIVITY_REZZING: - activity_icon = "ff_edit_theirs.tga"; + { + activity_icon = "ff_edit_theirs.tga"; + activity_tip = getString("Rezzing objects"); + } break; case LLAvatarListEntry::ACTIVITY_PARTICLES: - activity_icon = "particles_scan.tga"; + { + activity_icon = "particles_scan.tga"; + activity_tip = getString("Creating particles"); + } break; case LLAvatarListEntry::ACTIVITY_NEW: - activity_icon = "avatar_new.tga"; + { + activity_icon = "avatar_new.tga"; + activity_tip = getString("Just arrived"); + } break; case LLAvatarListEntry::ACTIVITY_TYPING: - activity_icon = "avatar_typing.tga"; + { + activity_icon = "avatar_typing.tga"; + activity_tip = getString("Typing"); + } break; default: break; @@ -901,6 +1033,40 @@ void LLFloaterAvatarList::refreshAvatarList() element["columns"][LIST_ACTIVITY]["value"] = activity_icon;//icon_image_id; //"icn_active-speakers-dot-lvl0.tga"; //element["columns"][LIST_AVATAR_ACTIVITY]["color"] = icon_color.getValue(); + element["columns"][LIST_ACTIVITY]["tool_tip"] = activity_tip; + + element["columns"][LIST_AGE]["column"] = "age"; + element["columns"][LIST_AGE]["type"] = "text"; + color = sDefaultListText; + std::string age = boost::lexical_cast(entry->mAge); + if (entry->mAge > -1) + { + static LLCachedControl sAvatarAgeAlertDays(gSavedSettings, "AvatarAgeAlertDays"); + if ((U32)entry->mAge < sAvatarAgeAlertDays) + { + color = sRadarTextYoung; + if (!entry->mAgeAlert) //Only announce age once per entry. + { + entry->mAgeAlert = true; + chat_avatar_status(entry->getName().c_str(), av_id, ALERT_TYPE_AGE, true); + } + } + } + else + { + age = "?"; + } + element["columns"][LIST_AGE]["value"] = age; + element["columns"][LIST_AGE]["color"] = color.getValue(); + + int dur = difftime(time(NULL), entry->getTime()); + int hours = dur / 3600; + int mins = (dur % 3600) / 60; + int secs = (dur % 3600) % 60; + + element["columns"][LIST_TIME]["column"] = "time"; + element["columns"][LIST_TIME]["type"] = "text"; + element["columns"][LIST_TIME]["value"] = llformat("%d:%02d:%02d", hours, mins, secs); element["columns"][LIST_CLIENT]["column"] = "client"; element["columns"][LIST_CLIENT]["type"] = "text"; @@ -944,36 +1110,44 @@ void LLFloaterAvatarList::refreshAvatarList() } // finish - mAvatarList->sortItems(); + mAvatarList->updateSort(); mAvatarList->selectMultiple(selected); mAvatarList->setScrollPos(scrollpos); + + mDirtyAvatarSorting = true; + + if (mAvatars.empty()) + setTitle(getString("Title")); + else if (mAvatars.size() == 1) + setTitle(getString("TitleOneAvatar")); + else + { + LLStringUtil::format_map_t args; + args["[COUNT]"] = boost::lexical_cast(mAvatars.size()); + setTitle(getString("TitleWithCount", args)); + } // llinfos << "radar refresh: done" << llendl; } -// static -void LLFloaterAvatarList::onClickIM(void* userdata) +void LLFloaterAvatarList::onClickIM() { //llinfos << "LLFloaterFriends::onClickIM()" << llendl; - LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata; - - LLDynamicArray ids = self->mAvatarList->getSelectedIDs(); - if (ids.size() > 0) + const uuid_vec_t ids = mAvatarList->getSelectedIDs(); + if (!ids.empty()) { if (ids.size() == 1) { // Single avatar LLUUID agent_id = ids[0]; - // [Ansariel: Display name support] - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(agent_id, &avatar_name)) + std::string avatar_name; + if (gCacheName->getFullName(agent_id, avatar_name)) { gIMMgr->setFloaterOpen(TRUE); - gIMMgr->addSession(LLCacheName::cleanFullName(avatar_name.getLegacyName()),IM_NOTHING_SPECIAL,agent_id); + gIMMgr->addSession(avatar_name,IM_NOTHING_SPECIAL,agent_id); } - // [Ansariel: Display name support] } else { @@ -986,42 +1160,34 @@ void LLFloaterAvatarList::onClickIM(void* userdata) } } -void LLFloaterAvatarList::onClickTeleportOffer(void* userdata) +void LLFloaterAvatarList::onClickTeleportOffer() { - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - - LLDynamicArray ids = self->mAvatarList->getSelectedIDs(); + uuid_vec_t ids = mAvatarList->getSelectedIDs(); if (ids.size() > 0) { handle_lure(ids); } } -void LLFloaterAvatarList::onClickTrack(void* userdata) +void LLFloaterAvatarList::onClickTrack() { - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - - LLScrollListItem* item = self->mAvatarList->getFirstSelected(); + LLScrollListItem* item = mAvatarList->getFirstSelected(); if (!item) return; LLUUID agent_id = item->getUUID(); - if (self->mTracking && self->mTrackedAvatar == agent_id) { + if (mTracking && mTrackedAvatar == agent_id) + { LLTracker::stopTracking(NULL); - self->mTracking = FALSE; + mTracking = FALSE; } else { - self->mTracking = TRUE; - self->mTrackedAvatar = agent_id; + mTracking = TRUE; + mTrackedAvatar = agent_id; // trackAvatar only works for friends allowing you to see them on map... // LLTracker::trackAvatar(agent_id, self->mAvatars[agent_id].getName()); - std::string name = self->mAvatars[agent_id].getName(); - if (!self->mUpdate) - { - name += "\n(last known position)"; - } - LLTracker::trackLocation(self->mAvatars[agent_id].getPosition(), name, name); + trackAvatar(getAvatarEntry(mTrackedAvatar)); } } @@ -1031,15 +1197,12 @@ void LLFloaterAvatarList::refreshTracker() if (LLTracker::isTracking(NULL)) { - LLVector3d pos = mAvatars[mTrackedAvatar].getPosition(); - if (pos != LLTracker::getTrackedPositionGlobal()) + if(LLAvatarListEntry* entry = getAvatarEntry(mTrackedAvatar)) { - std::string name = mAvatars[mTrackedAvatar].getName(); - if (!mUpdate) + if (entry->getPosition() != LLTracker::getTrackedPositionGlobal()) { - name += "\n(last known position)"; + trackAvatar(entry); } - LLTracker::trackLocation(pos, name, name); } } else @@ -1050,6 +1213,17 @@ void LLFloaterAvatarList::refreshTracker() } } +void LLFloaterAvatarList::trackAvatar(const LLAvatarListEntry* entry) +{ + if(!entry) return; + std::string name = entry->getName(); + if (!mUpdate) + { + name += "\n(last known position)"; + } + LLTracker::trackLocation(entry->getPosition(), name, name); +} + LLAvatarListEntry * LLFloaterAvatarList::getAvatarEntry(LLUUID avatar) { if (avatar.isNull()) @@ -1057,32 +1231,11 @@ LLAvatarListEntry * LLFloaterAvatarList::getAvatarEntry(LLUUID avatar) return NULL; } - std::map::iterator iter; - - iter = mAvatars.find(avatar); - if (iter == mAvatars.end()) - { + av_list_t::iterator iter = std::find_if(mAvatars.begin(),mAvatars.end(),LLAvatarListEntry::uuidMatch(avatar)); + if(iter != mAvatars.end()) + return iter->get(); + else return NULL; - } - - return &iter->second; -} - -//static -void LLFloaterAvatarList::onClickMark(void* userdata) -{ - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - LLDynamicArray ids = self->mAvatarList->getSelectedIDs(); - - for (LLDynamicArray::iterator itr = ids.begin(); itr != ids.end(); ++itr) - { - LLUUID avid = *itr; - LLAvatarListEntry* entry = self->getAvatarEntry(avid); - if (entry != NULL) - { - entry->toggleMark(); - } - } } BOOL LLFloaterAvatarList::handleKeyHere(KEY key, MASK mask) @@ -1094,8 +1247,7 @@ BOOL LLFloaterAvatarList::handleKeyHere(KEY key, MASK mask) LLUUID agent_id = item->getUUID(); if (( KEY_RETURN == key ) && (MASK_NONE == mask)) { - self->mFocusedAvatar = agent_id; - self->focusOnCurrent(); + self->setFocusAvatar(agent_id); return TRUE; } else if (( KEY_RETURN == key ) && (MASK_CONTROL == mask)) @@ -1112,7 +1264,7 @@ BOOL LLFloaterAvatarList::handleKeyHere(KEY key, MASK mask) if (( KEY_RETURN == key ) && (MASK_SHIFT == mask)) { - LLDynamicArray ids = self->mAvatarList->getSelectedIDs(); + uuid_vec_t ids = self->mAvatarList->getSelectedIDs(); if (ids.size() > 0) { if (ids.size() == 1) @@ -1120,14 +1272,12 @@ BOOL LLFloaterAvatarList::handleKeyHere(KEY key, MASK mask) // Single avatar LLUUID agent_id = ids[0]; - // [Ansariel: Display name support] - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(agent_id, &avatar_name)) + std::string avatar_name; + if (gCacheName->getFullName(agent_id, avatar_name)) { gIMMgr->setFloaterOpen(TRUE); - gIMMgr->addSession(LLCacheName::cleanFullName(avatar_name.getLegacyName()),IM_NOTHING_SPECIAL,agent_id); + gIMMgr->addSession(avatar_name,IM_NOTHING_SPECIAL,agent_id); } - // [Ansariel: Display name support] } else { @@ -1142,143 +1292,73 @@ BOOL LLFloaterAvatarList::handleKeyHere(KEY key, MASK mask) return LLPanel::handleKeyHere(key, mask); } -void LLFloaterAvatarList::onClickFocus(void* userdata) +void LLFloaterAvatarList::onClickFocus() { - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - - LLScrollListItem* item = self->mAvatarList->getFirstSelected(); + LLScrollListItem* item = mAvatarList->getFirstSelected(); if (item) { - self->mFocusedAvatar = item->getUUID(); - self->focusOnCurrent(); + setFocusAvatar(item->getUUID()); } } void LLFloaterAvatarList::removeFocusFromAll() { - std::map::iterator iter; - - for (iter = mAvatars.begin(); iter != mAvatars.end(); iter++) + BOOST_FOREACH(av_list_t::value_type& entry, mAvatars) { - LLAvatarListEntry* entry = &iter->second; entry->setFocus(FALSE); } } -void LLFloaterAvatarList::focusOnCurrent() +void LLFloaterAvatarList::setFocusAvatar(const LLUUID& id) { - std::map::iterator iter; - LLAvatarListEntry* entry; - - if (mAvatars.size() == 0) + av_list_t::iterator iter = std::find_if(mAvatars.begin(),mAvatars.end(),LLAvatarListEntry::uuidMatch(id)); + if(iter != mAvatars.end()) { - return; + if(!gAgentCamera.lookAtObject(id, false)) + return; + removeFocusFromAll(); + (*iter)->setFocus(TRUE); } +} - for (iter = mAvatars.begin(); iter != mAvatars.end(); iter++) +template +void decrement_focus_target(T begin, T end, BOOL marked_only) +{ + T iter = begin; + while(iter != end && !(*iter)->isFocused()) ++iter; + if(iter == end) + return; + T prev_iter = iter; + while(prev_iter != begin) { - entry = &iter->second; - - if (entry->isDead()) - continue; - - if (entry->getID() == mFocusedAvatar) + const LLAvatarListEntry& entry = *((--prev_iter)->get()); + if(entry.isInList() && (entry.isMarked() || !marked_only) && gAgentCamera.lookAtObject(entry.getID(), false)) { - removeFocusFromAll(); - entry->setFocus(TRUE); - gAgentCamera.lookAtObject(mFocusedAvatar, false); + (*iter)->setFocus(FALSE); + (*prev_iter)->setFocus(TRUE); + gAgentCamera.lookAtObject((*prev_iter)->getID(), false); return; } } + gAgentCamera.lookAtObject((*iter)->getID(), false); } void LLFloaterAvatarList::focusOnPrev(BOOL marked_only) { - std::map::iterator iter; - LLAvatarListEntry* prev = NULL; - LLAvatarListEntry* entry; - - if (mAvatars.size() == 0) - { - return; - } - - for (iter = mAvatars.begin(); iter != mAvatars.end(); iter++) - { - entry = &iter->second; - - if (entry->isDead()) - continue; - - if (prev != NULL && entry->getID() == mFocusedAvatar) - { - break; - } - - if ((!marked_only && entry->isDrawn()) || entry->isMarked()) - { - prev = entry; - } - } - - if (prev != NULL) - { - removeFocusFromAll(); - prev->setFocus(TRUE); - mFocusedAvatar = prev->getID(); - gAgentCamera.lookAtObject(mFocusedAvatar, false); - } + updateAvatarSorting(); + decrement_focus_target(mAvatars.begin(), mAvatars.end(), marked_only); } void LLFloaterAvatarList::focusOnNext(BOOL marked_only) { - std::map::iterator iter; - BOOL found = FALSE; - LLAvatarListEntry* next = NULL; - LLAvatarListEntry* entry; - - if (mAvatars.size() == 0) - { - return; - } - - for (iter = mAvatars.begin(); iter != mAvatars.end(); iter++) - { - entry = &iter->second; - - if (entry->isDead()) - continue; - - if (next == NULL && ((!marked_only && entry->isDrawn()) || entry->isMarked())) - { - next = entry; - } - - if (found && ((!marked_only && entry->isDrawn()) || entry->isMarked())) - { - next = entry; - break; - } - - if (entry->getID() == mFocusedAvatar) - { - found = TRUE; - } - } - - if (next != NULL) - { - removeFocusFromAll(); - next->setFocus(TRUE); - mFocusedAvatar = next->getID(); - gAgentCamera.lookAtObject(mFocusedAvatar, false); - } + updateAvatarSorting(); + decrement_focus_target(mAvatars.rbegin(), mAvatars.rend(), marked_only); } /*static*/ void LLFloaterAvatarList::lookAtAvatar(LLUUID &uuid) { // twisted laws - LLViewerObject* voavatar = gObjectList.findObject(uuid); + LLVOAvatar* voavatar = gObjectList.findAvatar(uuid); if(voavatar && voavatar->isAvatar()) { gAgentCamera.setFocusOnAvatar(FALSE, FALSE); @@ -1291,39 +1371,9 @@ void LLFloaterAvatarList::lookAtAvatar(LLUUID &uuid) } } -//static -void LLFloaterAvatarList::onClickPrevInList(void* userdata) +void LLFloaterAvatarList::onClickGetKey() { - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - self->focusOnPrev(FALSE); -} - -//static -void LLFloaterAvatarList::onClickNextInList(void* userdata) -{ - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - self->focusOnNext(FALSE); -} - -//static -void LLFloaterAvatarList::onClickPrevMarked(void* userdata) -{ - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - self->focusOnPrev(TRUE); -} - -//static -void LLFloaterAvatarList::onClickNextMarked(void* userdata) -{ - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - self->focusOnNext(TRUE); -} - -//static -void LLFloaterAvatarList::onClickGetKey(void *userdata) -{ - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - LLScrollListItem* item = self->mAvatarList->getFirstSelected(); + LLScrollListItem* item = mAvatarList->getFirstSelected(); if (NULL == item) return; @@ -1334,7 +1384,7 @@ void LLFloaterAvatarList::onClickGetKey(void *userdata) gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); } -//static + void LLFloaterAvatarList::sendKeys() { LLViewerRegion* regionp = gAgent.getRegion(); @@ -1432,11 +1482,6 @@ bool LLFloaterAvatarList::onConfirmRadarChatKeys(const LLSD& notification, const } return false; } -//static -void LLFloaterAvatarList::onClickSendKeys(void *userdata) -{ - LLFloaterAvatarList::getInstance()->sendKeys(); -} static void send_freeze(const LLUUID& avatar_id, bool freeze) { @@ -1521,46 +1566,44 @@ static void send_estate_message( msg->sendReliable(gAgent.getRegion()->getHost()); } -static void cmd_freeze(const LLUUID& avatar, const std::string& name) { send_freeze(avatar, true); } -static void cmd_unfreeze(const LLUUID& avatar, const std::string& name) { send_freeze(avatar, false); } -static void cmd_eject(const LLUUID& avatar, const std::string& name) { send_eject(avatar, false); } -static void cmd_ban(const LLUUID& avatar, const std::string& name) { send_eject(avatar, true); } -static void cmd_profile(const LLUUID& avatar, const std::string& name) { LLFloaterAvatarInfo::showFromDirectory(avatar); } -static void cmd_estate_eject(const LLUUID& avatar, const std::string& name){ send_estate_message("teleporthomeuser", avatar); } -static void cmd_estate_ban(const LLUUID &avatar, const std::string &name) { LLPanelEstateInfo::sendEstateAccessDelta(ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY, avatar); } +static void cmd_append_names(const LLAvatarListEntry* entry, std::string &str, std::string &sep) + { if(!str.empty())str.append(sep);str.append(entry->getName()); } +static void cmd_toggle_mark(LLAvatarListEntry* entry) { entry->toggleMark(); } +static void cmd_ar(const LLAvatarListEntry* entry) { LLFloaterReporter::showFromObject(entry->getID()); } +static void cmd_profile(const LLAvatarListEntry* entry) { LLFloaterAvatarInfo::showFromDirectory(entry->getID()); } +static void cmd_teleport(const LLAvatarListEntry* entry) { gAgent.teleportViaLocation(entry->getPosition()); } +static void cmd_freeze(const LLAvatarListEntry* entry) { send_freeze(entry->getID(), true); } +static void cmd_unfreeze(const LLAvatarListEntry* entry) { send_freeze(entry->getID(), false); } +static void cmd_eject(const LLAvatarListEntry* entry) { send_eject(entry->getID(), false); } +static void cmd_ban(const LLAvatarListEntry* entry) { send_eject(entry->getID(), true); } +static void cmd_estate_eject(const LLAvatarListEntry* entry){ send_estate_message("teleporthomeuser", entry->getID()); } +static void cmd_estate_ban(const LLAvatarListEntry* entry) { LLPanelEstateInfo::sendEstateAccessDelta(ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY, entry->getID()); } -void LLFloaterAvatarList::doCommand(void (*func)(const LLUUID& avatar, const std::string& name)) +void LLFloaterAvatarList::doCommand(avlist_command_t func, bool single/*=false*/) { - LLDynamicArray ids = mAvatarList->getSelectedIDs(); - - for (LLDynamicArray::iterator itr = ids.begin(); itr != ids.end(); ++itr) + uuid_vec_t ids; + if(!single) + ids = mAvatarList->getSelectedIDs(); + else + ids.push_back(getSelectedID()); + for (uuid_vec_t::iterator itr = ids.begin(); itr != ids.end(); ++itr) { - LLUUID avid = *itr; + LLUUID& avid = *itr; + if(avid.isNull()) + continue; LLAvatarListEntry* entry = getAvatarEntry(avid); if (entry != NULL) { llinfos << "Executing command on " << entry->getName() << llendl; - func(avid, entry->getName()); + func(entry); } } } std::string LLFloaterAvatarList::getSelectedNames(const std::string& separator) { - std::string ret = ""; - - LLDynamicArray ids = mAvatarList->getSelectedIDs(); - for (LLDynamicArray::iterator itr = ids.begin(); itr != ids.end(); ++itr) - { - LLUUID avid = *itr; - LLAvatarListEntry* entry = getAvatarEntry(avid); - if (entry != NULL) - { - if (!ret.empty()) ret += separator; - ret += entry->getName(); - } - } - + std::string ret; + doCommand(boost::bind(&cmd_append_names,_1,boost::ref(ret),separator)); return ret; } @@ -1585,6 +1628,9 @@ LLUUID LLFloaterAvatarList::getSelectedID() //static void LLFloaterAvatarList::callbackFreeze(const LLSD& notification, const LLSD& response) { + if(!instanceExists()) + return; + S32 option = LLNotification::getSelectedOption(notification, response); if (option == 0) @@ -1600,6 +1646,9 @@ void LLFloaterAvatarList::callbackFreeze(const LLSD& notification, const LLSD& r //static void LLFloaterAvatarList::callbackEject(const LLSD& notification, const LLSD& response) { + if(!instanceExists()) + return; + S32 option = LLNotification::getSelectedOption(notification, response); if (option == 0) @@ -1615,6 +1664,9 @@ void LLFloaterAvatarList::callbackEject(const LLSD& notification, const LLSD& re //static void LLFloaterAvatarList::callbackEjectFromEstate(const LLSD& notification, const LLSD& response) { + if(!instanceExists()) + return; + S32 option = LLNotification::getSelectedOption(notification, response); if (option == 0) @@ -1626,6 +1678,9 @@ void LLFloaterAvatarList::callbackEjectFromEstate(const LLSD& notification, cons //static void LLFloaterAvatarList::callbackBanFromEstate(const LLSD& notification, const LLSD& response) { + if(!instanceExists()) + return; + S32 option = LLNotification::getSelectedOption(notification, response); if (option == 0) @@ -1648,32 +1703,28 @@ void LLFloaterAvatarList::callbackIdle(void* userdata) } } -void LLFloaterAvatarList::onClickFreeze(void* userdata) +void LLFloaterAvatarList::onClickFreeze() { LLSD args; LLSD payload; - args["AVATAR_NAME"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames(); + args["AVATAR_NAME"] = getSelectedNames(); LLNotificationsUtil::add("FreezeAvatarFullname", args, payload, callbackFreeze); } -//static -void LLFloaterAvatarList::onClickEject(void* userdata) +void LLFloaterAvatarList::onClickEject() { LLSD args; LLSD payload; - args["AVATAR_NAME"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames(); + args["AVATAR_NAME"] = getSelectedNames(); LLNotificationsUtil::add("EjectAvatarFullname", args, payload, callbackEject); } -//static -void LLFloaterAvatarList::onClickMute(void* userdata) +void LLFloaterAvatarList::onClickMute() { - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - - LLDynamicArray ids = self->mAvatarList->getSelectedIDs(); + uuid_vec_t ids = mAvatarList->getSelectedIDs(); if (ids.size() > 0) { - for (LLDynamicArray::iterator itr = ids.begin(); itr != ids.end(); ++itr) + for (uuid_vec_t::iterator itr = ids.begin(); itr != ids.end(); ++itr) { LLUUID agent_id = *itr; @@ -1695,86 +1746,45 @@ void LLFloaterAvatarList::onClickMute(void* userdata) } } -//static -void LLFloaterAvatarList::onClickEjectFromEstate(void* userdata) +void LLFloaterAvatarList::onClickEjectFromEstate() { LLSD args; LLSD payload; - args["EVIL_USER"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames(); + args["EVIL_USER"] = getSelectedNames(); LLNotificationsUtil::add("EstateKickUser", args, payload, callbackEjectFromEstate); } -//static -void LLFloaterAvatarList::onClickBanFromEstate(void* userdata) +void LLFloaterAvatarList::onClickBanFromEstate() { LLSD args; LLSD payload; - args["EVIL_USER"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames(); + args["EVIL_USER"] = getSelectedNames(); LLNotificationsUtil::add("EstateBanUser", args, payload, callbackBanFromEstate); } -//static -void LLFloaterAvatarList::onClickAR(void* userdata) +void LLFloaterAvatarList::onAvatarSortingChanged() { - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - LLScrollListItem* item = self->mAvatarList->getFirstSelected(); + mDirtyAvatarSorting = true; +} + +void LLFloaterAvatarList::onSelectName() +{ + LLScrollListItem* item = mAvatarList->getFirstSelected(); if (item) { LLUUID agent_id = item->getUUID(); - LLAvatarListEntry* entry = self->getAvatarEntry(agent_id); - if (entry) - { - LLFloaterReporter::showFromObject(entry->getID()); - } - } -} - -// static -void LLFloaterAvatarList::onClickProfile(void* userdata) -{ - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - self->doCommand(cmd_profile); -} - -//static -void LLFloaterAvatarList::onClickTeleport(void* userdata) -{ - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - LLScrollListItem* item = self->mAvatarList->getFirstSelected(); - if (item) - { - LLUUID agent_id = item->getUUID(); - LLAvatarListEntry* entry = self->getAvatarEntry(agent_id); - if (entry) - { -// llinfos << "Trying to teleport to " << entry->getName() << " at " << entry->getPosition() << llendl; - gAgent.teleportViaLocation(entry->getPosition()); - } - } -} - -void LLFloaterAvatarList::onSelectName(LLUICtrl*, void* userdata) -{ - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - - LLScrollListItem* item = self->mAvatarList->getFirstSelected(); - if (item) - { - LLUUID agent_id = item->getUUID(); - LLAvatarListEntry* entry = self->getAvatarEntry(agent_id); + LLAvatarListEntry* entry = getAvatarEntry(agent_id); if (entry) { BOOL enabled = entry->isDrawn(); - self->childSetEnabled("focus_btn", enabled); - self->childSetEnabled("prev_in_list_btn", enabled); - self->childSetEnabled("next_in_list_btn", enabled); + childSetEnabled("focus_btn", enabled); + childSetEnabled("prev_in_list_btn", enabled); + childSetEnabled("next_in_list_btn", enabled); } } } -void LLFloaterAvatarList::onCommitUpdateRate(LLUICtrl*, void* userdata) +void LLFloaterAvatarList::onCommitUpdateRate() { - LLFloaterAvatarList* self = (LLFloaterAvatarList*)userdata; - - self->mUpdateRate = gSavedSettings.getU32("RadarUpdateRate") * 3 + 3; + mUpdateRate = gSavedSettings.getU32("RadarUpdateRate") * 3 + 3; } diff --git a/indra/newview/llfloateravatarlist.h b/indra/newview/llfloateravatarlist.h index 46bdd1a0f..3bcf4ea67 100644 --- a/indra/newview/llfloateravatarlist.h +++ b/indra/newview/llfloateravatarlist.h @@ -11,6 +11,7 @@ // // #include "llavatarname.h" +#include "llavatarpropertiesprocessor.h" #include "llfloater.h" #include "llfloaterreporter.h" #include "lluuid.h" @@ -21,6 +22,8 @@ #include #include +#include + class LLFloaterAvatarList; /** @@ -29,7 +32,8 @@ class LLFloaterAvatarList; * Instances are kept in a map. We keep track of the * frame where the avatar was last seen. */ -class LLAvatarListEntry { +class LLAvatarListEntry : public LLAvatarPropertiesObserver +{ public: @@ -52,6 +56,10 @@ enum ACTIVITY_TYPE * @param position Avatar's current position */ LLAvatarListEntry(const LLUUID& id = LLUUID::null, const std::string &name = "", const LLVector3d &position = LLVector3d::zero); + ~LLAvatarListEntry(); + + // Get properties, such as age and other niceties displayed on profiles. + /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); /** * Update world position. @@ -59,7 +67,7 @@ enum ACTIVITY_TYPE */ void setPosition(LLVector3d position, bool this_sim, bool drawn, bool chatrange, bool shoutrange); - LLVector3d getPosition() { return mPosition; } + const LLVector3d& getPosition() const { return mPosition; } /** * @brief Returns the age of this entry in frames @@ -72,55 +80,75 @@ enum ACTIVITY_TYPE /** * @brief Returns the age of this entry in seconds */ - F32 getEntryAgeSeconds(); + F32 getEntryAgeSeconds() const; /** * @brief Returns the name of the avatar */ - std::string getName() { return mName; } + const std::string& getName() const { return mName; } + const time_t& getTime() const { return mTime; } /** * @brief Returns the ID of the avatar */ - LLUUID getID() { return mID; } + const LLUUID& getID() const { return mID; } void setActivity(ACTIVITY_TYPE activity); /** * @brief Returns the activity type */ - ACTIVITY_TYPE getActivity(); + const ACTIVITY_TYPE getActivity(); /** * @brief Sets the 'focus' status on this entry (camera focused on this avatar) */ void setFocus(BOOL value) { mFocused = value; } - BOOL isFocused() { return mFocused; } + bool isFocused() const { return mFocused; } - BOOL isMarked() { return mMarked; } + bool isMarked() const { return mMarked; } - BOOL isDrawn() { return (mInDrawFrame != U32_MAX); } + bool isDrawn() const { return (mInDrawFrame != U32_MAX); } - BOOL isInSim() { return (mInSimFrame != U32_MAX); } + bool isInSim() const { return (mInSimFrame != U32_MAX); } + /** + * @brief 'InList' signifies that the entry has been displayed in the floaters avatar list + * Until this happens our focusprev/focusnext logic should ignore this entry. + */ + + void setInList() { mIsInList = true; } + + bool isInList() const { return mIsInList; } /** * @brief Returns whether the item is dead and shouldn't appear in the list * @returns TRUE if dead */ - BOOL isDead(); + bool isDead() const; void toggleMark() { mMarked = !mMarked; } + struct uuidMatch + { + uuidMatch(const LLUUID& id) : mID(id) {} + bool operator()(const boost::shared_ptr& l) { return l->getID() == mID; } + LLUUID mID; + }; + private: friend class LLFloaterAvatarList; LLUUID mID; std::string mName; + time_t mTime; LLVector3d mPosition; LLVector3d mDrawPosition; - BOOL mMarked; - BOOL mFocused; + bool mMarked; + bool mFocused; + bool mIsInList; + bool mAgeAlert; + int mAge; /** * @brief Timer to keep track of whether avatars are still there @@ -186,6 +214,9 @@ public: static void showInstance(); + // Decides which user-chosen columns to show and hide. + void assessColumns(); + /** * @brief Updates the internal avatar list with the currently present avatars. */ @@ -212,7 +243,10 @@ public: static void lookAtAvatar(LLUUID &uuid); static void sound_trigger_hook(LLMessageSystem* msg,void **); - static void sendKeys(); + void sendKeys(); + + typedef boost::shared_ptr LLAvatarListEntryPtr; + typedef std::vector< LLAvatarListEntryPtr > av_list_t; private: // when a line editor loses keyboard focus, it is committed. @@ -227,11 +261,12 @@ private: LIST_POSITION, LIST_ALTITUDE, LIST_ACTIVITY, + LIST_AGE, + LIST_TIME, LIST_CLIENT, }; - - typedef void (*avlist_command_t)(const LLUUID &avatar, const std::string &name); + typedef boost::function avlist_command_t; /** * @brief Removes focus status from all avatars in list @@ -239,9 +274,9 @@ private: void removeFocusFromAll(); /** - * @brief Focus camera on current avatar + * @brief Focus camera on specified avatar */ - void focusOnCurrent(); + void setFocusAvatar(const LLUUID& id); /** * @brief Focus camera on previous avatar @@ -255,6 +290,9 @@ private: */ void focusOnNext(BOOL marked_only); + void refreshTracker(); + void trackAvatar(const LLAvatarListEntry* entry); + /** * @brief Handler for the "refresh" button click. * I am unsure whether this is actually necessary at the time. @@ -263,42 +301,38 @@ private: * @param userdata Pointer to user data (LLFloaterAvatarList instance) */ - static void onClickProfile(void *userdata); - static void onClickIM(void *userdata); - static void onClickTeleportOffer(void *userdata); - static void onClickTrack(void *userdata); - static void onClickMark(void *userdata); - static void onClickFocus(void *userdata); + void onClickIM(); + void onClickTeleportOffer(); + void onClickTrack(); + void onClickMute(); + void onClickFocus(); + void onClickGetKey(); - static void onClickPrevInList(void *userdata); - static void onClickNextInList(void *userdata); - static void onClickPrevMarked(void *userdata); - static void onClickNextMarked(void *userdata); - static void onClickGetKey(void *userdata); + void onSelectName(); + void onCommitUpdateRate(); - static void onClickFreeze(void *userdata); - static void onClickEject(void *userdata); - static void onClickMute(void *userdata); - static void onClickAR(void *userdata); - static void onClickTeleport(void *userdata); - static void onClickEjectFromEstate(void *userdata); - static void onClickBanFromEstate(void *userdata); + /** + * @brief These callbacks fire off notifications, which THEN fire the related callback* functions. + */ + void onClickFreeze(); + void onClickEject(); + void onClickEjectFromEstate(); + void onClickBanFromEstate(); + void onAvatarSortingChanged(); + /** + * @brief Called via notification feedback. + */ static void callbackFreeze(const LLSD& notification, const LLSD& response); static void callbackEject(const LLSD& notification, const LLSD& response); - static void callbackAR(void *userdata); static void callbackEjectFromEstate(const LLSD& notification, const LLSD& response); static void callbackBanFromEstate(const LLSD& notification, const LLSD& response); - static void onSelectName(LLUICtrl*, void *userdata); - - static void onCommitUpdateRate(LLUICtrl*, void *userdata); - static void onClickSendKeys(void *userdata); static bool onConfirmRadarChatKeys(const LLSD& notification, const LLSD& response ); static void callbackIdle(void *userdata); - void doCommand(avlist_command_t cmd); + void doCommand(avlist_command_t cmd, bool single = false); /** * @brief Cleanup avatar list, removing dead entries from it. @@ -307,28 +341,28 @@ private: * to do something to them. */ void expireAvatarList(); + void updateAvatarSorting(); private: /** * @brief Pointer to the avatar scroll list */ LLScrollListCtrl* mAvatarList; - std::map mAvatars; + av_list_t mAvatars; + bool mDirtyAvatarSorting; /** * @brief TRUE when Updating */ - BOOL mUpdate; + bool mUpdate; /** * @brief Update rate (if min frames per update) */ U32 mUpdateRate; - - void refreshTracker(); // tracking data - BOOL mTracking; // Tracking ? + bool mTracking; // Tracking ? LLUUID mTrackedAvatar; // Who we are tracking /** diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index b93812506..dc0ad358c 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -33,21 +33,26 @@ #include "llfloateravatarpicker.h" -#include "message.h" - +// Viewer includes #include "llagent.h" -#include "llbutton.h" #include "llfocusmgr.h" #include "llfoldervieweventlistener.h" -#include "llinventorypanel.h" -#include "llinventorymodel.h" #include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llinventorypanel.h" +#include "llviewercontrol.h" +#include "llviewerregion.h" +#include "llworld.h" + +// Linden libraries +#include "llavatarnamecache.h" // IDEVO +#include "llbutton.h" +#include "llcachename.h" #include "lllineeditor.h" #include "llscrolllistctrl.h" #include "lltextbox.h" #include "lluictrlfactory.h" -#include "llviewercontrol.h" -#include "llworld.h" +#include "message.h" // [RLVa:KB] #include "rlvhandler.h" @@ -60,45 +65,36 @@ const std::string FLOATER_TITLE = "Choose Resident"; // static LLFloaterAvatarPicker* LLFloaterAvatarPicker::sInstance = NULL; +static std::map sAvatarNameMap; - -LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(callback_t callback, - void* userdata, +LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, BOOL allow_multiple, BOOL closeOnSelect) { // TODO: This class should not be a singleton as it's used in multiple places // and therefore can't be used simultaneously. -MG - if (!sInstance) + + LLFloaterAvatarPicker* floater = sInstance ? sInstance : new LLFloaterAvatarPicker(); + floater->open(); /* Flawfinder: ignore */ + if(!sInstance) { - sInstance = new LLFloaterAvatarPicker(); - sInstance->mCallback = callback; - sInstance->mCallbackUserdata = userdata; - sInstance->mCloseOnSelect = FALSE; - - sInstance->open(); /* Flawfinder: ignore */ - sInstance->center(); - sInstance->setAllowMultiple(allow_multiple); - } - else - { - sInstance->open(); /*Flawfinder: ignore*/ - sInstance->mCallback = callback; - sInstance->mCallbackUserdata = userdata; - sInstance->setAllowMultiple(allow_multiple); + sInstance = floater; + floater->center(); } - sInstance->mNearMeListComplete = FALSE; - sInstance->mCloseOnSelect = closeOnSelect; - return sInstance; + floater->mSelectionCallback = callback; + floater->setAllowMultiple(allow_multiple); + floater->mNearMeListComplete = FALSE; + floater->mCloseOnSelect = closeOnSelect; + return floater; } // Default constructor LLFloaterAvatarPicker::LLFloaterAvatarPicker() : LLFloater(std::string("avatarpicker"), FLOATER_RECT, FLOATER_TITLE, TRUE, MIN_WIDTH, MIN_HEIGHT), - mResultsReturned(FALSE), - mCallback(NULL), - mCallbackUserdata(NULL) + mNumResultsReturned(0), + mNearMeListComplete(FALSE), + mCloseOnSelect(FALSE) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml", NULL); } @@ -108,23 +104,25 @@ BOOL LLFloaterAvatarPicker::postBuild() childSetKeystrokeCallback("Edit", editKeystroke, this); childSetKeystrokeCallback("EditUUID", editKeystroke, this); - childSetAction("Find", onBtnFind, this); - childDisable("Find"); - childSetAction("Refresh", onBtnRefresh, this); - childSetCommitCallback("near_me_range", onRangeAdjust, this); + childSetAction("Find", boost::bind(&LLFloaterAvatarPicker::onBtnFind, this)); + getChildView("Find")->setEnabled(FALSE); + childSetAction("Refresh", boost::bind(&LLFloaterAvatarPicker::onBtnRefresh, this)); + getChild("near_me_range")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onRangeAdjust, this)); - childSetDoubleClickCallback("SearchResults", onBtnSelect); - childSetDoubleClickCallback("NearMe", onBtnSelect); - childSetCommitCallback("SearchResults", onList, this); - childSetCommitCallback("NearMe", onList, this); - childDisable("SearchResults"); + LLScrollListCtrl* searchresults = getChild("SearchResults"); + searchresults->setDoubleClickCallback( boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this)); + searchresults->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this)); + getChildView("SearchResults")->setEnabled(FALSE); - childSetAction("Select", onBtnSelect, this); - childDisable("Select"); + LLScrollListCtrl* nearme = getChild("NearMe"); + nearme->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this)); + nearme->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this)); - childSetAction("Cancel", onBtnClose, this); + childSetAction("Select", boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this)); + getChildView("Select")->setEnabled(FALSE); + childSetAction("Cancel", boost::bind(&LLFloaterAvatarPicker::onBtnClose, this)); - childSetFocus("Edit"); + getChild("Edit")->setFocus(TRUE); LLPanel* search_panel = getChild("SearchPanel"); if (search_panel) @@ -133,16 +131,17 @@ BOOL LLFloaterAvatarPicker::postBuild() search_panel->setDefaultBtn("Find"); } - getChild("SearchResults")->addCommentText(getString("no_results")); + getChild("SearchResults")->setCommentText(getString("no_results")); LLInventoryPanel* inventory_panel = getChild("InventoryPanel"); inventory_panel->setFilterTypes(0x1 << LLInventoryType::IT_CALLINGCARD); inventory_panel->setFollowsAll(); inventory_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); inventory_panel->openDefaultFolderForType(LLAssetType::AT_CALLINGCARD); - inventory_panel->setSelectCallback(boost::bind(&LLFloaterAvatarPicker::onCallingCardSelectionChange, _1, _2, (void*)this)); + inventory_panel->setSelectCallback(boost::bind(&LLFloaterAvatarPicker::onCallingCardSelectionChange, this, _1, _2)); - getChild("ResidentChooserTabs")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onTabChanged,this)); + getChild("ResidentChooserTabs")->setCommitCallback( + boost::bind(&LLFloaterAvatarPicker::onTabChanged,this)); setAllowMultiple(FALSE); @@ -162,13 +161,12 @@ LLFloaterAvatarPicker::~LLFloaterAvatarPicker() sInstance = NULL; } -void LLFloaterAvatarPicker::onBtnFind(void* userdata) +void LLFloaterAvatarPicker::onBtnFind() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; - if(self) self->find(); + find(); } -static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vector& avatar_names, std::vector& avatar_ids) +static void getSelectedAvatarData(const LLScrollListCtrl* from, uuid_vec_t& avatar_ids, std::vector& avatar_names) { std::vector items = from->getAllSelected(); for (std::vector::iterator iter = items.begin(); iter != items.end(); ++iter) @@ -176,105 +174,141 @@ static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vectorgetUUID().notNull()) { - avatar_names.push_back(item->getColumn(0)->getValue().asString()); avatar_ids.push_back(item->getUUID()); + + std::map::iterator iter = sAvatarNameMap.find(item->getUUID()); + if (iter != sAvatarNameMap.end()) + { + avatar_names.push_back(iter->second); + } + else + { + // the only case where it isn't in the name map is friends + // but it should be in the name cache + LLAvatarName av_name; + LLAvatarNameCache::get(item->getUUID(), &av_name); + avatar_names.push_back(av_name); + } } } } -void LLFloaterAvatarPicker::onBtnSelect(void* userdata) +void LLFloaterAvatarPicker::onBtnSelect() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; - if(self->mCallback) + // If select btn not enabled then do not callback + if (!visibleItemsSelected()) + return; + + if(mSelectionCallback) { - LLPanel* active_panel = self->childGetVisibleTab("ResidentChooserTabs"); - - if(active_panel == self->getChild("CallingCardsPanel")) + std::vector avatar_names; + std::vector avatar_ids; + std::string active_panel_name; + LLScrollListCtrl* list = NULL; + LLPanel* active_panel = childGetVisibleTab("ResidentChooserTabs"); + if(active_panel) { - self->mCallback(self->mSelectedInventoryAvatarNames, self->mSelectedInventoryAvatarIDs, self->mCallbackUserdata); + active_panel_name = active_panel->getName(); } - else if(active_panel == self->getChild("SearchPanel")) + if(active_panel_name == "CallingCardsPanel") { - std::vector avatar_names; - std::vector avatar_ids; - getSelectedAvatarData(self->getChild("SearchResults"), avatar_names, avatar_ids); - self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata); + avatar_ids = mSelectedInventoryAvatarIDs; + for(std::vector::size_type i = 0; i < avatar_ids.size(); ++i) + { + std::map::iterator iter = sAvatarNameMap.find(avatar_ids[i]); + LLAvatarName av_name; + if (iter != sAvatarNameMap.end()) + { + avatar_names.push_back(iter->second); + } + else if(LLAvatarNameCache::get(avatar_ids[i], &av_name)) + { + avatar_names.push_back(av_name); + } + else + { + std::string name = gCacheName->buildLegacyName(mSelectedInventoryAvatarNames[i]); + std::string::size_type pos = name.find(' '); + av_name.mLegacyFirstName = name.substr(pos); + av_name.mLegacyLastName = pos!=std::string::npos ? name.substr(pos+1) : "Resident"; + av_name.mDisplayName = name; + av_name.mUsername = ""; + avatar_names.push_back(av_name); + } + } } - else if(active_panel == self->getChild("NearMePanel")) + else if(active_panel_name == "SearchPanel") { - std::vector avatar_names; - std::vector avatar_ids; - getSelectedAvatarData(self->getChild("NearMe"), avatar_names, avatar_ids); - self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata); + list = getChild("SearchResults"); } - else if(active_panel == self->getChild("KeyPanel")) + else if(active_panel_name == "NearMePanel") { - LLUUID specified = self->getChild("EditUUID")->getValue().asUUID(); + list = getChild("NearMe"); + } + else if(active_panel_name == "KeyPanel") + { + LLUUID specified = getChild("EditUUID")->getValue().asUUID(); if(specified.isNull()) return; - std::vector avatar_names; - std::vector avatar_ids; avatar_ids.push_back(specified); - avatar_names.push_back(specified.asString()); - self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata); + + std::map::iterator iter = sAvatarNameMap.find(specified); + if (iter != sAvatarNameMap.end()) + { + avatar_names.push_back(iter->second); + } + else + { + LLAvatarName av_name; + LLAvatarNameCache::get(specified, &av_name); + avatar_names.push_back(av_name); + } + } + + if(list) + { + getSelectedAvatarData(list, avatar_ids, avatar_names); + } + if(!avatar_names.empty() && !avatar_ids.empty()) + { + mSelectionCallback(avatar_ids, avatar_names); } } - self->getChild("InventoryPanel")->setSelection(LLUUID::null, FALSE); - self->getChild("SearchResults")->deselectAllItems(TRUE); - self->getChild("NearMe")->deselectAllItems(TRUE); - if(self->mCloseOnSelect) + getChild("InventoryPanel")->setSelection(LLUUID::null, FALSE); + getChild("SearchResults")->deselectAllItems(TRUE); + getChild("NearMe")->deselectAllItems(TRUE); + if(mCloseOnSelect) { - self->mCloseOnSelect = FALSE; - self->close(); + mCloseOnSelect = FALSE; + close(); } } -void LLFloaterAvatarPicker::onBtnRefresh(void* userdata) +void LLFloaterAvatarPicker::onBtnRefresh() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; - if (!self) - { - return; - } - - self->getChild("NearMe")->deleteAllItems(); - self->getChild("NearMe")->addCommentText(self->getString("searching")); - self->mNearMeListComplete = FALSE; + getChild("NearMe")->deleteAllItems(); + getChild("NearMe")->setCommentText(getString("searching")); + mNearMeListComplete = FALSE; } -void LLFloaterAvatarPicker::onBtnClose(void* userdata) +void LLFloaterAvatarPicker::onBtnClose() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; - if(self) self->close(); + close(); } -void LLFloaterAvatarPicker::onRangeAdjust(LLUICtrl* source, void* data) +void LLFloaterAvatarPicker::onRangeAdjust() { - LLFloaterAvatarPicker::onBtnRefresh(data); + onBtnRefresh(); } -void LLFloaterAvatarPicker::onList(LLUICtrl* ctrl, void* userdata) +void LLFloaterAvatarPicker::onList() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; - if (self) - { - self->childSetEnabled("Select", self->visibleItemsSelected()); - } -} - -// static callback for inventory picker (select from calling cards) -void LLFloaterAvatarPicker::onCallingCardSelectionChange(const std::deque &items, BOOL user_action, void* data) -{ - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)data; - if (self) - { - self->doCallingCardSelectionChange( items, user_action, data ); - } + getChildView("Select")->setEnabled(visibleItemsSelected()); } // Callback for inventory picker (select from calling cards) -void LLFloaterAvatarPicker::doCallingCardSelectionChange(const std::deque &items, BOOL user_action, void* data) +void LLFloaterAvatarPicker::onCallingCardSelectionChange(const std::deque &items, BOOL user_action) { bool panel_active = (childGetVisibleTab("ResidentChooserTabs") == getChild("CallingCardsPanel")); @@ -314,7 +348,7 @@ void LLFloaterAvatarPicker::populateNearMe() LLScrollListCtrl* near_me_scroller = getChild("NearMe"); near_me_scroller->deleteAllItems(); - std::vector avatar_ids; + uuid_vec_t avatar_ids; LLWorld::getInstance()->getAvatars(&avatar_ids, NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); for(U32 i=0; igetFullName(av, fullname)) + LLAvatarName av_name; + + if (!LLAvatarNameCache::get(av, &av_name)) { + element["columns"][0]["column"] = "name"; element["columns"][0]["value"] = LLCacheName::getDefaultName(); all_loaded = FALSE; } else { - element["columns"][0]["value"] = fullname; + element["columns"][0]["column"] = "name"; + element["columns"][0]["value"] = av_name.mDisplayName; + element["columns"][1]["column"] = "username"; + element["columns"][1]["value"] = av_name.mUsername; + + sAvatarNameMap[av] = av_name; } near_me_scroller->addElement(element); empty = FALSE; @@ -338,16 +379,16 @@ void LLFloaterAvatarPicker::populateNearMe() if (empty) { - childDisable("NearMe"); - childDisable("Select"); - near_me_scroller->addCommentText(getString("no_one_near")); + getChildView("NearMe")->setEnabled(FALSE); + getChildView("Select")->setEnabled(FALSE); + near_me_scroller->setCommentText(getString("no_one_near")); } else { - childEnable("NearMe"); - childEnable("Select"); + getChildView("NearMe")->setEnabled(TRUE); + getChildView("Select")->setEnabled(TRUE); near_me_scroller->selectFirstItem(); - onList(near_me_scroller, this); + onList(); near_me_scroller->setFocus(TRUE); } @@ -400,38 +441,103 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const } else if(active_panel == getChild("CallingCardsPanel")) { - return mSelectedInventoryAvatarIDs.size() > 0; + return !mSelectedInventoryAvatarIDs.empty(); } else if(active_panel == getChild("NearMePanel")) { return getChild("NearMe")->getFirstSelectedIndex() >= 0; } + else if(active_panel == getChild("KeyPanel")) + { + LLUUID specified = getChild("EditUUID")->getValue().asUUID(); + return !specified.isNull(); + } return FALSE; } +extern AIHTTPTimeoutPolicy avatarPickerResponder_timeout; +class LLAvatarPickerResponder : public LLHTTPClient::ResponderWithCompleted +{ +public: + LLUUID mQueryID; + + LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { } + + /*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content) + { + //std::ostringstream ss; + //LLSDSerialize::toPrettyXML(content, ss); + //llinfos << ss.str() << llendl; + + // in case of invalid characters, the avatar picker returns a 400 + // just set it to process so it displays 'not found' + if ((200 <= status && status < 300) || status == 400) + { + LLFloaterAvatarPicker* floater = LLFloaterAvatarPicker::sInstance; + if (floater) + { + floater->processResponse(mQueryID, content); + } + } + else + { + llinfos << "avatar picker failed " << status + << " reason " << reason << llendl; + + } + } + + const AIHTTPTimeoutPolicy &getHTTPTimeoutPolicy(void) const { return avatarPickerResponder_timeout; } +}; + void LLFloaterAvatarPicker::find() { + //clear our stored LLAvatarNames + sAvatarNameMap.clear(); + const std::string& text = childGetValue("Edit").asString(); mQueryID.generate(); - LLMessageSystem* msg = gMessageSystem; + std::string url; + url.reserve(128); // avoid a memory allocation or two - msg->newMessage("AvatarPickerRequest"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->addUUID("QueryID", mQueryID); // not used right now - msg->nextBlock("Data"); - msg->addString("Name", text); - - gAgent.sendReliableMessage(); + LLViewerRegion* region = gAgent.getRegion(); + url = region->getCapability("AvatarPickerSearch"); + // Prefer use of capabilities to search on both SLID and display name + // but allow display name search to be manually turned off for test + if (!url.empty() + && LLAvatarNameCache::useDisplayNames()) + { + // capability urls don't end in '/', but we need one to parse + // query parameters correctly + if (url.size() > 0 && url[url.size()-1] != '/') + { + url += "/"; + } + url += "?page_size=100&names="; + url += LLURI::escape(text); + llinfos << "avatar picker " << url << llendl; + LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID)); + } + else + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("AvatarPickerRequest"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->addUUID("QueryID", mQueryID); // not used right now + msg->nextBlock("Data"); + msg->addString("Name", text); + gAgent.sendReliableMessage(); + } getChild("SearchResults")->deleteAllItems(); - getChild("SearchResults")->addCommentText(getString("searching")); + getChild("SearchResults")->setCommentText(getString("searching")); childSetEnabled("Select", FALSE); - mResultsReturned = FALSE; + mNumResultsReturned = 0; } void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple) @@ -457,21 +563,21 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* if (agent_id != gAgent.getID()) return; // Dialog already closed - LLFloaterAvatarPicker *self = sInstance; - if (!self) return; + LLFloaterAvatarPicker *floater = sInstance; - // these are not results from our last request - if (query_id != self->mQueryID) + // floater is closed or these are not results from our last request + if (NULL == floater || query_id != floater->mQueryID) { return; } - LLScrollListCtrl* search_results = self->getChild("SearchResults"); + LLScrollListCtrl* search_results = floater->getChild("SearchResults"); // clear "Searching" label on first results - search_results->deleteAllItems(); - - self->mResultsReturned = TRUE; + if (floater->mNumResultsReturned++ == 0) + { + search_results->deleteAllItems(); + } BOOL found_one = FALSE; S32 num_new_rows = msg->getNumberOfBlocks("Data"); @@ -485,32 +591,92 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* if (avatar_id.isNull()) { LLStringUtil::format_map_t map; - map["[TEXT]"] = self->childGetText("Edit"); - avatar_name = self->getString("not_found", map); + map["[TEXT]"] = floater->childGetText("Edit"); + avatar_name = floater->getString("not_found", map); search_results->setEnabled(FALSE); - self->childDisable("Select"); + floater->getChildView("Select")->setEnabled(FALSE); } else { - avatar_name = first_name + " " + last_name; + avatar_name = LLCacheName::buildFullName(first_name, last_name); search_results->setEnabled(TRUE); found_one = TRUE; + + LLAvatarName av_name; + av_name.mLegacyFirstName = first_name; + av_name.mLegacyLastName = last_name; + av_name.mDisplayName = avatar_name; + const LLUUID& agent_id = avatar_id; + sAvatarNameMap[agent_id] = av_name; + } LLSD element; element["id"] = avatar_id; // value + element["columns"][0]["column"] = "name"; element["columns"][0]["value"] = avatar_name; search_results->addElement(element); } if (found_one) { - self->childEnable("Select"); + floater->getChildView("Select")->setEnabled(TRUE); search_results->selectFirstItem(); - self->onList(search_results, self); + floater->onList(); search_results->setFocus(TRUE); } } +void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD& content) +{ + // Check for out-of-date query + if (query_id != mQueryID) return; + + LLScrollListCtrl* search_results = getChild("SearchResults"); + + LLSD agents = content["agents"]; + if (agents.size() == 0) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = childGetText("Edit"); + LLSD item; + item["id"] = LLUUID::null; + item["columns"][0]["column"] = "name"; + item["columns"][0]["value"] = getString("not_found", map); + search_results->addElement(item); + search_results->setEnabled(false); + getChildView("Select")->setEnabled(false); + return; + } + + // clear "Searching" label on first results + search_results->deleteAllItems(); + + LLSD item; + LLSD::array_const_iterator it = agents.beginArray(); + for ( ; it != agents.endArray(); ++it) + { + const LLSD& row = *it; + item["id"] = row["id"]; + LLSD& columns = item["columns"]; + columns[0]["column"] = "name"; + columns[0]["value"] = row["display_name"]; + columns[1]["column"] = "username"; + columns[1]["value"] = row["username"]; + search_results->addElement(item); + + // add the avatar name to our list + LLAvatarName avatar_name; + avatar_name.fromLLSD(row); + sAvatarNameMap[row["id"].asUUID()] = avatar_name; + } + + getChildView("Select")->setEnabled(true); + search_results->setEnabled(true); + search_results->selectFirstItem(); + onList(); + search_results->setFocus(TRUE); +} + //static void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data) { @@ -530,13 +696,13 @@ BOOL LLFloaterAvatarPicker::handleKeyHere(KEY key, MASK mask) { if (key == KEY_RETURN && mask == MASK_NONE) { - if (childHasFocus("Edit")) + if (getChild("Edit")->hasFocus()) { - onBtnFind(this); + onBtnFind(); } else { - onBtnSelect(this); + onBtnSelect(); } return TRUE; } diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 17b928f40..2fc8543a8 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -37,35 +37,40 @@ #include +class LLAvatarName; +class LLScrollListCtrl; class LLFloaterAvatarPicker : public LLFloater { public: - // Call this to select an avatar. + typedef boost::signals2::signal validate_signal_t; + typedef validate_signal_t::slot_type validate_callback_t; + // The callback function will be called with an avatar name and UUID. - typedef void(*callback_t)(const std::vector&, const std::vector&, void*); - static LLFloaterAvatarPicker* show(callback_t callback, - void* userdata, + typedef boost::function&)> select_callback_t; + // Call this to select an avatar. + static LLFloaterAvatarPicker* show(select_callback_t callback, BOOL allow_multiple = FALSE, BOOL closeOnSelect = FALSE); virtual BOOL postBuild(); static void processAvatarPickerReply(class LLMessageSystem* msg, void**); + void processResponse(const LLUUID& query_id, const LLSD& content); + static LLFloaterAvatarPicker* sInstance; private: static void editKeystroke(class LLLineEditor* caller, void* user_data); - static void onBtnFind(void* userdata); - static void onBtnSelect(void* userdata); - static void onBtnRefresh(void* userdata); - static void onRangeAdjust(LLUICtrl* source, void* data); - static void onBtnClose(void* userdata); - static void onList(class LLUICtrl* ctrl, void* userdata); + void onBtnFind(); + void onBtnSelect(); + void onBtnRefresh(); + void onRangeAdjust(); + void onBtnClose(); + void onList(); void onTabChanged(); - void doCallingCardSelectionChange(const std::deque &items, BOOL user_action, void* data); - static void onCallingCardSelectionChange(const std::deque &items, BOOL user_action, void* data); + void onCallingCardSelectionChange(const std::deque &items, BOOL user_action); void populateNearMe(); BOOL visibleItemsSelected() const; // Returns true if any items in the current tab are selected. @@ -79,14 +84,11 @@ private: std::vector mSelectedInventoryAvatarIDs; std::vector mSelectedInventoryAvatarNames; LLUUID mQueryID; - BOOL mResultsReturned; + int mNumResultsReturned; BOOL mNearMeListComplete; BOOL mCloseOnSelect; - void (*mCallback)(const std::vector& name, const std::vector& id, void* userdata); - void* mCallbackUserdata; - - static LLFloaterAvatarPicker* sInstance; + select_callback_t mSelectionCallback; // do not call these directly LLFloaterAvatarPicker(); diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp index 287b799bd..926caee95 100644 --- a/indra/newview/llfloaterbulkpermission.cpp +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -95,7 +95,7 @@ void LLFloaterBulkPermission::doApply() LLSelectMgr::getInstance()->getSelection()->applyToNodes(&gatherer); if(mObjectIDs.empty()) { - list->addCommentText(getString("nothing_to_modify_text")); + list->setCommentText(getString("nothing_to_modify_text")); } else { @@ -180,7 +180,7 @@ void LLFloaterBulkPermission::onCommitCopy(LLUICtrl* ctrl, void* data) BOOL LLFloaterBulkPermission::start() { // note: number of top-level objects to modify is mObjectIDs.count(). - getChild("queue output")->addCommentText(getString("start_text")); + getChild("queue output")->setCommentText(getString("start_text")); return nextObject(); } @@ -203,7 +203,7 @@ BOOL LLFloaterBulkPermission::nextObject() if(isDone() && !mDone) { - getChild("queue output")->addCommentText(getString("done_text")); + getChild("queue output")->setCommentText(getString("done_text")); mDone = TRUE; } return successful_start; @@ -349,7 +349,7 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, LLInv status_text.setArg("[STATUS]", ""); } - list->addCommentText(status_text.getString()); + list->setCommentText(status_text.getString()); //TODO if we are an object inside an object we should check a recuse flag and if set //open the inventory of the object and recurse - Michelle2 Zenovka diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 22281826d..bfb4892c6 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -317,8 +317,9 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) } else { + static LLCachedControl color_muted_chat("ColorMutedChat"); // desaturate muted chat - LLColor4 muted_color = lerp(color, LLColor4::grey, 0.5f); + LLColor4 muted_color = lerp(color, color_muted_chat ? gSavedSettings.getColor4("AscentMutedColor") : LLColor4::grey, 0.5f); add_timestamped_line(history_editor_with_mute, chat, muted_color); } @@ -493,7 +494,7 @@ void LLFloaterChat::triggerAlerts(const std::string& text) { // Cannot instantiate LLTextParser before logging in. if (gDirUtilp->getLindenUserDir(true).empty()) - return; + return; LLTextParser* parser = LLTextParser::getInstance(); // bool spoken=FALSE; @@ -539,7 +540,11 @@ LLColor4 get_text_color(const LLChat& chat) if(chat.mMuted) { - text_color.setVec(0.8f, 0.8f, 0.8f, 1.f); + static LLCachedControl color_muted_chat("ColorMutedChat"); + if (color_muted_chat) + text_color = gSavedSettings.getColor4("AscentMutedColor"); + else + text_color.setVec(0.8f, 0.8f, 0.8f, 1.f); } else { @@ -549,7 +554,7 @@ LLColor4 get_text_color(const LLChat& chat) text_color = gSavedSettings.getColor4("SystemChatColor"); break; case CHAT_SOURCE_AGENT: - if (chat.mFromID.isNull()) + if (chat.mFromID.isNull()) { text_color = gSavedSettings.getColor4("SystemChatColor"); } @@ -561,7 +566,34 @@ LLColor4 get_text_color(const LLChat& chat) } else { - text_color = gSavedSettings.getColor4("AgentChatColor"); + static LLCachedControl color_linden_chat("ColorLindenChat"); + if (color_linden_chat && LLMuteList::getInstance()->isLinden(chat.mFromName)) + { + text_color = gSavedSettings.getColor4("AscentLindenColor"); + } + else if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) + { + static LLCachedControl color_friend_chat("ColorFriendChat"); + static LLCachedControl color_eo_chat("ColorEstateOwnerChat"); + if (color_friend_chat && LLAvatarTracker::instance().isBuddy(chat.mFromID)) + { + text_color = gSavedSettings.getColor4("AscentFriendColor"); + } + else if (color_eo_chat) + { + LLViewerRegion* parent_estate = gAgent.getRegion(); + if (parent_estate && parent_estate->isAlive() && chat.mFromID == parent_estate->getOwner()) + text_color = gSavedSettings.getColor4("AscentEstateOwnerColor"); + else + text_color = gSavedSettings.getColor4("AgentChatColor"); + } + else + text_color = gSavedSettings.getColor4("AgentChatColor"); + } + else + { + text_color = gSavedSettings.getColor4("AgentChatColor"); + } } } break; diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 474e4d874..d44e6f7cb 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -78,8 +78,7 @@ const F32 CONTEXT_FADE_TIME = 0.08f; ////////////////////////////////////////////////////////////////////////////// // default ctor -LLFloaterColorPicker:: -LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate ) +LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate ) : LLFloater (std::string("Color Picker Floater")), mComponents ( 3 ), mMouseDownInLumRegion ( FALSE ), @@ -124,10 +123,7 @@ LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate ) } } -////////////////////////////////////////////////////////////////////////////// -// dtor -LLFloaterColorPicker:: -~LLFloaterColorPicker() +LLFloaterColorPicker::~LLFloaterColorPicker() { // destroy the UI we created destroyUI (); @@ -135,9 +131,7 @@ LLFloaterColorPicker:: ////////////////////////////////////////////////////////////////////////////// // -void -LLFloaterColorPicker:: -createUI () +void LLFloaterColorPicker::createUI () { // build the majority of the gui using the factory builder LLUICtrlFactory::getInstance()->buildFloater ( this, "floater_color_picker.xml" ); @@ -184,9 +178,7 @@ createUI () ////////////////////////////////////////////////////////////////////////////// // -void -LLFloaterColorPicker:: -showUI () +void LLFloaterColorPicker::showUI () { setVisible ( TRUE ); setFocus ( TRUE ); @@ -219,27 +211,24 @@ showUI () ////////////////////////////////////////////////////////////////////////////// // called after the dialog is rendered -BOOL -LLFloaterColorPicker:: -postBuild() +BOOL LLFloaterColorPicker::postBuild() { mCancelBtn = getChild( "cancel_btn" ); - mCancelBtn->setClickedCallback ( boost::bind(&LLFloaterColorPicker::onClickCancel,this) ); + mCancelBtn->setClickedCallback ( onClickCancel, this ); mSelectBtn = getChild( "select_btn"); - mSelectBtn->setClickedCallback ( boost::bind(&LLFloaterColorPicker::onClickSelect,this) ); + mSelectBtn->setClickedCallback ( onClickSelect, this ); mSelectBtn->setFocus ( TRUE ); mPipetteBtn = getChild("color_pipette" ); mPipetteBtn->setImages(std::string("eye_button_inactive.tga"), std::string("eye_button_active.tga")); - mPipetteBtn->setClickedCallback( boost::bind(&LLFloaterColorPicker::onClickPipette,this) ); + mPipetteBtn->setClickedCallback( boost::bind(&LLFloaterColorPicker::onClickPipette,this )); mApplyImmediateCheck = getChild("apply_immediate"); mApplyImmediateCheck->set(gSavedSettings.getBOOL("ApplyColorImmediately")); - mApplyImmediateCheck->setCommitCallback(onImmediateCheck); - mApplyImmediateCheck->setCallbackUserData(this); + mApplyImmediateCheck->setCommitCallback(onImmediateCheck, this); childSetCommitCallback("rspin", onTextCommit, (void*)this ); childSetCommitCallback("gspin", onTextCommit, (void*)this ); @@ -249,14 +238,14 @@ postBuild() childSetCommitCallback("lspin", onTextCommit, (void*)this ); childSetCommitCallback("hexval", onHexCommit, (void*)this ); + LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterColorPicker::onColorSelect, this, _1)); + return TRUE; } ////////////////////////////////////////////////////////////////////////////// // -void -LLFloaterColorPicker:: -initUI ( F32 rValIn, F32 gValIn, F32 bValIn ) +void LLFloaterColorPicker::initUI ( F32 rValIn, F32 gValIn, F32 bValIn ) { // start catching lose-focus events from entry widgets enableTextCallbacks ( TRUE ); @@ -278,9 +267,7 @@ initUI ( F32 rValIn, F32 gValIn, F32 bValIn ) ////////////////////////////////////////////////////////////////////////////// // -void -LLFloaterColorPicker:: -destroyUI () +void LLFloaterColorPicker::destroyUI () { // shut down pipette tool if active stopUsingPipette(); @@ -296,7 +283,7 @@ destroyUI () if ( mSwatchView ) { this->removeChild ( mSwatchView ); - delete mSwatchView; + mSwatchView->die();; mSwatchView = NULL; } } @@ -304,9 +291,7 @@ destroyUI () ////////////////////////////////////////////////////////////////////////////// // -F32 -LLFloaterColorPicker:: -hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn ) +F32 LLFloaterColorPicker::hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn ) { if ( valHUeIn < 0.0f ) valHUeIn += 1.0f; if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f; @@ -318,9 +303,7 @@ hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn ) ////////////////////////////////////////////////////////////////////////////// // -void -LLFloaterColorPicker:: -hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut ) +void LLFloaterColorPicker::hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut ) { if ( sValIn < 0.00001f ) { @@ -348,9 +331,7 @@ hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& ////////////////////////////////////////////////////////////////////////////// // mutator for original RGB value -void -LLFloaterColorPicker:: -setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn ) +void LLFloaterColorPicker::setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn ) { origR = origRIn; origG = origGIn; @@ -359,9 +340,7 @@ setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn ) ////////////////////////////////////////////////////////////////////////////// // accessor for original RGB value -void -LLFloaterColorPicker:: -getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut ) +void LLFloaterColorPicker::getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut ) { origROut = origR; origGOut = origG; @@ -370,9 +349,7 @@ getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut ) ////////////////////////////////////////////////////////////////////////////// // mutator for current RGB value -void -LLFloaterColorPicker:: -setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn ) +void LLFloaterColorPicker::setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn ) { // save current RGB curR = curRIn; @@ -392,9 +369,7 @@ setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn ) ////////////////////////////////////////////////////////////////////////////// // accessor for current RGB value -void -LLFloaterColorPicker:: -getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut ) +void LLFloaterColorPicker::getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut ) { curROut = curR; curGOut = curG; @@ -403,9 +378,7 @@ getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut ) ////////////////////////////////////////////////////////////////////////////// // mutator for current HSL value -void -LLFloaterColorPicker:: -setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn ) +void LLFloaterColorPicker::setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn ) { // save current HSL curH = curHIn; @@ -418,9 +391,7 @@ setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn ) ////////////////////////////////////////////////////////////////////////////// // accessor for current HSL value -void -LLFloaterColorPicker:: -getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut ) +void LLFloaterColorPicker::getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut ) { curHOut = curH; curSOut = curS; @@ -429,9 +400,7 @@ getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut ) ////////////////////////////////////////////////////////////////////////////// // called when 'cancel' clicked -void -LLFloaterColorPicker:: -onClickCancel ( void* data ) +void LLFloaterColorPicker::onClickCancel ( void* data ) { if (data) { @@ -447,9 +416,7 @@ onClickCancel ( void* data ) ////////////////////////////////////////////////////////////////////////////// // called when 'select' clicked -void -LLFloaterColorPicker:: -onClickSelect ( void* data ) +void LLFloaterColorPicker::onClickSelect ( void* data ) { if (data) { @@ -464,31 +431,23 @@ onClickSelect ( void* data ) } } -void LLFloaterColorPicker::onClickPipette( void* data ) +void LLFloaterColorPicker::onClickPipette() { - LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data; - - if ( self) + BOOL pipette_active = mPipetteBtn->getToggleState(); + pipette_active = !pipette_active; + if (pipette_active) { - BOOL pipette_active = self->mPipetteBtn->getToggleState(); - pipette_active = !pipette_active; - if (pipette_active) - { - LLToolPipette::getInstance()->setSelectCallback(onColorSelect, self); - LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance()); - } - else - { - LLToolMgr::getInstance()->clearTransientTool(); - } + LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance()); + } + else + { + LLToolMgr::getInstance()->clearTransientTool(); } } ////////////////////////////////////////////////////////////////////////////// // called when 'text is committed' - i,e. focus moves from a text field -void -LLFloaterColorPicker:: -onTextCommit ( LLUICtrl* ctrl, void* data ) +void LLFloaterColorPicker::onTextCommit ( LLUICtrl* ctrl, void* data ) { if ( data ) { @@ -514,16 +473,12 @@ void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data) } } -void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te, void *data ) +void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te) { - LLFloaterColorPicker* self = (LLFloaterColorPicker*)data; - if (self) + setCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]); + if (mApplyImmediateCheck->get()) { - self->setCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]); - if (self->mApplyImmediateCheck->get()) - { - LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); - } + LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); } } @@ -678,9 +633,7 @@ void LLFloaterColorPicker::draw() ////////////////////////////////////////////////////////////////////////////// // find a complimentary color to the one passed in that can be used to highlight -const LLColor4& -LLFloaterColorPicker:: -getComplimentaryColor ( const LLColor4& backgroundColor ) +const LLColor4& LLFloaterColorPicker::getComplimentaryColor ( const LLColor4& backgroundColor ) { // going to base calculation on luminance F32 hVal, sVal, lVal; @@ -700,9 +653,7 @@ getComplimentaryColor ( const LLColor4& backgroundColor ) ////////////////////////////////////////////////////////////////////////////// // draw color palette -void -LLFloaterColorPicker:: -drawPalette () +void LLFloaterColorPicker::drawPalette () { S32 curEntry = 0; @@ -764,9 +715,7 @@ std::string RGBToHex(int rNum, int gNum, int bNum) } //Called when a hex value is entered into the Hex field - Convert and set values. -void -LLFloaterColorPicker:: -onHexCommit ( LLUICtrl* ctrl, void* data ) +void LLFloaterColorPicker::onHexCommit ( LLUICtrl* ctrl, void* data ) { if ( data ) { @@ -839,9 +788,7 @@ enableTextCallbacks ( BOOL stateIn ) ////////////////////////////////////////////////////////////////////////////// // -void -LLFloaterColorPicker:: -onTextEntryChanged ( LLUICtrl* ctrl ) +void LLFloaterColorPicker::onTextEntryChanged ( LLUICtrl* ctrl ) { // value in RGB boxes changed std::string name = ctrl->getName(); @@ -910,9 +857,7 @@ onTextEntryChanged ( LLUICtrl* ctrl ) ////////////////////////////////////////////////////////////////////////////// // -BOOL -LLFloaterColorPicker:: -updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn ) +BOOL LLFloaterColorPicker::updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn ) { if ( xPosIn >= mRGBViewerImageLeft && xPosIn <= mRGBViewerImageLeft + mRGBViewerImageWidth && @@ -948,9 +893,7 @@ updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn ) ////////////////////////////////////////////////////////////////////////////// // -BOOL -LLFloaterColorPicker:: -handleMouseDown ( S32 x, S32 y, MASK mask ) +BOOL LLFloaterColorPicker::handleMouseDown ( S32 x, S32 y, MASK mask ) { // make it the frontmost gFloaterView->bringToFront(this); @@ -1052,9 +995,7 @@ handleMouseDown ( S32 x, S32 y, MASK mask ) ////////////////////////////////////////////////////////////////////////////// // -BOOL -LLFloaterColorPicker:: -handleHover ( S32 x, S32 y, MASK mask ) +BOOL LLFloaterColorPicker::handleHover ( S32 x, S32 y, MASK mask ) { // if we're the front most window if ( isFrontmost () ) @@ -1130,9 +1071,7 @@ void LLFloaterColorPicker::onClose(bool app_quitting) ////////////////////////////////////////////////////////////////////////////// // reverts state once mouse button is released -BOOL -LLFloaterColorPicker:: -handleMouseUp ( S32 x, S32 y, MASK mask ) +BOOL LLFloaterColorPicker::handleMouseUp ( S32 x, S32 y, MASK mask ) { getWindow()->setCursor ( UI_CURSOR_ARROW ); @@ -1207,9 +1146,7 @@ handleMouseUp ( S32 x, S32 y, MASK mask ) ////////////////////////////////////////////////////////////////////////////// // cancel current color selection, revert to original and close picker -void -LLFloaterColorPicker:: -cancelSelection () +void LLFloaterColorPicker::cancelSelection () { // restore the previous color selection setCurRgb ( getOrigR (), getOrigG (), getOrigB () ); diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h index b93ea664c..185b2a400 100644 --- a/indra/newview/llfloatercolorpicker.h +++ b/indra/newview/llfloatercolorpicker.h @@ -123,11 +123,11 @@ class LLFloaterColorPicker // callbacks static void onClickCancel ( void* data ); static void onClickSelect ( void* data ); - static void onClickPipette ( void* data ); + void onClickPipette ( ); static void onTextCommit ( LLUICtrl* ctrl, void* data ); - static void onHexCommit ( LLUICtrl* ctrl, void* data ); static void onImmediateCheck ( LLUICtrl* ctrl, void* data ); - static void onColorSelect( const LLTextureEntry& te, void *data ); + static void onHexCommit ( LLUICtrl* ctrl, void* data ); + void onColorSelect( const LLTextureEntry& te ); private: // turns on or off text entry commit call backs void enableTextCallbacks ( BOOL stateIn ); diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 890d80829..680df5f05 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -32,7 +32,6 @@ #include "llviewerprecompiledheaders.h" -#include "llappearancemgr.h" #include "llimagejpeg.h" #include "llfloatercustomize.h" #include "llfontgl.h" @@ -64,7 +63,6 @@ #include "llviewercamera.h" #include "llappearance.h" #include "imageids.h" -#include "llmodaldialog.h" #include "llassetstorage.h" #include "lltexturectrl.h" #include "lltextureentry.h" @@ -79,9 +77,9 @@ #include "lluictrlfactory.h" #include "llnotificationsutil.h" #include "llpaneleditwearable.h" +#include "llmakeoutfitdialog.h" #include "statemachine/aifilepicker.h" -#include "hippogridmanager.h" using namespace LLVOAvatarDefines; @@ -119,220 +117,6 @@ BOOL edit_wearable_for_teens(LLWearableType::EType type) } } -class LLMakeOutfitDialog : public LLModalDialog -{ -private: - std::string mFolderName; - void (*mCommitCallback)(LLMakeOutfitDialog*,void*); - void* mCallbackUserData; - std::vector > mCheckBoxList; - -public: - LLMakeOutfitDialog( void(*commit_cb)(LLMakeOutfitDialog*,void*), void* userdata ) - : LLModalDialog(LLStringUtil::null,515, 510, TRUE ), - mCommitCallback( commit_cb ), - mCallbackUserData( userdata ) - { - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_new_outfit_dialog.xml"); - - // Build list of check boxes - for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ ) - { - std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel( (LLWearableType::EType)i ); - mCheckBoxList.push_back(std::make_pair(name,i)); - // Hide teen items - if (gAgent.isTeen() && - !edit_wearable_for_teens((LLWearableType::EType)i)) - { - // hide wearable checkboxes that don't apply to this account - std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel( (LLWearableType::EType)i ); - childSetVisible(name, FALSE); - } - } - - // NOTE: .xml needs to be updated if attachments are added or their names are changed! - LLVOAvatar* avatar = gAgentAvatarp; - if( avatar ) - { - for (LLVOAvatar::attachment_map_t::iterator iter = avatar->mAttachmentPoints.begin(); - iter != avatar->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - S32 attachment_pt = curiter->first; - BOOL object_attached = ( attachment->getNumObjects() > 0 ); - std::string name = std::string("checkbox_") + attachment->getName(); - mCheckBoxList.push_back(std::make_pair(name,attachment_pt)); - childSetEnabled(name, object_attached); - } - } - - if(!gHippoGridManager->getConnectedGrid()->supportsInvLinks()) { - childSetEnabled("checkbox_use_links", FALSE); - childSetValue("checkbox_use_links", FALSE); - childSetEnabled("checkbox_use_outfits", FALSE); - childSetValue("checkbox_use_outfits", FALSE); - } - - childSetAction("Save", onSave, this ); - childSetAction("Cancel", onCancel, this ); - childSetAction("Check All", onCheckAll, this ); - childSetAction("Uncheck All", onUncheckAll, this ); - - LLCheckBoxCtrl* pOutfitFoldersCtrl = getChild("checkbox_use_outfits"); - pOutfitFoldersCtrl->setCommitCallback(&LLMakeOutfitDialog::onOutfitFoldersToggle); - pOutfitFoldersCtrl->setCallbackUserData(this); - } - - bool getUseOutfits() - { - return childGetValue("checkbox_use_outfits").asBoolean(); - } - bool getUseLinks() - { - return childGetValue("checkbox_use_links").asBoolean(); - } - /*bool getRenameClothing() - { - return childGetValue("rename").asBoolean(); - }*/ - virtual void draw() - { - BOOL one_or_more_items_selected = FALSE; - for( S32 i = 0; i < (S32)mCheckBoxList.size(); i++ ) - { - if( childGetValue(mCheckBoxList[i].first).asBoolean() ) - { - one_or_more_items_selected = TRUE; - break; - } - } - - childSetEnabled("Save", one_or_more_items_selected ); - - LLModalDialog::draw(); - } - - const std::string& getFolderName() { return mFolderName; } - - void setWearableToInclude( S32 wearable, S32 enabled, S32 selected ) - { - LLWearableType::EType wtType = (LLWearableType::EType)wearable; - if ( ( (0 <= wtType) && (wtType < LLWearableType::WT_COUNT) ) && - ( (LLAssetType::AT_BODYPART != LLWearableType::getAssetType(wtType)) || (!getUseOutfits()) ) ) - { - std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel(wtType); - childSetEnabled(name, enabled); - childSetValue(name, selected); - } - } - - void getIncludedItems( LLInventoryModel::item_array_t& item_list ) - { - LLInventoryModel::cat_array_t *cats; - LLInventoryModel::item_array_t *items; - gInventory.getDirectDescendentsOf(LLAppearanceMgr::instance().getCOF(), cats, items); - for (LLInventoryModel::item_array_t::const_iterator iter = items->begin(); - iter != items->end(); - ++iter) - { - LLViewerInventoryItem* item = (*iter); - if(!item) - continue; - if(item->isWearableType()) - { - LLWearableType::EType type = item->getWearableType(); - if (type < LLWearableType::WT_COUNT && childGetValue(mCheckBoxList[type].first).asBoolean()) - { - item_list.push_back(item); - } - } - else - { - LLViewerJointAttachment* attachment = gAgentAvatarp->getWornAttachmentPoint(item->getLinkedUUID()); - if(attachment && childGetValue(std::string("checkbox_")+attachment->getName()).asBoolean()) - { - item_list.push_back(item); - } - } - } - } - - static void onSave( void* userdata ) - { - LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata; - self->mFolderName = self->childGetValue("name ed").asString(); - LLStringUtil::trim(self->mFolderName); - if( !self->mFolderName.empty() ) - { - if( self->mCommitCallback ) - { - self->mCommitCallback( self, self->mCallbackUserData ); - } - self->close(); // destroys this object - } - } - - static void onCheckAll( void* userdata ) - { - LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata; - for( S32 i = 0; i < (S32)(self->mCheckBoxList.size()); i++) - { - std::string name = self->mCheckBoxList[i].first; - if(self->childIsEnabled(name))self->childSetValue(name,TRUE); - } - } - - static void onUncheckAll( void* userdata ) - { - LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata; - for( S32 i = 0; i < (S32)(self->mCheckBoxList.size()); i++) - { - std::string name = self->mCheckBoxList[i].first; - if(self->childIsEnabled(name))self->childSetValue(name,FALSE); - } - } - - static void onCancel( void* userdata ) - { - LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata; - self->close(); // destroys this object - } - - BOOL postBuild() - { - refresh(); - return TRUE; - } - - void refresh() - { - BOOL fUseOutfits = getUseOutfits(); - - for (S32 idxType = 0; idxType < LLWearableType::WT_COUNT; idxType++ ) - { - LLWearableType::EType wtType = (LLWearableType::EType)idxType; - if (LLAssetType::AT_BODYPART != LLWearableType::getAssetType(wtType)) - continue; - LLCheckBoxCtrl* pCheckCtrl = getChild(std::string("checkbox_") + LLWearableType::getTypeLabel(wtType)); - if (!pCheckCtrl) - continue; - - pCheckCtrl->setEnabled(!fUseOutfits); - if (fUseOutfits) - pCheckCtrl->setValue(TRUE); - } - childSetEnabled("checkbox_use_links", !fUseOutfits); - } - - static void onOutfitFoldersToggle(LLUICtrl*, void* pParam) - { - LLMakeOutfitDialog* pSelf = (LLMakeOutfitDialog*)pParam; - if (pSelf) - pSelf->refresh(); - } -}; - //////////////////////////////////////////////////////////////////////////// void updateAvatarHeightDisplay() @@ -393,13 +177,13 @@ LLFloaterCustomize::LLFloaterCustomize() BOOL LLFloaterCustomize::postBuild() { - childSetAction("Make Outfit", LLFloaterCustomize::onBtnMakeOutfit, (void*)this); - childSetAction("Ok", LLFloaterCustomize::onBtnOk, (void*)this); - childSetAction("Cancel", LLFloater::onClickClose, (void*)this); + getChild("Make Outfit")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnMakeOutfit, this)); + getChild("Ok")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnOk, this)); + getChild("Cancel")->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); // reX - childSetAction("Import", LLFloaterCustomize::onBtnImport, (void*)this); - childSetAction("Export", LLFloaterCustomize::onBtnExport, (void*)this); + getChild("Import")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnImport, this)); + getChild("Export")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnExport, this)); // Wearable panels initWearablePanels(); @@ -459,7 +243,7 @@ void LLFloaterCustomize::setCurrentWearableType( LLWearableType::EType type ) } // reX: new function -void LLFloaterCustomize::onBtnImport( void* userdata ) +void LLFloaterCustomize::onBtnImport() { AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open(FFLOAD_XML); @@ -519,7 +303,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) } // reX: new function -void LLFloaterCustomize::onBtnExport( void* userdata ) +void LLFloaterCustomize::onBtnExport() { AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open("", FFSAVE_XML); @@ -592,10 +376,8 @@ void LLFloaterCustomize::onBtnExport_continued(AIFilePicker* filepicker) fclose(fp); } -// static -void LLFloaterCustomize::onBtnOk( void* userdata ) +void LLFloaterCustomize::onBtnOk() { - LLFloaterCustomize* floater = (LLFloaterCustomize*) userdata; gAgentWearables.saveAllWearables(); if ( gAgentAvatarp ) @@ -607,55 +389,13 @@ void LLFloaterCustomize::onBtnOk( void* userdata ) gAgent.sendAgentSetAppearance(); } - gFloaterView->sendChildToBack(floater); + gFloaterView->sendChildToBack(this); handle_reset_view(); // Calls askToSaveIfDirty } -// static -void LLFloaterCustomize::onBtnMakeOutfit( void* userdata ) +void LLFloaterCustomize::onBtnMakeOutfit() { - LLVOAvatar* avatar = gAgentAvatarp; - if(avatar) - { - LLMakeOutfitDialog* dialog = new LLMakeOutfitDialog( onMakeOutfitCommit, NULL ); - // LLMakeOutfitDialog deletes itself. - - for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ ) - { - BOOL enabled = (gAgentWearables.getWearableCount( (LLWearableType::EType) i )); // TODO: MULTI-WEARABLE - BOOL selected = (enabled && (LLWearableType::WT_SHIRT <= i) && (i < LLWearableType::WT_COUNT)); // only select clothing by default - if (gAgent.isTeen() - && !edit_wearable_for_teens((LLWearableType::EType)i)) - { - dialog->setWearableToInclude( i, FALSE, FALSE ); - } - else - { - dialog->setWearableToInclude( i, enabled, selected ); - } - } - dialog->startModal(); - } -} - -// static -void LLFloaterCustomize::onMakeOutfitCommit( LLMakeOutfitDialog* dialog, void* userdata ) -{ - LLVOAvatar* avatar = gAgentAvatarp; - if(avatar) - { - LLDynamicArray wearables_to_include; - LLDynamicArray attachments_to_include; // attachment points - - LLInventoryModel::item_array_t item_list; - dialog->getIncludedItems(item_list); - - // MULTI-WEARABLES TODO - if(dialog->getUseOutfits()) - LLAppearanceMgr::instance().makeNewOutfitLinks( dialog->getFolderName(), item_list); - else - LLAppearanceMgr::instance().makeNewOutfitLegacy( dialog->getFolderName(), item_list, dialog->getUseLinks()); - } + new LLMakeOutfitDialog(true); // LLMakeOutfitDialog deletes itself. } //////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llfloatercustomize.h b/indra/newview/llfloatercustomize.h index e603209fe..d82d7c267 100644 --- a/indra/newview/llfloatercustomize.h +++ b/indra/newview/llfloatercustomize.h @@ -98,12 +98,12 @@ public: static LLWearableType::EType getCurrentWearableType() { return sCurrentWearableType; } // Callbacks - static void onBtnOk( void* userdata ); - static void onBtnMakeOutfit( void* userdata ); - static void onMakeOutfitCommit( LLMakeOutfitDialog* dialog, void* userdata ); - static void onBtnImport( void* userdata ); + void onBtnOk(); + void onBtnMakeOutfit(); + void onMakeOutfitCommit(); + void onBtnImport(); static void onBtnImport_continued(AIFilePicker* filepicker); - static void onBtnExport( void* userdata ); + void onBtnExport(); static void onBtnExport_continued(AIFilePicker* filepicker); static void onTabChanged( const LLSD& param ); diff --git a/indra/newview/llfloaterdaycycle.cpp b/indra/newview/llfloaterdaycycle.cpp index 7028e5016..3a4e829cf 100644 --- a/indra/newview/llfloaterdaycycle.cpp +++ b/indra/newview/llfloaterdaycycle.cpp @@ -156,7 +156,7 @@ void LLFloaterDayCycle::initCallbacks(void) childSetAction("DayCycleSavePreset", onSavePreset, comboBox); childSetAction("DayCycleDeletePreset", onDeletePreset, comboBox); - comboBox->setCommitCallback(onChangePresetName); + comboBox->setCommitCallback(boost::bind(&LLFloaterDayCycle::onChangePresetName,_1)); childSetAction("WLAddKey", onAddKey, NULL); @@ -478,7 +478,7 @@ bool LLFloaterDayCycle::newPromptCallback(const LLSD& notification, const LLSD& } -void LLFloaterDayCycle::onChangePresetName(LLUICtrl* ctrl, void * userData) +void LLFloaterDayCycle::onChangePresetName(LLUICtrl* ctrl) { LLComboBox * combo_box = static_cast(ctrl); diff --git a/indra/newview/llfloaterdaycycle.h b/indra/newview/llfloaterdaycycle.h index 9adfc3a02..863ed5418 100644 --- a/indra/newview/llfloaterdaycycle.h +++ b/indra/newview/llfloaterdaycycle.h @@ -117,7 +117,7 @@ public: static bool newPromptCallback(const LLSD& notification, const LLSD& response); /// what to do when you change the preset name - static void onChangePresetName(LLUICtrl* ctrl, void* userData); + static void onChangePresetName(LLUICtrl* ctrl); /// toggle for Linden time static void onUseLindenTime(void* userData); diff --git a/indra/newview/llfloaterexploresounds.cpp b/indra/newview/llfloaterexploresounds.cpp index 6ada9c155..4ce0cf111 100644 --- a/indra/newview/llfloaterexploresounds.cpp +++ b/indra/newview/llfloaterexploresounds.cpp @@ -75,15 +75,16 @@ void LLFloaterExploreSounds::close(bool app_quitting) BOOL LLFloaterExploreSounds::postBuild(void) { - childSetDoubleClickCallback("sound_list", handle_play_locally, this); + LLScrollListCtrl* soundlist = getChild("sound_list"); + soundlist->setDoubleClickCallback(boost::bind(&LLFloaterExploreSounds::handle_play_locally,this)); + soundlist->sortByColumn("playing", TRUE); childSetAction("play_locally_btn", handle_play_locally, this); childSetAction("look_at_btn", handle_look_at, this); childSetAction("stop_btn", handle_stop, this); childSetAction("bl_btn", blacklistSound, this); - LLScrollListCtrl* list = getChild("sound_list"); - list->sortByColumn("playing", TRUE); + return TRUE; } @@ -165,13 +166,7 @@ BOOL LLFloaterExploreSounds::tick() // Save scroll pos and selection so they can be restored S32 scroll_pos = list->getScrollPos(); - LLDynamicArray selected_ids; - std::vector selected_items = list->getAllSelected(); - std::vector::iterator selection_iter = selected_items.begin(); - std::vector::iterator selection_end = selected_items.end(); - for(; selection_iter != selection_end; ++selection_iter) - selected_ids.push_back((*selection_iter)->getUUID()); - + uuid_vec_t selected_ids = list->getSelectedIDs(); list->clearRows(); std::list unique_asset_list; diff --git a/indra/newview/llfloaterfeed.cpp b/indra/newview/llfloaterfeed.cpp new file mode 100644 index 000000000..7b39b13e3 --- /dev/null +++ b/indra/newview/llfloaterfeed.cpp @@ -0,0 +1,177 @@ +/** + * @file llfloaterfeed.cpp + * @brief Feed send floater, allows setting caption and whether or to add location, etc. + * + * $LicenseInfo:firstyear=2012&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * Copyright (c) 2012, Aleric Ingelwood. + * + * 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 "llfloaterfeed.h" + +#include "llfloatersnapshot.h" +#include "llimagepng.h" +#include "llnotificationsutil.h" +#include "lluictrlfactory.h" +#include "llviewertexture.h" +#include "llviewerwindow.h" +#include "llwebprofile.h" + +#include + +///---------------------------------------------------------------------------- +/// Class LLFloaterFeed +///---------------------------------------------------------------------------- + +LLFloaterFeed::LLFloaterFeed(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& img_scale, int index) : + LLFloater(std::string("Feed Floater")), + mPNGImage(png), mViewerImage(img), mImageScale(img_scale), mSnapshotIndex(index) +{ +} + +// Destroys the object +LLFloaterFeed::~LLFloaterFeed() +{ + mPNGImage = NULL; +} + +BOOL LLFloaterFeed::postBuild() +{ + getChild("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterFeed::onClickCancel, this)); + getChild("post_btn")->setCommitCallback(boost::bind(&LLFloaterFeed::onClickPost, this)); + + return true; +} + +// static +LLFloaterFeed* LLFloaterFeed::showFromSnapshot(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& image_scale, int index) +{ + // Take the images from the caller + // It's now our job to clean them up + LLFloaterFeed* instance = new LLFloaterFeed(png, img, image_scale, index); + + LLUICtrlFactory::getInstance()->buildFloater(instance, "floater_snapshot_feed.xml"); + + S32 left, top; + gFloaterView->getNewFloaterPosition(&left, &top); + instance->setOrigin(left, top - instance->getRect().getHeight()); + + instance->open(); + + return instance; +} + +void LLFloaterFeed::draw(void) +{ + LLGLSUIDefault gls_ui; + LLFloater::draw(); + + if (!isMinimized() && mViewerImage.notNull() && mPNGImage.notNull()) + { + LLRect rect(getRect()); + + // First set the max extents of our preview. + rect.translate(-rect.mLeft, -rect.mBottom); + rect.mLeft += 10; + rect.mRight -= 10; + rect.mTop -= 25; + rect.mBottom = rect.mTop - 150; + + // Then fix the aspect ratio. + F32 ratio = (F32)mPNGImage->getWidth() / (F32)mPNGImage->getHeight(); + if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio) + { + rect.mRight = (S32)((F32)rect.mLeft + ((F32)rect.getHeight() * ratio)); + } + else + { + rect.mBottom = (S32)((F32)rect.mTop - ((F32)rect.getWidth() / ratio)); + } + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f)); + rect.stretch(-1); + } + { + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.pushMatrix(); + { + gGL.scalef(mImageScale.mV[VX], mImageScale.mV[VY], 1.f); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), mViewerImage, LLColor4::white); + } + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + } +} + +void LLFloaterFeed::onClickCancel() +{ + // Return false on cancel, to enable the upload button again. + LLFloaterSnapshot::saveFeedDone(false, mSnapshotIndex); + close(false); +} + +void LLFloaterFeed::onClose(bool app_quitting) +{ + LLFloaterSnapshot::saveFeedDone(false, mSnapshotIndex); + destroy(); +} + +void LLFloaterFeed::onClickPost() +{ + if (mPNGImage.notNull()) + { + static LLCachedControl add_location("SnapshotFeedAddLocation"); + const std::string caption = childGetValue("caption").asString(); + LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::saveFeedDone, _1, mPNGImage)); + LLWebProfile::uploadImage(mPNGImage, caption, add_location); + + // give user feedback of the event + gViewerWindow->playSnapshotAnimAndSound(); + + // don't destroy the window until the upload is done + // this way we keep the information in the form + setVisible(FALSE); + + // remove any dependency on snapshot floater + // so we outlive it during the upload. + LLFloater* dependee = getDependee(); + if (dependee) + { + dependee->removeDependentFloater(this); + } + } + else + { + LLNotificationsUtil::add("ErrorProcessingSnapshot"); + } +} diff --git a/indra/newview/llfloaterfeed.h b/indra/newview/llfloaterfeed.h new file mode 100644 index 000000000..a204906ba --- /dev/null +++ b/indra/newview/llfloaterfeed.h @@ -0,0 +1,64 @@ +/** + * @file llfloaterfeed.h + * @brief Feed send floater, allows setting caption and whether or not to include location. + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * Copyright (c) 2012, Aleric Inglewood. + * + * 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_LLFLOATERFEED_H +#define LL_LLFLOATERFEED_H + +#include "llfloater.h" // LLFloater +#include "v2math.h" // LLVector2 +#include "llpointer.h" // LLPointer + +class LLImagePNG; +class LLViewerTexture; + +class LLFloaterFeed : public LLFloater +{ +public: + LLFloaterFeed(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& img_scale, int index); + virtual ~LLFloaterFeed(); + + /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + + static LLFloaterFeed* showFromSnapshot(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& img_scale, int index); + + void onClickCancel(); + void onClickPost(); + +protected: + LLPointer mPNGImage; + LLPointer mViewerImage; + LLVector2 const mImageScale; + int mSnapshotIndex; +}; + +#endif // LL_LLFLOATERFEED_H diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 2b09b57d4..e0ac0a06e 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -44,10 +44,7 @@ #include "llagent.h" #include "llappviewer.h" // for gLastVersionChannel -// [Ansariel: Display name support] -#include "llavatarname.h" #include "llavatarnamecache.h" -// [/Ansariel: Display name support] #include "llfloateravatarpicker.h" #include "llviewerwindow.h" @@ -78,7 +75,7 @@ #include "llfloaterchat.h" // stuff for Contact groups -#include "ascentfloatercontactgroups.h" +//#include "ascentfloatercontactgroups.h" #define DEFAULT_PERIOD 5.0 #define RIGHTS_CHANGE_TIMEOUT 5.0 @@ -87,18 +84,40 @@ #define ONLINE_SIP_ICON_NAME "slim_icon_16_viewer.tga" // simple class to observe the calling cards. -class LLLocalFriendsObserver : public LLFriendObserver, public LLEventTimer + + +class LLAvatarListUpdater : public LLEventTimer { -public: - LLLocalFriendsObserver(LLPanelFriends* floater) : mFloater(floater), LLEventTimer(OBSERVER_TIMEOUT) +public: + LLAvatarListUpdater(F32 period) + : LLEventTimer(period) { mEventTimer.stop(); } - virtual ~LLLocalFriendsObserver() + + virtual BOOL tick() // from LLEventTimer { - mFloater = NULL; + return FALSE; } - virtual void changed(U32 mask) +}; + +class LLLocalFriendsObserver : public LLAvatarListUpdater, public LLFriendObserver +{ + LOG_CLASS(LLLocalFriendsObserver); +public: + LLLocalFriendsObserver(LLPanelFriends* floater) + : mFloater(floater), LLAvatarListUpdater(OBSERVER_TIMEOUT) + { + LLAvatarTracker::instance().addObserver(this); + // For notification when SIP online status changes. + LLVoiceClient::getInstance()->addObserver(this); + } + /*virtual*/ ~LLLocalFriendsObserver() + { + LLVoiceClient::getInstance()->removeObserver(this); + LLAvatarTracker::instance().removeObserver(this); + } + /*virtual*/ void changed(U32 mask) { // events can arrive quickly in bulk - we need not process EVERY one of them - // so we wait a short while to let others pile-in, and process them in aggregate. @@ -107,9 +126,9 @@ public: // save-up all the mask-bits which have come-in mMask |= mask; } - virtual BOOL tick() + /*virtual*/ BOOL tick() { - mFloater->populateContactGroupSelect(); + //mFloater->populateContactGroupSelect(); mFloater->updateFriends(mMask); mEventTimer.stop(); @@ -134,16 +153,10 @@ LLPanelFriends::LLPanelFriends() : { mEventTimer.stop(); mObserver = new LLLocalFriendsObserver(this); - LLAvatarTracker::instance().addObserver(mObserver); - // For notification when SIP online status changes. - LLVoiceClient::getInstance()->addObserver(mObserver); } LLPanelFriends::~LLPanelFriends() { - // For notification when SIP online status changes. - LLVoiceClient::getInstance()->removeObserver(mObserver); - LLAvatarTracker::instance().removeObserver(mObserver); delete mObserver; } @@ -168,7 +181,7 @@ void LLPanelFriends::updateFriends(U32 changed_mask) // if the maximum amount of friends are selected mShowMaxSelectWarning = false; - LLDynamicArray selected_friends = getSelectedIDs(); + const uuid_vec_t selected_friends = mFriendsList->getSelectedIDs(); if(changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE)) { refreshNames(changed_mask); @@ -187,13 +200,13 @@ void LLPanelFriends::updateFriends(U32 changed_mask) tick(); } } - if(selected_friends.size() > 0) + if(!selected_friends.empty()) { // only non-null if friends was already found. This may fail, // but we don't really care here, because refreshUI() will // clean up the interface. friends_list->setCurrentByID(selected_id); - for(LLDynamicArray::iterator itr = selected_friends.begin(); itr != selected_friends.end(); ++itr) + for(uuid_vec_t::const_iterator itr = selected_friends.begin(); itr != selected_friends.end(); ++itr) { friends_list->setSelectedByValue(*itr, true); } @@ -218,7 +231,7 @@ std::string LLPanelFriends::cleanFileName(std::string filename) return filename; } -void LLPanelFriends::populateContactGroupSelect() +/*void LLPanelFriends::populateContactGroupSelect() { LLComboBox* combo = getChild("buddy_group_combobox"); @@ -241,18 +254,18 @@ void LLPanelFriends::populateContactGroupSelect() LLChat msg("Null combo"); LLFloaterChat::addChat(msg); } -} +}*/ -void LLPanelFriends::setContactGroup(std::string contact_grp) +/*void LLPanelFriends::setContactGroup(std::string contact_grp) { LLChat msg("Group set to " + contact_grp); LLFloaterChat::addChat(msg); refreshNames(LLFriendObserver::ADD); refreshUI(); categorizeContacts(); -} +}*/ -void LLPanelFriends::categorizeContacts() +/*void LLPanelFriends::categorizeContacts() { LLSD contact_groups = gSavedPerAccountSettings.getLLSD("AscentContactGroups"); std::string group_name = "All"; @@ -306,7 +319,7 @@ void LLPanelFriends::categorizeContacts() LLChat msg("Null combo."); LLFloaterChat::addChat(msg); } -} +}*/ void LLPanelFriends::filterContacts(const std::string& search_name) { @@ -350,7 +363,7 @@ void LLPanelFriends::onContactSearchEdit(const std::string& search_string, void* } } -void LLPanelFriends::onChangeContactGroup(LLUICtrl* ctrl, void* user_data) +/*void LLPanelFriends::onChangeContactGroup(LLUICtrl* ctrl, void* user_data) { LLPanelFriends* panelp = (LLPanelFriends*)user_data; @@ -359,7 +372,7 @@ void LLPanelFriends::onChangeContactGroup(LLUICtrl* ctrl, void* user_data) LLComboBox* combo = panelp->getChild("buddy_group_combobox"); panelp->setContactGroup(combo->getValue().asString()); } -} +}*/ // -- // virtual @@ -367,9 +380,9 @@ BOOL LLPanelFriends::postBuild() { mFriendsList = getChild("friend_list"); mFriendsList->setCommitOnSelectionChange(TRUE); - childSetCommitCallback("friend_list", onSelectName, this); - childSetCommitCallback("buddy_group_combobox", onChangeContactGroup, this); - childSetDoubleClickCallback("friend_list", onClickIM); + mFriendsList->setCommitCallback(onSelectName, this); + //childSetCommitCallback("buddy_group_combobox", onChangeContactGroup, this); + mFriendsList->setDoubleClickCallback(onClickIM, this); // // Contact search and group system. @@ -387,7 +400,7 @@ BOOL LLPanelFriends::postBuild() refreshNames(changed_mask); childSetAction("im_btn", onClickIM, this); - childSetAction("assign_btn", onClickAssign, this); + //childSetAction("assign_btn", onClickAssign, this); childSetAction("expand_collapse_btn", onClickExpand, this); childSetAction("profile_btn", onClickProfile, this); childSetAction("offer_teleport_btn", onClickOfferTeleport, this); @@ -421,26 +434,8 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id) bool isOnline = relationInfo->isOnline(); std::string fullname; - // [Ansariel: Display name support] - //BOOL have_name = gCacheName->getFullName(agent_id, fullname); - LLAvatarName avatar_name; - BOOL have_name; - if (LLAvatarNameCache::get(agent_id, &avatar_name)) - { - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - switch (phoenix_name_system) - { - case 0 : fullname = avatar_name.getLegacyName(); break; - case 1 : fullname = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : fullname = avatar_name.mDisplayName; break; - default : fullname = avatar_name.getCompleteName(); break; - } + BOOL have_name = LLAvatarNameCache::getPNSName(agent_id, fullname); - have_name = TRUE; - } - else have_name = FALSE; - // [/Ansariel: Display name support] - LLSD element; element["id"] = agent_id; LLSD& friend_column = element["columns"][LIST_FRIEND_NAME]; @@ -520,26 +515,8 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh bool isOnlineSIP = LLVoiceClient::getInstance()->isOnlineSIP(itemp->getUUID()); bool isOnline = info->isOnline(); - std::string fullname; - // [Ansariel: Display name support] - //BOOL have_name = gCacheName->getFullName(agent_id, fullname); - LLAvatarName avatar_name; - BOOL have_name; - if (LLAvatarNameCache::get(agent_id, &avatar_name)) - { - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - switch (phoenix_name_system) - { - case 0 : fullname = avatar_name.getLegacyName(); break; - case 1 : fullname = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : fullname = avatar_name.mDisplayName; break; - default : fullname = avatar_name.getCompleteName(); break; - } - - have_name = TRUE; - } - else have_name = FALSE; - // [/Ansariel: Display name support] + std::string fullname; + BOOL have_name = LLAvatarNameCache::getPNSName(agent_id, fullname); // Name of the status icon to use std::string statusIcon; @@ -580,6 +557,8 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh // enable this item, in case it was disabled after user input itemp->setEnabled(TRUE); + mFriendsList->setNeedsSort(); + // Do not resort, this function can be called frequently. return have_name; } @@ -587,7 +566,7 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh void LLPanelFriends::refreshRightsChangeList() { - LLDynamicArray friends = getSelectedIDs(); + const uuid_vec_t friends = mFriendsList->getSelectedIDs(); S32 num_selected = friends.size(); bool can_offer_teleport = num_selected >= 1; @@ -610,7 +589,7 @@ void LLPanelFriends::refreshRightsChangeList() processing_label->setVisible(false); } Making Dummy View -HgB */ const LLRelationship* friend_status = NULL; - for(LLDynamicArray::iterator itr = friends.begin(); itr != friends.end(); ++itr) + for(uuid_vec_t::const_iterator itr = friends.begin(); itr != friends.end(); ++itr) { friend_status = LLAvatarTracker::instance().getBuddyInfo(*itr); if (friend_status) @@ -635,7 +614,7 @@ void LLPanelFriends::refreshRightsChangeList() if (num_selected == 0) // nothing selected { childSetEnabled("im_btn", FALSE); - childSetEnabled("assign_btn", FALSE); + //childSetEnabled("assign_btn", FALSE); childSetEnabled("offer_teleport_btn", FALSE); } else // we have at least one friend selected... @@ -644,7 +623,7 @@ void LLPanelFriends::refreshRightsChangeList() // to be consistent with context menus in inventory and because otherwise // offline friends would be silently dropped from the session childSetEnabled("im_btn", selected_friends_online || num_selected == 1); - childSetEnabled("assign_btn", num_selected == 1); + //childSetEnabled("assign_btn", num_selected == 1); childSetEnabled("offer_teleport_btn", can_offer_teleport); } } @@ -659,7 +638,7 @@ struct SortFriendsByID void LLPanelFriends::refreshNames(U32 changed_mask) { - LLDynamicArray selected_ids = getSelectedIDs(); + const uuid_vec_t selected_ids = mFriendsList->getSelectedIDs(); S32 pos = mFriendsList->getScrollPos(); // get all buddies we know about @@ -685,7 +664,7 @@ void LLPanelFriends::refreshNames(U32 changed_mask) // Changed item in place, need to request sort and update columns // because we might have changed data in a column on which the user // has already sorted. JC - mFriendsList->sortItems(); + mFriendsList->updateSort(); // re-select items mFriendsList->selectMultiple(selected_ids); @@ -776,7 +755,7 @@ void LLPanelFriends::refreshUI() //Options that can only be performed with one friend selected childSetEnabled("profile_btn", single_selected && !multiple_selected); childSetEnabled("pay_btn", single_selected && !multiple_selected); - childSetEnabled("assign_btn", single_selected && !multiple_selected); + //childSetEnabled("assign_btn", single_selected && !multiple_selected); //Options that can be performed with up to MAX_FRIEND_SELECT friends selected //(single_selected will always be true in this situations) @@ -787,18 +766,6 @@ void LLPanelFriends::refreshUI() refreshRightsChangeList(); } -LLDynamicArray LLPanelFriends::getSelectedIDs() -{ - LLUUID selected_id; - LLDynamicArray friend_ids; - std::vector selected = mFriendsList->getAllSelected(); - for(std::vector::iterator itr = selected.begin(); itr != selected.end(); ++itr) - { - friend_ids.push_back((*itr)->getUUID()); - } - return friend_ids; -} - // static void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data) { @@ -818,8 +785,8 @@ void LLPanelFriends::onClickProfile(void* user_data) LLPanelFriends* panelp = (LLPanelFriends*)user_data; //llinfos << "LLPanelFriends::onClickProfile()" << llendl; - LLDynamicArray ids = panelp->getSelectedIDs(); - if(ids.size() > 0) + const uuid_vec_t ids = panelp->mFriendsList->getSelectedIDs(); + if(!ids.empty()) { LLUUID agent_id = ids[0]; BOOL online; @@ -829,15 +796,15 @@ void LLPanelFriends::onClickProfile(void* user_data) } // static -void LLPanelFriends::onClickAssign(void* user_data) +/*void LLPanelFriends::onClickAssign(void* user_data) { LLPanelFriends* panelp = (LLPanelFriends*)user_data; if (panelp) { - LLDynamicArray ids = panelp->getSelectedIDs(); + const uuid_vec_t ids = panelp->mFriendsList->getSelectedIDs(); ASFloaterContactGroups::show(ids); } -} +}*/ // static void LLPanelFriends::onClickExpand(void* user_data) @@ -885,31 +852,23 @@ void LLPanelFriends::onClickIM(void* user_data) LLPanelFriends* panelp = (LLPanelFriends*)user_data; //llinfos << "LLPanelFriends::onClickIM()" << llendl; - LLDynamicArray ids = panelp->getSelectedIDs(); - if(ids.size() > 0) + const uuid_vec_t ids = panelp->mFriendsList->getSelectedIDs(); + if(!ids.empty()) { + static LLCachedControl tear_off("OtherChatsTornOff"); + if(!tear_off) gIMMgr->setFloaterOpen(TRUE); if(ids.size() == 1) { LLUUID agent_id = ids[0]; const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(agent_id); - // [Ansariel: Display name support] - //std::string fullname; - //if(info && gCacheName->getFullName(agent_id, fullname)) - //{ - // gIMMgr->setFloaterOpen(TRUE); - // gIMMgr->addSession(fullname, IM_NOTHING_SPECIAL, agent_id); - //} - LLAvatarName avatar_name; - if (info && LLAvatarNameCache::get(agent_id, &avatar_name)) + std::string fullname; + if(info && gCacheName->getFullName(agent_id, fullname)) { - gIMMgr->setFloaterOpen(TRUE); - gIMMgr->addSession(LLCacheName::cleanFullName(avatar_name.getLegacyName()),IM_NOTHING_SPECIAL,agent_id); + gIMMgr->addSession(fullname, IM_NOTHING_SPECIAL, agent_id); } - // [/Ansariel: Display name support] } else { - gIMMgr->setFloaterOpen(TRUE); gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], ids); } make_ui_sound("UISndStartIM"); @@ -959,13 +918,12 @@ bool LLPanelFriends::callbackAddFriend(const LLSD& notification, const LLSD& res } // static -void LLPanelFriends::onPickAvatar(const std::vector& names, - const std::vector& ids, - void* ) +void LLPanelFriends::onPickAvatar( const uuid_vec_t& ids, + const std::vector& names ) { if (names.empty()) return; if (ids.empty()) return; - requestFriendshipDialog(ids[0], names[0]); + requestFriendshipDialog(ids[0], names[0].getCompleteName()); } // static @@ -1001,7 +959,7 @@ void LLPanelFriends::onClickAddFriend(void* user_data) { LLPanelFriends* panelp = (LLPanelFriends*)user_data; LLFloater* root_floater = gFloaterView->getParentFloater(panelp); - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(onPickAvatar, user_data, FALSE, TRUE); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelFriends::onPickAvatar, _1, _2), FALSE, TRUE); if (root_floater) { root_floater->addDependentFloater(picker); @@ -1014,38 +972,17 @@ void LLPanelFriends::onClickRemove(void* user_data) LLPanelFriends* panelp = (LLPanelFriends*)user_data; //llinfos << "LLPanelFriends::onClickRemove()" << llendl; - LLDynamicArray ids = panelp->getSelectedIDs(); + const uuid_vec_t ids = panelp->mFriendsList->getSelectedIDs(); LLSD args; - if(ids.size() > 0) + if(!ids.empty()) { std::string msgType = "RemoveFromFriends"; if(ids.size() == 1) { LLUUID agent_id = ids[0]; - // [Ansariel: Display name support] - //std::string first, last; - //if(gCacheName->getName(agent_id, first, last)) - //{ - // args["FIRST_NAME"] = first; - // args["LAST_NAME"] = last; - //} - - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(agent_id, &avatar_name)) - { - std::string fullname; - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - switch (phoenix_name_system) - { - case 0 : fullname = avatar_name.getLegacyName(); break; - case 1 : fullname = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : fullname = avatar_name.mDisplayName; break; - default : fullname = avatar_name.getCompleteName(); break; - } - + std::string fullname; + if (LLAvatarNameCache::getPNSName(agent_id, fullname)) args["NAME"] = fullname; - } - // [/Ansariel: Display name support] } else { @@ -1053,7 +990,7 @@ void LLPanelFriends::onClickRemove(void* user_data) } LLSD payload; - for (LLDynamicArray::iterator it = ids.begin(); + for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) { @@ -1257,8 +1194,8 @@ void LLPanelFriends::onClickOfferTeleport(void* user_data) { LLPanelFriends* panelp = (LLPanelFriends*)user_data; - LLDynamicArray ids = panelp->getSelectedIDs(); - if(ids.size() > 0) + const uuid_vec_t ids = panelp->mFriendsList->getSelectedIDs(); + if(!ids.empty()) { handle_lure(ids); } @@ -1269,8 +1206,8 @@ void LLPanelFriends::onClickPay(void* user_data) { LLPanelFriends* panelp = (LLPanelFriends*)user_data; - LLDynamicArray ids = panelp->getSelectedIDs(); - if(ids.size() == 1) + const uuid_vec_t ids = panelp->mFriendsList->getSelectedIDs(); + if(!ids.empty()) { handle_pay_by_id(ids[0]); } @@ -1281,7 +1218,7 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command if (ids.empty()) return; LLSD args; - if(ids.size() > 0) + if(!ids.empty()) { rights_map_t* rights = new rights_map_t(ids); @@ -1289,28 +1226,9 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command if(ids.size() == 1) { LLUUID agent_id = ids.begin()->first; - //std::string first, last; - //if(gCacheName->getName(agent_id, first, last)) - //{ - // args["FIRST_NAME"] = first; - // args["LAST_NAME"] = last; - //} - - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(agent_id, &avatar_name)) - { - std::string fullname; - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - switch (phoenix_name_system) - { - case 0 : fullname = avatar_name.getLegacyName(); break; - case 1 : fullname = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : fullname = avatar_name.mDisplayName; break; - default : fullname = avatar_name.getCompleteName(); break; - } - + std::string fullname; + if (LLAvatarNameCache::getPNSName(agent_id, fullname)) args["NAME"] = fullname; - } if (command == GRANT) { @@ -1407,6 +1325,7 @@ void LLPanelFriends::applyRightsToFriends() rights &= ~LLRelationship::GRANT_MAP_LOCATION; // propagate rights constraint to UI (*itr)->getColumn(LIST_VISIBLE_MAP)->setValue(FALSE); + mFriendsList->setNeedsSortColumn(LIST_VISIBLE_MAP); } } if(buddy_relationship->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION) != show_map_location) @@ -1418,6 +1337,7 @@ void LLPanelFriends::applyRightsToFriends() rights |= LLRelationship::GRANT_MAP_LOCATION; rights |= LLRelationship::GRANT_ONLINE_STATUS; (*itr)->getColumn(LIST_VISIBLE_ONLINE)->setValue(TRUE); + mFriendsList->setNeedsSortColumn(LIST_VISIBLE_ONLINE); } else { diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h index e97aecc0f..94bfe17b0 100644 --- a/indra/newview/llfloaterfriends.h +++ b/indra/newview/llfloaterfriends.h @@ -41,6 +41,7 @@ #include "lleventtimer.h" #include "llcallingcard.h" +class LLAvatarName; class LLFriendObserver; class LLRelationship; class LLScrollListItem; @@ -126,15 +127,12 @@ private: void confirmModifyRights(rights_map_t& ids, EGrantRevoke command); void sendRightsGrant(rights_map_t& ids); - // return LLUUID::null if nothing is selected - LLDynamicArray getSelectedIDs(); - // callback methods static void onSelectName(LLUICtrl* ctrl, void* user_data); static void onChangeContactGroup(LLUICtrl* ctrl, void* user_data); static bool callbackAddFriend(const LLSD& notification, const LLSD& response); static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response); - static void onPickAvatar(const std::vector& names, const std::vector& ids, void* user_data); + static void onPickAvatar(const uuid_vec_t& ids, const std::vector& names ); static void onContactSearchEdit(const std::string& search_string, void* user_data); static void onClickIM(void* user_data); static void onClickAssign(void* user_data); diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index c2d7ac14b..66c41cd7b 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -114,8 +114,9 @@ BOOL LLFloaterGesture::postBuild() setTitle(label); - childSetCommitCallback("gesture_list", onCommitList, this); - childSetDoubleClickCallback("gesture_list", onClickPlay); + LLScrollListCtrl* gesture_list = getChild("avatar_list"); + gesture_list->setCommitCallback(boost::bind(&LLFloaterGesture::onCommitList,this)); + gesture_list->setDoubleClickCallback(boost::bind(&LLFloaterGesture::onClickPlay,this)); childSetAction("inventory_btn", onClickInventory, this); @@ -168,7 +169,7 @@ void LLFloaterGesture::show() self->mSelectedID = LLUUID::null; // Update button labels - onCommitList(NULL, self); + self->onCommitList(); self->open(); /*Flawfinder: ignore*/ } @@ -213,7 +214,7 @@ void LLFloaterGesture::refreshAll() } // Update button labels - onCommitList(NULL, sInstance); + sInstance->onCommitList(); } } @@ -404,22 +405,19 @@ void LLFloaterGesture::onClickEdit(void* data) } } -// static -void LLFloaterGesture::onCommitList(LLUICtrl* ctrl, void* data) +void LLFloaterGesture::onCommitList() { - LLFloaterGesture* self = (LLFloaterGesture*)data; + const LLUUID& item_id = childGetValue("gesture_list").asUUID(); - const LLUUID& item_id = self->childGetValue("gesture_list").asUUID(); - - self->mSelectedID = item_id; + mSelectedID = item_id; if (LLGestureMgr::instance().isGesturePlaying(item_id)) { - self->childSetVisible("play_btn", false); - self->childSetVisible("stop_btn", true); + childSetVisible("play_btn", false); + childSetVisible("stop_btn", true); } else { - self->childSetVisible("play_btn", true); - self->childSetVisible("stop_btn", false); + childSetVisible("play_btn", true); + childSetVisible("stop_btn", false); } } diff --git a/indra/newview/llfloatergesture.h b/indra/newview/llfloatergesture.h index 4e11a10e6..ba4da14f2 100644 --- a/indra/newview/llfloatergesture.h +++ b/indra/newview/llfloatergesture.h @@ -74,7 +74,7 @@ protected: static void onClickEdit(void* data); static void onClickPlay(void* data); static void onClickNew(void* data); - static void onCommitList(LLUICtrl* ctrl, void* data); + void onCommitList(); protected: LLUUID mSelectedID; diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index ba047ae41..e51e84af0 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -46,6 +46,7 @@ #include "llagent.h" #include "llalertdialog.h" +#include "llavatarnamecache.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" @@ -1264,7 +1265,7 @@ void LLPanelObjectTools::onClickSet(void* data) { LLPanelObjectTools* panelp = (LLPanelObjectTools*) data; // grandparent is a floater, which can have a dependent - gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, data)); + gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, panelp, _1, _2))); } void LLPanelObjectTools::onClickSetBySelection(void* data) @@ -1288,14 +1289,12 @@ void LLPanelObjectTools::onClickSetBySelection(void* data) panelp->childSetValue("target_avatar_name", name); } -// static -void LLPanelObjectTools::callbackAvatarID(const std::vector& names, const std::vector& ids, void* data) +void LLPanelObjectTools::callbackAvatarID(const uuid_vec_t& ids, const std::vector& names) { - LLPanelObjectTools* object_tools = (LLPanelObjectTools*) data; if (ids.empty() || names.empty()) return; - object_tools->mTargetAvatar = ids[0]; - object_tools->childSetValue("target_avatar_name", names[0]); - object_tools->refresh(); + mTargetAvatar = ids[0]; + childSetValue("target_avatar_name", names[0].getCompleteName()); + refresh(); } // static diff --git a/indra/newview/llfloatergodtools.h b/indra/newview/llfloatergodtools.h index 3c36f256f..1c68a7175 100644 --- a/indra/newview/llfloatergodtools.h +++ b/indra/newview/llfloatergodtools.h @@ -41,6 +41,7 @@ #include "llpanel.h" #include +class LLAvatarName; class LLButton; class LLCheckBoxCtrl; class LLComboBox; @@ -237,7 +238,7 @@ public: static void onChangeAnything(LLUICtrl* ctrl, void* data); static void onApplyChanges(void* data); static void onClickSet(void* data); - static void callbackAvatarID(const std::vector& names, const std::vector& ids, void* data); + void callbackAvatarID(const uuid_vec_t& ids, const std::vector& names); static void onClickDeletePublicOwnedBy(void* data); static void onClickDeleteAllScriptedOwnedBy(void* data); static void onClickDeleteAllOwnedBy(void* data); diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp index ddc601f9d..eff6d409b 100644 --- a/indra/newview/llfloatergroups.cpp +++ b/indra/newview/llfloatergroups.cpp @@ -70,9 +70,6 @@ std::map LLFloaterGroupPicker::sInstances; // helper functions void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, const std::string& none_text, U64 powers_mask = GP_ALL_POWERS); -//callbacks -void onGroupSortChanged(void* user_data); - ///---------------------------------------------------------------------------- /// Class LLFloaterGroupPicker ///---------------------------------------------------------------------------- @@ -128,7 +125,8 @@ BOOL LLFloaterGroupPicker::postBuild() { const std::string none_text = getString("none"); - init_group_list(getChild("group list"), gAgent.getGroupID(), none_text, mPowersMask); + LLScrollListCtrl* group_list = getChild("group list"); + init_group_list(group_list, gAgent.getGroupID(), none_text, mPowersMask); childSetAction("OK", onBtnOK, this); @@ -136,8 +134,7 @@ BOOL LLFloaterGroupPicker::postBuild() setDefaultBtn("OK"); - childSetDoubleClickCallback("group list", onBtnOK); - childSetUserData("group list", this); + group_list->setDoubleClickCallback(boost::bind(&LLFloaterGroupPicker::onBtnOK,this)); childEnable("OK"); @@ -214,15 +211,15 @@ void LLPanelGroups::reset() BOOL LLPanelGroups::postBuild() { - childSetCommitCallback("group list", onGroupList, this); - childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count())); childSetTextArg("groupcount", "[MAX]", llformat("%d", gHippoLimits->getMaxAgentGroups())); const std::string none_text = getString("none"); LLScrollListCtrl *group_list = getChild("group list"); init_group_list(group_list, gAgent.getGroupID(), none_text); - group_list->setSortChangedCallback(onGroupSortChanged); //Force 'none' to always be first entry. + group_list->setCommitCallback(boost::bind(&LLPanelGroups::onGroupList,this)); + group_list->setSortChangedCallback(boost::bind(&LLPanelGroups::onGroupSortChanged,this)); //Force 'none' to always be first entry. + group_list->setDoubleClickCallback(boost::bind(&LLPanelGroups::onBtnIM,this)); childSetAction("Activate", onBtnActivate, this); @@ -242,9 +239,6 @@ BOOL LLPanelGroups::postBuild() setDefaultBtn("IM"); - childSetDoubleClickCallback("group list", onBtnIM); - childSetUserData("group list", this); - reset(); return TRUE; @@ -392,7 +386,9 @@ void LLPanelGroups::startIM() LLGroupData group_data; if (gAgent.getGroupData(group_id, group_data)) { - gIMMgr->setFloaterOpen(TRUE); + static LLCachedControl tear_off("OtherChatsTornOff"); + if (!tear_off) + gIMMgr->setFloaterOpen(TRUE); gIMMgr->addSession( group_data.mName, IM_SESSION_GROUP_START, @@ -478,15 +474,20 @@ bool LLPanelGroups::callbackLeaveGroup(const LLSD& notification, const LLSD& res return false; } -void LLPanelGroups::onGroupList(LLUICtrl* ctrl, void* userdata) +void LLPanelGroups::onGroupSortChanged() { - LLPanelGroups *self = (LLPanelGroups*)userdata; - if(!self) + LLScrollListCtrl *group_list = getChild("group list"); + if(!group_list) return; - self->enableButtons(); + group_list->moveToFront(group_list->getItemIndex(LLUUID::null)); +} - LLScrollListCtrl *group_list = (LLScrollListCtrl*)self->getChild("group list"); +void LLPanelGroups::onGroupList() +{ + enableButtons(); + + LLScrollListCtrl *group_list = getChild("group list"); if(!group_list) return; @@ -561,18 +562,6 @@ LLSD create_group_element(const LLGroupData *group_datap, const LLUUID &active_g return element; } -void onGroupSortChanged(void* user_data) -{ - LLPanelGroups *panel = (LLPanelGroups*)user_data; - if(!panel) - return; - LLScrollListCtrl *group_list = (LLScrollListCtrl*)panel->getChild("group list"); - if(!group_list) - return; - - group_list->moveToFront(group_list->getItemIndex(LLUUID::null)); -} - void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, const std::string& none_text, U64 powers_mask) { S32 count = gAgent.mGroups.count(); diff --git a/indra/newview/llfloatergroups.h b/indra/newview/llfloatergroups.h index 5311809eb..ebf37acd7 100644 --- a/indra/newview/llfloatergroups.h +++ b/indra/newview/llfloatergroups.h @@ -103,7 +103,8 @@ protected: // highlight_id is a group id to highlight void enableButtons(); - static void onGroupList(LLUICtrl* ctrl, void* userdata); + void onGroupSortChanged(); + void onGroupList(); static void onBtnCreate(void* userdata); static void onBtnActivate(void* userdata); static void onBtnInfo(void* userdata); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 3d1a4452f..ab3f45aff 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -37,6 +37,7 @@ #include "llfloaterland.h" +#include "llavatarnamecache.h" #include "llcachename.h" #include "llfocusmgr.h" #include "llnotificationsutil.h" @@ -653,20 +654,26 @@ void LLPanelLandGeneral::refresh() S32 area; S32 claim_price; S32 rent_price; - F32 dwell; + F32 dwell = DWELL_NAN; LLViewerParcelMgr::getInstance()->getDisplayInfo(&area, &claim_price, &rent_price, &for_sale, &dwell); - // Area LLUIString price = getString("area_size_text"); price.setArg("[AREA]", llformat("%d",area)); mTextPriceLabel->setText(getString("area_text")); mTextPrice->setText(price.getString()); - mTextDwell->setText(llformat("%.0f", dwell)); + if (dwell == DWELL_NAN) + { + mTextDwell->setText(LLTrans::getString("LoadingData")); + } + else + { + mTextDwell->setText(llformat("%.0f", dwell)); + } if (for_sale) { @@ -1125,8 +1132,8 @@ BOOL LLPanelLandObjects::postBuild() mOwnerList = getChild("owner list"); mOwnerList->sortByColumnIndex(3, FALSE); - childSetCommitCallback("owner list", onCommitList, this); - mOwnerList->setDoubleClickCallback(onDoubleClickOwner); + mOwnerList->setCommitCallback(boost::bind(&LLPanelLandObjects::onCommitList,this)); + mOwnerList->setDoubleClickCallback(boost::bind(&LLPanelLandObjects::onDoubleClickOwner, this)); return TRUE; } @@ -1499,7 +1506,7 @@ void LLPanelLandObjects::onClickRefresh(void* userdata) // ready the list for results self->mOwnerList->deleteAllItems(); - self->mOwnerList->addCommentText(LLTrans::getString("Searching")); + self->mOwnerList->setCommentText(LLTrans::getString("Searching")); self->mOwnerList->setEnabled(FALSE); self->mFirstReply = TRUE; @@ -1526,8 +1533,6 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo return; } - const LLFontGL* FONT = LLFontGL::getFontSansSerif(); - // Extract all of the owners. S32 rows = msg->getNumberOfBlocksFast(_PREHASH_Data); //uuid_list_t return_ids; @@ -1568,44 +1573,64 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo BOOL in_sim = (std::find(avatar_ids.begin(), avatar_ids.end(), owner_id) != avatar_ids.end()); - LLScrollListItem *row = new LLScrollListItem( TRUE, NULL, owner_id); + LLSD item; + item["id"] = owner_id; + LLSD& row = item["columns"]; + LLSD icon_column; + LLSD status_column; + icon_column["type"] = "icon"; + icon_column["column"] = "type"; + status_column["font"] = "SANSSERIF"; + status_column["column"] = "online_status"; + if (is_group_owned) { - row->addColumn(self->mIconGroup); - row->addColumn(OWNER_GROUP, FONT); + icon_column["value"] = self->mIconGroup->getName(); + status_column["value"] = OWNER_GROUP; } else if (in_sim) { - row->addColumn(self->mIconAvatarInSim); - row->addColumn(OWNER_INSIM, FONT); + icon_column["value"] = self->mIconAvatarInSim->getName(); + status_column["value"] = OWNER_INSIM; } else if (is_online) { - row->addColumn(self->mIconAvatarOnline); - row->addColumn(OWNER_ONLINE, FONT); + icon_column["value"] = self->mIconAvatarOnline->getName(); + status_column["value"] = OWNER_ONLINE; } else // offline { - row->addColumn(self->mIconAvatarOffline); - row->addColumn(OWNER_OFFLINE, FONT); + icon_column["value"] = self->mIconAvatarOffline->getName(); + status_column["value"] = OWNER_OFFLINE; } + row.append(icon_column); + row.append(status_column); + // Placeholder for name. - row->addColumn(LLStringUtil::null, FONT); + LLAvatarName av_name; + LLAvatarNameCache::get(owner_id, &av_name); + LLSD name_column; + name_column["value"] = av_name.getCompleteName(); + name_column["font"] = "SANSSERIF"; + name_column["column"] = "name"; + row.append(name_column); - object_count_str = llformat("%d", object_count); - row->addColumn(object_count_str, FONT); + LLSD count_column; + count_column["value"] = llformat("%d", object_count); + count_column["font"] = "SANSSERIF"; + count_column["column"] = "count"; + row.append(count_column); - row->addColumn(formatted_time((time_t)most_recent_time), FONT); + LLSD time_column; + time_column["value"] = formatted_time((time_t)most_recent_time); + time_column["font"] = "SANSSERIF"; + time_column["column"] = "mostrecent"; + row.append(time_column); - - if (is_group_owned) - { - self->mOwnerList->addGroupNameItem(row, ADD_BOTTOM); - } + if( is_group_owned ) + self->mOwnerList->addGroupNameItem(item, ADD_BOTTOM); else - { - self->mOwnerList->addNameItem(row, ADD_BOTTOM); - } + self->mOwnerList->addNameItem(item, ADD_BOTTOM); lldebugs << "object owner " << owner_id << " (" << (is_group_owned ? "group" : "agent") << ") owns " << object_count << " objects." << llendl; @@ -1613,7 +1638,7 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo // check for no results if (0 == self->mOwnerList->getItemCount()) { - self->mOwnerList->addCommentText(LLTrans::getString("NoneFound")); + self->mOwnerList->setCommentText(LLTrans::getString("NoneFound")); } else { @@ -1621,16 +1646,13 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo } } -// static -void LLPanelLandObjects::onCommitList(LLUICtrl* ctrl, void* data) +void LLPanelLandObjects::onCommitList() { - LLPanelLandObjects* self = (LLPanelLandObjects*)data; - - if (FALSE == self->mOwnerList->getCanSelect()) + if (FALSE == mOwnerList->getCanSelect()) { return; } - LLScrollListItem *item = self->mOwnerList->getFirstSelected(); + LLScrollListItem *item = mOwnerList->getFirstSelected(); if (item) { // Look up the selected name, for future dialog box use. @@ -1641,19 +1663,19 @@ void LLPanelLandObjects::onCommitList(LLUICtrl* ctrl, void* data) return; } // Is this a group? - self->mSelectedIsGroup = cell->getValue().asString() == OWNER_GROUP; + mSelectedIsGroup = cell->getValue().asString() == OWNER_GROUP; cell = item->getColumn(2); - self->mSelectedName = cell->getValue().asString(); + mSelectedName = cell->getValue().asString(); cell = item->getColumn(3); - self->mSelectedCount = atoi(cell->getValue().asString().c_str()); + mSelectedCount = atoi(cell->getValue().asString().c_str()); // Set the selection, and enable the return button. - self->mSelectedOwners.clear(); - self->mSelectedOwners.insert(item->getUUID()); - self->mBtnReturnOwnerList->setEnabled(TRUE); + mSelectedOwners.clear(); + mSelectedOwners.insert(item->getUUID()); + mBtnReturnOwnerList->setEnabled(TRUE); // Highlight this user's objects - clickShowCore(self, RT_LIST, &(self->mSelectedOwners)); + clickShowCore(this, RT_LIST, &(mSelectedOwners)); } } @@ -2442,7 +2464,11 @@ void LLPanelLandAccess::refresh() childSetLabelArg("GroupCheck", "[GROUP]", group_name ); // Allow list + if (mListAccess) { + // Clear the sort order so we don't re-sort on every add. + mListAccess->clearSortOrder(); + mListAccess->deleteAllItems(); S32 count = parcel->mAccessList.size(); childSetToolTipArg("AccessList", "[LISTED]", llformat("%d",count)); childSetToolTipArg("AccessList", "[MAX]", llformat("%d",PARCEL_MAX_ACCESS_LIST)); @@ -2478,13 +2504,17 @@ void LLPanelLandAccess::refresh() } suffix.append(" " + getString("remaining") + ")"); } - if (mListAccess) - mListAccess->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix); + mListAccess->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix); } + mListAccess->sortByName(TRUE); } // Ban List + if(mListBanned) { + // Clear the sort order so we don't re-sort on every add. + mListBanned->clearSortOrder(); + mListBanned->deleteAllItems(); S32 count = parcel->mBanList.size(); childSetToolTipArg("BannedList", "[LISTED]", llformat("%d",count)); @@ -2523,6 +2553,7 @@ void LLPanelLandAccess::refresh() } mListBanned->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix); } + mListBanned->sortByName(TRUE); } if(parcel->getRegionDenyAnonymousOverride()) @@ -2790,23 +2821,21 @@ void LLPanelLandAccess::onClickAddAccess(void* data) LLPanelLandAccess* panelp = (LLPanelLandAccess*)data; if (panelp) { - gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarCBAccess, data) ); + gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, panelp, _1))); } } -// static -void LLPanelLandAccess::callbackAvatarCBAccess(const std::vector& names, const std::vector& ids, void* userdata) +void LLPanelLandAccess::callbackAvatarCBAccess(const uuid_vec_t& ids) { - LLPanelLandAccess* panelp = (LLPanelLandAccess*)userdata; - if (!names.empty() && !ids.empty()) + if (!ids.empty()) { LLUUID id = ids[0]; - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (parcel) { parcel->addToAccessList(id, 0); LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_ACCESS); - panelp->refresh(); + refresh(); } } } @@ -2838,22 +2867,20 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data) void LLPanelLandAccess::onClickAddBanned(void* data) { LLPanelLandAccess* panelp = (LLPanelLandAccess*)data; - gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarCBBanned, data) ); + gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, panelp, _1))); } -// static -void LLPanelLandAccess::callbackAvatarCBBanned(const std::vector& names, const std::vector& ids, void* userdata) +void LLPanelLandAccess::callbackAvatarCBBanned(const uuid_vec_t& ids) { - LLPanelLandAccess* panelp = (LLPanelLandAccess*)userdata; - if (!names.empty() && !ids.empty()) + if (!ids.empty()) { LLUUID id = ids[0]; - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (parcel) { parcel->addToBanList(id, 0); LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_BAN); - panelp->refresh(); + refresh(); } } } diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 19e8b5260..d7c0cfeef 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -274,7 +274,7 @@ public: static void onDoubleClickOwner(void*); - static void onCommitList(LLUICtrl* ctrl, void* data); + void onCommitList(); static void onLostFocus(LLFocusableElement* caller, void* user_data); static void onCommitClean(LLUICtrl* caller, void* user_data); static void processParcelObjectOwnersReply(LLMessageSystem *msg, void **); @@ -383,10 +383,10 @@ public: static void onCommitPublicAccess(LLUICtrl* ctrl, void *userdata); static void onCommitAny(LLUICtrl* ctrl, void *userdata); static void onClickAddAccess(void*); - static void callbackAvatarCBAccess(const std::vector& names, const std::vector& ids, void* userdata); + void callbackAvatarCBAccess(const uuid_vec_t& ids); static void onClickRemoveAccess(void*); static void onClickAddBanned(void*); - static void callbackAvatarCBBanned(const std::vector& names, const std::vector& ids, void* userdata); + void callbackAvatarCBBanned(const uuid_vec_t& ids); static void onClickRemoveBanned(void*); virtual BOOL postBuild(); diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp index bd1186b15..832bf6b86 100644 --- a/indra/newview/llfloaterlandholdings.cpp +++ b/indra/newview/llfloaterlandholdings.cpp @@ -100,11 +100,12 @@ BOOL LLFloaterLandHoldings::postBuild() childSetAction("Teleport", onClickTeleport, this); childSetAction("Show on Map", onClickMap, this); - // Grant list - childSetDoubleClickCallback("grant list", onGrantList); - childSetUserData("grant list", this); + LLScrollListCtrl *grant_list = getChild("grant list"); - LLCtrlListInterface *list = childGetListInterface("grant list"); + // Grant list + grant_list->setDoubleClickCallback(boost::bind(&LLFloaterLandHoldings::onGrantList,this)); + + LLCtrlListInterface *list = grant_list->getListInterface(); if (!list) return TRUE; S32 count = gAgent.mGroups.count(); diff --git a/indra/newview/llfloatermessagelog.cpp b/indra/newview/llfloatermessagelog.cpp index ac1ecd99c..230a4b15a 100644 --- a/indra/newview/llfloatermessagelog.cpp +++ b/indra/newview/llfloatermessagelog.cpp @@ -636,18 +636,18 @@ void LLFloaterMessageLog::refreshNetList() { LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1); icon->setValue("icon_net_close_circuit.tga"); - icon->setClickCallback(onClickCloseCircuit, itemp); + icon->setClickCallback(boost::bind(&LLFloaterMessageLog::onClickCloseCircuit, itemp)); } else { LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1); icon->setValue("icon_net_close_circuit_gray.tga"); - icon->setClickCallback(NULL, NULL); + //icon->setClickCallback(NULL); } // Event queue isn't even supported yet... FIXME LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(2); icon->setValue("icon_net_close_eventpoll_gray.tga"); - icon->setClickCallback(NULL, NULL); + //icon->setClickCallback(NULL); } if(selected_id.notNull()) scrollp->selectByID(selected_id); if(scroll_pos < scrollp->getItemCount()) scrollp->setScrollPos(scroll_pos); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 89d34dea3..b85b1b3e5 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -455,7 +455,7 @@ BOOL LLFloaterModelPreview::postBuild() std::string validate_url; if (gHippoGridManager->getCurrentGrid()->isSecondLife()) { - if (LLViewerLogin::getInstance()->isInProductionGrid()) + if (gHippoGridManager->getConnectedGrid()->isInProductionGrid()) { validate_url = "http://secondlife.com/my/account/mesh.php"; } diff --git a/indra/newview/llfloatermute.cpp b/indra/newview/llfloatermute.cpp index 8e071dcde..624c244a4 100644 --- a/indra/newview/llfloatermute.cpp +++ b/indra/newview/llfloatermute.cpp @@ -43,18 +43,21 @@ // project include #include "llagent.h" +#include "llavatarnamecache.h" #include "llfloateravatarpicker.h" #include "llbutton.h" #include "lllineeditor.h" #include "llmutelist.h" +#include "llnamelistctrl.h" #include "llresizehandle.h" -#include "llscrolllistctrl.h" #include "lltextbox.h" #include "llviewertexteditor.h" #include "llviewerwindow.h" #include "lluictrlfactory.h" #include "llfocusmgr.h" +#include + // // Constants // @@ -208,7 +211,12 @@ BOOL LLFloaterMute::postBuild() childSetAction("Mute object by name...", onClickMuteByName, this); childSetAction("Unmute", onClickRemove, this); - mMuteList = getChild("mutes"); + mAvatarIcon = LLUI::getUIImage("icon_avatar_offline.tga"); + mObjectIcon = LLUI::getUIImage("inv_item_object.tga"); + mGroupIcon = LLUI::getUIImage("icon_group.tga"); + mNameIcon = LLUI::getUIImage("icon_name.tga"); + + mMuteList = getChild("mutes"); mMuteList->setCommitOnSelectionChange(TRUE); LLMuteList::getInstance()->addObserver(this); @@ -230,16 +238,63 @@ LLFloaterMute::~LLFloaterMute() //----------------------------------------------------------------------------- void LLFloaterMute::refreshMuteList() { + uuid_vec_t selected = mMuteList->getSelectedIDs(); + S32 scrollpos = mMuteList->getScrollPos(); + mMuteList->deleteAllItems(); + mMuteDict.clear(); std::vector mutes = LLMuteList::getInstance()->getMutes(); std::vector::iterator it; + U32 count = 0; for (it = mutes.begin(); it != mutes.end(); ++it) { - std::string display_name = it->getDisplayName(); - mMuteList->addStringUUIDItem(display_name, it->mID); - } + std::string display_name = it->mName; + LLSD element; + LLUUID entry_id; + if(it->mType == LLMute::GROUP || it->mType == LLMute::AGENT) + entry_id = it->mID; + else + entry_id.generate(boost::lexical_cast( count++ )); + mMuteDict.insert(std::make_pair(entry_id,*it)); + element["id"] = entry_id; + element["name"] = display_name; + LLSD& name_column = element["columns"][1]; + name_column["column"] = "name"; + name_column["type"] = "text"; + name_column["value"] = ""; + + LLSD& icon_column = element["columns"][0]; + icon_column["column"] = "icon"; + icon_column["type"] = "icon"; + + switch(it->mType) + { + case LLMute::GROUP: + icon_column["value"] = mGroupIcon->getName(); + element["target"] = LLNameListCtrl::GROUP; + break; + case LLMute::AGENT: + icon_column["value"] = mAvatarIcon->getName(); + element["target"] = LLNameListCtrl::INDIVIDUAL; + break; + case LLMute::OBJECT: + icon_column["value"] = mObjectIcon->getName(); + element["target"] = LLNameListCtrl::SPECIAL; + break; + case LLMute::BY_NAME: + default: + icon_column["value"] = mNameIcon->getName(); + element["target"] = LLNameListCtrl::SPECIAL; + + break; + } + mMuteList->addNameItemRow(element); + } + mMuteList->updateSort(); + mMuteList->selectMultiple(selected); + mMuteList->setScrollPos(scrollpos); updateButtons(); } @@ -281,17 +336,22 @@ void LLFloaterMute::onClickRemove(void *data) { LLFloaterMute* floater = (LLFloaterMute *)data; - std::string name = floater->mMuteList->getSelectedItemLabel(); - LLUUID id = floater->mMuteList->getStringUUIDSelectedItem(); - LLMute mute(id); - mute.setFromDisplayName(name); - // now mute.mName has the suffix trimmed off - S32 last_selected = floater->mMuteList->getFirstSelectedIndex(); - if (LLMuteList::getInstance()->remove(mute)) + bool removed = false; + const std::vector items = floater->mMuteList->getAllSelected(); + for(std::vector::const_iterator it = items.begin(); it != items.end(); ++it) + { + std::map::iterator mute_it = floater->mMuteDict.find((*it)->getUUID()); + if(mute_it != floater->mMuteDict.end() && LLMuteList::getInstance()->remove(mute_it->second)) + { + floater->mMuteDict.erase(mute_it); + removed = true; + } + } + + if (removed) { // Above removals may rebuild this dialog. - if (last_selected == floater->mMuteList->getItemCount()) { // we were on the last item, so select the last item again @@ -302,8 +362,12 @@ void LLFloaterMute::onClickRemove(void *data) // else select the item after the last item previously selected floater->mMuteList->selectNthItem(last_selected); } + floater->mMuteList->setNeedsSort(); + floater->mMuteList->updateSort(); + floater->updateButtons(); } - floater->updateButtons(); + + } //----------------------------------------------------------------------------- @@ -314,22 +378,20 @@ void LLFloaterMute::onClickPick(void *data) LLFloaterMute* floaterp = (LLFloaterMute*)data; const BOOL allow_multiple = FALSE; const BOOL close_on_select = TRUE; - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(onPickUser, data, allow_multiple, close_on_select); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterMute::onPickUser, floaterp, _1, _2), allow_multiple, close_on_select); floaterp->addDependentFloater(picker); } //----------------------------------------------------------------------------- // onPickUser() //----------------------------------------------------------------------------- -void LLFloaterMute::onPickUser(const std::vector& names, const std::vector& ids, void* user_data) +void LLFloaterMute::onPickUser(const uuid_vec_t& ids, const std::vector& names) { - LLFloaterMute* floaterp = (LLFloaterMute*)user_data; - if (!floaterp) return; if (names.empty() || ids.empty()) return; - LLMute mute(ids[0], names[0], LLMute::AGENT); + LLMute mute(ids[0], names[0].getLegacyName(), LLMute::AGENT); LLMuteList::getInstance()->add(mute); - floaterp->updateButtons(); + updateButtons(); } diff --git a/indra/newview/llfloatermute.h b/indra/newview/llfloatermute.h index 93f1bb2c1..8abb6afdf 100644 --- a/indra/newview/llfloatermute.h +++ b/indra/newview/llfloatermute.h @@ -37,11 +37,13 @@ #include "llmutelist.h" #include +class LLAvatarName; class LLButton; class LLLineEditor; class LLMessageSystem; class LLUUID; -class LLScrollListCtrl; +class LLNameListCtrl; +class LLMute; class LLFloaterMute : public LLFloater, public LLMuteListObserver, public LLFloaterSingleton @@ -68,12 +70,19 @@ private: static void onClickRemove(void *data); static void onClickPick(void *data); static void onSelectName(LLUICtrl* caller, void *data); - static void onPickUser(const std::vector& names, const std::vector& ids, void* user_data); + void onPickUser(const uuid_vec_t& ids, const std::vector& names); static void onClickMuteByName(void*); static void callbackMuteByName(const std::string& text, void*); private: - LLScrollListCtrl* mMuteList; + LLNameListCtrl* mMuteList; + + LLPointer mAvatarIcon; //icon_avatar_offline.tga + LLPointer mObjectIcon; //inv_item_object.tga + LLPointer mGroupIcon; //icon_group.tga + LLPointer mNameIcon; //icon_name.tga + + std::map mMuteDict; //Easiest way to associate listitems with LLMute instances without hacking in, say, a hidden column. }; diff --git a/indra/newview/llfloaternewim.cpp b/indra/newview/llfloaternewim.cpp index de1a306da..3acca6e38 100644 --- a/indra/newview/llfloaternewim.cpp +++ b/indra/newview/llfloaternewim.cpp @@ -60,8 +60,7 @@ BOOL LLFloaterNewIM::postBuild() mSelectionList = getChild("user_list"); if (mSelectionList) { - mSelectionList->setDoubleClickCallback(&LLFloaterNewIM::onStart); - mSelectionList->setCallbackUserData(this); + mSelectionList->setDoubleClickCallback(boost::bind(&LLFloaterNewIM::onStart,this)); } else { @@ -93,7 +92,7 @@ void LLFloaterNewIM::addSpecial(const LLUUID& uuid, const std::string& name, LLSD row; row["id"] = uuid; row["name"] = name; - row["target"] = "SPECIAL"; + row["target"] = LLNameListCtrl::SPECIAL; row["columns"][0]["value"] = name; row["columns"][0]["width"] = COL_1_WIDTH; row["columns"][0]["font"] = "SANSSERIF"; @@ -114,7 +113,7 @@ void LLFloaterNewIM::addGroup(const LLUUID& uuid, void* data, BOOL bold, BOOL on { LLSD row; row["id"] = uuid; - row["target"] = "GROUP"; + row["target"] = LLNameListCtrl::GROUP; row["columns"][0]["value"] = ""; // name will be looked up row["columns"][0]["width"] = COL_1_WIDTH; row["columns"][0]["font"] = "SANSSERIF"; @@ -133,12 +132,10 @@ void LLFloaterNewIM::addGroup(const LLUUID& uuid, void* data, BOOL bold, BOOL on void LLFloaterNewIM::addAgent(const LLUUID& uuid, void* data, BOOL online) { - std::string fullname; - gCacheName->getFullName(uuid, fullname); - LLSD row; row["id"] = uuid; - row["columns"][0]["value"] = fullname; + row["target"] = LLNameListCtrl::INDIVIDUAL; + row["columns"][0]["value"] = ""; row["columns"][0]["width"] = COL_1_WIDTH; row["columns"][0]["font"] = "SANSSERIF"; row["columns"][0]["font-style"] = online ? "BOLD" : "NORMAL"; diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index e6250063f..5d6b771d5 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -77,12 +77,10 @@ BOOL LLNotificationChannelPanel::postBuild() mChannelRejectsPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, false)); LLScrollListCtrl* scroll = getChild("notifications_list"); - scroll->setDoubleClickCallback(onClickNotification); - scroll->setCallbackUserData(this); + scroll->setDoubleClickCallback(boost::bind(&LLNotificationChannelPanel::onClickNotification,this)); scroll = getChild("notification_rejects_list"); - scroll->setDoubleClickCallback(onClickNotificationReject); - scroll->setCallbackUserData(this); + scroll->setDoubleClickCallback(boost::bind(&LLNotificationChannelPanel::onClickNotificationReject,this)); return TRUE; } diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index 6ff9d6695..132bc5d73 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -67,6 +67,7 @@ #include "llassetuploadresponders.h" #include "hippogridmanager.h" +#include "llfloatersnapshot.h" #if LL_MSVC #pragma warning( disable : 4265 ) // "class has virtual functions, but destructor is not virtual" @@ -84,13 +85,14 @@ LLFloaterPostcard::instance_list_t LLFloaterPostcard::sInstances; /// Class LLFloaterPostcard ///---------------------------------------------------------------------------- -LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global) +LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index) : LLFloater(std::string("Postcard Floater")), mJPEGImage(jpeg), mViewerImage(img), mImageScale(img_scale), mPosTakenGlobal(pos_taken_global), - mHasFirstMsgFocus(false) + mHasFirstMsgFocus(false), + mSnapshotIndex(index) { init(); } @@ -146,11 +148,11 @@ BOOL LLFloaterPostcard::postBuild() // static -LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global) +LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global, int index) { // Take the images from the caller // It's now our job to clean them up - LLFloaterPostcard *instance = new LLFloaterPostcard(jpeg, img, image_scale, pos_taken_global); + LLFloaterPostcard *instance = new LLFloaterPostcard(jpeg, img, image_scale, pos_taken_global, index); LLUICtrlFactory::getInstance()->buildFloater(instance, "floater_postcard.xml"); @@ -221,25 +223,47 @@ void LLFloaterPostcard::onClickCancel(void* data) if (data) { LLFloaterPostcard *self = (LLFloaterPostcard *)data; - + LLFloaterSnapshot::savePostcardDone(false, self->mSnapshotIndex); self->close(false); } } +void LLFloaterPostcard::onClose(bool app_quitting) +{ + LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex); + destroy(); +} + class LLSendPostcardResponder : public LLAssetUploadResponder { +private: + int mSnapshotIndex; + public: LLSendPostcardResponder(const LLSD &post_data, const LLUUID& vfile_id, - LLAssetType::EType asset_type): - LLAssetUploadResponder(post_data, vfile_id, asset_type) + LLAssetType::EType asset_type, + int index) : + LLAssetUploadResponder(post_data, vfile_id, asset_type), + mSnapshotIndex(index) { } // *TODO define custom uploadFailed here so it's not such a generic message - void uploadComplete(const LLSD& content) + /*virtual*/ void uploadComplete(const LLSD& content) { // we don't care about what the server returns from this post, just clean up the UI LLUploadDialog::modalUploadFinished(); + LLFloaterSnapshot::savePostcardDone(true, mSnapshotIndex); + } + /*virtual*/ void uploadFailure(const LLSD& content) + { + LLAssetUploadResponder::uploadFailure(content); + LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex); + } + /*virtual*/ void error(U32 statusNum, const std::string& reason) + { + LLAssetUploadResponder::error(statusNum, reason); + LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex); } }; @@ -292,6 +316,8 @@ void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data, LLUploadDialog::modalUploadFinished(); + LLFloaterSnapshot::savePostcardDone(!result, self->mSnapshotIndex); + if (result) { LLSD args; @@ -396,7 +422,7 @@ void LLFloaterPostcard::sendPostcard() body["name"] = childGetValue("name_form").asString(); body["subject"] = childGetValue("subject_form").asString(); body["msg"] = childGetValue("msg_form").asString(); - LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG)); + LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG, mSnapshotIndex)); } else { diff --git a/indra/newview/llfloaterpostcard.h b/indra/newview/llfloaterpostcard.h index e2ad154ef..e40479c17 100644 --- a/indra/newview/llfloaterpostcard.h +++ b/indra/newview/llfloaterpostcard.h @@ -50,14 +50,15 @@ class LLFloaterPostcard : public LLFloater { public: - LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global); - virtual ~LLFloaterPostcard(); + LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index); + /*virtual*/ ~LLFloaterPostcard(); - virtual void init(); - virtual BOOL postBuild(); - virtual void draw(); + /*virtual*/ void init(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + /*virtual*/ void onClose(bool app_quitting); - static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global); + static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index); static void onClickCancel(void* data); static void onClickSend(void* data); @@ -82,6 +83,7 @@ protected: LLVector2 mImageScale; LLVector3d mPosTakenGlobal; bool mHasFirstMsgFocus; + int mSnapshotIndex; typedef std::set instance_list_t; static instance_list_t sInstances; diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp index 3e279936f..0c8e7914e 100644 --- a/indra/newview/llfloaterproperties.cpp +++ b/indra/newview/llfloaterproperties.cpp @@ -537,11 +537,11 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) if (!is_link && is_obj_modify && can_agent_manipulate) { childSetEnabled("GroupLabel", true); - childSetEnabled("CheckGroupCopy",owner_mask & PERM_TRANSFER); + childSetEnabled("CheckGroupCopy", (owner_mask & (PERM_TRANSFER|PERM_COPY)) == (PERM_TRANSFER|PERM_COPY)); childSetEnabled("CheckGroupMod", owner_mask & PERM_MODIFY); childSetEnabled("CheckGroupMove", true); childSetEnabled("EveryoneLabel", true); - childSetEnabled("CheckEveryoneCopy",(owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER)); + childSetEnabled("CheckEveryoneCopy", (owner_mask & (PERM_TRANSFER|PERM_COPY)) == (PERM_TRANSFER|PERM_COPY)); childSetEnabled("CheckEveryoneMove",true); } else @@ -551,7 +551,7 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) childSetEnabled("CheckGroupMod", false); childSetEnabled("CheckGroupMove", false); childSetEnabled("EveryoneLabel", false); - childSetEnabled("CheckEveryoneCopy",FALSE); + childSetEnabled("CheckEveryoneCopy",false); childSetEnabled("CheckEveryoneMove",false); } diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 0a6b234f0..bc6dbbde0 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -258,7 +258,8 @@ void LLFloaterRegionInfo::requestRegionInfo() void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) { static LLDispatcher dispatch; - if(!findInstance()) + LLFloaterRegionInfo* floater = findInstance(); + if(!floater) { return; } @@ -268,7 +269,7 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) LLPanelEstateInfo::initDispatch(dispatch); } - LLTabContainer* tab = findInstance()->getChild("region_panels"); + LLTabContainer* tab = floater->getChild("region_panels"); LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild("Estate"); // unpack the message @@ -285,8 +286,7 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) //dispatch the message dispatch.dispatch(request, invoice, strings); - LLViewerRegion* region = gAgent.getRegion(); - panel->updateControls(region); + panel->updateControls(gAgent.getRegion()); } @@ -296,12 +296,18 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) LLPanel* panel; llinfos << "LLFloaterRegionInfo::processRegionInfo" << llendl; - if(!findInstance()) + LLFloaterRegionInfo* floater = findInstance(); + if(!floater) { return; } + // We need to re-request environment setting here, + // otherwise after we apply (send) updated region settings we won't get them back, + // so our environment won't be updated. + // This is also the way to know about externally changed region environment. + LLEnvManagerNew::instance().requestRegionSettings(); - LLTabContainer* tab = findInstance()->getChild("region_panels"); + LLTabContainer* tab = floater->getChild("region_panels"); LLViewerRegion* region = gAgent.getRegion(); BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); @@ -389,7 +395,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel->childSetEnabled("sun_hour_slider", allow_modify && !use_estate_sun); panel->setCtrlsEnabled(allow_modify); - getInstance()->refreshFromRegion( gAgent.getRegion() ); + floater->refreshFromRegion( gAgent.getRegion() ); } // static @@ -414,6 +420,11 @@ LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant() void LLFloaterRegionInfo::refreshFromRegion(LLViewerRegion* region) { + if (!region) + { + return; + } + // call refresh from region on all panels std::for_each( mInfoPanels.begin(), @@ -632,18 +643,18 @@ void LLPanelRegionGeneralInfo::onClickKick(void* userdata) // this depends on the grandparent view being a floater // in order to set up floater dependency LLFloater* parent_floater = gFloaterView->getParentFloater(panelp); - LLFloater* child_floater = LLFloaterAvatarPicker::show(onKickCommit, userdata, FALSE, TRUE); - parent_floater->addDependentFloater(child_floater); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, panelp, _1), FALSE, TRUE); + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } } -// static -void LLPanelRegionGeneralInfo::onKickCommit(const std::vector& names, const std::vector& ids, void* userdata) +void LLPanelRegionGeneralInfo::onKickCommit(const uuid_vec_t& ids) { - if (names.empty() || ids.empty()) return; + if (ids.empty()) return; if(ids[0].notNull()) { - LLPanelRegionGeneralInfo* self = (LLPanelRegionGeneralInfo*)userdata; - if(!self) return; strings_t strings; // [0] = our agent id // [1] = target agent id @@ -655,7 +666,7 @@ void LLPanelRegionGeneralInfo::onKickCommit(const std::vector& name strings.push_back(strings_t::value_type(buffer)); LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - self->sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings); + sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings); } } @@ -886,17 +897,15 @@ BOOL LLPanelRegionDebugInfo::sendUpdate() void LLPanelRegionDebugInfo::onClickChooseAvatar(void* data) { - LLFloaterAvatarPicker::show(callbackAvatarID, data, FALSE, TRUE); + LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, (LLPanelRegionDebugInfo*)data, _1, _2), FALSE, TRUE); } -// static -void LLPanelRegionDebugInfo::callbackAvatarID(const std::vector& names, const std::vector& ids, void* data) +void LLPanelRegionDebugInfo::callbackAvatarID(const uuid_vec_t& ids, const std::vector& names) { - LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*) data; if (ids.empty() || names.empty()) return; - self->mTargetAvatar = ids[0]; - self->childSetValue("target_avatar_name", LLSD(names[0])); - self->refreshFromRegion( gAgent.getRegion() ); + mTargetAvatar = ids[0]; + childSetValue("target_avatar_name", LLSD(names[0].getCompleteName())); + refreshFromRegion( gAgent.getRegion() ); } // static @@ -1615,35 +1624,35 @@ void LLPanelEstateInfo::onClickKickUser(void *user_data) // this depends on the grandparent view being a floater // in order to set up floater dependency LLFloater* parent_floater = gFloaterView->getParentFloater(panelp); - LLFloater* child_floater = LLFloaterAvatarPicker::show(LLPanelEstateInfo::onKickUserCommit, user_data, FALSE, TRUE); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, panelp, _1, _2), FALSE, TRUE); + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } parent_floater->addDependentFloater(child_floater); } -void LLPanelEstateInfo::onKickUserCommit(const std::vector& names, const std::vector& ids, void* userdata) +void LLPanelEstateInfo::onKickUserCommit(const uuid_vec_t& ids, const std::vector& names) { if (names.empty() || ids.empty()) return; //check to make sure there is one valid user and id - if( (ids[0].isNull()) || - (names[0].length() == 0) ) + if( ids[0].isNull() ) { return; } - LLPanelEstateInfo* self = (LLPanelEstateInfo*)userdata; - if(!self) return; - //keep track of what user they want to kick and other misc info LLKickFromEstateInfo *kick_info = new LLKickFromEstateInfo(); - kick_info->mEstatePanelp = self; + kick_info->mEstatePanelp = this; kick_info->mAgentID = ids[0]; //Bring up a confirmation dialog LLSD args; - args["EVIL_USER"] = names[0]; + args["EVIL_USER"] = names[0].getCompleteName(); LLSD payload; payload["agent_id"] = ids[0]; - LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, self, _1, _2)); + LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, this, _1, _2)); } @@ -1808,14 +1817,13 @@ bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& res LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]); // avatar picker yes multi-select, yes close-on-select - LLFloaterAvatarPicker::show(accessAddCore3, (void*)change_info, TRUE, TRUE); + LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, change_info), TRUE, TRUE); return false; } // static -void LLPanelEstateInfo::accessAddCore3(const std::vector& names, const std::vector& ids, void* data) +void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, LLEstateAccessChangeInfo* change_info) { - LLEstateAccessChangeInfo* change_info = (LLEstateAccessChangeInfo*)data; if (!change_info) return; if (ids.empty()) { @@ -2063,7 +2071,6 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region) BOOL owner = (region && (region->getOwner() == gAgent.getID())); BOOL manager = (region && region->isEstateManager()); setCtrlsEnabled(god || owner || manager); - childDisable("apply_btn"); childSetEnabled("add_allowed_avatar_btn", god || owner || manager); childSetEnabled("remove_allowed_avatar_btn", god || owner || manager); @@ -2313,13 +2320,20 @@ void LLPanelEstateInfo::getEstateOwner() class LLEstateChangeInfoResponder : public LLHTTPClient::ResponderWithResult { public: - LLEstateChangeInfoResponder(void* userdata) : mpPanel((LLPanelEstateInfo*)userdata) {}; + LLEstateChangeInfoResponder(LLPanelEstateInfo* panel) + { + mpPanel = panel->getHandle(); + } // if we get a normal response, handle it here virtual void result(const LLSD& content) { + LL_INFOS("Windlight") << "Successfully committed estate info" << llendl; + // refresh the panel from the database - mpPanel->refresh(); + LLPanelEstateInfo* panel = dynamic_cast(mpPanel.get()); + if (panel) + panel->refresh(); } // if we get an error response @@ -2332,7 +2346,7 @@ public: virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return estateChangeInfoResponder_timeout; } private: - LLPanelEstateInfo* mpPanel; + LLHandle mpPanel; }; // tries to send estate info using a cap; returns true if it succeeded @@ -2370,7 +2384,7 @@ bool LLPanelEstateInfo::commitEstateInfoCaps() body["owner_abuse_email"] = childGetValue("abuse_email_address").asString(); // we use a responder so that we can re-get the data after committing to the database - LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder((void*)this)); + LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder(this)); return true; } @@ -3200,7 +3214,8 @@ bool LLDispatchSetEstateAccess::operator()( if (allowed_agent_name_list) { - //allowed_agent_name_list->deleteAllItems(); + // Don't sort these as we add them, sort them when we are done. + allowed_agent_name_list->clearSortOrder(); for (S32 i = 0; i < num_allowed_agents && i < ESTATE_MAX_ACCESS_IDS; i++) { LLUUID id; @@ -3208,7 +3223,7 @@ bool LLDispatchSetEstateAccess::operator()( allowed_agent_name_list->addNameItem(id); } panel->childSetEnabled("remove_allowed_avatar_btn", allowed_agent_name_list->getFirstSelected() ? TRUE : FALSE); - allowed_agent_name_list->sortByColumnIndex(0, TRUE); + allowed_agent_name_list->sortByName(TRUE); } } @@ -3225,6 +3240,8 @@ bool LLDispatchSetEstateAccess::operator()( if (allowed_group_name_list) { + // Don't sort these as we add them, sort them when we are done. + allowed_group_name_list->clearSortOrder(); allowed_group_name_list->deleteAllItems(); for (S32 i = 0; i < num_allowed_groups && i < ESTATE_MAX_GROUP_IDS; i++) { @@ -3233,7 +3250,7 @@ bool LLDispatchSetEstateAccess::operator()( allowed_group_name_list->addGroupNameItem(id); } panel->childSetEnabled("remove_allowed_group_btn", allowed_group_name_list->getFirstSelected() ? TRUE : FALSE); - allowed_group_name_list->sortByColumnIndex(0, TRUE); + allowed_group_name_list->sortByName(TRUE); } } @@ -3257,7 +3274,9 @@ bool LLDispatchSetEstateAccess::operator()( if (banned_agent_name_list) { - //banned_agent_name_list->deleteAllItems(); + // Don't sort these as we add them, sort them when we are done. + banned_agent_name_list->clearSortOrder(); + for (S32 i = 0; i < num_banned_agents && i < ESTATE_MAX_ACCESS_IDS; i++) { LLUUID id; @@ -3265,7 +3284,7 @@ bool LLDispatchSetEstateAccess::operator()( banned_agent_name_list->addNameItem(id); } panel->childSetEnabled("remove_banned_avatar_btn", banned_agent_name_list->getFirstSelected() ? TRUE : FALSE); - banned_agent_name_list->sortByColumnIndex(0, TRUE); + banned_agent_name_list->sortByName(TRUE); } } @@ -3280,6 +3299,9 @@ bool LLDispatchSetEstateAccess::operator()( panel->getChild("estate_manager_name_list"); if (estate_manager_name_list) { + // Don't sort these as we add them, sort them when we are done. + estate_manager_name_list->clearSortOrder(); + estate_manager_name_list->deleteAllItems(); // Clear existing entries // There should be only ESTATE_MAX_MANAGERS people in the list, but if the database gets more (SL-46107) don't @@ -3292,7 +3314,7 @@ bool LLDispatchSetEstateAccess::operator()( estate_manager_name_list->addNameItem(id); } panel->childSetEnabled("remove_estate_manager_btn", estate_manager_name_list->getFirstSelected() ? TRUE : FALSE); - estate_manager_name_list->sortByColumnIndex(0, TRUE); + estate_manager_name_list->sortByName(TRUE); } } diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index c5ec3b7d6..8a3d77075 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -38,6 +38,8 @@ #include "llfloater.h" #include "llpanel.h" +class LLAvatarName; +struct LLEstateAccessChangeInfo; class LLLineEditor; class LLMessageSystem; class LLPanelRegionInfo; @@ -164,7 +166,7 @@ protected: virtual BOOL sendUpdate(); static void onClickKick(void* userdata); - static void onKickCommit(const std::vector& names, const std::vector& ids, void* userdata); + void onKickCommit(const uuid_vec_t& ids); static void onClickKickAll(void* userdata); bool onKickAllCommit(const LLSD& notification, const LLSD& response); static void onClickMessage(void* userdata); @@ -189,7 +191,7 @@ protected: virtual BOOL sendUpdate(); static void onClickChooseAvatar(void*); - static void callbackAvatarID(const std::vector& names, const std::vector& ids, void* data); + void callbackAvatarID(const uuid_vec_t& ids, const std::vector& names); static void onClickReturn(void *); bool callbackReturn(const LLSD& notification, const LLSD& response); static void onClickTopColliders(void*); @@ -282,7 +284,7 @@ public: // Core methods for all above add/remove button clicks static void accessAddCore(U32 operation_flag, const std::string& dialog_name); static bool accessAddCore2(const LLSD& notification, const LLSD& response); - static void accessAddCore3(const std::vector& names, const std::vector& ids, void* data); + static void accessAddCore3(const uuid_vec_t& ids, LLEstateAccessChangeInfo* change_info); static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name); static bool accessRemoveCore2(const LLSD& notification, const LLSD& response); @@ -294,7 +296,7 @@ public: // Send the actual EstateOwnerRequest "estateaccessdelta" message static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id); - static void onKickUserCommit(const std::vector& names, const std::vector& ids, void* userdata); + void onKickUserCommit(const uuid_vec_t& ids, const std::vector& names); static void onClickMessageEstate(void* data); bool onMessageCommit(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 9952eadd3..db29806ac 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -378,24 +378,21 @@ void LLFloaterReporter::onClickSelectAbuser(void *userdata) { LLFloaterReporter *self = (LLFloaterReporter *)userdata; - gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, userdata, FALSE, TRUE )); + gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, self, _1, _2), FALSE, TRUE )); } -// static -void LLFloaterReporter::callbackAvatarID(const std::vector& names, const std::vector& ids, void* data) +void LLFloaterReporter::callbackAvatarID(const uuid_vec_t& ids, const std::vector& names) { - LLFloaterReporter* self = (LLFloaterReporter*) data; - if (ids.empty() || names.empty()) return; // this should never be called in a bug report but here for safety. - if ( self->mReportType != BUG_REPORT ) + if ( mReportType != BUG_REPORT ) { - self->childSetText("abuser_name_edit", names[0] ); + childSetText("abuser_name_edit", names[0].getCompleteName() ); - self->mAbuserID = ids[0]; + mAbuserID = ids[0]; - self->refresh(); + refresh(); }; } @@ -901,7 +898,8 @@ void LLFloaterReporter::takeScreenshot() const S32 IMAGE_HEIGHT = 768; LLPointer raw = new LLImageRaw; - if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE, FALSE)) + // Warning: This crops left and right in case of wide-screen monitor: + if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, (F32)IMAGE_WIDTH / IMAGE_HEIGHT, TRUE, FALSE)) { llwarns << "Unable to take screenshot" << llendl; return; diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index 5f53142e4..e4d13e906 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -38,6 +38,7 @@ #include "lluuid.h" #include "v3math.h" +class LLAvatarName; class LLMessageSystem; class LLViewerTexture; class LLInventoryItem; @@ -126,7 +127,7 @@ private: void setPosBox(const LLVector3d &pos); void enableControls(BOOL own_avatar); void getObjectInfo(const LLUUID& object_id); - static void callbackAvatarID(const std::vector& names, const std::vector& ids, void* data); + void callbackAvatarID(const uuid_vec_t& ids, const std::vector& names); private: EReportType mReportType; diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index dfb82dada..1b50f3ead 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -33,6 +33,7 @@ #include "llfloatersellland.h" +#include "llavatarnamecache.h" #include "llfloateravatarpicker.h" #include "llfloater.h" #include "llfloaterland.h" @@ -88,7 +89,7 @@ private: static void doShowObjects(void *userdata); static bool callbackHighlightTransferable(const LLSD& notification, const LLSD& response); - static void callbackAvatarPick(const std::vector& names, const std::vector& ids, void* data); + void callbackAvatarPick(const uuid_vec_t& ids, const std::vector& names); public: virtual BOOL postBuild(); @@ -413,25 +414,23 @@ void LLFloaterSellLandUI::doSelectAgent(void *userdata) { LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)userdata; // grandparent is a floater, in order to set up dependency - floaterp->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarPick, floaterp, FALSE, TRUE)); + floaterp->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, floaterp, _1, _2), FALSE, TRUE)); } -// static -void LLFloaterSellLandUI::callbackAvatarPick(const std::vector& names, const std::vector& ids, void* data) +void LLFloaterSellLandUI::callbackAvatarPick(const uuid_vec_t& ids, const std::vector& names) { - LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)data; - LLParcel* parcel = floaterp->mParcelSelection->getParcel(); + LLParcel* parcel = mParcelSelection->getParcel(); if (names.empty() || ids.empty()) return; LLUUID id = ids[0]; parcel->setAuthorizedBuyerID(id); - floaterp->mAuthorizedBuyer = ids[0]; + mAuthorizedBuyer = ids[0]; - floaterp->childSetText("sell_to_agent", names[0]); + childSetText("sell_to_agent", names[0].getCompleteName()); - floaterp->refreshUI(); + refreshUI(); } // static diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 393dd78af..6dcf63a74 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -65,12 +65,14 @@ #include "llwindow.h" #include "llviewermenufile.h" // upload_new_resource() #include "llfloaterpostcard.h" +#include "llfloaterfeed.h" #include "llcheckboxctrl.h" #include "llradiogroup.h" #include "lltoolfocus.h" #include "lltoolmgr.h" #include "llworld.h" #include "llagentui.h" +#include "llvoavatar.h" #include "llgl.h" #include "llglheaders.h" @@ -87,9 +89,10 @@ ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- -S32 LLFloaterSnapshot::sUIWinHeightLong = 546 ; -S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 250 ; -S32 LLFloaterSnapshot::sUIWinWidth = 215 ; +S32 LLFloaterSnapshot::sUIWinHeightLong = 619 ; +S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 260 ; +S32 LLFloaterSnapshot::sUIWinWidth = 219 ; +S32 const THUMBHEIGHT = 159; LLSnapshotFloaterView* gSnapshotFloaterView = NULL; @@ -114,11 +117,31 @@ class LLSnapshotLivePreview : public LLView public: enum ESnapshotType { + SNAPSHOT_FEED, SNAPSHOT_POSTCARD, SNAPSHOT_TEXTURE, SNAPSHOT_LOCAL }; + enum EAspectSizeProblem + { + ASPECTSIZE_OK, + CANNOT_CROP_HORIZONTALLY, + CANNOT_CROP_VERTICALLY, + SIZE_TOO_LARGE, + CANNOT_RESIZE, + DELAYED, + NO_RAW_IMAGE, + ENCODING_FAILED + }; + + U32 typeToMask(ESnapshotType type) const { return 1 << type; } + void addUsedBy(ESnapshotType type) { mUsedBy |= typeToMask(type); } + void delUsedBy(ESnapshotType type) { mUsedBy &= ~typeToMask(type); } + bool isUsedBy(ESnapshotType type) const { return (mUsedBy & typeToMask(type)) != 0; } + bool isUsed(void) const { return mUsedBy; } + void addManualOverride(ESnapshotType type) { mManualSizeOverride |= typeToMask(type); } + bool isOverriddenBy(ESnapshotType type) const { return (mManualSizeOverride & typeToMask(type)) != 0; } LLSnapshotLivePreview(const LLRect& rect); ~LLSnapshotLivePreview(); @@ -128,123 +151,204 @@ public: void setSize(S32 w, S32 h); void getSize(S32& w, S32& h) const; - S32 getDataSize() const { return mDataSize; } + void setAspect(F32 a); + F32 getAspect() const; + void getRawSize(S32& w, S32& h) const; + S32 getDataSize() const { return mFormattedDataSize; } void setMaxImageSize(S32 size) ; S32 getMaxImageSize() {return mMaxImageSize ;} ESnapshotType getSnapshotType() const { return mSnapshotType; } LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; } - BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; } + BOOL getRawSnapshotUpToDate() const; + BOOL getSnapshotUpToDate() const; BOOL isSnapshotActive() { return mSnapshotActive; } LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; } S32 getThumbnailWidth() const { return mThumbnailWidth ; } S32 getThumbnailHeight() const { return mThumbnailHeight ; } BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; } BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;} + bool getShowFreezeFrameSnapshot() const { return mShowFreezeFrameSnapshot; } LLViewerTexture* getCurrentImage(); - F32 getImageAspect(); - F32 getAspect() ; - LLRect getImageRect(); - BOOL isImageScaled(); + char const* aspectComboName() const; void setSnapshotType(ESnapshotType type) { mSnapshotType = type; } void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } void setSnapshotQuality(S32 quality); - void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } + void setSnapshotBufferType(LLFloaterSnapshot* floater, LLViewerWindow::ESnapshotType type); + void showFreezeFrameSnapshot(bool show); void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); + LLFloaterFeed* getCaptionAndSaveFeed(); LLFloaterPostcard* savePostcard(); void saveTexture(); + void saveTextureDone(bool success, int index); + static void saveTextureDone(LLUUID const& asset_id, void* user_data, S32 status, LLExtStat ext_status); void saveLocal(); + void saveLocalDone(bool success, int index); + void saveFeedDone(bool success, int index); + void savePostcardDone(bool success, int index); + void close(LLFloaterSnapshot* view); + void doCloseAfterSave(); - BOOL setThumbnailImageSize() ; - void generateThumbnailImage(BOOL force_update = FALSE) ; - void resetThumbnailImage() { mThumbnailImage = NULL ; } + BOOL setThumbnailImageSize(); + void generateThumbnailImage(); + EAspectSizeProblem getAspectSizeProblem(S32& width_out, S32& height_out, bool& crop_vertically_out, S32& crop_offset_out); + EAspectSizeProblem generateFormattedAndFullscreenPreview(bool delayed_formatted = false); void drawPreviewRect(S32 offset_x, S32 offset_y) ; // Returns TRUE when snapshot generated, FALSE otherwise. - static BOOL onIdle( void* snapshot_preview ); + static BOOL onIdle(LLSnapshotLivePreview* previewp); private: LLColor4 mColor; - LLPointer mViewerImage[2]; //used to represent the scene when the frame is frozen. - LLRect mImageRect[2]; - S32 mWidth[2]; - S32 mHeight[2]; - BOOL mImageScaled[2]; - S32 mMaxImageSize ; + + LLPointer mFullScreenPreviewTexture; // Used to represent the scene when the frame is frozen. + LLRect mFullScreenImageRect; // The portion of the screen that is captured (the window size minus any cropping). + S32 mWidth; // The target image width. + S32 mHeight; // The target image height. + BOOL mFullScreenPreviewTextureNeedsScaling; // True when the actual data in mFullScreenPreviewTexture is smaller than its size. + + // Temporary data for the fall animation (same as the above). + LLPointer mFallFullScreenPreviewTexture; + LLRect mFallFullScreenImageRect; + S32 mFallWidth; + S32 mFallHeight; + BOOL mFallFullScreenPreviewTextureNeedsScaling; + + S32 mMaxImageSize; + F32 mAspectRatio; - //thumbnail image + // Thumbnail image. LLPointer mThumbnailImage ; + LLRect mThumbnailPreviewRect ; S32 mThumbnailWidth ; S32 mThumbnailHeight ; - LLRect mPreviewRect ; BOOL mThumbnailUpdateLock ; BOOL mThumbnailUpToDate ; - S32 mCurImageIndex; - LLPointer mPreviewImage; - LLPointer mPreviewImageEncoded; + // The last raw snapshot image. + LLPointer mRawSnapshot; + S32 mRawSnapshotWidth; + S32 mRawSnapshotHeight; + F32 mRawSnapshotAspectRatio; + BOOL mRawSnapshotRenderUI; + BOOL mRawSnapshotRenderHUD; + LLViewerWindow::ESnapshotType mRawSnapshotBufferType; + LLPointer mFormattedImage; + S32 mFormattedWidth; + S32 mFormattedHeight; + S32 mFormattedRawWidth; + S32 mFormattedRawHeight; + S32 mFormattedCropOffset; + bool mFormattedCropVertically; + LLFloaterSnapshot::ESnapshotFormat mFormattedSnapshotFormat; + S32 mFormattedSnapshotQuality; + bool mFormattedUpToDate; + LLFrameTimer mSnapshotDelayTimer; + U32 mUsedBy; + U32 mManualSizeOverride; S32 mShineCountdown; LLFrameTimer mShineAnimTimer; F32 mFlashAlpha; BOOL mNeedsFlash; LLVector3d mPosTakenGlobal; S32 mSnapshotQuality; - S32 mDataSize; + S32 mFormattedDataSize; ESnapshotType mSnapshotType; LLFloaterSnapshot::ESnapshotFormat mSnapshotFormat; - BOOL mSnapshotUpToDate; + BOOL mShowFreezeFrameSnapshot; LLFrameTimer mFallAnimTimer; LLVector3 mCameraPos; LLQuaternion mCameraRot; BOOL mSnapshotActive; LLViewerWindow::ESnapshotType mSnapshotBufferType; + bool mCallbackHappened; + bool mSaveSuccessful; + LLFloaterSnapshot* mCloseCalled; + int mSnapshotIndex; + public: static std::set sList; - BOOL mKeepAspectRatio ; + LLFrameTimer mFormattedDelayTimer; }; +void LLSnapshotLivePreview::setSnapshotBufferType(LLFloaterSnapshot* floater, LLViewerWindow::ESnapshotType type) +{ + mSnapshotBufferType = type; + switch(type) + { + case LLViewerWindow::SNAPSHOT_TYPE_COLOR: + floater->childSetValue("layer_types", "colors"); + break; + case LLViewerWindow::SNAPSHOT_TYPE_DEPTH: + floater->childSetValue("layer_types", "depth"); + break; + } +} + +BOOL LLSnapshotLivePreview::getRawSnapshotUpToDate() const +{ + return mRawSnapshotRenderUI == gSavedSettings.getBOOL("RenderUIInSnapshot") && + mRawSnapshotRenderHUD == gSavedSettings.getBOOL("RenderHUDInSnapshot") && + mRawSnapshotBufferType == mSnapshotBufferType; +} + +BOOL LLSnapshotLivePreview::getSnapshotUpToDate() const +{ + return mFormattedUpToDate && getRawSnapshotUpToDate(); +} + std::set LLSnapshotLivePreview::sList; + LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : LLView(std::string("snapshot_live_preview"), rect, FALSE), mColor(1.f, 0.f, 0.f, 0.5f), - mCurImageIndex(0), - mPreviewImage(NULL), + mRawSnapshot(NULL), + mRawSnapshotWidth(0), + mRawSnapshotHeight(0), + mRawSnapshotAspectRatio(1.0), + mRawSnapshotRenderUI(FALSE), + mRawSnapshotRenderHUD(FALSE), + mRawSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), mThumbnailImage(NULL) , mThumbnailWidth(0), mThumbnailHeight(0), - mPreviewImageEncoded(NULL), mFormattedImage(NULL), + mFormattedUpToDate(false), + mUsedBy(0), + mManualSizeOverride(0), mShineCountdown(0), mFlashAlpha(0.f), mNeedsFlash(TRUE), mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")), - mDataSize(0), - mSnapshotType(SNAPSHOT_POSTCARD), + mFormattedDataSize(0), + mSnapshotType(SNAPSHOT_FEED), mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))), - mSnapshotUpToDate(FALSE), + mShowFreezeFrameSnapshot(FALSE), mCameraPos(LLViewerCamera::getInstance()->getOrigin()), mCameraRot(LLViewerCamera::getInstance()->getQuaternion()), mSnapshotActive(FALSE), - mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR) + mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), + mCloseCalled(NULL), + mSnapshotIndex(0) { + DoutEntering(dc::notice, "LLSnapshotLivePreview() [" << (void*)this << "]"); setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); mSnapshotDelayTimer.start(); -// gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); sList.insert(this); setFollowsAll(); - mWidth[0] = gViewerWindow->getWindowDisplayWidth(); - mWidth[1] = gViewerWindow->getWindowDisplayWidth(); - mHeight[0] = gViewerWindow->getWindowDisplayHeight(); - mHeight[1] = gViewerWindow->getWindowDisplayHeight(); - mImageScaled[0] = FALSE; - mImageScaled[1] = FALSE; + mWidth = gViewerWindow->getWindowDisplayWidth(); + mHeight = gViewerWindow->getWindowDisplayHeight(); + mAspectRatio = (F32)mWidth / mHeight; + mFallWidth = mWidth; + mFallHeight = mHeight; + mFullScreenPreviewTextureNeedsScaling = FALSE; + mFallFullScreenPreviewTextureNeedsScaling = FALSE; mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ; - mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ; mThumbnailUpdateLock = FALSE ; mThumbnailUpToDate = FALSE ; updateSnapshot(TRUE,TRUE); //To initialize mImageRect to correct values @@ -252,12 +356,10 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : LLSnapshotLivePreview::~LLSnapshotLivePreview() { + DoutEntering(dc::notice, "~LLSnapshotLivePreview() [" << (void*)this << "]"); // delete images - mPreviewImage = NULL; - mPreviewImageEncoded = NULL; + mRawSnapshot = NULL; mFormattedImage = NULL; - -// gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); sList.erase(this); } @@ -275,78 +377,51 @@ void LLSnapshotLivePreview::setMaxImageSize(S32 size) LLViewerTexture* LLSnapshotLivePreview::getCurrentImage() { - return mViewerImage[mCurImageIndex]; + return mFullScreenPreviewTexture; } -F32 LLSnapshotLivePreview::getAspect() +void LLSnapshotLivePreview::showFreezeFrameSnapshot(bool show) { - F32 image_aspect_ratio = ((F32)mWidth[mCurImageIndex]) / ((F32)mHeight[mCurImageIndex]); - F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); - - if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) + DoutEntering(dc::notice, "LLSnapshotLivePreview::showFreezeFrameSnapshot(" << show << ")"); + // If we stop to show the fullscreen "freeze frame" snapshot, play the "fall away" animation. + if (mShowFreezeFrameSnapshot && !show) { - return image_aspect_ratio; + mFallFullScreenPreviewTexture = mFullScreenPreviewTexture; + mFallFullScreenPreviewTextureNeedsScaling = mFullScreenPreviewTextureNeedsScaling; + mFallFullScreenImageRect = mFullScreenImageRect; + mFallWidth = mFormattedWidth; + mFallHeight = mFormattedHeight; + mFallAnimTimer.start(); } - else - { - return window_aspect_ratio; - } -} - -F32 LLSnapshotLivePreview::getImageAspect() -{ - if (!mViewerImage[mCurImageIndex]) - { - return 0.f; - } - - return getAspect() ; -} - -LLRect LLSnapshotLivePreview::getImageRect() -{ - return mImageRect[mCurImageIndex]; -} - -BOOL LLSnapshotLivePreview::isImageScaled() -{ - return mImageScaled[mCurImageIndex]; + mShowFreezeFrameSnapshot = show; } void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) -{ - if (mSnapshotUpToDate) - { - S32 old_image_index = mCurImageIndex; - mCurImageIndex = (mCurImageIndex + 1) % 2; - mWidth[mCurImageIndex] = mWidth[old_image_index]; - mHeight[mCurImageIndex] = mHeight[old_image_index]; - mFallAnimTimer.start(); - } - mSnapshotUpToDate = FALSE; +{ + DoutEntering(dc::notice, "LLSnapshotLivePreview::updateSnapshot(" << new_snapshot << ", " << new_thumbnail << ", " << delay << ")"); - LLRect& rect = mImageRect[mCurImageIndex]; + LLRect& rect = mFullScreenImageRect; rect.set(0, getRect().getHeight(), getRect().getWidth(), 0); - F32 image_aspect_ratio = ((F32)mWidth[mCurImageIndex]) / ((F32)mHeight[mCurImageIndex]); - F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); + S32 window_width = gViewerWindow->getWindowWidthRaw() ; + S32 window_height = gViewerWindow->getWindowHeightRaw() ; + F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height); - if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) + if (mAspectRatio > window_aspect_ratio) { - if (image_aspect_ratio > window_aspect_ratio) - { - // trim off top and bottom - S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); - rect.mBottom += (getRect().getHeight() - new_height) / 2; - rect.mTop -= (getRect().getHeight() - new_height) / 2; - } - else if (image_aspect_ratio < window_aspect_ratio) - { - // trim off left and right - S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); - rect.mLeft += (getRect().getWidth() - new_width) / 2; - rect.mRight -= (getRect().getWidth() - new_width) / 2; - } + // trim off top and bottom + S32 height_diff = llround(getRect().getHeight() - (F32)getRect().getWidth() / mAspectRatio); + S32 half_height_diff = llround((getRect().getHeight() - (F32)getRect().getWidth() / mAspectRatio) * 0.5); + rect.mBottom += half_height_diff; + rect.mTop -= height_diff - half_height_diff; + } + else if (mAspectRatio < window_aspect_ratio) + { + // trim off left and right + S32 width_diff = llround(getRect().getWidth() - (F32)getRect().getHeight() * mAspectRatio); + S32 half_width_diff = llround((getRect().getWidth() - (F32)getRect().getHeight() * mAspectRatio) * 0.5f); + rect.mLeft += half_width_diff; + rect.mRight -= width_diff - half_width_diff; } mShineAnimTimer.stop(); @@ -373,63 +448,55 @@ void LLSnapshotLivePreview::setSnapshotQuality(S32 quality) void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) { - F32 line_width ; - glGetFloatv(GL_LINE_WIDTH, &line_width) ; - glLineWidth(2.0f * line_width) ; - LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ; - gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y, - mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ; - glLineWidth(line_width) ; - - //draw four alpha rectangles to cover areas outside of the snapshot image - if(!mKeepAspectRatio) + // Draw two alpha rectangles to cover areas outside of the snapshot image. + LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f); + if (mThumbnailWidth > mThumbnailPreviewRect.getWidth()) { - LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ; - S32 dwl = 0, dwr = 0 ; - if(mThumbnailWidth > mPreviewRect.getWidth()) - { - dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ; - dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ; - - gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y, - mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; - gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y, - mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ; - } - - if(mThumbnailHeight > mPreviewRect.getHeight()) - { - S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ; - gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y , - mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ; - - dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ; - gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh, - mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ; - } + gl_rect_2d( offset_x, offset_y, + mThumbnailPreviewRect.mLeft + offset_x, mThumbnailHeight + offset_y, + alpha_color, TRUE); + gl_rect_2d(mThumbnailPreviewRect.mRight + offset_x, offset_y, + mThumbnailWidth + offset_x, mThumbnailHeight + offset_y, + alpha_color, TRUE); } + if (mThumbnailHeight > mThumbnailPreviewRect.getHeight()) + { + gl_rect_2d( offset_x, offset_y, + mThumbnailWidth + offset_x, mThumbnailPreviewRect.mBottom + offset_y, + alpha_color, TRUE); + gl_rect_2d( offset_x, mThumbnailPreviewRect.mTop + offset_y, + mThumbnailWidth + offset_x, mThumbnailHeight + offset_y, + alpha_color, TRUE); + } + // Draw border around captured part. + F32 line_width; + glGetFloatv(GL_LINE_WIDTH, &line_width); + glLineWidth(2.0f * line_width); + gl_rect_2d( mThumbnailPreviewRect.mLeft + offset_x, mThumbnailPreviewRect.mTop + offset_y, + mThumbnailPreviewRect.mRight + offset_x, mThumbnailPreviewRect.mBottom + offset_y, + LLColor4::black, FALSE); + glLineWidth(line_width); } //called when the frame is frozen. void LLSnapshotLivePreview::draw() { - if (mViewerImage[mCurImageIndex].notNull() && - mPreviewImageEncoded.notNull() && - mSnapshotUpToDate) + if (mFullScreenPreviewTexture.notNull() && + mShowFreezeFrameSnapshot) { LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f); gl_rect_2d(getRect(), bg_color); - LLRect &rect = mImageRect[mCurImageIndex]; - LLRect shadow_rect = mImageRect[mCurImageIndex]; + LLRect const& rect = mFullScreenImageRect; + LLRect shadow_rect = mFullScreenImageRect; shadow_rect.stretch(BORDER_WIDTH); gl_drop_shadow(shadow_rect.mLeft, shadow_rect.mTop, shadow_rect.mRight, shadow_rect.mBottom, LLColor4(0.f, 0.f, 0.f, mNeedsFlash ? 0.f :0.5f), 10); LLColor4 image_color(1.f, 1.f, 1.f, 1.f); gGL.color4fv(image_color.mV); - gGL.getTexUnit(0)->bind(mViewerImage[mCurImageIndex]); + gGL.getTexUnit(0)->bind(mFullScreenPreviewTexture); // calculate UV scale - F32 uv_width = mImageScaled[mCurImageIndex] ? 1.f : llmin((F32)mWidth[mCurImageIndex] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f); - F32 uv_height = mImageScaled[mCurImageIndex] ? 1.f : llmin((F32)mHeight[mCurImageIndex] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f); + F32 uv_width = mFullScreenPreviewTextureNeedsScaling ? llmin((F32)mFormattedWidth / (F32)mFullScreenPreviewTexture->getWidth(), 1.f) : 1.f; + F32 uv_height = mFullScreenPreviewTextureNeedsScaling ? llmin((F32)mFormattedHeight / (F32)mFullScreenPreviewTexture->getHeight(), 1.f) : 1.f; gGL.pushMatrix(); { gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f); @@ -527,7 +594,7 @@ void LLSnapshotLivePreview::draw() { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f(1.f, 1.f, 1.f, 1.f); - LLRect outline_rect = mImageRect[mCurImageIndex]; + LLRect outline_rect = mFullScreenImageRect; gGL.begin(LLRender::QUADS); { gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH); @@ -556,22 +623,19 @@ void LLSnapshotLivePreview::draw() // draw old image dropping away if (mFallAnimTimer.getStarted()) { - S32 old_image_index = (mCurImageIndex + 1) % 2; - if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME) + if (mFallFullScreenPreviewTexture.notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME) { F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME; F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f); LLColor4 image_color(1.f, 1.f, 1.f, alpha); gGL.color4fv(image_color.mV); - gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]); + gGL.getTexUnit(0)->bind(mFallFullScreenPreviewTexture); // calculate UV scale - // *FIX get this to work with old image - BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull(); - F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f; - F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f; + F32 uv_width = mFallFullScreenPreviewTextureNeedsScaling ? llmin((F32)mFallWidth / (F32)mFallFullScreenPreviewTexture->getWidth(), 1.f) : 1.f; + F32 uv_height = mFallFullScreenPreviewTextureNeedsScaling ? llmin((F32)mFallHeight / (F32)mFallFullScreenPreviewTexture->getHeight(), 1.f) : 1.f; gGL.pushMatrix(); { - LLRect& rect = mImageRect[old_image_index]; + LLRect const& rect = mFallFullScreenImageRect; gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f); gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f); gGL.begin(LLRender::QUADS); @@ -608,7 +672,7 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare BOOL LLSnapshotLivePreview::setThumbnailImageSize() { - if(mWidth[mCurImageIndex] < 10 || mHeight[mCurImageIndex] < 10) + if(mWidth < 10 || mHeight < 10) { return FALSE ; } @@ -618,8 +682,8 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize() F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height); // UI size for thumbnail - S32 max_width = LLFloaterSnapshot::getUIWinWidth() - 20; - S32 max_height = 90; + S32 max_width = THUMBHEIGHT * 4 / 3; // == LLFloaterSnapshot::getUIWinWidth() - 7; + S32 max_height = THUMBHEIGHT; if (window_aspect_ratio > (F32)max_width / max_height) { @@ -640,49 +704,35 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize() } S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ; - if(!mKeepAspectRatio) + F32 ratio = mAspectRatio * window_height / window_width; + if(ratio > 1.f) { - F32 ratio_x = (F32)mWidth[mCurImageIndex] / window_width ; - F32 ratio_y = (F32)mHeight[mCurImageIndex] / window_height ; - - //if(mWidth[mCurImageIndex] > window_width || - // mHeight[mCurImageIndex] > window_height ) - { - if(ratio_x > ratio_y) - { - top = (S32)(top * ratio_y / ratio_x) ; - } - else - { - right = (S32)(right * ratio_x / ratio_y) ; - } - } - //else - //{ - // right = (S32)(right * ratio_x) ; - // top = (S32)(top * ratio_y) ; - //} - left = (S32)((mThumbnailWidth - right) * 0.5f) ; - bottom = (S32)((mThumbnailHeight - top) * 0.5f) ; - top += bottom ; - right += left ; + top = llround(top / ratio); } - mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ; + else + { + right = llround(right * ratio); + } + left = (mThumbnailWidth - right + 1) / 2; + bottom = (mThumbnailHeight - top + 1) / 2; + top += bottom ; + right += left ; + mThumbnailPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ; return TRUE ; } -void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) +void LLSnapshotLivePreview::generateThumbnailImage(void) { if(mThumbnailUpdateLock) //in the process of updating { return ; } - if(mThumbnailUpToDate && !force_update)//already updated + if(mThumbnailUpToDate) //already updated { return ; } - if(mWidth[mCurImageIndex] < 10 || mHeight[mCurImageIndex] < 10) + if(mWidth < 10 || mHeight < 10) { return ; } @@ -697,32 +747,30 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) return ; } - if(mThumbnailImage) - { - resetThumbnailImage() ; - } + Dout(dc::notice, "LLSnapshotLivePreview::generateThumbnailImage: Actually making a new thumbnail!"); + + mThumbnailImage = NULL; - LLPointer raw = NULL ; S32 w , h ; - w = get_lower_power_two(mThumbnailWidth, 512) * 2 ; - h = get_lower_power_two(mThumbnailHeight, 512) * 2 ; + // Set w, h to the nearest power of two that is larger or equal to mThumbnailWidth, mThumbnailHeight (but never more than 1024). + w = get_lower_power_two(mThumbnailWidth - 1, 512) * 2 ; // -1 so that w becomes mThumbnailWidth if it is a power of 2, instead of 2 * mThumbnailWidth. + h = get_lower_power_two(mThumbnailHeight - 1, 512) * 2 ; + LLPointer raw = new LLImageRaw ; + if(!gViewerWindow->thumbnailSnapshot(raw, + w, h, + gSavedSettings.getBOOL("RenderUIInSnapshot"), + FALSE, + mSnapshotBufferType) ) { - raw = new LLImageRaw ; - if(!gViewerWindow->thumbnailSnapshot(raw, - w, h, - gSavedSettings.getBOOL("RenderUIInSnapshot"), - FALSE, - mSnapshotBufferType) ) - { - raw = NULL ; - } + raw = NULL ; } if(raw) { mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); mThumbnailUpToDate = TRUE ; + Dout(dc::notice, "thumbnailSnapshot(" << w << ", " << h << ", ...) returns " << raw->getWidth() << ", " << raw->getHeight()); } //unlock updating @@ -733,10 +781,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) // Called often. Checks whether it's time to grab a new snapshot and if so, does it. // Returns TRUE if new snapshot generated, FALSE otherwise. //static -BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) +BOOL LLSnapshotLivePreview::onIdle(LLSnapshotLivePreview* previewp) { - LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview; - LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin(); LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion(); static const LLCachedControl freeze_time("FreezeTime",false); @@ -745,6 +791,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) { previewp->mCameraPos = new_camera_pos; previewp->mCameraRot = new_camera_rot; + previewp->showFreezeFrameSnapshot(false); // request a new snapshot whenever the camera moves, with a time delay BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot"); previewp->updateSnapshot( @@ -753,269 +800,707 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true. } - // see if it's time yet to snap the shot and bomb out otherwise. + // See if it's time yet to snap the shot and bomb out otherwise. previewp->mSnapshotActive = (previewp->mSnapshotDelayTimer.getStarted() && previewp->mSnapshotDelayTimer.hasExpired()) && !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active - if ( ! previewp->mSnapshotActive) + if (!previewp->mSnapshotActive) { + if (previewp->mFormattedDelayTimer.getStarted() && previewp->mFormattedDelayTimer.hasExpired()) + { + previewp->mFormattedDelayTimer.stop(); + LLFloaterSnapshot::updateControls(); + } return FALSE; } - // time to produce a snapshot + // Time to produce a snapshot. - if (!previewp->mPreviewImage) - { - previewp->mPreviewImage = new LLImageRaw; - } + // Reset Feed and Postcard Aspect to Default. + LLFloaterSnapshot::resetFeedAndPostcardAspect(); - if (!previewp->mPreviewImageEncoded) + if (!previewp->mRawSnapshot) { - previewp->mPreviewImageEncoded = new LLImageRaw; + previewp->mRawSnapshot = new LLImageRaw; } previewp->setVisible(FALSE); previewp->setEnabled(FALSE); previewp->getWindow()->incBusyCount(); - previewp->mImageScaled[previewp->mCurImageIndex] = FALSE; - // grab the raw image and encode it into desired format - if(gViewerWindow->rawSnapshot( - previewp->mPreviewImage, - previewp->mWidth[previewp->mCurImageIndex], - previewp->mHeight[previewp->mCurImageIndex], - previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"), - previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE, - gSavedSettings.getBOOL("RenderUIInSnapshot"), + // Grab the raw image and encode it into desired format. + Dout(dc::notice, "LLSnapshotLivePreview::onIdle: Actually making a new snapshot!"); + previewp->mSnapshotIndex++; + previewp->mFormattedImage = NULL; + previewp->mFormattedUpToDate = false; + previewp->mUsedBy = 0; // This snapshot wasn't used yet. + previewp->mManualSizeOverride = 0; + previewp->mThumbnailUpToDate = FALSE; + + // Remember with what parameters this snapshot was taken. + previewp->mRawSnapshotRenderUI = gSavedSettings.getBOOL("RenderUIInSnapshot"); + previewp->mRawSnapshotRenderHUD = gSavedSettings.getBOOL("RenderHUDInSnapshot"); + previewp->mRawSnapshotBufferType = previewp->mSnapshotBufferType; + previewp->mRawSnapshotAspectRatio = previewp->mAspectRatio; + // Mark that the those values do not represent the current snapshot (yet). + previewp->mRawSnapshotWidth = 0; + previewp->mRawSnapshotHeight = 0; + + if (gViewerWindow->rawRawSnapshot( + previewp->mRawSnapshot, + previewp->mWidth, + previewp->mHeight, + previewp->mRawSnapshotAspectRatio, + previewp->mRawSnapshotRenderUI, FALSE, - previewp->mSnapshotBufferType, + previewp->mRawSnapshotBufferType, previewp->getMaxImageSize())) { - previewp->mPreviewImageEncoded->resize( - previewp->mPreviewImage->getWidth(), - previewp->mPreviewImage->getHeight(), - previewp->mPreviewImage->getComponents()); + // On success, cache the size of the raw snapshot. + previewp->mRawSnapshotWidth = previewp->mRawSnapshot->getWidth(); + previewp->mRawSnapshotHeight = previewp->mRawSnapshot->getHeight(); + Dout(dc::notice, "Created a new raw snapshot of size " << previewp->mRawSnapshotWidth << "x" << previewp->mRawSnapshotHeight); - if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE) + previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); + EAspectSizeProblem ret = previewp->generateFormattedAndFullscreenPreview(); + // If the required size is too large, we might have to scale up one dimension... So that is ok. + // For example, if the target is 1000x1000 and the aspect is set to 8:1, then the required + // raw snapshot would be 8000x1000, but since 8000 is too large it would end up being only + // 6144x768 (since 6144 is the maximum) and we'll have to stretch the 768 to 1000. + llassert(previewp->mFormattedUpToDate || ret == SIZE_TOO_LARGE || ret == ENCODING_FAILED); + if (!previewp->mFormattedUpToDate && ret == SIZE_TOO_LARGE) { - LLPointer formatted = new LLImageJ2C; - LLPointer scaled = new LLImageRaw( - previewp->mPreviewImage->getData(), - previewp->mPreviewImage->getWidth(), - previewp->mPreviewImage->getHeight(), - previewp->mPreviewImage->getComponents()); - - scaled->biasedScaleToPowerOfTwo(512); - previewp->mImageScaled[previewp->mCurImageIndex] = TRUE; - if (formatted->encode(scaled, 0.f)) - { - previewp->mDataSize = formatted->getDataSize(); - formatted->decode(previewp->mPreviewImageEncoded, 0); - } - } - else - { - // delete any existing image - previewp->mFormattedImage = NULL; - // now create the new one of the appropriate format. - // note: postcards hardcoded to use jpeg always. - LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotType() == SNAPSHOT_POSTCARD - ? LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG : previewp->getSnapshotFormat(); - switch(format) - { - case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: - previewp->mFormattedImage = new LLImagePNG(); - break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: - previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality); - break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: - previewp->mFormattedImage = new LLImageBMP(); - break; - } - if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0)) - { - previewp->mDataSize = previewp->mFormattedImage->getDataSize(); - // special case BMP to copy instead of decode otherwise decode will crash. - if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP) - { - previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage); - } - else - { - previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0); - } - } + // ENCODING_FAILED was already reported. + LLNotificationsUtil::add("ErrorSizeAspectSnapshot"); } + } - LLPointer scaled = new LLImageRaw( - previewp->mPreviewImageEncoded->getData(), - previewp->mPreviewImageEncoded->getWidth(), - previewp->mPreviewImageEncoded->getHeight(), - previewp->mPreviewImageEncoded->getComponents()); - - if(!scaled->isBufferInvalid()) - { - // leave original image dimensions, just scale up texture buffer - if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024) - { - // go ahead and shrink image to appropriate power of 2 for display - scaled->biasedScaleToPowerOfTwo(1024); - previewp->mImageScaled[previewp->mCurImageIndex] = TRUE; - } - else - { - // expand image but keep original image data intact - scaled->expandToPowerOfTwo(1024, FALSE); - } - - previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); - LLPointer curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; - gGL.getTexUnit(0)->bind(curr_preview_image); - if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE) - { - curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT); - } - else - { - curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - } - curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); - - previewp->mSnapshotUpToDate = TRUE; - //Resize to thumbnail. - { - previewp->mThumbnailUpToDate = TRUE ; - previewp->mThumbnailUpdateLock = TRUE ; - S32 w = get_lower_power_two(scaled->getWidth(), 512) * 2 ; - S32 h = get_lower_power_two(scaled->getHeight(), 512) * 2 ; - scaled->scale(w,h); - previewp->mThumbnailImage = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); - previewp->mThumbnailUpdateLock = FALSE ; - previewp->setThumbnailImageSize(); - } - - previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); - previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame - } - } previewp->getWindow()->decBusyCount(); - // only show fullscreen preview when in freeze frame mode - previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame")); + + // Only show fullscreen preview when in freeze frame mode. + previewp->setVisible(gSavedSettings.getBOOL("FreezeTime")); previewp->mSnapshotDelayTimer.stop(); previewp->mSnapshotActive = FALSE; - - if(!previewp->getThumbnailUpToDate()) - { - previewp->generateThumbnailImage() ; - } + previewp->generateThumbnailImage(); return TRUE; } +LLSnapshotLivePreview::EAspectSizeProblem LLSnapshotLivePreview::getAspectSizeProblem(S32& width_out, S32& height_out, bool& crop_vertically_out, S32& crop_offset_out) +{ + S32 const window_width = gViewerWindow->getWindowWidthRaw(); + S32 const window_height = gViewerWindow->getWindowHeightRaw(); + + // We need an image with the aspect mAspectRatio (from which mWidth and mHeight were derived). + + // The current aspect ratio of mRawSnapshot is: + F32 const raw_aspect = (F32)mRawSnapshotWidth / mRawSnapshotHeight; + // The smaller dimension might have been rounded up to 0.5 up or down. Calculate upper and lower limits. + F32 lower_raw_aspect; + F32 upper_raw_aspect; + if (mRawSnapshotWidth < mRawSnapshotHeight) + { + lower_raw_aspect = (mRawSnapshotWidth - 0.5) / mRawSnapshotHeight; + upper_raw_aspect = (mRawSnapshotWidth + 0.5) / mRawSnapshotHeight; + } + else + { + lower_raw_aspect = mRawSnapshotWidth / (mRawSnapshotHeight + 0.5); + upper_raw_aspect = mRawSnapshotWidth / (mRawSnapshotHeight - 0.5); + } + // Find out if mRawSnapshot was cropped already. + bool const allow_vertical_crop = window_height * raw_aspect >= window_width; // mRawSnapshot was cropped horizontally. + bool const allow_horizontal_crop = window_width / raw_aspect >= window_height; // mRawSnapshot was cropped vertically. + crop_vertically_out = true; // Prefer this, as it is faster. + crop_offset_out = 0; // The number of columns or rows to cut off on the left or bottom. + // Construct a rectangle size w,h that fits inside mRawSnapshot but has the correct aspect. + width_out = mRawSnapshotWidth; + height_out = mRawSnapshotHeight; + if (mAspectRatio < lower_raw_aspect) + { + width_out = llround(width_out * mAspectRatio / raw_aspect); + if (width_out < mRawSnapshotWidth) + { + // Only set this to false when there is actually something to crop. + crop_vertically_out = false; + if (!allow_horizontal_crop) + { + Dout(dc::notice, "NOT up to date: required aspect " << mAspectRatio << + " is less than the (lower) raw aspect " << lower_raw_aspect << " which is already vertically cropped."); + return CANNOT_CROP_HORIZONTALLY; + } + crop_offset_out = (mRawSnapshotWidth - width_out) / 2; + } + } + else if (mAspectRatio > upper_raw_aspect) + { + height_out = llround(height_out * raw_aspect / mAspectRatio); + if (height_out < mRawSnapshotHeight) + { + if (!allow_vertical_crop) + { + Dout(dc::notice, "NOT up to date: required aspect " << mAspectRatio << + " is larger than the (upper) raw aspect " << upper_raw_aspect << " which is already horizontally cropped."); + return CANNOT_CROP_VERTICALLY; + } + crop_offset_out = (mRawSnapshotHeight - height_out) / 2; + } + } + // Never allow upscaling of the existing snapshot, of course. + if (mWidth > width_out || mHeight > height_out) + { + Dout(dc::notice, "NOT up to date: required target size " << mWidth << "x" << mHeight << + " is larger than (cropped) raw snapshot with size " << width_out << "x" << height_out << "!"); + return SIZE_TOO_LARGE; + } + // Do not allow any resizing for target images that are equal or larger than the current window, when the target is the harddisk. + // If the target size is smaller, than a resize would occur anyway, so in that case we allow resizing whatever we have, + // unless the aspect is different in which case we have to allow resizing in one direction. + if (mSnapshotType == SNAPSHOT_LOCAL && (mWidth >= window_width || mHeight >= window_height) && mWidth != width_out && mHeight != height_out) + { + Dout(dc::notice, "NOT up to date: required target size " << mWidth << "x" << mHeight << + " is larger or equal the window size (" << window_width << "x" << window_height << ")" + " but unequal the (cropped) raw snapshot size (" << width_out << "x" << height_out << ")" + " and target is disk!"); + return CANNOT_RESIZE; + } + return ASPECTSIZE_OK; +} + +LLSnapshotLivePreview::EAspectSizeProblem LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(bool delayed) +{ + DoutEntering(dc::notice, "LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(" << delayed << ")"); + mFormattedUpToDate = false; + + S32 w, h, crop_offset; + bool crop_vertically; + EAspectSizeProblem ret = getAspectSizeProblem(w, h, crop_vertically, crop_offset); + if (ret != ASPECTSIZE_OK) + { + // Current raw snapshot cannot be used. + return ret; + } + + // Determine the required format. + LLFloaterSnapshot::ESnapshotFormat format; + switch (mSnapshotType) + { + case SNAPSHOT_FEED: + // Feeds hardcoded to always use png. + format = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; + break; + case SNAPSHOT_POSTCARD: + // Postcards hardcoded to always use jpeg. + format = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; + break; + case SNAPSHOT_TEXTURE: + format = LLFloaterSnapshot::SNAPSHOT_FORMAT_J2C; + break; + case SNAPSHOT_LOCAL: + format = mSnapshotFormat; + break; + default: + format = mSnapshotFormat; + break; + } + + if (mFormattedImage && + mFormattedWidth == mWidth && + mFormattedHeight == mHeight && + mFormattedRawWidth == w && + mFormattedRawHeight == h && + mFormattedCropOffset == crop_offset && + mFormattedCropVertically == crop_vertically && + mFormattedSnapshotFormat == format && + (mFormattedSnapshotQuality == mSnapshotQuality || + format != LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG)) + { + Dout(dc::notice, "Already up to date."); + mFormattedUpToDate = true; + return ret; + } + +#ifdef CWDEBUG + if (!mFormattedImage) + { + Dout(dc::notice, "mFormattedImage == NULL!"); + } + else + { + if (mFormattedWidth != mWidth) + Dout(dc::notice, "Target width changed from " << mFormattedWidth << " to " << mWidth); + if (mFormattedHeight != mHeight) + Dout(dc::notice, "Target height changed from " << mFormattedHeight << " to " << mHeight); + if (mFormattedRawWidth != w) + Dout(dc::notice, "Cropped (raw) width changed from " << mFormattedRawWidth << " to " << w); + if (mFormattedRawHeight != h) + Dout(dc::notice, "Cropped (raw) height changed from " << mFormattedRawHeight << " to " << h); + if (mFormattedCropOffset != crop_offset) + Dout(dc::notice, "Crop offset changed from " << mFormattedCropOffset << " to " << crop_offset); + if (mFormattedCropVertically != crop_vertically) + Dout(dc::notice, "Crop direction changed from " << (mFormattedCropVertically ? "vertical" : "horizontal") << " to " << (crop_vertically ? "vertical" : "horizontal")); + if (mFormattedSnapshotFormat != format) + Dout(dc::notice, "Format changed from " << mFormattedSnapshotFormat << " to " << format); + if (!(mFormattedSnapshotQuality == mSnapshotQuality || format != LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG)) + Dout(dc::notice, "Format is JPEG and quality changed from " << mFormattedSnapshotQuality << " to " << mSnapshotQuality); + } +#endif + + if (delayed) + { + // Just set mFormattedUpToDate. + Dout(dc::notice, "NOT up to date, but delayed. Returning."); + return DELAYED; + } + + if (!mRawSnapshot) + { + Dout(dc::notice, "No raw snapshot exists."); + return NO_RAW_IMAGE; + } + + Dout(dc::notice, "Generating a new formatted image!"); + + mFormattedWidth = mWidth; + mFormattedHeight = mHeight; + mFormattedRawWidth = w; + mFormattedRawHeight = h; + mFormattedCropOffset = crop_offset; + mFormattedCropVertically = crop_vertically; + mFormattedSnapshotFormat = format; + mFormattedSnapshotQuality = mSnapshotQuality; + + // Served, so no need to call this again. + mFormattedDelayTimer.stop(); + + // A cropped copy of raw snapshot is put in 'scaled', which then is + // scaled to the target size (or a close power of two in the case + // of textures) and then encoded to 'formatted' of the same size. + LLPointer scaled = new LLImageRaw(mRawSnapshot, w, h, crop_offset, crop_vertically); + + // Subsequently, 'formatted' is decoded into 'decoded' again, + // to serve the full screen preview. + LLPointer decoded = new LLImageRaw; + + // Scale 'scaled' and allocate the correct image format. + if (mSnapshotType == SNAPSHOT_TEXTURE) + { + // 'scaled' must be a power of two. + scaled->biasedScaleToPowerOfTwo(mWidth, mHeight, 512); + } + else + { + // 'scaled' is just the target size. + scaled->scale(mWidth, mHeight); + } + + bool lossless = false; + switch(format) + { + case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: + mFormattedImage = new LLImagePNG; + lossless = true; + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: + mFormattedImage = new LLImageJPEG(mSnapshotQuality); + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: + mFormattedImage = new LLImageBMP; + lossless = true; + break; + case LLFloaterSnapshot::SNAPSHOT_FORMAT_J2C: + mFormattedImage = new LLImageJ2C; + break; + } + + // Encode the scaled snapshot into 'mFormatted' for save/upload. + if (mFormattedImage->encode(scaled, 0)) + { + mFormattedDataSize = mFormattedImage->getDataSize(); + if (!lossless) + { + // decoded must be pre-allocated. + decoded->resize( + mFormattedImage->getWidth(), + mFormattedImage->getHeight(), + mFormattedImage->getComponents()); + mFormattedImage->decode(decoded, 0); + } + } + else + { + // Mark formatted image size as unknown. + mFormattedDataSize = 0; + // Disable upload/save button. + mFormattedImage = NULL; + ret = ENCODING_FAILED; + LLNotificationsUtil::add("ErrorEncodingSnapshot"); + } + + // Generate mFullScreenPreviewTexture + + // Copy 'decoded' into 'scaled'. + if (!lossless) // Otherwise scaled is already "decoded". + { + scaled = NULL; // Free memory before allocating new image. + scaled = new LLImageRaw( + decoded->getData(), + decoded->getWidth(), + decoded->getHeight(), + decoded->getComponents()); + } + + // Generate mFullScreenPreviewTexture from 'scaled'. + if (!scaled->isBufferInvalid()) + { + // Leave original image dimensions, just scale up texture buffer. + if (scaled->getWidth() > 1024 || scaled->getHeight() > 1024) + { + // Go ahead and shrink image to appropriate power of two for display. + scaled->biasedScaleToPowerOfTwo(1024); + mFullScreenPreviewTextureNeedsScaling = FALSE; + } + else + { + // Expand image but keep original image data intact. + scaled->expandToPowerOfTwo(1024, FALSE); + mFullScreenPreviewTextureNeedsScaling = TRUE; + } + mFullScreenPreviewTexture = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); + LLPointer curr_preview_texture = mFullScreenPreviewTexture; + gGL.getTexUnit(0)->bind(curr_preview_texture); + if (mSnapshotType != SNAPSHOT_TEXTURE) + { + curr_preview_texture->setFilteringOption(LLTexUnit::TFO_POINT); + } + else + { + curr_preview_texture->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + } + curr_preview_texture->setAddressMode(LLTexUnit::TAM_CLAMP); + + showFreezeFrameSnapshot(TRUE); + + mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame + } + + // Return success if mFormattedImage was succesfully generated. + mFormattedUpToDate = mFormattedImage; + return ret; +} + void LLSnapshotLivePreview::setSize(S32 w, S32 h) { - mWidth[mCurImageIndex] = w; - mHeight[mCurImageIndex] = h; + mWidth = w; + mHeight = h; } void LLSnapshotLivePreview::getSize(S32& w, S32& h) const { - w = mWidth[mCurImageIndex]; - h = mHeight[mCurImageIndex]; + w = mWidth; + h = mHeight; +} + +void LLSnapshotLivePreview::setAspect(F32 a) +{ + mAspectRatio = a; +} + +F32 LLSnapshotLivePreview::getAspect() const +{ + return mAspectRatio; +} + +void LLSnapshotLivePreview::getRawSize(S32& w, S32& h) const +{ + w = mRawSnapshotWidth; + h = mRawSnapshotHeight; +} + +LLFloaterFeed* LLSnapshotLivePreview::getCaptionAndSaveFeed() +{ + if (mCloseCalled) + { + return NULL; + } + + mCallbackHappened = false; + mSaveSuccessful = false; + addUsedBy(SNAPSHOT_FEED); + + if (mFullScreenPreviewTexture.isNull()) + { + // This should never happen! + llwarns << "The snapshot image has not been generated!" << llendl; + saveFeedDone(false, mSnapshotIndex); + return NULL; + } + + // Calculate and pass in image scale in case image data only uses portion of viewerimage buffer. + F32 uv_width = mFullScreenPreviewTextureNeedsScaling ? llmin((F32)mFormattedWidth / (F32)mFullScreenPreviewTexture->getWidth(), 1.f) : 1.f; + F32 uv_height = mFullScreenPreviewTextureNeedsScaling ? llmin((F32)mFormattedHeight / (F32)mFullScreenPreviewTexture->getHeight(), 1.f) : 1.f; + LLVector2 image_scale(uv_width, uv_height); + + LLImagePNG* png = dynamic_cast(mFormattedImage.get()); + if (!png) + { + llwarns << "Formatted image not a PNG" << llendl; + saveFeedDone(false, mSnapshotIndex); + return NULL; + } + + LLFloaterFeed* floater = LLFloaterFeed::showFromSnapshot(png, mFullScreenPreviewTexture, image_scale, mSnapshotIndex); + + return floater; } LLFloaterPostcard* LLSnapshotLivePreview::savePostcard() { - if(mViewerImage[mCurImageIndex].isNull()) + if (mCloseCalled) + { + return NULL; + } + + mCallbackHappened = false; + mSaveSuccessful = false; + addUsedBy(SNAPSHOT_POSTCARD); + + if(mFullScreenPreviewTexture.isNull()) { //this should never happen!! llwarns << "The snapshot image has not been generated!" << llendl ; + savePostcardDone(false, mSnapshotIndex); return NULL ; } // calculate and pass in image scale in case image data only use portion // of viewerimage buffer - LLVector2 image_scale(1.f, 1.f); - if (!isImageScaled()) - { - image_scale.setVec(llmin(1.f, (F32)mWidth[mCurImageIndex] / (F32)getCurrentImage()->getWidth()), llmin(1.f, (F32)mHeight[mCurImageIndex] / (F32)getCurrentImage()->getHeight())); - } + // calculate UV scale + F32 uv_width = mFullScreenPreviewTextureNeedsScaling ? llmin((F32)mFormattedWidth / (F32)mFullScreenPreviewTexture->getWidth(), 1.f) : 1.f; + F32 uv_height = mFullScreenPreviewTextureNeedsScaling ? llmin((F32)mFormattedHeight / (F32)mFullScreenPreviewTexture->getHeight(), 1.f) : 1.f; + LLVector2 image_scale(uv_width, uv_height); LLImageJPEG* jpg = dynamic_cast(mFormattedImage.get()); if(!jpg) { llwarns << "Formatted image not a JPEG" << llendl; + savePostcardDone(false, mSnapshotIndex); return NULL; } - LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(jpg, mViewerImage[mCurImageIndex], image_scale, mPosTakenGlobal); - // relinquish lifetime of jpeg image to postcard floater - mFormattedImage = NULL; - mDataSize = 0; - updateSnapshot(FALSE, FALSE); + LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(jpg, mFullScreenPreviewTexture, image_scale, mPosTakenGlobal, mSnapshotIndex); return floater; } +class saveTextureUserData { +public: + saveTextureUserData(LLSnapshotLivePreview* self, int index) : mSelf(self), mSnapshotIndex(index) { } + LLSnapshotLivePreview* mSelf; + int mSnapshotIndex; +}; + void LLSnapshotLivePreview::saveTexture() { + if (mCloseCalled) + { + return; + } + + mCallbackHappened = false; + mSaveSuccessful = false; + addUsedBy(SNAPSHOT_TEXTURE); + // gen a new uuid for this asset LLTransactionID tid; tid.generate(); LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - - LLPointer formatted = new LLImageJ2C; - LLPointer scaled = new LLImageRaw(mPreviewImage->getData(), - mPreviewImage->getWidth(), - mPreviewImage->getHeight(), - mPreviewImage->getComponents()); - - scaled->biasedScaleToPowerOfTwo(512); - - if (formatted->encode(scaled, 0.0f)) - { - LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE); - std::string pos_string; - LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL); - std::string who_took_it; - LLAgentUI::buildFullname(who_took_it); - LLAssetStorage::LLStoreAssetCallback callback = NULL; - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - void *userdata = NULL; - upload_new_resource(tid, // tid - LLAssetType::AT_TEXTURE, - "Snapshot : " + pos_string, - "Taken by " + who_took_it + " at " + pos_string, - 0, - LLFolderType::FT_SNAPSHOT_CATEGORY, - LLInventoryType::IT_SNAPSHOT, - PERM_ALL, // Note: Snapshots to inventory is a special case of content upload - LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads - LLFloaterPerms::getEveryonePerms(), - "Snapshot : " + pos_string, - callback, expected_upload_cost, userdata); - gViewerWindow->playSnapshotAnimAndSound(); - } - else - { - LLNotificationsUtil::add("ErrorEncodingSnapshot"); - llwarns << "Error encoding snapshot" << llendl; - } + LLVFile::writeFile(mFormattedImage->getData(), mFormattedImage->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE); + std::string pos_string; + LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL); + std::string who_took_it; + LLAgentUI::buildFullname(who_took_it); + LLAssetStorage::LLStoreAssetCallback callback = &LLSnapshotLivePreview::saveTextureDone; + S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + upload_new_resource(tid, // tid + LLAssetType::AT_TEXTURE, + "Snapshot : " + pos_string, + "Taken by " + who_took_it + " at " + pos_string, + 0, + LLFolderType::FT_SNAPSHOT_CATEGORY, + LLInventoryType::IT_SNAPSHOT, + PERM_ALL, // Note: Snapshots to inventory is a special case of content upload + LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads + LLFloaterPerms::getEveryonePerms(), + "Snapshot : " + pos_string, + callback, expected_upload_cost, new saveTextureUserData(this, mSnapshotIndex)); + gViewerWindow->playSnapshotAnimAndSound(); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT ); - - mDataSize = 0; } void LLSnapshotLivePreview::saveLocal() { - gViewerWindow->saveImageNumbered(mFormattedImage); + if (mCloseCalled) + { + return; + } - // Relinquish image memory. Save button will be disabled as a side-effect. - mFormattedImage = NULL; - mDataSize = 0; - updateSnapshot(FALSE, FALSE); + mCallbackHappened = false; + mSaveSuccessful = false; + addUsedBy(SNAPSHOT_LOCAL); + + gViewerWindow->saveImageNumbered(mFormattedImage, mSnapshotIndex); // This calls saveLocalDone() immediately, or later. +} + +void LLSnapshotLivePreview::close(LLFloaterSnapshot* view) +{ + mCloseCalled = view; + if (mCallbackHappened) + { + doCloseAfterSave(); + } + else + { + view->setEnabled(FALSE); + } +} + +void LLSnapshotLivePreview::saveFeedDone(bool success, int index) +{ + if (mSnapshotIndex != index) + { + // The snapshot was already replaced, so this callback has nothing to do with us anymore. + if (!success) + { + llwarns << "Permanent failure to upload snapshot" << llendl; + } + return; + } + + mCallbackHappened = true; + mSaveSuccessful = success; + if (!success) + { + // Enable Upload button. + delUsedBy(SNAPSHOT_FEED); + LLFloaterSnapshot::updateControls(); + } + if (mCloseCalled) + { + doCloseAfterSave(); + } +} + +void LLSnapshotLivePreview::savePostcardDone(bool success, int index) +{ + if (mSnapshotIndex != index) + { + // The snapshot was already replaced, so this callback has nothing to do with us anymore. + if (!success) + { + llwarns << "Permanent failure to email snapshot" << llendl; + } + return; + } + + mCallbackHappened = true; + mSaveSuccessful = success; + if (!success) + { + // Enable Upload button. + delUsedBy(SNAPSHOT_POSTCARD); + LLFloaterSnapshot::updateControls(); + } + if (mCloseCalled) + { + doCloseAfterSave(); + } +} + +void LLSnapshotLivePreview::saveTextureDone(bool success, int index) +{ + if (mSnapshotIndex != index) + { + // The snapshot was already replaced, so this callback has nothing to do with us anymore. + if (!success) + { + llwarns << "Permanent failure to upload texture" << llendl; + } + return; + } + + mCallbackHappened = true; + mSaveSuccessful = success; + if (!success) + { + // Enable Upload button. + delUsedBy(LLSnapshotLivePreview::SNAPSHOT_TEXTURE); + LLFloaterSnapshot::updateControls(); + } + if (mCloseCalled) + { + doCloseAfterSave(); + } +} + +//static +void LLSnapshotLivePreview::saveTextureDone(LLUUID const& asset_id, void* user_data, S32 status, LLExtStat ext_status) +{ + bool success = status != LL_ERR_NOERR; + if (!success) + { + LLSD args; + args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); + LLNotificationsUtil::add("UploadSnapshotFail", args); + } + saveTextureUserData* data = (saveTextureUserData*)user_data; + data->mSelf->saveTextureDone(success, data->mSnapshotIndex); + delete data; +} + +void LLSnapshotLivePreview::saveLocalDone(bool success, int index) +{ + if (mSnapshotIndex != index) + { + // The snapshot was already replaced, so this callback has nothing to do with us anymore. + if (!success) + { + llwarns << "Permanent failure to save snapshot." << llendl; + } + return; + } + + mCallbackHappened = true; + mSaveSuccessful = success; + if (!success) + { + // Enable Save button. + delUsedBy(SNAPSHOT_LOCAL); + LLFloaterSnapshot::updateControls(); + } + if (mCloseCalled) + { + doCloseAfterSave(); + } +} + +void LLSnapshotLivePreview::doCloseAfterSave() +{ + if (mSaveSuccessful) + { + // Relinquish image memory. + mFormattedImage = NULL; + mFormattedUpToDate = false; + mFormattedDataSize = 0; + updateSnapshot(FALSE, FALSE); + mCloseCalled->close(); + } + else + { + mCloseCalled->setEnabled(TRUE); + mCloseCalled = NULL; + } } ///---------------------------------------------------------------------------- @@ -1034,60 +1519,64 @@ public: { //unpause avatars mAvatarPauseHandles.clear(); - + mQualityMouseUpConnection.disconnect(); } - static void onClickDiscard(void* data); static void onClickKeep(void* data); static void onCommitSave(LLUICtrl* ctrl, void* data); static void onClickNewSnapshot(void* data); + static void onClickFreezeTime(void* data); static void onClickAutoSnap(LLUICtrl *ctrl, void* data); + static void onClickTemporaryImage(LLUICtrl *ctrl, void* data); //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); static void onClickLess(void* data) ; static void onClickMore(void* data) ; static void onClickUICheck(LLUICtrl *ctrl, void* data); static void onClickHUDCheck(LLUICtrl *ctrl, void* data); static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data); - static void onClickKeepAspectCheck(LLUICtrl *ctrl, void* data); static void onCommitQuality(LLUICtrl* ctrl, void* data); - static void onCommitResolution(LLUICtrl* ctrl, void* data) { updateResolution(ctrl, data); } - static void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE); - static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data); + static void onCommitFeedResolution(LLUICtrl* ctrl, void* data); + static void onCommitPostcardResolution(LLUICtrl* ctrl, void* data); + static void onCommitTextureResolution(LLUICtrl* ctrl, void* data); + static void onCommitLocalResolution(LLUICtrl* ctrl, void* data); + static void onCommitFeedAspect(LLUICtrl* ctrl, void* data); + static void onCommitPostcardAspect(LLUICtrl* ctrl, void* data); + static void onCommitTextureAspect(LLUICtrl* ctrl, void* data); + static void onCommitLocalAspect(LLUICtrl* ctrl, void* data); + static void updateResolution(LLUICtrl* ctrl, void* data, bool update_controls = true); + static void updateAspect(LLUICtrl* ctrl, void* data, bool update_controls = true); + static void onCommitFreezeTime(LLUICtrl* ctrl, void* data); static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); static void onCommitSnapshotType(LLUICtrl* ctrl, void* data); static void onCommitSnapshotFormat(LLUICtrl* ctrl, void* data); static void onCommitCustomResolution(LLUICtrl *ctrl, void* data); - static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ; - static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); + static void onCommitCustomAspect(LLUICtrl *ctrl, void* data); + static void onQualityMouseUp(void* data); static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater); - static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname); - static void updateControls(LLFloaterSnapshot* floater); + static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool visible, bool update_controls = true); + static void setAspect(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls = true); + static void updateControls(LLFloaterSnapshot* floater, bool delayed_formatted = false); + static void resetFeedAndPostcardAspect(LLFloaterSnapshot* floater); static void updateLayout(LLFloaterSnapshot* floater); - static void updateResolutionTextEntry(LLFloaterSnapshot* floater); static LLHandle sPreviewHandle; - static BOOL sAspectRatioCheckOff ; private: static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater); static ESnapshotFormat getFormatIndex(LLFloaterSnapshot* floater); - static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater); static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname); static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE); - static void checkAspectRatio(LLFloaterSnapshot *view, S32 index) ; public: std::vector mAvatarPauseHandles; LLToolset* mLastToolset; + boost::signals2::connection mQualityMouseUpConnection; }; // static LLHandle LLFloaterSnapshot::Impl::sPreviewHandle; -//static -BOOL LLFloaterSnapshot::Impl::sAspectRatioCheckOff = FALSE ; - // static LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater) { @@ -1098,10 +1587,12 @@ LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot // static LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getTypeIndex(LLFloaterSnapshot* floater) { - LLSnapshotLivePreview::ESnapshotType index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; + LLSnapshotLivePreview::ESnapshotType index = LLSnapshotLivePreview::SNAPSHOT_FEED; LLSD value = floater->childGetValue("snapshot_type_radio"); const std::string id = value.asString(); - if (id == "postcard") + if (id == "feed") + index = LLSnapshotLivePreview::SNAPSHOT_FEED; + else if (id == "postcard") index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; else if (id == "texture") index = LLSnapshotLivePreview::SNAPSHOT_TEXTURE; @@ -1126,27 +1617,30 @@ LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getFormatIndex(LLFlo return index; } - - // static -LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater) +void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool visible, bool update_controls) { - LLViewerWindow::ESnapshotType type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; - LLSD value = floater->childGetValue("layer_types"); - const std::string id = value.asString(); - if (id == "colors") - type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; - else if (id == "depth") - type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH; - return type; + LLComboBox* combo = floater->getChild(comboname); + combo->setVisible(visible); + updateResolution(combo, floater, update_controls); // to sync spinners with combo } // static -void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname) +void LLFloaterSnapshot::Impl::setAspect(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls) { LLComboBox* combo = floater->getChild(comboname); - combo->setVisible(TRUE); - updateResolution(combo, floater, FALSE); // to sync spinners with combo + combo->setVisible(TRUE); + updateAspect(combo, floater, update_controls); // to sync spinner with combo +} + +//static +void LLFloaterSnapshot::Impl::resetFeedAndPostcardAspect(LLFloaterSnapshot* floaterp) +{ + floaterp->getChild("feed_aspect_combo")->setCurrentByIndex(0); // Default + gSavedSettings.setS32("SnapshotFeedLastAspect", 0); + + floaterp->getChild("postcard_aspect_combo")->setCurrentByIndex(0); // Default + gSavedSettings.setS32("SnapshotPostcardLastAspect", 0); } //static @@ -1158,24 +1652,28 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) if(!gSavedSettings.getBOOL("AdvanceSnapshot")) //set to original window resolution { - previewp->mKeepAspectRatio = TRUE; + floaterp->getChild("feed_size_combo")->setCurrentByIndex(2); // 500x375 + gSavedSettings.setS32("SnapshotFeedLastResolution", 2); - floaterp->getChild("postcard_size_combo")->setCurrentByIndex(0); + floaterp->getChild("postcard_size_combo")->setCurrentByIndex(0); // Current window gSavedSettings.setS32("SnapshotPostcardLastResolution", 0); - floaterp->getChild("texture_size_combo")->setCurrentByIndex(0); + resetFeedAndPostcardAspect(floaterp); + + floaterp->getChild("texture_size_combo")->setCurrentByIndex(0); // 512x512 (most likely result for current window). gSavedSettings.setS32("SnapshotTextureLastResolution", 0); + floaterp->getChild("texture_aspect_combo")->setCurrentByIndex(0); // Current window + gSavedSettings.setS32("SnapshotTextureLastAspect", 0); - floaterp->getChild("local_size_combo")->setCurrentByIndex(0); + floaterp->getChild("local_size_combo")->setCurrentByIndex(0); // Current window gSavedSettings.setS32("SnapshotLocalLastResolution", 0); + floaterp->getChild("local_aspect_combo")->setCurrentByIndex(0); // Current window + gSavedSettings.setS32("SnapshotLocalLastAspect", 0); - LLSnapshotLivePreview* previewp = getPreviewView(floaterp); - previewp->setSize(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); + updateControls(floaterp); } - bool use_freeze_frame = floaterp->childGetValue("freeze_frame_check").asBoolean(); - - if (use_freeze_frame) + if (gSavedSettings.getBOOL("UseFreezeTime")) { // stop all mouse events at fullscreen preview layer floaterp->getParent()->setMouseOpaque(TRUE); @@ -1190,16 +1688,14 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) previewp->setEnabled(TRUE); } - //RN: freeze all avatars - LLCharacter* avatarp; + // Freeze all avatars. for (std::vector::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) { - avatarp = *iter; - sInstance->impl.mAvatarPauseHandles.push_back(avatarp->requestPause()); + sInstance->impl.mAvatarPauseHandles.push_back((*iter)->requestPause()); } - // freeze everything else + // Freeze everything else. gSavedSettings.setBOOL("FreezeTime", TRUE); if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset) @@ -1218,12 +1714,18 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) previewp->setEnabled(FALSE); } - //RN: thaw all avatars - sInstance->impl.mAvatarPauseHandles.clear(); - - // thaw everything else + // Thaw everything except avatars. gSavedSettings.setBOOL("FreezeTime", FALSE); + // Thaw all avatars. + LLVOAvatar* avatarp; + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) + { + avatarp = static_cast(*iter); + avatarp->resetFreezeTime(); + } + sInstance->impl.mAvatarPauseHandles.clear(); + // restore last tool (e.g. pie menu, etc) if (sInstance->impl.mLastToolset) { @@ -1238,15 +1740,21 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) // The basic pattern for programmatically changing the GUI settings is to first set the // appropriate saved settings and then call this method to sync the GUI with them. // static -void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) +void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool delayed_formatted) { + DoutEntering(dc::notice, "LLFloaterSnapshot::Impl::updateControls()"); std::string fee = gHippoGridManager->getConnectedGrid()->getUploadFee(); + if (gSavedSettings.getBOOL("TemporaryUpload")) + { + fee = fee.substr(0, fee.find_first_of("0123456789")) + "0"; + } floater->childSetLabelArg("upload_btn", "[UPLOADFEE]", fee); - + + LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType"); LLRadioGroup* snapshot_type_radio = floater->getChild("snapshot_type_radio"); if (snapshot_type_radio) { - snapshot_type_radio->setSelectedIndex(gSavedSettings.getS32("LastSnapshotType")); + snapshot_type_radio->setSelectedIndex(shot_type); const child_list_t *childs = snapshot_type_radio->getChildList(); if (childs) @@ -1262,122 +1770,128 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) } } } - LLSnapshotLivePreview::ESnapshotType shot_type = getTypeIndex(floater); - ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); //getFormatIndex(floater); LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); - LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); + ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); + floater->childSetVisible("feed_size_combo", FALSE); + floater->childSetVisible("feed_aspect_combo", FALSE); floater->childSetVisible("postcard_size_combo", FALSE); + floater->childSetVisible("postcard_aspect_combo", FALSE); floater->childSetVisible("texture_size_combo", FALSE); + floater->childSetVisible("texture_aspect_combo", FALSE); floater->childSetVisible("local_size_combo", FALSE); + floater->childSetVisible("local_aspect_combo", FALSE); - floater->getChild("postcard_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution")); - floater->getChild("texture_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution")); - floater->getChild("local_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution")); - floater->getChild("local_format_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFormat")); + LLSnapshotLivePreview* previewp = getPreviewView(floater); + if (previewp) + { + previewp->setSnapshotType(shot_type); + LLViewerWindow::ESnapshotType layer_type = + (shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL) ? + (LLViewerWindow::ESnapshotType)gSavedSettings.getS32("SnapshotLayerType") : + LLViewerWindow::SNAPSHOT_TYPE_COLOR; + // Do this before calling setResolution(). + previewp->setSnapshotBufferType(floater, layer_type); + } + BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot"); + switch(shot_type) + { + case LLSnapshotLivePreview::SNAPSHOT_FEED: + setResolution(floater, "feed_size_combo", is_advance, false); + break; + case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: + setResolution(floater, "postcard_size_combo", is_advance, false); + break; + case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: + setResolution(floater, "texture_size_combo", is_advance, false); + break; + case LLSnapshotLivePreview::SNAPSHOT_LOCAL: + setResolution(floater, "local_size_combo", is_advance, false); + break; + } + floater->getChild("local_format_combo")->selectNthItem(shot_format); floater->childSetVisible("upload_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE); floater->childSetVisible("send_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD); + floater->childSetVisible("feed_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_FEED); floater->childSetVisible("save_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); - floater->childSetEnabled("keep_aspect_check", shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE && !sAspectRatioCheckOff); floater->childSetEnabled("layer_types", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); - BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot"); BOOL is_local = shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL; - BOOL show_slider = - shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD - || (is_local && shot_format == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + BOOL show_slider = + shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD || + (is_local && shot_format == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + floater->getChild(previewp->aspectComboName())->setVisible(is_advance); floater->childSetVisible("more_btn", !is_advance); // the only item hidden in advanced mode floater->childSetVisible("less_btn", is_advance); floater->childSetVisible("type_label2", is_advance); + floater->childSetVisible("type_label3", is_advance); floater->childSetVisible("format_label", is_advance && is_local); - floater->childSetVisible("local_format_combo", is_advance && is_local); + floater->childSetVisible("local_format_combo", is_local); floater->childSetVisible("layer_types", is_advance); floater->childSetVisible("layer_type_label", is_advance); + floater->childSetVisible("aspect_one_label", is_advance); floater->childSetVisible("snapshot_width", is_advance); floater->childSetVisible("snapshot_height", is_advance); - floater->childSetVisible("keep_aspect_check", is_advance); + floater->childSetVisible("aspect_ratio", is_advance); floater->childSetVisible("ui_check", is_advance); floater->childSetVisible("hud_check", is_advance); floater->childSetVisible("keep_open_check", is_advance); - floater->childSetVisible("freeze_frame_check", is_advance); + floater->childSetVisible("freeze_time_check", is_advance); floater->childSetVisible("auto_snapshot_check", is_advance); - floater->childSetVisible("image_quality_slider", is_advance && show_slider); + floater->childSetVisible("image_quality_slider", show_slider); floater->childSetVisible("temp_check", is_advance); - LLSnapshotLivePreview* previewp = getPreviewView(floater); BOOL got_bytes = previewp && previewp->getDataSize() > 0; - BOOL got_snap = previewp->getSnapshotUpToDate(); + BOOL is_texture = shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE; - floater->childSetEnabled("send_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD && got_snap && previewp->getDataSize() <= MAX_POSTCARD_DATASIZE); - floater->childSetEnabled("upload_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE && got_snap); - floater->childSetEnabled("save_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL && got_snap); + if (previewp) + { + previewp->setSnapshotFormat(shot_format); + if (previewp->getRawSnapshotUpToDate()) + { + if (delayed_formatted) + { + previewp->mFormattedDelayTimer.start(0.5); + } + previewp->generateFormattedAndFullscreenPreview(delayed_formatted); + } + else + { + previewp->mFormattedDelayTimer.stop(); + } + } LLLocale locale(LLLocale::USER_LOCALE); std::string bytes_string; - LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); + if (got_bytes) + { + LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); + } + else + { + bytes_string = floater->getString("unknown"); + } S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); floater->childSetLabelArg("texture", "[AMOUNT]", llformat("%d",upload_cost)); floater->childSetLabelArg("upload_btn", "[AMOUNT]", llformat("%d",upload_cost)); - floater->childSetTextArg("file_size_label", "[SIZE]", got_snap ? bytes_string : floater->getString("unknown")); + floater->childSetTextArg("file_size_label", "[SIZE]", bytes_string); floater->childSetColor("file_size_label", shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD && got_bytes && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLColor4::red : gColors.getColor( "LabelTextColor" )); - switch(shot_type) - { - case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: - layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; - floater->childSetValue("layer_types", "colors"); - if(is_advance) - { - setResolution(floater, "postcard_size_combo"); - } - break; - case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: - layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; - floater->childSetValue("layer_types", "colors"); - if(is_advance) - { - setResolution(floater, "texture_size_combo"); - } - break; - case LLSnapshotLivePreview::SNAPSHOT_LOCAL: - if(is_advance) - { - setResolution(floater, "local_size_combo"); - } - break; - default: - break; - } - - updateResolutionTextEntry(floater); + bool up_to_date = previewp && previewp->getSnapshotUpToDate(); + bool can_upload = up_to_date && !previewp->isUsedBy(shot_type); + floater->childSetEnabled("feed_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_FEED && can_upload); + floater->childSetEnabled("send_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD && can_upload && previewp->getDataSize() <= MAX_POSTCARD_DATASIZE); + floater->childSetEnabled("upload_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE && can_upload); + floater->childSetEnabled("save_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL && can_upload); + floater->childSetEnabled("temp_check", is_advance && is_texture); if (previewp) { - previewp->setSnapshotType(shot_type); - previewp->setSnapshotFormat(shot_format); - previewp->setSnapshotBufferType(layer_type); - } -} - -// static -void LLFloaterSnapshot::Impl::updateResolutionTextEntry(LLFloaterSnapshot* floater) -{ - LLSpinCtrl* width_spinner = floater->getChild("snapshot_width"); - LLSpinCtrl* height_spinner = floater->getChild("snapshot_height"); - - if(getTypeIndex(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) - { - width_spinner->setAllowEdit(FALSE); - height_spinner->setAllowEdit(FALSE); - } - else - { - width_spinner->setAllowEdit(TRUE); - height_spinner->setAllowEdit(TRUE); + previewp->showFreezeFrameSnapshot(up_to_date); } } @@ -1392,15 +1906,116 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, } // static -void LLFloaterSnapshot::Impl::onClickDiscard(void* data) +void LLFloaterSnapshot::Impl::onCommitFeedResolution(LLUICtrl* ctrl, void* data) { + LLComboBox* combobox = (LLComboBox*)ctrl; + gSavedSettings.setS32("SnapshotFeedLastResolution", combobox->getCurrentIndex()); LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (view) + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp && previewp->isUsed()) { - view->close(); + previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_FEED); } + updateResolution(ctrl, data); } +// static +void LLFloaterSnapshot::Impl::onCommitPostcardResolution(LLUICtrl* ctrl, void* data) +{ + LLComboBox* combobox = (LLComboBox*)ctrl; + gSavedSettings.setS32("SnapshotPostcardLastResolution", combobox->getCurrentIndex()); + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp && previewp->isUsed()) + { + previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_POSTCARD); + } + updateResolution(ctrl, data); +} + +// static +void LLFloaterSnapshot::Impl::onCommitTextureResolution(LLUICtrl* ctrl, void* data) +{ + LLComboBox* combobox = (LLComboBox*)ctrl; + gSavedSettings.setS32("SnapshotTextureLastResolution", combobox->getCurrentIndex()); + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp && previewp->isUsed()) + { + previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_TEXTURE); + } + updateResolution(ctrl, data); +} + +// static +void LLFloaterSnapshot::Impl::onCommitLocalResolution(LLUICtrl* ctrl, void* data) +{ + LLComboBox* combobox = (LLComboBox*)ctrl; + gSavedSettings.setS32("SnapshotLocalLastResolution", combobox->getCurrentIndex()); + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp && previewp->isUsed()) + { + previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_LOCAL); + } + updateResolution(ctrl, data); +} + +// static +void LLFloaterSnapshot::Impl::onCommitFeedAspect(LLUICtrl* ctrl, void* data) +{ + LLComboBox* combobox = (LLComboBox*)ctrl; + gSavedSettings.setS32("SnapshotFeedLastAspect", combobox->getCurrentIndex()); + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp && previewp->isUsed()) + { + previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_FEED); + } + updateAspect(ctrl, data); +} + +// static +void LLFloaterSnapshot::Impl::onCommitPostcardAspect(LLUICtrl* ctrl, void* data) +{ + LLComboBox* combobox = (LLComboBox*)ctrl; + gSavedSettings.setS32("SnapshotPostcardLastAspect", combobox->getCurrentIndex()); + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp && previewp->isUsed()) + { + previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_POSTCARD); + } + updateAspect(ctrl, data); +} + +// static +void LLFloaterSnapshot::Impl::onCommitTextureAspect(LLUICtrl* ctrl, void* data) +{ + LLComboBox* combobox = (LLComboBox*)ctrl; + gSavedSettings.setS32("SnapshotTextureLastAspect", combobox->getCurrentIndex()); + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp && previewp->isUsed()) + { + previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_TEXTURE); + } + updateAspect(ctrl, data); +} + +// static +void LLFloaterSnapshot::Impl::onCommitLocalAspect(LLUICtrl* ctrl, void* data) +{ + LLComboBox* combobox = (LLComboBox*)ctrl; + gSavedSettings.setS32("SnapshotLocalLastAspect", combobox->getCurrentIndex()); + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp && previewp->isUsed()) + { + previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_LOCAL); + } + updateAspect(ctrl, data); +} // static void LLFloaterSnapshot::Impl::onCommitSave(LLUICtrl* ctrl, void* data) @@ -1412,6 +2027,37 @@ void LLFloaterSnapshot::Impl::onCommitSave(LLUICtrl* ctrl, void* data) onClickKeep(data); } +// Called from LLViewerWindow::saveImageNumbered, LLViewerWindow::saveImageNumbered_continued1 and LLViewerWindow::saveImageNumbered_continued2. +//static +void LLFloaterSnapshot::saveLocalDone(bool success, int index) +{ + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(sInstance); + if (previewp) + { + previewp->saveLocalDone(success, index); + } +} + +//static +void LLFloaterSnapshot::saveFeedDone(bool success, int index) +{ + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(sInstance); + if (previewp) + { + previewp->saveFeedDone(success, index); + } +} + +//static +void LLFloaterSnapshot::savePostcardDone(bool success, int index) +{ + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(sInstance); + if (previewp) + { + previewp->savePostcardDone(success, index); + } +} + // static void LLFloaterSnapshot::Impl::onClickKeep(void* data) { @@ -1420,7 +2066,19 @@ void LLFloaterSnapshot::Impl::onClickKeep(void* data) if (previewp) { - if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD) + if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_FEED) + { + LLFloaterFeed* floater = previewp->getCaptionAndSaveFeed(); + // If still in snapshot mode, put feed floater in snapshot floaterview + // and link it to snapshot floater. + if (floater && !gSavedSettings.getBOOL("CloseSnapshotOnKeep")) + { + gFloaterView->removeChild(floater); + gSnapshotFloaterView->addChild(floater); + view->addDependentFloater(floater, FALSE); + } + } + else if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD) { LLFloaterPostcard* floater = previewp->savePostcard(); // if still in snapshot mode, put postcard floater in snapshot floaterview @@ -1443,7 +2101,7 @@ void LLFloaterSnapshot::Impl::onClickKeep(void* data) if (gSavedSettings.getBOOL("CloseSnapshotOnKeep")) { - view->close(); + previewp->close(view); } else { @@ -1457,14 +2115,26 @@ void LLFloaterSnapshot::Impl::onClickKeep(void* data) // static void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data) { - LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLFloaterSnapshot* view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); if (previewp && view) { previewp->updateSnapshot(TRUE); } } +// static +void LLFloaterSnapshot::Impl::onClickFreezeTime(void* data) +{ + LLFloaterSnapshot* view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp && view) + { + gSavedSettings.setBOOL("UseFreezeTime", TRUE); + updateLayout(view); + } +} + // static void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data) { @@ -1479,6 +2149,16 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data) } } +// static +void LLFloaterSnapshot::Impl::onClickTemporaryImage(LLUICtrl *ctrl, void* data) +{ + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + if (view) + { + updateControls(view); + } +} + void LLFloaterSnapshot::Impl::onClickMore(void* data) { gSavedSettings.setBOOL( "AdvanceSnapshot", TRUE ); @@ -1550,50 +2230,34 @@ void LLFloaterSnapshot::Impl::onClickKeepOpenCheck(LLUICtrl* ctrl, void* data) gSavedSettings.setBOOL( "CloseSnapshotOnKeep", !check->get() ); } -// static -void LLFloaterSnapshot::Impl::onClickKeepAspectCheck(LLUICtrl* ctrl, void* data) -{ - LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; - gSavedSettings.setBOOL( "KeepAspectForSnapshot", check->get() ); - - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (view) - { - LLSnapshotLivePreview* previewp = getPreviewView(view) ; - if(previewp) - { - previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ; - - S32 w, h ; - previewp->getSize(w, h) ; - if(checkImageSize(previewp, w, h, TRUE, previewp->getMaxImageSize())) - { - resetSnapshotSizeOnUI(view, w, h) ; - } - - previewp->setSize(w, h) ; - previewp->updateSnapshot(FALSE, TRUE); - checkAutoSnapshot(previewp, TRUE); - } - } -} - // static void LLFloaterSnapshot::Impl::onCommitQuality(LLUICtrl* ctrl, void* data) { LLSliderCtrl* slider = (LLSliderCtrl*)ctrl; S32 quality_val = llfloor((F32)slider->getValue().asReal()); - LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data); - if (previewp) + LLFloaterSnapshot* view = (LLFloaterSnapshot *)data; + if (view) { - previewp->setSnapshotQuality(quality_val); + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp) + { + previewp->setSnapshotQuality(quality_val); + checkAutoSnapshot(previewp, TRUE); + } } - checkAutoSnapshot(previewp, TRUE); +} + +//static +void LLFloaterSnapshot::Impl::onQualityMouseUp(void* data) +{ + Dout(dc::notice, "Calling LLFloaterSnapshot::Impl::QualityMouseUp()"); + LLFloaterSnapshot* view = (LLFloaterSnapshot *)data; + updateControls(view); } // static -void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data) +void LLFloaterSnapshot::Impl::onCommitFreezeTime(LLUICtrl* ctrl, void* data) { LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; @@ -1603,83 +2267,44 @@ void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data) return; } - gSavedSettings.setBOOL("UseFreezeFrame", check_box->get()); - - updateLayout(view); -} - -// static -void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 index) -{ - LLSnapshotLivePreview *previewp = getPreviewView(view) ; - - // Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here -#if 0 - if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getTypeIndex(view)) - { - previewp->mKeepAspectRatio = FALSE ; - return ; - } -#endif - - if(0 == index) //current window size - { - sAspectRatioCheckOff = TRUE ; - view->childSetEnabled("keep_aspect_check", FALSE) ; - - if(previewp) - { - previewp->mKeepAspectRatio = TRUE ; - } - } - else if(-1 == index) //custom - { - sAspectRatioCheckOff = FALSE ; - //if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE != gSavedSettings.getS32("LastSnapshotType")) - { - view->childSetEnabled("keep_aspect_check", TRUE) ; - - if(previewp) - { - previewp->mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ; - } - } - } - else - { - sAspectRatioCheckOff = TRUE ; - view->childSetEnabled("keep_aspect_check", FALSE) ; - - if(previewp) - { - previewp->mKeepAspectRatio = FALSE ; - } - } - - return ; + gSavedSettings.setBOOL("SnapshotOpenFreezeTime", check_box->get()); } static std::string lastSnapshotWidthName() { switch(gSavedSettings.getS32("LastSnapshotType")) { + case LLSnapshotLivePreview::SNAPSHOT_FEED: return "LastSnapshotToFeedWidth"; case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: return "LastSnapshotToEmailWidth"; case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: return "LastSnapshotToInventoryWidth"; default: return "LastSnapshotToDiskWidth"; } } + static std::string lastSnapshotHeightName() { switch(gSavedSettings.getS32("LastSnapshotType")) { + case LLSnapshotLivePreview::SNAPSHOT_FEED: return "LastSnapshotToFeedHeight"; case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: return "LastSnapshotToEmailHeight"; case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: return "LastSnapshotToInventoryHeight"; default: return "LastSnapshotToDiskHeight"; } } +static std::string lastSnapshotAspectName() +{ + switch(gSavedSettings.getS32("LastSnapshotType")) + { + case LLSnapshotLivePreview::SNAPSHOT_FEED: return "LastSnapshotToFeedAspect"; + case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: return "LastSnapshotToEmailAspect"; + case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: return "LastSnapshotToInventoryAspect"; + default: return "LastSnapshotToDiskAspect"; + } +} + // static -void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update) +void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool update_controls) { LLComboBox* combobox = (LLComboBox*)ctrl; LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; @@ -1689,10 +2314,192 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL return; } - // save off all selected resolution values - gSavedSettings.setS32("SnapshotPostcardLastResolution", view->getChild("postcard_size_combo")->getCurrentIndex()); - gSavedSettings.setS32("SnapshotTextureLastResolution", view->getChild("texture_size_combo")->getCurrentIndex()); - gSavedSettings.setS32("SnapshotLocalLastResolution", view->getChild("local_size_combo")->getCurrentIndex()); + S32 new_width = 0; + S32 new_height = 0; + F32 new_aspect = 0; + LLSnapshotLivePreview* previewp = getPreviewView(view); +#if 0 // Broken -- not doing this for now. + LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType"); + + // Is the snapshot was already used (saved or uploaded) and no manual changes + // have been made since to the current destination type, and the raw snapshot + // is still up to date with regard to visibility of UI, HUD and BufferType etc? + if (previewp && previewp->isUsed() && !previewp->isOverriddenBy(shot_type) && previewp->getRawSnapshotUpToDate()) + { + previewp->getSize(new_width, new_height); + new_aspect = previewp->getAspect(); + S32 const old_width = new_width; + S32 const old_height = new_height; + F32 const old_aspect = new_aspect; + S32 raw_width; + S32 raw_height; + previewp->getRawSize(raw_width, raw_height); + F32 const raw_aspect = (F32)raw_width / raw_height; + bool fixed_crop = false; + bool fixed_size = false; + bool fixed_scale = false; + bool done = false; + bool fail = false; + while (!done) + { + // Attempt to change the size and aspect so the raw snapshot can also be used for this new destination. + S32 w, h, crop_offset; + bool crop_vertically; + previewp->setSize(new_width, new_height); + previewp->setAspect(new_aspect); + LLSnapshotLivePreview::EAspectSizeProblem ret = previewp->getAspectSizeProblem(w, h, crop_vertically, crop_offset); + switch(ret) + { + case LLSnapshotLivePreview::ASPECTSIZE_OK: + done = true; // Don't change anything (else) if the current settings are usable. + break; + case LLSnapshotLivePreview::CANNOT_CROP_HORIZONTALLY: + case LLSnapshotLivePreview::CANNOT_CROP_VERTICALLY: + if (fixed_crop) + { + done = fail = true; + } + else + { + // Set target aspect to aspect of the raw snapshot we have (no reason to crop anything). + new_aspect = raw_aspect; + fixed_crop = true; + } + break; + case LLSnapshotLivePreview::SIZE_TOO_LARGE: + if (fixed_size) + { + done = fail = true; + } + else + { + if (new_width > w) + { + new_width = w; + new_height = llround(new_width / new_aspect); + } + if (new_height > h) + { + new_width = llmin(w, llround(h * new_aspect)); + new_height = llmin(h, llround(new_width / new_aspect)); + } + fixed_size = true; + } + break; + case LLSnapshotLivePreview::CANNOT_RESIZE: + if (fixed_scale) + { + done = fail = true; + } + else + { + F32 ratio = llmin((F32)w / new_width, (F32)h / new_height); + new_width = llround(new_width * ratio); + new_height = llround(new_height * ratio); + fixed_scale = true; + } + break; + } + } + previewp->setAspect(old_aspect); + previewp->setSize(old_width, old_height); + if (fail) + { + new_aspect = 0; + new_width = new_height = 0; + } + else + { + LLComboBox* size_combo_box = NULL; + LLComboBox* aspect_combo_box = NULL; + switch(shot_type) + { + case LLSnapshotLivePreview::SNAPSHOT_FEED: + size_combo_box = view->getChild("feed_size_combo"); + aspect_combo_box = view->getChild("feed_aspect_combo"); + break; + case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: + size_combo_box = view->getChild("postcard_size_combo"); + aspect_combo_box = view->getChild("postcard_aspect_combo"); + break; + case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: + size_combo_box = view->getChild("texture_size_combo"); + aspect_combo_box = view->getChild("texture_aspect_combo"); + break; + case LLSnapshotLivePreview::SNAPSHOT_LOCAL: + size_combo_box = view->getChild("local_size_combo"); + aspect_combo_box = view->getChild("local_aspect_combo"); + break; + } + S32 index = 0; + S32 const size_custom = size_combo_box->getItemCount() - (shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE ? 0 : 1); // Texture does not end on 'Custom'. + while (index < size_custom) + { + size_combo_box->setCurrentByIndex(index); + std::string sdstring = size_combo_box->getSelectedValue(); + LLSD sdres; + std::stringstream sstream(sdstring); + LLSDSerialize::fromNotation(sdres, sstream, sdstring.size()); + S32 width = sdres[0]; + S32 height = sdres[1]; + if (width == 0 || height == 0) + { + width = gViewerWindow->getWindowDisplayWidth(); + height = gViewerWindow->getWindowDisplayHeight(); + } + if (width == new_width && height == new_height) + { + break; + } + ++index; + } + if (index == size_custom && shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + { + size_combo_box->setCurrentByIndex(index); + } + index = 0; + S32 const aspect_custom = aspect_combo_box->getItemCount() - 1; + while (index < aspect_custom) + { + aspect_combo_box->setCurrentByIndex(index); + std::string sdstring = aspect_combo_box->getSelectedValue(); + std::stringstream sstream; + sstream << sdstring; + F32 aspect; + sstream >> aspect; + if (aspect == -2) // Default + { + aspect = (F32)new_width / new_height; + } + if (aspect == 0) // Current window + { + aspect = (F32)gViewerWindow->getWindowDisplayWidth() / gViewerWindow->getWindowDisplayHeight(); + } + if (llabs(aspect - new_aspect) < 0.0001) + { + break; + } + ++index; + } + if (index == aspect_custom) + { + aspect_combo_box->setCurrentByIndex(index); + setAspect(view, previewp->aspectComboName(), update_controls); + } + } + } + else +#endif + { + view->getChild("feed_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastResolution")); + view->getChild("feed_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastAspect")); + view->getChild("postcard_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution")); + view->getChild("postcard_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastAspect")); + view->getChild("texture_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution")); + view->getChild("texture_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastAspect")); + view->getChild("local_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution")); + view->getChild("local_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastAspect")); + } std::string sdstring = combobox->getSelectedValue(); LLSD sdres; @@ -1702,12 +2509,10 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL S32 width = sdres[0]; S32 height = sdres[1]; - LLSnapshotLivePreview* previewp = getPreviewView(view); if (previewp && combobox->getCurrentIndex() >= 0) { S32 original_width = 0 , original_height = 0 ; previewp->getSize(original_width, original_height) ; - if (width == 0 || height == 0 || gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) { // take resolution from current window size @@ -1715,8 +2520,15 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL } else if (width == -1 || height == -1) { - // load last custom value - previewp->setSize(gSavedSettings.getS32(lastSnapshotWidthName()), gSavedSettings.getS32(lastSnapshotHeightName())); + if (previewp->isUsed() && new_width != 0 && new_height != 0) + { + previewp->setSize(new_width, new_height); + } + else + { + // load last custom value + previewp->setSize(gSavedSettings.getS32(lastSnapshotWidthName()), gSavedSettings.getS32(lastSnapshotHeightName())); + } } else { @@ -1724,51 +2536,137 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL previewp->setSize(width, height); } - checkAspectRatio(view, width) ; - previewp->getSize(width, height); - if(checkImageSize(previewp, width, height, TRUE, previewp->getMaxImageSize())) - { - resetSnapshotSizeOnUI(view, width, height) ; - } - if(view->childGetValue("snapshot_width").asInteger() != width || view->childGetValue("snapshot_height").asInteger() != height) { view->childSetValue("snapshot_width", width); view->childSetValue("snapshot_height", height); } + } - if(original_width != width || original_height != height) + // Set whether or not the spinners can be changed. + + LLSpinCtrl* width_spinner = view->getChild("snapshot_width"); + LLSpinCtrl* height_spinner = view->getChild("snapshot_height"); + + if (gSavedSettings.getS32("LastSnapshotType") == LLSnapshotLivePreview::SNAPSHOT_TEXTURE || + gSavedSettings.getBOOL("RenderUIInSnapshot") || + gSavedSettings.getBOOL("RenderHUDInSnapshot")) + { + // Disable without making label gray. + width_spinner->setAllowEdit(FALSE); + width_spinner->setIncrement(0); + height_spinner->setAllowEdit(FALSE); + height_spinner->setIncrement(0); + } + else + { + width_spinner->setAllowEdit(TRUE); + width_spinner->setIncrement(32); + height_spinner->setAllowEdit(TRUE); + height_spinner->setIncrement(32); + } + + if (previewp) + { + if (new_aspect == 0) { - previewp->setSize(width, height); - - // hide old preview as the aspect ratio could be wrong - checkAutoSnapshot(previewp, FALSE); - getPreviewView(view)->updateSnapshot(FALSE, TRUE); - if(do_update) - { - updateControls(view); - } + // In case the aspect is 'Default', need to update aspect (which will call updateControls, if necessary). + setAspect(view, previewp->aspectComboName(), update_controls); } + else + { + LLSpinCtrl* aspect_spinner = view->getChild("aspect_ratio"); + aspect_spinner->set(new_aspect); + previewp->setAspect(new_aspect); + } + } +} + +// static +void LLFloaterSnapshot::Impl::updateAspect(LLUICtrl* ctrl, void* data, bool update_controls) +{ + LLComboBox* combobox = (LLComboBox*)ctrl; + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + + if (!view || !combobox) + { + return; + } + + LLSnapshotLivePreview* previewp = getPreviewView(view); + + view->getChild("feed_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastAspect")); + view->getChild("postcard_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastAspect")); + view->getChild("texture_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastAspect")); + view->getChild("local_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastAspect")); + + std::string sdstring = combobox->getSelectedValue(); + std::stringstream sstream; + sstream << sdstring; + F32 aspect; + sstream >> aspect; + + if (aspect == -2) // Default + { + S32 width, height; + previewp->getSize(width, height); + aspect = (F32)width / height; + } + else if (aspect == -1) // Custom + { + aspect = gSavedSettings.getF32(lastSnapshotAspectName()); + } + if (aspect == 0) // Current window + { + aspect = (F32)gViewerWindow->getWindowDisplayWidth() / gViewerWindow->getWindowDisplayHeight(); + } + + LLSpinCtrl* aspect_spinner = view->getChild("aspect_ratio"); + + // Set whether or not the spinners can be changed. + if (gSavedSettings.getBOOL("RenderUIInSnapshot") || + gSavedSettings.getBOOL("RenderHUDInSnapshot")) + { + aspect = (F32)gViewerWindow->getWindowDisplayWidth() / gViewerWindow->getWindowDisplayHeight(); + // Disable without making label gray. + aspect_spinner->setAllowEdit(FALSE); + aspect_spinner->setIncrement(0); + } + else + { + aspect_spinner->setAllowEdit(TRUE); + aspect_spinner->setIncrement(llmax(0.01f, lltrunc(aspect) / 100.0f)); + } + + // Sync the spinner and cache value. + aspect_spinner->set(aspect); + if (previewp) + { + F32 old_aspect = previewp->getAspect(); + previewp->setAspect(aspect); + if (old_aspect != aspect) + { + checkAutoSnapshot(previewp, TRUE); + } + } + if (update_controls) + { + // In case getSnapshotUpToDate() changed. + updateControls(view); } } // static void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data) { - LLComboBox* combobox = (LLComboBox*)ctrl; - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (view) { - LLSnapshotLivePreview* previewp = getPreviewView(view); - if (previewp) - { - previewp->setSnapshotBufferType((LLViewerWindow::ESnapshotType)combobox->getCurrentIndex()); - } - checkAutoSnapshot(previewp, TRUE); + LLComboBox* combobox = (LLComboBox*)ctrl; + gSavedSettings.setS32("SnapshotLayerType", combobox->getCurrentIndex()); + updateControls(view); } } @@ -1779,7 +2677,6 @@ void LLFloaterSnapshot::Impl::onCommitSnapshotType(LLUICtrl* ctrl, void* data) if (view) { gSavedSettings.setS32("LastSnapshotType", getTypeIndex(view)); - getPreviewView(view)->updateSnapshot(TRUE); updateControls(view); } } @@ -1792,7 +2689,6 @@ void LLFloaterSnapshot::Impl::onCommitSnapshotFormat(LLUICtrl* ctrl, void* data) if (view) { gSavedSettings.setS32("SnapshotFormat", getFormatIndex(view)); - getPreviewView(view)->updateSnapshot(TRUE); updateControls(view); } } @@ -1807,110 +2703,34 @@ void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const s combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index - if(comboname == "postcard_size_combo") + if(comboname == "feed_size_combo") + { + gSavedSettings.setS32("SnapshotFeedLastResolution", combo->getCurrentIndex()); + } + else if(comboname == "postcard_size_combo") { gSavedSettings.setS32("SnapshotPostcardLastResolution", combo->getCurrentIndex()); } - else if(comboname == "texture_size_combo") - { - gSavedSettings.setS32("SnapshotTextureLastResolution", combo->getCurrentIndex()); - } else if(comboname == "local_size_combo") { gSavedSettings.setS32("SnapshotLocalLastResolution", combo->getCurrentIndex()); } - - checkAspectRatio(floater, -1); // -1 means custom -} - - - -//static -BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value) -{ - S32 w = width ; - S32 h = height ; - - //if texture, ignore aspect ratio setting, round image size to power of 2. -#if 0 // Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here - if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == gSavedSettings.getS32("LastSnapshotType")) + else if(comboname == "feed_aspect_combo") { - if(width > max_value) - { - width = max_value ; - } - if(height > max_value) - { - height = max_value ; - } - - //round to nearest power of 2 based on the direction of movement - // i.e. higher power of two if increasing texture resolution - if(gSavedSettings.getS32("LastSnapshotToInventoryWidth") < width || - gSavedSettings.getS32("LastSnapshotToInventoryHeight") < height) - { - // Up arrow pressed - width = get_next_power_two(width, MAX_TEXTURE_SIZE) ; - height = get_next_power_two(height, MAX_TEXTURE_SIZE) ; - } - else - { - // Down or no change - width = get_lower_power_two(width, MAX_TEXTURE_SIZE) ; - height = get_lower_power_two(height, MAX_TEXTURE_SIZE) ; - } + gSavedSettings.setS32("SnapshotFeedLastAspect", combo->getCurrentIndex()); } - else -#endif - if(previewp && previewp->mKeepAspectRatio) + else if(comboname == "postcard_aspect_combo") { - if(gViewerWindow->getWindowDisplayWidth() < 1 || gViewerWindow->getWindowDisplayHeight() < 1) - { - return FALSE ; - } - - //aspect ratio of the current window - F32 aspect_ratio = (F32)gViewerWindow->getWindowDisplayWidth() / gViewerWindow->getWindowDisplayHeight() ; - - //change another value proportionally - if(isWidthChanged) - { - height = (S32)(width / aspect_ratio) ; - } - else - { - width = (S32)(height * aspect_ratio) ; - } - - //bound w/h by the max_value - if(width > max_value || height > max_value) - { - if(width > height) - { - width = max_value ; - height = (S32)(width / aspect_ratio) ; - } - else - { - height = max_value ; - width = (S32)(height * aspect_ratio) ; - } - } + gSavedSettings.setS32("SnapshotPostcardLastAspect", combo->getCurrentIndex()); } - else + else if(comboname == "texture_aspect_combo") { + gSavedSettings.setS32("SnapshotTextureLastAspect", combo->getCurrentIndex()); + } + else if(comboname == "local_aspect_combo") + { + gSavedSettings.setS32("SnapshotLocalLastAspect", combo->getCurrentIndex()); } - - return (w != width || h != height) ; -} - -//static -void LLFloaterSnapshot::Impl::resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) -{ - view->getChild("snapshot_width")->forceSetValue(width); - view->getChild("snapshot_height")->forceSetValue(height); - gSavedSettings.setS32(lastSnapshotWidthName(), width); - gSavedSettings.setS32(lastSnapshotHeightName(), height); } //static @@ -1919,8 +2739,8 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { - S32 w = llfloor((F32)view->childGetValue("snapshot_width").asReal()); - S32 h = llfloor((F32)view->childGetValue("snapshot_height").asReal()); + S32 w = llround(view->childGetValue("snapshot_width").asReal(), 1.0); + S32 h = llround(view->childGetValue("snapshot_height").asReal(), 1.0); LLSnapshotLivePreview* previewp = getPreviewView(view); if (previewp) @@ -1930,43 +2750,12 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat if (w != curw || h != curh) { - BOOL update_ = FALSE ; - //if to upload a snapshot, process spinner input in a special way. -#if 0 // Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here - if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == gSavedSettings.getS32("LastSnapshotType")) - { - S32 spinner_increment = (S32)((LLSpinCtrl*)ctrl)->getIncrement() ; - S32 dw = w - curw ; - S32 dh = h - curh ; - dw = (dw == spinner_increment) ? 1 : ((dw == -spinner_increment) ? -1 : 0) ; - dh = (dh == spinner_increment) ? 1 : ((dh == -spinner_increment) ? -1 : 0) ; - - if(dw) - { - w = (dw > 0) ? curw << dw : curw >> -dw ; - update_ = TRUE ; - } - if(dh) - { - h = (dh > 0) ? curh << dh : curh >> -dh ; - update_ = TRUE ; - } - } -#endif previewp->setMaxImageSize((S32)((LLSpinCtrl *)ctrl)->getMaxValue()) ; - - // Check image size changes the value of height and width - if(checkImageSize(previewp, w, h, w != curw, previewp->getMaxImageSize()) - || update_) - { - resetSnapshotSizeOnUI(view, w, h) ; - } - previewp->setSize(w,h); checkAutoSnapshot(previewp, FALSE); previewp->updateSnapshot(FALSE, TRUE); + comboSetCustom(view, "feed_size_combo"); comboSetCustom(view, "postcard_size_combo"); - comboSetCustom(view, "texture_size_combo"); comboSetCustom(view, "local_size_combo"); } } @@ -1974,7 +2763,58 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat gSavedSettings.setS32(lastSnapshotWidthName(), w); gSavedSettings.setS32(lastSnapshotHeightName(), h); - updateControls(view); + updateControls(view, true); + } +} + +char const* LLSnapshotLivePreview::aspectComboName() const +{ + char const* result; + switch(mSnapshotType) + { + case SNAPSHOT_FEED: + result = "feed_aspect_combo"; + break; + case SNAPSHOT_POSTCARD: + result = "postcard_aspect_combo"; + break; + case SNAPSHOT_TEXTURE: + result = "texture_aspect_combo"; + break; + case SNAPSHOT_LOCAL: + result = "local_aspect_combo"; + break; + default: + result= ""; + break; + } + return result; +} + +//static +void LLFloaterSnapshot::Impl::onCommitCustomAspect(LLUICtrl *ctrl, void* data) +{ + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + if (view) + { + F32 a = view->childGetValue("aspect_ratio").asReal(); + + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp) + { + F32 cura = previewp->getAspect(); + + if (a != cura) + { + previewp->setAspect(a); + previewp->updateSnapshot(FALSE, TRUE); + comboSetCustom(view, previewp->aspectComboName()); + } + } + + gSavedSettings.setF32(lastSnapshotAspectName(), a); + + updateControls(view, true); } } @@ -2017,21 +2857,25 @@ BOOL LLFloaterSnapshot::postBuild() childSetCommitCallback("local_format_combo", Impl::onCommitSnapshotFormat, this); childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this); + childSetAction("freeze_time_btn", Impl::onClickFreezeTime, this); childSetAction("more_btn", Impl::onClickMore, this); childSetAction("less_btn", Impl::onClickLess, this); childSetAction("upload_btn", Impl::onClickKeep, this); childSetAction("send_btn", Impl::onClickKeep, this); + childSetAction("feed_btn", Impl::onClickKeep, this); childSetCommitCallback("save_btn", Impl::onCommitSave, this); - childSetAction("discard_btn", Impl::onClickDiscard, this); childSetCommitCallback("image_quality_slider", Impl::onCommitQuality, this); childSetValue("image_quality_slider", gSavedSettings.getS32("SnapshotQuality")); + impl.mQualityMouseUpConnection = getChild("image_quality_slider")->setSliderMouseUpCallback(boost::bind(&Impl::onQualityMouseUp, this)); childSetCommitCallback("snapshot_width", Impl::onCommitCustomResolution, this); childSetCommitCallback("snapshot_height", Impl::onCommitCustomResolution, this); + childSetCommitCallback("aspect_ratio", Impl::onCommitCustomAspect, this); + childSetCommitCallback("ui_check", Impl::onClickUICheck, this); childSetValue("ui_check", gSavedSettings.getBOOL("RenderUIInSnapshot")); @@ -2041,9 +2885,6 @@ BOOL LLFloaterSnapshot::postBuild() childSetCommitCallback("keep_open_check", Impl::onClickKeepOpenCheck, this); childSetValue("keep_open_check", !gSavedSettings.getBOOL("CloseSnapshotOnKeep")); - childSetCommitCallback("keep_aspect_check", Impl::onClickKeepAspectCheck, this); - childSetValue("keep_aspect_check", gSavedSettings.getBOOL("KeepAspectForSnapshot")); - childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this); childSetValue("layer_types", "colors"); childSetEnabled("layer_types", FALSE); @@ -2051,15 +2892,22 @@ BOOL LLFloaterSnapshot::postBuild() childSetValue("snapshot_width", gSavedSettings.getS32(lastSnapshotWidthName())); childSetValue("snapshot_height", gSavedSettings.getS32(lastSnapshotHeightName())); - childSetValue("freeze_frame_check", gSavedSettings.getBOOL("UseFreezeFrame")); - childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this); + childSetValue("freeze_time_check", gSavedSettings.getBOOL("SnapshotOpenFreezeTime")); + childSetCommitCallback("freeze_time_check", Impl::onCommitFreezeTime, this); childSetValue("auto_snapshot_check", gSavedSettings.getBOOL("AutoSnapshot")); childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); + childSetCommitCallback("temp_check", Impl::onClickTemporaryImage, this); - childSetCommitCallback("postcard_size_combo", Impl::onCommitResolution, this); - childSetCommitCallback("texture_size_combo", Impl::onCommitResolution, this); - childSetCommitCallback("local_size_combo", Impl::onCommitResolution, this); + childSetCommitCallback("feed_size_combo", Impl::onCommitFeedResolution, this); + childSetCommitCallback("postcard_size_combo", Impl::onCommitPostcardResolution, this); + childSetCommitCallback("texture_size_combo", Impl::onCommitTextureResolution, this); + childSetCommitCallback("local_size_combo", Impl::onCommitLocalResolution, this); + + childSetCommitCallback("feed_aspect_combo", Impl::onCommitFeedAspect, this); + childSetCommitCallback("postcard_aspect_combo", Impl::onCommitPostcardAspect, this); + childSetCommitCallback("texture_aspect_combo", Impl::onCommitTextureAspect, this); + childSetCommitCallback("local_aspect_combo", Impl::onCommitLocalAspect, this); // create preview window LLRect full_screen_rect = sInstance->getRootView()->getRect(); @@ -2069,18 +2917,23 @@ BOOL LLFloaterSnapshot::postBuild() sInstance->getRootView()->addChild(previewp); sInstance->getRootView()->addChild(gSnapshotFloaterView); - // + gSavedSettings.setBOOL("UseFreezeTime", gSavedSettings.getBOOL("SnapshotOpenFreezeTime")); gSavedSettings.setBOOL("TemporaryUpload",FALSE); - childSetValue("temp_check",FALSE); - // + childSetValue("temp_check",FALSE); Impl::sPreviewHandle = previewp->getHandle(); impl.updateControls(this); - + return TRUE; } +LLRect LLFloaterSnapshot::getThumbnailAreaRect() +{ + // getRect() includes shadows and the title bar, therefore the real corners are as follows: + return LLRect(1, getRect().getHeight() - 17, getRect().getWidth() - 1, getRect().getHeight() - 17 - THUMBHEIGHT); +} + void LLFloaterSnapshot::draw() { LLSnapshotLivePreview* previewp = impl.getPreviewView(this); @@ -2097,10 +2950,13 @@ void LLFloaterSnapshot::draw() { if(previewp->getThumbnailImage()) { - S32 offset_x = (getRect().getWidth() - previewp->getThumbnailWidth()) / 2 ; - S32 offset_y = getRect().getHeight() - 205 + (90 - previewp->getThumbnailHeight()) / 2 ; + LLRect const thumb_area = getThumbnailAreaRect(); + // The offset needed to center the thumbnail is: center - thumbnailSize/2 = + S32 offset_x = (thumb_area.mLeft + thumb_area.mRight - previewp->getThumbnailWidth()) / 2; + S32 offset_y = (thumb_area.mBottom + thumb_area.mTop - previewp->getThumbnailHeight()) / 2; gGL.matrixMode(LLRender::MM_MODELVIEW); + gl_rect_2d(thumb_area, LLColor4::grey4, true); gl_draw_scaled_image(offset_x, offset_y, previewp->getThumbnailWidth(), previewp->getThumbnailHeight(), previewp->getThumbnailImage(), LLColor4::white); @@ -2121,6 +2977,8 @@ void LLFloaterSnapshot::onClose(bool app_quitting) // Set invisible so it doesn't eat tooltips. JC gSnapshotFloaterView->setVisible(FALSE); gSavedSettings.setBOOL("SnapshotBtnState", FALSE); + gSavedSettings.setBOOL("UseFreezeTime", FALSE); + impl.updateLayout(this); destroy(); } @@ -2137,14 +2995,6 @@ void LLFloaterSnapshot::show(void*) sInstance->impl.updateLayout(sInstance); } - else // just refresh the snapshot in the existing floater instance (DEV-12255) - { - LLSnapshotLivePreview* preview = LLFloaterSnapshot::Impl::getPreviewView(sInstance); - if(preview) - { - preview->updateSnapshot(TRUE); - } - } sInstance->open(); /* Flawfinder: ignore */ sInstance->focusFirstItem(FALSE); @@ -2176,6 +3026,83 @@ void LLFloaterSnapshot::update() } } +//static +void LLFloaterSnapshot::updateControls() +{ + Impl::updateControls(sInstance); +} + +//static +void LLFloaterSnapshot::resetFeedAndPostcardAspect() +{ + Impl::resetFeedAndPostcardAspect(sInstance); +} + +BOOL LLFloaterSnapshot::handleKeyHere(KEY key, MASK mask) +{ + static const LLCachedControl freeze_time("FreezeTime",false); + if (freeze_time && key == KEY_ESCAPE && mask == MASK_NONE) + { + // Ignore trying to defocus the snapshot floater in Freeze Time mode. + // However, if we're showing the fullscreen frozen preview, drop out of it; + // otherwise leave Freeze Time (so the next ESC press DOES defocus + // the floater and only the fourth will finally reset the cam). + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(this); + if (previewp && previewp->getShowFreezeFrameSnapshot()) + { + previewp->showFreezeFrameSnapshot(false); + } + else + { + gSavedSettings.setBOOL("UseFreezeTime", FALSE); + impl.updateLayout(this); + } + return TRUE; + } + else if (key == 'Q' && mask == MASK_CONTROL) + { + // Allow users to quit with ctrl-Q. + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(this); + if (previewp && previewp->getShowFreezeFrameSnapshot()) + { + previewp->showFreezeFrameSnapshot(false); + } + gSavedSettings.setBOOL("UseFreezeTime", FALSE); + impl.updateLayout(this); + gFocusMgr.removeKeyboardFocusWithoutCallback(gFocusMgr.getKeyboardFocus()); + return FALSE; + } + return LLFloater::handleKeyHere(key, mask); +} + +BOOL LLFloaterSnapshot::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if (mask == MASK_NONE) + { + LLRect thumb_area = getThumbnailAreaRect(); + if (thumb_area.pointInRect(x, y)) + { + return TRUE; + } + } + return LLFloater::handleMouseDown(x, y, mask); +} + +BOOL LLFloaterSnapshot::handleMouseUp(S32 x, S32 y, MASK mask) +{ + if (mask == MASK_NONE) + { + // In FreezeTime mode, show preview again (after user pressed ESC) when + // clicking on the thumbnail area. + LLRect thumb_area = getThumbnailAreaRect(); + if (thumb_area.pointInRect(x, y)) + { + impl.updateControls(this); + return TRUE; + } + } + return LLFloater::handleMouseUp(x, y, mask); +} ///---------------------------------------------------------------------------- /// Class LLSnapshotFloaterView diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 8fb51c945..a2ad6f385 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -47,16 +47,22 @@ public: { SNAPSHOT_FORMAT_PNG, SNAPSHOT_FORMAT_JPEG, - SNAPSHOT_FORMAT_BMP + SNAPSHOT_FORMAT_BMP, + SNAPSHOT_FORMAT_J2C } ESnapshotFormat; LLFloaterSnapshot(); virtual ~LLFloaterSnapshot(); + LLRect getThumbnailAreaRect(); + /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void onOpen(); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); static void show(void*); static void hide(void*); @@ -66,6 +72,13 @@ public: static S32 getUIWinHeightShort() {return sUIWinHeightShort ;} static S32 getUIWinWidth() {return sUIWinWidth ;} + static void saveLocalDone(bool success, int index); + static void saveFeedDone(bool success, int index); + static void savePostcardDone(bool success, int index); + + static void updateControls(); + static void resetFeedAndPostcardAspect(); + private: class Impl; Impl& impl; diff --git a/indra/newview/llfloaterteleporthistory.cpp b/indra/newview/llfloaterteleporthistory.cpp index 14ddd9541..6f3d06407 100644 --- a/indra/newview/llfloaterteleporthistory.cpp +++ b/indra/newview/llfloaterteleporthistory.cpp @@ -96,8 +96,8 @@ BOOL LLFloaterTeleportHistory::postBuild() } // setup callbacks for the scroll list - mPlacesList->setDoubleClickCallback(onTeleport); - childSetCommitCallback("places_list", onPlacesSelected, this); + mPlacesList->setDoubleClickCallback(boost::bind(&LLFloaterTeleportHistory::onTeleport,this)); + mPlacesList->setCommitCallback(boost::bind(&LLFloaterTeleportHistory::onPlacesSelected,_1,this)); childSetAction("teleport", onTeleport, this); childSetAction("show_on_map", onShowOnMap, this); childSetAction("copy_slurl", onCopySLURL, this); diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 1219176d6..f52b0960c 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -277,6 +277,8 @@ BOOL LLFloaterTools::postBuild() mComboGridMode = getChild("combobox grid mode"); childSetCommitCallback("combobox grid mode",commit_grid_mode, this); + mCheckShowHighlight = getChild("checkbox show highlight"); + mCheckActualRoot = getChild("checkbox actual root"); // // Create Buttons // @@ -382,6 +384,8 @@ LLFloaterTools::LLFloaterTools() mCheckStretchUniform(NULL), mCheckStretchTexture(NULL), mCheckLimitDrag(NULL), + mCheckShowHighlight(NULL), + mCheckActualRoot(NULL), mBtnRotateLeft(NULL), mBtnRotateReset(NULL), @@ -712,6 +716,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) if (mCheckStretchUniform) mCheckStretchUniform->setVisible( edit_visible ); if (mCheckStretchTexture) mCheckStretchTexture->setVisible( edit_visible ); if (mCheckLimitDrag) mCheckLimitDrag->setVisible( edit_visible ); + if (mCheckShowHighlight) mCheckShowHighlight->setVisible(edit_visible); + if (mCheckActualRoot) mCheckActualRoot->setVisible(edit_visible); // Create buttons BOOL create_visible = (tool == LLToolCompCreate::getInstance()); diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 085a2774e..90cdf83eb 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -143,6 +143,8 @@ public: LLCheckBoxCtrl* mCheckStretchUniform; LLCheckBoxCtrl* mCheckStretchTexture; LLCheckBoxCtrl* mCheckLimitDrag; + LLCheckBoxCtrl* mCheckShowHighlight; + LLCheckBoxCtrl* mCheckActualRoot; LLButton *mBtnRotateLeft; diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 8abbc2d26..e737b3d56 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -92,12 +92,13 @@ LLFloaterTopObjects::~LLFloaterTopObjects() // virtual BOOL LLFloaterTopObjects::postBuild() { - childSetCommitCallback("objects_list", onCommitObjectsList, this); - childSetDoubleClickCallback("objects_list", onDoubleClickObjectsList); - childSetFocus("objects_list"); + LLScrollListCtrl *objects_list = getChild("objects_list"); if (objects_list) { + objects_list->setCommitCallback(boost::bind(&LLFloaterTopObjects::onCommitObjectsList,_1,this)); + objects_list->setDoubleClickCallback(boost::bind(&LLFloaterTopObjects::onDoubleClickObjectsList,this)); + objects_list->setFocus(true); objects_list->setCommitOnSelectionChange(TRUE); } @@ -249,7 +250,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) if (total_count == 0 && list->getItemCount() == 0) { - list->addCommentText(getString("none_descriptor")); + list->setCommentText(getString("none_descriptor")); } else { diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index d541a93e5..0cd3906fb 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -70,6 +70,7 @@ #include "llviewerregion.h" #include "llviewerstats.h" #include "llworldmap.h" +#include "llworldmapmessage.h" #include "llworldmapview.h" #include "lluictrlfactory.h" #include "llappviewer.h" @@ -88,6 +89,21 @@ //--------------------------------------------------------------------------- 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; + +// It would be more logical to have this inside the method where it is used but to compile under gcc this +// struct has to be here. +struct SortRegionNames +{ + inline bool operator ()(std::pair const& _left, std::pair const& _right) + { + return(LLStringUtil::compareInsensitive(_left.second->getName(), _right.second->getName()) < 0); + } +}; enum EPanDirection { PAN_UP, @@ -97,17 +113,10 @@ enum EPanDirection }; // Values in pixels per region -static const F32 ZOOM_MIN = -8.f; // initial value, updated by adjustZoomSlider -static const F32 ZOOM_MAX = 0.f; -static const F32 ZOOM_INC = 0.2f; +static const F32 ZOOM_MAX = 128.f; -static const F32 SIM_COORD_MIN = 0.f; -static const F32 SIM_COORD_MAX = 255.f; static const F32 SIM_COORD_DEFAULT = 128.f; -static const F64 MAX_FLY_DISTANCE = 363.f; // Diagonal size of one sim. -static const F64 MAX_FLY_DISTANCE_SQUARED = MAX_FLY_DISTANCE * MAX_FLY_DISTANCE; - //--------------------------------------------------------------------------- // Globals //--------------------------------------------------------------------------- @@ -166,13 +175,16 @@ LLFloaterWorldMap::LLFloaterWorldMap() mInventory(NULL), mInventoryObserver(NULL), mFriendObserver(NULL), - mCompletingRegionName(""), + mCompletingRegionName(), + mCompletingRegionPos(), mWaitingForTracker(FALSE), - mExactMatch(FALSE), mIsClosing(FALSE), mSetToUserPosition(TRUE), mTrackedLocation(0,0,0), - mTrackedStatus(LLTracker::TRACKING_NOTHING) + mTrackedStatus(LLTracker::TRACKING_NOTHING), + mListFriendCombo(NULL), + mListLandmarkCombo(NULL), + mListSearchResults(NULL) { LLCallbackMap::map_t factory_map; factory_map["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL); @@ -197,54 +209,54 @@ BOOL LLFloaterWorldMap::postBuild() mPanel = getChild("objects_mapview"); - childSetCommitCallback("friend combo", onAvatarComboCommit, this); - LLComboBox *avatar_combo = getChild("friend combo"); - if (avatar_combo) - { - avatar_combo->selectFirstItem(); - avatar_combo->setPrearrangeCallback( onAvatarComboPrearrange ); - avatar_combo->setTextEntryCallback( onComboTextEntry ); - } - - childSetAction("DoSearch", onLocationCommit, this); - + avatar_combo->selectFirstItem(); + avatar_combo->setPrearrangeCallback( onAvatarComboPrearrange ); + avatar_combo->setTextEntryCallback( onComboTextEntry ); + mListFriendCombo = dynamic_cast(avatar_combo); + LLLineEditor *location_editor = getChild("location"); location_editor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1)); location_editor->setKeystrokeCallback( onSearchTextEntry ); - childSetCommitCallback("search_results", onCommitSearchResult, this); - childSetDoubleClickCallback("search_results", onClickTeleportBtn); - childSetCommitCallback("spin x", onCommitLocation, this); - childSetCommitCallback("spin y", onCommitLocation, this); - childSetCommitCallback("spin z", onCommitLocation, this); - - childSetCommitCallback("landmark combo", onLandmarkComboCommit, this); + LLScrollListCtrl* search_results = getChild("search_results"); + search_results->setDoubleClickCallback(boost::bind(&LLFloaterWorldMap::onClickTeleportBtn,this)); + mListSearchResults = dynamic_cast(search_results); LLComboBox *landmark_combo = getChild( "landmark combo"); - if (landmark_combo) - { - landmark_combo->selectFirstItem(); - landmark_combo->setPrearrangeCallback( onLandmarkComboPrearrange ); - landmark_combo->setTextEntryCallback( onComboTextEntry ); - } - childSetAction("Go Home", onGoHome, this); + landmark_combo->selectFirstItem(); + landmark_combo->setPrearrangeCallback( onLandmarkComboPrearrange ); + landmark_combo->setTextEntryCallback( onComboTextEntry ); + mListLandmarkCombo = dynamic_cast(landmark_combo); + + avatar_combo->setCommitCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboCommit,this) ); + + search_results->setCommitCallback( boost::bind(&LLFloaterWorldMap::onCommitSearchResult,this) ); + + landmark_combo->setCommitCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboCommit,this) ); + + getChild("spin x")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCoordinatesCommit,this) ); + getChild("spin y")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCoordinatesCommit,this) ); + getChild("spin z")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCoordinatesCommit,this) ); + + getChild("DoSearch")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onLocationCommit,this) ); + getChild("Go Home")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onGoHome,this) ); + getChild("Teleport")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onClickTeleportBtn,this) ); + getChild("Show Destination")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onShowTargetBtn,this) ); + getChild("Show My Location")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onShowAgentBtn,this) ); + getChild("Clear")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onClearBtn,this) ); + getChild("copy_slurl")->setCommitCallback(boost::bind(&LLFloaterWorldMap::onCopySLURL,this) ); - childSetAction("Teleport", onClickTeleportBtn, this); - - childSetAction("Show Destination", onShowTargetBtn, this); - childSetAction("Show My Location", onShowAgentBtn, this); - childSetAction("Clear", onClearBtn, this); - childSetAction("copy_slurl", onCopySLURL, this); - - mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f); - childSetValue("zoom slider", LLWorldMapView::sMapScale); + mCurZoomVal = log(LLWorldMapView::sMapScale/256.f)/log(2.f); + childSetValue("zoom slider", mCurZoomVal); setDefaultBtn(NULL); mZoomTimer.stop(); - + + onChangeMaturity(); + return TRUE; } @@ -253,13 +265,15 @@ LLFloaterWorldMap::~LLFloaterWorldMap() { // All cleaned up by LLView destructor mPanel = NULL; - + // Inventory deletes all observers on shutdown mInventory = NULL; mInventoryObserver = NULL; - + // avatar tracker will delete this for us. mFriendObserver = NULL; + + gFloaterWorldMap = NULL; } @@ -297,14 +311,8 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target) } 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 bool request_from_sim = true; - LLWorldMap::getInstance()->setCurrentLayer(0, 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. @@ -338,9 +346,7 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target) // static void LLFloaterWorldMap::reloadIcons(void*) { - LLWorldMap::getInstance()->eraseItems(); - - LLWorldMap::getInstance()->sendMapLayerRequest(); + LLWorldMap::getInstance()->reloadItems(); } @@ -396,9 +402,7 @@ BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks) { if (!isMinimized() && isFrontmost()) { - LLRect area; - childGetRect("search_results", area); - if(!area.pointInRect(x, y)) + if(mPanel->pointInView(x, y)) { F32 slider_value = (F32)childGetValue("zoom slider").asReal(); slider_value += ((F32)clicks * -0.3333f); @@ -427,20 +431,6 @@ void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent // virtual void LLFloaterWorldMap::draw() { - // Hide/Show Mature Events controls - childSetVisible("events_mature_icon", gAgent.canAccessMature()); - childSetVisible("events_mature_label", gAgent.canAccessMature()); - childSetVisible("event_mature_chk", gAgent.canAccessMature()); - - childSetVisible("events_adult_icon", gAgent.canAccessMature()); - childSetVisible("events_adult_label", gAgent.canAccessMature()); - childSetVisible("event_adult_chk", gAgent.canAccessMature()); - bool adult_enabled = gAgent.canAccessAdult(); - if (!adult_enabled) - { - childSetValue("event_adult_chk", FALSE); - } - childSetEnabled("event_adult_chk", adult_enabled); // On orientation island, users don't have a home location yet, so don't // let them teleport "home". It dumps them in an often-crowed welcome @@ -481,7 +471,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); } @@ -499,36 +489,30 @@ 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); getDragHandle()->setMouseOpaque(TRUE); - + //RN: snaps to zoom value because interpolation caused jitter in the text rendering - F32 interp = 1.f; - if (!mZoomTimer.getStarted()) + if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)getChild("zoom slider")->getValue().asReal()) { - mCurZoomValInterpolationStart = mCurZoomVal; - if (mCurZoomVal < (F32)childGetValue("zoom slider").asReal()) - { - mZoomTimer.start(); - } + mZoomTimer.start(); } - if (mZoomTimer.getStarted()) - { - interp = mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME; - } - if (interp >= 1.f) + F32 interp = mZoomTimer.getStarted() ? mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME : 1.f; + if (interp > 1.f) { interp = 1.f; mZoomTimer.stop(); } - // Interpolate between mCurZoomValInterpolationStart and "zoom slider". - mCurZoomVal = lerp(mCurZoomValInterpolationStart, (F32)childGetValue("zoom slider").asReal(), interp); + mCurZoomVal = lerp(mCurZoomVal, (F32)getChild("zoom slider")->getValue().asReal(), interp); F32 map_scale = 256.f*pow(2.f, mCurZoomVal); LLWorldMapView::setScale( map_scale ); + onChangeMaturity(); + + LLFloater::draw(); } @@ -632,32 +616,37 @@ 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(""); + + // clicked on a non-region - turn off coord display + enableTeleportCoordsDisplay( false ); + return; } 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(""); + + // clicked on a down region - turn off coord display + enableTeleportCoordsDisplay( false ); + return; } - + std::string sim_name = sim_info->getName(); - U32 locX, locY; - from_region_handle(sim_info->getHandle(), &locX, &locY); - F32 region_x = pos_global.mdV[VX] - locX; - F32 region_y = pos_global.mdV[VY] - locY; + 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)", // sim_name.c_str(), // [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-04 (RLVa-1.0.0a) @@ -670,13 +659,43 @@ 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 + + LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal(); + updateTeleportCoordsDisplay( coord_pos ); + + // we have a valid region - turn on coord display + enableTeleportCoordsDisplay( true ); + setDefaultBtn("Teleport"); } + +// enable/disable teleport destination coordinates +void LLFloaterWorldMap::enableTeleportCoordsDisplay( bool enabled ) +{ + childSetEnabled("spin x", enabled ); + childSetEnabled("spin y", enabled ); + childSetEnabled("spin z", enabled ); +} + +// update display of teleport destination coordinates - pos is in global coordinates +void LLFloaterWorldMap::updateTeleportCoordsDisplay( const LLVector3d& pos ) +{ + // if we're going to update their value, we should also enable them + enableTeleportCoordsDisplay( true ); + + // convert global specified position to a local one + F32 region_local_x = (F32)fmod( pos.mdV[VX], (F64)REGION_WIDTH_METERS ); + F32 region_local_y = (F32)fmod( pos.mdV[VY], (F64)REGION_WIDTH_METERS ); + F32 region_local_z = (F32)llclamp( pos.mdV[VZ], 0.0, (F64)REGION_HEIGHT_METERS ); + + // write in the values + childSetValue("spin x", region_local_x ); + childSetValue("spin y", region_local_y ); + childSetValue("spin z", region_local_z ); + } + void LLFloaterWorldMap::updateLocation() { bool gotSimName; @@ -703,19 +722,16 @@ void LLFloaterWorldMap::updateLocation() // Fill out the location field childSetValue("location", agent_sim_name); + // update the coordinate display with location of avatar in region + updateTeleportCoordsDisplay( agentPos ); + + S32 x = llround( (F32)fmod( (F32)agentPos[VX], (F32)REGION_WIDTH_METERS ) ); + S32 y = llround( (F32)fmod( (F32)agentPos[VY], (F32)REGION_WIDTH_METERS ) ); + S32 z = llround( (F32)agentPos[VZ] ); + // Figure out where user is - LLVector3d agentPos = gAgent.getPositionGlobal(); - - S32 agent_x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) ); - S32 agent_y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) ); - S32 agent_z = llround( (F32)agentPos.mdV[VZ] ); - - childSetValue("spin x", LLSD(agent_x) ); - childSetValue("spin y", LLSD(agent_y) ); - childSetValue("spin z", LLSD(agent_z) ); - // Set the current SLURL - mSLURL = LLURLDispatcher::buildSLURL(agent_sim_name, agent_x, agent_y, agent_z); + mSLURL = LLURLDispatcher::buildSLURL(agent_sim_name, x, y, z); // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) @@ -751,16 +767,18 @@ void LLFloaterWorldMap::updateLocation() childSetValue("location", sim_name); - 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 ); - childSetValue("spin x", LLSD(region_x) ); - childSetValue("spin y", LLSD(region_y) ); - childSetValue("spin z", LLSD((F32)pos_global.mdV[VZ]) ); - + // refresh coordinate display to reflect where user clicked. + LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal(); + updateTeleportCoordsDisplay( coord_pos ); + // simNameFromPosGlobal can fail, so don't give the user an invalid SLURL if ( gotSimName ) { - mSLURL = LLURLDispatcher::buildSLURL(sim_name, llround(region_x), llround(region_y), llround((F32)pos_global.mdV[VZ])); + LLVector3d agentPos = gAgent.getPositionGlobal(); + S32 x = llround( (F32)fmod( (F32)agentPos[VX], (F32)REGION_WIDTH_METERS ) ); + S32 y = llround( (F32)fmod( (F32)agentPos[VY], (F32)REGION_WIDTH_METERS ) ); + S32 z = llround( (F32)agentPos[VZ] ); + mSLURL = LLURLDispatcher::buildSLURL(sim_name, x, y, z); } else { // Empty SLURL will disable the "Copy SLURL to clipboard" button @@ -795,15 +813,17 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3 { // fill in UI based on URL gFloaterWorldMap->childSetValue("location", region_name); - childSetValue("spin x", LLSD((F32)x_coord)); - childSetValue("spin y", LLSD((F32)y_coord)); - childSetValue("spin z", LLSD((F32)z_coord)); + + // Save local coords to highlight position after region global + // position is returned. + gFloaterWorldMap->mCompletingRegionPos.set( + (F32)x_coord, (F32)y_coord, (F32)z_coord); // 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(); } } @@ -868,9 +888,9 @@ void LLFloaterWorldMap::friendsChanged() // No longer really builds a list. Instead, just updates mAvatarCombo. void LLFloaterWorldMap::buildAvatarIDList() { - LLCtrlListInterface *list = childGetListInterface("friend combo"); + LLCtrlListInterface *list = mListFriendCombo; if (!list) return; - + // Delete all but the "None" entry S32 list_size = list->getItemCount(); if (list_size > 1) @@ -879,12 +899,6 @@ void LLFloaterWorldMap::buildAvatarIDList() list->operateOnSelection(LLCtrlListInterface::OP_DELETE); } - 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); @@ -904,12 +918,9 @@ void LLFloaterWorldMap::buildAvatarIDList() void LLFloaterWorldMap::buildLandmarkIDLists() { - LLCtrlListInterface *list = childGetListInterface("landmark combo"); - if (!list) - { - return; - } - + LLCtrlListInterface *list = mListLandmarkCombo; + if (!list) return; + // Delete all but the "None" entry S32 list_size = list->getItemCount(); if (list_size > 1) @@ -969,7 +980,7 @@ F32 LLFloaterWorldMap::getDistanceToDestination(const LLVector3d &destination, void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) { - LLCtrlListInterface *list = childGetListInterface("search_results"); + LLCtrlListInterface *list = mListSearchResults; if (list) { list->operateOnAll(LLCtrlListInterface::OP_DELETE); @@ -986,9 +997,9 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) { childSetValue("spin z", 0); } - LLWorldMap::getInstance()->mIsTrackingCommit = FALSE; + //Singu Note: Don't do this. It basically 'eats' the first click onto void space if the previous tracked target was a valid sim. + //LLWorldMap::getInstance()->cancelTracking(); mCompletingRegionName = ""; - mExactMatch = FALSE; } @@ -996,7 +1007,7 @@ void LLFloaterWorldMap::clearLandmarkSelection(BOOL clear_ui) { if (clear_ui || !childHasKeyboardFocus("landmark combo")) { - LLCtrlListInterface *list = childGetListInterface("landmark combo"); + LLCtrlListInterface *list = mListLandmarkCombo; if (list) { list->selectByValue( "None" ); @@ -1010,7 +1021,7 @@ void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui) if (clear_ui || !childHasKeyboardFocus("friend combo")) { mTrackedStatus = LLTracker::TRACKING_NOTHING; - LLCtrlListInterface *list = childGetListInterface("friend combo"); + LLCtrlListInterface *list = mListFriendCombo; if (list) { list->selectByValue( "None" ); @@ -1023,22 +1034,22 @@ 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 - LLRect view_rect = mPanel->getRect(); - + LLWorldMapView* map_panel; + map_panel = (LLWorldMapView*)mPanel; + LLRect view_rect = map_panel->getRect(); + // View size in pixels S32 view_width = view_rect.getWidth(); S32 view_height = view_rect.getHeight(); - + // Pixels per region to display entire width/height F32 width_pixels_per_region = (F32) view_width / (F32) world_width_regions; F32 height_pixels_per_region = (F32) view_height / (F32) world_height_regions; @@ -1052,9 +1063,10 @@ void LLFloaterWorldMap::adjustZoomSliderBounds() // Make sure the zoom slider can be moved at least a little bit. // Likewise, less than the increment pixels per region is just silly. - pixels_per_region = llclamp(pixels_per_region, 1.f, (F32)(pow(2.f, ZOOM_MAX) * 128.f)); - + pixels_per_region = llclamp(pixels_per_region, 1.f, ZOOM_MAX); + F32 min_power = log(pixels_per_region/256.f)/log(2.f); + childSetMinValue("zoom slider", min_power); } @@ -1063,34 +1075,10 @@ void LLFloaterWorldMap::adjustZoomSliderBounds() // User interface widget callbacks //------------------------------------------------------------------------- -// static -void LLFloaterWorldMap::onPanBtn( void* userdata ) -{ - if( !gFloaterWorldMap ) return; - - EPanDirection direction = (EPanDirection)(intptr_t)userdata; - - S32 pan_x = 0; - S32 pan_y = 0; - switch( direction ) - { - case PAN_UP: pan_y = -1; break; - case PAN_DOWN: pan_y = 1; break; - case PAN_LEFT: pan_x = 1; break; - case PAN_RIGHT: pan_x = -1; break; - default: llassert(0); return; - } - - LLWorldMapView* map_panel; - map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; - map_panel->translatePan( pan_x, pan_y ); -} - -// static -void LLFloaterWorldMap::onGoHome(void*) +void LLFloaterWorldMap::onGoHome() { gAgent.teleportHome(); - gFloaterWorldMap->close(); + close(); } @@ -1122,7 +1110,7 @@ void LLFloaterWorldMap::onComboTextEntry( LLLineEditor* ctrl, void* userdata ) // Reset the tracking whenever we start typing into any of the search fields, // so that hitting does an auto-complete versus teleporting us to the // previously selected landmark/friend. - LLTracker::clearFocus(); + LLTracker::stopTracking(NULL); } // static @@ -1133,16 +1121,14 @@ void LLFloaterWorldMap::onSearchTextEntry( LLLineEditor* ctrl, void* userdata ) } // static -void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata ) +void LLFloaterWorldMap::onLandmarkComboCommit() { - LLFloaterWorldMap* self = gFloaterWorldMap; - - if( !self || self->mIsClosing ) + if( mIsClosing ) { return; } - - LLCtrlListInterface *list = gFloaterWorldMap->childGetListInterface("landmark combo"); + + LLCtrlListInterface *list = mListLandmarkCombo; if (!list) return; LLUUID asset_id; @@ -1174,11 +1160,11 @@ void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata ) } } - self->trackLandmark( item_id); - onShowTargetBtn(self); - + trackLandmark( item_id); + onShowTargetBtn(); + // Reset to user postion if nothing is tracked - self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); + mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); } // static @@ -1208,31 +1194,28 @@ void LLFloaterWorldMap::onAvatarComboPrearrange( LLUICtrl* ctrl, void* userdata } } - -// static -void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata ) +void LLFloaterWorldMap::onAvatarComboCommit() { - LLFloaterWorldMap* self = gFloaterWorldMap; - if( !self || self->mIsClosing ) + if( mIsClosing ) { return; } - - LLCtrlListInterface *list = gFloaterWorldMap->childGetListInterface("friend combo"); + + LLCtrlListInterface *list = mListFriendCombo; if (!list) return; - + const LLUUID& new_avatar_id = list->getCurrentID(); if (new_avatar_id.notNull()) { std::string name; - LLComboBox* combo = gFloaterWorldMap->getChild("friend combo"); + LLComboBox* combo = getChild("friend combo"); if (combo) name = combo->getSimple(); - self->trackAvatar(new_avatar_id, name); - onShowTargetBtn(self); + trackAvatar(new_avatar_id, name); + onShowTargetBtn(); } else { // Reset to user postion if nothing is tracked - self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); + mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); } } @@ -1254,105 +1237,99 @@ void LLFloaterWorldMap::updateSearchEnabled() } } -// static -void LLFloaterWorldMap::onLocationCommit( void* userdata ) +void LLFloaterWorldMap::onLocationCommit() { - LLFloaterWorldMap *self = gFloaterWorldMap; - if( !self || self->mIsClosing ) + if( mIsClosing ) { return; } + + clearLocationSelection(FALSE); + mCompletingRegionName = ""; + mLastRegionName = ""; - self->clearLocationSelection(FALSE); - self->mCompletingRegionName = ""; - self->mLastRegionName = ""; - - std::string str = self->childGetValue("location").asString(); + std::string str = childGetValue("location").asString(); // Trim any leading and trailing spaces in the search target std::string saved_str = str; LLStringUtil::trim( str ); if ( str != saved_str ) { // Set the value in the UI if any spaces were removed - self->childSetValue("location", str); + childSetValue("location", str); + } + + // Don't try completing empty name (STORM-1427). + if (str.empty()) + { + return; } LLStringUtil::toLower(str); - gFloaterWorldMap->mCompletingRegionName = str; - LLWorldMap::getInstance()->mIsTrackingCommit = TRUE; - self->mExactMatch = FALSE; + mCompletingRegionName = str; + 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); } } - -// static -void LLFloaterWorldMap::onClearBtn(void* data) +void LLFloaterWorldMap::onCoordinatesCommit() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->mTrackedStatus = LLTracker::TRACKING_NOTHING; + if( mIsClosing ) + { + return; + } + + S32 x_coord = (S32)childGetValue("spin x").asReal(); + S32 y_coord = (S32)childGetValue("spin y").asReal(); + S32 z_coord = (S32)childGetValue("spin z").asReal(); + + const std::string region_name = childGetValue("location").asString(); + + trackURL( region_name, x_coord, y_coord, z_coord ); +} + +void LLFloaterWorldMap::onClearBtn() +{ + mTrackedStatus = LLTracker::TRACKING_NOTHING; LLTracker::stopTracking((void *)(intptr_t)TRUE); - LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE; - self->mSLURL = ""; // Clear the SLURL since it's invalid - self->mSetToUserPosition = TRUE; // Revert back to the current user position + LLWorldMap::getInstance()->cancelTracking(); + mSLURL = ""; // Clear the SLURL since it's invalid + mSetToUserPosition = TRUE; // Revert back to the current user position } -// static -void LLFloaterWorldMap::onFlyBtn(void* data) +void LLFloaterWorldMap::onShowTargetBtn() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->fly(); + centerOnTarget(TRUE); } -void LLFloaterWorldMap::onShowTargetBtn(void* data) -{ - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->centerOnTarget(TRUE); -} - -void LLFloaterWorldMap::onShowAgentBtn(void* data) +void LLFloaterWorldMap::onShowAgentBtn() { LLWorldMapView::setPan( 0, 0, FALSE); // FALSE == animate - // Set flag so user's location will be displayed if not tracking anything else - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->mSetToUserPosition = TRUE; + mSetToUserPosition = TRUE; } -// static -void LLFloaterWorldMap::onClickTeleportBtn(void* data) +void LLFloaterWorldMap::onClickTeleportBtn() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - self->teleport(); + teleport(); } -// static -void LLFloaterWorldMap::onCopySLURL(void* data) +void LLFloaterWorldMap::onCopySLURL() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(self->mSLURL)); + getWindow()->copyTextToClipboard(utf8str_to_wstring(mSLURL)); LLSD args; - args["SLURL"] = self->mSLURL; + args["SLURL"] = mSLURL; LLNotificationsUtil::add("CopySLURL", args); } -void LLFloaterWorldMap::onCheckEvents(LLUICtrl*, void* data) -{ - LLFloaterWorldMap* self = (LLFloaterWorldMap*)data; - if(!self) return; - self->childSetEnabled("event_mature_chk", self->childGetValue("event_chk")); - self->childSetEnabled("event_adult_chk", self->childGetValue("event_chk")); -} - // protected void LLFloaterWorldMap::centerOnTarget(BOOL animate) { @@ -1374,9 +1351,12 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate) pos_global = LLTracker::getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal(); } } - else if(LLWorldMap::getInstance()->mIsTrackingUnknownLocation) + else if(LLWorldMap::getInstance()->isTracking()) { - pos_global = LLWorldMap::getInstance()->mUnknownLocation - gAgentCamera.getCameraPositionGlobal();; + pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal();; + + + } else { @@ -1472,24 +1452,6 @@ void LLFloaterWorldMap::teleport() } } -// static -void LLFloaterWorldMap::onGoToLandmarkDialog( S32 option, void* userdata ) -{ - LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata; - switch( option ) - { - case 0: - self->teleportToLandmark(); - break; - case 1: - self->flyToLandmark(); - break; - default: - // nothing - break; - } -} - void LLFloaterWorldMap::flyToLandmark() { LLVector3d destination_pos_global; @@ -1570,94 +1532,72 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) LLScrollListCtrl *list = getChild("search_results"); list->operateOnAll(LLCtrlListInterface::OP_DELETE); - - LLSD selected_value = list->getSelectedValue(); - + S32 name_length = mCompletingRegionName.length(); + + LLSD match; - BOOL match_found = FALSE; S32 num_results = 0; - std::map::const_iterator it; - for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + + std::vector > sim_info_vec(LLWorldMap::getInstance()->getRegionMap().begin(), LLWorldMap::getInstance()->getRegionMap().end()); + std::sort(sim_info_vec.begin(), sim_info_vec.end(), SortRegionNames()); + + for (std::vector >::const_iterator it = sim_info_vec.begin(); it != sim_info_vec.end(); ++it) { - LLSimInfo* info = (*it).second; - std::string sim_name = info->getName(); - 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 (LLWorldMap::getInstance()->mIsTrackingCommit) + if (sim_name_lower == mCompletingRegionName) { - if (sim_name_lower == mCompletingRegionName) - { - selected_value = sim_name; - match_found = TRUE; - } + 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++; } } - list->selectByValue(selected_value); - - if (found_null_sim) + if (found_null_sim || match.isDefined()) { mCompletingRegionName = ""; } - - if (match_found) + + if (num_results > 0) { - mExactMatch = TRUE; + // if match found, highlight it and go + if (!match.isUndefined()) + { + list->selectByValue(match); + } + // else select first found item + else + { + list->selectFirstItem(); + } childSetFocus("search_results"); - onCommitSearchResult(NULL, this); - } - else if (!mExactMatch && num_results > 0) - { - list->selectFirstItem(); // select first item by default - childSetFocus("search_results"); - onCommitSearchResult(NULL, this); + onCommitSearchResult(); } else { // if we found nothing, say "none" - list->addCommentText(LLTrans::getString("worldmap_results_none_found")); + list->setCommentText(LLTrans::getString("worldmap_results_none_found")); list->operateOnAll(LLCtrlListInterface::OP_DESELECT); } } -// static -void LLFloaterWorldMap::onCommitLocation(LLUICtrl* ctrl, void* userdata) -{ - LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata; - LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); - if ( LLTracker::TRACKING_LOCATION == tracking_status) - { - LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); - F64 local_x = self->childGetValue("spin x"); - F64 local_y = self->childGetValue("spin y"); - F64 local_z = self->childGetValue("spin z"); - pos_global.mdV[VX] += -fmod(pos_global.mdV[VX], 256.0) + local_x; - pos_global.mdV[VY] += -fmod(pos_global.mdV[VY], 256.0) + local_y; - pos_global.mdV[VZ] = local_z; - self->trackLocation(pos_global); - } -} -// static -void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata) +void LLFloaterWorldMap::onCommitSearchResult() { - LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata; - - LLCtrlListInterface *list = self->childGetListInterface("search_results"); + LLCtrlListInterface *list = mListSearchResults; if (!list) return; - + LLSD selected_value = list->getSelectedValue(); std::string sim_name = selected_value.asString(); if (sim_name.empty()) @@ -1674,19 +1614,52 @@ void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata) if (info->isName(sim_name)) { LLVector3d pos_global = info->getGlobalOrigin(); - F64 local_x = self->childGetValue("spin x"); - F64 local_y = self->childGetValue("spin y"); - F64 local_z = self->childGetValue("spin z"); - pos_global.mdV[VX] += local_x; - pos_global.mdV[VY] += local_y; - pos_global.mdV[VZ] = local_z; + + const F64 SIM_COORD_DEFAULT = 128.0; + LLVector3 pos_local(SIM_COORD_DEFAULT, SIM_COORD_DEFAULT, 0.0f); + + // Did this value come from a trackURL() request? + if (!mCompletingRegionPos.isExactlyZero()) + { + pos_local = mCompletingRegionPos; + mCompletingRegionPos.clear(); + } + pos_global.mdV[VX] += (F64)pos_local.mV[VX]; + pos_global.mdV[VY] += (F64)pos_local.mV[VY]; + pos_global.mdV[VZ] = (F64)pos_local.mV[VZ]; - self->childSetValue("location", sim_name); - self->trackLocation(pos_global); - self->setDefaultBtn("Teleport"); + childSetValue("location", sim_name); + trackLocation(pos_global); + setDefaultBtn("Teleport"); break; } } - onShowTargetBtn(self); + onShowTargetBtn(); +} + +void LLFloaterWorldMap::onChangeMaturity() +{ + bool can_access_mature = gAgent.canAccessMature(); + bool can_access_adult = gAgent.canAccessAdult(); + + childSetVisible("events_mature_icon", can_access_mature); + childSetVisible("events_mature_label", can_access_mature); + childSetVisible("event_mature_chk", can_access_mature); + + childSetVisible("events_adult_icon", can_access_adult); + childSetVisible("events_adult_label", can_access_adult); + childSetVisible("event_adult_chk", can_access_adult); + + // disable mature / adult events. + if (!can_access_mature) + { + static LLCachedControl show_mature("MapShowMatureEvents",false); + show_mature = false; + } + if (!can_access_adult) + { + static LLCachedControl show_adult("MapShowAdultEvents",false); + show_adult = false; + } } diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 80cc25abd..53cd425b7 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -111,29 +111,25 @@ public: // teleport to the tracked item, if there is one void teleport(); + void onChangeMaturity(); -protected: - static void onPanBtn( void* userdata ); - - static void onGoHome(void* data); +protected: + void onGoHome(); static void onLandmarkComboPrearrange( LLUICtrl* ctrl, void* data ); - static void onLandmarkComboCommit( LLUICtrl* ctrl, void* data ); + void onLandmarkComboCommit(); static void onAvatarComboPrearrange( LLUICtrl* ctrl, void* data ); - static void onAvatarComboCommit( LLUICtrl* ctrl, void* data ); + void onAvatarComboCommit(); static void onComboTextEntry( LLLineEditor* ctrl, void* data ); static void onSearchTextEntry( LLLineEditor* ctrl, void* data ); - static void onClearBtn(void*); - static void onFlyBtn(void*); - static void onClickTeleportBtn(void*); - static void onShowTargetBtn(void*); - static void onShowAgentBtn(void*); - static void onCopySLURL(void*); - - static void onCheckEvents(LLUICtrl* ctrl, void*); + void onClearBtn(); + void onClickTeleportBtn(); + void onShowTargetBtn(); + void onShowAgentBtn(); + void onCopySLURL(); void centerOnTarget(BOOL animate); void updateLocation(); @@ -142,7 +138,6 @@ protected: void fly(); void buildLandmarkIDLists(); - static void onGoToLandmarkDialog(S32 option,void* userdata); void flyToLandmark(); void teleportToLandmark(); void setLandmarkVisited(); @@ -152,24 +147,28 @@ protected: void teleportToAvatar(); void updateSearchEnabled(); - void onLocationFocusChanged( LLFocusableElement* focus ); - static void onLocationCommit( void* userdata ); - static void onCommitLocation( LLUICtrl* ctrl, void* userdata ); - static void onCommitSearchResult( LLUICtrl* ctrl, void* userdata ); + void onLocationFocusChanged( LLFocusableElement* ctrl ); + void onLocationCommit(); + void onCoordinatesCommit(); + void onCommitSearchResult(); void cacheLandmarkPosition(); -protected: - LLPanel* mPanel; // Panel displaying the map +private: + LLPanel* mPanel; // Panel displaying the map // Sets sMapScale, in pixels per region F32 mCurZoomVal; - F32 mCurZoomValInterpolationStart; // Used during mZoomTimer interpolation. LLFrameTimer mZoomTimer; + // update display of teleport destination coordinates - pos is in global coordinates + void updateTeleportCoordsDisplay( const LLVector3d& pos ); + + // enable/disable teleport destination coordinates + void enableTeleportCoordsDisplay( bool enabled ); + LLDynamicArray mLandmarkAssetIDList; LLDynamicArray mLandmarkItemIDList; - BOOL mHasLandmarkPosition; static const LLUUID sHomeID; @@ -178,9 +177,12 @@ protected: LLFriendObserver* mFriendObserver; std::string mCompletingRegionName; + // Local position from trackURL() request, used to select final + // position once region lookup complete. + LLVector3 mCompletingRegionPos; + std::string mLastRegionName; BOOL mWaitingForTracker; - BOOL mExactMatch; BOOL mIsClosing; BOOL mSetToUserPosition; @@ -190,6 +192,10 @@ protected: std::string mTrackedSimName; std::string mTrackedAvatarName; std::string mSLURL; + + LLCtrlListInterface * mListFriendCombo; + LLCtrlListInterface * mListLandmarkCombo; + LLCtrlListInterface * mListSearchResults; }; extern LLFloaterWorldMap* gFloaterWorldMap; diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index 3bfbf3611..69060653f 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -77,7 +77,7 @@ public: virtual BOOL copyToClipboard() const = 0; virtual void cutToClipboard() = 0; virtual BOOL isClipboardPasteable() const = 0; - virtual void pasteFromClipboard() = 0; + virtual void pasteFromClipboard(bool only_copies = false) = 0; virtual void pasteLinkFromClipboard() = 0; virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; virtual BOOL isUpToDate() const = 0; diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 852ad01b8..e5d1bb259 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -792,7 +792,7 @@ void LLGestureMgr::update() if (gesture->mDoneCallback) { - gesture->mDoneCallback(gesture, gesture->mCallbackData); + gesture->mDoneCallback(gesture); // callback might have deleted gesture, can't // rely on this pointer any more @@ -1299,7 +1299,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture) if (gesture->mDoneCallback) { - gesture->mDoneCallback(gesture, gesture->mCallbackData); + gesture->mDoneCallback(gesture); // callback might have deleted gesture, can't // rely on this pointer any more diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index c89c414b5..3cde11774 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -36,6 +36,7 @@ #include #include +#include "llappviewer.h" //For gFrameCount #include "llagent.h" #include "llui.h" #include "message.h" @@ -44,6 +45,7 @@ #include "llstatusbar.h" #include "lleconomy.h" #include "llviewercontrol.h" +#include "llviewerregion.h" #include "llviewerwindow.h" #include "llfloaterdirectory.h" #include "llfloatergroupinfo.h" @@ -821,6 +823,7 @@ void LLGroupMgrGroupData::cancelRoleChanges() LLGroupMgr::LLGroupMgr() { + mLastGroupMembersRequestFrame = 0; } LLGroupMgr::~LLGroupMgr() @@ -1885,6 +1888,187 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id, } } + +class AIHTTPTimeoutPolicy; +extern AIHTTPTimeoutPolicy groupMemberDataResponder_timeout; + +// Responder class for capability group management +class GroupMemberDataResponder : public LLHTTPClient::ResponderWithResult +{ +public: + virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return groupMemberDataResponder_timeout; } + + GroupMemberDataResponder() {} + virtual ~GroupMemberDataResponder() {} + virtual void result(const LLSD& pContent); + virtual void error(U32 pStatus, const std::string& pReason); +private: + LLSD mMemberData; +}; + +void GroupMemberDataResponder::error(U32 pStatus, const std::string& pReason) +{ + LL_WARNS("GrpMgr") << "Error receiving group member data." << LL_ENDL; +} + +void GroupMemberDataResponder::result(const LLSD& content) +{ + LLGroupMgr::processCapGroupMembersRequest(content); +} + + +// static +void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id) +{ + // Have we requested the information already this frame? + if (mLastGroupMembersRequestFrame == gFrameCount) + return; + + LLViewerRegion* currentRegion = gAgent.getRegion(); + // Thank you FS:Ansariel! + if (!currentRegion) + { + LL_WARNS("GrpMgr") << "Agent does not have a current region. Uh-oh!" << LL_ENDL; + return; + } + + // Check to make sure we have our capabilities + if (!currentRegion->capabilitiesReceived()) + { + LL_WARNS("GrpMgr") << " Capabilities not received!" << LL_ENDL; + return; + } + + // Get our capability + std::string cap_url = currentRegion->getCapability("GroupMemberData"); + + // Thank you FS:Ansariel! + if (cap_url.empty()) + { + LL_INFOS("GrpMgr") << "Region has no GroupMemberData capability. Falling back to UDP fetch." << LL_ENDL; + sendGroupMembersRequest(group_id); + return; + } + + // Post to our service. Add a body containing the group_id. + LLSD body = LLSD::emptyMap(); + body["group_id"] = group_id; + + LLHTTPClient::ResponderPtr grp_data_responder = new GroupMemberDataResponder(); + + // This could take a while to finish, timeout after 5 minutes. + LLHTTPClient::post(cap_url, body, grp_data_responder); + + mLastGroupMembersRequestFrame = gFrameCount; +} + +// static +void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) +{ + // Did we get anything in content? + if (!content.size()) + { + LL_DEBUGS("GrpMgr") << "No group member data received." << LL_ENDL; + return; + } + + // If we have no members, there's no reason to do anything else + S32 num_members = content["member_count"]; + if (num_members < 1) + return; + + LLUUID group_id = content["group_id"].asUUID(); + + LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id); + if (!group_datap) + { + LL_WARNS("GrpMgr") << "Received incorrect, possibly stale, group or request id" << LL_ENDL; + return; + } + + group_datap->mMemberCount = num_members; + + LLSD member_list = content["members"]; + LLSD titles = content["titles"]; + LLSD defaults = content["defaults"]; + + std::string online_status; + std::string title; + S32 contribution; + U64 member_powers; + // If this is changed to a bool, make sure to change the LLGroupMemberData constructor + BOOL is_owner; + + // Compute this once, rather than every time. + U64 default_powers = llstrtou64(defaults["default_powers"].asString().c_str(), NULL, 16); + + LLSD::map_const_iterator member_iter_start = member_list.beginMap(); + LLSD::map_const_iterator member_iter_end = member_list.endMap(); + for ( ; member_iter_start != member_iter_end; ++member_iter_start) + { + // Reset defaults + online_status = "unknown"; + title = titles[0].asString(); + contribution = 0; + member_powers = default_powers; + is_owner = false; + + const LLUUID member_id(member_iter_start->first); + LLSD member_info = member_iter_start->second; + + if (member_info.has("last_login")) + { + online_status = member_info["last_login"].asString(); + if (online_status == "Online") + online_status = LLTrans::getString("group_member_status_online"); + else + formatDateString(online_status); + } + + if (member_info.has("title")) + title = titles[member_info["title"].asInteger()].asString(); + + if (member_info.has("powers")) + member_powers = llstrtou64(member_info["powers"].asString().c_str(), NULL, 16); + + if (member_info.has("donated_square_meters")) + contribution = member_info["donated_square_meters"]; + + if (member_info.has("owner")) + is_owner = true; + + LLGroupMemberData* data = new LLGroupMemberData(member_id, + contribution, + member_powers, + title, + online_status, + is_owner); + + group_datap->mMembers[member_id] = data; + } + + // Technically, we have this data, but to prevent completely overhauling + // this entire system (it would be nice, but I don't have the time), + // I'm going to be dumb and just call services I most likely don't need + // with the thought being that the system might need it to be done. + // + // TODO: Refactor to reduce multiple calls for data we already have. + if (group_datap->mTitles.size() < 1) + LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id); + + group_datap->mMemberDataComplete = TRUE; + group_datap->mMemberRequestID.setNull(); + // Make the role-member data request + if (group_datap->mPendingRoleMemberRequest) + { + group_datap->mPendingRoleMemberRequest = FALSE; + LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_id); + } + + group_datap->mChanged = TRUE; + LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA); +} + void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id) { lldebugs << "LLGroupMgr::sendGroupRoleChanges" << llendl; diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index 225db1735..6a18add68 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -335,6 +335,9 @@ public: static void sendGroupMemberEjects(const LLUUID& group_id, uuid_vec_t& member_ids); + void sendCapGroupMembersRequest(const LLUUID& group_id); + static void processCapGroupMembersRequest(const LLSD& content); + void cancelGroupRoleChanges(const LLUUID& group_id); static void processGroupPropertiesReply(LLMessageSystem* msg, void** data); @@ -370,6 +373,8 @@ private: typedef std::set observer_set_t; typedef std::map observer_map_t; observer_map_t mParticularObservers; + + S32 mLastGroupMembersRequestFrame; }; diff --git a/indra/newview/llhoverview.cpp b/indra/newview/llhoverview.cpp index f6cff6f16..fa922a94b 100644 --- a/indra/newview/llhoverview.cpp +++ b/indra/newview/llhoverview.cpp @@ -262,39 +262,16 @@ void LLHoverView::updateText() else { // [/RLVa:KB] - - // [Ansariel: Display name support] - std::string complete_name = firstname->getString(); - complete_name += " "; - complete_name += lastname->getString(); - - if (LLAvatarNameCache::useDisplayNames()) - { - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(hit_object->getID(), &avatar_name)) - { - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - if (phoenix_name_system == 2 || (phoenix_name_system == 1 && avatar_name.mIsDisplayNameDefault)) - { - complete_name = avatar_name.mDisplayName; - } - else - { - complete_name = avatar_name.getCompleteName(); - } - } - } - // [/Ansariel: Display name support] + std::string complete_name; + if (!LLAvatarNameCache::getPNSName(hit_object->getID(), complete_name)) + complete_name = firstname->getString() + std::string(" ") + lastname->getString(); if (title) { line.append(title->getString()); line.append(1, ' '); } - - // [Ansariel: Display name support] line += complete_name; - // [/Ansariel: Display name support] // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) } @@ -347,27 +324,13 @@ void LLHoverView::updateText() std::string name; if (!nodep->mPermissions->isGroupOwned()) { - // [Ansariel: Display name support] - LLAvatarName avatar_name; - // [/Ansariel: Display name support] owner = nodep->mPermissions->getOwner(); if (LLUUID::null == owner) { line.append(LLTrans::getString("TooltipPublic")); } - // [Ansariel: Display name support] - //else if(gCacheName->getFullName(owner, name)) - else if (LLAvatarNameCache::get(owner, &avatar_name)) + else if(LLAvatarNameCache::getPNSName(owner, name)) { - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - switch (phoenix_name_system) - { - case 0 : name = avatar_name.getCompleteName(); break; - case 1 : name = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : name = avatar_name.mDisplayName; break; - default : name = avatar_name.getCompleteName(); break; - } - // [/Ansariel: Display name support] // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) { diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index bd8ec64be..2cbe64c02 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1297,27 +1297,23 @@ void LLFloaterIMPanel::init(const std::string& session_label) } } -// [Ansariel: Display name support] void LLFloaterIMPanel::lookupName() { LLAvatarNameCache::get(mOtherParticipantUUID, boost::bind(&LLFloaterIMPanel::onAvatarNameLookup, _1, _2, this)); } //static -void LLFloaterIMPanel::onAvatarNameLookup(const LLUUID& id, const LLAvatarName& avatar_name, void* user_data) +void LLFloaterIMPanel::onAvatarNameLookup(const LLUUID&, const LLAvatarName& avatar_name, void* data) { - LLFloaterIMPanel* self = (LLFloaterIMPanel*)user_data; + LLFloaterIMPanel* self = (LLFloaterIMPanel*)data; if (self && sFloaterIMPanels.count(self) != 0) { - std::string title = avatar_name.getCompleteName(); - if (!title.empty()) - { - self->setTitle(title); - } + std::string title; + LLAvatarNameCache::getPNSName(avatar_name, title); + self->setTitle(title); } } -// [/Ansariel: Display name support] LLFloaterIMPanel::~LLFloaterIMPanel() { @@ -1676,19 +1672,8 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, LLColor4 incol else { std::string show_name = name; - LLAvatarName avatar_name; - if (source.notNull() && - LLAvatarNameCache::get(source, &avatar_name)) - { - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - switch (phoenix_name_system) - { - case 0 : show_name = avatar_name.getCompleteName(); break; - case 1 : show_name = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : show_name = avatar_name.mDisplayName; break; - default : show_name = avatar_name.getCompleteName(); break; - } - } + if (source.notNull()) + LLAvatarNameCache::getPNSName(source, show_name); // Convert the name to a hotlink and add to message. const LLStyleSP &source_style = LLStyleMap::instance().lookupAgent(source); mHistoryEditor->appendStyledText(show_name,false,prepend_newline,source_style); diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 943bd37c1..61d8c01f7 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -196,10 +196,8 @@ public: EInstantMessage dialog); virtual ~LLFloaterIMPanel(); - // [Ansariel: Display name support] void lookupName(); - static void onAvatarNameLookup(const LLUUID& id, const LLAvatarName& avatar_name, void* user_data); - // [/Ansariel: Display name support] + static void onAvatarNameLookup(const LLUUID&, const LLAvatarName& avatar_name, void* data); /*virtual*/ BOOL postBuild(); @@ -400,7 +398,6 @@ private: typedef std::map styleMap; static styleMap mStyleMap; - // [Ansariel: Display name support] static std::set sFloaterIMPanels; }; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d6dabcdae..92f5cd320 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -483,8 +483,8 @@ void LLIMMgr::addMessage( } //not sure why...but if it is from ourselves we set the target_id - //to be NULL - if( other_participant_id == gAgent.getID() ) + //to be NULL, which seems to be breaking links on group chats, so let's not there. + if (other_participant_id == gAgent.getID() && !gAgent.isInGroup(session_id)) { other_participant_id = LLUUID::null; } @@ -553,7 +553,6 @@ void LLIMMgr::addMessage( // when answering questions. if(gAgent.isGodlike()) { - // *TODO:translate (low priority, god ability) std::ostringstream bonus_info; bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + LLTrans::getString(":") + " " << parent_estate_id @@ -574,9 +573,26 @@ void LLIMMgr::addMessage( // now add message to floater bool is_from_system = target_id.isNull() || (from == SYSTEM_FROM); - const LLColor4& color = ( is_from_system ? - gSavedSettings.getColor4("SystemChatColor") : - gSavedSettings.getColor("IMChatColor")); + + static LLCachedControl color_linden_chat("ColorLindenChat"); + bool linden = color_linden_chat && LLMuteList::getInstance()->isLinden(from); + + static LLCachedControl color_friend_chat("ColorFriendChat"); + bool contact = color_friend_chat && LLAvatarTracker::instance().isBuddy(other_participant_id); + + static LLCachedControl color_eo_chat("ColorEstateOwnerChat"); + bool estate_owner = false; + if (color_eo_chat) + { + LLViewerRegion* parent_estate = gAgent.getRegion(); + estate_owner = (parent_estate && parent_estate->isAlive() && other_participant_id == parent_estate->getOwner()); + } + + const LLColor4& color = ( is_from_system ? gSavedSettings.getColor4("SystemChatColor") + : linden ? gSavedSettings.getColor4("AscentLindenColor") + : contact ? gSavedSettings.getColor4("AscentFriendColor") + : estate_owner ? gSavedSettings.getColor4("AscentEstateOwnerColor") + : gSavedSettings.getColor("IMChatColor")); if ( !link_name ) { floater->addHistoryLine(msg,color); // No name to prepend, so just add the message normally @@ -731,7 +747,18 @@ LLUUID LLIMMgr::addSession( { noteMutedUsers(floater, ids); } - LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater); + + static LLCachedControl tear_off("OtherChatsTornOff"); + if(tear_off) + { + // removal sets up relationship for re-attach + LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater); + // reparent to floater view + gFloaterView->addChild(floater); + gFloaterView->bringToFront(floater); + } + else + LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater); } else { @@ -1103,6 +1130,19 @@ LLFloaterIMPanel* LLIMMgr::createFloater( dialog); LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt); + static LLCachedControl tear_off("OtherChatsTornOff"); + if (tear_off) + { + LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater); // removal sets up relationship for re-attach + gFloaterView->addChild(floater); // reparent to floater view + LLFloater* focused_floater = gFloaterView->getFocusedFloater(); // obtain the focused floater + floater->open(); // make the new chat floater appear + if (focused_floater != NULL) // there was a focused floater + { + floater->setMinimized(true); // so minimize this one, for now + focused_floater->setFocus(true); // and work around focus being removed by focusing on the last + } + } mFloaters.insert(floater->getHandle()); return floater; } @@ -1129,6 +1169,24 @@ LLFloaterIMPanel* LLIMMgr::createFloater( dialog); LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt); + static LLCachedControl tear_off("OtherChatsTornOff"); + if (tear_off) + { + LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater); // removal sets up relationship for re-attach + gFloaterView->addChild(floater); // reparent to floater view + LLFloater* focused_floater = gFloaterView->getFocusedFloater(); // obtain the focused floater + floater->open(); // make the new chat floater appear + static LLCachedControl minimize("OtherChatsTornOffAndMinimized"); + if (focused_floater != NULL) // there was a focused floater + { + floater->setMinimized(true); // so minimize this one, for now + focused_floater->setFocus(true); // and work around focus being removed by focusing on the last + } + else if (minimize) + { + floater->setMinimized(true); + } + } mFloaters.insert(floater->getHandle()); return floater; } @@ -1153,7 +1211,7 @@ void LLIMMgr::noteOfflineUsers( std::string full_name; if (info && !info->isOnline() - && gCacheName->getFullName(ids.get(i), full_name)) + && LLAvatarNameCache::getPNSName(ids.get(i), full_name)) { LLUIString offline = LLTrans::getString("offline_message"); offline.setArg("[NAME]", full_name); diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index 372b9bf83..074c4132a 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -67,6 +67,7 @@ #include "llinventoryclipboard.h" #include "llinventorymodelbackgroundfetch.h" #include "lllineeditor.h" +#include "llmakeoutfitdialog.h" #include "llmenugl.h" #include "llpreviewanim.h" #include "llpreviewgesture.h" @@ -382,6 +383,10 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type, LLInventoryType::IT_GESTURE, PERM_ALL); } + else if ("outfit" == type) + { + new LLMakeOutfitDialog(false); + } else { LLWearableType::EType wear_type = LLWearableType::typeNameToType(type); diff --git a/indra/newview/llinventorybackup.cpp b/indra/newview/llinventorybackup.cpp index b3caf401f..6963d4ff9 100644 --- a/indra/newview/llinventorybackup.cpp +++ b/indra/newview/llinventorybackup.cpp @@ -106,7 +106,7 @@ void LLFloaterInventoryBackupSettings::onClickNext(void* userdata) for( ; item_iter != order->mItems.end(); ) { if(type_remove[(*item_iter)->getType()]) - order->mItems.erase(item_iter); + item_iter = order->mItems.erase(item_iter); else ++item_iter; } @@ -619,11 +619,11 @@ BOOL LLFloaterInventoryBackup::postBuild(void) status_column["column"] = "status"; status_column["value"] = "Pending"; - LLScrollListItem* scroll_itemp = list->addElement(element, ADD_BOTTOM); + /*LLScrollListItem* scroll_itemp = */list->addElement(element, ADD_BOTTOM); //hack to stop crashing - LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(LIST_TYPE); - icon->setClickCallback(NULL, NULL); + //LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(LIST_TYPE); + //icon->setClickCallback(NULL); } // Setup and go! diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 8efcc693d..a690f9c7b 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -259,7 +259,7 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, mInvType(LLInventoryType::IT_NONE), mIsLink(FALSE) { - mInventoryPanel = inventory->getHandle(); + mInventoryPanel = inventory->getInventoryPanelHandle(); const LLInventoryObject* obj = getInventoryObject(); mIsLink = obj && obj->getIsLinkType(); } @@ -612,6 +612,48 @@ BOOL LLInvFVBridge::isClipboardPasteable() const return TRUE; } +bool LLInvFVBridge::isClipboardPasteableAsCopy() const +{ + // In cut mode, we don't paste copies. + if (LLInventoryClipboard::instance().isCutMode()) + { + return false; + } + + LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return false; + } + + // In copy mode, we need to check each element of the clipboard to know if it's a link + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + const S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLUUID &item_id = objects.get(i); + + // Folders may be links + const LLInventoryCategory *cat = model->getCategory(item_id); + if (cat) + { + const LLFolderBridge cat_br(panel, mRoot, item_id); + if (cat_br.isLink()) + return true; + // Skip to the next item in the clipboard + continue; + } + + // May be link item + const LLItemBridge item_br(panel, mRoot, item_id); + if (item_br.isLink()) + return true; + } + return false; +} + BOOL LLInvFVBridge::isClipboardPasteableAsLink() const { if (!InventoryLinksEnabled()) @@ -731,6 +773,20 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, { if (obj->getIsLinkType()) { + // Patch: Inventory-Links tweak, Can copy and cut Inventory Links + 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("Cut")); + if (!isItemMovable() || !isItemRemovable()) + { + disabled_items.push_back(std::string("Cut")); + } items.push_back(std::string("Find Original")); if (isLinkedObjectMissing()) { @@ -798,17 +854,26 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } } + bool paste_as_copy = false; // If Paste As Copy is on the menu, Paste As Link will always show up disabled, so don't bother. // Don't allow items to be pasted directly into the COF or the inbox/outbox if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder()) { items.push_back(std::string("Paste")); + // Paste as copy if we have links. + if (InventoryLinksEnabled() && isClipboardPasteableAsCopy()) + { + items.push_back(std::string("Paste As Copy")); + paste_as_copy = true; + } } if (!isClipboardPasteable() || ((flags & FIRST_SELECTED_ITEM) == 0)) { disabled_items.push_back(std::string("Paste")); + disabled_items.push_back(std::string("Paste As Copy")); + paste_as_copy = false; } - if(InventoryLinksEnabled()) + if (!paste_as_copy && InventoryLinksEnabled()) { items.push_back(std::string("Paste As Link")); if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) @@ -993,7 +1058,7 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const LLInventoryModel* LLInvFVBridge::getInventoryModel() const { - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); return panel ? panel->getModel() : NULL; } @@ -1469,6 +1534,18 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) folder_view_itemp->getListener()->pasteFromClipboard(); return; } + else if ("paste_copies" == action) + { + // Single item only + LLInventoryItem* itemp = model->getItem(mUUID); + if (!itemp) return; + + LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); + if (!folder_view_itemp) return; + + folder_view_itemp->getListener()->pasteFromClipboard(true); + return; + } else if ("paste_link" == action) { // Single item only @@ -1812,7 +1889,10 @@ BOOL LLItemBridge::removeItem() // we can't do this check because we may have items in a folder somewhere that is // not yet in memory, so we don't want false negatives. (If disabled, then we // know we only have links in the Outfits folder which we explicitly fetch.) - if (!InventoryLinksEnabled()) +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-06-01 (Catznip-2.2.0a) | Added: Catznip-2.0.1a + // Users move folders around and reuse links that way... if we know something has links then it's just bad not to warn them :| +// [/SL:KB] +// if (!InventoryLinksEnabled()) { if (!item->getIsLinkType()) { @@ -1873,13 +1953,26 @@ BOOL LLItemBridge::isItemCopyable() const return FALSE; }*/ - // You can never copy a link. - if (item->getIsLinkType()) +// // You can never copy a link. +// if (item->getIsLinkType()) +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + // We'll allow copying a link if: + // - its target is available + // - it doesn't point to another link [see LLViewerInventoryItem::getLinkedItem() which returns NULL in that case] + if (item->getIsLinkType() && !item->getLinkedItem()) +// [/SL:KB] { return FALSE; } - return item->getPermissions().allowCopyBy(gAgent.getID()) || InventoryLinksEnabled(); +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + // User can copy the item if: + // - the item (or its target in the case of a link) is "copy" + // - and/or if the item (or its target in the case of a link) has a linkable asset type + // NOTE: we do *not* want to return TRUE on everything like LL seems to do in SL-2.1.0 because not all types are "linkable" + return (item->getPermissions().allowCopyBy(gAgent.getID())) || (LLAssetType::lookupCanLink(item->getType())); +// [/SL:KB] +// return item->getPermissions().allowCopyBy(gAgent.getID()) || InventoryLinksEnabled(); } return FALSE; } @@ -1952,7 +2045,7 @@ BOOL LLFolderBridge::isItemRemovable() const return FALSE; } - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); LLFolderViewFolder* folderp = dynamic_cast(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); if (folderp) { @@ -2824,6 +2917,11 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) pasteFromClipboard(); return; } + else if ("paste_copies" == action) + { + pasteFromClipboard(true); + return; + } else if ("paste_link" == action) { pasteLinkFromClipboard(); @@ -3062,7 +3160,7 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re return FALSE; } -void LLFolderBridge::pasteFromClipboard() +void LLFolderBridge::pasteFromClipboard(bool only_copies) { LLInventoryModel* model = getInventoryModel(); if(model && isClipboardPasteable()) @@ -3135,7 +3233,7 @@ void LLFolderBridge::pasteFromClipboard() dropToOutfit(item, move_is_into_current_outfit); } } - else if(LLInventoryClipboard::instance().isCutMode()) + else if (!only_copies && LLInventoryClipboard::instance().isCutMode()) { // Do a move to "paste" a "cut" // move_inventory_item() is not enough, as we have to update inventory locally too @@ -3160,6 +3258,11 @@ void LLFolderBridge::pasteFromClipboard() } else { + if (only_copies) + { + item = model->getLinkedItem(item_id); + obj = model->getObject(item->getUUID()); + } // Do a "copy" to "paste" a regular copy clipboard if (LLAssetType::AT_CATEGORY == obj->getType()) { @@ -3170,6 +3273,19 @@ void LLFolderBridge::pasteFromClipboard() copy_inventory_category(model, vicat, parent_id); } } +// [SL:KB] - Patch: Inventory-Links | Checked: 2010-04-12 (Catznip-2.2.0a) | Added: Catznip-2.0.0a + else if (!only_copies && LLAssetType::lookupIsLinkType(item->getActualType())) + { + link_inventory_item( + gAgent.getID(), + item->getLinkedUUID(), + parent_id, + item->getName(), + item->getDescription(), + item->getActualType(), + LLPointer(NULL)); + } +// [/SL:KB] else { copy_inventory_item( @@ -3322,7 +3438,7 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) // Not sure what the right thing is to do here. if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) { - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); if(panel && !panel->getFilterWorn()) if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox or outbox { @@ -3603,7 +3719,7 @@ void LLFolderBridge::createNewCategory(void* user_data) { LLFolderBridge* bridge = (LLFolderBridge*)user_data; if(!bridge) return; - LLInventoryPanel* panel = dynamic_cast(bridge->mInventoryPanel.get()); + LLInventoryPanel* panel = bridge->mInventoryPanel.get(); if (!panel) return; LLInventoryModel* model = panel->getModel(); if(!model) return; @@ -3797,7 +3913,7 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) // use callback to rearrange favorite landmarks after adding // to have new one placed before target (on which it was dropped). See EXT-4312. LLPointer cb = new AddFavoriteLandmarkCallback(); - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; if (drag_over_item && drag_over_item->getListener()) { @@ -3846,6 +3962,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, if(!isAgentInventory()) return FALSE; // cannot drag into library if (!isAgentAvatarValid()) return FALSE; + LLInventoryPanel* destination_panel = mInventoryPanel.get(); + if (!destination_panel) return false; + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); @@ -3977,6 +4096,15 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } } + LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + + // Check whether the item being dragged from active inventory panel + if (accept && active_panel) + { + LLFolderView* active_folder_view = active_panel->getRootFolder(); + if (!active_folder_view) return false; + } + if(accept && drop) { if (inv_item->getType() == LLAssetType::AT_GESTURE @@ -3986,14 +4114,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } // 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). - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); - if (active_panel) + if (active_panel && (destination_panel != active_panel)) { - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - if (active_panel && (panel != active_panel)) - { active_panel->unSelectAll(); - } } // FAVORITES folder @@ -4156,6 +4279,15 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, accept = can_move_to_landmarks(inv_item); } + LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + + // Check whether the item being dragged from the library + if (accept && active_panel) + { + LLFolderView* active_folder_view = active_panel->getRootFolder(); + if (!active_folder_view) return false; + } + if (accept && drop) { // FAVORITES folder @@ -4558,7 +4690,7 @@ LLCallingCardBridge::~LLCallingCardBridge() void LLCallingCardBridge::refreshFolderViewItem() { - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; if (itemp) { @@ -5215,9 +5347,10 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) void LLObjectBridge::openItem() { + static LLCachedControl add(gSavedSettings, "LiruAddNotReplace"); // object double-click action is to wear/unwear object performAction(getInventoryModel(), - get_is_item_worn(mUUID) ? "detach" : "attach"); + get_is_item_worn(mUUID) ? "detach" : (add ? "wear_add" : "attach")); } std::string LLObjectBridge::getLabelSuffix() const @@ -6671,10 +6804,14 @@ void LLWearableBridgeAction::wearOnAvatar() { // TODO: investigate wearables may not be loaded at this point EXT-8231 + static LLCachedControl add(gSavedSettings, "LiruAddNotReplace"); LLViewerInventoryItem* item = getItem(); if(item) { - LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true); + if (get_is_item_worn(item)) + LLAppearanceMgr::instance().removeItemFromAvatar(item->getUUID()); + else + LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, !add); } } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 8b386710d..c5e26b752 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -108,8 +108,9 @@ public: virtual BOOL copyToClipboard() const; virtual void cutToClipboard(); virtual BOOL isClipboardPasteable() const; + bool isClipboardPasteableAsCopy() const; virtual BOOL isClipboardPasteableAsLink() const; - virtual void pasteFromClipboard() {} + virtual void pasteFromClipboard(bool only_copies = false) {} virtual void pasteLinkFromClipboard() {} void getClipboardEntries(bool show_asset_id, menuentry_vec_t &items, menuentry_vec_t &disabled_items, U32 flags); @@ -160,7 +161,7 @@ protected: BOOL restamp); void removeBatchNoCheck(LLDynamicArray& batch); protected: - LLHandle mInventoryPanel; + LLHandle mInventoryPanel; LLFolderView* mRoot; const LLUUID mUUID; // item id LLInventoryType::EType mInvType; @@ -261,7 +262,7 @@ public: BOOL removeSystemFolder(); bool removeItemResponse(const LLSD& notification, const LLSD& response); - virtual void pasteFromClipboard(); + virtual void pasteFromClipboard(bool only_copies = false); virtual void pasteLinkFromClipboard(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual BOOL hasChildren() const; diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 330e8d3d2..f1ae05685 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -130,6 +130,8 @@ public: LLScrollableContainerView* getScrollableContainer() { return mScroller; } void onSelectionChange(const std::deque &items, BOOL user_action); + + LLHandle getInventoryPanelHandle() const { return getDerivedHandle(); } // DEBUG ONLY: static void dumpSelectionInformation(void* user_data); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index e80032239..192c5f531 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -88,11 +88,18 @@ std::string LLLogChat::timestamp(bool withdate) // it's daylight savings time there. timep = utc_to_pacific_time(utc_time, gPacificDaylightTime); + static LLCachedControl withseconds("SecondsInLog"); std::string text; if (withdate) - text = llformat("[%d/%02d/%02d %02d:%02d] ", (timep->tm_year-100)+2000, timep->tm_mon+1, timep->tm_mday, timep->tm_hour, timep->tm_min); + if (withseconds) + text = llformat("[%d-%02d-%02d %02d:%02d:%02d] ", (timep->tm_year-100)+2000, timep->tm_mon+1, timep->tm_mday, timep->tm_hour, timep->tm_min, timep->tm_sec); + else + text = llformat("[%d/%02d/%02d %02d:%02d] ", (timep->tm_year-100)+2000, timep->tm_mon+1, timep->tm_mday, timep->tm_hour, timep->tm_min); else - text = llformat("[%02d:%02d] ", timep->tm_hour, timep->tm_min); + if (withseconds) + text = llformat("[%02d:%02d:%02d] ", timep->tm_hour, timep->tm_min, timep->tm_sec); + else + text = llformat("[%02d:%02d] ", timep->tm_hour, timep->tm_min); return text; } diff --git a/indra/newview/llmakeoutfitdialog.cpp b/indra/newview/llmakeoutfitdialog.cpp new file mode 100644 index 000000000..b84e668b6 --- /dev/null +++ b/indra/newview/llmakeoutfitdialog.cpp @@ -0,0 +1,218 @@ +/** + * @file llmakeoutfitdialog.cpp + * @brief The Make Outfit Dialog, triggered by "Make Outfit" and similar UICtrls. + * + * $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 "llmakeoutfitdialog.h" + +#include "llagent.h" +#include "llappearancemgr.h" +#include "lluictrlfactory.h" +#include "llvoavatarself.h" + +#include "hippogridmanager.h" + +LLMakeOutfitDialog::LLMakeOutfitDialog(bool modal) : LLModalDialog(LLStringUtil::null, 515, 510, modal) +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_new_outfit_dialog.xml"); + + setCanClose(!modal); + setCanMinimize(!modal); + + // Build list of check boxes + for (S32 i = 0; i < LLWearableType::WT_COUNT; i++) + { + std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel((LLWearableType::EType)i); + mCheckBoxList.push_back(std::make_pair(name, i)); + // Hide undergarments from teens + if (gAgent.isTeen() && ((LLWearableType::WT_UNDERSHIRT == (LLWearableType::EType)i) || (LLWearableType::WT_UNDERPANTS == (LLWearableType::EType)i))) + { + childSetVisible(name, false); // Lest they know what's beyond their reach. + } + else + { + bool enabled = gAgentWearables.getWearableCount((LLWearableType::EType)i); // TODO: MULTI-WEARABLE + bool selected = enabled && (LLWearableType::WT_SHIRT <= i); // only select clothing by default + childSetEnabled(name, enabled); + childSetValue(name, selected); + } + } + + // NOTE: .xml needs to be updated if attachments are added or their names are changed! + LLVOAvatar* avatar = gAgentAvatarp; + if (avatar) + { + for (LLVOAvatar::attachment_map_t::iterator iter = avatar->mAttachmentPoints.begin(); iter != avatar->mAttachmentPoints.end();) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + S32 attachment_pt = curiter->first; + bool object_attached = (attachment->getNumObjects() > 0); + std::string name = std::string("checkbox_") + attachment->getName(); + mCheckBoxList.push_back(std::make_pair(name, attachment_pt)); + childSetEnabled(name, object_attached); + } + } + + if (!gHippoGridManager->getConnectedGrid()->supportsInvLinks()) + { + childSetEnabled("checkbox_use_links", false); + childSetValue("checkbox_use_links", false); + childSetEnabled("checkbox_use_outfits", false); + childSetValue("checkbox_use_outfits", false); + } + + getChild("Save")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::onSave, this)); + getChild("Cancel")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::close, this, _1)); + getChild("Check All")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::onCheckAll, this, true)); + getChild("Uncheck All")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::onCheckAll, this, false)); + getChild("checkbox_use_outfits")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::refresh, this)); + startModal(); +} + +//virtual +void LLMakeOutfitDialog::draw() +{ + bool one_or_more_items_selected = false; + for (S32 i = 0; i < (S32)mCheckBoxList.size(); i++) + { + if (childGetValue(mCheckBoxList[i].first).asBoolean()) + { + one_or_more_items_selected = true; + break; + } + } + childSetEnabled("Save", one_or_more_items_selected); + + LLModalDialog::draw(); +} + +BOOL LLMakeOutfitDialog::postBuild() +{ + refresh(); + return true; +} + +void LLMakeOutfitDialog::refresh() +{ + bool fUseOutfits = getUseOutfits(); + + for (S32 idxType = 0; idxType < LLWearableType::WT_COUNT; idxType++) + { + LLWearableType::EType wtType = (LLWearableType::EType)idxType; + if (LLAssetType::AT_BODYPART != LLWearableType::getAssetType(wtType)) + continue; + LLUICtrl* pCheckCtrl = getChild(std::string("checkbox_") + LLWearableType::getTypeLabel(wtType)); + if (!pCheckCtrl) + continue; + + pCheckCtrl->setEnabled(!fUseOutfits); + if (fUseOutfits) + pCheckCtrl->setValue(true); + } + childSetEnabled("checkbox_use_links", !fUseOutfits); +} + + +void LLMakeOutfitDialog::setWearableToInclude(S32 wearable, bool enabled, bool selected) +{ + LLWearableType::EType wtType = (LLWearableType::EType)wearable; + if (((0 <= wtType) && (wtType < LLWearableType::WT_COUNT)) && + ((LLAssetType::AT_BODYPART != LLWearableType::getAssetType(wtType)) || !getUseOutfits())) + { + std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel(wtType); + childSetEnabled(name, enabled); + childSetValue(name, selected); + } +} + +void LLMakeOutfitDialog::getIncludedItems(LLInventoryModel::item_array_t& item_list) +{ + LLInventoryModel::cat_array_t *cats; + LLInventoryModel::item_array_t *items; + gInventory.getDirectDescendentsOf(LLAppearanceMgr::instance().getCOF(), cats, items); + for (LLInventoryModel::item_array_t::const_iterator iter = items->begin(); iter != items->end(); ++iter) + { + LLViewerInventoryItem* item = (*iter); + if (!item) + continue; + if (item->isWearableType()) + { + LLWearableType::EType type = item->getWearableType(); + if (type < LLWearableType::WT_COUNT && childGetValue(mCheckBoxList[type].first).asBoolean()) + { + item_list.push_back(item); + } + } + else + { + LLViewerJointAttachment* attachment = gAgentAvatarp->getWornAttachmentPoint(item->getLinkedUUID()); + if (attachment && childGetValue(std::string("checkbox_")+attachment->getName()).asBoolean()) + { + item_list.push_back(item); + } + } + } +} + +void LLMakeOutfitDialog::onSave() +{ + std::string folder_name = childGetValue("name ed").asString(); + LLStringUtil::trim(folder_name); + if (!folder_name.empty()) + { + makeOutfit(folder_name); + close(); // destroys this object + } +} + +void LLMakeOutfitDialog::onCheckAll(bool check) +{ + for (S32 i = 0; i < (S32)(mCheckBoxList.size()); i++) + { + std::string name = mCheckBoxList[i].first; + if (childIsEnabled(name)) childSetValue(name, check); + } +} + +void LLMakeOutfitDialog::makeOutfit(const std::string folder_name) +{ + LLInventoryModel::item_array_t item_list; + getIncludedItems(item_list); + + // MULTI-WEARABLES TODO + if (getUseOutfits()) + LLAppearanceMgr::instance().makeNewOutfitLinks(folder_name, item_list); + else + LLAppearanceMgr::instance().makeNewOutfitLegacy(folder_name, item_list, getUseLinks()); +} + diff --git a/indra/newview/llmakeoutfitdialog.h b/indra/newview/llmakeoutfitdialog.h new file mode 100644 index 000000000..caed1ceef --- /dev/null +++ b/indra/newview/llmakeoutfitdialog.h @@ -0,0 +1,66 @@ +/** + * @file llmakeoutfitdialog.h + * @brief The Make Outfit Dialog, triggered by "Make Outfit" and similar UICtrls. + * + * $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 LLMAKEOUTFITDIALOG_H +#define LLMAKEOUTFITDIALOG_H + + +#include "llinventorymodel.h" +#include "llmodaldialog.h" + +class LLMakeOutfitDialog : public LLModalDialog +{ +private: + std::vector > mCheckBoxList; + +public: + LLMakeOutfitDialog(bool modal = true); + /*virtual*/ void draw(); + BOOL postBuild(); + void refresh(); + + void setWearableToInclude(S32 wearable, bool enabled, bool selected); //TODO: Call this when Wearables are added or removed to update the Dialog in !modal mode. + void onSave(); + void onCheckAll(bool check); + + //Accessors + void getIncludedItems(LLInventoryModel::item_array_t& item_list); + bool getUseOutfits() { return childGetValue("checkbox_use_outfits").asBoolean(); } + bool getUseLinks() { return childGetValue("checkbox_use_links").asBoolean(); } + //bool getRenameClothing() { return childGetValue("rename").asBoolean(); } + +protected: + void makeOutfit(const std::string folder_name); +}; + +#endif //LLMAKEOUTFITDIALOG_H + diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 304f00e4b..33baf4231 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1381,74 +1381,28 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) BOOL hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); projected_mouse -= snap_plane_center; - S32 snap_plane = 0; - - F32 dot = cam_to_snap_plane * constraint_axis; - if (llabs(dot) < 0.01f) - { - // looking at ring edge on, project onto view plane and check if mouse is past ring - getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); - projected_mouse -= snap_plane_center; - dot = projected_mouse * constraint_axis; - if (projected_mouse * constraint_axis > 0) - { - snap_plane = 1; - } - projected_mouse -= dot * constraint_axis; - } - else if (dot > 0.f) - { - // look for mouse position outside and in front of snap circle - if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) - { - snap_plane = 1; - } - } - else - { - // look for mouse position inside or in back of snap circle - if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) - { - snap_plane = 1; - } - } - - if (snap_plane == 0) - { - // try other plane - snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f)); - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - cam_to_snap_plane.setVec(1.f, 0.f, 0.f); - } - else - { - cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); - cam_to_snap_plane.normVec(); - } - - hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); - projected_mouse -= snap_plane_center; - - dot = cam_to_snap_plane * constraint_axis; + if (gSavedSettings.getBOOL("SnapEnabled")) { + S32 snap_plane = 0; + + F32 dot = cam_to_snap_plane * constraint_axis; if (llabs(dot) < 0.01f) { // looking at ring edge on, project onto view plane and check if mouse is past ring getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); projected_mouse -= snap_plane_center; dot = projected_mouse * constraint_axis; - if (projected_mouse * constraint_axis < 0) + if (projected_mouse * constraint_axis > 0) { - snap_plane = 2; + snap_plane = 1; } projected_mouse -= dot * constraint_axis; } - else if (dot < 0.f) + else if (dot > 0.f) { // look for mouse position outside and in front of snap circle if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) { - snap_plane = 2; + snap_plane = 1; } } else @@ -1456,78 +1410,136 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) // look for mouse position inside or in back of snap circle if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) { - snap_plane = 2; + snap_plane = 1; } } - } - - if (snap_plane > 0) - { - LLVector3 cam_at_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + + if (snap_plane == 0) { - cam_at_axis.setVec(1.f, 0.f, 0.f); + // try other plane + snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f)); + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + cam_to_snap_plane.setVec(1.f, 0.f, 0.f); + } + else + { + cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); + cam_to_snap_plane.normVec(); + } + + hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); + projected_mouse -= snap_plane_center; + + dot = cam_to_snap_plane * constraint_axis; + if (llabs(dot) < 0.01f) + { + // looking at ring edge on, project onto view plane and check if mouse is past ring + getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); + projected_mouse -= snap_plane_center; + dot = projected_mouse * constraint_axis; + if (projected_mouse * constraint_axis < 0) + { + snap_plane = 2; + } + projected_mouse -= dot * constraint_axis; + } + else if (dot < 0.f) + { + // look for mouse position outside and in front of snap circle + if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) + { + snap_plane = 2; + } + } + else + { + // look for mouse position inside or in back of snap circle + if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) + { + snap_plane = 2; + } + } } - else - { - cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent(); - cam_at_axis.normVec(); - } - - // first, project mouse onto screen plane at point tangent to rotation radius. - getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis); - // project that point onto rotation plane - projected_mouse -= snap_plane_center; - projected_mouse -= projected_vec(projected_mouse, constraint_axis); - - F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec()); - F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; - if (llabs(mouse_lateral_dist) > 0.01f) - { - mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - - (mouse_lateral_dist * mouse_lateral_dist)); - } - LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis); - projected_mouse -= mouse_depth * projected_camera_at; - - if (!mInSnapRegime) - { - mSmoothRotate = TRUE; - } - mInSnapRegime = TRUE; - // 0 to 360 deg - F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); - F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); - //fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f); - - LLVector3 object_axis; - getObjectAxisClosestToMouse(object_axis); - object_axis = object_axis * first_object_node->mSavedRotation; - - // project onto constraint plane - object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); - object_axis.normVec(); - - if (relative_mouse_angle < SNAP_ANGLE_DETENTE) + if (snap_plane > 0) { - F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); - angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + LLVector3 cam_at_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + cam_at_axis.setVec(1.f, 0.f, 0.f); + } + else + { + cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent(); + cam_at_axis.normVec(); + } + + // first, project mouse onto screen plane at point tangent to rotation radius. + getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis); + // project that point onto rotation plane + projected_mouse -= snap_plane_center; + projected_mouse -= projected_vec(projected_mouse, constraint_axis); + + F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec()); + F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; + if (llabs(mouse_lateral_dist) > 0.01f) + { + mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - + (mouse_lateral_dist * mouse_lateral_dist)); + } + LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis); + projected_mouse -= mouse_depth * projected_camera_at; + + if (!mInSnapRegime) + { + mSmoothRotate = TRUE; + } + mInSnapRegime = TRUE; + // 0 to 360 deg + F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); + + F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); + //fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f); + + LLVector3 object_axis; + getObjectAxisClosestToMouse(object_axis); + object_axis = object_axis * first_object_node->mSavedRotation; + + // project onto constraint plane + object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); + object_axis.normVec(); + + if (relative_mouse_angle < SNAP_ANGLE_DETENTE) + { + F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); + angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + } + else + { + angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + } + return LLQuaternion( -angle, constraint_axis ); } else { - angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + if (mInSnapRegime) + { + mSmoothRotate = TRUE; + } + mInSnapRegime = FALSE; } - return LLQuaternion( -angle, constraint_axis ); } - else - { + else { if (mInSnapRegime) { mSmoothRotate = TRUE; } mInSnapRegime = FALSE; - + } + + if (!mInSnapRegime) + { LLVector3 up_from_axis = mCenterToCamNorm % constraint_axis; up_from_axis.normVec(); LLVector3 cur_intersection; diff --git a/indra/newview/llmapresponders.cpp b/indra/newview/llmapresponders.cpp index cf0769bce..eaae3e450 100644 --- a/indra/newview/llmapresponders.cpp +++ b/indra/newview/llmapresponders.cpp @@ -38,6 +38,8 @@ #include "llviewertexturelist.h" #include "llworldmap.h" #include "llagent.h" +#include "llworldmapmessage.h" +#include "llsdserialize.h" //virtual void LLMapLayerResponder::result(const LLSD& result) @@ -45,22 +47,19 @@ void LLMapLayerResponder::result(const LLSD& result) llinfos << "LLMapLayerResponder::result from capabilities" << llendl; S32 agent_flags = result["AgentData"]["Flags"]; - - if (agent_flags != LLWorldMap::getInstance()->mCurrentMap) + U32 layer = flagsToLayer(agent_flags); + + if (layer != SIM_LAYER_COMPOSITE) { llwarns << "Invalid or out of date map image type returned!" << llendl; return; } LLUUID image_id; - //U32 left, right, top, bottom; - LLWorldMap::getInstance()->mMapLayers[agent_flags].clear(); - - bool use_web_map_tiles = LLWorldMap::useWebMapTiles(); + LLWorldMap::getInstance()->mMapLayers.clear(); LLSD::array_const_iterator iter; - BOOL adjust = FALSE; for(iter = result["LayerData"].beginArray(); iter != result["LayerData"].endArray(); ++iter) { const LLSD& layer_data = *iter; @@ -74,146 +73,12 @@ void LLMapLayerResponder::result(const LLSD& result) new_layer.LayerExtents.mTop = layer_data["Top"]; new_layer.LayerImageID = layer_data["ImageID"]; -// if (use_web_map_tiles) -// { -// new_layer.LayerImage = LLWorldMap::loadObjectsTile((U32)new_layer.LayerExtents.mLeft, (U32)new_layer.LayerExtents.mBottom); // no good... Maybe using of level 2 and higher web maps ? -// } -// else -// { - new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID); -// } + new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID); + gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); - F32 x_meters = F32(new_layer.LayerExtents.mLeft*REGION_WIDTH_UNITS); - F32 y_meters = F32(new_layer.LayerExtents.mBottom*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); + LLWorldMap::getInstance()->mMapLayers.push_back(new_layer); } - - LLWorldMap::getInstance()->mMapLoaded[agent_flags] = TRUE; - if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); - - /* - U32 agent_flags; - msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); - - if (agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES) - { - llwarns << "Invalid map image type returned! " << agent_flags << llendl; - return; - } - */ - - bool found_null_sim = false; - - adjust = FALSE; - if (result.has("MapBlocks")) - { - const LLSD& map_blocks = result["MapBlocks"]; - for (iter = map_blocks.beginArray(); iter != map_blocks.endArray(); ++iter) - { - const LLSD& map_block = *iter; - - S32 x_regions = map_block["X"]; - S32 y_regions = map_block["Y"]; - S32 x_size = map_block["SizeX"]; - S32 y_size = map_block["SizeY"]; - std::string name = map_block["Name"]; - S32 access = map_block["Access"]; - S32 region_flags = map_block["RegionFlags"]; - S32 water_height = map_block["WaterHeight"]; - LLUUID image_id = map_block["MapImageID"]; - - U32 x_meters = x_regions * REGION_WIDTH_UNITS; - U32 y_meters = y_regions * REGION_WIDTH_UNITS; - - if (access == 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 - { - adjust = LLWorldMap::getInstance()->extendAABB(x_meters, - y_meters, - x_meters+REGION_WIDTH_UNITS, - y_meters+REGION_WIDTH_UNITS) || adjust; - U64 handle = to_region_handle(x_meters, y_meters); - - // llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl; - - LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); - if (siminfo == NULL) - { - siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); - } - - siminfo->setName( name ); - siminfo->setAccess( access ); /*Flawfinder: ignore*/ - siminfo->setRegionFlags( region_flags ); - siminfo->setWaterHeight( (F32) water_height ); - siminfo->setMapImageID( image_id, agent_flags ); - siminfo->setSize((U16)x_size, (U16)y_size); - if (use_web_map_tiles) - { - siminfo->mCurrentImage = LLWorldMap::loadObjectsTile((U32)x_regions, (U32)y_regions); - } - else - { - siminfo->mCurrentImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap]); - } - siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); - gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get()); - - if (siminfo->mMapImageID[2].notNull()) - { - siminfo->mOverlayImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[2]); - } - 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->isDown()) - { - // 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 ); - } - } - } - } - } - } - if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); - gFloaterWorldMap->updateSims(found_null_sim); + LLWorldMap::getInstance()->mMapLoaded = true; } diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 47c8791c9..f9da070e2 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -41,24 +41,53 @@ // Helpers // +static std::string getLoginUriDomain() +{ + LLURI uri(gHippoGridManager->getConnectedGrid()->getLoginUri()); + std::string hostname = uri.hostName(); // Ie, "login..lindenlab.com" + if (hostname.substr(0, 6) == "login.") + { + hostname = hostname.substr(6); // ".lindenlab.com" + } + return hostname; +} + +// Apart from well-known cases, in general this function returns the domain of the loginUri (with the "login." stripped off). +// This should be correct for all SL BETA grids, assuming they have the form of "login..lindenlab.com", in which +// case it returns ".lindenlab.com". +// +// Well-known cases that deviate from this: +// agni --> "secondlife.com" +// damballah --> "secondlife-staging.com" +// static std::string getMarketplaceDomain() { - std::string domain = "secondlife.com"; + std::string domain; if (gHippoGridManager->getCurrentGrid()->isSecondLife()) { - if (!LLViewerLogin::getInstance()->isInProductionGrid()) + if (gHippoGridManager->getConnectedGrid()->isInProductionGrid()) { - domain = "secondlife.aditi.lindenlab.com"; + domain = "secondlife.com"; // agni + } + else + { + // SecondLife(tm) BETA grid. + // Using the login URI is a bit of a kludge, but it's the best we've got at the moment. + domain = utf8str_tolower(getLoginUriDomain()); // .lindenlab.com; ie, "aditi.lindenlab.com". + llassert(domain.length() > 14 && domain.substr(domain.length() - 14) == ".lindenlab.com"); + if (domain == "damballah.lindenlab.com") + { + domain = "secondlife-staging.com"; + } } } else { // TODO: Find out if OpenSim, and Avination adopted any outbox stuffs, if so code HippoGridManager for this // Aurora grid has not. - // For now, reset domain on other grids, so we don't harass LL web services. - domain = ""; //gHippoGridManager->getCurrentGrid()->getMarketPlaceDomain(); + // For now, set domain on other grids to the loginUri domain, so we don't harass LL web services. + domain = getLoginUriDomain(); //gHippoGridManager->getCurrentGrid()->getMarketPlaceDomain(); } - return domain; } @@ -167,14 +196,22 @@ namespace LLMarketplaceImport public: AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return MPImportGetResponder_timeout; } - bool needsHeaders(void) const { return true; } + /*virtual*/ bool followRedir(void) const { return true; } + /*virtual*/ bool needsHeaders(void) const { return true; } - void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers) + /*virtual*/ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers) { - std::string set_cookie_string; - if (headers.getFirstValue("set-cookie", set_cookie_string) && !set_cookie_string.empty()) + if (status == HTTP_OK) { - sMarketplaceCookie = set_cookie_string; + std::string value = get_cookie("_slm_session"); + if (!value.empty()) + { + sMarketplaceCookie = value; + } + else if (sMarketplaceCookie.empty()) + { + llwarns << "No such cookie \"_slm_session\" received!" << llendl; + } } } @@ -196,7 +233,7 @@ namespace LLMarketplaceImport { if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout" << llendl; + llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout (" << status << " / " << reason << ")." << llendl; } sMarketplaceCookie.clear(); @@ -342,7 +379,7 @@ namespace LLMarketplaceImport // Interface class // -//static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 300.0f; //1.0f; +static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 1.0f; //static void LLMarketplaceInventoryImporter::update() @@ -353,7 +390,7 @@ void LLMarketplaceInventoryImporter::update() if (update_timer.hasExpired()) { LLMarketplaceInventoryImporter::instance().updateImport(); - static LLCachedControl MARKET_IMPORTER_UPDATE_FREQUENCY("MarketImporterUpdateFreq", 10.0f); + //static LLCachedControl MARKET_IMPORTER_UPDATE_FREQUENCY("MarketImporterUpdateFreq", 1.0f); update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY); } } diff --git a/indra/newview/llmediaremotectrl.cpp b/indra/newview/llmediaremotectrl.cpp index 50d3276b8..e5fa89e16 100644 --- a/indra/newview/llmediaremotectrl.cpp +++ b/indra/newview/llmediaremotectrl.cpp @@ -35,6 +35,8 @@ #include "llmediaremotectrl.h" #include "llaudioengine.h" +#include "llchat.h" +#include "llfloaterchat.h" #include "lliconctrl.h" #include "llmimetypes.h" #include "lloverlaybar.h" @@ -53,6 +55,7 @@ // static LLRegisterWidget r("media_remote"); +static std::string sLastTooltip; LLMediaRemoteCtrl::LLMediaRemoteCtrl() { @@ -263,10 +266,22 @@ void LLMediaRemoteCtrl::enableMediaButtons() if(artist.isDefined() && title.isDefined()) info_text = artist.asString() + " -- " + title.asString(); else if(title.isDefined()) - info_text = std::string("Title: ") + title.asString(); + info_text = getString("Title") + ": " + title.asString(); else if(artist.isDefined()) - info_text = std::string("Artist: ") + artist.asString(); - music_pause_btn->setToolTip(info_text); + info_text = getString("Artist") + ": " + artist.asString(); + if(music_pause_btn->getToolTip() != info_text) //Has info_text changed since last call? + { + music_pause_btn->setToolTip(info_text); + static LLCachedControl announce_stream_metadata("AnnounceStreamMetadata"); + if(announce_stream_metadata && info_text != sLastTooltip && info_text != "Loading...") //Are we announcing? Don't annoounce what we've last announced. Don't announce Loading. + { + sLastTooltip = info_text; + LLChat chat; + chat.mText = getString("Now_playing") + " " + info_text; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::addChat(chat); + } + } } else music_pause_btn->setToolTip(mCachedPauseTip); diff --git a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp new file mode 100644 index 000000000..0dea26fb7 --- /dev/null +++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp @@ -0,0 +1,237 @@ +/** +* @file llmenuoptionpathfindingrebakenavmesh.cpp +* @brief Implementation of llmenuoptionpathfindingrebakenavmesh +* @author Prep@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + + +#include "llviewerprecompiledheaders.h" + +#include "llmenuoptionpathfindingrebakenavmesh.h" + +#include +#include + +#include "llagent.h" +#include "llenvmanager.h" +#include "llnotificationsutil.h" +#include "llpathfindingmanager.h" +#include "llpathfindingnavmesh.h" +#include "llpathfindingnavmeshstatus.h" +#include "llviewerregion.h" + +LLMenuOptionPathfindingRebakeNavmesh::LLMenuOptionPathfindingRebakeNavmesh() + : LLSingleton(), + mIsInitialized(false), + mCanRebakeRegion(false), + mRebakeNavMeshMode(kRebakeNavMesh_Default), + mNavMeshSlot(), + mRegionCrossingSlot(), + mAgentStateSlot() +{ +} + +LLMenuOptionPathfindingRebakeNavmesh::~LLMenuOptionPathfindingRebakeNavmesh() +{ + if (mRebakeNavMeshMode == kRebakeNavMesh_RequestSent) + { + LL_WARNS("navmeshRebaking") << "During destruction of the LLMenuOptionPathfindingRebakeNavmesh " + << "singleton, the mode indicates that a request has been sent for which a response has yet " + << "to be received. This could contribute to a crash on exit." << LL_ENDL; + } + + llassert(!mIsInitialized); + if (mIsInitialized) + { + quit(); + } +} + +void LLMenuOptionPathfindingRebakeNavmesh::initialize() +{ + if (!mIsInitialized) + { + mIsInitialized = true; + + setMode(kRebakeNavMesh_Default); + + createNavMeshStatusListenerForCurrentRegion(); + + if ( !mRegionCrossingSlot.connected() ) + { + mRegionCrossingSlot = LLEnvManagerNew::getInstance()->setRegionChangeCallback(boost::bind(&LLMenuOptionPathfindingRebakeNavmesh::handleRegionBoundaryCrossed, this)); + } + + if (!mAgentStateSlot.connected()) + { + mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLMenuOptionPathfindingRebakeNavmesh::handleAgentState, this, _1)); + } + LLPathfindingManager::getInstance()->requestGetAgentState(); + } +} + +void LLMenuOptionPathfindingRebakeNavmesh::quit() +{ + llassert(mIsInitialized); + if (mIsInitialized) + { + if (mNavMeshSlot.connected()) + { + mNavMeshSlot.disconnect(); + } + + if (mRegionCrossingSlot.connected()) + { + mRegionCrossingSlot.disconnect(); + } + + if (mAgentStateSlot.connected()) + { + mAgentStateSlot.disconnect(); + } + + mIsInitialized = false; + } +} + +bool LLMenuOptionPathfindingRebakeNavmesh::canRebakeRegion() const +{ + if (!mIsInitialized) + { + LL_ERRS("navmeshRebaking") << "LLMenuOptionPathfindingRebakeNavmesh class has not been initialized " + << "when the ability to rebake navmesh is being requested." << LL_ENDL; + } + return mCanRebakeRegion; +} + +LLMenuOptionPathfindingRebakeNavmesh::ERebakeNavMeshMode LLMenuOptionPathfindingRebakeNavmesh::getMode() const +{ + if (!mIsInitialized) + { + LL_ERRS("navmeshRebaking") << "LLMenuOptionPathfindingRebakeNavmesh class has not been initialized " + << "when the mode is being requested." << LL_ENDL; + } + return mRebakeNavMeshMode; +} + +void LLMenuOptionPathfindingRebakeNavmesh::sendRequestRebakeNavmesh() +{ + if (!mIsInitialized) + { + LL_ERRS("navmeshRebaking") << "LLMenuOptionPathfindingRebakeNavmesh class has not been initialized " + << "when the request is being made to rebake the navmesh." << LL_ENDL; + } + else + { + if (!canRebakeRegion()) + { + LL_WARNS("navmeshRebaking") << "attempting to rebake navmesh when user does not have permissions " + << "on this region" << LL_ENDL; + } + if (getMode() != kRebakeNavMesh_Available) + { + LL_WARNS("navmeshRebaking") << "attempting to rebake navmesh when mode is not available" + << LL_ENDL; + } + + setMode(kRebakeNavMesh_RequestSent); + LLPathfindingManager::getInstance()->requestRebakeNavMesh(boost::bind(&LLMenuOptionPathfindingRebakeNavmesh::handleRebakeNavMeshResponse, this, _1)); + } +} + +void LLMenuOptionPathfindingRebakeNavmesh::setMode(ERebakeNavMeshMode pRebakeNavMeshMode) +{ + mRebakeNavMeshMode = pRebakeNavMeshMode; +} + +void LLMenuOptionPathfindingRebakeNavmesh::handleAgentState(BOOL pCanRebakeRegion) +{ + llassert(mIsInitialized); + mCanRebakeRegion = pCanRebakeRegion; +} + +void LLMenuOptionPathfindingRebakeNavmesh::handleRebakeNavMeshResponse(bool pResponseStatus) +{ + llassert(mIsInitialized); + if (getMode() == kRebakeNavMesh_RequestSent) + { + setMode(pResponseStatus ? kRebakeNavMesh_InProgress : kRebakeNavMesh_Default); + } + + if (!pResponseStatus) + { + LLNotificationsUtil::add("PathfindingCannotRebakeNavmesh"); + } +} + +void LLMenuOptionPathfindingRebakeNavmesh::handleNavMeshStatus(const LLPathfindingNavMeshStatus &pNavMeshStatus) +{ + llassert(mIsInitialized); + ERebakeNavMeshMode rebakeNavMeshMode = kRebakeNavMesh_Default; + if (pNavMeshStatus.isValid()) + { + switch (pNavMeshStatus.getStatus()) + { + case LLPathfindingNavMeshStatus::kPending : + case LLPathfindingNavMeshStatus::kRepending : + rebakeNavMeshMode = kRebakeNavMesh_Available; + break; + case LLPathfindingNavMeshStatus::kBuilding : + rebakeNavMeshMode = kRebakeNavMesh_InProgress; + break; + case LLPathfindingNavMeshStatus::kComplete : + rebakeNavMeshMode = kRebakeNavMesh_NotAvailable; + break; + default : + rebakeNavMeshMode = kRebakeNavMesh_Default; + llassert(0); + break; + } + } + + setMode(rebakeNavMeshMode); +} + +void LLMenuOptionPathfindingRebakeNavmesh::handleRegionBoundaryCrossed() +{ + llassert(mIsInitialized); + createNavMeshStatusListenerForCurrentRegion(); + mCanRebakeRegion = FALSE; + LLPathfindingManager::getInstance()->requestGetAgentState(); +} + +void LLMenuOptionPathfindingRebakeNavmesh::createNavMeshStatusListenerForCurrentRegion() +{ + if (mNavMeshSlot.connected()) + { + mNavMeshSlot.disconnect(); + } + + LLViewerRegion *currentRegion = gAgent.getRegion(); + if (currentRegion != NULL) + { + mNavMeshSlot = LLPathfindingManager::getInstance()->registerNavMeshListenerForRegion(currentRegion, boost::bind(&LLMenuOptionPathfindingRebakeNavmesh::handleNavMeshStatus, this, _2)); + LLPathfindingManager::getInstance()->requestGetNavMeshForRegion(currentRegion, true); + } +} diff --git a/indra/newview/llpanelpathfindingrebakenavmesh.h b/indra/newview/llmenuoptionpathfindingrebakenavmesh.h similarity index 63% rename from indra/newview/llpanelpathfindingrebakenavmesh.h rename to indra/newview/llmenuoptionpathfindingrebakenavmesh.h index 5aa1c68d8..7b1d2873b 100644 --- a/indra/newview/llpanelpathfindingrebakenavmesh.h +++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.h @@ -1,6 +1,6 @@ /** -* @file llpanelpathfindingrebakenavmesh.h -* @brief Header file for llpanelpathfindingrebakenavmesh +* @file llmenuoptionpathfindingrebakenavmesh.h +* @brief Header file for llmenuoptionpathfindingrebakenavmesh * @author Prep@lindenlab.com * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ @@ -24,34 +24,22 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LL_LLPANELPATHFINDINGREBAKENAVMESH_H -#define LL_LLPANELPATHFINDINGREBAKENAVMESH_H +#ifndef LL_LLMENUOPTIONPATHFINDINGREBAKENAVMESH_H +#define LL_LLMENUOPTIONPATHFINDINGREBAKENAVMESH_H #include -#include "llpanel.h" #include "llpathfindingmanager.h" #include "llpathfindingnavmesh.h" +#include "llsingleton.h" -class LLButton; class LLPathfindingNavMeshStatus; -class LLPanelPathfindingRebakeNavmesh : public LLPanel +class LLMenuOptionPathfindingRebakeNavmesh : public LLSingleton { - - LOG_CLASS(LLPanelPathfindingRebakeNavmesh); + LOG_CLASS(LLMenuOptionPathfindingRebakeNavmesh); public: - static LLPanelPathfindingRebakeNavmesh* getInstance(); - - virtual BOOL postBuild(); - - virtual void draw(); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen); - -protected: - -private: typedef enum { kRebakeNavMesh_Available, @@ -61,15 +49,21 @@ private: kRebakeNavMesh_Default = kRebakeNavMesh_NotAvailable } ERebakeNavMeshMode; - LLPanelPathfindingRebakeNavmesh(); - virtual ~LLPanelPathfindingRebakeNavmesh(); + LLMenuOptionPathfindingRebakeNavmesh(); + virtual ~LLMenuOptionPathfindingRebakeNavmesh(); - static LLPanelPathfindingRebakeNavmesh* getPanel(); + void initialize(); + void quit(); - void setMode(ERebakeNavMeshMode pRebakeNavMeshMode); + bool canRebakeRegion() const; ERebakeNavMeshMode getMode() const; - void onNavMeshRebakeClick(); + void sendRequestRebakeNavmesh(); + +protected: + +private: + void setMode(ERebakeNavMeshMode pRebakeNavMeshMode); void handleAgentState(BOOL pCanRebakeRegion); void handleRebakeNavMeshResponse(bool pResponseStatus); @@ -78,19 +72,14 @@ private: void createNavMeshStatusListenerForCurrentRegion(); - bool doDraw() const; - void updatePosition(); + bool mIsInitialized; - BOOL mCanRebakeRegion; + bool mCanRebakeRegion; ERebakeNavMeshMode mRebakeNavMeshMode; - LLButton* mNavMeshRebakeButton; - LLButton* mNavMeshSendingButton; - LLButton* mNavMeshBakingButton; - LLPathfindingNavMesh::navmesh_slot_t mNavMeshSlot; boost::signals2::connection mRegionCrossingSlot; LLPathfindingManager::agent_state_slot_t mAgentStateSlot; }; -#endif // LL_LLPANELPATHFINDINGREBAKENAVMESH_H +#endif // LL_LLMENUOPTIONPATHFINDINGREBAKENAVMESH_H diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index efeb7c557..3ce3eb188 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -295,6 +295,23 @@ BOOL LLMuteList::isLinden(const std::string& name) const return last_name == "Linden"; } +static LLVOAvatar* find_avatar(const LLUUID& id) +{ + LLViewerObject *obj = gObjectList.findObject(id); + while (obj && obj->isAttachment()) + { + obj = (LLViewerObject *)obj->getParent(); + } + + if (obj && obj->isAvatar()) + { + return (LLVOAvatar*)obj; + } + else + { + return NULL; + } +} BOOL LLMuteList::add(const LLMute& mute, U32 flags) { @@ -391,6 +408,12 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags) LLViewerPartSim::getInstance()->clearParticlesByOwnerID(localmute.mID); } } + //mute local lights that are attached to the avatar + LLVOAvatar *avatarp = find_avatar(localmute.mID); + if (avatarp) + { + LLPipeline::removeMutedAVsLights(avatarp); + } return TRUE; } } diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 60eafcd4a..0ec781e40 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -32,13 +32,16 @@ #include "llviewerprecompiledheaders.h" +#include "llnamelistctrl.h" + #include -#include "llnamelistctrl.h" +#include "llavatarnamecache.h" #include "llcachename.h" #include "llagent.h" #include "llinventory.h" +#include "lltrans.h" static LLRegisterWidget r("name_list"); @@ -51,12 +54,14 @@ LLNameListCtrl::LLNameListCtrl(const std::string& name, void* userdata, BOOL allow_multiple_selection, BOOL draw_border, + bool draw_heading, S32 name_column_index, const std::string& tooltip) : LLScrollListCtrl(name, rect, cb, userdata, allow_multiple_selection, - draw_border), + draw_border,draw_heading), mNameColumnIndex(name_column_index), - mAllowCallingCardDrop(FALSE) + mAllowCallingCardDrop(FALSE), + mShortNames(FALSE) { setToolTip(tooltip); LLNameListCtrl::sInstances.insert(this); @@ -71,19 +76,22 @@ LLNameListCtrl::~LLNameListCtrl() // public -BOOL LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, - BOOL enabled, std::string const& suffix) +LLScrollListItem* LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, + BOOL enabled, const std::string& suffix) { //llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl; - std::string fullname; - BOOL result = gCacheName->getFullName(agent_id, fullname); - - fullname.append(suffix); - - addStringUUIDItem(fullname, agent_id, pos, enabled); - - return result; + LLSD item; + item["id"] = agent_id; + item["enabled"] = enabled; + item["target"] = INDIVIDUAL; + item["suffix"] = suffix; + LLSD& column = item["columns"][0]; + column["value"] = ""; + column["font"] = "SANSSERIF"; + column["column"] = "name"; + + return addNameItemRow(item, pos); } // virtual, public @@ -134,79 +142,99 @@ BOOL LLNameListCtrl::handleDragAndDrop( return handled; } + // public void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos, BOOL enabled) { - //llinfos << "LLNameListCtrl::addGroupNameItem " << group_id << llendl; - std::string group_name; - gCacheName->getGroupName(group_id, group_name); - addStringUUIDItem(group_name, group_id, pos, enabled); + LLSD item; + item["id"] = group_id; + item["enabled"] = enabled; + item["target"] = GROUP; + LLSD& column = item["columns"][0]; + column["value"] = ""; + column["font"] = "SANSSERIF"; + column["column"] = "name"; + + addNameItemRow(item, pos); } // public -void LLNameListCtrl::addGroupNameItem(LLScrollListItem* item, EAddPosition pos) - +void LLNameListCtrl::addGroupNameItem(LLSD& item, EAddPosition pos) { - //llinfos << "LLNameListCtrl::addGroupNameItem " << item->getUUID() << llendl; - - std::string group_name; - gCacheName->getGroupName(item->getUUID(), group_name); - - LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex); - ((LLScrollListText*)cell)->setText( std::string(group_name) ); - - addItem(item, pos); + item["target"] = GROUP; + addNameItemRow(item, pos); } -BOOL LLNameListCtrl::addNameItem(LLScrollListItem* item, EAddPosition pos) +LLScrollListItem* LLNameListCtrl::addNameItem(LLSD& item, EAddPosition pos) { - //llinfos << "LLNameListCtrl::addNameItem " << item->getUUID() << llendl; - - std::string fullname; - BOOL result = gCacheName->getFullName(item->getUUID(), fullname); - - LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex); - ((LLScrollListText*)cell)->setText( fullname ); - - addItem(item, pos); - - // this column is resizable - LLScrollListColumn* columnp = getColumn(mNameColumnIndex); - if (columnp && columnp->mHeader) - { - columnp->mHeader->setHasResizableElement(TRUE); - } - - return result; + item["target"] = INDIVIDUAL; + return addNameItemRow(item, pos); } LLScrollListItem* LLNameListCtrl::addElement(const LLSD& value, EAddPosition pos, void* userdata) { + return addNameItemRow(value, pos, userdata); +} +LLScrollListItem* LLNameListCtrl::addNameItemRow(const LLSD& value, EAddPosition pos, void* userdata) +{ + LLScrollListItem* item = LLScrollListCtrl::addElement(value, pos, userdata); + if (!item) return NULL; + + LLUUID id = item->getUUID(); // use supplied name by default std::string fullname = value["name"].asString(); - if (value["target"].asString() == "GROUP") + switch(value["target"].asInteger()) { - gCacheName->getGroupName(item->getUUID(), fullname); + case GROUP: + gCacheName->getGroupName(id, fullname); // fullname will be "nobody" if group not found - } - else if (value["target"].asString() == "SPECIAL") - { + break; + case SPECIAL: // just use supplied name - } - else // normal resident + break; + case INDIVIDUAL: { - std::string name; - if (gCacheName->getFullName(item->getUUID(), name)) + LLAvatarName av_name; + if (id.isNull()) { - fullname = name; + fullname = LLTrans::getString("AvatarNameNobody"); } + else if (LLAvatarNameCache::get(id, &av_name)) + { + if (mShortNames) + fullname = av_name.mDisplayName; + else + fullname = av_name.getCompleteName(); + } + else + { + fullname = " ( " + LLTrans::getString("LoadingData") + " ) "; + // ...schedule a callback + LLAvatarNameCache::get(id, + boost::bind(&LLNameListCtrl::onAvatarNameCache, + this, _1, _2, item->getHandle())); + } + break; + } + default: + break; } - LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex); - ((LLScrollListText*)cell)->setText( fullname ); + // Append optional suffix. + std::string suffix = value["suffix"]; + if(!suffix.empty()) + { + fullname.append(suffix); + } + + LLScrollListCell* cell = item->getColumn(mNameColumnIndex); + if (cell && !fullname.empty() && cell->getValue().asString().empty()) + { + cell->setValue(fullname); + } dirtyColumns(); @@ -223,54 +251,53 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& value, EAddPosition pos // public void LLNameListCtrl::removeNameItem(const LLUUID& agent_id) { - BOOL item_exists = selectByID( agent_id ); - if(item_exists) + // Find the item specified with agent_id. + S32 idx = -1; + for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++) { - S32 index = getItemIndex(getFirstSelected()); - if(index >= 0) + LLScrollListItem* item = *it; + if (item->getUUID() == agent_id) { - deleteSingleItem(index); + idx = getItemIndex(item); + break; } } + + // Remove it. + if (idx >= 0) + { + selectNthItem(idx); // not sure whether this is needed, taken from previous implementation + deleteSingleItem(idx); + } } -// public -void LLNameListCtrl::refresh(const LLUUID& agent_id, const std::string& full_name) +void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, + const LLAvatarName& av_name, + LLHandle item) { - //llinfos << "LLNameListCtrl::refresh " << id << " '" << first << " " - // << last << "'" << llendl; + std::string name; + if (mShortNames) + name = av_name.mDisplayName; + else + name = av_name.getCompleteName(); - - // TODO: scan items for that ID, fix if necessary - item_list::iterator iter; - for (iter = getItemList().begin(); iter != getItemList().end(); iter++) + LLScrollListItem* list_item = item.get(); + if (list_item && list_item->getUUID() == agent_id) { - LLScrollListItem* item = *iter; - if (item->getUUID() == agent_id) + LLScrollListCell* cell = list_item->getColumn(mNameColumnIndex); + if (cell) { - LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex); - if (cell) - { - ((LLScrollListText*)cell)->setText( full_name ); - } + cell->setValue(name); + setNeedsSort(); } } dirtyColumns(); } - -// static -void LLNameListCtrl::refreshAll(const LLUUID& id, const std::string& full_name) +void LLNameListCtrl::sortByName(BOOL ascending) { - std::set::iterator it; - for (it = LLNameListCtrl::sInstances.begin(); - it != LLNameListCtrl::sInstances.end(); - ++it) - { - LLNameListCtrl* ctrl = *it; - ctrl->refresh(id, full_name); - } + sortByColumnIndex(mNameColumnIndex,ascending); } // virtual @@ -320,9 +347,9 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto NULL, multi_select, draw_border, - name_column_index); - - name_list->setDisplayHeading(draw_heading); + draw_heading, + name_column_index + ); if (node->hasAttribute("heading_height")) { S32 heading_height; @@ -439,7 +466,7 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto while(token_iter != tokens.end()) { const std::string& line = *token_iter; - name_list->addCommentText(line); + name_list->setCommentText(line); ++token_iter; } diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 0ff74423d..8a4f4141d 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -37,17 +37,26 @@ #include "llscrolllistctrl.h" +class LLAvatarName; class LLNameListCtrl -: public LLScrollListCtrl +: public LLScrollListCtrl, public LLInstanceTracker { public: + typedef enum e_name_type + { + INDIVIDUAL, + GROUP, + SPECIAL + } ENameType; + LLNameListCtrl(const std::string& name, const LLRect& rect, LLUICtrlCallback callback, void* userdata, BOOL allow_multiple_selection, BOOL draw_border = TRUE, + bool draw_heading = false, S32 name_column_index = 0, const std::string& tooltip = LLStringUtil::null); virtual ~LLNameListCtrl(); @@ -57,36 +66,38 @@ public: // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. - BOOL addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM, + LLScrollListItem* addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, std::string const& suffix = LLStringUtil::null); - BOOL addNameItem(LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM); + LLScrollListItem* addNameItem(LLSD& item, EAddPosition pos = ADD_BOTTOM); - virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); + /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); + LLScrollListItem* addNameItemRow(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. void addGroupNameItem(const LLUUID& group_id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); - void addGroupNameItem(LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM); + + void addGroupNameItem(LLSD& item, EAddPosition pos = ADD_BOTTOM); void removeNameItem(const LLUUID& agent_id); - void refresh(const LLUUID& agent_id, const std::string& full_name); - - static void refreshAll(const LLUUID& id, const std::string& full_name); - - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + // LLView interface + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg); void setAllowCallingCardDrop(BOOL b) { mAllowCallingCardDrop = b; } + void sortByName(BOOL ascending); private: static std::set sInstances; + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, LLHandle item); S32 mNameColumnIndex; BOOL mAllowCallingCardDrop; + bool mShortNames; // display name only, no SLID }; #endif diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 86294d46b..724b15c94 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -381,27 +381,29 @@ void LLNetMap::draw() LLWorld::getInstance()->getAvatars(&avatar_ids, &positions); for(U32 i=0; igetFullName(avatar_ids[i], avName); - if(LLMuteList::getInstance()->isMuted(avatar_ids[i])) + gCacheName->getFullName(id, avName); + if(LLMuteList::getInstance()->isMuted(id)) { avColor = muted_color; } - LLViewerRegion* avatar_region = LLWorld::getInstance()->getRegionFromPosGlobal(positions[i]); + LLViewerRegion* avatar_region = LLWorld::getInstance()->getRegionFromPosGlobal(pos); LLUUID estate_owner = avatar_region? avatar_region->getOwner() : LLUUID::null; // MOYMOD Minimap custom av colors. - boost::unordered_map::const_iterator it = mm_MarkerColors.find(avatar_ids[i]); + boost::unordered_map::const_iterator it = mm_MarkerColors.find(id); if(it != mm_MarkerColors.end()) { avColor = it->second; @@ -412,12 +414,12 @@ void LLNetMap::draw() avColor = linden_color; } //check if they are an estate owner at their current position - else if(estate_owner.notNull() && avatar_ids[i] == estate_owner) + else if(estate_owner.notNull() && id == estate_owner) { avColor = em_color; } //without these dots, SL would suck. - else if(is_agent_friend(avatar_ids[i])) + else if(is_agent_friend(id)) { avColor = friend_color; } @@ -432,8 +434,8 @@ void LLNetMap::draw() if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist) { closest_dist = dist_to_cursor; - mClosestAgentToCursor = avatar_ids[i]; - mClosestAgentPosition = positions[i]; + mClosestAgentToCursor = id; + mClosestAgentPosition = pos; } } @@ -627,37 +629,11 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rec { msg.assign(""); std::string fullname; - if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname)) + if(mClosestAgentToCursor.notNull() && LLAvatarNameCache::getPNSName(mClosestAgentToCursor, fullname)) { //msg.append(fullname); // [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b - // [Ansariel: Display name support] - // msg.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? fullname : RlvStrings::getAnonym(fullname) ); - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - { - msg.append(RlvStrings::getAnonym(fullname)); - } - else - { - if (LLAvatarNameCache::useDisplayNames()) - { - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(mClosestAgentToCursor, &avatar_name)) - { - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - if (phoenix_name_system == 2 || (phoenix_name_system == 1 && avatar_name.mIsDisplayNameDefault)) - { - fullname = avatar_name.mDisplayName; - } - else - { - fullname = avatar_name.getCompleteName(true); - } - } - } - msg.append(fullname); - } - // [/Ansariel: Display name support] + msg.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? fullname : RlvStrings::getAnonym(fullname) ); // [/RLVa:KB] msg.append("\n"); diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp index 5522f27a4..a834e7812 100644 --- a/indra/newview/lloverlaybar.cpp +++ b/indra/newview/lloverlaybar.cpp @@ -246,19 +246,23 @@ void LLOverlayBar::layoutButtons() if (state_buttons_panel->getVisible()) { - U32 required_width=0; + U32 button_count = 0; const child_list_t& view_list = *(state_buttons_panel->getChildList()); BOOST_FOREACH(LLView* viewp, view_list) { - required_width+=viewp->getRect().getWidth(); + if(!viewp->getEnabled()) + continue; + ++button_count; } + const S32 MAX_BAR_WIDTH = 600; + S32 bar_width = llclamp(state_buttons_panel->getRect().getWidth(), 0, MAX_BAR_WIDTH); - const S32 MAX_BAR_WIDTH = 800; - //const S32 MAX_BUTTON_WIDTH = 150; + // calculate button widths + const S32 MAX_BUTTON_WIDTH = 150; static LLCachedControl status_bar_pad("StatusBarPad",10); - S32 usable_bar_width = llclamp(state_buttons_panel->getRect().getWidth(), 0, MAX_BAR_WIDTH) - (view_list.size()-1) * status_bar_pad; - F32 element_scale = (F32)usable_bar_width / (F32)required_width; + S32 segment_width = llclamp(lltrunc((F32)(bar_width) / (F32)button_count), 0, MAX_BUTTON_WIDTH); + S32 btn_width = segment_width - status_bar_pad; // Evenly space all buttons, starting from left S32 left = 0; @@ -266,13 +270,14 @@ void LLOverlayBar::layoutButtons() BOOST_REVERSE_FOREACH(LLView* viewp, view_list) { + if(!viewp->getEnabled()) + continue; LLRect r = viewp->getRect(); - S32 new_width = r.getWidth() * element_scale; //if(dynamic_cast(viewp)) // new_width = llclamp(new_width,0,MAX_BUTTON_WIDTH); - r.setOriginAndSize(left, bottom, new_width, r.getHeight()); - viewp->setShape(r,false); - left += viewp->getRect().getWidth() + status_bar_pad; + r.setOriginAndSize(left, bottom, btn_width, r.getHeight()); + viewp->setRect(r); + left += segment_width; } } } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 14709805e..904a809c9 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -89,6 +89,7 @@ #include +#include @@ -167,21 +168,9 @@ void LLPanelAvatarSecondLife::updatePartnerName() { if (mPartnerID.notNull()) { - // [Ansariel: Display name support] - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(mPartnerID, &avatar_name)) - { - std::string name; - switch (gSavedSettings.getS32("PhoenixNameSystem")) - { - case 0 : name = avatar_name.getLegacyName(); break; - case 1 : name = (avatar_name.mIsDisplayNameDefault ? avatar_name.mDisplayName : avatar_name.getCompleteName()); break; - case 2 : name = avatar_name.mDisplayName; break; - default : name = avatar_name.getLegacyName(); break; - } + std::string name; + if (LLAvatarNameCache::getPNSName(mPartnerID, name)) childSetTextArg("partner_edit", "[NAME]", name); - } - // [/Ansariel: Display name support] childSetEnabled("partner_info", TRUE); } } @@ -202,9 +191,7 @@ void LLPanelAvatarSecondLife::clearControls() childSetValue("born", ""); childSetValue("acct", ""); - // [Ansariel: Display name support] childSetTextArg("partner_edit", "[NAME]", LLStringUtil::null); - // [/Ansariel: Display name support] mPartnerID = LLUUID::null; @@ -283,23 +270,15 @@ void LLPanelAvatarSecondLife::processProperties(void* data, EAvatarProcessorType getChild("img")->setImageAssetID(pAvatarData->image_id); - //Chalice - Show avatar age in days. - int year, month, day; - sscanf(pAvatarData->born_on.c_str(),"%d/%d/%d",&month,&day,&year); - time_t now = time(NULL); - struct tm * timeinfo; - timeinfo=localtime(&now); - timeinfo->tm_mon = --month; - timeinfo->tm_year = year - 1900; - timeinfo->tm_mday = day; - time_t birth = mktime(timeinfo); - std::stringstream NumberString; - NumberString << (difftime(now,birth) / (60*60*24)); - std::string born_on = pAvatarData->born_on; - born_on += " ("; - born_on += NumberString.str(); - born_on += ")"; - childSetValue("born", born_on); + // Show avatar age in days. + { + using namespace boost::gregorian; + int year, month, day; + sscanf(pAvatarData->born_on.c_str(),"%d/%d/%d",&month,&day,&year); + std::ostringstream born_on; + born_on << pAvatarData->born_on << " (" << day_clock::local_day() - date(year, month, day) << ")"; + childSetValue("born", born_on.str()); + } bool allow_publish = (pAvatarData->flags & AVATAR_ALLOW_PUBLISH); childSetValue("allow_publish", allow_publish); @@ -320,7 +299,7 @@ void LLPanelAvatarSecondLife::processProperties(void* data, EAvatarProcessorType // } if (0 == pAvatarGroups->group_list.size()) { - group_list->addCommentText(getString("None")); + group_list->setCommentText(getString("None")); } for(LLAvatarGroups::group_list_t::const_iterator it = pAvatarGroups->group_list.begin(); @@ -582,11 +561,10 @@ BOOL LLPanelAvatarSecondLife::postBuild(void) childSetAction("Offer Teleport...", LLPanelAvatar::onClickOfferTeleport, getPanelAvatar() ); - childSetDoubleClickCallback("groups", onDoubleClickGroup, this ); + getChild("groups")->setDoubleClickCallback(boost::bind(&LLPanelAvatarSecondLife::onDoubleClickGroup,this)); childSetAction("bigimg", onClickImage, this); - getChild("img")->setFallbackImageName("default_profile_picture.j2c"); return TRUE; diff --git a/indra/newview/llpaneldirbrowser.cpp b/indra/newview/llpaneldirbrowser.cpp index 4680780da..5dee332b3 100644 --- a/indra/newview/llpaneldirbrowser.cpp +++ b/indra/newview/llpaneldirbrowser.cpp @@ -212,7 +212,7 @@ void LLPanelDirBrowser::updateResultCount() // add none found response if (list->getItemCount() == 0) { - list->addCommentText(LLTrans::getString("NoneFound")); + list->setCommentText(LLTrans::getString("NoneFound")); list->operateOnAll(LLCtrlListInterface::OP_DESELECT); } } @@ -648,7 +648,7 @@ void LLPanelDirBrowser::processDirPlacesReply(LLMessageSystem* msg, void**) std::string buffer = llformat("%.0f", (F64)dwell); row["columns"][3]["column"] = "dwell"; row["columns"][3]["value"] = buffer; - row["columns"][3]["font"] = "SANSSERIFSMALL"; + row["columns"][3]["font"] = "SANSSERIF_SMALL"; list->addElement(row); self->mResultsContents[parcel_id.asString()] = content; @@ -792,11 +792,11 @@ void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**) row["columns"][2]["column"] = "date"; row["columns"][2]["value"] = date; - row["columns"][2]["font"] = "SANSSERIFSMALL"; + row["columns"][2]["font"] = "SANSSERIF_SMALL"; row["columns"][3]["column"] = "time"; row["columns"][3]["value"] = llformat("%u", unix_time); - row["columns"][3]["font"] = "SANSSERIFSMALL"; + row["columns"][3]["font"] = "SANSSERIF_SMALL"; list->addElement(row, ADD_SORTED); @@ -879,7 +879,7 @@ void LLPanelDirBrowser::processDirGroupsReply(LLMessageSystem* msg, void**) row["columns"][2]["column"] = "members"; row["columns"][2]["value"] = members; - row["columns"][2]["font"] = "SANSSERIFSMALL"; + row["columns"][2]["font"] = "SANSSERIF_SMALL"; row["columns"][3]["column"] = "score"; row["columns"][3]["value"] = search_order; @@ -1069,12 +1069,12 @@ void LLPanelDirBrowser::processDirLandReply(LLMessageSystem *msg, void**) } row["columns"][3]["column"] = "price"; row["columns"][3]["value"] = buffer; - row["columns"][3]["font"] = "SANSSERIFSMALL"; + row["columns"][3]["font"] = "SANSSERIF_SMALL"; buffer = llformat("%d", actual_area); row["columns"][4]["column"] = "area"; row["columns"][4]["value"] = buffer; - row["columns"][4]["font"] = "SANSSERIFSMALL"; + row["columns"][4]["font"] = "SANSSERIF_SMALL"; if (!auction) { @@ -1091,19 +1091,19 @@ void LLPanelDirBrowser::processDirLandReply(LLMessageSystem *msg, void**) buffer = llformat("%.1f", price_per_meter); row["columns"][5]["column"] = "per_meter"; row["columns"][5]["value"] = buffer; - row["columns"][5]["font"] = "SANSSERIFSMALL"; + row["columns"][5]["font"] = "SANSSERIF_SMALL"; } else { // Auctions start at L$1 per meter row["columns"][5]["column"] = "per_meter"; row["columns"][5]["value"] = "1.0"; - row["columns"][5]["font"] = "SANSSERIFSMALL"; + row["columns"][5]["font"] = "SANSSERIF_SMALL"; } row["columns"][6]["column"] = "landtype"; row["columns"][6]["value"] = land_type; - row["columns"][6]["font"] = "SANSSERIFSMALL"; + row["columns"][6]["font"] = "SANSSERIF_SMALL"; list->addElement(row); self->mResultsContents[parcel_id.asString()] = content; @@ -1138,7 +1138,7 @@ void LLPanelDirBrowser::addClassified(LLCtrlListInterface *list, const LLUUID& p row["columns"][2]["column"] = "price"; row["columns"][2]["value"] = price_for_listing; - row["columns"][2]["font"] = "SANSSERIFSMALL"; + row["columns"][2]["font"] = "SANSSERIF_SMALL"; list->addElement(row); } @@ -1222,7 +1222,7 @@ void LLPanelDirBrowser::setupNewSearch() // ready the list for results list->operateOnAll(LLCtrlListInterface::OP_DELETE); - list->addCommentText(LLTrans::getString("Searching")); + list->setCommentText(LLTrans::getString("Searching")); childDisable("results"); mResultsReceived = 0; diff --git a/indra/newview/llpaneldirland.cpp b/indra/newview/llpaneldirland.cpp index c1b4c8ce9..d89c049fa 100644 --- a/indra/newview/llpaneldirland.cpp +++ b/indra/newview/llpaneldirland.cpp @@ -111,7 +111,7 @@ BOOL LLPanelDirLand::postBuild() LLScrollListCtrl* results = getChild("results"); if (results) { - results->setSortChangedCallback(onClickSort); + results->setSortChangedCallback(boost::bind(&LLPanelDirLand::onClickSort,this)); results->sortByColumn(mCurrentSortColumn,mCurrentSortAscending); LLStringUtil::format_map_t args; diff --git a/indra/newview/llpaneldisplay.cpp b/indra/newview/llpaneldisplay.cpp index d2f3bdd01..362675292 100644 --- a/indra/newview/llpaneldisplay.cpp +++ b/indra/newview/llpaneldisplay.cpp @@ -897,10 +897,14 @@ void LLPanelDisplay::apply() LLWindow* window = gViewerWindow->getWindow(); LLCoordScreen size; window->getSize(&size); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); gViewerWindow->changeDisplaySettings(window->getFullscreen(), size, gSavedSettings.getBOOL("DisableVerticalSync"), logged_in); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); } } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index d19d14a4b..ca19b2caa 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -544,7 +544,7 @@ void LLPanelFace::getState() bool identical; LLTextureCtrl* texture_ctrl = getChild("texture control"); - + texture_ctrl->setFallbackImageName( "" ); //Singu Note: Don't show the 'locked' image when the texid is null. // Texture { LLUUID id; @@ -552,8 +552,14 @@ void LLPanelFace::getState() { LLUUID get(LLViewerObject* object, S32 te) { - LLViewerTexture* image = object->getTEImage(te); + //LLViewerTexture* image = object->getTEImage(te); + LLTextureEntry* image = object->getTE(te); //Singu Note: Use this instead of the above. + //The above actually returns LLViewerFetchedTexture::sDefaultImagep when + //the texture id is null, which gives us IMG_DEFAULT, not LLUUID::null + //Such behavior prevents the 'None' button from ever greying out in the face panel. return image ? image->getID() : LLUUID::null; + + } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id ); diff --git a/indra/newview/llpanelgeneral.cpp b/indra/newview/llpanelgeneral.cpp index fbd323a09..097f0d8db 100644 --- a/indra/newview/llpanelgeneral.cpp +++ b/indra/newview/llpanelgeneral.cpp @@ -70,8 +70,10 @@ BOOL LLPanelGeneral::postBuild() childSetValue("show_my_name_checkbox", gSavedSettings.getBOOL("RenderNameHideSelf")); childSetValue("small_avatar_names_checkbox", gSavedSettings.getBOOL("SmallAvatarNames")); childSetValue("show_my_title_checkbox", gSavedSettings.getBOOL("RenderHideGroupTitle")); + childSetValue("away_when_idle_checkbox", gSavedSettings.getBOOL("AllowIdleAFK")); childSetValue("afk_timeout_spinner", gSavedSettings.getF32("AFKTimeout")); childSetValue("notify_money_change_checkbox", gSavedSettings.getBOOL("NotifyMoneyChange")); + childSetValue("no_transaction_clutter_checkbox", gSavedSettings.getBOOL("LiruNoTransactionClutter")); @@ -111,6 +113,12 @@ BOOL LLPanelGeneral::postBuild() childSetVisible("maturity_desired_combobox", can_choose); childSetVisible("maturity_desired_textbox", !can_choose); + childSetEnabled("afk_timeout_spinner", gSavedSettings.getBOOL("AllowIdleAFK")); + childSetCommitCallback("away_when_idle_checkbox", &onClickCheckbox, this); + + childSetEnabled("no_transaction_clutter_checkbox", gSavedSettings.getBOOL("NotifyMoneyChange")); + childSetCommitCallback("notify_money_change_checkbox", &onClickCheckbox, this); + childSetAction("clear_settings", &onClickClearSettings, this); return TRUE; @@ -145,8 +153,10 @@ void LLPanelGeneral::apply() gSavedSettings.setBOOL("RenderNameHideSelf", childGetValue("show_my_name_checkbox")); gSavedSettings.setBOOL("SmallAvatarNames", childGetValue("small_avatar_names_checkbox")); gSavedSettings.setBOOL("RenderHideGroupTitle", childGetValue("show_my_title_checkbox")); + gSavedSettings.setBOOL("AllowIdleAFK", childGetValue("away_when_idle_checkbox")); gSavedSettings.setF32("AFKTimeout", childGetValue("afk_timeout_spinner").asReal()); gSavedSettings.setBOOL("NotifyMoneyChange", childGetValue("notify_money_change_checkbox")); + gSavedSettings.setBOOL("LiruNoTransactionClutter", childGetValue("no_transaction_clutter_checkbox")); gSavedSettings.setF32("UIScaleFactor", childGetValue("ui_scale_slider").asReal()); @@ -163,6 +173,17 @@ void LLPanelGeneral::cancel() { } +// static +void LLPanelGeneral::onClickCheckbox(LLUICtrl* ctrl, void* data) +{ + LLPanelGeneral* self = (LLPanelGeneral*)data; + bool enabled = ctrl->getValue().asBoolean(); + if(ctrl->getName() == "away_when_idle_checkbox") + self->childSetEnabled("afk_timeout_spinner", enabled); + else if(ctrl->getName() == "notify_money_change_checkbox") + self->childSetEnabled("no_transaction_clutter_checkbox", enabled); +} + // static void LLPanelGeneral::onClickClearSettings(void*) { diff --git a/indra/newview/llpanelgeneral.h b/indra/newview/llpanelgeneral.h index 1249ec8ca..48c44b15c 100644 --- a/indra/newview/llpanelgeneral.h +++ b/indra/newview/llpanelgeneral.h @@ -47,6 +47,7 @@ public: void apply(); void cancel(); + static void onClickCheckbox(LLUICtrl* ctrl, void* data); static void onClickClearSettings(void*); static void callbackResetAllSettings(const LLSD& notification, const LLSD& response); }; diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 5aecdce57..776f7fb9f 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -118,18 +118,16 @@ BOOL LLPanelGroupGeneral::postBuild() mInsignia = getChild("insignia", recurse); if (mInsignia) { - mInsignia->setCommitCallback(onCommitAny); - mInsignia->setCallbackUserData(this); + mInsignia->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitAny,this)); mDefaultIconID = mInsignia->getImageAssetID(); } mEditCharter = getChild("charter", recurse); if(mEditCharter) { - mEditCharter->setCommitCallback(onCommitAny); + mEditCharter->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitAny,this)); mEditCharter->setFocusReceivedCallback(boost::bind(&LLPanelGroupGeneral::onFocusEdit, this)); mEditCharter->setFocusChangedCallback(boost::bind(&LLPanelGroupGeneral::onFocusEdit, this)); - mEditCharter->setCallbackUserData(this); } mBtnJoinGroup = getChild("join_button", recurse); @@ -156,24 +154,21 @@ BOOL LLPanelGroupGeneral::postBuild() mListVisibleMembers = getChild("visible_members", recurse); if (mListVisibleMembers) { - mListVisibleMembers->setDoubleClickCallback(&LLPanelGroupGeneral::openProfile); - mListVisibleMembers->setCallbackUserData(this); + mListVisibleMembers->setDoubleClickCallback(boost::bind(&LLPanelGroupGeneral::openProfile,this)); } // Options mCtrlShowInGroupList = getChild("show_in_group_list", recurse); if (mCtrlShowInGroupList) { - mCtrlShowInGroupList->setCommitCallback(&LLPanelGroupGeneral::onCommitAny); - mCtrlShowInGroupList->setCallbackUserData(this); + mCtrlShowInGroupList->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitAny,this)); } mComboMature = getChild("group_mature_check", recurse); if(mComboMature) { mComboMature->setCurrentByIndex(0); - mComboMature->setCommitCallback(onCommitAny); - mComboMature->setCallbackUserData(this); + mComboMature->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitAny,this)); if (gAgent.isTeen()) { // Teens don't get to set mature flag. JC @@ -184,23 +179,20 @@ BOOL LLPanelGroupGeneral::postBuild() mCtrlOpenEnrollment = getChild("open_enrollement", recurse); if (mCtrlOpenEnrollment) { - mCtrlOpenEnrollment->setCommitCallback(onCommitAny); - mCtrlOpenEnrollment->setCallbackUserData(this); + mCtrlOpenEnrollment->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitAny,this)); } mCtrlEnrollmentFee = getChild("check_enrollment_fee", recurse); if (mCtrlEnrollmentFee) { mCtrlEnrollmentFee->setLabelArg("[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); - mCtrlEnrollmentFee->setCommitCallback(onCommitEnrollment); - mCtrlEnrollmentFee->setCallbackUserData(this); + mCtrlEnrollmentFee->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitEnrollment,this)); } mSpinEnrollmentFee = getChild("spin_enrollment_fee", recurse); if (mSpinEnrollmentFee) { - mSpinEnrollmentFee->setCommitCallback(onCommitAny); - mSpinEnrollmentFee->setCallbackUserData(this); + mSpinEnrollmentFee->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitAny,this)); mSpinEnrollmentFee->setPrecision(0); mSpinEnrollmentFee->resetDirty(); } @@ -216,8 +208,7 @@ BOOL LLPanelGroupGeneral::postBuild() mCtrlReceiveNotices = getChild("receive_notices", recurse); if (mCtrlReceiveNotices) { - mCtrlReceiveNotices->setCommitCallback(onCommitUserOnly); - mCtrlReceiveNotices->setCallbackUserData(this); + mCtrlReceiveNotices->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitUserOnly,this)); mCtrlReceiveNotices->set(accept_notices); mCtrlReceiveNotices->setEnabled(data.mID.notNull()); mCtrlReceiveNotices->resetDirty(); @@ -226,8 +217,7 @@ BOOL LLPanelGroupGeneral::postBuild() mCtrlReceiveChat = getChild("receive_chat", recurse); if (mCtrlReceiveChat) { - mCtrlReceiveChat->setCommitCallback(onCommitUserOnly); - mCtrlReceiveChat->setCallbackUserData(this); + mCtrlReceiveChat->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitUserOnly,this)); mCtrlReceiveChat->set(!gIMMgr->getIgnoreGroup(mGroupID)); mCtrlReceiveChat->setEnabled(mGroupID.notNull()); mCtrlReceiveChat->resetDirty(); @@ -236,8 +226,7 @@ BOOL LLPanelGroupGeneral::postBuild() mCtrlListGroup = getChild("list_groups_in_profile", recurse); if (mCtrlListGroup) { - mCtrlListGroup->setCommitCallback(onCommitUserOnly); - mCtrlListGroup->setCallbackUserData(this); + mCtrlListGroup->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitUserOnly,this)); mCtrlListGroup->set(list_in_profile); mCtrlListGroup->setEnabled(data.mID.notNull()); mCtrlListGroup->resetDirty(); @@ -248,8 +237,7 @@ BOOL LLPanelGroupGeneral::postBuild() mComboActiveTitle = getChild("active_title", recurse); if (mComboActiveTitle) { - mComboActiveTitle->setCommitCallback(onCommitTitle); - mComboActiveTitle->setCallbackUserData(this); + mComboActiveTitle->setCommitCallback(boost::bind(&LLPanelGroupGeneral::onCommitTitle,this)); mComboActiveTitle->resetDirty(); } @@ -284,60 +272,54 @@ void LLPanelGroupGeneral::onFocusEdit() notifyObservers(); } -void LLPanelGroupGeneral::onCommitAny(LLUICtrl* ctrl, void* data) +void LLPanelGroupGeneral::onCommitAny() { - LLPanelGroupGeneral* self = (LLPanelGroupGeneral*)data; - self->updateChanged(); - self->notifyObservers(); + updateChanged(); + notifyObservers(); } // static -void LLPanelGroupGeneral::onCommitUserOnly(LLUICtrl* ctrl, void* data) +void LLPanelGroupGeneral::onCommitUserOnly() { - LLPanelGroupGeneral* self = (LLPanelGroupGeneral*)data; - self->mChanged = TRUE; - self->notifyObservers(); + mChanged = TRUE; + notifyObservers(); } -// static -void LLPanelGroupGeneral::onCommitEnrollment(LLUICtrl* ctrl, void* data) +void LLPanelGroupGeneral::onCommitEnrollment() { - onCommitAny(ctrl, data); + onCommitAny(); - LLPanelGroupGeneral* self = (LLPanelGroupGeneral*)data; // Make sure both enrollment related widgets are there. - if (!self->mCtrlEnrollmentFee || !self->mSpinEnrollmentFee) + if (!mCtrlEnrollmentFee || !mSpinEnrollmentFee) { return; } // Make sure the agent can change enrollment info. - if (!gAgent.hasPowerInGroup(self->mGroupID,GP_MEMBER_OPTIONS) - || !self->mAllowEdit) + if (!gAgent.hasPowerInGroup(mGroupID,GP_MEMBER_OPTIONS) + || !mAllowEdit) { return; } - if (self->mCtrlEnrollmentFee->get()) + if (mCtrlEnrollmentFee->get()) { - self->mSpinEnrollmentFee->setEnabled(TRUE); + mSpinEnrollmentFee->setEnabled(TRUE); } else { - self->mSpinEnrollmentFee->setEnabled(FALSE); - self->mSpinEnrollmentFee->set(0); + mSpinEnrollmentFee->setEnabled(FALSE); + mSpinEnrollmentFee->set(0); } } -// static -void LLPanelGroupGeneral::onCommitTitle(LLUICtrl* ctrl, void* data) +void LLPanelGroupGeneral::onCommitTitle() { - LLPanelGroupGeneral* self = (LLPanelGroupGeneral*)data; - if (self->mGroupID.isNull() || !self->mAllowEdit) return; - LLGroupMgr::getInstance()->sendGroupTitleUpdate(self->mGroupID,self->mComboActiveTitle->getCurrentID()); - self->update(GC_TITLES); - self->mComboActiveTitle->resetDirty(); + if (mGroupID.isNull() || !mAllowEdit) return; + LLGroupMgr::getInstance()->sendGroupTitleUpdate(mGroupID,mComboActiveTitle->getCurrentID()); + update(GC_TITLES); + mComboActiveTitle->resetDirty(); } // static @@ -433,10 +415,9 @@ void LLPanelGroupGeneral::activate() LLGroupMgr::getInstance()->sendGroupTitlesRequest(mGroupID); LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID); - if (!gdatap || !gdatap->isMemberDataComplete() ) { - LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); } mFirstUse = FALSE; @@ -872,6 +853,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) LLSD row; row["columns"][0]["value"] = pending.str(); + row["columns"][0]["column"] = "name"; mListVisibleMembers->setEnabled(FALSE); mListVisibleMembers->addElement(row); @@ -901,7 +883,7 @@ void LLPanelGroupGeneral::updateMembers() for( ; mMemberProgress != gdatap->mMembers.end() && ifirst << ", " << iter->second->getTitle() << llendl; + lldebugs << "Adding " << mMemberProgress->first << ", " << mMemberProgress->second->getTitle() << llendl; LLGroupMemberData* member = mMemberProgress->second; if (!member) { @@ -936,20 +918,20 @@ void LLPanelGroupGeneral::updateMembers() sSDTime += sd_timer.getElapsedTimeF32(); element_timer.reset(); - mListVisibleMembers->addElement(row);//, ADD_SORTED); + mListVisibleMembers->addNameItem(row); sElementTime += element_timer.getElapsedTimeF32(); } sAllTime += all_timer.getElapsedTimeF32(); - llinfos << "Updated " << i << " of " << UPDATE_MEMBERS_PER_FRAME << "members in the list." << llendl; + lldebugs << "Updated " << i << " of " << UPDATE_MEMBERS_PER_FRAME << "members in the list." << llendl; if (mMemberProgress == gdatap->mMembers.end()) { - llinfos << " member list completed." << llendl; + lldebugs << " member list completed." << llendl; mListVisibleMembers->setEnabled(TRUE); - llinfos << "All Time: " << sAllTime << llendl; - llinfos << "SD Time: " << sSDTime << llendl; - llinfos << "Element Time: " << sElementTime << llendl; + lldebugs << "All Time: " << sAllTime << llendl; + lldebugs << "SD Time: " << sSDTime << llendl; + lldebugs << "Element Time: " << sElementTime << llendl; } else { diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h index 2eeb901c7..1c275d9aa 100644 --- a/indra/newview/llpanelgroupgeneral.h +++ b/indra/newview/llpanelgroupgeneral.h @@ -68,10 +68,10 @@ public: private: void onFocusEdit(); - static void onCommitAny(LLUICtrl* ctrl, void* data); - static void onCommitUserOnly(LLUICtrl* ctrl, void* data); - static void onCommitTitle(LLUICtrl* ctrl, void* data); - static void onCommitEnrollment(LLUICtrl* ctrl, void* data); + void onCommitAny(); + void onCommitUserOnly(); + void onCommitTitle(); + void onCommitEnrollment(); static void onClickJoin(void* userdata); static void onClickInfo(void* userdata); static void onReceiveNotices(LLUICtrl* ctrl, void* data); diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 35f405340..2f44a34bc 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -34,8 +34,10 @@ #include "llpanelgroupinvite.h" #include "llagent.h" +#include "llavatarnamecache.h" #include "llfloateravatarpicker.h" #include "llbutton.h" +#include "llcallingcard.h" #include "llcombobox.h" #include "llgroupmgr.h" #include "llnamelistctrl.h" @@ -54,7 +56,7 @@ public: ~impl(); void addUsers(const std::vector& names, - const std::vector& agent_ids); + const uuid_vec_t& agent_ids); void submitInvitations(); void addRoleNames(LLGroupMgrGroupData* gdatap); void handleRemove(); @@ -65,9 +67,13 @@ public: static void callbackClickAdd(void* userdata); static void callbackClickRemove(void* userdata); static void callbackSelect(LLUICtrl* ctrl, void* userdata); - static void callbackAddUsers(const std::vector& names, - const std::vector& agent_ids, + static void callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data); + + static void onAvatarNameCache(const LLUUID& agent_id, + const LLAvatarName& av_name, + void* user_data); + bool inviteOwnerCallback(const LLSD& notification, const LLSD& response); public: @@ -80,6 +86,8 @@ public: LLButton *mRemoveButton; LLTextBox *mGroupName; std::string mOwnerWarning; + std::string mAlreadyInGroup; + std::string mTooManySelected; bool mConfirmedOwnerInvite; void (*mCloseCallback)(void* data); @@ -107,7 +115,7 @@ LLPanelGroupInvite::impl::~impl() } void LLPanelGroupInvite::impl::addUsers(const std::vector& names, - const std::vector& agent_ids) + const uuid_vec_t& agent_ids) { std::string name; LLUUID id; @@ -138,9 +146,10 @@ void LLPanelGroupInvite::impl::addUsers(const std::vector& names, //add the name to the names list LLSD row; row["id"] = id; + row["columns"][0]["column"] = "name"; row["columns"][0]["value"] = name; - mInvitees->addElement(row); + mInvitees->addNameItem(row); } } @@ -167,16 +176,40 @@ void LLPanelGroupInvite::impl::submitInvitations() } } + bool already_in_group = false; //loop over the users std::vector items = mInvitees->getAllData(); for (std::vector::iterator iter = items.begin(); iter != items.end(); ++iter) { LLScrollListItem* item = *iter; + if(gdatap->mMembers.find(item->getUUID()) != gdatap->mMembers.end()) + { + already_in_group = true; + continue; + } role_member_pairs[item->getUUID()] = role_id; } + + const S32 MAX_GROUP_INVITES = 100; // Max invites per request. 100 to match server cap. + if (role_member_pairs.size() > MAX_GROUP_INVITES) + { + // Fail! + LLSD msg; + msg["MESSAGE"] = mTooManySelected; + LLNotificationsUtil::add("GenericAlert", msg); + (*mCloseCallback)(mCloseCallbackUserData); + return; + } LLGroupMgr::getInstance()->sendGroupMemberInvites(mGroupID, role_member_pairs); + + if(already_in_group) + { + LLSD msg; + msg["MESSAGE"] = mAlreadyInGroup; + LLNotificationsUtil::add("GenericAlert", msg); + } //then close (*mCloseCallback)(mCloseCallbackUserData); @@ -184,7 +217,7 @@ void LLPanelGroupInvite::impl::submitInvitations() bool LLPanelGroupInvite::impl::inviteOwnerCallback(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); switch(option) { @@ -273,12 +306,12 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata) //Soon the avatar picker will be embedded into this panel //instead of being it's own separate floater. But that is next week. //This will do for now. -jwolk May 10, 2006 - LLFloater* parentp; - - parentp = gFloaterView->getParentFloater(panelp); - parentp->addDependentFloater(LLFloaterAvatarPicker::show(callbackAddUsers, - panelp->mImplementation, - TRUE)); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( + boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), TRUE); + if (picker) + { + gFloaterView->getParentFloater(panelp)->addDependentFloater(picker); + } } } @@ -342,26 +375,43 @@ void LLPanelGroupInvite::impl::callbackClickOK(void* userdata) if ( selfp ) selfp->submitInvitations(); } + + //static -void LLPanelGroupInvite::impl::callbackAddUsers(const std::vector& names, - const std::vector& ids, - void* user_data) +void LLPanelGroupInvite::impl::callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data) +{ + std::vector names; + for (S32 i = 0; i < (S32)agent_ids.size(); i++) + { + LLAvatarNameCache::get(agent_ids[i], + boost::bind(&LLPanelGroupInvite::impl::onAvatarNameCache, _1, _2, user_data)); + } + +} + +void LLPanelGroupInvite::impl::onAvatarNameCache(const LLUUID& agent_id, + const LLAvatarName& av_name, + void* user_data) { impl* selfp = (impl*) user_data; - if ( selfp) selfp->addUsers(names, ids); + if (selfp) + { + std::vector names; + uuid_vec_t agent_ids; + agent_ids.push_back(agent_id); + names.push_back(av_name.getCompleteName()); + + selfp->addUsers(names, agent_ids); + } } LLPanelGroupInvite::LLPanelGroupInvite(const std::string& name, const LLUUID& group_id) - : LLPanel(name) + : LLPanel(name), + mImplementation(new impl(group_id)), + mPendingUpdate(FALSE) { - mImplementation = new impl(group_id); - mPendingUpdate = FALSE; - mStoreSelected = LLUUID::null; - - std::string panel_def_file; - // Pass on construction of this panel to the control factory. LLUICtrlFactory::getInstance()->buildPanel(this, "panel_group_invite.xml", &getFactoryMap()); } @@ -387,18 +437,72 @@ void LLPanelGroupInvite::clear() mImplementation->mOKButton->setEnabled(FALSE); } -void LLPanelGroupInvite::addUsers(std::vector& agent_ids) +void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) { std::vector names; for (S32 i = 0; i < (S32)agent_ids.size(); i++) { - std::string name; - if(gCacheName->getFullName(agent_ids[i], name)) - names.push_back(name); + std::string fullname; + LLUUID agent_id = agent_ids[i]; + LLViewerObject* dest = gObjectList.findObject(agent_id); + if(dest && dest->isAvatar()) + { + LLNameValue* nvfirst = dest->getNVPair("FirstName"); + LLNameValue* nvlast = dest->getNVPair("LastName"); + if(nvfirst && nvlast) + { + fullname = LLCacheName::buildFullName( + nvfirst->getString(), nvlast->getString()); + + } + if (!fullname.empty()) + { + names.push_back(fullname); + } + else + { + llwarns << "llPanelGroupInvite: Selected avatar has no name: " << dest->getID() << llendl; + names.push_back("(Unknown)"); + } + } + else + { + //looks like user try to invite offline friend + //for offline avatar_id gObjectList.findObject() will return null + //so we need to do this additional search in avatar tracker, see EXT-4732 + if (LLAvatarTracker::instance().isBuddy(agent_id)) + { + LLAvatarName av_name; + if (!LLAvatarNameCache::get(agent_id, &av_name)) + { + // actually it should happen, just in case + LLAvatarNameCache::get(LLUUID(agent_id), boost::bind( + &LLPanelGroupInvite::addUserCallback, this, _1, _2)); + // for this special case! + //when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence + // removed id will be added in callback + agent_ids.erase(agent_ids.begin() + i); + } + else + { + names.push_back(av_name.getLegacyName()); + } + } + } } mImplementation->addUsers(names, agent_ids); } +void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const LLAvatarName& av_name) +{ + std::vector names; + uuid_vec_t agent_ids; + agent_ids.push_back(id); + names.push_back(av_name.getLegacyName()); + + mImplementation->addUsers(names, agent_ids); +} + void LLPanelGroupInvite::draw() { LLPanel::draw(); @@ -472,8 +576,8 @@ void LLPanelGroupInvite::updateLists() if (!mPendingUpdate) { LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID); - LLGroupMgr::getInstance()->sendGroupMembersRequest(mImplementation->mGroupID); LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID); + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID); } mPendingUpdate = TRUE; } @@ -499,9 +603,8 @@ BOOL LLPanelGroupInvite::postBuild() getChild("invitee_list", recurse); if ( mImplementation->mInvitees ) { - mImplementation->mInvitees->setCallbackUserData(mImplementation); mImplementation->mInvitees->setCommitOnSelectionChange(TRUE); - mImplementation->mInvitees->setCommitCallback(impl::callbackSelect); + mImplementation->mInvitees->setCommitCallback(impl::callbackSelect, mImplementation); } LLButton* button = getChild("add_button", recurse); @@ -509,14 +612,14 @@ BOOL LLPanelGroupInvite::postBuild() { // default to opening avatarpicker automatically // (*impl::callbackClickAdd)((void*)this); - button->setClickedCallback(boost::bind(&impl::callbackClickAdd, this)); + button->setClickedCallback(impl::callbackClickAdd, this); } mImplementation->mRemoveButton = getChild("remove_button", recurse); if ( mImplementation->mRemoveButton ) { - mImplementation->mRemoveButton->setClickedCallback(boost::bind(&impl::callbackClickRemove, mImplementation)); + mImplementation->mRemoveButton->setClickedCallback(impl::callbackClickRemove, mImplementation); mImplementation->mRemoveButton->setEnabled(FALSE); } @@ -524,17 +627,19 @@ BOOL LLPanelGroupInvite::postBuild() getChild("ok_button", recurse); if ( mImplementation->mOKButton ) { - mImplementation->mOKButton->setClickedCallback(boost::bind(&impl::callbackClickOK, mImplementation)); + mImplementation->mOKButton->setClickedCallback(impl::callbackClickOK, mImplementation); mImplementation->mOKButton->setEnabled(FALSE); } button = getChild("cancel_button", recurse); if ( button ) { - button->setClickedCallback(boost::bind(&impl::callbackClickCancel,mImplementation)); + button->setClickedCallback(impl::callbackClickCancel, mImplementation); } mImplementation->mOwnerWarning = getString("confirm_invite_owner_str"); + mImplementation->mAlreadyInGroup = getString("already_in_group"); + mImplementation->mTooManySelected = getString("invite_selection_too_large"); update(); diff --git a/indra/newview/llpanelgroupinvite.h b/indra/newview/llpanelgroupinvite.h index 9117b83e7..b296e3dd4 100644 --- a/indra/newview/llpanelgroupinvite.h +++ b/indra/newview/llpanelgroupinvite.h @@ -35,6 +35,7 @@ #include "llpanel.h" #include "lluuid.h" +class LLAvatarName; class LLPanelGroupInvite : public LLPanel { @@ -42,7 +43,11 @@ public: LLPanelGroupInvite(const std::string& name, const LLUUID& group_id); ~LLPanelGroupInvite(); - void addUsers(std::vector& agent_ids); + void addUsers(uuid_vec_t& agent_ids); + /** + * this callback is being used to add a user whose fullname isn't been loaded before invoking of addUsers(). + */ + void addUserCallback(const LLUUID& id, const LLAvatarName& av_name); void clear(); void update(); diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index 9b7ee5c78..5ad7ad7a1 100644 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -462,19 +462,19 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) row["columns"][0]["column"] = "name"; row["columns"][0]["value"] = name; - row["columns"][0]["font"] = "SANSSERIFSMALL"; + row["columns"][0]["font"] = "SANSSERIF_SMALL"; row["columns"][1]["column"] = "location"; row["columns"][1]["value"] = location; - row["columns"][1]["font"] = "SANSSERIFSMALL"; + row["columns"][1]["font"] = "SANSSERIF_SMALL"; row["columns"][2]["column"] = "area"; row["columns"][2]["value"] = area; - row["columns"][2]["font"] = "SANSSERIFSMALL"; + row["columns"][2]["font"] = "SANSSERIF_SMALL"; row["columns"][3]["column"] = "type"; row["columns"][3]["value"] = land_type; - row["columns"][3]["font"] = "SANSSERIFSMALL"; + row["columns"][3]["font"] = "SANSSERIF_SMALL"; // hidden is always last column row["columns"][4]["column"] = "hidden"; @@ -676,7 +676,7 @@ BOOL LLPanelGroupLandMoney::postBuild() { if ( mImplementationp->mGroupParcelsp ) { - mImplementationp->mGroupParcelsp->addCommentText( + mImplementationp->mGroupParcelsp->setCommentText( mImplementationp->mCantViewParcelsText); mImplementationp->mGroupParcelsp->setEnabled(FALSE); } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 13786d9e4..ffec84e7d 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -450,7 +450,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) if (1 == count && id.isNull()) { // Only one entry, the dummy entry. - mNoticesList->addCommentText(mNoNoticesStr); + mNoticesList->setCommentText(mNoNoticesStr); mNoticesList->setEnabled(FALSE); return; } @@ -493,7 +493,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) mNoticesList->addElement(row, ADD_BOTTOM); } - mNoticesList->sortItems(); + mNoticesList->updateSort(); } void LLPanelGroupNotices::onSelectNotice(LLUICtrl* ctrl, void* data) diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 155ab8dde..b7f09bd69 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -402,7 +402,7 @@ void LLPanelGroupRoles::activate() if (!gdatap || !gdatap->isMemberDataComplete() ) { - LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); } // Check role data. @@ -790,7 +790,7 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl, row["columns"][column_index]["column"] = "action"; row["columns"][column_index]["value"] = (*ra_it)->mDescription; - row["columns"][column_index]["font"] = "SANSSERIFSMALL"; + row["columns"][column_index]["font"] = "SANSSERIF_SMALL"; LLScrollListItem* item = ctrl->addElement(row, ADD_BOTTOM, (*ra_it)); @@ -890,11 +890,10 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root) if (!mMembersList || !mAssignedRolesList || !mAllowedActionsList) return FALSE; // We want to be notified whenever a member is selected. - mMembersList->setCallbackUserData(this); mMembersList->setCommitOnSelectionChange(TRUE); - mMembersList->setCommitCallback(onMemberSelect); + mMembersList->setCommitCallback(boost::bind(&LLPanelGroupMembersSubTab::onMemberSelect,_1,this)); // Show the member's profile on double click. - mMembersList->setDoubleClickCallback(onMemberDoubleClick); + mMembersList->setDoubleClickCallback(boost::bind(&LLPanelGroupMembersSubTab::onMemberDoubleClick,this)); LLButton* button = parent->getChild("member_invite", recurse); if ( button ) @@ -1616,7 +1615,7 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc) retrieved << "Retrieving role member mappings..."; } mMembersList->setEnabled(FALSE); - mMembersList->addCommentText(retrieved.str()); + mMembersList->setCommentText(retrieved.str()); } } @@ -1679,9 +1678,9 @@ void LLPanelGroupMembersSubTab::updateMembers() row["columns"][2]["column"] = "online"; row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus(); - row["columns"][2]["font"] = "SANSSERIFSMALL"; + row["columns"][2]["font"] = "SANSSERIF_SMALL"; - mMembersList->addElement(row);//, ADD_SORTED); + mMembersList->addNameItem(row); mHasMatch = TRUE; } } @@ -1695,7 +1694,7 @@ void LLPanelGroupMembersSubTab::updateMembers() else { mMembersList->setEnabled(FALSE); - mMembersList->addCommentText(std::string("No match.")); + mMembersList->setCommentText(std::string("No match.")); } } else @@ -1980,7 +1979,7 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc) if (!gdatap || !gdatap->isMemberDataComplete()) { - LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); } if (!gdatap || !gdatap->isRoleMemberDataComplete()) @@ -2572,7 +2571,7 @@ void LLPanelGroupActionsSubTab::handleActionSelect() } else { - LLGroupMgr::getInstance()->sendGroupMembersRequest(mGroupID); + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); } if (gdatap->isRoleDataComplete()) diff --git a/indra/newview/llpanelgroupvoting.cpp b/indra/newview/llpanelgroupvoting.cpp index 89134c437..3af05adc6 100644 --- a/indra/newview/llpanelgroupvoting.cpp +++ b/indra/newview/llpanelgroupvoting.cpp @@ -916,19 +916,19 @@ void LLPanelGroupVoting::impl::addPendingActiveScrollListItem(unsigned int curre << current << "\\" << expected << ")"; - mProposals->addCommentText(pending.str()); + mProposals->setCommentText(pending.str()); } void LLPanelGroupVoting::impl::addNoActiveScrollListItem(EAddPosition pos) { // *TODO: translate - mProposals->addCommentText(std::string("There are currently no active proposals"), pos); + mProposals->setCommentText(std::string("There are currently no active proposals")); } void LLPanelGroupVoting::impl::addNoHistoryScrollListItem(EAddPosition pos) { // *TODO: translate - mVotesHistory->addCommentText(std::string("There are currently no archived proposals"), pos); + mVotesHistory->setCommentText(std::string("There are currently no archived proposals")); } void LLPanelGroupVoting::impl::addPendingHistoryScrollListItem(unsigned int current, @@ -941,7 +941,7 @@ void LLPanelGroupVoting::impl::addPendingHistoryScrollListItem(unsigned int curr << current << "\\" << expected << ")"; - mVotesHistory->addCommentText(pending.str()); + mVotesHistory->setCommentText(pending.str()); } @@ -1579,11 +1579,9 @@ BOOL LLPanelGroupVoting::postBuild() //associate callbacks if ( success ) { - mImpl->mProposals->setDoubleClickCallback(impl::onDoubleClickProposal); - mImpl->mProposals->setCallbackUserData(mImpl); + mImpl->mProposals->setDoubleClickCallback(boost::bind(&LLPanelGroupVoting::impl::onDoubleClickProposal,mImpl)); - mImpl->mVotesHistory->setDoubleClickCallback(impl::onDoubleClickHistoryItem); - mImpl->mVotesHistory->setCallbackUserData(mImpl); + mImpl->mVotesHistory->setDoubleClickCallback(boost::bind(&LLPanelGroupVoting::impl::onDoubleClickHistoryItem,mImpl)); mImpl->mBtnAbstain->setClickedCallback(boost::bind(&impl::onClickAbstain,mImpl)); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 019ddd668..134363bce 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -162,10 +162,6 @@ public: LLLoginRefreshHandler gLoginRefreshHandler; -// -std::string gFullName; -// - // helper class that trys to download a URL from a web site and calls a method // on parent class indicating if the web server is working or not class LLIamHereLogin : public LLHTTPClient::ResponderHeadersOnly diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 53eb9b52d..1812b6fc7 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -41,10 +41,6 @@ class LLUIImage; class LLComboBox; -// -extern std::string gFullName; -// - class LLPanelLogin: public LLPanel, public LLViewerMediaObserver @@ -165,8 +161,4 @@ private: std::string load_password_from_disk(void); void save_password_to_disk(const char* hashed_password); -// -extern std::string gFullName; -// - #endif diff --git a/indra/newview/llpanelmediahud.cpp b/indra/newview/llpanelmediahud.cpp index 2fcee26c6..27d1473d6 100644 --- a/indra/newview/llpanelmediahud.cpp +++ b/indra/newview/llpanelmediahud.cpp @@ -78,8 +78,6 @@ LLPanelMediaHUD::LLPanelMediaHUD(viewer_media_t media_impl) mFadeTimer.stop(); mCurrentZoom = ZOOM_NONE; mScrollState = SCROLL_NONE; - - mPanelHandle.bind(this); } LLPanelMediaHUD::~LLPanelMediaHUD() { diff --git a/indra/newview/llpanelmediahud.h b/indra/newview/llpanelmediahud.h index 81d40591e..1d1f5e1be 100644 --- a/indra/newview/llpanelmediahud.h +++ b/indra/newview/llpanelmediahud.h @@ -55,7 +55,8 @@ public: void nextZoomLevel(); void resetZoomLevel() { mCurrentZoom = ZOOM_NONE; } - LLHandle getHandle() const { return mPanelHandle; } + LLHandle getHandle() const { return getDerivedHandle(); } + void setMediaImpl(viewer_media_t media_impl) { mMediaImpl = media_impl; } @@ -105,7 +106,6 @@ private: F32 mMouseInactiveTime; F32 mControlFadeTime; viewer_media_t mMediaImpl; - LLRootHandle mPanelHandle; }; #endif // LL_PANELMEDIAHUD_H diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 8929780d5..cd9d17587 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -131,7 +131,7 @@ public: virtual BOOL copyToClipboard() const; virtual void cutToClipboard(); virtual BOOL isClipboardPasteable() const; - virtual void pasteFromClipboard(); + virtual void pasteFromClipboard(bool only_copies = false); virtual void pasteLinkFromClipboard(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual void performAction(LLInventoryModel* model, std::string action); @@ -604,7 +604,7 @@ BOOL LLTaskInvFVBridge::isClipboardPasteable() const return FALSE; } -void LLTaskInvFVBridge::pasteFromClipboard() +void LLTaskInvFVBridge::pasteFromClipboard(bool only_copies) { } diff --git a/indra/newview/llpanelpathfindingrebakenavmesh.cpp b/indra/newview/llpanelpathfindingrebakenavmesh.cpp deleted file mode 100644 index ca4bcfb67..000000000 --- a/indra/newview/llpanelpathfindingrebakenavmesh.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/** -* @file llpanelpathfindingrebakenavmesh.cpp -* @brief Implementation of llpanelpathfindingrebakenavmesh -* @author Prep@lindenlab.com -* -* $LicenseInfo:firstyear=2012&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2012, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - - -#include "llviewerprecompiledheaders.h" - -#include "llpanelpathfindingrebakenavmesh.h" - -#include -#include - -#include "llagent.h" -#include "llbutton.h" -#include "llenvmanager.h" -#include "llnotificationsutil.h" -#include "llpanel.h" -#include "llpathfindingmanager.h" -#include "llpathfindingnavmesh.h" -#include "llpathfindingnavmeshstatus.h" -#include "lltoolbar.h" -#include "llviewerregion.h" -#include "llviewerwindow.h" -#include "lluictrlfactory.h" - - -LLPanelPathfindingRebakeNavmesh* LLPanelPathfindingRebakeNavmesh::getInstance() -{ - static LLPanelPathfindingRebakeNavmesh* panel = getPanel(); - return panel; -} - -BOOL LLPanelPathfindingRebakeNavmesh::postBuild() -{ - //Rebake button - mNavMeshRebakeButton = getChild("navmesh_btn"); - llassert(mNavMeshRebakeButton != NULL); - mNavMeshRebakeButton->setCommitCallback(boost::bind(&LLPanelPathfindingRebakeNavmesh::onNavMeshRebakeClick, this)); - //LLHints::registerHintTarget("navmesh_btn", mNavMeshRebakeButton->getHandle()); - - //Sending rebake request - mNavMeshSendingButton = findChild("navmesh_btn_sending"); - llassert(mNavMeshSendingButton != NULL); - //LLHints::registerHintTarget("navmesh_btn_sending", mNavMeshSendingButton->getHandle()); - - //rebaking... - mNavMeshBakingButton = findChild("navmesh_btn_baking"); - llassert(mNavMeshBakingButton != NULL); - //LLHints::registerHintTarget("navmesh_btn_baking", mNavMeshBakingButton->getHandle()); - - setMode(kRebakeNavMesh_Default); - - createNavMeshStatusListenerForCurrentRegion(); - - if ( !mRegionCrossingSlot.connected() ) - { - mRegionCrossingSlot = LLEnvManagerNew::getInstance()->setRegionChangeCallback(boost::bind(&LLPanelPathfindingRebakeNavmesh::handleRegionBoundaryCrossed, this)); - } - - if (!mAgentStateSlot.connected()) - { - mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLPanelPathfindingRebakeNavmesh::handleAgentState, this, _1)); - } - LLPathfindingManager::getInstance()->requestGetAgentState(); - - return LLPanel::postBuild(); -} - -void LLPanelPathfindingRebakeNavmesh::draw() -{ - if (doDraw()) - { - updatePosition(); - LLPanel::draw(); - } -} - -BOOL LLPanelPathfindingRebakeNavmesh::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) -{ - gViewerWindow->unblockToolTips(); - - if (mNavMeshRebakeButton->getVisible()) - { - msg=mNavMeshRebakeButton->getToolTip(); - //LLToolTipMgr::instance().show(mNavMeshRebakeButton->getToolTip()); - } - else if (mNavMeshSendingButton->getVisible()) - { - msg=mNavMeshSendingButton->getToolTip(); - //LLToolTipMgr::instance().show(mNavMeshSendingButton->getToolTip()); - } - else if (mNavMeshBakingButton->getVisible()) - { - msg=mNavMeshBakingButton->getToolTip(); - //LLToolTipMgr::instance().show(mNavMeshBakingButton->getToolTip()); - } - - // Convert rect local to screen coordinates - localPointToScreen( - 0, 0, - &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); - localPointToScreen( - getRect().getWidth(), getRect().getHeight(), - &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) ); - return true;//LLPanel::handleToolTip(x, y, mask); -} - -LLPanelPathfindingRebakeNavmesh::LLPanelPathfindingRebakeNavmesh() - : LLPanel(), - mCanRebakeRegion(FALSE), - mRebakeNavMeshMode(kRebakeNavMesh_Default), - mNavMeshRebakeButton(NULL), - mNavMeshSendingButton(NULL), - mNavMeshBakingButton(NULL), - mNavMeshSlot(), - mRegionCrossingSlot(), - mAgentStateSlot() -{ - // make sure we have the only instance of this class - static bool b = true; - llassert_always(b); - b=false; -} - -LLPanelPathfindingRebakeNavmesh::~LLPanelPathfindingRebakeNavmesh() -{ -} - -LLPanelPathfindingRebakeNavmesh* LLPanelPathfindingRebakeNavmesh::getPanel() -{ - LLPanelPathfindingRebakeNavmesh* panel = new LLPanelPathfindingRebakeNavmesh(); - LLUICtrlFactory::getInstance()->buildPanel(panel,"panel_navmesh_rebake.xml"); - return panel; -} - -void LLPanelPathfindingRebakeNavmesh::setMode(ERebakeNavMeshMode pRebakeNavMeshMode) -{ - if (pRebakeNavMeshMode == kRebakeNavMesh_Available) - { - LLNotificationsUtil::add("PathfindingRebakeNavmesh"); - } - mNavMeshRebakeButton->setVisible(pRebakeNavMeshMode == kRebakeNavMesh_Available); - mNavMeshSendingButton->setVisible(pRebakeNavMeshMode == kRebakeNavMesh_RequestSent); - mNavMeshBakingButton->setVisible(pRebakeNavMeshMode == kRebakeNavMesh_InProgress); - mRebakeNavMeshMode = pRebakeNavMeshMode; -} - -LLPanelPathfindingRebakeNavmesh::ERebakeNavMeshMode LLPanelPathfindingRebakeNavmesh::getMode() const -{ - return mRebakeNavMeshMode; -} - -void LLPanelPathfindingRebakeNavmesh::onNavMeshRebakeClick() -{ - setMode(kRebakeNavMesh_RequestSent); - LLPathfindingManager::getInstance()->requestRebakeNavMesh(boost::bind(&LLPanelPathfindingRebakeNavmesh::handleRebakeNavMeshResponse, this, _1)); -} - -void LLPanelPathfindingRebakeNavmesh::handleAgentState(BOOL pCanRebakeRegion) -{ - mCanRebakeRegion = pCanRebakeRegion; -} - -void LLPanelPathfindingRebakeNavmesh::handleRebakeNavMeshResponse(bool pResponseStatus) -{ - if (getMode() == kRebakeNavMesh_RequestSent) - { - setMode(pResponseStatus ? kRebakeNavMesh_InProgress : kRebakeNavMesh_Default); - } - - if (!pResponseStatus) - { - LLNotificationsUtil::add("PathfindingCannotRebakeNavmesh"); - } -} - -void LLPanelPathfindingRebakeNavmesh::handleNavMeshStatus(const LLPathfindingNavMeshStatus &pNavMeshStatus) -{ - ERebakeNavMeshMode rebakeNavMeshMode = kRebakeNavMesh_Default; - if (pNavMeshStatus.isValid()) - { - switch (pNavMeshStatus.getStatus()) - { - case LLPathfindingNavMeshStatus::kPending : - case LLPathfindingNavMeshStatus::kRepending : - rebakeNavMeshMode = kRebakeNavMesh_Available; - break; - case LLPathfindingNavMeshStatus::kBuilding : - rebakeNavMeshMode = kRebakeNavMesh_InProgress; - break; - case LLPathfindingNavMeshStatus::kComplete : - rebakeNavMeshMode = kRebakeNavMesh_NotAvailable; - break; - default : - rebakeNavMeshMode = kRebakeNavMesh_Default; - llassert(0); - break; - } - } - - setMode(rebakeNavMeshMode); -} - -void LLPanelPathfindingRebakeNavmesh::handleRegionBoundaryCrossed() -{ - createNavMeshStatusListenerForCurrentRegion(); - mCanRebakeRegion = FALSE; - LLPathfindingManager::getInstance()->requestGetAgentState(); -} - -void LLPanelPathfindingRebakeNavmesh::createNavMeshStatusListenerForCurrentRegion() -{ - if (mNavMeshSlot.connected()) - { - mNavMeshSlot.disconnect(); - } - - LLViewerRegion *currentRegion = gAgent.getRegion(); - if (currentRegion != NULL) - { - mNavMeshSlot = LLPathfindingManager::getInstance()->registerNavMeshListenerForRegion(currentRegion, boost::bind(&LLPanelPathfindingRebakeNavmesh::handleNavMeshStatus, this, _2)); - LLPathfindingManager::getInstance()->requestGetNavMeshForRegion(currentRegion, true); - } -} - -bool LLPanelPathfindingRebakeNavmesh::doDraw() const -{ - return (mCanRebakeRegion && (mRebakeNavMeshMode != kRebakeNavMesh_NotAvailable)); -} - -void LLPanelPathfindingRebakeNavmesh::updatePosition() -{ -#if 0 - S32 y_pos = 0; - S32 bottom_tb_center = 0; - - if (LLToolBar* toolbar_bottom = gToolBarView->getChild("toolbar_bottom")) - { - y_pos = toolbar_bottom->getRect().getHeight(); - bottom_tb_center = toolbar_bottom->getRect().getCenterX(); - } - - S32 left_tb_width = 0; - if (LLToolBar* toolbar_left = gToolBarView->getChild("toolbar_left")) - { - left_tb_width = toolbar_left->getRect().getWidth(); - } - - if(LLPanel* panel_ssf_container = getRootView()->getChild("state_management_buttons_container")) - { - panel_ssf_container->setOrigin(0, y_pos); - } - - S32 x_pos = bottom_tb_center-getRect().getWidth()/2 - left_tb_width + 113 /* width of stand/fly button *//* + 10 *//* margin */; - - /*setOrigin( x_pos, 0);*/ -#endif -} diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp new file mode 100644 index 000000000..42db9fdd6 --- /dev/null +++ b/indra/newview/llpanelprofile.cpp @@ -0,0 +1,441 @@ +/** +* @file llpanelprofile.cpp +* @brief Profile panel implementation +* +* $LicenseInfo:firstyear=2009&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "llpanelprofile.h" + +#ifdef AI_UNUSED +#include "llagent.h" +#include "llavataractions.h" +#include "llfloaterreg.h" +#include "llcommandhandler.h" +#include "llnotificationsutil.h" +#include "llpanelpicks.h" +#include "lltabcontainer.h" +#include "llviewercontrol.h" +#include "llviewernetwork.h" + +static const std::string PANEL_PICKS = "panel_picks"; +#endif // AI_UNUSED + +#include "hippogridmanager.h" +#include "llcontrol.h" +#include "llweb.h" + +std::string getProfileURL(const std::string& agent_name) +{ + std::string url; + + if (gHippoGridManager->getConnectedGrid()->isInProductionGrid()) + { + url = gSavedSettings.getString("WebProfileURL"); + } + else + { + url = gSavedSettings.getString("WebProfileNonProductionURL"); + } + LLSD subs; + subs["AGENT_NAME"] = agent_name; + url = LLWeb::expandURLSubstitutions(url,subs); + LLStringUtil::toLower(url); + return url; +} + +#ifdef AI_UNUSED +class LLProfileHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLProfileHandler() : LLCommandHandler("profile", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, + LLMediaCtrl* web) + { + if (params.size() < 1) return false; + std::string agent_name = params[0]; + llinfos << "Profile, agent_name " << agent_name << llendl; + std::string url = getProfileURL(agent_name); + LLWeb::loadURLInternal(url); + + return true; + } +}; +LLProfileHandler gProfileHandler; + +class LLAgentHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, + LLMediaCtrl* web) + { + if (params.size() < 2) return false; + LLUUID avatar_id; + if (!avatar_id.set(params[0], FALSE)) + { + return false; + } + + const std::string verb = params[1].asString(); + if (verb == "about") + { + LLAvatarActions::showProfile(avatar_id); + return true; + } + + if (verb == "inspect") + { + LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id)); + return true; + } + + if (verb == "im") + { + LLAvatarActions::startIM(avatar_id); + return true; + } + + if (verb == "pay") + { + if (!LLUI::sSettingGroups["config"]->getBOOL("EnableAvatarPay")) + { + LLNotificationsUtil::add("NoAvatarPay", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); + return true; + } + + 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; + } +}; +LLAgentHandler gAgentHandler; + + +//-- LLPanelProfile::ChildStack begins ---------------------------------------- +LLPanelProfile::ChildStack::ChildStack() +: mParent(NULL) +{ +} + +LLPanelProfile::ChildStack::~ChildStack() +{ + while (mStack.size() != 0) + { + view_list_t& top = mStack.back(); + for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it) + { + LLView* viewp = *it; + if (viewp) + { + viewp->die(); + } + } + mStack.pop_back(); + } +} + +void LLPanelProfile::ChildStack::setParent(LLPanel* parent) +{ + llassert_always(parent != NULL); + mParent = parent; +} + +/// Save current parent's child views and remove them from the child list. +bool LLPanelProfile::ChildStack::push() +{ + view_list_t vlist = *mParent->getChildList(); + + for (view_list_t::const_iterator it = vlist.begin(); it != vlist.end(); ++it) + { + LLView* viewp = *it; + mParent->removeChild(viewp); + } + + mStack.push_back(vlist); + dump(); + return true; +} + +/// Restore saved children (adding them back to the child list). +bool LLPanelProfile::ChildStack::pop() +{ + if (mStack.size() == 0) + { + llwarns << "Empty stack" << llendl; + llassert(mStack.size() == 0); + return false; + } + + view_list_t& top = mStack.back(); + for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it) + { + LLView* viewp = *it; + mParent->addChild(viewp); + } + + mStack.pop_back(); + dump(); + return true; +} + +/// Temporarily add all saved children back. +void LLPanelProfile::ChildStack::preParentReshape() +{ + mSavedStack = mStack; + while(mStack.size() > 0) + { + pop(); + } +} + +/// Add the temporarily saved children back. +void LLPanelProfile::ChildStack::postParentReshape() +{ + mStack = mSavedStack; + mSavedStack = stack_t(); + + for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it) + { + const view_list_t& vlist = (*stack_it); + for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) + { + LLView* viewp = *list_it; + lldebugs << "removing " << viewp->getName() << llendl; + mParent->removeChild(viewp); + } + } +} + +void LLPanelProfile::ChildStack::dump() +{ + unsigned lvl = 0; + lldebugs << "child stack dump:" << llendl; + for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it, ++lvl) + { + std::ostringstream dbg_line; + dbg_line << "lvl #" << lvl << ":"; + const view_list_t& vlist = (*stack_it); + for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it) + { + dbg_line << " " << (*list_it)->getName(); + } + lldebugs << dbg_line.str() << llendl; + } +} + +//-- LLPanelProfile::ChildStack ends ------------------------------------------ + +LLPanelProfile::LLPanelProfile() + : LLPanel() + , mAvatarId(LLUUID::null) +{ + mChildStack.setParent(this); +} + +BOOL LLPanelProfile::postBuild() +{ + LLPanelPicks* panel_picks = findChild(PANEL_PICKS); + panel_picks->setProfilePanel(this); + + getTabContainer()[PANEL_PICKS] = panel_picks; + + return TRUE; +} + +// virtual +void LLPanelProfile::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + // Temporarily add saved children back and reshape them. + mChildStack.preParentReshape(); + LLPanel::reshape(width, height, called_from_parent); + mChildStack.postParentReshape(); +} + +void LLPanelProfile::onOpen(const LLSD& key) +{ + getTabContainer()[PANEL_PICKS]->onOpen(getAvatarId()); + + // support commands to open further pieces of UI + if (key.has("show_tab_panel")) + { + std::string panel = key["show_tab_panel"].asString(); + if (panel == "create_classified") + { + LLPanelPicks* picks = dynamic_cast(getTabContainer()[PANEL_PICKS]); + if (picks) + { + picks->createNewClassified(); + } + } + else if (panel == "classified_details") + { + LLPanelPicks* picks = dynamic_cast(getTabContainer()[PANEL_PICKS]); + if (picks) + { + LLSD params = key; + params.erase("show_tab_panel"); + params.erase("open_tab_name"); + picks->openClassifiedInfo(params); + } + } + else if (panel == "edit_classified") + { + LLPanelPicks* picks = dynamic_cast(getTabContainer()[PANEL_PICKS]); + if (picks) + { + LLSD params = key; + params.erase("show_tab_panel"); + params.erase("open_tab_name"); + picks->openClassifiedEdit(params); + } + } + else if (panel == "create_pick") + { + LLPanelPicks* picks = dynamic_cast(getTabContainer()[PANEL_PICKS]); + if (picks) + { + picks->createNewPick(); + } + } + else if (panel == "edit_pick") + { + LLPanelPicks* picks = dynamic_cast(getTabContainer()[PANEL_PICKS]); + if (picks) + { + LLSD params = key; + params.erase("show_tab_panel"); + params.erase("open_tab_name"); + picks->openPickEdit(params); + } + } + } +} + +void LLPanelProfile::onTabSelected(const LLSD& param) +{ + std::string tab_name = param.asString(); + if (NULL != getTabContainer()[tab_name]) + { + getTabContainer()[tab_name]->onOpen(getAvatarId()); + } +} + +void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params) +{ + // Hide currently visible panel (STORM-690). + mChildStack.push(); + + // Add the panel or bring it to front. + if (panel->getParent() != this) + { + addChild(panel); + } + else + { + sendChildToFront(panel); + } + + panel->setVisible(TRUE); + panel->setFocus(TRUE); // prevent losing focus by the floater + panel->onOpen(params); + + LLRect new_rect = getRect(); + panel->reshape(new_rect.getWidth(), new_rect.getHeight()); + new_rect.setLeftTopAndSize(0, new_rect.getHeight(), new_rect.getWidth(), new_rect.getHeight()); + panel->setRect(new_rect); +} + +void LLPanelProfile::closePanel(LLPanel* panel) +{ + panel->setVisible(FALSE); + + if (panel->getParent() == this) + { + removeChild(panel); + + // Make the underlying panel visible. + mChildStack.pop(); + + // Prevent losing focus by the floater + const child_list_t* child_list = getChildList(); + if (child_list->size() > 0) + { + child_list->front()->setFocus(TRUE); + } + else + { + llwarns << "No underlying panel to focus." << llendl; + } + } +} + +S32 LLPanelProfile::notifyParent(const LLSD& info) +{ + std::string action = info["action"]; + // lets update Picks list after Pick was saved + if("save_new_pick" == action) + { + onOpen(info); + return 1; + } + + return LLPanel::notifyParent(info); +} +#endif // AI_UNUSED diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h new file mode 100644 index 000000000..73539dda2 --- /dev/null +++ b/indra/newview/llpanelprofile.h @@ -0,0 +1,106 @@ +/** +* @file llpanelprofile.h +* @brief Profile panel +* +* $LicenseInfo:firstyear=2009&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_LLPANELPROFILE_H +#define LL_LLPANELPROFILE_H + +#ifdef AI_UNUSED +#include "llpanel.h" +#include "llpanelavatar.h" + +class LLTabContainer; +#endif // AI_UNUSED + +std::string getProfileURL(const std::string& agent_name); + +#ifdef AI_UNUSED +/** +* Base class for Profile View and My Profile. +*/ +class LLPanelProfile : public LLPanel +{ + LOG_CLASS(LLPanelProfile); + +public: + /*virtual*/ BOOL postBuild(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void onOpen(const LLSD& key); + + virtual void openPanel(LLPanel* panel, const LLSD& params); + + virtual void closePanel(LLPanel* panel); + + S32 notifyParent(const LLSD& info); + +protected: + + LLPanelProfile(); + + virtual void onTabSelected(const LLSD& param); + + const LLUUID& getAvatarId() { return mAvatarId; } + + void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; } + + typedef std::map profile_tabs_t; + + profile_tabs_t& getTabContainer() { return mTabContainer; } + +private: + + //-- ChildStack begins ---------------------------------------------------- + class ChildStack + { + LOG_CLASS(LLPanelProfile::ChildStack); + public: + ChildStack(); + ~ChildStack(); + void setParent(LLPanel* parent); + + bool push(); + bool pop(); + void preParentReshape(); + void postParentReshape(); + + private: + void dump(); + + typedef LLView::child_list_t view_list_t; + typedef std::list stack_t; + + stack_t mStack; + stack_t mSavedStack; + LLPanel* mParent; + }; + //-- ChildStack ends ------------------------------------------------------ + + profile_tabs_t mTabContainer; + ChildStack mChildStack; + LLUUID mAvatarId; +}; +#endif // AI_UNUSED + +#endif //LL_LLPANELPROFILE_H diff --git a/indra/newview/llpathfindinglinkset.cpp b/indra/newview/llpathfindinglinkset.cpp index fe4daabd8..50b76378f 100644 --- a/indra/newview/llpathfindinglinkset.cpp +++ b/indra/newview/llpathfindinglinkset.cpp @@ -39,6 +39,7 @@ #define LINKSET_MODIFIABLE_FIELD "modifiable" #define LINKSET_CATEGORY_FIELD "navmesh_category" #define LINKSET_CAN_BE_VOLUME "can_be_volume" +#define LINKSET_IS_SCRIPTED_FIELD "is_scripted" #define LINKSET_PHANTOM_FIELD "phantom" #define LINKSET_WALKABILITY_A_FIELD "A" #define LINKSET_WALKABILITY_B_FIELD "B" @@ -62,6 +63,8 @@ LLPathfindingLinkset::LLPathfindingLinkset(const LLSD& pTerrainData) mLandImpact(0U), mIsModifiable(FALSE), mCanBeVolume(FALSE), + mIsScripted(FALSE), + mHasIsScripted(TRUE), mLinksetUse(kUnknown), mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), @@ -77,6 +80,8 @@ LLPathfindingLinkset::LLPathfindingLinkset(const std::string &pUUID, const LLSD& mLandImpact(0U), mIsModifiable(TRUE), mCanBeVolume(TRUE), + mIsScripted(FALSE), + mHasIsScripted(FALSE), mLinksetUse(kUnknown), mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), @@ -93,6 +98,8 @@ LLPathfindingLinkset::LLPathfindingLinkset(const LLPathfindingLinkset& pOther) mLandImpact(pOther.mLandImpact), mIsModifiable(pOther.mIsModifiable), mCanBeVolume(pOther.mCanBeVolume), + mIsScripted(pOther.mIsScripted), + mHasIsScripted(pOther.mHasIsScripted), mLinksetUse(pOther.mLinksetUse), mWalkabilityCoefficientA(pOther.mWalkabilityCoefficientA), mWalkabilityCoefficientB(pOther.mWalkabilityCoefficientB), @@ -113,6 +120,8 @@ LLPathfindingLinkset& LLPathfindingLinkset::operator =(const LLPathfindingLinkse mLandImpact = pOther.mLandImpact; mIsModifiable = pOther.mIsModifiable; mCanBeVolume = pOther.mCanBeVolume; + mIsScripted = pOther.mIsScripted; + mHasIsScripted = pOther.mHasIsScripted; mLinksetUse = pOther.mLinksetUse; mWalkabilityCoefficientA = pOther.mWalkabilityCoefficientA; mWalkabilityCoefficientB = pOther.mWalkabilityCoefficientB; @@ -140,6 +149,11 @@ bool LLPathfindingLinkset::isShowUnmodifiablePhantomWarning(ELinksetUse pLinkset return (!isModifiable() && (isPhantom() != isPhantom(pLinksetUse))); } +bool LLPathfindingLinkset::isShowPhantomToggleWarning(ELinksetUse pLinksetUse) const +{ + return (isModifiable() && (isPhantom() != isPhantom(pLinksetUse))); +} + bool LLPathfindingLinkset::isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const { return (!canBeVolume() && ((pLinksetUse == kMaterialVolume) || (pLinksetUse == kExclusionVolume))); @@ -193,6 +207,13 @@ void LLPathfindingLinkset::parseLinksetData(const LLSD &pLinksetData) llassert(pLinksetData.has(LINKSET_MODIFIABLE_FIELD)); llassert(pLinksetData.get(LINKSET_MODIFIABLE_FIELD).isBoolean()); mIsModifiable = pLinksetData.get(LINKSET_MODIFIABLE_FIELD).asBoolean(); + + mHasIsScripted = pLinksetData.has(LINKSET_IS_SCRIPTED_FIELD); + if (mHasIsScripted) + { + llassert(pLinksetData.get(LINKSET_IS_SCRIPTED_FIELD).isBoolean()); + mIsScripted = pLinksetData.get(LINKSET_IS_SCRIPTED_FIELD).asBoolean(); + } } void LLPathfindingLinkset::parsePathfindingData(const LLSD &pLinksetData) diff --git a/indra/newview/llpathfindinglinkset.h b/indra/newview/llpathfindinglinkset.h index 73b4d6bad..308a3a1e0 100644 --- a/indra/newview/llpathfindinglinkset.h +++ b/indra/newview/llpathfindinglinkset.h @@ -63,12 +63,16 @@ public: inline ELinksetUse getLinksetUse() const {return mLinksetUse;}; + inline BOOL isScripted() const {return mIsScripted;}; + inline BOOL hasIsScripted() const {return mHasIsScripted;}; + inline S32 getWalkabilityCoefficientA() const {return mWalkabilityCoefficientA;}; inline S32 getWalkabilityCoefficientB() const {return mWalkabilityCoefficientB;}; inline S32 getWalkabilityCoefficientC() const {return mWalkabilityCoefficientC;}; inline S32 getWalkabilityCoefficientD() const {return mWalkabilityCoefficientD;}; bool isShowUnmodifiablePhantomWarning(ELinksetUse pLinksetUse) const; + bool isShowPhantomToggleWarning(ELinksetUse pLinksetUse) const; bool isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const; LLSD encodeAlteredFields(ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; @@ -98,6 +102,8 @@ private: U32 mLandImpact; BOOL mIsModifiable; BOOL mCanBeVolume; + BOOL mIsScripted; + BOOL mHasIsScripted; ELinksetUse mLinksetUse; S32 mWalkabilityCoefficientA; S32 mWalkabilityCoefficientB; diff --git a/indra/newview/llpathfindinglinksetlist.cpp b/indra/newview/llpathfindinglinksetlist.cpp index 746fa342a..b886e4676 100644 --- a/indra/newview/llpathfindinglinksetlist.cpp +++ b/indra/newview/llpathfindinglinksetlist.cpp @@ -113,6 +113,20 @@ bool LLPathfindingLinksetList::isShowUnmodifiablePhantomWarning(LLPathfindingLin return isShowWarning; } +bool LLPathfindingLinksetList::isShowPhantomToggleWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const +{ + bool isShowWarning = false; + + for (const_iterator objectIter = begin(); !isShowWarning && (objectIter != end()); ++objectIter) + { + const LLPathfindingObjectPtr objectPtr = objectIter->second; + const LLPathfindingLinkset *linkset = dynamic_cast(objectPtr.get()); + isShowWarning = linkset->isShowPhantomToggleWarning(pLinksetUse); + } + + return isShowWarning; +} + bool LLPathfindingLinksetList::isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const { bool isShowWarning = false; diff --git a/indra/newview/llpathfindinglinksetlist.h b/indra/newview/llpathfindinglinksetlist.h index 77c635864..1d38e4c11 100644 --- a/indra/newview/llpathfindinglinksetlist.h +++ b/indra/newview/llpathfindinglinksetlist.h @@ -43,6 +43,7 @@ public: LLSD encodeTerrainFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; bool isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; + bool isShowPhantomToggleWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; bool isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; void determinePossibleStates(BOOL &pCanBeWalkable, BOOL &pCanBeStaticObstacle, BOOL &pCanBeDynamicObstacle, diff --git a/indra/newview/llpathfindingobject.cpp b/indra/newview/llpathfindingobject.cpp index 916eceb4c..858d3203c 100644 --- a/indra/newview/llpathfindingobject.cpp +++ b/indra/newview/llpathfindingobject.cpp @@ -55,8 +55,10 @@ LLPathfindingObject::LLPathfindingObject() mOwnerUUID(), mHasOwnerName(false), mOwnerName(), + mAvatarNameCacheConnection(), mIsGroupOwned(false), - mLocation() + mLocation(), + mOwnerNameSignal() { } @@ -67,8 +69,10 @@ LLPathfindingObject::LLPathfindingObject(const std::string &pUUID, const LLSD &p mOwnerUUID(), mHasOwnerName(false), mOwnerName(), + mAvatarNameCacheConnection(), mIsGroupOwned(false), - mLocation() + mLocation(), + mOwnerNameSignal() { parseObjectData(pObjectData); } @@ -80,14 +84,17 @@ LLPathfindingObject::LLPathfindingObject(const LLPathfindingObject& pOther) mOwnerUUID(pOther.mOwnerUUID), mHasOwnerName(false), mOwnerName(), + mAvatarNameCacheConnection(), mIsGroupOwned(pOther.mIsGroupOwned), - mLocation(pOther.mLocation) + mLocation(pOther.mLocation), + mOwnerNameSignal() { fetchOwnerName(); } LLPathfindingObject::~LLPathfindingObject() { + disconnectAvatarNameCacheConnection(); } LLPathfindingObject &LLPathfindingObject::operator =(const LLPathfindingObject& pOther) @@ -115,6 +122,23 @@ std::string LLPathfindingObject::getOwnerName() const return ownerName; } +LLPathfindingObject::name_connection_t LLPathfindingObject::registerOwnerNameListener(name_callback_t pOwnerNameCallback) +{ + llassert(hasOwner()); + + name_connection_t connection; + if (hasOwnerName()) + { + pOwnerNameCallback(this); + } + else + { + connection = mOwnerNameSignal.connect(pOwnerNameCallback); + } + + return connection; +} + void LLPathfindingObject::parseObjectData(const LLSD &pObjectData) { llassert(pObjectData.has(PATHFINDING_OBJECT_NAME_FIELD)); @@ -149,7 +173,7 @@ void LLPathfindingObject::fetchOwnerName() mHasOwnerName = LLAvatarNameCache::get(mOwnerUUID, &mOwnerName); if (!mHasOwnerName) { - LLAvatarNameCache::get(mOwnerUUID, boost::bind(&LLPathfindingObject::handleAvatarNameFetch, this, _1, _2)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(mOwnerUUID, boost::bind(&LLPathfindingObject::handleAvatarNameFetch, this, _1, _2)); } } } @@ -157,6 +181,19 @@ void LLPathfindingObject::fetchOwnerName() void LLPathfindingObject::handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName) { llassert(mOwnerUUID == pOwnerUUID); + mOwnerName = pAvatarName; mHasOwnerName = true; + + disconnectAvatarNameCacheConnection(); + + mOwnerNameSignal(this); +} + +void LLPathfindingObject::disconnectAvatarNameCacheConnection() +{ + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } } diff --git a/indra/newview/llpathfindingobject.h b/indra/newview/llpathfindingobject.h index d45cc554f..b8d3ca236 100644 --- a/indra/newview/llpathfindingobject.h +++ b/indra/newview/llpathfindingobject.h @@ -30,8 +30,11 @@ #include #include +#include +#include #include "llavatarname.h" +#include "llavatarnamecache.h" #include "lluuid.h" #include "v3math.h" @@ -59,6 +62,12 @@ public: inline BOOL isGroupOwned() const {return mIsGroupOwned;}; inline const LLVector3& getLocation() const {return mLocation;}; + typedef boost::function name_callback_t; + typedef boost::signals2::signal name_signal_t; + typedef boost::signals2::connection name_connection_t; + + name_connection_t registerOwnerNameListener(name_callback_t pOwnerNameCallback); + protected: private: @@ -66,15 +75,18 @@ private: void fetchOwnerName(); void handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName); + void disconnectAvatarNameCacheConnection(); - LLUUID mUUID; - std::string mName; - std::string mDescription; - LLUUID mOwnerUUID; - bool mHasOwnerName; - LLAvatarName mOwnerName; - BOOL mIsGroupOwned; - LLVector3 mLocation; + LLUUID mUUID; + std::string mName; + std::string mDescription; + LLUUID mOwnerUUID; + bool mHasOwnerName; + LLAvatarName mOwnerName; + LLAvatarNameCache::callback_connection_t mAvatarNameCacheConnection; + BOOL mIsGroupOwned; + LLVector3 mLocation; + name_signal_t mOwnerNameSignal; }; #endif // LL_LLPATHFINDINGOBJECT_H diff --git a/indra/newview/llpathfindingobjectlist.cpp b/indra/newview/llpathfindingobjectlist.cpp index 68a7e736e..f1ecb45fc 100644 --- a/indra/newview/llpathfindingobjectlist.cpp +++ b/indra/newview/llpathfindingobjectlist.cpp @@ -45,6 +45,7 @@ LLPathfindingObjectList::LLPathfindingObjectList() LLPathfindingObjectList::~LLPathfindingObjectList() { + clear(); } bool LLPathfindingObjectList::isEmpty() const @@ -52,6 +53,15 @@ bool LLPathfindingObjectList::isEmpty() const return mObjectMap.empty(); } +void LLPathfindingObjectList::clear() +{ + for (LLPathfindingObjectMap::iterator objectIter = mObjectMap.begin(); objectIter != mObjectMap.end(); ++objectIter) + { + objectIter->second.reset(); + } + mObjectMap.clear(); +} + void LLPathfindingObjectList::update(LLPathfindingObjectPtr pUpdateObjectPtr) { if (pUpdateObjectPtr != NULL) diff --git a/indra/newview/llpathfindingobjectlist.h b/indra/newview/llpathfindingobjectlist.h index 3ad8e8b09..61580582d 100644 --- a/indra/newview/llpathfindingobjectlist.h +++ b/indra/newview/llpathfindingobjectlist.h @@ -47,6 +47,8 @@ public: bool isEmpty() const; + void clear(); + void update(LLPathfindingObjectPtr pUpdateObjectPtr); void update(LLPathfindingObjectListPtr pUpdateObjectListPtr); @@ -56,7 +58,6 @@ public: const_iterator begin() const; const_iterator end() const; - protected: LLPathfindingObjectMap &getObjectMap(); diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index 1265ed7c7..7eae05c10 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -125,28 +125,28 @@ void LLPolyMeshSharedData::setupLOD(LLPolyMeshSharedData* reference_data) //----------------------------------------------------------------------------- void LLPolyMeshSharedData::freeMeshData() { - if (!mReferenceData) - { - mNumVertices = 0; + if (!mReferenceData) + { + mNumVertices = 0; - delete [] mBaseCoords; - mBaseCoords = NULL; + ll_aligned_free_16(mBaseCoords); + mBaseCoords = NULL; - delete [] mBaseNormals; - mBaseNormals = NULL; + ll_aligned_free_16(mBaseNormals); + mBaseNormals = NULL; - delete [] mBaseBinormals; - mBaseBinormals = NULL; + ll_aligned_free_16(mBaseBinormals); + mBaseBinormals = NULL; - delete [] mTexCoords; - mTexCoords = NULL; + ll_aligned_free_16(mTexCoords); + mTexCoords = NULL; - delete [] mDetailTexCoords; - mDetailTexCoords = NULL; + ll_aligned_free_16(mDetailTexCoords); + mDetailTexCoords = NULL; - delete [] mWeights; - mWeights = NULL; - } + ll_aligned_free_16(mWeights); + mWeights = NULL; + } mNumFaces = 0; delete [] mFaces; @@ -228,14 +228,14 @@ U32 LLPolyMeshSharedData::getNumKB() //----------------------------------------------------------------------------- BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) { - U32 i; - mBaseCoords = new LLVector4a[ numVertices ]; - mBaseNormals = new LLVector4a[ numVertices ]; - mBaseBinormals = new LLVector4a[ numVertices ]; - mTexCoords = new LLVector2[ numVertices ]; - mDetailTexCoords = new LLVector2[ numVertices ]; - mWeights = new F32[ numVertices ]; - for (i = 0; i < numVertices; i++) + U32 i; + mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseNormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseBinormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32)); + for (i = 0; i < numVertices; i++) { mBaseCoords[i].clear(); mBaseNormals[i].clear(); diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h index d09909309..184372a95 100644 --- a/indra/newview/llpolymesh.h +++ b/indra/newview/llpolymesh.h @@ -428,6 +428,16 @@ public: LLPolySkeletalDistortion(LLVOAvatar *avatarp); ~LLPolySkeletalDistortion(); + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + // Special: These functions are overridden by child classes LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; } // This sets mInfo and calls initialization functions diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index cfbe6907c..3524cb057 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -74,9 +74,9 @@ LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : { const S32 numVertices = mNumIndices; - mCoords = new LLVector4a[numVertices]; - mNormals = new LLVector4a[numVertices]; - mBinormals = new LLVector4a[numVertices]; + mCoords = static_cast(ll_aligned_malloc_16(numVertices * sizeof(LLVector4a))); + mNormals = static_cast(ll_aligned_malloc_16(numVertices * sizeof(LLVector4a))); + mBinormals = static_cast(ll_aligned_malloc_16(numVertices * sizeof(LLVector4a))); mTexCoords = new LLVector2[numVertices]; mVertexIndices = new U32[numVertices]; @@ -90,17 +90,12 @@ LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : } } - //----------------------------------------------------------------------------- // ~LLPolyMorphData() //----------------------------------------------------------------------------- LLPolyMorphData::~LLPolyMorphData() { - delete [] mVertexIndices; - delete [] mCoords; - delete [] mNormals; - delete [] mBinormals; - delete [] mTexCoords; + freeData(); } //----------------------------------------------------------------------------- @@ -119,12 +114,17 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) return FALSE; } + //------------------------------------------------------------------------- + // free any existing data + //------------------------------------------------------------------------- + freeData(); + //------------------------------------------------------------------------- // allocate vertices //------------------------------------------------------------------------- - mCoords = new LLVector4a[numVertices]; - mNormals = new LLVector4a[numVertices]; - mBinormals = new LLVector4a[numVertices]; + mCoords = static_cast(ll_aligned_malloc_16(numVertices * sizeof(LLVector4a))); + mNormals = static_cast(ll_aligned_malloc_16(numVertices * sizeof(LLVector4a))); + mBinormals = static_cast(ll_aligned_malloc_16(numVertices * sizeof(LLVector4a))); mTexCoords = new LLVector2[numVertices]; // Actually, we are allocating more space than we need for the skiplist mVertexIndices = new U32[numVertices]; @@ -207,6 +207,42 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) return TRUE; } +//----------------------------------------------------------------------------- +// freeData() +//----------------------------------------------------------------------------- +void LLPolyMorphData::freeData() +{ + if (mCoords != NULL) + { + ll_aligned_free_16(mCoords); + mCoords = NULL; + } + + if (mNormals != NULL) + { + ll_aligned_free_16(mNormals); + mNormals = NULL; + } + + if (mBinormals != NULL) + { + ll_aligned_free_16(mBinormals); + mBinormals = NULL; + } + + if (mTexCoords != NULL) + { + delete [] mTexCoords; + mTexCoords = NULL; + } + + if (mVertexIndices != NULL) + { + delete [] mVertexIndices; + mVertexIndices = NULL; + } +} + //----------------------------------------------------------------------------- // LLPolyMesh::saveLLM() //----------------------------------------------------------------------------- @@ -354,9 +390,9 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) if (num_significant == 0) nindices = 1; - LLVector4a* new_coords = new LLVector4a[nindices]; - LLVector4a* new_normals = new LLVector4a[nindices]; - LLVector4a* new_binormals = new LLVector4a[nindices]; + LLVector4a* new_coords = static_cast(ll_aligned_malloc_16(nindices * sizeof(LLVector4a))); + LLVector4a* new_normals = static_cast(ll_aligned_malloc_16(nindices * sizeof(LLVector4a))); + LLVector4a* new_binormals = static_cast(ll_aligned_malloc_16(nindices * sizeof(LLVector4a))); LLVector2* new_tex_coords = new LLVector2[nindices]; U32* new_vertex_indices = new U32[nindices]; @@ -490,11 +526,7 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) //------------------------------------------------------------------------- // reallocate vertices //------------------------------------------------------------------------- - delete [] mVertexIndices; - delete [] mCoords; - delete [] mNormals; - delete [] mBinormals; - delete [] mTexCoords; + freeData(); mVertexIndices = new_vertex_indices; mCoords = new_coords; diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h index dac698437..02f5be42f 100644 --- a/indra/newview/llpolymorph.h +++ b/indra/newview/llpolymorph.h @@ -54,6 +54,16 @@ public: ~LLPolyMorphData(); LLPolyMorphData(const LLPolyMorphData &rhs); + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + BOOL loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh); const std::string& getName() { return mName; } @@ -77,6 +87,9 @@ public: F32 mMaxDistortion; // maximum single vertex distortion in a given morph LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph LLPolyMeshSharedData* mMesh; + +private: + void freeData(); }; //----------------------------------------------------------------------------- diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index ecb260704..8349b5e03 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -120,70 +120,67 @@ struct SortItemPtrsByName // static LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& item_id, const LLUUID& object_id, BOOL take_focus) { - LLPreviewGesture* previewp = (LLPreviewGesture*)LLPreview::find(item_id); - if (previewp) + LLPreviewGesture* preview = (LLPreviewGesture*)LLPreview::find(item_id); + if (preview) { - previewp->open(); /*Flawfinder: ignore*/ - if (take_focus) + preview->open(); /*Flawfinder: ignore*/ + } + else + { + preview = new LLPreviewGesture(); + + // Finish internal construction + preview->init(item_id, object_id); + + // Builds and adds to gFloaterView + LLUICtrlFactory::getInstance()->buildFloater(preview, "floater_preview_gesture.xml"); + preview->setTitle(title); + + // Move window to top-left of screen + LLMultiFloater* hostp = preview->getHost(); + if (hostp == NULL) { - previewp->setFocus(TRUE); + LLRect r = preview->getRect(); + LLRect screen = gFloaterView->getRect(); + r.setLeftTopAndSize(0, screen.getHeight(), r.getWidth(), r.getHeight()); + preview->setRect(r); + } + else + { + // re-add to host to update title + hostp->addFloater(preview, TRUE); } - return previewp; - } - LLPreviewGesture* self = new LLPreviewGesture(); + // Start speculative download of sounds and animations + const LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ANIMATION); + LLInventoryModelBackgroundFetch::instance().start(animation_folder_id); - // Finish internal construction - self->init(item_id, object_id); + const LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SOUND); + LLInventoryModelBackgroundFetch::instance().start(sound_folder_id); - // Builds and adds to gFloaterView - LLUICtrlFactory::getInstance()->buildFloater(self, "floater_preview_gesture.xml"); - self->setTitle(title); - - // Move window to top-left of screen - LLMultiFloater* hostp = self->getHost(); - if (hostp == NULL) - { - LLRect r = self->getRect(); - LLRect screen = gFloaterView->getRect(); - r.setLeftTopAndSize(0, screen.getHeight(), r.getWidth(), r.getHeight()); - self->setRect(r); - } - else - { - // re-add to host to update title - hostp->addFloater(self, TRUE); - } - - // Start speculative download of sounds and animations - LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ANIMATION); - LLInventoryModelBackgroundFetch::instance().start(animation_folder_id); - - LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SOUND); - LLInventoryModelBackgroundFetch::instance().start(sound_folder_id); - - // this will call refresh when we have everything. - LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem(); - if (item && !item->isFinished()) - { - LLInventoryGestureAvailable* observer; - observer = new LLInventoryGestureAvailable(); - observer->watchItem(item_id); - gInventory.addObserver(observer); - item->fetchFromServer(); - } - else - { - // not sure this is necessary. - self->refresh(); + // this will call refresh when we have everything. + LLViewerInventoryItem* item = (LLViewerInventoryItem*)preview->getItem(); + if (item && !item->isFinished()) + { + LLInventoryGestureAvailable* observer; + observer = new LLInventoryGestureAvailable(); + observer->watchItem(item_id); + gInventory.addObserver(observer); + item->fetchFromServer(); + } + else + { + // not sure this is necessary. + preview->refresh(); + } } if (take_focus) { - self->setFocus(TRUE); + preview->setFocus(TRUE); } - return self; + return preview; } void LLPreviewGesture::draw() @@ -334,7 +331,7 @@ bool LLPreviewGesture::handleSaveChangesDialog(const LLSD& notification, const L case 0: // "Yes" LLGestureMgr::instance().stopGesture(mPreviewGesture); mCloseAfterSave = TRUE; - onClickSave(this); + onClickSave(); break; case 1: // "No" @@ -403,9 +400,9 @@ BOOL LLPreviewGesture::postBuild() edit = getChild("trigger_editor"); edit->setKeystrokeCallback(onKeystrokeCommit); - edit->setCommitCallback(onCommitSetDirty); - edit->setCommitOnFocusLost(TRUE); edit->setCallbackUserData(this); + edit->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitSetDirty,this)); + edit->setCommitOnFocusLost(TRUE); edit->setIgnoreTab(TRUE); mTriggerEditor = edit; @@ -416,26 +413,24 @@ BOOL LLPreviewGesture::postBuild() edit = getChild("replace_editor"); edit->setEnabled(FALSE); edit->setKeystrokeCallback(onKeystrokeCommit); - edit->setCommitCallback(onCommitSetDirty); - edit->setCommitOnFocusLost(TRUE); edit->setCallbackUserData(this); + edit->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitSetDirty,this)); + edit->setCommitOnFocusLost(TRUE); + edit->setIgnoreTab(TRUE); mReplaceEditor = edit; combo = getChild( "modifier_combo"); - combo->setCommitCallback(onCommitSetDirty); - combo->setCallbackUserData(this); + combo->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitSetDirty,this)); mModifierCombo = combo; combo = getChild( "key_combo"); - combo->setCommitCallback(onCommitSetDirty); - combo->setCallbackUserData(this); + combo->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitSetDirty,this)); mKeyCombo = combo; list = getChild("library_list"); - list->setCommitCallback(onCommitLibrary); - list->setDoubleClickCallback(onClickAdd); - list->setCallbackUserData(this); + list->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitLibrary,this)); + list->setDoubleClickCallback(boost::bind(&LLPreviewGesture::onClickAdd,this)); mLibraryList = list; btn = getChild( "add_btn"); @@ -459,8 +454,7 @@ BOOL LLPreviewGesture::postBuild() mDeleteBtn = btn; list = getChild("step_list"); - list->setCommitCallback(onCommitStep); - list->setCallbackUserData(this); + list->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitStep,this)); mStepList = list; // Options @@ -470,42 +464,38 @@ BOOL LLPreviewGesture::postBuild() combo = getChild( "animation_list"); combo->setVisible(FALSE); - combo->setCommitCallback(onCommitAnimation); - combo->setCallbackUserData(this); + combo->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitAnimation,this)); mAnimationCombo = combo; LLRadioGroup* group; group = getChild("animation_trigger_type"); group->setVisible(FALSE); - group->setCommitCallback(onCommitAnimationTrigger); - group->setCallbackUserData(this); + group->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitAnimationTrigger,this)); mAnimationRadio = group; combo = getChild( "sound_list"); combo->setVisible(FALSE); - combo->setCommitCallback(onCommitSound); - combo->setCallbackUserData(this); + combo->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitSound,this)); mSoundCombo = combo; edit = getChild("chat_editor"); edit->setVisible(FALSE); - edit->setCommitCallback(onCommitChat); + edit->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitChat,this)); //edit->setKeystrokeCallback(onKeystrokeCommit); + //edit->setCallbackUserData(this); edit->setCommitOnFocusLost(TRUE); - edit->setCallbackUserData(this); + edit->setIgnoreTab(TRUE); mChatEditor = edit; check = getChild( "wait_anim_check"); check->setVisible(FALSE); - check->setCommitCallback(onCommitWait); - check->setCallbackUserData(this); + check->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitWait,this)); mWaitAnimCheck = check; check = getChild( "wait_time_check"); check->setVisible(FALSE); - check->setCommitCallback(onCommitWait); - check->setCallbackUserData(this); + check->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitWait,this)); mWaitTimeCheck = check; edit = getChild("wait_time_editor"); @@ -513,26 +503,24 @@ BOOL LLPreviewGesture::postBuild() edit->setVisible(FALSE); edit->setPrevalidate(LLLineEditor::prevalidateFloat); // edit->setKeystrokeCallback(onKeystrokeCommit); + //edit->setCallbackUserData(this); edit->setCommitOnFocusLost(TRUE); - edit->setCommitCallback(onCommitWaitTime); - edit->setCallbackUserData(this); + edit->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitWaitTime,this)); + edit->setIgnoreTab(TRUE); mWaitTimeEditor = edit; // Buttons at the bottom check = getChild( "active_check"); - check->setCommitCallback(onCommitActive); - check->setCallbackUserData(this); + check->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitActive,this)); mActiveCheck = check; btn = getChild( "save_btn"); btn->setClickedCallback(boost::bind(&LLPreviewGesture::onClickSave,this)); - btn->setCallbackUserData(this); mSaveBtn = btn; btn = getChild( "preview_btn"); btn->setClickedCallback(boost::bind(&LLPreviewGesture::onClickPreview,this)); - btn->setCallbackUserData(this); mPreviewBtn = btn; @@ -940,13 +928,13 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, LLVFile file(vfs, asset_uuid, type, LLVFile::READ); S32 size = file.getSize(); - char* buffer = new char[size+1]; - file.read((U8*)buffer, size); /*Flawfinder: ignore*/ + std::vector buffer(size+1); + file.read((U8*)&buffer[0], size); buffer[size] = '\0'; LLMultiGesture* gesture = new LLMultiGesture(); - LLDataPackerAsciiBuffer dp(buffer, size+1); + LLDataPackerAsciiBuffer dp(&buffer[0], size+1); BOOL ok = gesture->deserialize(dp); if (ok) @@ -968,9 +956,6 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, delete gesture; gesture = NULL; - delete [] buffer; - buffer = NULL; - self->mAssetStatus = PREVIEW_ASSET_LOADED; } else @@ -1405,47 +1390,35 @@ void LLPreviewGesture::updateLabel(LLScrollListItem* item) text_cell->setText(label); } -// static -void LLPreviewGesture::onCommitSetDirty(LLUICtrl* ctrl, void* data) +void LLPreviewGesture::onCommitSetDirty() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - self->mDirty = TRUE; - self->refresh(); + mDirty = TRUE; + refresh(); } -// static -void LLPreviewGesture::onCommitLibrary(LLUICtrl* ctrl, void* data) +void LLPreviewGesture::onCommitLibrary() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* library_item = self->mLibraryList->getFirstSelected(); + LLScrollListItem* library_item = mLibraryList->getFirstSelected(); if (library_item) { - self->mStepList->deselectAllItems(); - self->refresh(); + mStepList->deselectAllItems(); + refresh(); } } -// static -void LLPreviewGesture::onCommitStep(LLUICtrl* ctrl, void* data) +void LLPreviewGesture::onCommitStep() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* step_item = self->mStepList->getFirstSelected(); + LLScrollListItem* step_item = mStepList->getFirstSelected(); if (!step_item) return; - self->mLibraryList->deselectAllItems(); - self->refresh(); + mLibraryList->deselectAllItems(); + refresh(); } - -// static -void LLPreviewGesture::onCommitAnimation(LLUICtrl* ctrl, void* data) +void LLPreviewGesture::onCommitAnimation() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* step_item = self->mStepList->getFirstSelected(); + LLScrollListItem* step_item = mStepList->getFirstSelected(); if (step_item) { LLGestureStep* step = (LLGestureStep*)step_item->getUserdata(); @@ -1453,40 +1426,37 @@ void LLPreviewGesture::onCommitAnimation(LLUICtrl* ctrl, void* data) { // Assign the animation name LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step; - if (self->mAnimationCombo->getCurrentIndex() == 0) + if (mAnimationCombo->getCurrentIndex() == 0) { anim_step->mAnimName.clear(); anim_step->mAnimAssetID.setNull(); } else { - anim_step->mAnimName = self->mAnimationCombo->getSimple(); - anim_step->mAnimAssetID = self->mAnimationCombo->getCurrentID(); + anim_step->mAnimName = mAnimationCombo->getSimple(); + anim_step->mAnimAssetID = mAnimationCombo->getCurrentID(); } //anim_step->mFlags = 0x0; // Update the UI label in the list updateLabel(step_item); - self->mDirty = TRUE; - self->refresh(); + mDirty = TRUE; + refresh(); } } } -// static -void LLPreviewGesture::onCommitAnimationTrigger(LLUICtrl* ctrl, void *data) +void LLPreviewGesture::onCommitAnimationTrigger() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* step_item = self->mStepList->getFirstSelected(); + LLScrollListItem* step_item = mStepList->getFirstSelected(); if (step_item) { LLGestureStep* step = (LLGestureStep*)step_item->getUserdata(); if (step->getType() == STEP_ANIMATION) { LLGestureStepAnimation* anim_step = (LLGestureStepAnimation*)step; - if (self->mAnimationRadio->getSelectedIndex() == 0) + if (mAnimationRadio->getSelectedIndex() == 0) { // start anim_step->mFlags &= ~ANIM_FLAG_STOP; @@ -1499,18 +1469,15 @@ void LLPreviewGesture::onCommitAnimationTrigger(LLUICtrl* ctrl, void *data) // Update the UI label in the list updateLabel(step_item); - self->mDirty = TRUE; - self->refresh(); + mDirty = TRUE; + refresh(); } } } -// static -void LLPreviewGesture::onCommitSound(LLUICtrl* ctrl, void* data) +void LLPreviewGesture::onCommitSound() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* step_item = self->mStepList->getFirstSelected(); + LLScrollListItem* step_item = mStepList->getFirstSelected(); if (step_item) { LLGestureStep* step = (LLGestureStep*)step_item->getUserdata(); @@ -1518,47 +1485,41 @@ void LLPreviewGesture::onCommitSound(LLUICtrl* ctrl, void* data) { // Assign the sound name LLGestureStepSound* sound_step = (LLGestureStepSound*)step; - sound_step->mSoundName = self->mSoundCombo->getSimple(); - sound_step->mSoundAssetID = self->mSoundCombo->getCurrentID(); + sound_step->mSoundName = mSoundCombo->getSimple(); + sound_step->mSoundAssetID = mSoundCombo->getCurrentID(); sound_step->mFlags = 0x0; // Update the UI label in the list updateLabel(step_item); - self->mDirty = TRUE; - self->refresh(); + mDirty = TRUE; + refresh(); } } } -// static -void LLPreviewGesture::onCommitChat(LLUICtrl* ctrl, void* data) +void LLPreviewGesture::onCommitChat() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* step_item = self->mStepList->getFirstSelected(); + LLScrollListItem* step_item = mStepList->getFirstSelected(); if (!step_item) return; LLGestureStep* step = (LLGestureStep*)step_item->getUserdata(); if (step->getType() != STEP_CHAT) return; LLGestureStepChat* chat_step = (LLGestureStepChat*)step; - chat_step->mChatText = self->mChatEditor->getText(); + chat_step->mChatText = mChatEditor->getText(); chat_step->mFlags = 0x0; // Update the UI label in the list updateLabel(step_item); - self->mDirty = TRUE; - self->refresh(); + mDirty = TRUE; + refresh(); } -// static -void LLPreviewGesture::onCommitWait(LLUICtrl* ctrl, void* data) +void LLPreviewGesture::onCommitWait() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* step_item = self->mStepList->getFirstSelected(); + LLScrollListItem* step_item = mStepList->getFirstSelected(); if (!step_item) return; LLGestureStep* step = (LLGestureStep*)step_item->getUserdata(); @@ -1566,42 +1527,39 @@ void LLPreviewGesture::onCommitWait(LLUICtrl* ctrl, void* data) LLGestureStepWait* wait_step = (LLGestureStepWait*)step; U32 flags = 0x0; - if (self->mWaitAnimCheck->get()) flags |= WAIT_FLAG_ALL_ANIM; - if (self->mWaitTimeCheck->get()) flags |= WAIT_FLAG_TIME; + if (mWaitAnimCheck->get()) flags |= WAIT_FLAG_ALL_ANIM; + if (mWaitTimeCheck->get()) flags |= WAIT_FLAG_TIME; wait_step->mFlags = flags; { LLLocale locale(LLLocale::USER_LOCALE); - F32 wait_seconds = (F32)atof(self->mWaitTimeEditor->getText().c_str()); + F32 wait_seconds = (F32)atof(mWaitTimeEditor->getText().c_str()); if (wait_seconds < 0.f) wait_seconds = 0.f; if (wait_seconds > 3600.f) wait_seconds = 3600.f; wait_step->mWaitSeconds = wait_seconds; } // Enable the input area if necessary - self->mWaitTimeEditor->setEnabled(self->mWaitTimeCheck->get()); + mWaitTimeEditor->setEnabled(mWaitTimeCheck->get()); // Update the UI label in the list updateLabel(step_item); - self->mDirty = TRUE; - self->refresh(); + mDirty = TRUE; + refresh(); } -// static -void LLPreviewGesture::onCommitWaitTime(LLUICtrl* ctrl, void* data) +void LLPreviewGesture::onCommitWaitTime() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* step_item = self->mStepList->getFirstSelected(); + LLScrollListItem* step_item = mStepList->getFirstSelected(); if (!step_item) return; LLGestureStep* step = (LLGestureStep*)step_item->getUserdata(); if (step->getType() != STEP_WAIT) return; - self->mWaitTimeCheck->set(TRUE); - onCommitWait(ctrl, data); + mWaitTimeCheck->set(TRUE); + onCommitWait(); } @@ -1610,18 +1568,15 @@ void LLPreviewGesture::onKeystrokeCommit(LLLineEditor* caller, void* data) { // Just commit every keystroke - onCommitSetDirty(caller, data); + ((LLPreviewGesture*)data)->onCommitSetDirty(); } -// static -void LLPreviewGesture::onClickAdd(void* data) +void LLPreviewGesture::onClickAdd() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* library_item = self->mLibraryList->getFirstSelected(); + LLScrollListItem* library_item = mLibraryList->getFirstSelected(); if (!library_item) return; - S32 library_item_index = self->mLibraryList->getFirstSelectedIndex(); + S32 library_item_index = mLibraryList->getFirstSelectedIndex(); const LLScrollListCell* library_cell = library_item->getColumn(0); const std::string& library_text = library_cell->getValue().asString(); @@ -1632,9 +1587,9 @@ void LLPreviewGesture::onClickAdd(void* data) return; } - self->addStep( (EStepType)library_item_index ); - self->mDirty = TRUE; - self->refresh(); + addStep( (EStepType)library_item_index ); + mDirty = TRUE; + refresh(); } LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type ) @@ -1734,129 +1689,110 @@ std::string LLPreviewGesture::getLabel(std::vector labels) return result; } -// static -void LLPreviewGesture::onClickUp(void* data) -{ - LLPreviewGesture* self = (LLPreviewGesture*)data; - S32 selected_index = self->mStepList->getFirstSelectedIndex(); +void LLPreviewGesture::onClickUp() +{ + S32 selected_index = mStepList->getFirstSelectedIndex(); if (selected_index > 0) { - self->mStepList->swapWithPrevious(selected_index); - self->mDirty = TRUE; - self->refresh(); + mStepList->swapWithPrevious(selected_index); + mDirty = TRUE; + refresh(); } } -// static -void LLPreviewGesture::onClickDown(void* data) +void LLPreviewGesture::onClickDown() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - S32 selected_index = self->mStepList->getFirstSelectedIndex(); + S32 selected_index = mStepList->getFirstSelectedIndex(); if (selected_index < 0) return; - S32 count = self->mStepList->getItemCount(); + S32 count = mStepList->getItemCount(); if (selected_index < count-1) { - self->mStepList->swapWithNext(selected_index); - self->mDirty = TRUE; - self->refresh(); + mStepList->swapWithNext(selected_index); + mDirty = TRUE; + refresh(); } } -// static -void LLPreviewGesture::onClickDelete(void* data) +void LLPreviewGesture::onClickDelete() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - LLScrollListItem* item = self->mStepList->getFirstSelected(); - S32 selected_index = self->mStepList->getFirstSelectedIndex(); + LLScrollListItem* item = mStepList->getFirstSelected(); + S32 selected_index = mStepList->getFirstSelectedIndex(); if (item && selected_index >= 0) { LLGestureStep* step = (LLGestureStep*)item->getUserdata(); delete step; - step = NULL; - self->mStepList->deleteSingleItem(selected_index); + mStepList->deleteSingleItem(selected_index); - self->mDirty = TRUE; - self->refresh(); + mDirty = TRUE; + refresh(); } } -// static -void LLPreviewGesture::onCommitActive(LLUICtrl* ctrl, void* data) +void LLPreviewGesture::onCommitActive() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - if (!LLGestureMgr::instance().isGestureActive(self->mItemUUID)) + if (!LLGestureMgr::instance().isGestureActive(mItemUUID)) { - LLGestureMgr::instance().activateGesture(self->mItemUUID); + LLGestureMgr::instance().activateGesture(mItemUUID); } else { - LLGestureMgr::instance().deactivateGesture(self->mItemUUID); + LLGestureMgr::instance().deactivateGesture(mItemUUID); } // Make sure the (active) label in the inventory gets updated. - LLViewerInventoryItem* item = gInventory.getItem(self->mItemUUID); + LLViewerInventoryItem* item = gInventory.getItem(mItemUUID); if (item) { gInventory.updateItem(item); gInventory.notifyObservers(); } - self->refresh(); + refresh(); } -// static -void LLPreviewGesture::onClickSave(void* data) +void LLPreviewGesture::onClickSave() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - self->saveIfNeeded(); + saveIfNeeded(); } -// static -void LLPreviewGesture::onClickPreview(void* data) +void LLPreviewGesture::onClickPreview() { - LLPreviewGesture* self = (LLPreviewGesture*)data; - - if (!self->mPreviewGesture) + if (!mPreviewGesture) { // make temporary gesture - self->mPreviewGesture = self->createGesture(); + mPreviewGesture = createGesture(); // add a callback - self->mPreviewGesture->mDoneCallback = onDonePreview; - self->mPreviewGesture->mCallbackData = self; + mPreviewGesture->mDoneCallback = boost::bind(&LLPreviewGesture::onDonePreview,this,_1); // set the button title - self->mPreviewBtn->setLabel(self->getString("stop_txt")); + mPreviewBtn->setLabel(getString("stop_txt")); // play it, and delete when done - LLGestureMgr::instance().playGesture(self->mPreviewGesture); + LLGestureMgr::instance().playGesture(mPreviewGesture); - self->refresh(); + refresh(); } else { // Will call onDonePreview() below - LLGestureMgr::instance().stopGesture(self->mPreviewGesture); + LLGestureMgr::instance().stopGesture(mPreviewGesture); - self->refresh(); + refresh(); } } // static -void LLPreviewGesture::onDonePreview(LLMultiGesture* gesture, void* data) +void LLPreviewGesture::onDonePreview(LLMultiGesture* gesture) { - LLPreviewGesture* self = (LLPreviewGesture*)data; + mPreviewBtn->setLabel(getString("preview_txt")); - self->mPreviewBtn->setLabel(self->getString("preview_txt")); + delete mPreviewGesture; + mPreviewGesture = NULL; - delete self->mPreviewGesture; - self->mPreviewGesture = NULL; - - self->refresh(); + refresh(); } diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h index 8434a46e5..d4d7228f4 100644 --- a/indra/newview/llpreviewgesture.h +++ b/indra/newview/llpreviewgesture.h @@ -116,30 +116,30 @@ protected: static std::string getLabel(std::vector labels); static void updateLabel(LLScrollListItem* item); - static void onCommitSetDirty(LLUICtrl* ctrl, void* data); - static void onCommitLibrary(LLUICtrl* ctrl, void* data); - static void onCommitStep(LLUICtrl* ctrl, void* data); - static void onCommitAnimation(LLUICtrl* ctrl, void* data); - static void onCommitSound(LLUICtrl* ctrl, void* data); - static void onCommitChat(LLUICtrl* ctrl, void* data); - static void onCommitWait(LLUICtrl* ctrl, void* data); - static void onCommitWaitTime(LLUICtrl* ctrl, void* data); + void onCommitSetDirty(); + void onCommitLibrary(); + void onCommitStep(); + void onCommitAnimation(); + void onCommitSound(); + void onCommitChat(); + void onCommitWait(); + void onCommitWaitTime(); - static void onCommitAnimationTrigger(LLUICtrl* ctrl, void *data); + void onCommitAnimationTrigger(); // Handy function to commit each keystroke static void onKeystrokeCommit(LLLineEditor* caller, void* data); - static void onClickAdd(void* data); - static void onClickUp(void* data); - static void onClickDown(void* data); - static void onClickDelete(void* data); + void onClickAdd(); + void onClickUp(); + void onClickDown(); + void onClickDelete(); - static void onCommitActive(LLUICtrl* ctrl, void* data); - static void onClickSave(void* data); - static void onClickPreview(void* data); + void onCommitActive(); + void onClickSave(); + void onClickPreview(); - static void onDonePreview(LLMultiGesture* gesture, void* data); + void onDonePreview(LLMultiGesture* gesture); virtual const char *getTitleName() const { return "Gesture"; } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 31e686adb..16eef86fd 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1321,8 +1321,8 @@ LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect, void LLPreviewLSL::callbackLSLCompileSucceeded() { llinfos << "LSL Bytecode saved" << llendl; - mScriptEd->mErrorList->addCommentText(LLTrans::getString("CompileSuccessful")); - mScriptEd->mErrorList->addCommentText(LLTrans::getString("SaveComplete")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); closeIfNeeded(); } @@ -1931,8 +1931,8 @@ void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, bool is_script_running) { lldebugs << "LSL Bytecode saved" << llendl; - mScriptEd->mErrorList->addCommentText(LLTrans::getString("CompileSuccessful")); - mScriptEd->mErrorList->addCommentText(LLTrans::getString("SaveComplete")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); closeIfNeeded(); } @@ -2518,7 +2518,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, else { llinfos << "Compile worked!" << llendl; - mScriptEd->mErrorList->addCommentText(LLTrans::getString("CompileSuccessfulSaving")); + mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessfulSaving")); if(gAssetStorage) { llinfos << "LLLiveLSLEditor::saveAsset " @@ -2593,7 +2593,7 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use if(self) { // Tell the user that the compile worked. - self->mScriptEd->mErrorList->addCommentText(LLTrans::getString("SaveComplete")); + self->mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete")); // close the window if this completes both uploads self->getWindow()->decBusyCount(); self->mPendingUploads--; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 882b96b9c..4a4b3863b 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1593,7 +1593,10 @@ 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, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + //objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + objectp->setTETexture(te, mImageID); //Singu note: setTETexture will allow the real id to be passed to LLPrimitive::setTETexture, + // even if it's null. setTEImage would actually pass down IMG_DEFAULT under such a case, + // which we don't want. } return true; } @@ -1756,7 +1759,10 @@ BOOL LLSelectMgr::selectionRevertTextures() } else { - object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + //object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + object->setTETexture(te, id); //Singu note: setTETexture will allow the real id to be passed to LLPrimitive::setTETexture, + // even if it's null. setTEImage would actually pass down IMG_DEFAULT under such a case, + // which we don't want. } } } @@ -5944,8 +5950,6 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color) gDebugProgram.bind(); } - static LLCachedControl mode("OutlineMode",0); - gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); @@ -6426,7 +6430,7 @@ LLBBox LLSelectMgr::getBBoxOfSelection() const //----------------------------------------------------------------------------- BOOL LLSelectMgr::canUndo() const { - return const_cast(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG + return const_cast(this)->mSelectedObjects->getFirstMoveableObject() != NULL; // HACK: casting away constness - MG } //----------------------------------------------------------------------------- @@ -6444,7 +6448,7 @@ void LLSelectMgr::undo() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canRedo() const { - return const_cast(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG + return const_cast(this)->mSelectedObjects->getFirstMoveableObject() != NULL; // HACK: casting away constness - MG } //----------------------------------------------------------------------------- diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index dbc2a1961..02e2d8a15 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -73,6 +73,7 @@ const F32 SG_OCCLUSION_FUDGE = 0.25f; #define assert_states_valid(x) #endif +extern bool gShiftFrame; static U32 sZombieGroups = 0; U32 LLSpatialGroup::sNodeCount = 0; @@ -82,6 +83,7 @@ U32 LLSpatialGroup::sNodeCount = 0; std::set LLSpatialGroup::sPendingQueries; U32 gOctreeMaxCapacity; +U32 gOctreeReserveCapacity; BOOL LLSpatialGroup::sNoDelete = FALSE; @@ -98,7 +100,7 @@ public: protected: - std::list mAvailableName; + std::queue mAvailableName; //Use queue, because this usage is FIFO, which queue is desgined for GLuint mCurQuery; virtual GLuint allocateName() @@ -108,7 +110,7 @@ protected: if (!mAvailableName.empty()) { ret = mAvailableName.front(); - mAvailableName.pop_front(); + mAvailableName.pop(); } else { @@ -123,8 +125,8 @@ protected: #if LL_TRACK_PENDING_OCCLUSION_QUERIES LLSpatialGroup::sPendingQueries.erase(name); #endif - llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end()); - mAvailableName.push_back(name); + //llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end()); + mAvailableName.push(name); } }; @@ -412,6 +414,7 @@ void LLSpatialGroup::setVisible() void LLSpatialGroup::validate() { + ll_assert_aligned(this,64); #if LL_OCTREE_PARANOIA_CHECK sg_assert(!isState(DIRTY)); @@ -805,7 +808,10 @@ void LLSpatialGroup::shift(const LLVector4a &offset) mObjectExtents[0].add(offset); mObjectExtents[1].add(offset); - if (!mSpatialPartition->mRenderByGroup) + if (!mSpatialPartition->mRenderByGroup && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TREE && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_BRIDGE) { setState(GEOM_DIRTY); gPipeline.markRebuild(this, TRUE); @@ -1075,6 +1081,8 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mLastUpdateDistance(-1.f), mLastUpdateTime(gFrameTimeSeconds) { + ll_assert_aligned(this,16); + sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -1118,6 +1126,11 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) return; } + if (gShiftFrame) + { + return; + } + #if !LL_RELEASE_FOR_DOWNLOAD if (isState(LLSpatialGroup::OBJECT_DIRTY)) { @@ -1554,7 +1567,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) // Don't cull hole/edge water, unless RenderWaterVoidCulling is set and we have the GL_ARB_depth_clamp extension. //if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) || // earlyFail(camera, this)) - if (earlyFail(camera, this)) + if (earlyFail(camera, this)) //Returns true if camera is inside this spatial group. { LLFastTimer t(FTM_OCCLUSION_EARLY_FAIL); setOcclusionState(LLSpatialGroup::DISCARD_QUERY); @@ -1609,9 +1622,12 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) llassert(shader); shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mBounds[0].getF32ptr()); - shader->uniform3f(LLShaderMgr::BOX_SIZE, mBounds[1][0]+SG_OCCLUSION_FUDGE, - mBounds[1][1]+SG_OCCLUSION_FUDGE, - mBounds[1][2]+SG_OCCLUSION_FUDGE); + //static LLVector4a fudge(SG_OCCLUSION_FUDGE); + static LLCachedControl vel("SHOcclusionFudge",SG_OCCLUSION_FUDGE); + LLVector4a fudge(SG_OCCLUSION_FUDGE); + static LLVector4a bounds; + bounds.setAdd(fudge,mBounds[1]); + shader->uniform3fv(LLShaderMgr::BOX_SIZE, 1, bounds.getF32ptr()); if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER) { @@ -1732,6 +1748,8 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) drawablep->setSpatialGroup(NULL); } + drawablep->setSpatialGroup(NULL); + assert_octree_valid(mOctree); return TRUE; @@ -2308,12 +2326,11 @@ BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) return FALSE; } - const F32 vel = SG_OCCLUSION_FUDGE*2.f; - LLVector4a fudge; - fudge.splat(vel); + static LLCachedControl vel("SHOcclusionFudge",SG_OCCLUSION_FUDGE); + LLVector4a fudge(vel*2.f); const LLVector4a& c = group->mBounds[0]; - LLVector4a r; + static LLVector4a r; r.setAdd(group->mBounds[1], fudge); /*if (r.magVecSquared() > 1024.0*1024.0) @@ -3029,6 +3046,8 @@ void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLCo void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColor4& line_color) { + if(mesh.mPositions.empty() || mesh.mNormals.empty()) + return; gGL.diffuseColor4fv(color.mV); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); LLGLEnable offset(GL_POLYGON_OFFSET_LINE); @@ -3390,6 +3409,8 @@ void renderPhysicsShapes(LLSpatialGroup* group) LLViewerObject* object = drawable->getVObj(); if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) { + gGL.pushMatrix(); + gGL.multMatrix((F32*) object->getRegion()->mRenderMatrix.mMatrix); //push face vertices for terrain for (S32 i = 0; i < drawable->getNumFaces(); ++i) { @@ -3411,6 +3432,7 @@ void renderPhysicsShapes(LLSpatialGroup* group) } } } + gGL.popMatrix(); } } } @@ -4399,6 +4421,10 @@ public: } } + else if (avatar->isLangolier()) + { + skip_check = true; + } } if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal)) @@ -4489,251 +4515,27 @@ LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) return new LLVertexBuffer(type_mask, usage); } -LLCullResult::LLCullResult() -{ - mVisibleGroupsAllocated = 0; - mAlphaGroupsAllocated = 0; - mOcclusionGroupsAllocated = 0; - mDrawableGroupsAllocated = 0; - mVisibleListAllocated = 0; - mVisibleBridgeAllocated = 0; - - mVisibleGroups = NULL; - mVisibleGroupsEnd = NULL; - mAlphaGroups = NULL; - mAlphaGroupsEnd = NULL; - mOcclusionGroups = NULL; - mOcclusionGroupsEnd = NULL; - mDrawableGroups = NULL; - mDrawableGroupsEnd = NULL; - mVisibleList = NULL; - mVisibleListEnd = NULL; - mVisibleBridge = NULL; - mVisibleBridgeEnd = NULL; - - for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) - { - mRenderMap[i] = NULL; - mRenderMapEnd[i] = NULL; - mRenderMapAllocated[i] = 0; - } - - clear(); -} - -void LLCullResult::pushBack(void**& head, U32& count, void* val) -{ - count++; - head = (void**) realloc((void*) head, sizeof(void*) * count); - head[count-1] = val; -} void LLCullResult::clear() { - mVisibleGroupsSize = 0; - mVisibleGroupsEnd = mVisibleGroups; - - mAlphaGroupsSize = 0; - mAlphaGroupsEnd = mAlphaGroups; - - mOcclusionGroupsSize = 0; - mOcclusionGroupsEnd = mOcclusionGroups; - - mDrawableGroupsSize = 0; - mDrawableGroupsEnd = mDrawableGroups; - - mVisibleListSize = 0; - mVisibleListEnd = mVisibleList; - - mVisibleBridgeSize = 0; - mVisibleBridgeEnd = mVisibleBridge; - + mVisibleGroups.clear(); + mAlphaGroups.clear(); + mOcclusionGroups.clear(); + mDrawableGroups.clear(); + mVisibleList.clear(); + mVisibleBridge.clear(); for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) { - for (U32 j = 0; j < mRenderMapSize[i]; j++) - { - mRenderMap[i][j] = 0; - } - mRenderMapSize[i] = 0; - mRenderMapEnd[i] = mRenderMap[i]; + mRenderMap[i].clear(); } } -LLCullResult::sg_iterator LLCullResult::beginVisibleGroups() -{ - return mVisibleGroups; -} - -LLCullResult::sg_iterator LLCullResult::endVisibleGroups() -{ - return mVisibleGroupsEnd; -} - -LLCullResult::sg_iterator LLCullResult::beginAlphaGroups() -{ - return mAlphaGroups; -} - -LLCullResult::sg_iterator LLCullResult::endAlphaGroups() -{ - return mAlphaGroupsEnd; -} - -LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() -{ - return mOcclusionGroups; -} - -LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() -{ - return mOcclusionGroupsEnd; -} - -LLCullResult::sg_iterator LLCullResult::beginDrawableGroups() -{ - return mDrawableGroups; -} - -LLCullResult::sg_iterator LLCullResult::endDrawableGroups() -{ - return mDrawableGroupsEnd; -} - -LLCullResult::drawable_iterator LLCullResult::beginVisibleList() -{ - return mVisibleList; -} - -LLCullResult::drawable_iterator LLCullResult::endVisibleList() -{ - return mVisibleListEnd; -} - -LLCullResult::bridge_iterator LLCullResult::beginVisibleBridge() -{ - return mVisibleBridge; -} - -LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() -{ - return mVisibleBridgeEnd; -} - -LLCullResult::drawinfo_iterator LLCullResult::beginRenderMap(U32 type) -{ - return mRenderMap[type]; -} - -LLCullResult::drawinfo_iterator LLCullResult::endRenderMap(U32 type) -{ - return mRenderMapEnd[type]; -} - -void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) -{ - if (mVisibleGroupsSize < mVisibleGroupsAllocated) - { - mVisibleGroups[mVisibleGroupsSize] = group; - } - else - { - pushBack((void**&) mVisibleGroups, mVisibleGroupsAllocated, (void*) group); - } - ++mVisibleGroupsSize; - mVisibleGroupsEnd = mVisibleGroups+mVisibleGroupsSize; -} - -void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) -{ - if (mAlphaGroupsSize < mAlphaGroupsAllocated) - { - mAlphaGroups[mAlphaGroupsSize] = group; - } - else - { - pushBack((void**&) mAlphaGroups, mAlphaGroupsAllocated, (void*) group); - } - ++mAlphaGroupsSize; - mAlphaGroupsEnd = mAlphaGroups+mAlphaGroupsSize; -} - -void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) -{ - if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) - { - mOcclusionGroups[mOcclusionGroupsSize] = group; - } - else - { - pushBack((void**&) mOcclusionGroups, mOcclusionGroupsAllocated, (void*) group); - } - ++mOcclusionGroupsSize; - mOcclusionGroupsEnd = mOcclusionGroups+mOcclusionGroupsSize; -} - -void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) -{ - if (mDrawableGroupsSize < mDrawableGroupsAllocated) - { - mDrawableGroups[mDrawableGroupsSize] = group; - } - else - { - pushBack((void**&) mDrawableGroups, mDrawableGroupsAllocated, (void*) group); - } - ++mDrawableGroupsSize; - mDrawableGroupsEnd = mDrawableGroups+mDrawableGroupsSize; -} - -void LLCullResult::pushDrawable(LLDrawable* drawable) -{ - if (mVisibleListSize < mVisibleListAllocated) - { - mVisibleList[mVisibleListSize] = drawable; - } - else - { - pushBack((void**&) mVisibleList, mVisibleListAllocated, (void*) drawable); - } - ++mVisibleListSize; - mVisibleListEnd = mVisibleList+mVisibleListSize; -} - -void LLCullResult::pushBridge(LLSpatialBridge* bridge) -{ - if (mVisibleBridgeSize < mVisibleBridgeAllocated) - { - mVisibleBridge[mVisibleBridgeSize] = bridge; - } - else - { - pushBack((void**&) mVisibleBridge, mVisibleBridgeAllocated, (void*) bridge); - } - ++mVisibleBridgeSize; - mVisibleBridgeEnd = mVisibleBridge+mVisibleBridgeSize; -} - -void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) -{ - if (mRenderMapSize[type] < mRenderMapAllocated[type]) - { - mRenderMap[type][mRenderMapSize[type]] = draw_info; - } - else - { - pushBack((void**&) mRenderMap[type], mRenderMapAllocated[type], (void*) draw_info); - } - ++mRenderMapSize[type]; - mRenderMapEnd[type] = mRenderMap[type] + mRenderMapSize[type]; -} - - void LLCullResult::assertDrawMapsEmpty() { for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) { - if (mRenderMapSize[i] != 0) + if (hasRenderMap(i)) { llerrs << "Stale LLDrawInfo's in LLCullResult!" << llendl; } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index e6b018087..9a00bc1e6 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -73,6 +73,16 @@ protected: ~LLDrawInfo(); public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLDrawInfo(const LLDrawInfo& rhs) { @@ -111,7 +121,7 @@ public: F32 mPartSize; F32 mVSize; LLSpatialGroup* mGroup; - LLFace* mFace; //associated face + LL_ALIGN_16(LLFace* mFace); //associated face F32 mDistance; U32 mDrawMode; @@ -186,7 +196,7 @@ public: }; }; -LL_ALIGN_PREFIX(64) +LL_ALIGN_PREFIX(16) class LLSpatialGroup : public LLOctreeListener { friend class LLSpatialPartition; @@ -198,6 +208,16 @@ public: *this = rhs; } + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + const LLSpatialGroup& operator=(const LLSpatialGroup& rhs) { llerrs << "Illegal operation!" << llendl; @@ -332,9 +352,10 @@ public: void dirtyMesh() { setState(MESH_DIRTY); } //octree wrappers to make code more readable - //element_list& getData() { return mOctreeNode->getData(); } + //element_list& getData() { return mOctreeNode->getData(); } //unused element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } + bool hasElement(LLDrawable* drawablep) { return std::find(mOctreeNode->getDataBegin(), mOctreeNode->getDataEnd(), drawablep) != mOctreeNode->getDataEnd(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } bool isEmpty() const { return mOctreeNode->isEmpty(); } @@ -359,12 +380,12 @@ public: V4_COUNT = 10 } eV4Index; - LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) - LLVector4a mExtents[2]; // extents (min, max) of this node and all its children - LLVector4a mObjectExtents[2]; // extents (min, max) of objects in this node - LLVector4a mObjectBounds[2]; // bounding box (center, size) of objects in this node - LLVector4a mViewAngle; - LLVector4a mLastUpdateViewAngle; + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children + LL_ALIGN_16(LLVector4a mObjectExtents[2]); // extents (min, max) of objects in this node + LL_ALIGN_16(LLVector4a mObjectBounds[2]); // bounding box (center, size) of objects in this node + LL_ALIGN_16(LLVector4a mViewAngle); + LL_ALIGN_16(LLVector4a mLastUpdateViewAngle); F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3() @@ -525,95 +546,63 @@ public: class LLCullResult { public: - LLCullResult(); + LLCullResult() {} - typedef LLSpatialGroup** sg_list_t; - typedef LLDrawable** drawable_list_t; - typedef LLSpatialBridge** bridge_list_t; - typedef LLDrawInfo** drawinfo_list_t; + typedef std::vector sg_list_t; + typedef std::vector drawable_list_t; + typedef std::vector bridge_list_t; + typedef std::vector drawinfo_list_t; - typedef LLSpatialGroup** sg_iterator; - typedef LLSpatialBridge** bridge_iterator; - typedef LLDrawInfo** drawinfo_iterator; - typedef LLDrawable** drawable_iterator; + typedef sg_list_t::const_iterator sg_iterator; + typedef bridge_list_t::const_iterator bridge_iterator; + typedef drawinfo_list_t::const_iterator drawinfo_iterator; + typedef drawable_list_t::const_iterator drawable_iterator; void clear(); - sg_iterator beginVisibleGroups(); - sg_iterator endVisibleGroups(); + const sg_iterator beginVisibleGroups() const { return mVisibleGroups.begin(); } + const sg_iterator endVisibleGroups() const { return mVisibleGroups.end(); } - sg_iterator beginAlphaGroups(); - sg_iterator endAlphaGroups(); + const sg_iterator beginAlphaGroups() const { return mAlphaGroups.begin(); } + const sg_iterator endAlphaGroups() const { return mAlphaGroups.end(); } + const sg_list_t::iterator beginAlphaGroups() { return mAlphaGroups.begin(); } + const sg_list_t::iterator endAlphaGroups() { return mAlphaGroups.end(); } - bool hasOcclusionGroups() { return mOcclusionGroupsSize > 0; } - sg_iterator beginOcclusionGroups(); - sg_iterator endOcclusionGroups(); + bool hasOcclusionGroups() const { return !mOcclusionGroups.empty(); } + const sg_iterator beginOcclusionGroups() const { return mOcclusionGroups.begin(); } + const sg_iterator endOcclusionGroups() const { return mOcclusionGroups.end(); } - sg_iterator beginDrawableGroups(); - sg_iterator endDrawableGroups(); + const sg_iterator beginDrawableGroups() const { return mDrawableGroups.begin(); } + const sg_iterator endDrawableGroups() const { return mDrawableGroups.end(); } - drawable_iterator beginVisibleList(); - drawable_iterator endVisibleList(); + const drawable_iterator beginVisibleList() const { return mVisibleList.begin(); } + const drawable_iterator endVisibleList() const { return mVisibleList.end(); } - bridge_iterator beginVisibleBridge(); - bridge_iterator endVisibleBridge(); + const bridge_iterator beginVisibleBridge() const { return mVisibleBridge.begin(); } + const bridge_iterator endVisibleBridge() const { return mVisibleBridge.end(); } - drawinfo_iterator beginRenderMap(U32 type); - drawinfo_iterator endRenderMap(U32 type); + bool hasRenderMap(U32 type) const { return !mRenderMap[type].empty(); } + const drawinfo_iterator beginRenderMap(U32 type)const { return mRenderMap[type].begin(); } + const drawinfo_iterator endRenderMap(U32 type) const { return mRenderMap[type].end(); } - void pushVisibleGroup(LLSpatialGroup* group); - void pushAlphaGroup(LLSpatialGroup* group); - void pushOcclusionGroup(LLSpatialGroup* group); - void pushDrawableGroup(LLSpatialGroup* group); - void pushDrawable(LLDrawable* drawable); - void pushBridge(LLSpatialBridge* bridge); - void pushDrawInfo(U32 type, LLDrawInfo* draw_info); - - U32 getVisibleGroupsSize() { return mVisibleGroupsSize; } - U32 getAlphaGroupsSize() { return mAlphaGroupsSize; } - U32 getDrawableGroupsSize() { return mDrawableGroupsSize; } - U32 getVisibleListSize() { return mVisibleListSize; } - U32 getVisibleBridgeSize() { return mVisibleBridgeSize; } - U32 getRenderMapSize(U32 type) { return mRenderMapSize[type]; } + void pushVisibleGroup(LLSpatialGroup* group) { mVisibleGroups.push_back(group); } + void pushAlphaGroup(LLSpatialGroup* group) { mAlphaGroups.push_back(group); } + void pushOcclusionGroup(LLSpatialGroup* group) { mOcclusionGroups.push_back(group); } + void pushDrawableGroup(LLSpatialGroup* group) { mDrawableGroups.push_back(group); } + void pushDrawable(LLDrawable* drawable) { mVisibleList.push_back(drawable); } + void pushBridge(LLSpatialBridge* bridge) { mVisibleBridge.push_back(bridge); } + void pushDrawInfo(U32 type, LLDrawInfo* draw_info) { mRenderMap[type].push_back(draw_info); } void assertDrawMapsEmpty(); private: - - void pushBack(void** &head, U32& count, void* val); - - U32 mVisibleGroupsSize; - U32 mAlphaGroupsSize; - U32 mOcclusionGroupsSize; - U32 mDrawableGroupsSize; - U32 mVisibleListSize; - U32 mVisibleBridgeSize; - - U32 mVisibleGroupsAllocated; - U32 mAlphaGroupsAllocated; - U32 mOcclusionGroupsAllocated; - U32 mDrawableGroupsAllocated; - U32 mVisibleListAllocated; - U32 mVisibleBridgeAllocated; - - U32 mRenderMapSize[LLRenderPass::NUM_RENDER_TYPES]; - sg_list_t mVisibleGroups; - sg_iterator mVisibleGroupsEnd; sg_list_t mAlphaGroups; - sg_iterator mAlphaGroupsEnd; sg_list_t mOcclusionGroups; - sg_iterator mOcclusionGroupsEnd; sg_list_t mDrawableGroups; - sg_iterator mDrawableGroupsEnd; drawable_list_t mVisibleList; - drawable_iterator mVisibleListEnd; bridge_list_t mVisibleBridge; - bridge_iterator mVisibleBridgeEnd; drawinfo_list_t mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; - U32 mRenderMapAllocated[LLRenderPass::NUM_RENDER_TYPES]; - drawinfo_iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; - }; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 21f4738f8..e33a2b8f3 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -191,6 +191,7 @@ #include "llwind.h" #include "llworld.h" #include "llworldmap.h" +#include "llworldmapmessage.h" #include "llxfermanager.h" #include "pipeline.h" #include "llappviewer.h" @@ -306,7 +307,6 @@ bool process_login_success_response(std::string &password); void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is_group) { - LLNameListCtrl::refreshAll(id, full_name); LLNameBox::refreshAll(id, full_name, is_group); LLNameEditor::refreshAll(id, full_name, is_group); @@ -757,9 +757,6 @@ bool idle_startup() // We have at least some login information on a SLURL firstname = gLoginHandler.getFirstName(); lastname = gLoginHandler.getLastName(); - // - gFullName = utf8str_tolower(firstname + " " + lastname); - // web_login_key = gLoginHandler.getWebLoginKey(); // Show the login screen if we don't have everything @@ -771,9 +768,6 @@ bool idle_startup() LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); firstname = cmd_line_login[0].asString(); lastname = cmd_line_login[1].asString(); - // - gFullName = utf8str_tolower(firstname + " " + lastname); - // LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str()); char md5pass[33]; /* Flawfinder: ignore */ @@ -791,9 +785,6 @@ bool idle_startup() { firstname = gSavedSettings.getString("FirstName"); lastname = gSavedSettings.getString("LastName"); - // - gFullName = utf8str_tolower(firstname + " " + lastname); - // password = LLStartUp::loadPasswordFromDisk(); gSavedSettings.setBOOL("RememberPassword", TRUE); @@ -809,9 +800,6 @@ bool idle_startup() // a valid grid is selected firstname = gSavedSettings.getString("FirstName"); lastname = gSavedSettings.getString("LastName"); - // - gFullName = utf8str_tolower(firstname + " " + lastname); - // password = LLStartUp::loadPasswordFromDisk(); show_connect_box = true; } @@ -895,9 +883,6 @@ bool idle_startup() else { LLPanelLogin::setFields(firstname, lastname, password); - // - gFullName = utf8str_tolower(firstname + " " + lastname); - // LLPanelLogin::giveFocus(); } display_startup(); @@ -969,9 +954,6 @@ bool idle_startup() { firstname = gLoginHandler.getFirstName(); lastname = gLoginHandler.getLastName(); - // - gFullName = utf8str_tolower(firstname + " " + lastname); - // web_login_key = gLoginHandler.getWebLoginKey(); } @@ -990,15 +972,21 @@ bool idle_startup() { gSavedSettings.setString("FirstName", firstname); gSavedSettings.setString("LastName", lastname); - // - gFullName = utf8str_tolower(firstname + " " + lastname); - // if (!gSavedSettings.controlExists("RememberLogin")) gSavedSettings.declareBOOL("RememberLogin", false, "Remember login", false); gSavedSettings.setBOOL("RememberLogin", LLPanelLogin::getRememberLogin()); LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << LL_ENDL; gDebugInfo["LoginName"] = firstname + " " + lastname; } + else + { + // User tried to login on a non-SecondLife grid with an empty lastname. + LLSD subs; + subs["GRIDNAME"] = gHippoGridManager->getConnectedGrid()->getGridName(); + LLNotificationsUtil::add(firstname.empty() ? "EmptyFirstNameMessage" : "EmptyLastNameMessage", subs); + LLStartUp::setStartupState(STATE_LOGIN_SHOW); + return FALSE; + } LLScriptEdCore::parseFunctions("lsl_functions_sl.xml"); //Singu Note: This parsing function essentially replaces the entirety of the lscript_library library @@ -1076,7 +1064,7 @@ bool idle_startup() gSavedSettings.getControl("_NACL_AntiSpamAmount")->getSignal()->connect(boost::bind(&NACLAntiSpamRegistry::handleNaclAntiSpamAmountChanged, _2)); // NaCl End - //good as place as any to create user windlight directories + //good a place as any to create user windlight directories std::string user_windlight_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight", "")); LLFile::mkdir(user_windlight_path_name.c_str()); @@ -1432,7 +1420,6 @@ bool idle_startup() LL_DEBUGS("AppInit") << "downloading..." << LL_ENDL; return FALSE; } - Debug(if (gCurlIo) dc::curlio.off()); // Login succeeded: restore dc::curlio to original state. LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); progress += 0.01f; set_startup_status(progress, LLTrans::getString("LoginProcessingResponse"), auth_message); @@ -1469,6 +1456,7 @@ bool idle_startup() { // Yay, login! successful_login = true; + Debug(if (gCurlIo) dc::curlio.off()); // Login succeeded: restore dc::curlio to original state. } else { @@ -1548,13 +1536,12 @@ bool idle_startup() } } break; - case LLUserAuth::E_COULDNT_RESOLVE_HOST: - case LLUserAuth::E_SSL_PEER_CERTIFICATE: - case LLUserAuth::E_UNHANDLED_ERROR: - case LLUserAuth::E_SSL_CACERT: - case LLUserAuth::E_SSL_CONNECT_ERROR: default: - if (LLViewerLogin::getInstance()->tryNextURI()) + { + static int http_failures = 0; + http_failures = (error == LLUserAuth::E_HTTP_SERVER_ERROR) ? http_failures + 1 : 0; + if ((error == LLUserAuth::E_HTTP_SERVER_ERROR && http_failures <= 3) || + LLViewerLogin::getInstance()->tryNextURI()) { static int login_attempt_number = 0; std::ostringstream s; @@ -1569,6 +1556,7 @@ bool idle_startup() emsg << "Unable to connect to " << gHippoGridManager->getCurrentGrid()->getGridName() << ".\n"; emsg << LLUserAuth::getInstance()->errorMessage(); } + } break; } @@ -3394,8 +3382,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); @@ -4099,9 +4087,6 @@ bool process_login_success_response(std::string& password) if(!text.empty()) lastname.assign(text); gSavedSettings.setString("FirstName", firstname); gSavedSettings.setString("LastName", lastname); - // - gFullName = utf8str_tolower(firstname + " " + lastname); - // if (gSavedSettings.getBOOL("RememberPassword")) { diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index f9af3a2a9..5ad86c388 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -725,11 +725,9 @@ void LLStatusBar::setHealth(S32 health) { if (mHealth > (health + gSavedSettings.getF32("UISndHealthReductionThreshold"))) { - LLVOAvatar *me; - - if ((me = gAgentAvatarp)) + if (isAgentAvatarValid()) { - if (me->getSex() == SEX_FEMALE) + if (gAgentAvatarp->getSex() == SEX_FEMALE) { make_ui_sound("UISndHealthReductionF"); } diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index de0562b7f..bd1b99911 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -2,31 +2,25 @@ * @file llsurface.cpp * @brief Implementation of LLSurface class * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -48,6 +42,7 @@ #include "llappviewer.h" #include "llworld.h" #include "llviewercontrol.h" +#include "llviewertexture.h" #include "llsurfacepatch.h" #include "llvosurfacepatch.h" #include "llvowater.h" @@ -61,6 +56,7 @@ #include "lldrawable.h" extern LLPipeline gPipeline; +extern bool gShiftFrame; LLColor4U MAX_WATER_COLOR(0, 48, 96, 240); @@ -351,13 +347,21 @@ void LLSurface::getNeighboringRegions( std::vector& uniqueRegio } } + +void LLSurface::getNeighboringRegionsStatus( std::vector& regions ) +{ + S32 i; + for (i = 0; i < 8; i++) + { + if ( mNeighbors[i] != NULL ) + { + regions.push_back( i ); + } + } +} + void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction) { - if (gNoRender) - { - return; - } - S32 i; LLSurfacePatch *patchp, *neighbor_patchp; @@ -618,6 +622,11 @@ void LLSurface::moveZ(const S32 x, const S32 y, const F32 delta) void LLSurface::updatePatchVisibilities(LLAgent &agent) { + if (gShiftFrame) + { + return; + } + LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgentCamera.getCameraPositionGlobal()); LLSurfacePatch *patchp; diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h index 127bec465..a693f6943 100644 --- a/indra/newview/llsurface.h +++ b/indra/newview/llsurface.h @@ -2,31 +2,25 @@ * @file llsurface.h * @brief Description of LLSurface class * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -148,6 +142,7 @@ public: friend std::ostream& operator<<(std::ostream &s, const LLSurface &S); void getNeighboringRegions( std::vector& uniqueRegions ); + void getNeighboringRegionsStatus( std::vector& regions ); public: // Number of grid points on one side of a region, including +1 buffer for diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 770f6579a..3ebea883c 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -2,31 +2,25 @@ * @file llsurfacepatch.cpp * @brief LLSurfacePatch class implementation * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -49,6 +43,7 @@ #include "lldrawpool.h" #include "noise.h" +extern bool gShiftFrame; extern U64 gFrameTime; extern LLPipeline gPipeline; @@ -224,7 +219,7 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 pos_agent.mV[VX] += x * mSurfacep->getMetersPerGrid(); pos_agent.mV[VY] += y * mSurfacep->getMetersPerGrid(); pos_agent.mV[VZ] = *(mDataZ + point_offset); - *vertex = pos_agent; + *vertex = pos_agent-mVObjp->getRegion()->getOriginAgent(); LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent(); LLVector3 tex_pos = rel_pos * (1.f/surface_stride); @@ -372,10 +367,13 @@ void LLSurfacePatch::updateCameraDistanceRegion(const LLVector3 &pos_region) { if (LLPipeline::sDynamicLOD) { - LLVector3 dv = pos_region; - dv -= mCenterRegion; - mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ - llmax(LLVOSurfacePatch::sLODFactor, 0.1f); + if (!gShiftFrame) + { + LLVector3 dv = pos_region; + dv -= mCenterRegion; + mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ + llmax(LLVOSurfacePatch::sLODFactor, 0.1f); + } } else { diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h index 2c0da60b4..fffe20208 100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/newview/lltexlayerparams.h @@ -67,6 +67,16 @@ public: /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex avatar_sex ) {} @@ -143,6 +153,16 @@ public: LLTexLayerParamColor( LLVOAvatar* avatar ); /* virtual */ ~LLTexLayerParamColor(); + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; // LLVisualParam Virtual functions diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 085f01688..051c3e4c8 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -873,7 +873,7 @@ BOOL LLTextureCache::isInLocal(const LLUUID& id) //static const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB -F32 LLTextureCache::sHeaderCacheVersion = 1.7f; +F32 LLTextureCache::sHeaderCacheVersion = 1.8f; U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE; S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit const char* entries_filename = "texture.entries"; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 18493bd7c..12fcfc77d 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -161,18 +161,19 @@ public: static void onBtnSetToDefault( void* userdata ); static void onBtnSelect( void* userdata ); static void onBtnCancel( void* userdata ); - static void onBtnPipette( void* userdata ); + void onBtnPipette( ); static void onBtnUUID( void* userdata ); //static void onBtnRevert( void* userdata ); static void onBtnWhite( void* userdata ); + static void onBtnNone( void* userdata ); static void onBtnInvisible( void* userdata ); static void onBtnAlpha( void* userdata ); static void onBtnClear( void* userdata ); - static void onSelectionChange(const std::deque &items, BOOL user_action, void* data); + void onSelectionChange(const std::deque &items, BOOL user_action); static void onShowFolders(LLUICtrl* ctrl, void* userdata); static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); static void onSearchEdit(const std::string& search_string, void* user_data ); - static void onTextureSelect( const LLTextureEntry& te, void *data ); + void onTextureSelect( const LLTextureEntry& te ); // tag: vaa emerald local_asset_browser [begin] // static void onBtnLocal( void* userdata ); @@ -250,81 +251,9 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( mNonImmediateFilterPermMask(non_immediate_filter_perm_mask), mContextConeOpacity(0.f) { + mCanApplyImmediately = can_apply_immediately; LLUICtrlFactory::getInstance()->buildFloater(this,"floater_texture_ctrl.xml"); - mTentativeLabel = getChild("Multiple"); - - mResolutionLabel = getChild("unknown"); - - - childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this); - childSetAction("Alpha", LLFloaterTexturePicker::onBtnAlpha,this); - childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this); - childSetAction("Invisible", LLFloaterTexturePicker::onBtnInvisible,this); - - // tag: vaa emerald local_asset_browser [begin] -// childSetAction("Local", LLFloaterTexturePicker::onBtnLocal, this); -// childSetAction("Server", LLFloaterTexturePicker::onBtnServer, this); - childSetAction("Add", LLFloaterTexturePicker::onBtnAdd, this); - childSetAction("Remove", LLFloaterTexturePicker::onBtnRemove, this); - childSetAction("Browser", LLFloaterTexturePicker::onBtnBrowser, this); - - mLocalScrollCtrl = getChild("local_name_list"); - mLocalScrollCtrl->setCallbackUserData(this); - mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit); - LocalAssetBrowser::UpdateTextureCtrlList( mLocalScrollCtrl ); - // tag: vaa emerald local_asset_browser [end] - - childSetCommitCallback("show_folders_check", onShowFolders, this); - childSetVisible("show_folders_check", FALSE); - - mSearchEdit = getChild("inventory search editor"); - mSearchEdit->setSearchCallback(onSearchEdit, this); - - mInventoryPanel = getChild("inventory panel"); - - if(mInventoryPanel) - { - U32 filter_types = 0x0; - filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; - filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; - - mInventoryPanel->setFilterTypes(filter_types); - //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss. - mInventoryPanel->setFilterPermMask(immediate_filter_perm_mask); - mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, _1, _2, (void*)this)); - mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mInventoryPanel->setAllowMultiSelect(FALSE); - - // store this filter as the default one - mInventoryPanel->getRootFolder()->getFilter()->markDefault(); - - // Commented out to stop opening all folders with textures - // mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_TEXTURE); - - // don't put keyboard focus on selected item, because the selection callback - // will assume that this was user input - mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); - } - - mCanApplyImmediately = can_apply_immediately; - mNoCopyTextureSelected = FALSE; - - childSetValue("apply_immediate_check", gSavedSettings.getBOOL("ApplyTextureImmediately")); - childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); - - if (!can_apply_immediately) - { - childSetEnabled("show_folders_check", FALSE); - } - - childSetAction("Pipette", LLFloaterTexturePicker::onBtnPipette,this); - childSetAction("ApplyUUID", LLFloaterTexturePicker::onBtnUUID,this); - childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this); - childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this); - - // update permission filter once UI is fully initialized - updateFilterPermMask(); setCanMinimize(FALSE); @@ -532,7 +461,80 @@ BOOL LLFloaterTexturePicker::postBuild() setTitle(pick + mLabel); } + mTentativeLabel = getChild("Multiple"); + mResolutionLabel = getChild("unknown"); + + + childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this); + childSetAction("None", LLFloaterTexturePicker::onBtnNone,this); + childSetAction("Alpha", LLFloaterTexturePicker::onBtnAlpha,this); + childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this); + childSetAction("Invisible", LLFloaterTexturePicker::onBtnInvisible,this); + + // tag: vaa emerald local_asset_browser [begin] +// childSetAction("Local", LLFloaterTexturePicker::onBtnLocal, this); +// childSetAction("Server", LLFloaterTexturePicker::onBtnServer, this); + childSetAction("Add", LLFloaterTexturePicker::onBtnAdd, this); + childSetAction("Remove", LLFloaterTexturePicker::onBtnRemove, this); + childSetAction("Browser", LLFloaterTexturePicker::onBtnBrowser, this); + + mLocalScrollCtrl = getChild("local_name_list"); + mLocalScrollCtrl->setCallbackUserData(this); + mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit); + LocalAssetBrowser::UpdateTextureCtrlList( mLocalScrollCtrl ); + // tag: vaa emerald local_asset_browser [end] + + childSetCommitCallback("show_folders_check", onShowFolders, this); + childSetVisible("show_folders_check", FALSE); + + mSearchEdit = getChild("inventory search editor"); + mSearchEdit->setSearchCallback(onSearchEdit, this); + + mInventoryPanel = getChild("inventory panel"); + + if(mInventoryPanel) + { + U32 filter_types = 0x0; + filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; + filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; + + mInventoryPanel->setFilterTypes(filter_types); + //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss. + mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask); + mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2)); + mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + mInventoryPanel->setAllowMultiSelect(FALSE); + + // store this filter as the default one + mInventoryPanel->getRootFolder()->getFilter()->markDefault(); + + // Commented out to stop opening all folders with textures + // mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_TEXTURE); + + // don't put keyboard focus on selected item, because the selection callback + // will assume that this was user input + mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); + } + + mNoCopyTextureSelected = FALSE; + + childSetValue("apply_immediate_check", gSavedSettings.getBOOL("ApplyTextureImmediately")); + childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); + + if (!mCanApplyImmediately) + { + childSetEnabled("show_folders_check", FALSE); + } + + getChild("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this)); + childSetAction("ApplyUUID", LLFloaterTexturePicker::onBtnUUID,this); + childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this); + childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this); + + // update permission filter once UI is fully initialized + updateFilterPermMask(); + LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1)); return TRUE; } @@ -624,6 +626,7 @@ void LLFloaterTexturePicker::draw() childSetEnabled("Default", mImageAssetID != mOwner->getDefaultImageAssetID()); childSetEnabled("Blank", mImageAssetID != mWhiteImageAssetID ); + childSetEnabled("None", mOwner->getAllowNoTexture() && !mImageAssetID.isNull() ); childSetEnabled("Invisible", mOwner->getAllowInvisibleTexture() && mImageAssetID != mInvisibleImageAssetID ); childSetEnabled("Alpha", mImageAssetID != mAlphaImageAssetID ); @@ -758,6 +761,13 @@ void LLFloaterTexturePicker::onBtnWhite(void* userdata) self->commitIfImmediateSet(); } +// static +void LLFloaterTexturePicker::onBtnNone(void* userdata) +{ + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setImageID( LLUUID::null ); + self->commitIfImmediateSet(); +} // static void LLFloaterTexturePicker::onBtnInvisible(void* userdata) @@ -876,26 +886,18 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl *ctrl, void *userdata) // tag: vaa emerald local_asset_browser [end] -// static -void LLFloaterTexturePicker::onBtnPipette( void* userdata ) +void LLFloaterTexturePicker::onBtnPipette() { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - - if ( self) + BOOL pipette_active = getChild("Pipette")->getValue().asBoolean(); + pipette_active = !pipette_active; + if (pipette_active) { - BOOL pipette_active = self->childGetValue("Pipette").asBoolean(); - pipette_active = !pipette_active; - if (pipette_active) - { - LLToolPipette::getInstance()->setSelectCallback(onTextureSelect, self); - LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance()); - } - else - { - LLToolMgr::getInstance()->clearTransientTool(); - } + LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance()); + } + else + { + LLToolMgr::getInstance()->clearTransientTool(); } - } // static @@ -916,33 +918,32 @@ void LLFloaterTexturePicker::onBtnUUID( void* userdata ) } // static -void LLFloaterTexturePicker::onSelectionChange(const std::deque &items, BOOL user_action, void* data) +void LLFloaterTexturePicker::onSelectionChange(const std::deque &items, BOOL user_action) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data; if (items.size()) { LLFolderViewItem* first_item = items.front(); LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); - self->mNoCopyTextureSelected = FALSE; + mNoCopyTextureSelected = FALSE; if (itemp) { // if (itemp->getPermissions().getMaskOwner() & PERM_ALL) - self->childSetValue("texture_uuid", self->mImageAssetID); + childSetValue("texture_uuid", mImageAssetID); else - self->childSetValue("texture_uuid", LLUUID::null.asString()); + childSetValue("texture_uuid", LLUUID::null.asString()); // if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) { - self->mNoCopyTextureSelected = TRUE; + mNoCopyTextureSelected = TRUE; } - self->mImageAssetID = itemp->getAssetUUID(); - self->mIsDirty = TRUE; + mImageAssetID = itemp->getAssetUUID(); + mIsDirty = TRUE; if (user_action) { // only commit intentional selections, not implicit ones - self->commitIfImmediateSet(); + commitIfImmediateSet(); } } } @@ -1017,32 +1018,28 @@ void LLFloaterTexturePicker::onSearchEdit(const std::string& search_string, void picker->mInventoryPanel->setFilterSubString(upper_case_search_string); } -//static -void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te, void *data ) +void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data; - - LLUUID inventory_item_id = self->findItemID(te.getID(), TRUE); - if (self && inventory_item_id.notNull()) + LLUUID inventory_item_id = findItemID(te.getID(), TRUE); + if (inventory_item_id.notNull()) { LLToolPipette::getInstance()->setResult(TRUE, ""); - self->setImageID(te.getID()); - - self->mNoCopyTextureSelected = FALSE; + setImageID(te.getID()); + mNoCopyTextureSelected = FALSE; LLInventoryItem* itemp = gInventory.getItem(inventory_item_id); if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) { // no copy texture - self->mNoCopyTextureSelected = TRUE; + mNoCopyTextureSelected = TRUE; } else { - self->childSetValue("texture_uuid", inventory_item_id.asString()); + childSetValue("texture_uuid", inventory_item_id.asString()); } - self->commitIfImmediateSet(); + commitIfImmediateSet(); } else { diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 5d4894948..84096d94a 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -408,7 +408,7 @@ public: } } - virtual bool followRedir() + /*virtual*/ bool followRedir() const { return mFollowRedir; } @@ -1282,7 +1282,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { //NOTE: //control the number of the http requests issued for: - //1, not openning too many file descriptors at the same time; + //1, not opening too many file descriptors at the same time; //2, control the traffic of http so udp gets bandwidth. // static const LLCachedControl max_http_requests("HTTPMaxRequests", 32); @@ -2223,27 +2223,21 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) { lockQueue() ; LLTextureFetchWorker* worker = getWorkerAfterLock(id); - if (worker) - { - size_t erased_1 = mRequestMap.erase(worker->mID); - unlockQueue() ; - llassert_always(erased_1 > 0) ; - - removeFromNetworkQueue(worker, cancel); - llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ; - - worker->scheduleDelete(); - } - else - { - unlockQueue() ; - } + removeRequest(worker, cancel, false); } -void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel) +void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel, bool bNeedsLock) { - lockQueue() ; + if(!worker) + { + if(!bNeedsLock) + unlockQueue() ; + return; + } + if(bNeedsLock) + lockQueue() ; + size_t erased_1 = mRequestMap.erase(worker->mID); unlockQueue() ; @@ -2254,6 +2248,23 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel) worker->scheduleDelete(); } +void LLTextureFetch::deleteAllRequests() +{ + while(1) + { + lockQueue(); + if(mRequestMap.empty()) + { + unlockQueue() ; + break; + } + + LLTextureFetchWorker* worker = mRequestMap.begin()->second; + + removeRequest(worker, true, false); + } +} + S32 LLTextureFetch::getNumRequests() { lockQueue() ; diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index b0caf2619..ea72f4582 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -69,6 +69,7 @@ public: 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, bool can_use_http); void deleteRequest(const LLUUID& id, bool cancel); + void deleteAllRequests(); bool getRequestFinished(const LLUUID& id, S32& discard_level, LLPointer& raw, LLPointer& aux); bool updateRequestPriority(const LLUUID& id, F32 priority); @@ -118,7 +119,7 @@ protected: void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); void addToHTTPQueue(const LLUUID& id); void removeFromHTTPQueue(const LLUUID& id, S32 received_size = 0); - void removeRequest(LLTextureFetchWorker* worker, bool cancel); + void removeRequest(LLTextureFetchWorker* worker, bool cancel, bool bNeedsLock = true); // Overrides from the LLThread tree bool runCondition(); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index d39061bb4..a49674550 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1089,14 +1089,17 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj, { return; } - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); + //LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); S32 num_faces = hit_obj->getNumTEs(); for( S32 face = 0; face < num_faces; face++ ) { // update viewer side image in anticipation of update from simulator - hit_obj->setTEImage(face, image); + //hit_obj->setTEImage(face, image); + hit_obj->setTETexture(face, asset_id); //Singu note: setTETexture will allow the real id to be passed to LLPrimitive::setTETexture, + // even if it's null. setTEImage would actually pass down IMG_DEFAULT under such a case, + // which we don't want. dialog_refresh_all(); } // send the update to the simulator @@ -1157,9 +1160,12 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, return; } // update viewer side image in anticipation of update from simulator - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); + //LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); - hit_obj->setTEImage(hit_face, image); + //hit_obj->setTEImage(hit_face, image); + hit_obj->setTETexture(hit_face, asset_id); //Singu note: setTETexture will allow the real id to be passed to LLPrimitive::setTETexture, + // even if it's null. setTEImage would actually pass down IMG_DEFAULT under such a case, + // which we don't want. dialog_refresh_all(); // send the update to the simulator diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp index 9d95ccc06..878ed0f9a 100644 --- a/indra/newview/lltoolpipette.cpp +++ b/indra/newview/lltoolpipette.cpp @@ -55,8 +55,6 @@ LLToolPipette::LLToolPipette() : LLTool(std::string("Pipette")), mSuccess(TRUE) { - mSelectCallback = NULL; - mUserData = NULL; } @@ -106,6 +104,15 @@ BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky return TRUE; } +void LLToolPipette::setTextureEntry(const LLTextureEntry* entry) +{ + if (entry) + { + mTextureEntry = *entry; + mSignal(mTextureEntry); + } +} + void LLToolPipette::pickCallback(const LLPickInfo& pick_info) { LLViewerObject* hit_obj = pick_info.getObject(); @@ -118,20 +125,11 @@ void LLToolPipette::pickCallback(const LLPickInfo& pick_info) { //TODO: this should highlight the selected face only LLSelectMgr::getInstance()->highlightObjectOnly(hit_obj); - LLToolPipette::getInstance()->mTextureEntry = *hit_obj->getTE(pick_info.mObjectFace); - if (LLToolPipette::getInstance()->mSelectCallback) - { - LLToolPipette::getInstance()->mSelectCallback(LLToolPipette::getInstance()->mTextureEntry, LLToolPipette::getInstance()->mUserData); - } + const LLTextureEntry* entry = hit_obj->getTE(pick_info.mObjectFace); + LLToolPipette::getInstance()->setTextureEntry(entry); } } -void LLToolPipette::setSelectCallback(select_callback callback, void* user_data) -{ - mSelectCallback = callback; - mUserData = user_data; -} - void LLToolPipette::setResult(BOOL success, const std::string& msg) { mTooltipMsg = msg; diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h index 54c24e946..b9d53623f 100644 --- a/indra/newview/lltoolpipette.h +++ b/indra/newview/lltoolpipette.h @@ -56,18 +56,19 @@ public: virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen); - typedef void (*select_callback)(const LLTextureEntry& te, void *data); - void setSelectCallback(select_callback callback, void* user_data); + // Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots + typedef boost::signals2::signal signal_t; + void setToolSelectCallback(const signal_t::slot_type& cb) { mSignal.connect(cb); } void setResult(BOOL success, const std::string& msg); - + + void setTextureEntry(const LLTextureEntry* entry); static void pickCallback(const LLPickInfo& pick_info); protected: LLTextureEntry mTextureEntry; - select_callback mSelectCallback; + signal_t mSignal; BOOL mSuccess; std::string mTooltipMsg; - void* mUserData; }; #endif //LL_LLTOOLPIPETTE_H diff --git a/indra/newview/lltracker.h b/indra/newview/lltracker.h index 285036527..c727c29d5 100644 --- a/indra/newview/lltracker.h +++ b/indra/newview/lltracker.h @@ -81,7 +81,7 @@ public: // these are static so that they can be used a callbacks static ETrackingStatus getTrackingStatus() { return instance()->mTrackingStatus; } static ETrackingLocationType getTrackedLocationType() { return instance()->mTrackingLocationType; } - static BOOL isTracking(void*) { return (BOOL) instance()->mTrackingStatus; } + static BOOL isTracking(void*) { return instance()->mTrackingStatus != TRACKING_NOTHING; } static void stopTracking(void*); static void clearFocus(); diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 1144c5827..a9971abbd 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -45,6 +45,7 @@ #include "llurlsimstring.h" #include "llweb.h" #include "llworldmap.h" +#include "llworldmapmessage.h" // library includes #include "llsd.h" @@ -243,7 +244,7 @@ bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mous 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 @@ -282,7 +283,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); } @@ -401,7 +402,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/lluserauth.cpp b/indra/newview/lluserauth.cpp index a692f9575..a0791989e 100644 --- a/indra/newview/lluserauth.cpp +++ b/indra/newview/lluserauth.cpp @@ -323,7 +323,16 @@ LLUserAuth::UserAuthcode LLUserAuth::parseResponse() // will all be string => string pairs. UserAuthcode rv = E_UNHANDLED_ERROR; XMLRPC_REQUEST response = mResponder->response(); - if(!response) return rv; + if(!response) + { + U32 status = mResponder->http_status(); + // Is it an HTTP error? + if (!(200 <= status && status < 400)) + { + rv = E_HTTP_SERVER_ERROR; + } + return rv; + } // clear out any old parsing mResponses.clear(); diff --git a/indra/newview/lluserauth.h b/indra/newview/lluserauth.h index 847b1e8b5..1bc76cb84 100644 --- a/indra/newview/lluserauth.h +++ b/indra/newview/lluserauth.h @@ -88,6 +88,7 @@ public: E_SSL_PEER_CERTIFICATE, E_SSL_CACERT, E_SSL_CONNECT_ERROR, + E_HTTP_SERVER_ERROR, E_UNHANDLED_ERROR, E_LAST // never use! } UserAuthcode; diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 958f4f0e6..7df652c41 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -253,8 +253,11 @@ void audio_update_wind(bool force_update) // which is sufficient to completely turn off or turn on wind noise volume_delta = 1.f; } - // mute wind entirely when the user asked - if (gSavedSettings.getBOOL("MuteWind")) + + static LLCachedControl MuteWind("MuteWind"); + static LLCachedControl ContinueFlying("LiruContinueFlyingOnUnsit"); + // mute wind entirely when the user asked or when the user is seated, but flying + if (MuteWind || (ContinueFlying && gAgentAvatarp&& gAgentAvatarp->isSitting())) { // volume decreases by itself gAudiop->mMaxWindGain = 0.f; diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index a4a05fca8..82d88bc3d 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -52,9 +52,20 @@ const F32 OGL_TO_CFR_ROTATION[16] = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X const BOOL FOR_SELECTION = TRUE; const BOOL NOT_FOR_SELECTION = FALSE; + +LL_ALIGN_PREFIX(16) class LLViewerCamera : public LLCamera, public LLSingleton { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } typedef enum { @@ -138,6 +149,7 @@ protected: S16 mZoomSubregion; public: -}; +} LL_ALIGN_POSTFIX(16); + #endif // LL_LLVIEWERCAMERA_H diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 4e1ad8645..ee7e04803 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -437,6 +437,7 @@ static bool handleRepartition(const LLSD&) if (gPipeline.isInit()) { gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); + gOctreeReserveCapacity = llmin(gSavedSettings.getU32("OctreeReserveNodeCapacity"),U32(512)); gObjectList.repartitionObjects(); } return true; @@ -638,6 +639,7 @@ void settings_setup_listeners() gSavedSettings.getControl("OctreeStaticObjectSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeMaxNodeCapacity")->getSignal()->connect(boost::bind(&handleRepartition, _2)); + gSavedSettings.getControl("OctreeReserveNodeCapacity")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeAlphaDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeAttachmentSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("RenderMaxTextureIndex")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 8c932285b..e8294fc8b 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -51,6 +51,7 @@ #include "llhudmanager.h" #include "llimagebmp.h" #include "llimagegl.h" +#include "lloctree.h" #include "llselectmgr.h" #include "llsky.h" #include "llstartup.h" @@ -90,6 +91,8 @@ #include "rlvlocks.h" // [/RLVa:KB] +extern bool gShiftFrame; + LLPointer gDisconnectedImagep = NULL; // used to toggle renderer back on after teleport @@ -185,7 +188,8 @@ void display_update_camera(bool tiling=false) // Cut draw distance in half when customizing avatar, // but on the viewer only. F32 final_far = gAgentCamera.mDrawDistance; - if(tiling) //Don't animate clouds and water if tiling! + static const LLCachedControl freeze_time("FreezeTime",false); + if(freeze_time || tiling) //Don't animate clouds and water if tiling! { LLViewerCamera::getInstance()->setFar(final_far); gViewerWindow->setup3DRender(); @@ -223,6 +227,9 @@ void display_stats() F32 fps = gRecentFrameCount / fps_log_freq; llinfos << llformat("FPS: %.02f", fps) << llendl; llinfos << llformat("VBO: %d glVBO: %d", LLVertexBuffer::sCount, LLVertexBuffer::sGLCount) << llendl; +#ifdef LL_OCTREE_STATS + OctreeStats::getInstance()->dump(); +#endif gRecentFrameCount = 0; gRecentFPSTime.reset(); } @@ -318,6 +325,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo } gViewerWindow->checkSettings(); + + if(gWindowResized) //Singu Note: gViewerWindow->checkSettings() can call LLViewerWindow::reshape(). If it has then skip this frame. + { + return; + } { LLFastTimer ftm(FTM_PICK); @@ -411,18 +423,30 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo gAgent.setTeleportMessage(std::string()); } + static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); const std::string& message = gAgent.getTeleportMessage(); switch( gAgent.getTeleportState() ) { + case LLAgent::TELEPORT_PENDING: + gTeleportDisplayTimer.reset(); + if(!hide_tp_screen) + gViewerWindow->setShowProgress(TRUE); + gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); + gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["pending"]); + gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["pending"]); + break; + case LLAgent::TELEPORT_START: // Transition to REQUESTED. Viewer has sent some kind // of TeleportRequest to the source simulator gTeleportDisplayTimer.reset(); - if(!gSavedSettings.getBOOL("AscentDisableTeleportScreens"))gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressPercent(0); + if(!hide_tp_screen) + gViewerWindow->setShowProgress(TRUE); + gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); + gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: @@ -446,14 +470,15 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["arriving"]); gTextureList.mForceResetTextureStats = TRUE; - if(!gSavedSettings.getBOOL("AscentDisableTeleportScreens"))gAgentCamera.resetView(TRUE, TRUE); + if(!hide_tp_screen) + gAgentCamera.resetView(TRUE, TRUE); break; case LLAgent::TELEPORT_ARRIVING: // Make the user wait while content "pre-caches" { F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); - if( arrival_fraction > 1.f || gSavedSettings.getBOOL("AscentDisableTeleportScreens")) + if( arrival_fraction > 1.f || hide_tp_screen) { arrival_fraction = 1.f; LLFirstUse::useTeleport(); @@ -1109,6 +1134,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo display_stats(); LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); + + gShiftFrame = false; } void render_hud_attachments() diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index d9e9499ce..eb8b79a2a 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -568,8 +568,8 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { // This warning will always trigger if you've hacked the avatar to show as incomplete. // Ignore the warning if that's the case. - static const LLCachedControl rener_unloaded_avatar("RenderUnloadedAvatar"); - if (!rener_unloaded_avatar) + static const LLCachedControl render_unloaded_avatar("RenderUnloadedAvatar", false); + if (!render_unloaded_avatar) { llwarns << "Layerset without composite" << llendl; } @@ -736,8 +736,10 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w F32* vw = (F32*) vertex_weightsp.get(); F32* cw = (F32*) clothing_weightsp.get(); - LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), num_verts*2*sizeof(F32)); - LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), num_verts*sizeof(F32)); + S32 tc_size = (num_verts*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), tc_size); + S32 vw_size = (num_verts*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), vw_size); LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32)); } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 94b05c958..9599ae0cc 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -55,6 +55,7 @@ #include "llwindow.h" #include "llvieweraudio.h" #include "llweb.h" +#include "llwebprofile.h" #include "llfloateravatarinfo.h" // for getProfileURL() function //#include "viewerversion.h" @@ -75,14 +76,15 @@ class LLMimeDiscoveryResponder : public LLHTTPClient::ResponderHeadersOnly { LOG_CLASS(LLMimeDiscoveryResponder); public: - LLMimeDiscoveryResponder( viewer_media_t media_impl) + LLMimeDiscoveryResponder(viewer_media_t media_impl, std::string const& default_mime_type) : mMediaImpl(media_impl), + mDefaultMimeType(default_mime_type), mInitialized(false) {} /*virtual*/ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers) { - if (200 <= status && status < 300) + if (200 <= status && status < 300 || status == 405) // Using HEAD may result in a 405 METHOD NOT ALLOWED, but still have the right Content-TYpe header. { std::string media_type; if (headers.getFirstValue("content-type", media_type)) @@ -92,9 +94,13 @@ public: completeAny(status, mime_type); return; } - llwarns << "LLMimeDiscoveryResponder::completedHeaders: OK HTTP status (" << status << ") but no Content-Type! Received headers: " << headers << llendl; + if (200 <= status && status < 300) + { + llwarns << "LLMimeDiscoveryResponder::completedHeaders: OK HTTP status (" << status << ") but no Content-Type! Received headers: " << headers << llendl; + } } - completeAny(status, "none/none"); + llwarns << "LLMimeDiscoveryResponder::completedHeaders: Got status " << status << ". Using default mime-type: " << mDefaultMimeType << llendl; + completeAny(status, mDefaultMimeType); } void completeAny(U32 status, const std::string& mime_type) @@ -113,6 +119,7 @@ public: public: viewer_media_t mMediaImpl; + std::string mDefaultMimeType; bool mInitialized; }; @@ -134,12 +141,7 @@ public: { LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; LL_DEBUGS("MediaAuth") << headers << LL_ENDL; - AIHTTPReceivedHeaders::range_type cookies; - if (headers.getValues("set-cookie", cookies)) - { - for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie) - LLViewerMedia::openIDCookieResponse(cookie->second); - } + LLViewerMedia::openIDCookieResponse(get_cookie("agni_sl_session_id")); } /* virtual */ void completedRaw( @@ -168,6 +170,7 @@ public: { } + /* virtual */ bool followRedir(void) const { return true; } /* virtual */ bool needsHeaders(void) const { return true; } /* virtual */ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers) @@ -175,11 +178,29 @@ public: LL_INFOS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; LL_INFOS("MediaAuth") << headers << LL_ENDL; + bool found = false; AIHTTPReceivedHeaders::range_type cookies; if (headers.getValues("set-cookie", cookies)) { for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie) + { LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie->second, mHost); + + std::string key = cookie->second.substr(0, cookie->second.find('=')); + if (key == "_my_secondlife_session") + { + // Set cookie for snapshot publishing. + std::string auth_cookie = cookie->second.substr(0, cookie->second.find(";")); // strip path + LL_INFOS("MediaAuth") << "Setting openID auth cookie \"" << auth_cookie << "\"." << LL_ENDL; + LLWebProfile::setAuthCookie(auth_cookie); + found = true; + break; + } + } + } + if (!found) + { + llwarns << "LLViewerMediaWebProfileResponder did not receive a session ID cookie \"_my_secondlife_session\"! OpenID authentications will fail!" << llendl; } } @@ -1312,7 +1333,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi { if(mime_type.empty()) { - LLHTTPClient::getHeaderOnly( url, new LLMimeDiscoveryResponder(this)); + LLHTTPClient::getHeaderOnly(url, new LLMimeDiscoveryResponder(this, "text/html")); } else if(initializeMedia(mime_type) && (plugin = getMediaPlugin())) { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9d93b6970..c8fa64f01 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -178,14 +178,16 @@ #include "llinventorypanel.h" #include "llinventorybridge.h" #include "llkeyboard.h" -#include "llpanellogin.h" +#include "llmakeoutfitdialog.h" #include "llmenucommands.h" #include "llmenugl.h" #include "llmimetypes.h" #include "llmorphview.h" +#include "llmenuoptionpathfindingrebakenavmesh.h" #include "llmoveview.h" #include "llmutelist.h" #include "llnotify.h" +#include "llpanellogin.h" #include "llpanelobject.h" #include "llparcel.h" @@ -264,6 +266,10 @@ #include "llagentui.h" #include "llpathfindingmanager.h" +#include "lltexturecache.h" +#include "llvovolume.h" +#include + #include "hippogridmanager.h" using namespace LLOldEvents; @@ -2265,6 +2271,105 @@ class LLObjectDerender : public view_listener_t } }; +class LLTextureReloader +{ +public: + ~LLTextureReloader() + { + for(std::set< LLViewerFetchedTexture*>::iterator it=mTextures.begin();it!=mTextures.end();++it) + { + LLViewerFetchedTexture* img = *it; + const LLUUID& id = img->getID(); + if(id.notNull() && id != IMG_DEFAULT && id != IMG_DEFAULT_AVATAR && img != LLViewerFetchedTexture::sDefaultImagep) + { + LLAppViewer::getTextureCache()->removeFromCache(id); + img->forceRefetch(); + for (S32 i = 0; i < img->getNumVolumes(); ++i) + { + LLVOVolume* volume = (*(img->getVolumeList()))[i]; + if (volume && volume->isSculpted() && !volume->isMesh()) + volume->notifyMeshLoaded(); + } + } + } + } + void addTexture(LLViewerTexture* texture) + { + if(!texture) + return; + const LLUUID& id = texture->getID(); + if(id.notNull() && id != IMG_DEFAULT && id != IMG_DEFAULT_AVATAR && texture != LLViewerFetchedTexture::sDefaultImagep) + { + LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(texture); + if(img) + mTextures.insert(img); + } + } + +private: + std::set< LLViewerFetchedTexture*> mTextures; +}; +class LLAvatarReloadTextures : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(avatar) + { + LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(avatar->getID()); + LLTextureReloader texture_list; + for (U32 i = 0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) + { + if (LLVOAvatar::isIndexLocalTexture((ETextureIndex)i)) + { + if(avatar->isSelf()) + { + LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)i); + U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); + for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++) + { + texture_list.addTexture(((LLVOAvatarSelf*)avatar)->getLocalTextureGL((ETextureIndex)i,wearable_index)); + } + } + } + else + { + texture_list.addTexture(avatar->getTEImage((ETextureIndex)i)); + } + } + } + return true; + } +}; +class LLObjectReloadTextures : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLTextureReloader texture_list; + for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++) + { + LLViewerObject* object = (*iter)->getObject(); + + for (U8 i = 0; i < object->getNumTEs(); i++) + { + if((*iter)->isTESelected(i)) + { + texture_list.addTexture(object->getTEImage(i)); + } + if(object->isSculpted() && !object->isMesh()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + if(sculpt_params) + { + texture_list.addTexture(LLViewerTextureManager::getFetchedTexture(sculpt_params->getSculptTexture())); + } + } + } + } + return true; + } +}; //--------------------------------------------------------------------------- // Land pie menu @@ -3599,7 +3704,6 @@ void set_god_level(U8 god_level) // God mode changes region visibility LLWorldMap::getInstance()->reset(); - LLWorldMap::getInstance()->setCurrentLayer(0); // inventory in items may change in god mode gObjectList.dirtyAllObjectInventory(); @@ -5225,6 +5329,39 @@ class LLToolsEnablePathfindingView : public view_listener_t } }; +class LLToolsDoPathfindingRebakeRegion : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + bool hasPathfinding = (LLPathfindingManager::getInstance() != NULL); + + if (hasPathfinding) + { + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh(); + } + + return hasPathfinding; + } +}; + +class LLToolsEnablePathfindingRebakeRegion : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + bool returnValue = false; + + if (LLPathfindingManager::getInstance() != NULL) + { + LLMenuOptionPathfindingRebakeNavmesh *rebakeInstance = LLMenuOptionPathfindingRebakeNavmesh::getInstance(); + returnValue = (rebakeInstance->canRebakeRegion() && + (rebakeInstance->getMode() == LLMenuOptionPathfindingRebakeNavmesh::kRebakeNavMesh_Available)); + + } + gMenuHolder->findControl(userdata["control"].asString())->setValue(returnValue); + return returnValue; + } +}; + // Round the position of all root objects to the grid class LLToolsSnapObjectXY : public view_listener_t { @@ -6388,6 +6525,10 @@ class LLShowFloater : public view_listener_t gAgentCamera.changeCameraToCustomizeAvatar(); } } + else if (floater_name == "outfit") + { + new LLMakeOutfitDialog(false); + } // Phoenix: Wolfspirit: Enabled Show Floater out of viewer menu else if (floater_name == "displayname") { @@ -9409,7 +9550,8 @@ void initialize_menus() addMenu(new LLToolsEnablePathfinding(), "Tools.EnablePathfinding"); addMenu(new LLToolsEnablePathfindingView(), "Tools.EnablePathfindingView"); - + addMenu(new LLToolsDoPathfindingRebakeRegion(), "Tools.DoPathfindingRebakeRegion"); + addMenu(new LLToolsEnablePathfindingRebakeRegion(), "Tools.EnablePathfindingRebakeRegion"); /*addMenu(new LLToolsVisibleBuyObject(), "Tools.VisibleBuyObject"); addMenu(new LLToolsVisibleTakeObject(), "Tools.VisibleTakeObject");*/ @@ -9469,6 +9611,8 @@ void initialize_menus() addMenu(new LLObjectInspect(), "Object.Inspect"); // Visual mute, originally by Phox. addMenu(new LLObjectDerender(), "Object.DERENDER"); + addMenu(new LLAvatarReloadTextures(), "Avatar.ReloadTextures"); + addMenu(new LLObjectReloadTextures(), "Object.ReloadTextures"); addMenu(new LLObjectExport(), "Object.Export"); addMenu(new LLObjectImport(), "Object.Import"); addMenu(new LLObjectImportUpload(), "Object.ImportUpload"); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index fc795f8fb..0c1fa71a5 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -527,6 +527,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t S32 width = gViewerWindow->getWindowDisplayWidth(); S32 height = gViewerWindow->getWindowDisplayHeight(); + F32 ratio = (F32)width / height; F32 supersample = 1.f; if (gSavedSettings.getBOOL("HighResSnapshot")) @@ -546,8 +547,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t if (gViewerWindow->rawSnapshot(raw, width, height, - TRUE, - FALSE, + ratio, gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE, LLViewerWindow::SNAPSHOT_TYPE_COLOR, @@ -574,7 +574,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t formatted->enableOverSize() ; formatted->encode(raw, 0); formatted->disableOverSize(); - gViewerWindow->saveImageNumbered(formatted); + gViewerWindow->saveImageNumbered(formatted, -1); } return true; } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index e3a98c636..c452c85ab 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -208,10 +208,12 @@ static const U32 LLREQUEST_PERMISSION_THROTTLE_LIMIT = 5; // requests static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds extern BOOL gDebugClicks; +extern bool gShiftFrame; // function prototypes bool check_offer_throttle(const std::string& from_name, bool check_only); void callbackCacheEstateOwnerName(const LLUUID& id, const std::string& full_name, bool is_group); +static void process_money_balance_reply_extended(LLMessageSystem* msg); //inventory offer throttle globals LLFrameTimer gThrottleTimer; @@ -3632,29 +3634,11 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) } } - - // [Ansariel/Henri: Display name support] if (chatter && chatter->isAvatar()) { - if (LLAvatarNameCache::useDisplayNames()) - { - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(from_id, &avatar_name)) - { - static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - if (phoenix_name_system == 2 || (phoenix_name_system == 1 && avatar_name.mIsDisplayNameDefault)) - { - from_name = avatar_name.mDisplayName; - } - else - { - from_name = avatar_name.getCompleteName(); - } - } + if (LLAvatarNameCache::getPNSName(from_id, from_name)) chat.mFromName = from_name; - } } - // [/Ansariel/Henri: Display name support] BOOL visible_in_chat_bubble = FALSE; std::string verb; @@ -4221,6 +4205,7 @@ void process_avatar_init_complete(LLMessageSystem* msg, void**) void process_agent_movement_complete(LLMessageSystem* msg, void**) { + gShiftFrame = true; gAgentMovementCompleted = true; LLUUID agent_id; @@ -5400,7 +5385,10 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) gAgentCamera.setForceMouselook(force_mouselook); // Forcing turning off flying here to prevent flying after pressing "Stand" // to stand up from an object. See EXT-1655. - gAgent.setFlying(FALSE); + // Unless the user wants to. + static LLCachedControl ContinueFlying("LiruContinueFlyingOnUnsit"); + if (!ContinueFlying) + gAgent.setFlying(FALSE); LLViewerObject* object = gObjectList.findObject(sitObjectID); if (object) @@ -5704,20 +5692,20 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) gStatusBar->setLandCredit(credit); gStatusBar->setLandCommitted(committed); } - static std::deque recent; - if(!desc.empty() && gSavedSettings.getBOOL("NotifyMoneyChange") - && (std::find(recent.rbegin(), recent.rend(), tid) == recent.rend())) - { - // Make the user confirm the transaction, since they might - // have missed something during an event. - // *TODO:translate - LLSD args; - args["MESSAGE"] = desc; - LLNotificationsUtil::add("SystemMessage", args); - // Also send notification to chat -- MC - LLChat chat(desc); - LLFloaterChat::addChat(desc); + if (desc.empty() + || !gSavedSettings.getBOOL("NotifyMoneyChange")) + { + // ...nothing to display + return; + } + + // Suppress duplicate messages about the same transaction + static std::deque recent; + if (std::find(recent.rbegin(), recent.rend(), tid) != recent.rend()) + { + return; + } // Once the 'recent' container gets large enough, chop some // off the beginning. @@ -5730,20 +5718,247 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) } //LL_DEBUGS("Messaging") << "Pushing back transaction " << tid << LL_ENDL; recent.push_back(tid); + + if (msg->has("TransactionInfo")) + { + // ...message has extended info for localization + process_money_balance_reply_extended(msg); + } + else + { + // Only old dev grids will not supply the TransactionInfo block, + // so we can just use the hard-coded English string. + LLSD args; + args["MESSAGE"] = desc; + LLNotificationsUtil::add("SystemMessage", args); + + // Also send notification to chat -- MC + LLChat chat(desc); + LLFloaterChat::addChat(desc); } } -bool handle_special_notification_callback(const LLSD& notification, const LLSD& response) +static std::string reason_from_transaction_type(S32 transaction_type, + const std::string& item_desc) +{ + // *NOTE: The keys for the reason strings are unusual because + // an earlier version of the code used English language strings + // extracted from hard-coded server English descriptions. + // Keeping them so we don't have to re-localize them. + switch (transaction_type) + { + case TRANS_OBJECT_SALE: + { + LLStringUtil::format_map_t arg; + arg["ITEM"] = item_desc; + return LLTrans::getString("for item", arg); + } + case TRANS_LAND_SALE: + return LLTrans::getString("for a parcel of land"); + + case TRANS_LAND_PASS_SALE: + return LLTrans::getString("for a land access pass"); + + case TRANS_GROUP_LAND_DEED: + return LLTrans::getString("for deeding land"); + + case TRANS_GROUP_CREATE: + return LLTrans::getString("to create a group"); + + case TRANS_GROUP_JOIN: + return LLTrans::getString("to join a group"); + + case TRANS_UPLOAD_CHARGE: + return LLTrans::getString("to upload"); + + case TRANS_CLASSIFIED_CHARGE: + return LLTrans::getString("to publish a classified ad"); + + // These have no reason to display, but are expected and should not + // generate warnings + case TRANS_GIFT: + case TRANS_PAY_OBJECT: + case TRANS_OBJECT_PAYS: + return std::string(); + + default: + llwarns << "Unknown transaction type " + << transaction_type << llendl; + return std::string(); + } +} + +static void process_money_balance_reply_extended(LLMessageSystem* msg) +{ + // Added in server 1.40 and viewer 2.1, support for localization + // and agent ids for name lookup. + S32 transaction_type = 0; + LLUUID source_id; + BOOL is_source_group = false; + LLUUID dest_id; + BOOL is_dest_group = false; + S32 amount = 0; + std::string item_description; + BOOL success = false; + + msg->getS32("TransactionInfo", "TransactionType", transaction_type); + msg->getUUID("TransactionInfo", "SourceID", source_id); + msg->getBOOL("TransactionInfo", "IsSourceGroup", is_source_group); + msg->getUUID("TransactionInfo", "DestID", dest_id); + msg->getBOOL("TransactionInfo", "IsDestGroup", is_dest_group); + msg->getS32("TransactionInfo", "Amount", amount); + msg->getString("TransactionInfo", "ItemDescription", item_description); + msg->getBOOL("MoneyData", "TransactionSuccess", success); + LL_INFOS("Money") << "MoneyBalanceReply source " << source_id + << " dest " << dest_id + << " type " << transaction_type + << " item " << item_description << LL_ENDL; + + if (source_id.isNull() && dest_id.isNull()) + { + // this is a pure balance update, no notification required + return; + } + + std::string source_slurl; + if (is_source_group) + { + gCacheName->getGroupName(source_id, source_slurl); + } + else + { + LLAvatarNameCache::getPNSName(source_id, source_slurl); + } + + std::string dest_slurl; + if (is_dest_group) + { + gCacheName->getGroupName(dest_id, dest_slurl); + } + else + { + LLAvatarNameCache::getPNSName(dest_id, dest_slurl); + } + + std::string reason = + reason_from_transaction_type(transaction_type, item_description); + + LLStringUtil::format_map_t args; + args["REASON"] = reason; // could be empty + args["AMOUNT"] = llformat("%d", amount); + + // Need to delay until name looked up, so need to know whether or not + // is group + bool is_name_group = false; + LLUUID name_id; + std::string message; + static LLCachedControl no_transaction_clutter("LiruNoTransactionClutter", false); + std::string notification = no_transaction_clutter ? "Payment" : "SystemMessage"; + LLSD final_args; + LLSD payload; + + bool you_paid_someone = (source_id == gAgentID); + if (you_paid_someone) + { + args["NAME"] = dest_slurl; + is_name_group = is_dest_group; + name_id = dest_id; + if (!reason.empty()) + { + if (dest_id.notNull()) + { + message = success ? LLTrans::getString("you_paid_ldollars", args) : + LLTrans::getString("you_paid_failure_ldollars", args); + } + else + { + // transaction fee to the system, eg, to create a group + message = success ? LLTrans::getString("you_paid_ldollars_no_name", args) : + LLTrans::getString("you_paid_failure_ldollars_no_name", args); + } + } + else + { + if (dest_id.notNull()) + { + message = success ? LLTrans::getString("you_paid_ldollars_no_reason", args) : + LLTrans::getString("you_paid_failure_ldollars_no_reason", args); + } + else + { + // no target, no reason, you just paid money + message = success ? LLTrans::getString("you_paid_ldollars_no_info", args) : + LLTrans::getString("you_paid_failure_ldollars_no_info", args); + } + } + final_args["MESSAGE"] = message; + } + else + { + // ...someone paid you + args["NAME"] = source_slurl; + is_name_group = is_source_group; + name_id = source_id; + if (!reason.empty()) + { + message = LLTrans::getString("paid_you_ldollars", args); + } + else + { + message = LLTrans::getString("paid_you_ldollars_no_reason", args); + } + final_args["MESSAGE"] = message; + + // make notification loggable + payload["from_id"] = source_id; + } + + // Despite using SLURLs, wait until the name is available before + // showing the notification, otherwise the UI layout is strange and + // the user sees a "Loading..." message + if (is_name_group) + { + gCacheName->getGroup(name_id, + boost::bind(&LLNotificationsUtil::add, + notification, final_args, payload)); + } + else + { + LLAvatarNameCache::get(name_id, + boost::bind(&LLNotificationsUtil::add, + notification, final_args, payload)); + } +} + +bool handle_prompt_for_maturity_level_change_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option) { // set the preference to the maturity of the region we're calling - int preferredMaturity = notification["payload"]["_region_access"].asInteger(); - gSavedSettings.setU32("PreferredMaturity", preferredMaturity); - gAgent.sendMaturityPreferenceToServer(preferredMaturity); + U8 preferredMaturity = static_cast(notification["payload"]["_region_access"].asInteger()); + gSavedSettings.setU32("PreferredMaturity", static_cast(preferredMaturity)); + } + + return false; +} +bool handle_prompt_for_maturity_level_change_and_reteleport_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (0 == option) + { + // set the preference to the maturity of the region we're calling + U8 preferredMaturity = static_cast(notification["payload"]["_region_access"].asInteger()); + gSavedSettings.setU32("PreferredMaturity", static_cast(preferredMaturity)); + gAgent.setMaturityRatingChangeDuringTeleport(preferredMaturity); + gAgent.restartFailedTeleportRequest(); + } + else + { + gAgent.clearTeleportRequest(); } return false; @@ -5752,39 +5967,148 @@ bool handle_special_notification_callback(const LLSD& notification, const LLSD& // some of the server notifications need special handling. This is where we do that. bool handle_special_notification(std::string notificationID, LLSD& llsdBlock) { - int regionAccess = llsdBlock["_region_access"].asInteger(); - llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess); - - // we're going to throw the LLSD in there in case anyone ever wants to use it - LLNotificationsUtil::add(notificationID+"_Notify", llsdBlock); + U8 regionAccess = static_cast(llsdBlock["_region_access"].asInteger()); + std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); + LLStringUtil::toLower(regionMaturity); + llsdBlock["REGIONMATURITY"] = regionMaturity; + bool returnValue = false; + LLNotificationPtr maturityLevelNotification; + std::string notifySuffix = "_Notify"; if (regionAccess == SIM_ACCESS_MATURE) { if (gAgent.isTeen()) { - LLNotificationsUtil::add(notificationID+"_KB", llsdBlock); - return true; + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; } else if (gAgent.prefersPG()) { - LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); - return true; + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock); + returnValue = true; } } else if (regionAccess == SIM_ACCESS_ADULT) { if (!gAgent.isAdult()) { - LLNotificationsUtil::add(notificationID+"_KB", llsdBlock); - return true; + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; } else if (gAgent.prefersPG() || gAgent.prefersMature()) { - LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); - return true; + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock); + returnValue = true; } } - return false; + + if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored()) + { + // Given a simple notification if no maturityLevelNotification is set or it is ignore + LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); + } + + return returnValue; +} + +// some of the server notifications need special handling. This is where we do that. +bool handle_teleport_access_blocked(LLSD& llsdBlock) +{ + std::string notificationID("TeleportEntryAccessBlocked"); + U8 regionAccess = static_cast(llsdBlock["_region_access"].asInteger()); + std::string regionMaturity = LLViewerRegion::accessToString(regionAccess); + LLStringUtil::toLower(regionMaturity); + llsdBlock["REGIONMATURITY"] = regionMaturity; + + bool returnValue = false; + LLNotificationPtr maturityLevelNotification; + std::string notifySuffix = "_Notify"; + if (regionAccess == SIM_ACCESS_MATURE) + { + if (gAgent.isTeen()) + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG()) + { + if (gAgent.hasRestartableFailedTeleportRequest()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); + returnValue = true; + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + } + else if (regionAccess == SIM_ACCESS_ADULT) + { + if (!gAgent.isAdult()) + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock); + returnValue = true; + + notifySuffix = "_NotifyAdultsOnly"; + } + else if (gAgent.prefersPG() || gAgent.prefersMature()) + { + if (gAgent.hasRestartableFailedTeleportRequest()) + { + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback); + returnValue = true; + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + } + else + { + gAgent.clearTeleportRequest(); + maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); + returnValue = true; + } + } + + if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored()) + { + // Given a simple notification if no maturityLevelNotification is set or it is ignore + LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock); + } + + return returnValue; } bool attempt_standard_notification(LLMessageSystem* msgsystem) @@ -5828,16 +6152,20 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) RegionEntryAccessBlocked RegionEntryAccessBlocked_Notify + RegionEntryAccessBlocked_NotifyAdultsOnly RegionEntryAccessBlocked_Change - RegionEntryAccessBlocked_KB + RegionEntryAccessBlocked_AdultsOnlyContent + RegionEntryAccessBlocked_ChangeAndReTeleport LandClaimAccessBlocked LandClaimAccessBlocked_Notify + LandClaimAccessBlocked_NotifyAdultsOnly LandClaimAccessBlocked_Change - LandClaimAccessBlocked_KB + LandClaimAccessBlocked_AdultsOnlyContent LandBuyAccessBlocked LandBuyAccessBlocked_Notify + LandBuyAccessBlocked_NotifyAdultsOnly LandBuyAccessBlocked_Change - LandBuyAccessBlocked_KB + LandBuyAccessBlocked_AdultsOnlyContent -----------------------------------------------------------------------*/ if (handle_special_notification(notificationID, llsdBlock)) @@ -5889,6 +6217,30 @@ void process_alert_message(LLMessageSystem *msgsystem, void **user_data) } } +bool handle_not_age_verified_alert(const std::string &pAlertName) +{ + LLNotificationPtr notification = LLNotificationsUtil::add(pAlertName); + if ((notification == NULL) || notification->isIgnored()) + { + LLNotificationsUtil::add(pAlertName + "_Notify"); + } + + return true; +} + +bool handle_special_alerts(const std::string &pAlertName) +{ + bool isHandled = false; + + if (LLStringUtil::compareStrings(pAlertName, "NotAgeVerified") == 0) + { + + isHandled = handle_not_age_verified_alert(pAlertName); + } + + return isHandled; +} + void process_alert_core(const std::string& message, BOOL modal) { // HACK -- handle callbacks for specific alerts @@ -5912,7 +6264,10 @@ void process_alert_core(const std::string& message, BOOL modal) // Allow the server to spawn a named alert so that server alerts can be // translated out of English. std::string alert_name(message.substr(ALERT_PREFIX.length())); - LLNotificationsUtil::add(alert_name); + if (!handle_special_alerts(alert_name)) + { + LLNotificationsUtil::add(alert_name); + } } else if (message.find(NOTIFY_PREFIX) == 0) { @@ -6213,6 +6568,7 @@ bool script_question_cb(const LLSD& notification, const LLSD& response) // ...with description on top LLNotificationsUtil::add("DebitPermissionDetails"); + return false; } // check whether permissions were granted or denied @@ -6581,7 +6937,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**) else { // change notification name in this special case - if (handle_special_notification("RegionEntryAccessBlocked", llsd_block)) + if (handle_teleport_access_blocked(llsd_block)) { if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { @@ -6650,8 +7006,9 @@ void process_teleport_local(LLMessageSystem *msg,void**) } } + static LLCachedControl fly_after_tp(gSavedSettings, "LiruFlyAfterTeleport"); // Sim tells us whether the new position is off the ground - if (teleport_flags & TELEPORT_FLAGS_IS_FLYING) + if (fly_after_tp || (teleport_flags & TELEPORT_FLAGS_IS_FLYING)) { gAgent.setFlying(TRUE); } @@ -7044,40 +7401,35 @@ void process_script_dialog(LLMessageSystem* msg, void**) } else { - for (i = 1; i < button_count; i++) - { - std::string tdesc; - msg->getString("Buttons", "ButtonLabel", tdesc, i); - form.addElement("button", std::string(tdesc)); - } + for (i = 1; i < button_count; i++) + { + std::string tdesc; + msg->getString("Buttons", "ButtonLabel", tdesc, i); + form.addElement("button", std::string(tdesc)); + } } LLSD args; args["TITLE"] = object_name; args["MESSAGE"] = message; - // args["CHANNEL"] = chat_channel; - // LLNotificationPtr notification; - if (!first_name.empty()) + bool const is_group = first_name.empty(); + char const* name = (is_group && !is_text_box) ? "GROUPNAME" : "NAME"; + args[name] = is_group ? last_name : LLCacheName::buildFullName(first_name, last_name); + if (is_text_box) + { + args["DEFAULT"] = default_text; + payload["textbox"] = "true"; + LLNotificationsUtil::add("ScriptTextBoxDialog", args, payload, callback_script_dialog); + } + else if (!first_name.empty()) { - args["NAME"] = LLCacheName::buildFullName(first_name, last_name); - - if (is_text_box) - { - args["DEFAULT"] = default_text; - payload["textbox"] = "true"; - LLNotificationsUtil::add("ScriptTextBoxDialog", args, payload, callback_script_dialog); - } - else - { notification = LLNotifications::instance().add( LLNotification::Params("ScriptDialog").substitutions(args).payload(payload).form_elements(form.asLLSD())); } - } else { - args["GROUPNAME"] = last_name; notification = LLNotifications::instance().add( LLNotification::Params("ScriptDialogGroup").substitutions(args).payload(payload).form_elements(form.asLLSD())); } diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index a2625495c..dde9a9d47 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -77,6 +77,7 @@ bool LLViewerLogin::isSecondLife() bool LLViewerLogin::isInProductionGrid() { - return true; + // Return true (as before) on opensim grids, but return the real thing (agni or not) on SL. + return !gHippoGridManager->getConnectedGrid()->isSecondLife() || gHippoGridManager->getConnectedGrid()->isInProductionGrid(); } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index e917727d1..35f8e6931 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -205,6 +205,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mID(id), mLocalID(0), mTotalCRC(0), + mListIndex(-1), mTEImages(NULL), mGLName(0), mbCanSelect(TRUE), @@ -242,6 +243,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mTimeDilation(1.f), mRotTime(0.f), mAngularVelocityRot(), + mPreviousRotation(), mState(0), mMedia(NULL), mClickAction(0), @@ -271,7 +273,12 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe { mPositionAgent = mRegionp->getOriginAgent(); } - resetRot(); + + static const LLCachedControl use_new_target_omega ("UseNewTargetOmegaCode", true); + if (use_new_target_omega) + { + resetRot(); + } LLViewerObject::sNumObjects++; } @@ -809,6 +816,12 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) } LLDrawable* old_parent = mDrawable->mParent; mDrawable->mParent = parentp; + + if (parentp && mDrawable->isActive()) + { + parentp->makeActive(); + parentp->setState(LLDrawable::ACTIVE_CHILD); + } gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); if( (old_parent != parentp && old_parent) @@ -1258,11 +1271,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, mText->setString(mHudTextString); } - if (mDrawable.notNull()) - { - setChanged(MOVED | SILHOUETTE); - gPipeline.markMoved(mDrawable, FALSE); // undamped - } + setChanged(MOVED | SILHOUETTE); } else if (mText.notNull()) { @@ -2104,17 +2113,49 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } } - if (new_rot != getRotation() - || new_angv != old_angv) - { - if (new_angv != old_angv) + static const LLCachedControl use_new_target_omega ("UseNewTargetOmegaCode", true); + if (use_new_target_omega) + { // New, experimental code + if ((new_rot != getRotation()) || (new_angv != old_angv)) { + if (new_rot != mPreviousRotation) + { + resetRot(); + } + else if (new_angv != old_angv) + { + if (flagUsePhysics()) + { + resetRot(); + } + else + { + mRotTime = 0.0f; + } + } + + // Remember the last rotation value + mPreviousRotation = new_rot; + + // Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega) + setRotation(new_rot * mAngularVelocityRot); + setChanged(ROTATED | SILHOUETTE); + } + } + else + { // Old code + if (new_rot != mPreviousRotation || new_angv != old_angv) + { + if (new_rot != mPreviousRotation) + { + mPreviousRotation = new_rot; + setRotation(new_rot); + } + + setChanged(ROTATED | SILHOUETTE); + resetRot(); } - - // Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega) - setRotation(new_rot * mAngularVelocityRot); - setChanged(ROTATED | SILHOUETTE); } @@ -2132,9 +2173,15 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, gPipeline.addDebugBlip(getPositionAgent(), color); } - if ((0.0f == vel_mag_sq) && - (0.0f == accel_mag_sq) && - (0.0f == getAngularVelocity().magVecSquared())) + const F32 MAG_CUTOFF = F_APPROXIMATELY_ZERO; + + llassert(vel_mag_sq >= 0.f); + llassert(accel_mag_sq >= 0.f); + llassert(getAngularVelocity().magVecSquared() >= 0.f); + + if ((MAG_CUTOFF >= vel_mag_sq) && + (MAG_CUTOFF >= accel_mag_sq) && + (MAG_CUTOFF >= getAngularVelocity().magVecSquared())) { mStatic = TRUE; // This object doesn't move! } @@ -2208,17 +2255,15 @@ BOOL LLViewerObject::isActive() const return TRUE; } -BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) + + +void LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { //static LLFastTimer::DeclareTimer ftm("Viewer Object"); //LLFastTimer t(ftm); - if (mDead) + if (!mDead) { - // It's dead. Don't update it. - return TRUE; - } - // CRO - don't velocity interp linked objects! // Leviathan - but DO velocity interp joints if (!mStatic && sVelocityInterpolate && !isSelected()) @@ -2227,12 +2272,12 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) F32 dt_raw = (F32)(time - mLastInterpUpdateSecs); F32 dt = mTimeDilation * dt_raw; - applyAngularVelocity(dt); + applyAngularVelocity(dt); - if (isAttachment()) - { - mLastInterpUpdateSecs = time; - return TRUE; + if (isAttachment()) + { + mLastInterpUpdateSecs = time; + return; } else { // Move object based on it's velocity and rotation @@ -2241,8 +2286,7 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } updateDrawable(FALSE); - - return TRUE; +} } @@ -5450,9 +5494,12 @@ BOOL LLViewerObject::setFlagsWithoutUpdate(U32 flags, BOOL state) void LLViewerObject::setPhysicsShapeType(U8 type) { mPhysicsShapeUnknown = false; + if (type != mPhysicsShapeType) + { mPhysicsShapeType = type; mCostStale = true; } +} void LLViewerObject::setPhysicsGravity(F32 gravity) { @@ -5478,7 +5525,6 @@ U8 LLViewerObject::getPhysicsShapeType() const { if (mPhysicsShapeUnknown) { - mPhysicsShapeUnknown = false; gObjectList.updatePhysicsFlags(this); } @@ -5503,8 +5549,12 @@ void LLViewerObject::applyAngularVelocity(F32 dt) // calculate the delta increment based on the object's angular velocity dQ.setQuat(angle, ang_vel); - // accumulate the angular velocity rotations to re-apply in the case of an object update - mAngularVelocityRot *= dQ; + static const LLCachedControl use_new_target_omega ("UseNewTargetOmegaCode", true); + if (use_new_target_omega) + { + // accumulate the angular velocity rotations to re-apply in the case of an object update + mAngularVelocityRot *= dQ; + } // Just apply the delta increment to the current rotation setRotation(getRotation()*dQ); @@ -5516,8 +5566,28 @@ void LLViewerObject::resetRot() { mRotTime = 0.0f; - // Reset the accumulated angular velocity rotation - mAngularVelocityRot.loadIdentity(); + static const LLCachedControl use_new_target_omega ("UseNewTargetOmegaCode", true); + if(use_new_target_omega) + { + // Reset the accumulated angular velocity rotation + mAngularVelocityRot.loadIdentity(); + } +} + +//virtual +void LLViewerObject::setSelected(BOOL sel) +{ + mUserSelected = sel; + + static const LLCachedControl use_new_target_omega ("UseNewTargetOmegaCode", true); + if(use_new_target_omega) + { + resetRot(); + } + else + { + mRotTime = 0.f; + } } U32 LLViewerObject::getPartitionType() const diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 791393533..700370f01 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -150,7 +150,7 @@ public: LLNameValue* getNVPair(const std::string& name) const; // null if no name value pair by that name // Object create and update functions - virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + virtual void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); // Types of media we can associate enum { MEDIA_NONE = 0, MEDIA_SET = 1 }; @@ -214,11 +214,13 @@ public: LLViewerRegion* getRegion() const { return mRegionp; } BOOL isSelected() const { return mUserSelected; } - virtual void setSelected(BOOL sel) { mUserSelected = sel; mRotTime = 0.f;} + void setSelected(BOOL sel); const LLUUID &getID() const { return mID; } U32 getLocalID() const { return mLocalID; } U32 getCRC() const { return mTotalCRC; } + S32 getListIndex() const { return mListIndex; } + void setListIndex(S32 idx) { mListIndex = idx; } virtual BOOL isFlexible() const { return FALSE; } virtual BOOL isSculpted() const { return FALSE; } @@ -603,6 +605,9 @@ public: // Last total CRC received from sim, used for caching U32 mTotalCRC; + // index into LLViewerObjectList::mActiveObjects or -1 if not in list + S32 mListIndex; + LLPointer *mTEImages; // Selection, picking and rendering variables @@ -737,6 +742,7 @@ protected: F32 mTimeDilation; // Time dilation sent with the object. F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega) LLQuaternion mAngularVelocityRot; // accumulated rotation from the angular velocity computations + LLQuaternion mPreviousRotation; U8 mState; // legacy LLViewerObjectMedia* mMedia; // NULL if no media associated diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index a53805fe8..3f1c023df 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -56,6 +56,8 @@ #include "llstring.h" #include "llhudnametag.h" #include "lldrawable.h" +#include "llflexibleobject.h" +#include "llviewertextureanim.h" #include "xform.h" #include "llsky.h" #include "llviewercamera.h" @@ -90,6 +92,8 @@ extern BOOL gAnimateTextures; #include "importtracker.h" extern ImportTracker gImportTracker; +#define MAX_CONCURRENT_PHYSICS_REQUESTS 256 + void dialog_refresh_all(); class AIHTTPTimeoutPolicy; @@ -924,26 +928,35 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) const F64 frame_time = LLFrameTimer::getElapsedSeconds(); - std::vector kill_list; - S32 num_active_objects = 0; LLViewerObject *objectp = NULL; // Make a copy of the list in case something in idleUpdate() messes with it - std::vector idle_list; - + static std::vector idle_list; + if(mActiveObjects.size() > idle_list.capacity()) + idle_list.reserve( mActiveObjects.size() ); + + U32 idle_count = 0; + static LLFastTimer::DeclareTimer idle_copy("Idle Copy"); { LLFastTimer t(idle_copy); - idle_list.reserve( mActiveObjects.size() ); - for (std::set >::iterator active_iter = mActiveObjects.begin(); + for (std::vector >::iterator active_iter = mActiveObjects.begin(); active_iter != mActiveObjects.end(); active_iter++) { objectp = *active_iter; if (objectp) { - idle_list.push_back( objectp ); + if (idle_count >= idle_list.size()) + { + idle_list.push_back( objectp ); + } + else + { + idle_list[idle_count] = objectp; + } + ++idle_count; } else { // There shouldn't be any NULL pointers in the list, but they have caused @@ -952,12 +965,14 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) } } } + + std::vector::iterator idle_end = idle_list.begin()+idle_count; static const LLCachedControl freeze_time("FreezeTime",0); if (freeze_time) { for (std::vector::iterator iter = idle_list.begin(); - iter != idle_list.end(); iter++) + iter != idle_end; iter++) { objectp = *iter; if ( @@ -973,27 +988,23 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) else { for (std::vector::iterator idle_iter = idle_list.begin(); - idle_iter != idle_list.end(); idle_iter++) + idle_iter != idle_end; idle_iter++) { objectp = *idle_iter; - if (!objectp->idleUpdate(agent, world, frame_time)) - { - // If Idle Update returns false, kill object! - kill_list.push_back(objectp); - } - else - { - num_active_objects++; - } - } - for (std::vector::iterator kill_iter = kill_list.begin(); - kill_iter != kill_list.end(); kill_iter++) - { - objectp = *kill_iter; - killObject(objectp); + llassert(objectp->isActive()); + objectp->idleUpdate(agent, world, frame_time); + } + + //update flexible objects + LLVolumeImplFlexible::updateClass(); + + //update animated textures + LLViewerTextureAnim::updateClass(); } + + fetchObjectCosts(); fetchPhysicsFlags(); @@ -1060,7 +1071,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) */ LLViewerStats::getInstance()->mNumObjectsStat.addValue((S32) mObjects.size() - mNumDeadObjects); - LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(num_active_objects); + LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(idle_count); LLViewerStats::getInstance()->mNumSizeCulledStat.addValue(mNumSizeCulled); LLViewerStats::getInstance()->mNumVisCulledStat.addValue(mNumVisCulled); } @@ -1081,8 +1092,6 @@ void LLViewerObjectList::fetchObjectCosts() LLSD id_list; U32 object_index = 0; - U32 count = 0; - for ( std::set::iterator iter = mStaleObjectCost.begin(); iter != mStaleObjectCost.end(); @@ -1099,7 +1108,7 @@ void LLViewerObjectList::fetchObjectCosts() mStaleObjectCost.erase(iter++); - if (count++ >= 450) + if (object_index >= MAX_CONCURRENT_PHYSICS_REQUESTS) { break; } @@ -1144,7 +1153,7 @@ void LLViewerObjectList::fetchPhysicsFlags() for ( std::set::iterator iter = mStalePhysicsFlags.begin(); iter != mStalePhysicsFlags.end(); - ++iter) + ) { // Check to see if a request for this object // has already been made. @@ -1154,12 +1163,14 @@ void LLViewerObjectList::fetchPhysicsFlags() mPendingPhysicsFlags.insert(*iter); id_list[object_index++] = *iter; } - } - // id_list should now contain all - // requests in mStalePhysicsFlags before, so clear - // it now - mStalePhysicsFlags.clear(); + mStalePhysicsFlags.erase(iter++); + + if (object_index >= MAX_CONCURRENT_PHYSICS_REQUESTS) + { + break; + } + } if ( id_list.size() > 0 ) { @@ -1226,7 +1237,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) { //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list in cleanupReferences." << llendl; objectp->setOnActiveList(FALSE); - mActiveObjects.erase(objectp); + removeFromActiveList(objectp); } if (objectp->isOnMap()) @@ -1329,7 +1340,7 @@ void LLViewerObjectList::killAllObjects() killObject(objectp); // Object must be dead, or it's the LLVOAvatarSelf which never dies. - llassert((objectp == gAgentAvatarp) || objectp->isDead()); + llassert((objectp == gAgentAvatarp) || objectp->isDead() || (objectp->asAvatar() && objectp->asAvatar()->isFrozenDead())); } cleanDeadObjects(FALSE); @@ -1416,6 +1427,27 @@ void LLViewerObjectList::cleanDeadObjects(BOOL use_timer) mNumDeadObjects = 0; } +void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) +{ + S32 idx = objectp->getListIndex(); + if (idx != -1) + { //remove by moving last element to this object's position + llassert(mActiveObjects[idx] == objectp); + + objectp->setListIndex(-1); + + S32 last_index = mActiveObjects.size()-1; + + if (idx != last_index) + { + mActiveObjects[idx] = mActiveObjects[last_index]; + mActiveObjects[idx]->setListIndex(idx); + } + + mActiveObjects.pop_back(); + } +} + void LLViewerObjectList::updateActive(LLViewerObject *objectp) { LLMemType mt(LLMemType::MTYPE_OBJECT); @@ -1430,16 +1462,35 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) if (active) { //llinfos << "Adding " << objectp->mID << " " << objectp->getPCodeString() << " to active list." << llendl; - mActiveObjects.insert(objectp); - objectp->setOnActiveList(TRUE); + S32 idx = objectp->getListIndex(); + if (idx <= -1) + { + mActiveObjects.push_back(objectp); + objectp->setListIndex(mActiveObjects.size()-1); + objectp->setOnActiveList(TRUE); + } + else + { + llassert(idx < (S32)mActiveObjects.size()); + llassert(mActiveObjects[idx] == objectp); + + if (idx >= (S32)mActiveObjects.size() || + mActiveObjects[idx] != objectp) + { + llwarns << "Invalid object list index detected!" << llendl; + } + } } else { //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list." << llendl; - mActiveObjects.erase(objectp); + removeFromActiveList(objectp); objectp->setOnActiveList(FALSE); } } + + llassert(objectp->isActive() || objectp->getListIndex() == -1); + } void LLViewerObjectList::updateObjectCost(LLViewerObject* object) diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 9266dcf2d..5a48656b7 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -128,7 +128,9 @@ public: void dirtyAllObjectInventory(); + void removeFromActiveList(LLViewerObject* objectp); void updateActive(LLViewerObject *objectp); + void updateAvatarVisibility(); // Selection related stuff @@ -206,7 +208,7 @@ public: typedef std::vector > vobj_list_t; vobj_list_t mObjects; - std::set > mActiveObjects; + std::vector > mActiveObjects; vobj_list_t mMapObjects; diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 9ed016d71..9c18486cc 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -120,7 +120,7 @@ LLViewerParcelMgr::LLViewerParcelMgr() mRequestResult(0), mWestSouth(), mEastNorth(), - mSelectedDwell(0.f), + mSelectedDwell(DWELL_NAN), mAgentParcelSequenceID(-1), mHoverRequestResult(0), mHoverWestSouth(), @@ -244,7 +244,7 @@ void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out, S32 price = 0; S32 rent = 0; BOOL for_sale = FALSE; - F32 dwell = 0.f; + F32 dwell = DWELL_NAN; if (mSelected) { @@ -590,7 +590,7 @@ void LLViewerParcelMgr::deselectLand() mCurrentParcel->mBanList.clear(); //mCurrentParcel->mRenterList.reset(); - mSelectedDwell = 0.f; + mSelectedDwell = DWELL_NAN; // invalidate parcel selection so that existing users of this selection can clean up mCurrentParcelSelection->setParcel(NULL); @@ -1679,7 +1679,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use parcel_mgr.sendParcelAccessListRequest(AL_ACCESS | AL_BAN); // Request dwell for this land, if it's not public land. - parcel_mgr.mSelectedDwell = 0.f; + parcel_mgr.mSelectedDwell = DWELL_NAN; if (0 != local_id) { parcel_mgr.sendParcelDwellRequest(); diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index 49571f80a..5ae44e2d0 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -46,6 +46,8 @@ class LLParcel; class LLViewerTexture; class LLViewerRegion; +const F32 DWELL_NAN = -1.0f; // A dwell having this value will be displayed as Loading... + // Constants for sendLandOwner //const U32 NO_NEIGHBOR_JOIN = 0x0; //const U32 ALL_NEIGHBOR_JOIN = U32( NORTH_MASK diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 94a2968b4..6a8de2595 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -710,7 +710,9 @@ void LLViewerPartSim::updateSimulation() if (mViewerPartSources[i]->isDead()) { - mViewerPartSources.erase(mViewerPartSources.begin() + i); + mViewerPartSources[i] = mViewerPartSources.back(); + mViewerPartSources.pop_back(); + //mViewerPartSources.erase(mViewerPartSources.begin() + i); count--; i+=deldir; } @@ -727,7 +729,7 @@ void LLViewerPartSim::updateSimulation() LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp; S32 visirate = 1; - if (vobj) + if (vobj && vobj->mDrawable.notNull()) { LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup(); if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY)) @@ -738,7 +740,7 @@ void LLViewerPartSim::updateSimulation() if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%visirate == 0) { - if (vobj) + if (vobj && vobj->mDrawable.notNull()) { gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE); } @@ -747,7 +749,9 @@ void LLViewerPartSim::updateSimulation() if (!mViewerPartGroups[i]->getCount()) { delete mViewerPartGroups[i]; - mViewerPartGroups.erase(mViewerPartGroups.begin() + i); + mViewerPartGroups[i] = mViewerPartGroups.back(); + mViewerPartGroups.pop_back(); + //mViewerPartGroups.erase(mViewerPartGroups.begin() + i); i--; count--; } @@ -831,14 +835,16 @@ void LLViewerPartSim::removeLastCreatedSource() void LLViewerPartSim::cleanupRegion(LLViewerRegion *regionp) { LLMemType mt(LLMemType::MTYPE_PARTICLES); - for (group_list_t::iterator i = mViewerPartGroups.begin(); i != mViewerPartGroups.end(); ) - { - group_list_t::iterator iter = i++; - if ((*iter)->getRegion() == regionp) + group_list_t& vec = mViewerPartGroups; + for (group_list_t::size_type i = 0;igetRegion() == regionp) { - delete *iter; - i = mViewerPartGroups.erase(iter); + delete vec[i]; + vec[i--] = vec.back(); + vec.pop_back(); + //i = mViewerPartGroups.erase(iter); } } } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 7df9352f6..681cfd4fd 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -720,6 +720,31 @@ std::string LLViewerRegion::accessToShortString(U8 sim_access) } } +// static +U8 LLViewerRegion::shortStringToAccess(const std::string &sim_access) +{ + U8 accessValue; + + if (LLStringUtil::compareStrings(sim_access, "PG") == 0) + { + accessValue = SIM_ACCESS_PG; + } + else if (LLStringUtil::compareStrings(sim_access, "M") == 0) + { + accessValue = SIM_ACCESS_MATURE; + } + else if (LLStringUtil::compareStrings(sim_access, "A") == 0) + { + accessValue = SIM_ACCESS_ADULT; + } + else + { + accessValue = SIM_ACCESS_MIN; + } + + return accessValue; +} + // static void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) { @@ -1538,7 +1563,8 @@ void LLViewerRegion::unpackRegionHandshake() // all of our terrain stuff, by if (compp->getParamsReady()) { - getLand().dirtyAllPatches(); + //this line creates frame stalls on region crossing and removing it appears to have no effect + //getLand().dirtyAllPatches(); } else { @@ -1564,7 +1590,6 @@ void LLViewerRegion::unpackRegionHandshake() msg->sendReliable(host); } - void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) { capabilityNames.append("AgentState"); @@ -1575,11 +1600,9 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("CopyInventoryFromNotecard"); capabilityNames.append("CreateInventoryCategory"); capabilityNames.append("DispatchRegionInfo"); + capabilityNames.append("EnvironmentSettings"); capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); - capabilityNames.append("EnvironmentSettings"); - /*capabilityNames.append("ObjectMedia"); - capabilityNames.append("ObjectMediaNavigate");*/ if (gSavedSettings.getBOOL("UseHTTPInventory")) //Caps suffixed with 2 by LL. Don't update until rest of fetch system is updated first. { @@ -1590,12 +1613,12 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) } capabilityNames.append("GetDisplayNames"); - capabilityNames.append("GetTexture"); capabilityNames.append("GetMesh"); capabilityNames.append("GetObjectCost"); capabilityNames.append("GetObjectPhysicsData"); + capabilityNames.append("GetTexture"); + capabilityNames.append("GroupMemberData"); capabilityNames.append("GroupProposalBallot"); - capabilityNames.append("HomeLocation"); //capabilityNames.append("LandResources"); //Script limits (llfloaterscriptlimits.cpp) capabilityNames.append("MapLayer"); @@ -1605,9 +1628,11 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) #endif //MESH_IMPORT capabilityNames.append("NavMeshGenerationStatus"); capabilityNames.append("NewFileAgentInventory"); + /*capabilityNames.append("ObjectMedia"); + capabilityNames.append("ObjectMediaNavigate");*/ capabilityNames.append("ObjectNavMeshProperties"); + capabilityNames.append("ParcelNavigateMedia"); //Singu Note: Removed by Baker, do we need this? capabilityNames.append("ParcelPropertiesUpdate"); - capabilityNames.append("ParcelNavigateMedia"); capabilityNames.append("ParcelVoiceInfoRequest"); capabilityNames.append("ProductInfoRequest"); capabilityNames.append("ProvisionVoiceAccountRequest"); @@ -1621,10 +1646,10 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("SendUserReport"); capabilityNames.append("SendUserReportWithScreenshot"); capabilityNames.append("ServerReleaseNotes"); - capabilityNames.append("SimConsole"); - capabilityNames.append("SimulatorFeatures"); capabilityNames.append("SetDisplayName"); + capabilityNames.append("SimConsole"); //Singu Note: Removed by Baker, sim console won't work without this. capabilityNames.append("SimConsoleAsync"); + capabilityNames.append("SimulatorFeatures"); capabilityNames.append("StartGroupProposal"); capabilityNames.append("TerrainNavMeshProperties"); capabilityNames.append("TextureStats"); @@ -1632,10 +1657,10 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("UpdateAgentInformation"); capabilityNames.append("UpdateAgentLanguage"); capabilityNames.append("UpdateGestureAgentInventory"); - capabilityNames.append("UpdateNotecardAgentInventory"); - capabilityNames.append("UpdateScriptAgent"); capabilityNames.append("UpdateGestureTaskInventory"); + capabilityNames.append("UpdateNotecardAgentInventory"); capabilityNames.append("UpdateNotecardTaskInventory"); + capabilityNames.append("UpdateScriptAgent"); capabilityNames.append("UpdateScriptTask"); capabilityNames.append("UploadBakedTexture"); //capabilityNames.append("ViewerMetrics"); @@ -1927,3 +1952,9 @@ bool LLViewerRegion::meshRezEnabled() const } } +bool LLViewerRegion::dynamicPathfindingEnabled() const +{ + return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") && + mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean()); +} + diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index b7fd43602..3e5f1fd24 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -210,6 +210,7 @@ public: // Returns "M", "PG", "A" etc. static std::string accessToShortString(U8 sim_access); + static U8 shortStringToAccess(const std::string &sim_access); // Return access icon name static std::string getAccessIcon(U8 sim_access); @@ -293,6 +294,9 @@ public: void getSimulatorFeatures(LLSD& info); void setSimulatorFeatures(const LLSD& info); + + bool dynamicPathfindingEnabled() const; + typedef enum { CACHE_MISS_TYPE_FULL = 0, diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 25014b640..313673721 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -32,7 +32,6 @@ #include "llviewerprecompiledheaders.h" -#include //First, because glh_linear #defines equivalent.. which boost uses internally #include "llfeaturemanager.h" #include "llviewershadermgr.h" @@ -172,7 +171,8 @@ LLGLSLShader gPostNightVisionProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not LLGLSLShader gPostGaussianBlurProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList LLGLSLShader gPostPosterizeProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList LLGLSLShader gPostMotionBlurProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList - +LLGLSLShader gPostVignetteProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList + // Deferred rendering shaders LLGLSLShader gDeferredImpostorProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics @@ -307,18 +307,6 @@ void LLViewerShaderMgr::setShaders() return; } - { - const std::string dumpdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"shader_dump")+gDirUtilp->getDirDelimiter(); - try - { - boost::filesystem::remove_all(dumpdir); - } - catch(const boost::filesystem::filesystem_error& e) - { - llinfos << "boost::filesystem::remove_all(\""+dumpdir+"\") failed: '" + e.code().message() + "'" << llendl; - } - } - LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits, (S32) gSavedSettings.getU32("RenderMaxTextureIndex")), 1); static const LLCachedControl no_texture_indexing("ShyotlUseLegacyTextureBatching",false); if(no_texture_indexing) @@ -482,6 +470,12 @@ void LLViewerShaderMgr::setShaders() if (loaded) { loaded = loadTransformShaders(); + if(!loaded) //Failed to load. Just wipe all transformfeedback shaders and continue like nothing happened. + { + mVertexShaderLevel[SHADER_TRANSFORM] = 0; + unloadShaderClass(SHADER_TRANSFORM); + loaded = true; + } } if (loaded) @@ -908,7 +902,6 @@ BOOL LLViewerShaderMgr::loadShadersEffects() shaderUniforms.push_back("contrast"); shaderUniforms.push_back("contrastBase"); shaderUniforms.push_back("saturation"); - shaderUniforms.push_back("lumWeights"); gPostColorFilterProgram.mName = "Color Filter Shader (Post)"; gPostColorFilterProgram.mShaderFiles.clear(); @@ -929,7 +922,6 @@ BOOL LLViewerShaderMgr::loadShadersEffects() shaderUniforms.reserve(3); shaderUniforms.push_back("brightMult"); shaderUniforms.push_back("noiseStrength"); - shaderUniforms.push_back("lumWeights"); gPostNightVisionProgram.mName = "Night Vision Shader (Post)"; gPostNightVisionProgram.mShaderFiles.clear(); @@ -998,6 +990,26 @@ BOOL LLViewerShaderMgr::loadShadersEffects() gPostMotionBlurProgram.uniform1i("tex1", 1); } } + + { + vector shaderUniforms; + shaderUniforms.reserve(3); + shaderUniforms.push_back("vignette_darkness"); + shaderUniforms.push_back("vignette_radius"); + shaderUniforms.push_back("screen_res"); + + gPostVignetteProgram.mName = "Vignette Shader (Post)"; + gPostVignetteProgram.mShaderFiles.clear(); + gPostVignetteProgram.mShaderFiles.push_back(make_pair("effects/VignetteF.glsl", GL_FRAGMENT_SHADER_ARB)); + gPostVignetteProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB)); + gPostVignetteProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT]; + if(gPostVignetteProgram.createShader(NULL, &shaderUniforms)) + { + gPostVignetteProgram.bind(); + gPostVignetteProgram.uniform1i("tex0", 0); + } + } + #endif return success; @@ -1293,7 +1305,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { // load water shader gDeferredWaterProgram.mName = "Deferred Water Shader"; + gDeferredWaterProgram.mFeatures.atmosphericHelpers = true; gDeferredWaterProgram.mFeatures.calculatesAtmospherics = true; + gDeferredWaterProgram.mFeatures.hasAtmospherics = true; gDeferredWaterProgram.mFeatures.hasGamma = true; gDeferredWaterProgram.mFeatures.hasTransport = true; gDeferredWaterProgram.mShaderFiles.clear(); @@ -1493,12 +1507,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredStarProgram.mName = "Deferred Star Program"; + vector shaderUniforms(mWLUniforms); + shaderUniforms.push_back("custom_alpha"); gDeferredStarProgram.mShaderFiles.clear(); gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredStarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY; - success = gDeferredStarProgram.createShader(NULL, &mWLUniforms); + success = gDeferredStarProgram.createShader(NULL, &shaderUniforms); } if (success) @@ -2396,7 +2412,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() if (success) { - gAvatarEyeballProgram.mName = "Avatar Eyeball Program"; + /*gAvatarEyeballProgram.mName = "Avatar Eyeball Program"; gAvatarEyeballProgram.mFeatures.calculatesLighting = true; gAvatarEyeballProgram.mFeatures.isSpecular = true; gAvatarEyeballProgram.mFeatures.calculatesAtmospherics = true; @@ -2409,7 +2425,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB)); gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB)); gAvatarEyeballProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR]; - success = gAvatarEyeballProgram.createShader(NULL, NULL); + success = gAvatarEyeballProgram.createShader(NULL, NULL);*/ } if( !success ) diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 6013a47f2..8a2667555 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -873,7 +873,7 @@ void send_stats() llinfos << "Misc Stats: int_1: " << misc["int_1"] << " int_2: " << misc["int_2"] << llendl; llinfos << "Misc Stats: string_1: " << misc["string_1"] << " string_2: " << misc["string_2"] << llendl; - body["DisplayNamesEnabled"] = gSavedSettings.getS32("PhoenixNameSystem") > 0; + body["DisplayNamesEnabled"] = gSavedSettings.getS32("PhoenixNameSystem") == 1 || gSavedSettings.getS32("PhoenixNameSystem") == 2; body["DisplayNamesShowUsername"] = gSavedSettings.getS32("PhoenixNameSystem") == 1; body["MinimalSkin"] = false; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index cf54a6ce8..11fb67c92 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1330,6 +1330,31 @@ void LLViewerFetchedTexture::cleanup() mCachedRawDiscardLevel = -1 ; mCachedRawImageReady = FALSE ; mSavedRawImage = NULL ; + mSavedRawDiscardLevel = -1; +} + +void LLViewerFetchedTexture::forceRefetch() +{ + bool needs_aux = mNeedsAux; + bool save_raw = mForceToSaveRawImage; + S32 raw_discard = mDesiredSavedRawDiscardLevel; + F32 raw_time = mKeptSavedRawImageTime; + callback_list_t callback_list = mLoadedCallbackList; + mLoadedCallbackList.clear(); + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + if(mGLTexturep) + mGLTexturep->forceToInvalidateGLTexture(); + init(false); + mRawImage = NULL; + mAuxRawImage = NULL; + if(save_raw) + forceToSaveRawImage(raw_discard,raw_time); + for(callback_list_t::iterator iter = callback_list.begin(); + iter != callback_list.end(); ++iter) + { + LLLoadedCallbackEntry *entryp = *iter; + setLoadedCallback(entryp->mCallback,entryp->mDesiredDiscard,entryp->mNeedsImageRaw,needs_aux,entryp->mUserData,entryp->mSourceCallbackList,entryp->mPaused); + } } void LLViewerFetchedTexture::setForSculpt() @@ -1337,9 +1362,10 @@ void LLViewerFetchedTexture::setForSculpt() static const S32 MAX_INTERVAL = 8 ; //frames mForSculpt = TRUE ; - if(isForSculptOnly() && !getBoundRecently()) + if(isForSculptOnly() && hasGLTexture() && !getBoundRecently()) { destroyGLTexture() ; //sculpt image does not need gl texture. + mTextureState = ACTIVE; } checkCachedRawSculptImage() ; setMaxVirtualSizeResetInterval(MAX_INTERVAL) ; @@ -1446,7 +1472,11 @@ void LLViewerFetchedTexture::addToCreateTexture() for(U32 i = 0 ; i < mNumFaces ; i++) { - mFaceList[i]->dirtyTexture() ; + LLFace* facep = mFaceList[i]; + if(facep) + { + facep->dirtyTexture() ; + } } //discard the cached raw image and the saved raw image diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 85a6b4915..b0a6ad6a8 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -504,6 +504,8 @@ public: void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;} void forceToDeleteRequest(); + void forceRefetch(); + protected: /*virtual*/ void switchToCachedImage(); S32 getCurrentDiscardLevelForFetching() ; diff --git a/indra/newview/llviewertextureanim.cpp b/indra/newview/llviewertextureanim.cpp index 9f1ac7c49..2b364851a 100644 --- a/indra/newview/llviewertextureanim.cpp +++ b/indra/newview/llviewertextureanim.cpp @@ -27,21 +27,37 @@ #include "llviewerprecompiledheaders.h" #include "llviewertextureanim.h" +#include "llvovolume.h" #include "llmath.h" #include "llerror.h" -LLViewerTextureAnim::LLViewerTextureAnim() : LLTextureAnim() +std::vector LLViewerTextureAnim::sInstanceList; + +LLViewerTextureAnim::LLViewerTextureAnim(LLVOVolume* vobj) : LLTextureAnim() { + mVObj = vobj; mLastFrame = -1.f; // Force an update initially mLastTime = 0.f; mOffS = mOffT = 0; mScaleS = mScaleT = 1; mRot = 0; + + mInstanceIndex = sInstanceList.size(); + sInstanceList.push_back(this); } LLViewerTextureAnim::~LLViewerTextureAnim() { + S32 end_idx = sInstanceList.size()-1; + + if (end_idx != mInstanceIndex) + { + sInstanceList[mInstanceIndex] = sInstanceList[end_idx]; + sInstanceList[mInstanceIndex]->mInstanceIndex = mInstanceIndex; + } + + sInstanceList.pop_back(); } void LLViewerTextureAnim::reset() @@ -50,6 +66,14 @@ void LLViewerTextureAnim::reset() mTimer.reset(); } +//static +void LLViewerTextureAnim::updateClass() +{ + for (std::vector::iterator iter = sInstanceList.begin(); iter != sInstanceList.end(); ++iter) + { + (*iter)->mVObj->animateTextures(); + } +} S32 LLViewerTextureAnim::animateTextures(F32 &off_s, F32 &off_t, F32 &scale_s, F32 &scale_t, diff --git a/indra/newview/llviewertextureanim.h b/indra/newview/llviewertextureanim.h index dd7bd0cb9..abbfabceb 100644 --- a/indra/newview/llviewertextureanim.h +++ b/indra/newview/llviewertextureanim.h @@ -30,10 +30,18 @@ #include "lltextureanim.h" #include "llframetimer.h" +class LLVOVolume; + class LLViewerTextureAnim : public LLTextureAnim { +private: + static std::vector sInstanceList; + S32 mInstanceIndex; + public: - LLViewerTextureAnim(); + static void updateClass(); + + LLViewerTextureAnim(LLVOVolume* vobj); virtual ~LLViewerTextureAnim(); /*virtual*/ void reset(); @@ -51,6 +59,7 @@ public: F32 mRot; protected: + LLVOVolume* mVObj; LLFrameTimer mTimer; F64 mLastTime; F32 mLastFrame; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 937f79701..a7d79e200 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -65,6 +65,8 @@ #include "pipeline.h" #include "llappviewer.h" #include "llagent.h" +#include "llviewerdisplay.h" +#include "llflexibleobject.h" //////////////////////////////////////////////////////////////////////////// @@ -623,11 +625,30 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_MEDIA("Media"); void LLViewerTextureList::updateImages(F32 max_time) { - if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) + static BOOL cleared = FALSE; + static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); + + //Can't check gTeleportDisplay due to a process_teleport_local(), which sets it to true for local teleports... so: + // Do this case if IS teleporting but NOT local teleporting, AND either the TP screen is set to appear OR we just entered the sim (TELEPORT_START_ARRIVAL) + LLAgent::ETeleportState state = gAgent.getTeleportState(); + if(state != LLAgent::TELEPORT_NONE && state != LLAgent::TELEPORT_LOCAL && state != LLAgent::TELEPORT_PENDING && + (!hide_tp_screen || state == LLAgent::TELEPORT_START_ARRIVAL || state == LLAgent::TELEPORT_ARRIVING)) { - clearFetchingRequests(); + if(!cleared) + { + llinfos << "Flushing upon teleport." << llendl; + clearFetchingRequests(); + //gPipeline.clearRebuildGroups() really doesn't belong here... but since it is here, do a few other needed things too. + gPipeline.clearRebuildGroups(); + gPipeline.resetVertexBuffers(); + LLVolumeImplFlexible::resetTimers(); + cleared = TRUE; + } return; } + cleared = FALSE; + + LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec()); S32 global_raw_memory; { @@ -705,14 +726,13 @@ void LLViewerTextureList::clearFetchingRequests() return; } + LLAppViewer::getTextureFetch()->deleteAllRequests(); + for (image_priority_list_t::iterator iter = mImageList.begin(); iter != mImageList.end(); ++iter) { - LLViewerFetchedTexture* image = *iter; - if(image->hasFetcher()) - { - image->forceToDeleteRequest() ; - } + LLViewerFetchedTexture* imagep = *iter; + imagep->forceToDeleteRequest() ; } } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1c4bdfcff..88b6286c7 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -128,10 +128,10 @@ #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" +#include "llmenuoptionpathfindingrebakenavmesh.h" #include "llmodaldialog.h" #include "llmorphview.h" #include "llmoveview.h" -#include "llpanelpathfindingrebakenavmesh.h" #include "llnotify.h" #include "lloverlaybar.h" #include "llpreviewtexture.h" @@ -1467,7 +1467,7 @@ LLViewerWindow::LLViewerWindow( mIgnoreActivate( FALSE ), mHoverPick(), mResDirty(false), - mStatesDirty(false), + //mStatesDirty(false), //Singu Note: No longer needed. State update is now in restoreGL. mIsFullscreenChecked(false), mCurrResolutionIndex(0) { @@ -1959,10 +1959,11 @@ void LLViewerWindow::initWorldUI() // put behind everything else in the UI mRootView->addChildInBack(gHUDView); } - + LLPanel* panel_ssf_container = getRootView()->getChild("state_management_buttons_container"); - LLPanelPathfindingRebakeNavmesh *panel_rebake_navmesh = LLPanelPathfindingRebakeNavmesh::getInstance(); - panel_ssf_container->addChild(panel_rebake_navmesh); + panel_ssf_container->setVisible(TRUE); + + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->initialize(); } // initWorldUI that wasn't before logging in. Some of this may require the access the 'LindenUserDir'. @@ -2041,6 +2042,9 @@ void LLViewerWindow::shutdownViews() // Delete all child views. delete mRootView; mRootView = NULL; + llinfos << "RootView deleted." << llendl ; + + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->quit(); // Automatically deleted as children of mRootView. Fix the globals. gFloaterTools = NULL; @@ -3986,10 +3990,11 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d } // Saves an image to the harddrive as "SnapshotX" where X >= 1. -void LLViewerWindow::saveImageNumbered(LLPointer image) +void LLViewerWindow::saveImageNumbered(LLPointer image, int index) { if (!image) { + LLFloaterSnapshot::saveLocalDone(false, index); return; } @@ -4018,15 +4023,15 @@ void LLViewerWindow::saveImageNumbered(LLPointer image) // pick a directory in which to save AIFilePicker* filepicker = AIFilePicker::create(); // Deleted in LLViewerWindow::saveImageNumbered_continued1 filepicker->open(proposed_name, pick_type, "", "snapshot"); - filepicker->run(boost::bind(&LLViewerWindow::saveImageNumbered_continued1, this, image, extension, filepicker)); + filepicker->run(boost::bind(&LLViewerWindow::saveImageNumbered_continued1, this, image, extension, filepicker, index)); return; } // LLViewerWindow::sSnapshotBaseName and LLViewerWindow::sSnapshotDir already known. Go straight to saveImageNumbered_continued2. - saveImageNumbered_continued2(image, extension); + saveImageNumbered_continued2(image, extension, index); } -void LLViewerWindow::saveImageNumbered_continued1(LLPointer image, std::string const& extension, AIFilePicker* filepicker) +void LLViewerWindow::saveImageNumbered_continued1(LLPointer image, std::string const& extension, AIFilePicker* filepicker, int index) { if (filepicker->hasFilename()) { @@ -4036,11 +4041,15 @@ void LLViewerWindow::saveImageNumbered_continued1(LLPointer im LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true); LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath); - saveImageNumbered_continued2(image, extension); + saveImageNumbered_continued2(image, extension, index); + } + else + { + LLFloaterSnapshot::saveLocalDone(false, index); } } -void LLViewerWindow::saveImageNumbered_continued2(LLPointer image, std::string const& extension) +void LLViewerWindow::saveImageNumbered_continued2(LLPointer image, std::string const& extension, int index) { // Look for an unused file name std::string filepath; @@ -4064,6 +4073,11 @@ void LLViewerWindow::saveImageNumbered_continued2(LLPointer im if (image->save(filepath)) { playSnapshotAnimAndSound(); + LLFloaterSnapshot::saveLocalDone(true, index); + } + else + { + LLFloaterSnapshot::saveLocalDone(false, index); } } @@ -4093,10 +4107,14 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height) BOOL disable_sync = gSavedSettings.getBOOL("DisableVerticalSync"); if (gViewerWindow->mWindow->getFullscreen()) { + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); gViewerWindow->changeDisplaySettings(FALSE, new_size, disable_sync, TRUE); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); } else { @@ -4110,7 +4128,7 @@ BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, llinfos << "Saving snapshot to: " << filepath << llendl; LLPointer raw = new LLImageRaw; - BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild); + BOOL success = rawSnapshot(raw, image_width, image_height, (F32)image_width / image_height, show_ui, do_rebuild); if (success) { @@ -4146,7 +4164,7 @@ void LLViewerWindow::playSnapshotAnimAndSound() BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) { - return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type); + return rawSnapshot(raw, preview_width, preview_height, (F32)gViewerWindow->getWindowWidthRaw() / gViewerWindow->getWindowHeightRaw(), show_ui, do_rebuild, type); // *TODO below code was broken in deferred pipeline /* @@ -4285,25 +4303,29 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p return TRUE;*/ } -// Saves the image from the screen to the specified filename and path. -BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, - BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size, F32 supersample) +// Saves the image from the screen to the image pointed to by raw. +// This function does NOT yet scale the snapshot down to the requested size +// if that is smaller than the current window (scale_factor < 1) or if +// the aspect of the snapshot is unequal to the aspect of requested image. +bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, + S32 image_width, S32 image_height, F32 snapshot_aspect, BOOL show_ui, + BOOL do_rebuild, ESnapshotType type, S32 max_size, F32 supersample) { if (!raw) { - return FALSE; + return false; } //check if there is enough memory for the snapshot image if(LLPipeline::sMemAllocationThrottled) { - return FALSE ; //snapshot taking is disabled due to memory restriction. + return false; //snapshot taking is disabled due to memory restriction. } if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K { if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3)) { llwarns << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << llendl ; - return FALSE ; //there is no enough memory for taking this snapshot. + return false; //there is no enough memory for taking this snapshot. } } @@ -4327,27 +4349,13 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei LLPipeline::sShowHUDAttachments = FALSE; } - // Copy screen to a buffer - // crop sides or top and bottom, if taking a snapshot of different aspect ratio - // from window - LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); - S32 snapshot_width = window_rect.getWidth(); - S32 snapshot_height = window_rect.getHeight(); + LLRect const window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); + S32 const window_width = window_rect.getWidth(); + S32 const window_height = window_rect.getHeight(); + // SNAPSHOT - S32 window_width = snapshot_width; - S32 window_height = snapshot_height; - - - F32 scale_factor = 1.0f ; - - bool is_tiling = false; - - //fbo method no longer supported. Good riddance - /*LLRenderTarget target; - bool use_fbo = false; - static const LLCachedControl force_tile("SHHighResSnapshotForceTile",false);*/ #if 1//SHY_MOD // screenshot improvement F32 internal_scale = llmin(llmax(supersample,1.f),3.f); @@ -4371,86 +4379,79 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei } } - if(!keep_window_aspect) //image cropping - { - F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; - snapshot_width = (S32)(ratio * image_width) ; - snapshot_height = (S32)(ratio * image_height) ; - scale_factor = llmax(1.0f, 1.0f / ratio) ; - } - else //the scene(window) proportion needs to be maintained. + S32 buffer_x_offset = 0; + S32 buffer_y_offset = 0; + F32 scale_factor; + S32 image_buffer_x; + S32 image_buffer_y; + + F32 const window_aspect = (F32)window_width / window_height; + // snapshot fits precisely inside window, it is the portion of the window with the correct aspect. + F32 snapshot_width = (snapshot_aspect > window_aspect) ? (F32)window_width : window_height * snapshot_aspect; + F32 snapshot_height = (snapshot_aspect < window_aspect) ? (F32)window_height : window_width / snapshot_aspect; + // ratio is the ratio snapshot/image', where image' is a rectangle with aspect snapshot_aspect that precisely contains image. + // Thus image_width' / image_height' == aspect ==> snapshot_width / image_width' == snapshot_height / image_height'. + // Since image' precisely contains image, one of them is equal (ie, image_height' = image_height) and the other is larger + // (or equal) (ie, image_width' >= image_width), and therefore one of snapshot_width / image_width and + // snapshot_height / image_height is correct, and the other is larger. Therefore, the smallest value of the + // following equals the ratio we're looking for. + F32 ratio = llmin(snapshot_width / image_width, snapshot_height / image_height); + // buffer equals the largest of image' and snapshot. This is because in the first case we need the higher + // resolution because of the size of the target image, and in the second case there is no reason to go + // smaller because it takes the same amount of time (and a slightly better quality should result after + // the final scaling). Thus, if ratio < 1 then buffer equals image', otherwise it equals snapshot. + // scale_factor is the ratio buffer/snapshot, and is initiallly equal to the ratio between buffer + // and snapshot (which have the same aspect). + for(scale_factor = llmax(1.0f, 1.0f / ratio);; // Initial attempt. + // However, if the buffer turns out to be too large, then clamp it to max_size. + scale_factor = llmin(max_size / snapshot_width, max_size / snapshot_height)) // Clamp { - if(image_width > window_width || image_height > window_height) //need to enlarge the scene + image_buffer_x = llround(snapshot_width * scale_factor); + image_buffer_y = llround(snapshot_height * scale_factor); + if (llmax(image_buffer_x, image_buffer_y) > max_size && // Boundary check to avoid memory overflow. + internal_scale <= 1.f) // SHY_MOD: If supersampling... Don't care about max_size. { - //Unsupported - /*if (!force_tile && gGLManager.mHasFramebufferObject && !show_ui) - { - GLint max_size = 0; - glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size); - - if (image_width <= max_size && image_height <= max_size) //re-project the scene - { - use_fbo = TRUE; - - snapshot_width = image_width; - snapshot_height = image_height; - target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, TRUE); - window_width = snapshot_width; - window_height = snapshot_height; - scale_factor = 1.f; - mWindowRectRaw.set(0, snapshot_height, snapshot_width, 0); - target.bindTarget(); - } - } - - if(!use_fbo) //no re-projection, so tiling the scene*/ - { - F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; - snapshot_width = (S32)(ratio * image_width) ; - snapshot_height = (S32)(ratio * image_height) ; - scale_factor = llmax(1.0f, 1.0f / ratio) ; - is_tiling = true; - } + // Too big, clamp. + continue; } - //else: keep the current scene scale, re-scale it if necessary after reading out. + // Done. + break; } - - S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f); - S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f); + // Center the buffer. + buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f); + buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f); + Dout(dc::notice, "rawSnapshot(" << image_width << ", " << image_height << ", " << snapshot_aspect << "): image_buffer_x = " << image_buffer_x << "; image_buffer_y = " << image_buffer_y); - S32 image_buffer_x = llfloor(snapshot_width*scale_factor) ; - S32 image_buffer_y = llfloor(snapshot_height*scale_factor) ; -#if 1//SHY_MOD // screenshot improvement - if(internal_scale <= 1.f) //If supersampling... Don't care about max_size. -#endif //shy_mod - if(image_buffer_x > max_size || image_buffer_y > max_size) //boundary check to avoid memory overflow + bool error = !(image_buffer_x > 0 && image_buffer_y > 0); + if (!error) { - scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ; - image_buffer_x = llfloor(snapshot_width*scale_factor) ; - image_buffer_y = llfloor(snapshot_height *scale_factor) ; + raw->resize(image_buffer_x, image_buffer_y, 3); + error = raw->isBufferInvalid(); } - if (image_buffer_x > 0 && image_buffer_y > 0) + if (error) { - raw->resize(image_buffer_x, image_buffer_y, 3); - } - else - { - return FALSE ; - } - if(raw->isBufferInvalid()) - { - return FALSE ; + if (prev_draw_ui != gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = TRUE; + } + setCursor(UI_CURSOR_ARROW); + return false; } - BOOL high_res = scale_factor > 1.f; - if (high_res) + BOOL is_tiling = scale_factor > 1.f; + if (is_tiling) { + Dout(dc::warning, "USING TILING FOR SNAPSHOT!"); send_agent_pause(); if (show_ui || !hide_hud) { - //rescale fonts - initFonts(scale_factor); - LLHUDObject::reshapeAll(); + //rescale fonts + initFonts(scale_factor); + LLHUDObject::reshapeAll(); } } @@ -4463,7 +4464,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y) { - S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);; + S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height); // handle fractional columns U32 read_height = llmax(0, (window_height - subimage_y_offset) - llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight()))); @@ -4505,7 +4506,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei // Ping the watchdog thread every 100 lines to keep us alive (arbitrary number, feel free to change) if (out_y % 100 == 0) { - LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); + LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawRawSnapshot"); } if (type == SNAPSHOT_TYPE_COLOR) @@ -4548,12 +4549,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei output_buffer_offset_y += subimage_y_offset; } - /*if (use_fbo) - { - mWindowRect = window_rect; - target.flush(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - }*/ gDisplaySwapBuffers = FALSE; gDepthDirty = TRUE; @@ -4568,36 +4563,12 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei LLPipeline::sShowHUDAttachments = TRUE; } - if (high_res && (show_ui || !hide_hud)) + if (is_tiling && (show_ui || !hide_hud)) { initFonts(1.f); LLHUDObject::reshapeAll(); } - // Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding) - // Note: this formula depends on the number of components being 3. Not obvious, but it's correct. - image_width += (image_width * 3) % 4; - - BOOL ret = TRUE ; - // Resize image - if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4) - { - ret = raw->scale( image_width, image_height ); - } - else if(image_width != image_buffer_x || image_height != image_buffer_y) - { - ret = raw->scale( image_width, image_height, FALSE ); - } - -#if 1//SHY_MOD // screenshot improvement - if(raw->isBufferInvalid()) //Just checking! - return FALSE; - if(internal_scale != 1.f) //Scale down our render to the desired dimensions. - raw->scale( image_width/internal_scale, image_height/internal_scale ); - if(raw->isBufferInvalid()) //Just checking! - return FALSE; -#endif //shy_mod - setCursor(UI_CURSOR_ARROW); if (do_rebuild) @@ -4610,11 +4581,50 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei gPipeline.resetDrawOrders(); } - if (high_res) + if (is_tiling) { send_agent_resume(); } + return true; +} + +// Same as the above, but does the resizing. +bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, + S32 image_width, S32 image_height, F32 snapshot_aspect, BOOL show_ui, + BOOL do_rebuild, ESnapshotType type, S32 max_size, F32 supersample) +{ + bool ret = rawRawSnapshot(raw, image_width, image_height, snapshot_aspect, show_ui, do_rebuild, type, max_size, supersample); + +#if 1 + + if (ret && !raw->scale(image_width, image_height)) + { + ret = false; // Failure. + } + +#else // This was the old behavior.. but I don't think this is needed here. + + if (ret) + { + // Pad image width such that the line length is a multiple of 4 bytes (for BMP encoding). + int n = 4; + for (int c = raw->getComponents(); c % 2 == 0 && n > 1; c /= 2) { n /= 2; } // n /= gcd(n, components) + image_width += (image_width * (n - 1)) % n; // Now n divides image_width, and thus four divides image_width * components, the line length. + + // Resize image + if (llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4) + { + ret = raw->scale( image_width, image_height ); + } + else if (image_width != image_buffer_x || image_height != image_buffer_y) + { + ret = raw->scale( image_width, image_height, FALSE ); + } + } + +#endif + return ret; } @@ -4879,6 +4889,7 @@ void LLViewerWindow::restoreGL(const std::string& progress_message) gGLManager.mIsDisabled = FALSE; initGLDefaults(); + gGL.refreshState(); //Singu Note: Call immediately. Cached states may have prevented initGLDefaults from actually applying changes. LLGLState::restoreGL(); gTextureList.restoreGL(); @@ -4974,12 +4985,15 @@ void LLViewerWindow::requestResolutionUpdate(bool fullscreen_checked) BOOL LLViewerWindow::checkSettings() { - if (mStatesDirty) + //Singu Note: Don't do the following. + //setShaders is already called in restoreGL(), and gGL.refreshState() is too as to maintain blend states. + //This maintaining of blend states is needed for LLGLState::checkStates() to not error out. + /*if (mStatesDirty) { gGL.refreshState(); LLViewerShaderMgr::instance()->setShaders(); mStatesDirty = false; - } + }*/ // We want to update the resolution AFTER the states getting refreshed not before. if (mResDirty) @@ -5026,10 +5040,8 @@ BOOL LLViewerWindow::checkSettings() desired_screen_size, gSavedSettings.getBOOL("DisableVerticalSync"), mShowFullscreenProgress); - LLGLState::checkStates(); LLGLState::checkTextureChannels(); - mStatesDirty = true; return TRUE; } } @@ -5038,12 +5050,15 @@ BOOL LLViewerWindow::checkSettings() if(is_fullscreen) { // Changing to windowed mode. + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); changeDisplaySettings(FALSE, LLCoordScreen(gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight")), TRUE, mShowFullscreenProgress); - mStatesDirty = true; + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); return TRUE; } } @@ -5111,24 +5126,33 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, mIgnoreActivate = TRUE; LLCoordScreen old_size; LLCoordScreen old_pos; + LLCoordScreen new_pos; mWindow->getSize(&old_size); BOOL got_position = mWindow->getPosition(&old_pos); - if (!old_fullscreen && fullscreen && got_position) + //Singu Note: ALWAYS Save old values if we can. + if(!old_fullscreen && !mWindow->getMaximized() && got_position) { - // switching from windowed to fullscreen, so save window position + //Always save the current position if we can gSavedSettings.setS32("WindowX", old_pos.mX); gSavedSettings.setS32("WindowY", old_pos.mY); } + + //Singu Note: Try to feed switchcontext a posp pointer right off the bat. Looks less clunky on systems that implemented it. + if (!fullscreen && !mWindow->getMaximized()) + { + new_pos.mX = gSavedSettings.getS32("WindowX"); + new_pos.mY = gSavedSettings.getS32("WindowY"); + } mWindow->setFSAASamples(fsaa); - result_first_try = mWindow->switchContext(fullscreen, size, disable_vsync); + result_first_try = mWindow->switchContext(fullscreen, size, disable_vsync, &new_pos); if (!result_first_try) { // try to switch back mWindow->setFSAASamples(old_fsaa); - result_second_try = mWindow->switchContext(old_fullscreen, old_size, disable_vsync); + result_second_try = mWindow->switchContext(old_fullscreen, old_size, disable_vsync, &new_pos); if (!result_second_try) { @@ -5181,10 +5205,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, } else { - S32 windowX = gSavedSettings.getS32("WindowX"); - S32 windowY = gSavedSettings.getS32("WindowY"); - - mWindow->setPosition(LLCoordScreen ( windowX, windowY ) ); + mWindow->setPosition(new_pos); } } @@ -5193,6 +5214,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, mWantFullscreen = mWindow->getFullscreen(); mShowFullscreenProgress = FALSE; + //mStatesDirty = true; //Singu Note: No longer needed. State update is now in restoreGL. return success; } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 30848b386..42c8b4cf2 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -308,17 +308,21 @@ public: enum ESnapshotType { SNAPSHOT_TYPE_COLOR, - SNAPSHOT_TYPE_DEPTH, + SNAPSHOT_TYPE_DEPTH }; 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_SNAPSHOT_IMAGE_SIZE, F32 supersample = 1.f ); + bool rawRawSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, F32 aspect, + BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, + S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE, F32 supersample = 1.f); + bool rawSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, F32 aspect, + BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, + S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE, F32 supersample = 1.f); 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(); } - void saveImageNumbered(LLPointer image); - void saveImageNumbered_continued1(LLPointer image, std::string const& extension, AIFilePicker* filepicker); - void saveImageNumbered_continued2(LLPointer image, std::string const& extension); + void saveImageNumbered(LLPointer image, int index); + void saveImageNumbered_continued1(LLPointer image, std::string const& extension, AIFilePicker* filepicker, int index); + void saveImageNumbered_continued2(LLPointer image, std::string const& extension, int index); // Reset the directory where snapshots are saved. // Client will open directory picker on next snapshot save. @@ -449,7 +453,7 @@ protected: class LLDebugText* mDebugText; // Internal class for debug text bool mResDirty; - bool mStatesDirty; + //bool mStatesDirty; //Singu Note: No longer needed. State update is now in restoreGL. bool mIsFullscreenChecked; // Did the user check the fullscreen checkbox in the display settings U32 mCurrResolutionIndex; diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp index b586ab673..88afc9cc3 100644 --- a/indra/newview/llvlmanager.cpp +++ b/indra/newview/llvlmanager.cpp @@ -44,6 +44,11 @@ LLVLManager gVLManager; +// Extended land layer for Aurora Sim +const char AURORA_LAND_LAYER_CODE = 'M'; +const char AURORA_WIND_LAYER_CODE = '9'; +const char AURORA_CLOUD_LAYER_CODE = ':'; + LLVLManager::~LLVLManager() { S32 i; @@ -56,15 +61,15 @@ LLVLManager::~LLVLManager() void LLVLManager::addLayerData(LLVLData *vl_datap, const S32 mesg_size) { - if (LAND_LAYER_CODE == vl_datap->mType) + if (LAND_LAYER_CODE == vl_datap->mType || AURORA_LAND_LAYER_CODE == vl_datap->mType) { mLandBits += mesg_size * 8; } - else if (WIND_LAYER_CODE == vl_datap->mType) + else if (WIND_LAYER_CODE == vl_datap->mType || AURORA_WIND_LAYER_CODE == vl_datap->mType) { mWindBits += mesg_size * 8; } - else if (CLOUD_LAYER_CODE == vl_datap->mType) + else if (CLOUD_LAYER_CODE == vl_datap->mType || AURORA_CLOUD_LAYER_CODE == vl_datap->mType) { mCloudBits += mesg_size * 8; } @@ -93,12 +98,16 @@ void LLVLManager::unpackData(const S32 num_packets) { datap->mRegionp->getLand().decompressDCTPatch(bit_pack, &goph, FALSE); } - else if (WIND_LAYER_CODE == datap->mType) + else if (AURORA_LAND_LAYER_CODE == datap->mType) + { + datap->mRegionp->getLand().decompressDCTPatch(bit_pack, &goph, TRUE); + } + else if (WIND_LAYER_CODE == datap->mType || AURORA_WIND_LAYER_CODE == datap->mType) { datap->mRegionp->mWind.decompress(bit_pack, &goph); } - else if (CLOUD_LAYER_CODE == datap->mType) + else if (CLOUD_LAYER_CODE == datap->mType || AURORA_CLOUD_LAYER_CODE == datap->mType) { #if ENABLE_CLASSIC_CLOUDS datap->mRegionp->mCloudLayer.decompress(bit_pack, &goph); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 19bd366b4..82b6679f6 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1005,6 +1005,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mAttachmentGeometryBytes(0), mAttachmentSurfaceArea(0.f), mTurning(FALSE), + mFreezeTimeDead(false), mPelvisToFoot(0.f), mLastSkeletonSerialNum( 0 ), mHeadOffset(), @@ -1045,7 +1046,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mSupportsAlphaLayers(FALSE), mLoadedCallbacksPaused(FALSE), mHasPelvisOffset( FALSE ), - mRenderUnloadedAvatar(LLCachedControl(gSavedSettings, "RenderUnloadedAvatar")), mLastRezzedStatus(-1), mFirstSetActualBoobGravRan( false ), mSupportsPhysics( false ), @@ -1054,6 +1054,9 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mCCSChatTextOverride(false) // { + static LLCachedControl const freeze_time("FreezeTime", false); + mFreezeTimeLangolier = freeze_time; + LLMemType mt(LLMemType::MTYPE_AVATAR); //VTResume(); // VTune @@ -1229,6 +1232,13 @@ LLVOAvatar::~LLVOAvatar() void LLVOAvatar::markDead() { + static const LLCachedControl freeze_time("FreezeTime", false); + if (freeze_time && !mFreezeTimeLangolier) + { + // Delay the call to this function until FreezeTime is reset, otherwise avatars disappear from the frozen scene. + mFreezeTimeDead = true; + return; + } if (mNameText) { mNameText->markDead(); @@ -1861,8 +1871,6 @@ void LLVOAvatar::onShift(const LLVector4a& shift_vector) const LLVector3& shift = reinterpret_cast(shift_vector); mLastAnimExtents[0] += shift; mLastAnimExtents[1] += shift; - mNeedsImpostorUpdate = TRUE; - mNeedsAnimUpdate = TRUE; } void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) @@ -2855,7 +2863,7 @@ void LLVOAvatar::dumpAnimationState() //------------------------------------------------------------------------ // idleUpdate() //------------------------------------------------------------------------ -BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { LLMemType mt(LLMemType::MTYPE_AVATAR); LLFastTimer t(FTM_AVATAR_UPDATE); @@ -2863,12 +2871,12 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) if (isDead()) { llinfos << "Warning! Idle on dead avatar" << llendl; - return TRUE; - } + return; + } if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR))) { - return TRUE; + return; } checkTextureLoading() ; @@ -2937,7 +2945,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) if (gNoRender) { - return TRUE; + return; } idleUpdateVoiceVisualizer( voice_enabled ); @@ -2954,8 +2962,6 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) idleUpdateNameTag( root_pos_last ); idleUpdateRenderCost(); - - return TRUE; } void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) @@ -3135,7 +3141,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (isImpostor() && !mNeedsImpostorUpdate) { - LLVector4a ext[2]; + LL_ALIGN_16(LLVector4a ext[2]); F32 distance; LLVector3 angle; @@ -3666,6 +3672,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) } bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); bool is_cloud = getIsCloud(); + bool is_langolier = isLangolier(); if (is_appearance != mNameAppearance) { @@ -3691,7 +3698,8 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) || is_muted != mNameMute || is_appearance != mNameAppearance || is_friend != mNameFriend - || is_cloud != mNameCloud) + || is_cloud != mNameCloud + || is_langolier != mNameLangolier) { LLColor4 name_tag_color = getNameTagColor(is_friend); @@ -3701,7 +3709,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) std::string firstnameText; std::string lastnameText; - if (is_away || is_muted || is_busy || is_appearance || !idle_string.empty()) + if (is_away || is_muted || is_busy || is_appearance || is_langolier || !idle_string.empty()) { std::string line; if (is_away) @@ -3724,7 +3732,12 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) line += LLTrans::getString("AvatarEditingAppearance"); //"(Editing Appearance)" line += ", "; } - if (is_cloud) + if (is_langolier) + { + line += LLTrans::getString("AvatarLangolier"); //"Langolier" + line += ", "; + } + else if (is_cloud) { line += LLTrans::getString("LoadingData"); //"Loading..." line += ", "; @@ -3755,8 +3768,8 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) static const LLCachedControl phoenix_name_system("PhoenixNameSystem", 0); - bool show_display_names = phoenix_name_system > 0; - bool show_usernames = phoenix_name_system < 2; + bool show_display_names = phoenix_name_system == 1 || phoenix_name_system == 2; + bool show_usernames = phoenix_name_system != 2; if (show_display_names && LLAvatarNameCache::useDisplayNames()) { LLAvatarName av_name; @@ -3851,6 +3864,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) mNameAppearance = is_appearance; mNameFriend = is_friend; mNameCloud = is_cloud; + mNameLangolier = is_langolier; mTitle = title ? title->getString() : ""; LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); new_name = TRUE; @@ -4088,7 +4102,18 @@ bool LLVOAvatar::isVisuallyMuted() const return LLMuteList::getInstance()->isMuted(getID()) || (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || - (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); + (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) || + isLangolier(); +} + +void LLVOAvatar::resetFreezeTime() +{ + bool dead = mFreezeTimeDead; + mFreezeTimeLangolier = mFreezeTimeDead = false; + if (dead) + { + markDead(); + } } //------------------------------------------------------------------------ @@ -4099,6 +4124,13 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { LLMemType mt(LLMemType::MTYPE_AVATAR); + // Frozen! + if (areAnimationsPaused()) + { + updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again. + return FALSE; + } + // clear debug text mDebugText.clear(); if (LLVOAvatar::sShowAnimationDebug) @@ -4339,7 +4371,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } LLVector3 velDir = getVelocity(); velDir.normalize(); - if ( mSignaledAnimations.find(ANIM_AGENT_WALK) != mSignaledAnimations.end()) + static LLCachedControl TurnAround("TurnAroundWhenWalkingBackwards"); + if (!TurnAround && (mSignaledAnimations.find(ANIM_AGENT_WALK) != mSignaledAnimations.end())) { F32 vpD = velDir * primDir; if (vpD < -0.5f) @@ -5245,7 +5278,20 @@ void LLVOAvatar::updateTextures() LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture_index); U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); const LLTextureEntry *te = getTE(texture_index); - const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT); + + // getTE can return 0. + // Not sure yet why it does, but of course it crashes when te->mScale? gets used. + // Put safeguard in place so this corner case get better handling and does not result in a crash. + F32 texel_area_ratio = 1.0f; + if( te ) + { + texel_area_ratio = fabs(te->mScaleS * te->mScaleT); + } + else + { + llwarns << "getTE( " << texture_index << " ) returned 0" <resetTextureStats(); - imagep->setCanUseHTTP(false) ; //turn off http fetching for baked textures. + //imagep->setCanUseHTTP(false) ; //turn off http fetching for baked textures. imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); imagep->resetMaxVirtualSizeResetCounter() ; @@ -5596,7 +5642,9 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL if ( start ) // start animation { - if (anim_id == ANIM_AGENT_TYPE && gSavedSettings.getBOOL("PlayTypingSound")) + static LLCachedControl play_typing_sound("PlayTypingSound"); + static LLCachedControl announce_snapshots("AnnounceSnapshots"); + if (anim_id == ANIM_AGENT_TYPE && play_typing_sound) { if (gAudiop) { @@ -5622,6 +5670,17 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL { sitDown(TRUE); } + else if(anim_id == ANIM_AGENT_SNAPSHOT && announce_snapshots) + { + std::string name; + LLAvatarNameCache::getPNSName(mID, name); + LLChat chat; + chat.mFromName = name; + chat.mText = name + " " + LLTrans::getString("took_a_snapshot") + "."; + chat.mURL = llformat("secondlife:///app/agent/%s/about",mID.asString().c_str()); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::addChat(chat); + } if (startMotion(anim_id)) @@ -7598,9 +7657,11 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) BOOL LLVOAvatar::isFullyLoaded() const { + static LLCachedControl const render_unloaded_avatar("RenderUnloadedAvatar", false); + // [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2.0a) | Added: Catznip-2.2.0a // Changes to LLAppearanceMgr::updateAppearanceFromCOF() expect this function to actually return mFullyLoaded for gAgentAvatarp - if ( (!isSelf()) && (mRenderUnloadedAvatar) ) + if ( (!isSelf()) && render_unloaded_avatar ) return TRUE; else return mFullyLoaded; @@ -7641,7 +7702,7 @@ void LLVOAvatar::updateMeshTextures() if(!isSelf()) { src_callback_list = &mCallbackTextureList ; - paused = mLoadedCallbacksPaused ; + paused = !isVisible(); } std::vector is_layer_baked; @@ -8206,7 +8267,7 @@ void LLVOAvatar::onFirstTEMessageReceived() if(!isSelf()) { src_callback_list = &mCallbackTextureList ; - paused = mLoadedCallbacksPaused ; + paused = !isVisible(); } for (U32 i = 0; i < mBakedTextureDatas.size(); i++) @@ -8824,6 +8885,9 @@ void LLVOAvatar::cullAvatarsByPixelArea() } } + // runway - this doesn't detect gray/grey state. + // think we just need to be checking self av since it's the only + // one with lltexlayer stuff. S32 grey_avatars = 0; if (LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars)) { @@ -9743,17 +9807,14 @@ BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index return FALSE; } - LLViewerTexture* img = getImage(te, index); - if(img) + if( !getImage( te, index ) ) { - return (img->getID() != IMG_DEFAULT_AVATAR && - img->getID() != IMG_DEFAULT); - } - else - { - llwarns << "Image doesn't exist" << llendl; + llwarns << "getImage( " << te << ", " << index << " ) returned 0" << llendl; return FALSE; } + + return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR && + getImage(te, index)->getID() != IMG_DEFAULT); } //virtual diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 81529a2f3..2985a0da6 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -140,6 +140,16 @@ protected: **/ public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual void markDead(); static void initClass(); // Initialize data that's only init'd once per class. @@ -171,7 +181,7 @@ public: U32 block_num, const EObjectUpdateType update_type, LLDataPacker *dp); - virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + virtual void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); virtual BOOL updateLOD(); BOOL updateJointLODs(); void updateLODRiggedAttachments( void ); @@ -261,7 +271,7 @@ public: bool isBuilt() const { return mIsBuilt; } private: //aligned members - LLVector4a mImpostorExtents[2]; + LL_ALIGN_16(LLVector4a mImpostorExtents[2]); private: BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients @@ -331,6 +341,8 @@ public: BOOL hasGray() const; S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured. void updateRezzedStatusTimers(); + bool isLangolier() const { return mFreezeTimeLangolier; } + bool isFrozenDead() const { return mFreezeTimeDead; } S32 mLastRezzedStatus; protected: @@ -348,6 +360,8 @@ private: S32 mVisualComplexity; LLFrameTimer mFullyLoadedTimer; LLFrameTimer mRuthTimer; + bool mFreezeTimeLangolier; // True when this avatar was created during snapshot FreezeTime mode, and that mode is still active. + bool mFreezeTimeDead; // True when the avatar was marked dead (ie, TP-ed away) while in FreezeTime mode. protected: LLFrameTimer mInvisibleTimer; @@ -443,6 +457,7 @@ private: public: U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); bool isVisuallyMuted() const; + void resetFreezeTime(); U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); @@ -518,8 +533,6 @@ private: F32 mImpostorDistance; F32 mImpostorPixelArea; LLVector3 mLastAnimExtents[2]; - - LLCachedControl mRenderUnloadedAvatar; //-------------------------------------------------------------------- // Wind rippling in clothes @@ -1002,6 +1015,7 @@ private: bool mNameAppearance; bool mNameFriend; bool mNameCloud; + bool mNameLangolier; F32 mNameAlpha; BOOL mRenderGroupTitles; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 2d8010c70..2a23972df 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -570,25 +570,14 @@ BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent) } // virtual -BOOL LLVOAvatarSelf::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOAvatarSelf::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - if (!isAgentAvatarValid()) + if (isAgentAvatarValid()) { - return TRUE; + LLVOAvatar::idleUpdate(agent, world, time); + if(!gNoRender) + idleUpdateTractorBeam(); } - /*if(!gNoRender) - { - //Emerald performs some force-bakes stuff here. Added it in because we noticed slow responses with client tag ident. -HgB - for(U8 i=0;iforceActive(); - } - }*/ - LLVOAvatar::idleUpdate(agent,world,time); - if(!gNoRender) - idleUpdateTractorBeam(); - return TRUE; } // virtual @@ -2319,11 +2308,25 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) if (isAllLocalTextureDataFinal()) { LLNotificationsUtil::add("AvatarRezSelfBakedDoneNotification",args); + LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() + << "sec ]" + << avString() + << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() + << " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32() + << " Notification " << "AvatarRezSelfBakedDoneNotification" + << llendl; } else { args["STATUS"] = debugDumpAllLocalTextureDataInfo(); LLNotificationsUtil::add("AvatarRezSelfBakedUpdateNotification",args); + LL_DEBUGS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() + << "sec ]" + << avString() + << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() + << " SelfLoadTimer " << (U32)mDebugSelfLoadTimer.getElapsedTimeF32() + << " Notification " << "AvatarRezSelfBakedUpdateNotification" + << llendl; } } @@ -2331,6 +2334,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) } } +// FIXME: This is not called consistently. Something may be broken. void LLVOAvatarSelf::outputRezDiagnostics() const { if(!gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) @@ -2339,11 +2343,11 @@ void LLVOAvatarSelf::outputRezDiagnostics() const } const F32 final_time = mDebugSelfLoadTimer.getElapsedTimeF32(); - llinfos << "REZTIME: Myself rez stats:" << llendl; - llinfos << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl; - llinfos << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl; - llinfos << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl; - llinfos << "\t Load time for each texture: " << llendl; + LL_DEBUGS("Avatar") << "REZTIME: Myself rez stats:" << llendl; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << llendl; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << llendl; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl; + LL_DEBUGS("Avatar") << "\t Load time for each texture: " << llendl; for (U32 i = 0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) { std::stringstream out; @@ -2367,12 +2371,14 @@ void LLVOAvatarSelf::outputRezDiagnostics() const // Don't print out non-existent textures. if (j != 0) - llinfos << out.str() << llendl; + { + LL_DEBUGS("Avatar") << out.str() << LL_ENDL; + } } - llinfos << "\t Time points for each upload (start / finish)" << llendl; + LL_DEBUGS("Avatar") << "\t Time points for each upload (start / finish)" << llendl; for (U32 i = 0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i) { - llinfos << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl; + LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << llendl; } for (LLVOAvatarDefines::LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDefines::LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); @@ -2384,15 +2390,16 @@ void LLVOAvatarSelf::outputRezDiagnostics() const if (!layerset) continue; const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite(); if (!layerset_buffer) continue; - llinfos << layerset_buffer->dumpTextureInfo() << llendl; + LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << llendl; } } void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const { - LL_DEBUGS("Avatar Rez") + LL_INFOS("Avatar") + << avString() << llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32()) - << llendl; + << LL_ENDL; } void LLVOAvatarSelf::reportAvatarRezTime() const diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 0105315ff..4f261266f 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -49,6 +49,16 @@ class LLVOAvatarSelf : **/ public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVOAvatarSelf(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual ~LLVOAvatarSelf(); virtual void markDead(); @@ -75,7 +85,7 @@ protected: //-------------------------------------------------------------------- public: /*virtual*/ void updateRegion(LLViewerRegion *regionp); - /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + /*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); //-------------------------------------------------------------------- // LLCharacter interface and related diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index b63103acb..10c03ebda 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -79,11 +79,11 @@ BOOL LLVOClouds::isActive() const } -BOOL LLVOClouds::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOClouds::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS))) { - return TRUE; + return; } // Set dirty flag (so renderer will rebuild primitive) @@ -91,8 +91,6 @@ BOOL LLVOClouds::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); } - - return TRUE; } diff --git a/indra/newview/llvoclouds.h b/indra/newview/llvoclouds.h index 685400f32..089f3efc1 100644 --- a/indra/newview/llvoclouds.h +++ b/indra/newview/llvoclouds.h @@ -69,7 +69,7 @@ public: /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area void updateFaceSize(S32 idx) { } - BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); virtual U32 getPartitionType() const; diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 66c40fbb6..a124311b3 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -301,17 +301,17 @@ BOOL LLVOGrass::isActive() const return TRUE; } -BOOL LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_GRASS))) { - return TRUE; + return; } if (!mDrawable) { // So drones work. - return TRUE; + return; } if(LLVOTree::isTreeRenderingStopped()) //stop rendering grass @@ -321,14 +321,14 @@ BOOL LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) mNumBlades = 0 ; gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } - return TRUE ; + return; } else if(!mNumBlades)//restart grass rendering { mNumBlades = GRASS_MAX_BLADES ; gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); - return TRUE ; + return; } if (mPatch && (mLastPatchUpdateTime != mPatch->getLastUpdateTime())) @@ -336,7 +336,7 @@ BOOL LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); } - return TRUE; + return; } diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index 4dc79c4fd..1e1c97ea5 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -79,7 +79,7 @@ public: void plantBlades(); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. - BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + /*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face = -1, // which face to check, -1 = ALL_SIDES diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp index 3300cb697..97b7418b4 100644 --- a/indra/newview/llvoground.cpp +++ b/indra/newview/llvoground.cpp @@ -2,31 +2,25 @@ * @file llvoground.cpp * @brief LLVOGround class implementation * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -55,18 +49,8 @@ LLVOGround::~LLVOGround() { } -BOOL LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_GROUND))) - { - return TRUE; - } - - /*if (mDrawable) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - }*/ - return TRUE; } diff --git a/indra/newview/llvoground.h b/indra/newview/llvoground.h index 0ccb0834a..290579b4d 100644 --- a/indra/newview/llvoground.h +++ b/indra/newview/llvoground.h @@ -2,31 +2,25 @@ * @file llvoground.h * @brief LLVOGround class header file * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -47,7 +41,7 @@ protected: public: LLVOGround(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); - /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + /*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); // Graphical stuff for objects - maybe broken out into render class // later? diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 99f528dc8..9f4c1c22d 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -202,9 +202,8 @@ void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) mDrawable->setPositionGroup(pos); } -BOOL LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - return TRUE; } void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent) diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 4948ddf55..ecf149c67 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -69,7 +69,7 @@ public: LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. - BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); virtual F32 getBinRadius(); virtual void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index de657beed..d3f199fdf 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -1053,9 +1053,8 @@ void LLVOSky::calcAtmospherics(void) mFadeColor.setAlpha(0); } -BOOL LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - return TRUE; } BOOL LLVOSky::updateSky() @@ -1426,6 +1425,7 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons LLStrider normalsp; LLStrider texCoordsp; LLStrider indicesp; + LLStrider colorsp; S32 index_offset; LLFace *facep; @@ -1482,7 +1482,7 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons if (!facep->getVertexBuffer()) { facep->setSize(4, 6); - LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); //Singu Note: Using LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK on purpose. buff->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE); facep->setGeomIndex(0); facep->setIndicesIndex(0); @@ -1492,6 +1492,7 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons llassert(facep->getVertexBuffer()->getNumIndices() == 6); index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); + facep->getColors(colorsp); if (-1 == index_offset) { @@ -1517,6 +1518,11 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons *indicesp++ = index_offset + 2; *indicesp++ = index_offset + 3; + *(colorsp++) = LLColor4::white; + *(colorsp++) = LLColor4::white; + *(colorsp++) = LLColor4::white; + *(colorsp++) = LLColor4::white; + facep->getVertexBuffer()->flush(); if (is_sun) diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index c669b92d9..2a150eccb 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -2,31 +2,25 @@ * @file llvosky.h * @brief LLVOSky class header file * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -145,7 +139,7 @@ protected: ~LLSkyTex(); - static S32 getResolution() { return sResolution; } + static S32 getResolution() { return sResolution; } static S32 getCurrent() { return sCurrent; } static S32 stepCurrent() { sCurrent++; sCurrent &= 1; return sCurrent; } static S32 getNext() { return ((sCurrent+1) & 1); } @@ -467,7 +461,7 @@ public: void cleanupGL(); void restoreGL(); - /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + /*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); BOOL updateSky(); // Graphical stuff for objects - maybe broken out into render class @@ -616,8 +610,8 @@ protected: public: //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 + //to guarantee at least updating one VBO buffer every frame + //to work around the bug caused by ATI card --> DEV-3855 // void createDummyVertexBuffer() ; void updateDummyVertexBuffer() ; diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index c765371c6..e5794fba7 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -354,11 +354,11 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, return retval; } -BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TREE))) { - return TRUE; + return; } S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ; @@ -389,7 +389,7 @@ BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // *TODO: I don't know what's so special about trees // that they don't get REBUILD_POSITION automatically // at a higher level. - const LLVector3 &this_position = getPositionAgent(); + const LLVector3 &this_position = getPositionRegion(); if (this_position != mLastPosition) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); @@ -408,8 +408,6 @@ BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } mTrunkLOD = trunk_LOD; - - return TRUE; } const F32 TREE_BLEND_MIN = 1.f; @@ -858,10 +856,10 @@ void LLVOTree::updateMesh() LLMatrix4 matrix; // Translate to tree base HACK - adjustment in Z plants tree underground - const LLVector3 &pos_agent = getPositionAgent(); + const LLVector3 &pos_region = getPositionRegion(); //gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); LLMatrix4 trans_mat; - trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); + trans_mat.setTranslation(pos_region.mV[VX], pos_region.mV[VY], pos_region.mV[VZ] - 0.1f); trans_mat *= matrix; // Rotate to tree position and bend for current trunk/wind diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index c1c94563b..f90503030 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -65,7 +65,7 @@ public: void **user_data, U32 block_num, const EObjectUpdateType update_type, LLDataPacker *dp); - /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + /*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); // Graphical stuff for objects - maybe broken out into render class later? /*virtual*/ void render(LLAgent &agent); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index c7a7c44b0..d76f6e40d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -185,7 +185,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, { if (!mTextureAnimp) { - mTextureAnimp = new LLViewerTextureAnim(); + mTextureAnimp = new LLViewerTextureAnim(this); } else { @@ -274,7 +274,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, { if (!mTextureAnimp) { - mTextureAnimp = new LLViewerTextureAnim(); + mTextureAnimp = new LLViewerTextureAnim(this); } else { @@ -317,157 +317,118 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, void LLVOVolume::animateTextures() { - F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; - S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); - - if (result) + if (!mDead) { - if (!mTexAnimMode) + F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; + S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); + + if (result) { - mFaceMappingChanged = TRUE; - gPipeline.markTextured(mDrawable); - } - mTexAnimMode = result | mTextureAnimp->mMode; + if (!mTexAnimMode) + { + mFaceMappingChanged = TRUE; + gPipeline.markTextured(mDrawable); + } + mTexAnimMode = result | mTextureAnimp->mMode; - S32 start=0, end=mDrawable->getNumFaces()-1; - if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) - { - start = end = mTextureAnimp->mFace; - } + S32 start=0, end=mDrawable->getNumFaces()-1; + if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) + { + start = end = mTextureAnimp->mFace; + } - for (S32 i = start; i <= end; i++) - { - LLFace* facep = mDrawable->getFace(i); - if (!facep) continue; - if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; + for (S32 i = start; i <= end; i++) + { + LLFace* facep = mDrawable->getFace(i); + if (!facep) continue; + if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; - const LLTextureEntry* te = facep->getTextureEntry(); + const LLTextureEntry* te = facep->getTextureEntry(); - if (!te) - { - continue; - } + if (!te) + { + continue; + } - if (!(result & LLViewerTextureAnim::ROTATE)) - { - te->getRotation(&rot); - } - if (!(result & LLViewerTextureAnim::TRANSLATE)) - { - te->getOffset(&off_s,&off_t); - } - if (!(result & LLViewerTextureAnim::SCALE)) - { - te->getScale(&scale_s, &scale_t); - } + if (!(result & LLViewerTextureAnim::ROTATE)) + { + te->getRotation(&rot); + } + if (!(result & LLViewerTextureAnim::TRANSLATE)) + { + te->getOffset(&off_s,&off_t); + } + if (!(result & LLViewerTextureAnim::SCALE)) + { + te->getScale(&scale_s, &scale_t); + } - if (!facep->mTextureMatrix) - { - facep->mTextureMatrix = new LLMatrix4(); - } + if (!facep->mTextureMatrix) + { + facep->mTextureMatrix = new LLMatrix4(); + } - LLMatrix4& tex_mat = *facep->mTextureMatrix; - tex_mat.setIdentity(); - LLVector3 trans ; - { - trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); - tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); - } + LLMatrix4& tex_mat = *facep->mTextureMatrix; + tex_mat.setIdentity(); + LLVector3 trans ; + { + trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); + } - LLVector3 scale(scale_s, scale_t, 1.f); - LLQuaternion quat; - quat.setQuat(rot, 0, 0, -1.f); + LLVector3 scale(scale_s, scale_t, 1.f); + LLQuaternion quat; + quat.setQuat(rot, 0, 0, -1.f); - tex_mat.rotate(quat); + tex_mat.rotate(quat); - LLMatrix4 mat; - mat.initAll(scale, LLQuaternion(), LLVector3()); - tex_mat *= mat; + LLMatrix4 mat; + mat.initAll(scale, LLQuaternion(), LLVector3()); + tex_mat *= mat; - tex_mat.translate(trans); + tex_mat.translate(trans); + } } - } - else - { - if (mTexAnimMode && mTextureAnimp->mRate == 0) + else { - U8 start, count; - - if (mTextureAnimp->mFace == -1) + if (mTexAnimMode && mTextureAnimp->mRate == 0) { - start = 0; - count = getNumTEs(); - } - else - { - start = (U8) mTextureAnimp->mFace; - count = 1; - } + U8 start, count; - for (S32 i = start; i < start + count; i++) - { - if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) + if (mTextureAnimp->mFace == -1) { - setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); + start = 0; + count = getNumTEs(); } - if (mTexAnimMode & LLViewerTextureAnim::SCALE) + else { - setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); + start = (U8) mTextureAnimp->mFace; + count = 1; } - if (mTexAnimMode & LLViewerTextureAnim::ROTATE) - { - setTERotation(i, mTextureAnimp->mRot); - } - } - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; + for (S32 i = start; i < start + count; i++) + { + if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) + { + setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); + } + if (mTexAnimMode & LLViewerTextureAnim::SCALE) + { + setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); + } + if (mTexAnimMode & LLViewerTextureAnim::ROTATE) + { + setTERotation(i, mTextureAnimp->mRot); + } + } + + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } } } } -BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) -{ - LLViewerObject::idleUpdate(agent, world, time); - - //static LLFastTimer::DeclareTimer ftm("Volume Idle"); - //LLFastTimer t(ftm); - - if (mDead || mDrawable.isNull()) - { - return TRUE; - } - - /////////////////////// - // - // Do texture animation stuff - // - - if (mTextureAnimp && gAnimateTextures) - { - animateTextures(); - } - - // Dispatch to implementation - if (mVolumeImpl) - { - mVolumeImpl->doIdleUpdate(agent, world, time); - } - - const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40; - - if (mDrawable->isActive()) - { - if (mDrawable->isRoot() && - mDrawable->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && - (!mDrawable->getParent() || !mDrawable->getParent()->isActive())) - { - mDrawable->makeStatic(); - } - } - - return TRUE; -} void LLVOVolume::updateTextures() { @@ -489,6 +450,7 @@ void LLVOVolume::updateTextures() } } + } } @@ -655,7 +617,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) } } - S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture + S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; if (texture_discard >= 0 && //texture has some data available @@ -711,8 +673,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) BOOL LLVOVolume::isActive() const { - return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()) || - (mDrawable.notNull() && mDrawable->isActive()); + return !mStatic; } BOOL LLVOVolume::setMaterial(const U8 material) @@ -958,7 +919,7 @@ void LLVOVolume::sculpt() S8 sculpt_components = 0; const U8* sculpt_data = NULL; - S32 discard_level = mSculptTexture->getDiscardLevel(); + S32 discard_level = mSculptTexture->getCachedRawImageLevel(); LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; S32 max_discard = mSculptTexture->getMaxDiscardLevel(); @@ -1153,13 +1114,13 @@ void LLVOVolume::updateFaceFlags() { for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { - if(mDrawable->getNumFaces() <= i || getNumTEs() <= i) - return; - LLFace *face = mDrawable->getFace(i); if (face) { - BOOL fullbright = getTE(i)->getFullbright(); + LLTextureEntry *entry = getTE(i); + if(!entry) + continue; + BOOL fullbright = entry->getFullbright(); face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); if (fullbright || (mMaterial == LL_MCODE_LIGHT)) @@ -3102,6 +3063,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons LLVector4a* pos = dst_face.mPositions; + if( pos && dst_face.mExtents ) { LLFastTimer t(FTM_SKIN_RIGGED); @@ -4360,7 +4322,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } else if (facep->canRenderAsMask()) { - if (te->getFullbright() || LLPipeline::sNoAlpha) + if (te->getFullbright() || fullbright || LLPipeline::sNoAlpha) { registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index dbf9800db..a83a33680 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -70,7 +70,7 @@ class LLVolumeInterface public: virtual ~LLVolumeInterface() { } virtual LLVolumeInterfaceType getInterfaceType() const = 0; - virtual void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) = 0; + virtual void doIdleUpdate() = 0; virtual BOOL doUpdateGeometry(LLDrawable *drawable) = 0; virtual LLVector3 getPivotPosition() const = 0; virtual void onSetVolume(const LLVolumeParams &volume_params, const S32 detail) = 0; @@ -116,8 +116,7 @@ public: void deleteFaces(); void animateTextures(); - /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); - + BOOL isVisible() const ; /*virtual*/ BOOL isActive() const; /*virtual*/ BOOL isAttachment() const; diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 6f085d6cc..049a89d1a 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -106,17 +106,8 @@ void LLVOWater::updateTextures() } // Never gets called -BOOL LLVOWater::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOWater::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - /*if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER))) - { - return TRUE; - } - if (mDrawable) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - }*/ - return TRUE; } LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline) diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h index 02a577a50..1203fb2ea 100644 --- a/indra/newview/llvowater.h +++ b/indra/newview/llvowater.h @@ -64,7 +64,7 @@ public: static void initClass(); static void cleanupClass(); - /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + /*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 492bfe174..757c04b7e 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -98,9 +98,9 @@ void LLVOWLSky::initSunDirection(LLVector3 const & sun_direction, { } -BOOL LLVOWLSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOWLSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - return TRUE; + } BOOL LLVOWLSky::isActive(void) const diff --git a/indra/newview/llvowlsky.h b/indra/newview/llvowlsky.h index 82abe79cb..82124587d 100644 --- a/indra/newview/llvowlsky.h +++ b/indra/newview/llvowlsky.h @@ -59,7 +59,7 @@ public: void initSunDirection(LLVector3 const & sun_direction, LLVector3 const & sun_angular_velocity); - /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + /*virtual*/ void idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ BOOL isActive(void) const; /*virtual*/ LLDrawable * createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 307edffdd..08f1d85a8 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -374,7 +374,7 @@ void LLWaterParamManager::updateShaderLinks() void LLWaterParamManager::update(LLViewerCamera * cam) { LLFastTimer ftm(FTM_UPDATE_WATERPARAM); - + // update the shaders and the menu propagateParameters(); diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp new file mode 100644 index 000000000..992307160 --- /dev/null +++ b/indra/newview/llwebprofile.cpp @@ -0,0 +1,327 @@ +/** + * @file llwebprofile.cpp + * @brief Web profile access. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llwebprofile.h" + +// libs +#include "llbufferstream.h" +#include "llhttpclient.h" +#include "llimagepng.h" +#include "llplugincookiestore.h" + +// newview +#include "llpanelprofile.h" // getProfileURL (this is the original location LL put it). +#include "llviewermedia.h" // FIXME: don't use LLViewerMedia internals + +// third-party JSONCPP +#include // JSONCPP + +/* + * Workflow: + * 1. LLViewerMedia::setOpenIDCookie() + * -> GET https://my-demo.secondlife.com/ via LLViewerMediaWebProfileResponder + * -> LLWebProfile::setAuthCookie() + * 2. LLWebProfile::uploadImage() + * -> GET "https://my-demo.secondlife.com/snapshots/s3_upload_config" via ConfigResponder + * 3. LLWebProfile::post() + * -> POST via PostImageResponder + * -> redirect + * -> GET via PostImageRedirectResponder + */ + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfileResponders::ConfigResponder + +extern AIHTTPTimeoutPolicy webProfileResponders_timeout; + +class LLWebProfileResponders::ConfigResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLWebProfileResponders::ConfigResponder); + +public: + ConfigResponder(LLPointer imagep) + : mImagep(imagep) + { + } + + /*virtual*/ void completedRaw( + U32 status, + const std::string& reason, + const LLChannelDescriptors& channels, + const buffer_ptr_t& buffer) + { + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + + if (status != 200) + { + llwarns << "Failed to get upload config (" << status << ")" << llendl; + LLWebProfile::reportImageUploadStatus(false); + return; + } + + Json::Value root; + Json::Reader reader; + if (!reader.parse(body, root)) + { + llwarns << "Failed to parse upload config: " << reader.getFormatedErrorMessages() << llendl; + LLWebProfile::reportImageUploadStatus(false); + return; + } + + // *TODO: 404 = not supported by the grid + // *TODO: increase timeout or handle 499 Expired + + // Convert config to LLSD. + const Json::Value data = root["data"]; + const std::string upload_url = root["url"].asString(); + LLSD config; + config["acl"] = data["acl"].asString(); + config["AWSAccessKeyId"] = data["AWSAccessKeyId"].asString(); + config["Content-Type"] = data["Content-Type"].asString(); + config["key"] = data["key"].asString(); + config["policy"] = data["policy"].asString(); + config["success_action_redirect"] = data["success_action_redirect"].asString(); + config["signature"] = data["signature"].asString(); + config["add_loc"] = data.get("add_loc", "0").asString(); + config["caption"] = data.get("caption", "").asString(); + + // Do the actual image upload using the configuration. + LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << LL_ENDL; + LLWebProfile::post(mImagep, config, upload_url); + } + +protected: + /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; } + /*virtual*/ bool followRedir(void) const { return true; } + +private: + LLPointer mImagep; +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfilePostImageRedirectResponder +class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLWebProfileResponders::PostImageRedirectResponder); + +public: + /*virtual*/ void completedRaw( + U32 status, + const std::string& reason, + const LLChannelDescriptors& channels, + const buffer_ptr_t& buffer) + { + if (status != 200) + { + llwarns << "Failed to upload image: " << status << " " << reason << llendl; + LLWebProfile::reportImageUploadStatus(false); + return; + } + + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + llinfos << "Image uploaded." << llendl; + LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << LL_ENDL; + LLWebProfile::reportImageUploadStatus(true); + } + +protected: + /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; } + /*virtual*/ bool followRedir(void) const { return true; } + +private: + LLPointer mImagep; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfileResponders::PostImageResponder +class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::ResponderWithCompleted +{ + LOG_CLASS(LLWebProfileResponders::PostImageResponder); + +public: + /*virtual*/ bool needsHeaders(void) const { return true; } + + /*virtual*/ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& received_headers) + { + // Server abuses 303 status; Curl can't handle it because it tries to resent + // the just uploaded data, which fails + // (CURLE_SEND_FAIL_REWIND: Send failed since rewinding of the data stream failed). + // Handle it manually. + if (status == 303) + { + AIHTTPHeaders headers; + headers.addHeader("Accept", "*/*"); + headers.addHeader("Cookie", LLWebProfile::getAuthCookie()); + headers.addHeader("User-Agent", LLViewerMedia::getCurrentUserAgent()); + std::string redir_url; + received_headers.getFirstValue("location", redir_url); + LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << LL_ENDL; + LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers); + } + else + { + llwarns << "Unexpected POST status: " << status << " " << reason << llendl; + LL_DEBUGS("Snapshots") << "received_headers: [" << received_headers << "]" << LL_ENDL; + LLWebProfile::reportImageUploadStatus(false); + } + } + + // Override just to suppress warnings. + /*virtual*/ void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const buffer_ptr_t& buffer) + { + } + +protected: + /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; } + /*virtual*/ bool redirect_status_ok(void) const { return true; } +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfile + +std::string LLWebProfile::sAuthCookie; +LLWebProfile::status_callback_t LLWebProfile::mStatusCallback; + +// static +void LLWebProfile::uploadImage(LLPointer image, const std::string& caption, bool add_location) +{ + // Get upload configuration data. + std::string config_url(getProfileURL(LLStringUtil::null) + "snapshots/s3_upload_config"); + config_url += "?caption=" + LLURI::escape(caption); + config_url += "&add_loc=" + std::string(add_location ? "1" : "0"); + + LL_DEBUGS("Snapshots") << "Requesting " << config_url << LL_ENDL; + AIHTTPHeaders headers; + headers.addHeader("Accept", "*/*"); + headers.addHeader("Cookie", LLWebProfile::getAuthCookie()); + headers.addHeader("User-Agent", LLViewerMedia::getCurrentUserAgent()); + LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers); +} + +// static +void LLWebProfile::setAuthCookie(const std::string& cookie) +{ + LL_DEBUGS("Snapshots") << "Setting auth cookie: " << cookie << LL_ENDL; + sAuthCookie = cookie; +} + +// static +void LLWebProfile::post(LLPointer image, const LLSD& config, const std::string& url) +{ + if (dynamic_cast(image.get()) == 0) + { + llwarns << "Image to upload is not a PNG" << llendl; + llassert(dynamic_cast(image.get()) != 0); + return; + } + + const std::string boundary = "----------------------------0123abcdefab"; + + AIHTTPHeaders headers; + headers.addHeader("Accept", "*/*"); + headers.addHeader("Cookie", LLWebProfile::getAuthCookie()); + headers.addHeader("User-Agent", LLViewerMedia::getCurrentUserAgent()); + headers.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary); + + std::ostringstream body; + + // *NOTE: The order seems to matter. + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"key\"\r\n\r\n" + << config["key"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"AWSAccessKeyId\"\r\n\r\n" + << config["AWSAccessKeyId"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"acl\"\r\n\r\n" + << config["acl"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"Content-Type\"\r\n\r\n" + << config["Content-Type"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"policy\"\r\n\r\n" + << config["policy"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"signature\"\r\n\r\n" + << config["signature"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"success_action_redirect\"\r\n\r\n" + << config["success_action_redirect"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.png\"\r\n" + << "Content-Type: image/png\r\n\r\n"; + size_t const body_size = body.str().size(); + + std::ostringstream footer; + footer << "\r\n--" << boundary << "--\r\n"; + size_t const footer_size = footer.str().size(); + + size_t size = body_size + image->getDataSize() + footer_size; + // postRaw() takes ownership of the buffer and releases it later. + char* data = new char [size]; + memcpy(data, body.str().data(), body_size); + // Insert the image data. + memcpy(data + body_size, image->getData(), image->getDataSize()); + memcpy(data + body_size + image->getDataSize(), footer.str().data(), footer_size); + + // Send request, successful upload will trigger posting metadata. + LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers/*,*/ DEBUG_CURLIO_PARAM(debug_off), no_keep_alive); +} + +// static +void LLWebProfile::reportImageUploadStatus(bool ok) +{ + if (mStatusCallback) + { + mStatusCallback(ok); + } +} + +// static +std::string LLWebProfile::getAuthCookie() +{ + // This is needed to test image uploads on Linux viewer built with OpenSSL 1.0.0 (0.9.8 works fine). + const char* debug_cookie = getenv("LL_SNAPSHOT_COOKIE"); + return debug_cookie ? debug_cookie : sAuthCookie; +} diff --git a/indra/newview/llwebprofile.h b/indra/newview/llwebprofile.h new file mode 100644 index 000000000..10279bffa --- /dev/null +++ b/indra/newview/llwebprofile.h @@ -0,0 +1,69 @@ +/** + * @file llwebprofile.h + * @brief Web profile access. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLWEBPROFILE_H +#define LL_LLWEBPROFILE_H + +#include "llimage.h" + +namespace LLWebProfileResponders +{ + class ConfigResponder; + class PostImageResponder; + class PostImageRedirectResponder; +}; + +/** + * @class LLWebProfile + * + * Manages interaction with, a web service allowing the upload of snapshot images + * taken within the viewer. + */ +class LLWebProfile +{ + LOG_CLASS(LLWebProfile); + +public: + typedef boost::function status_callback_t; + + static void uploadImage(LLPointer image, const std::string& caption, bool add_location); + static void setAuthCookie(const std::string& cookie); + static void setImageUploadResultCallback(status_callback_t cb) { mStatusCallback = cb; } + +private: + friend class LLWebProfileResponders::ConfigResponder; + friend class LLWebProfileResponders::PostImageResponder; + friend class LLWebProfileResponders::PostImageRedirectResponder; + + static void post(LLPointer image, const LLSD& config, const std::string& url); + static void reportImageUploadStatus(bool ok); + static std::string getAuthCookie(); + + static std::string sAuthCookie; + static status_callback_t mStatusCallback; +}; + +#endif // LL_LLWEBPROFILE_H diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 0495d9c51..e6eb7299c 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -108,18 +108,25 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder() if (mID != sCount) { LL_INFOS("WindlightCaps") << "Got superseded by another responder; ignoring..." << LL_ENDL; - return; } - - if (unvalidated_content[0]["regionID"].asUUID() != gAgent.getRegion()->getRegionID()) + else if (!gAgent.getRegion() || gAgent.getRegion()->getRegionID().isNull()) + { + LL_WARNS("WindlightCaps") << "Ignoring responder. Current region is invalid." << LL_ENDL; + } + else if (unvalidated_content[0]["regionID"].asUUID().isNull()) + { + LL_WARNS("WindlightCaps") << "Ignoring responder. Response from invalid region." << LL_ENDL; + } + else if (unvalidated_content[0]["regionID"].asUUID() != gAgent.getRegion()->getRegionID()) { LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting " << gAgent.getRegion()->getRegionID() << " but got " << unvalidated_content[0]["regionID"].asUUID() << ") - ignoring..." << LL_ENDL; - return; } - - LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content); + else + { + LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content); + } } /*virtual*/ void LLEnvironmentRequestResponder::error(U32 status, const std::string& reason) { diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index 284da40cd..cbcd5ec4e 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -475,7 +475,7 @@ void LLWLParamManager::propagateParameters(void) void LLWLParamManager::update(LLViewerCamera * cam) { LLFastTimer ftm(FTM_UPDATE_WLPARAM); - + // update clouds, sun, and general mCurParams.updateCloudScrolling(); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index ff0d1558a..0ad2cfbda 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -682,6 +682,12 @@ void LLWorld::updateRegions(F32 max_update_time) void LLWorld::updateParticles() { + static const LLCachedControl freeze_time("FreezeTime",false); + if (freeze_time) + { + // don't move particles in snapshot mode + return; + } LLViewerPartSim::getInstance()->updateSimulation(); } diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 91e1e6cda..3f2d7b5ca 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -47,46 +47,79 @@ #include "llviewertexturelist.h" #include "llviewerregion.h" #include "llregionflags.h" - #include "hippogridmanager.h" -bool LLWorldMap::sGotMapURL = false; -const F32 AGENTS_UPDATE_TIMER = 60.0; // Seconds between 2 agent requests for a region -const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // 10 minutes +#include "llworldmapmessage.h" +#include "hippogridmanager.h" + +bool LLWorldMap::sGotMapURL = false; +// 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::LLSimInfo(U64 handle) : mHandle(handle), mName(), mAgentsUpdateTime(0), - mShowAgentLocations(FALSE), mAccess(0x0), mRegionFlags(0x0), - mWaterHeight(0.f), - mAlpha(-1.f) + mFirstAgentRequest(true), + mSizeX(REGION_WIDTH_UNITS), + mSizeY(REGION_WIDTH_UNITS), + mAlpha(0.f) { } +void LLSimInfo::setLandForSaleImage (LLUUID image_id) +{ + mMapImageID[SIM_LAYER_OVERLAY] = image_id; + // Fetch the image + if (mMapImageID[SIM_LAYER_OVERLAY].notNull()) + { + mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mLayerImage[SIM_LAYER_OVERLAY]->setAddressMode(LLTexUnit::TAM_CLAMP); + } + else + { + mLayerImage[SIM_LAYER_OVERLAY] = NULL; + } +} + +LLPointer LLSimInfo::getLandForSaleImage () +{ + if (mLayerImage[SIM_LAYER_OVERLAY].isNull() && mMapImageID[SIM_LAYER_OVERLAY].notNull()) + { + // Fetch the image if it hasn't been done yet (unlikely but...) + mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mLayerImage[SIM_LAYER_OVERLAY]->setAddressMode(LLTexUnit::TAM_CLAMP); + } + if (!mLayerImage[SIM_LAYER_OVERLAY].isNull()) + { + // Boost the fetch level when we try to access that image + mLayerImage[SIM_LAYER_OVERLAY]->setBoostLevel(LLViewerTexture::BOOST_MAP); + } + return mLayerImage[SIM_LAYER_OVERLAY]; +} LLVector3d LLSimInfo::getGlobalPos(const LLVector3& local_pos) const { @@ -109,18 +142,31 @@ LLVector3 LLSimInfo::getLocalPos(LLVector3d global_pos) const void LLSimInfo::clearImage() { - if (!mOverlayImage.isNull()) + for(U32 layer = SIM_LAYER_BEGIN; layer < SIM_LAYER_COUNT;++layer) { - mOverlayImage->setBoostLevel(0); - mOverlayImage = NULL; + if(!mLayerImage[layer].isNull()) + { + mLayerImage[layer]->setBoostLevel(0); + mLayerImage[layer]=NULL; + } } } -void LLSimInfo::dropImagePriority() +void LLSimInfo::dropImagePriority(sim_layer_type layer/* = SIM_LAYER_COUNT*/) { - if (!mOverlayImage.isNull()) + if(layer == SIM_LAYER_COUNT) { - mOverlayImage->setBoostLevel(0); + for(U32 layer = SIM_LAYER_BEGIN; layer < SIM_LAYER_COUNT;++layer) + { + if(!mLayerImage[layer].isNull()) + { + mLayerImage[layer]->setBoostLevel(0); + } + } + } + else if(layer < SIM_LAYER_COUNT && layer >= SIM_LAYER_BEGIN && !mLayerImage[layer].isNull()) + { + mLayerImage[layer]->setBoostLevel(0); } } @@ -129,116 +175,154 @@ void LLSimInfo::updateAgentCount(F64 time) { if ((time - mAgentsUpdateTime > AGENTS_UPDATE_TIMER) || mFirstAgentRequest) { - LLWorldMap::getInstance()->sendItemRequest(MAP_ITEM_AGENT_LOCATIONS, mHandle); + LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_AGENT_LOCATIONS, mHandle); mAgentsUpdateTime = time; mFirstAgentRequest = false; } } + +// Get the total agents count +const S32 LLSimInfo::getAgentCount() const +{ + S32 total_agent_count = 0; + for (LLSimInfo::item_info_list_t::const_iterator it = mAgentLocations.begin(); it != mAgentLocations.end(); ++it) + { + total_agent_count += it->getCount(); + } + return total_agent_count; +} + bool LLSimInfo::isName(const std::string& name) const { return (LLStringUtil::compareInsensitive(name, mName) == 0); } +void LLSimInfo::dump() const +{ + 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 + << " " << mSizeX << "x" << mSizeY +// << " " << 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(); + + // 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()) + { + mAgentLocations.erase(mAgentLocations.begin(), lastiter); + } + + // Now append the new location + mAgentLocations.push_back(item); +} + //--------------------------------------------------------------------------- // 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) + mIsTrackingLocation( false ), + mIsTrackingFound( false ), + mIsInvalidLocation( false ), + mIsTrackingDoubleClick( false ), + mIsTrackingCommit( false ), + mTrackingLocation( 0, 0, 0 ), + mFirstRequest(true), + mMapLoaded(false) { - for (S32 map=0; map LLWorldMap::LLWorldMap()" << LL_ENDL; + /*for (U32 map=SIM_LAYER_BEGIN; map LLWorldMap::~LLWorldMap()" << LL_ENDL; reset(); - for (S32 map=0; map 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. @@ -252,11 +336,6 @@ void LLWorldMap::clearImageRefs() sim_info = it->second; if(sim_info) { - if (sim_info->mCurrentImage) - { - sim_info->mCurrentImage->setBoostLevel(0); - sim_info->mCurrentImage = NULL; - } sim_info->clearImage(); } } @@ -265,12 +344,13 @@ void LLWorldMap::clearImageRefs() // Doesn't clear the already-loaded sim infos, just re-requests them void LLWorldMap::clearSimFlags() { - for (S32 map=0; map::const_iterator it; - for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) + sim_info_map_t::iterator it = mSimInfoMap.find(handle); + if (it != mSimInfoMap.end()) { - const U64 handle = (*it).first; - LLSimInfo* info = (*it).second; - if(handle == findhandle) - { - return info; - } - U32 x = 0, y = 0; - from_region_handle(findhandle, &x, &y); - U32 checkRegionX, checkRegionY; - from_region_handle(handle, &checkRegionX, &checkRegionY); - - if(x >= checkRegionX && x < (checkRegionX + info->getSizeX()) && - y >= checkRegionY && y < (checkRegionY + info->getSizeY())) - { - return info; - } + return it->second; } return NULL; } @@ -358,256 +423,75 @@ bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, std::string return (sim_info != NULL); } -void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer) -{ - //TODO: we only have 1 layer -SG - mCurrentMap = layer; - if (!mMapLoaded[layer] || request_layer) - { - sendMapLayerRequest(); - } - - 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() { if (!gAgent.getRegion()) return; - LLSD body; - body["Flags"] = mCurrentMap; std::string url = gAgent.getRegion()->getCapability( gAgent.isGodlike() ? "MapLayerGod" : "MapLayer"); + U32 flags = layerToFlags((sim_layer_type)SIM_LAYER_COMPOSITE); if (!url.empty()) { - llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl; + LLSD body; + body["Flags"] = (LLSD::Integer)flags; + //llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl; LLHTTPClient::post(url, body, new LLMapLayerResponder); } else { - llinfos << "LLWorldMap::sendMapLayerRequest via message system" << llendl; + //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_Flags, flags); msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim gAgent.sendReliableMessage(); - - if (mRequestLandForSale) - { - 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(); - } } } -// 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**) { - llinfos << "LLWorldMap::processMapLayerReply from message system" << llendl; + //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) + U32 layer = flagsToLayer(agent_flags); + if (layer != SIM_LAYER_COMPOSITE) { llwarns << "Invalid or out of date map image type returned!" << llendl; return; } LLUUID image_id; - //U32 left, right, top, bottom; S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_LayerData); - LLWorldMap::getInstance()->mMapLayers[agent_flags].clear(); + LLWorldMap::getInstance()->mMapLayers.clear(); -// bool use_web_map_tiles = useWebMapTiles(); - BOOL adjust = FALSE; for (S32 block=0; blockgetUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block); - + 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); -// if (use_web_map_tiles) -// { -// new_layer.LayerImage = loadObjectsTile(left, bottom); // no good... Maybe using of level 2 and higher web maps ? -// } -// else -// { - new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); -// } + new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -617,269 +501,148 @@ void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**) 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); + LLWorldMap::getInstance()->mMapLayers.push_back(new_layer); } - LLWorldMap::getInstance()->mMapLoaded[agent_flags] = TRUE; - if(adjust) gFloaterWorldMap->adjustZoomSliderBounds(); + LLWorldMap::getInstance()->mMapLoaded = true; } // public static bool LLWorldMap::useWebMapTiles() { - return gSavedSettings.getBOOL("UseWebMapTiles") && - (( gHippoGridManager->getConnectedGrid()->isSecondLife() || sGotMapURL) && LLWorldMap::getInstance()->mCurrentMap == 0); + static const LLCachedControl use_web_map_tiles("UseWebMapTiles",false); + return use_web_map_tiles && + (( gHippoGridManager->getConnectedGrid()->isSecondLife() || sGotMapURL)); } -// public static -LLPointer LLWorldMap::loadObjectsTile(U32 grid_x, U32 grid_y) +void LLWorldMap::reloadItems(bool force) { - // Get the grid coordinates - std::string imageurl = gSavedSettings.getString("MapServerURL") + llformat("map-%d-%d-%d-objects.jpg", 1, grid_x, grid_y); - - LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl,TRUE,LLViewerTexture::BOOST_MAP,LLViewerTexture::LOD_TEXTURE); - img->setBoostLevel(LLViewerTexture::BOOST_MAP); - - // Return the smart pointer - return img; -} - -// 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") << "LLWorldMap::reloadItems()" << LL_ENDL; + if (clearItems(force)) { - llwarns << "Invalid map image type returned! " << agent_flags << llendl; - return; + 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); } - - S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data); - - bool found_null_sim = false; - -#ifdef IMMEDIATE_IMAGE_LOAD - bool use_web_map_tiles = useWebMapTiles(); -#endif - BOOL adjust = FALSE; - for (S32 block=0; blockgetU16Fast(_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); - if(msg->getNumberOfBlocksFast(_PREHASH_Size) > 0) + if(!mMapLoaded || force) + 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, U32 x_size, U32 y_size, U32 agent_flags, std::string& name, LLUUID& image_id, U32 accesscode, U32 region_flags) +{ + // This region doesn't exist + if (accesscode == 255) + { + // 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)) { - msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeX, x_size, block); - msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeY, y_size, block); + LLWorldMap::getInstance()->setTrackingInvalid(); } - if(x_size == 0 || (x_size % 16) != 0|| (y_size % 16) != 0) + // return failure to insert + return false; + } + else + { + 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) { - x_size = 256; - y_size = 256; + siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); } - U32 x_meters = x_regions * REGION_WIDTH_UNITS; - U32 y_meters = y_regions * REGION_WIDTH_UNITS; + siminfo->setName( name ); + siminfo->setAccess( accesscode ); + siminfo->setRegionFlags( region_flags ); + //siminfo->setWaterHeight((F32) water_height); + U32 layer = flagsToLayer(agent_flags); + if (layer == SIM_LAYER_OVERLAY) + siminfo->setLandForSaleImage(image_id); + else if(layer < SIM_LAYER_COUNT) + siminfo->setMapImageID( image_id, layer ); + siminfo->setSize( x_size, y_size ); - U64 handle = to_region_handle(x_meters, y_meters); - - if (accesscode == 255) + // 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)) { - // 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) + if (siminfo->isDown()) { - // We were tracking this location, but it doesn't exist - LLWorldMap::getInstance()->mInvalidLocation = TRUE; - } - - found_null_sim = true; - } - else - { - adjust = LLWorldMap::getInstance()->extendAABB(x_meters, - y_meters, - x_meters+REGION_WIDTH_UNITS, - y_meters+REGION_WIDTH_UNITS) || adjust; - //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) - { - siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); - } - - siminfo->setName( name ); - siminfo->setAccess( accesscode ); - siminfo->setRegionFlags( region_flags ); - siminfo->setWaterHeight((F32) water_height); - siminfo->setMapImageID( image_id, agent_flags ); - siminfo->setSize( x_size, y_size ); - -#ifdef IMMEDIATE_IMAGE_LOAD - if (use_web_map_tiles) - { - siminfo->mCurrentImage = loadObjectsTile((U32)x_regions, (U32)y_regions); + // We were tracking this location, but it's no available + LLWorldMap::getInstance()->setTrackingInvalid(); } else { - siminfo->mCurrentImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); + // We were tracking this location, and it does exist and is available + LLWorldMap::getInstance()->setTrackingValid(); } - gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get()); - siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); -#endif + } + // return insert region success + return true; + } +} + +// 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) +{ + // Create an item record for the received object + LLItemInfo new_item((F32)x_world, (F32)y_world, name, uuid); + + // 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); + + // 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) + { + siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle); + } + + //LL_INFOS("World Map") << "Process item : type = " << type << LL_ENDL; + switch (type) + { + case MAP_ITEM_TELEHUB: // telehubs + { + /* 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::getFetchedTextureURL(siminfo->mMapImageID[2]); -#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->isDown()) - { - // 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) - { - // Server returns definitive capitalization, SLURL might not have that. - if ((LLStringUtil::compareInsensitive(LLWorldMap::getInstance()->mSLURLRegionName, name)==0) - || (LLWorldMap::getInstance()->mSLURLRegionHandle == handle)) - { - 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); - } - } - if( gAgent.mPendingLure && - (U16)(gAgent.mPendingLure->mPosGlobal.mdV[0] / REGION_WIDTH_UNITS) == x_regions && - (U16)(gAgent.mPendingLure->mPosGlobal.mdV[1] / REGION_WIDTH_UNITS) == y_regions ) - { - gAgent.onFoundLureDestination(); - } - } - - 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; blockgetU32Fast(_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.getRegionHandle()); - - switch (type) - { - case MAP_ITEM_TELEHUB: // telehubs - { - // 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; - } - case MAP_ITEM_PG_EVENT: // events - case MAP_ITEM_MATURE_EVENT: - case MAP_ITEM_ADULT_EVENT: + case MAP_ITEM_PG_EVENT: // events + case MAP_ITEM_MATURE_EVENT: + case MAP_ITEM_ADULT_EVENT: { struct tm* timep; // Convert to Pacific, based on server's opinion of whether @@ -894,252 +657,64 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) timep->tm_min, (timep->tm_hour < 12 ? "AM" : "PM") ) ); - // HACK: store Z in extra2 - new_item.setElevation((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; - } - case MAP_ITEM_LAND_FOR_SALE: // land for sale - case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale + // HACK: store Z in extra2 + new_item.setElevation((F64)extra2); + if (type == MAP_ITEM_PG_EVENT) { - new_item.setTooltip(llformat("%d sq. m. %s%d", new_item.mExtra, - gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str(), - 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); + siminfo->insertPGEvent(new_item); + } + else if (type == MAP_ITEM_MATURE_EVENT) + { + siminfo->insertMatureEvent(new_item); + } + else if (type == MAP_ITEM_ADULT_EVENT) + { + siminfo->insertAdultEvent(new_item); + } + break; + } + case MAP_ITEM_LAND_FOR_SALE: // land for sale + case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale + { + new_item.setTooltip(llformat("%d sq. m. %s%d", extra, + gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str(), + extra2)); + if (type == MAP_ITEM_LAND_FOR_SALE) + { + siminfo->insertLandForSale(new_item); + } + else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT) + { + siminfo->insertLandForSaleAdult(new_item); } break; } case MAP_ITEM_CLASSIFIED: // classifieds { - //DEPRECATED: no longer used - break; - } - case MAP_ITEM_AGENT_LOCATIONS: // agent locations - { - if (!siminfo) - { - llinfos << "siminfo missing for " << new_item.getGlobalPosition().mdV[0] << ", " << new_item.getGlobalPosition().mdV[1] << llendl; - break; - } -// llinfos << "New Location " << new_item.mName << llendl; - - item_info_list_t& agentcounts = LLWorldMap::getInstance()->mAgentLocationsMap[new_item.getRegionHandle()]; - - // 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.isName(new_item.getName())) - { - 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; - } - 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->getName() - << " " << (S32)info->getAccess() - << " " << std::hex << info->getRegionFlags() << std::dec - << " " << info->getWaterHeight() - //<< " " << info->mTelehubName - //<< " " << info->mTelehubPosition - << llendl; - - if (info->mCurrentImage) - { - llinfos << "image discard " << (S32)info->mCurrentImage->getDiscardLevel() - << " fullwidth " << info->mCurrentImage->getWidth(0) - << " fullheight " << info->mCurrentImage->getHeight(0) - << " maxvirt " << info->mCurrentImage->getMaxVirtualSize() - << " maxdisc " << (S32)info->mCurrentImage->getMaxDiscardLevel() - << llendl; + //DEPRECATED: no longer used + break; } - } -} - - -BOOL LLWorldMap::extendAABB(U32 min_x, U32 min_y, U32 max_x, U32 max_y) -{ - 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; -} - - -U32 LLWorldMap::getWorldWidth() const -{ - return mMaxX - mMinX; -} - - -U32 LLWorldMap::getWorldHeight() const -{ - return mMaxY - mMinY; -} - -BOOL LLWorldMap::coveredByTelehub(LLSimInfo* infop) -{ - /*if (!mTelehubCoverageMap) - { - return FALSE; - } - 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() -{ - /*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)); - - // leave 1 sim border - S32 min_x = (mMinX / REGION_WIDTH_UNITS) - 1; - S32 min_y = (mMinY / REGION_WIDTH_UNITS) - 1; - - std::map::const_iterator it; - 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); - 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]) + case MAP_ITEM_AGENT_LOCATIONS: // agent locations { - 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++) +// LL_INFOS("World Map") << "New Location " << new_item.mName << LL_ENDL; + if (extra > 0) { - memset(&mTelehubCoverageMap[x_start + y_index * mNeighborMapWidth], 0xff, sizeof(U8) * x_span); + new_item.setCount(extra); + siminfo->insertAgentLocation(new_item); } + break; } + default: + break; } + return true; +} - 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; - - S32 index = x_pos - min_x + (mNeighborMapWidth * (y_pos - min_y)); - mTelehubCoverageMap[index] *= mNeighborMap[index]; - }*/ +bool LLWorldMap::isTrackingInRectangle(F64 x0, F64 y0, F64 x1, F64 y1) +{ + if (!mIsTrackingLocation) + return false; + return ((mTrackingLocation[0] >= x0) && (mTrackingLocation[0] < x1) && (mTrackingLocation[1] >= y0) && (mTrackingLocation[1] < y1)); } // Drop priority of all images being fetched by the map @@ -1155,19 +730,85 @@ void LLWorldMap::dropImagePriorities() } } -LLPointer LLSimInfo::getLandForSaleImage () +// 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) { - if (mOverlayImage.isNull() && mMapImageID[2].notNull()) + // Convert those boundaries to the corresponding (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) block coordinates + U32 global_x0 = x0 / MAP_BLOCK_SIZE; + U32 global_x1 = x1 / MAP_BLOCK_SIZE; + U32 global_y0 = y0 / MAP_BLOCK_SIZE; + U32 global_y1 = y1 / MAP_BLOCK_SIZE; + + //Singu note: There's a bunch of extra logic here, as opensim grids support sim coordinates that extend beyond the range + // used on the official grid. We basically just extend what LL had here by nesting the mMapBlockLoaded array in a 'dynamic' grid, + // essentially making that array a 'block' itself. An std::map was used to conserve memory, as we selectively only allocate desired + // blocks, and although lookups aren't blazingly fast with that container, it isn't likeley to accumulate very many entries. + + //MapBlockRequest uses U16 for coordinate components. + // In order not to exceed U16_MAX values, MAP_BLOCK_RES*MAP_BLOCK_SIZE*(i or j) can't exceed U16_MAX(65535) + U32 max_range = (U16_MAX+1)/MAP_BLOCK_RES/MAP_BLOCK_SIZE - 1; + + //Desired coordinate ranges in our 'dynamic' grid of 512x512 grids of 4x4 sim blocks. + U32 map_block_x0 = global_x0 / MAP_BLOCK_RES; + U32 map_block_x1 = llmin(global_x1 / MAP_BLOCK_RES, max_range); + U32 map_block_y0 = global_y0 / MAP_BLOCK_RES; + U32 map_block_y1 = llmin(global_y1 / MAP_BLOCK_RES, max_range); + + const bool layer_start = useWebMapTiles() ? SIM_LAYER_OVERLAY : SIM_LAYER_BEGIN; + for (U32 i = map_block_x0; i <= map_block_x1; ++i) { - // Fetch the image if it hasn't been done yet (unlikely but...) - mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID[2], MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); - mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); - } - if (!mOverlayImage.isNull()) + for (U32 j = map_block_y0; j <= map_block_y1; ++j) { - // Boost the fetch level when we try to access that image - mOverlayImage->setBoostLevel(LLViewerTexture::BOOST_MAP); + + //Desired coordinate ranges in our 512x512 grids of 4x4 sim blocks. + x0 = global_x0 - i * MAP_BLOCK_RES; + x1 = llmin(global_x1 - i * (U32)MAP_BLOCK_RES, (U32)MAP_BLOCK_RES-1); + y0 = global_y0 - j * MAP_BLOCK_RES; + y1 = llmin(global_y1 - j * (U32)MAP_BLOCK_RES, (U32)MAP_BLOCK_RES-1); + + for(U32 layer = layer_start;layer &block = mMapBlockMap[layer][(i << 16) | j]; + if(block.empty()) + { + //New block. Allocate the array and set all entries to false. (seen as mMapBlockLoaded in v3) + block.resize(MAP_BLOCK_RES*MAP_BLOCK_RES,false); + } + + // Load the region info those blocks + for (S32 block_x = llmax(x0, 0); block_x <= llmin(x1, MAP_BLOCK_RES-1); ++block_x) + { + for (S32 block_y = llmax(y0, 0); block_y <= llmin(y1, MAP_BLOCK_RES-1); ++block_y) + { + S32 offset = block_x | (block_y * MAP_BLOCK_RES); + // if(!mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset]) + if (!block[offset]) + { + U16 min_x = (block_x + i * MAP_BLOCK_RES) * MAP_BLOCK_SIZE; + U16 max_x = min_x + MAP_BLOCK_SIZE - 1; + U16 min_y = (block_y + j * MAP_BLOCK_RES) * MAP_BLOCK_SIZE; + U32 max_y = min_y + MAP_BLOCK_SIZE - 1; + + //LL_INFOS("World Map") << "Loading Block (" << block_x << "," << block_y << ")" << LL_ENDL; + LLWorldMapMessage::getInstance()->sendMapBlockRequest(min_x, min_y, max_x, max_y, false, layerToFlags((sim_layer_type)layer)); + block[offset] = true; + } + } + } + } + } } - return mOverlayImage; } +void LLWorldMap::dump() +{ + LL_INFOS("World Map") << "LLWorldMap::dump()" << LL_ENDL; + for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) + { + LLSimInfo* info = it->second; + if (info) + { + info->dump(); + } + } +} diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h index c9e6be37e..c34dc0f21 100644 --- a/indra/newview/llworldmap.h +++ b/indra/newview/llworldmap.h @@ -51,39 +51,80 @@ 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); + LLItemInfo(F32 global_x, F32 global_y, const std::string& name, LLUUID id); // Setters void setTooltip(const 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; } - U64 getRegionHandle() const { return mRegionHandle; } + S32 getCount() const { return mCount; } + + U64 getRegionHandle() const { return to_region_handle(mPosGlobal); } // Build the handle on the fly + 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; - std::string mToolTip; - LLVector3d mPosGlobal; - LLUUID mID; - U64 mRegionHandle; -public: //public for now.. non-standard. - BOOL mSelected; - S32 mExtra; - S32 mExtra2; + 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 }; -#define MAP_SIM_IMAGE_TYPES 3 -// 0 - Prim -// 1 - Terrain Only -// 2 - Overlay: Land For Sale +//Layer types that we intend to support. +enum sim_layer_type +{ + SIM_LAYER_BEGIN, + SIM_LAYER_COMPOSITE=0, //Legacy terrain+prim texture provided in MapBlockReply message. + SIM_LAYER_OVERLAY, //The land-for-sale overlay texture provided in MapBlockReply message. + SIM_LAYER_COUNT +}; +//The MapBlockRequest message 'layerflags' don't match the order of the sim_layer_type, so a few +//simple inline functions have been provided to convert between sim_layer_type and layerflag. +inline U32 layerToFlags(sim_layer_type layer) +{ + static U32 flags[SIM_LAYER_COUNT] = {0,2}; + return flags[layer]; +} +inline U32 flagsToLayer(U32 flags) +{ + //We only want the low two bytes, so mask out the rest. + if((flags & 0xFFFF) == 0) + return SIM_LAYER_COMPOSITE; + else if((flags & 0xFFFF) == 2) + return SIM_LAYER_OVERLAY; + else + return U32_MAX; +} + +// 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: @@ -96,17 +137,17 @@ public: LLVector3 getLocalPos(LLVector3d global_pos) const; 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 - LLPointer getLandForSaleImage(); // Get the overlay image, fetch it if necessary + void dropImagePriority(sim_layer_type layer = SIM_LAYER_COUNT); // 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 + // Setters void setName(std::string& name) { mName = name; } - void setSize(U16 sizeX, U16 sizeY) { mSizeX = sizeX; mSizeY = sizeY; } - void setAccess (U8 accesscode) { mAccess = accesscode; } + void setAccess (U32 accesscode) { mAccess = accesscode; } void setRegionFlags (U32 region_flags) { mRegionFlags = region_flags; } - void setWaterHeight (F32 water_height) { mWaterHeight = water_height; } + void setSize(U16 sizeX, U16 sizeY) { mSizeX = sizeX; mSizeY = sizeY; } void setAlpha(F32 alpha) { mAlpha = alpha; } + void setLandForSaleImage (LLUUID image_id); void setMapImageID (const LLUUID& id, const U8 &layer) { mMapImageID[layer] = id; } // Accessors @@ -115,43 +156,73 @@ public: const U32 getRegionFlags() const { return mRegionFlags; } const std::string getAccessString() const { return LLViewerRegion::accessToString((U8)mAccess); } const U8 getAccess() const { return mAccess; } + const S32 getAgentCount() const; // Compute the total agents count + LLPointer getLandForSaleImage(); // Get the overlay image, fetch it if necessary - const F32 getWaterHeight() const { return mWaterHeight; } const F32 getAlpha() const { return mAlpha; } - const U64 getHandle() const { return mHandle; } const U16 getSizeX() const { return mSizeX; } const U16 getSizeY() const { return mSizeY; } bool isName(const std::string& name) const; bool isDown() { return (mAccess == SIM_ACCESS_DOWN); } bool isPG() { return (mAccess <= SIM_ACCESS_PG); } bool isAdult() { return (mAccess == SIM_ACCESS_ADULT); } + + // Debug only + void dump() const; // Print the region info to the standard output + + // Items lists handling + typedef std::vector 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; } + private: U64 mHandle; std::string mName; F64 mAgentsUpdateTime; // Time stamp giving the last time the agents information was requested for that region bool mFirstAgentRequest; // Init agent request flag - U8 mAccess; + + U32 mAccess; // Down/up and maturity rating of the region U32 mRegionFlags; - F32 mWaterHeight; U16 mSizeX; U16 mSizeY; F32 mAlpha; public: - BOOL mShowAgentLocations; // are agents visible? - - // Image ID for the current overlay mode. - LLUUID mMapImageID[MAP_SIM_IMAGE_TYPES]; - - // Hold a reference to the currently displayed image. - LLPointer mCurrentImage; - LLPointer mOverlayImage; + // Handling the "land for sale / land for auction" overlay image + LLUUID mMapImageID[SIM_LAYER_COUNT]; // Image ID of the overlay image + LLPointer mLayerImage[SIM_LAYER_COUNT]; + + // 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 }; -#define MAP_BLOCK_RES 256 - struct LLWorldMapLayer { BOOL LayerDefined; @@ -162,6 +233,11 @@ struct LLWorldMapLayer LLWorldMapLayer() : LayerDefined(FALSE) { } }; +// 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 { @@ -175,135 +251,103 @@ public: // clears the list void reset(); - // clear the visible items - void eraseItems(); - - // Removes references to cached images - void clearImageRefs(); - - // Clears the flags indicating that we've received sim infos - // Causes a re-request of the sim info without erasing extisting info - void clearSimFlags(); - - // Drops the priority of the images being fetched - void dropImagePriorities(); + 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...) // Region Map access typedef std::map sim_info_map_t; const LLWorldMap::sim_info_map_t& getRegionMap() const { return mSimInfoMap; } - // Returns simulator information, or NULL if out of range + void updateRegions(S32 x0, S32 y0, S32 x1, S32 y1); // Requests region info for a rectangle of regions (in grid coordinates) + + // 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, U32 x_size, U32 y_size, U32 agent_flags, std::string& name, LLUUID& image_id, 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); + + // 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 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**); - + static void gotMapServerURL(bool flag) { sGotMapURL = flag; } static bool useWebMapTiles(); - static LLPointer loadObjectsTile(U32 grid_x, U32 grid_y); 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); + // Track handling + void cancelTracking() { mIsTrackingLocation = false; mIsTrackingFound = false; mIsInvalidLocation = false; mIsTrackingDoubleClick = false; mIsTrackingCommit = false; } - // build coverage maps for telehub region visualization - void updateTelehubCoverage(); - BOOL coveredByTelehub(LLSimInfo* infop); + 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; } + + 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; } + + std::vector::iterator getMapLayerBegin() { return mMapLayers.begin(); } + std::vector::iterator getMapLayerEnd() { return mMapLayers.end(); } + std::map >::const_iterator findMapBlock(U32 layer, U32 x, U32 y) const + { return LLWorldMap::instance().mMapBlockMap[layer].find((x<<16)|y); } + std::map >::const_iterator getMapBlockEnd(U32 layer) const + { return LLWorldMap::instance().mMapBlockMap[layer].end(); } - // Bounds of the world, in meters - U32 getWorldWidth() const; - U32 getWorldHeight() const; - // World Mipmap delegation: currently used when drawing the mipmap void equalizeBoostLevels(); LLPointer getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load = true) { return mWorldMipmap.getObjectsTile(grid_x, grid_y, level, load); } + static void processMapLayerReply(LLMessageSystem*, void**); private: 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 simulator info sim_info_map_t mSimInfoMap; -public: + // Request legacy background layers. + void sendMapLayerRequest(); - BOOL mIsTrackingUnknownLocation, mInvalidLocation, mIsTrackingDoubleClick, mIsTrackingCommit; - LLVector3d mUnknownLocation; - - bool mRequestLandForSale; - - typedef std::vector 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 mNumAgents; - - typedef std::map agent_list_map_t; - agent_list_map_t mAgentLocationsMap; - - std::vector 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; + std::vector mMapLayers; + bool mMapLoaded; private: 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[MAP_SIM_IMAGE_TYPES]; // Telling us if the block of regions has been requested or not + std::map > mMapBlockMap[SIM_LAYER_COUNT]; + + // 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; - - // search for named region for url processing - std::string mSLURLRegionName; - U64 mSLURLRegionHandle; - std::string mSLURL; - url_callback_t mSLURLCallback; - bool mSLURLTeleport; - + bool mFirstRequest; + static bool sGotMapURL; }; diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp new file mode 100644 index 000000000..b25a3db75 --- /dev/null +++ b/indra/newview/llworldmapmessage.cpp @@ -0,0 +1,301 @@ +/** + * @file llworldmapmessage.cpp + * @brief Handling of the messages to the DB made by and for the world map. + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llworldmapmessage.h" +#include "message.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 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_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, LAYER_FLAG); +} + +// public +void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent, S32 layer) +{ + //LL_INFOS("World Map") << "LLWorldMap::sendMapBlockRequest()" << ", min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << "), nonexistent = " << return_nonexistent << LL_ENDL; + 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(); +} + +// public static +void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) +{ + U32 agent_flags; + msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); + + U32 layer = flagsToLayer(agent_flags); + if (layer >= SIM_LAYER_COUNT) + { + 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; blockgetU16Fast(_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); + if(msg->getNumberOfBlocksFast(_PREHASH_Size) > 0) + { + msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeX, x_size, block); + msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeY, y_size, block); + } + if(x_size == 0 || (x_size % 16) != 0|| (y_size % 16) != 0) + { + x_size = 256; + y_size = 256; + } + + U32 x_world = (U32)(x_regions) * REGION_WIDTH_UNITS; + U32 y_world = (U32)(y_regions) * REGION_WIDTH_UNITS; + + // name shouldn't be empty, see EXT-4568 + //llassert(!name.empty()); + + //Opensim bug. BlockRequest can return sims without names, with an accesscode that isn't 255. + // skip if this has happened. + if(name.empty() && accesscode != 255) + continue; + + // Insert that region in the world map, if failure, flag it as a "null_sim" + if (!(LLWorldMap::getInstance()->insertRegion(x_world, y_world, x_size, y_size, agent_flags, 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 + url_callback_t callback = LLWorldMapMessage::getInstance()->mSLURLCallback; + if(callback != 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)) + { + LLWorldMapMessage::getInstance()->mSLURLCallback = NULL; + LLWorldMapMessage::getInstance()->mSLURLRegionName.clear(); + LLWorldMapMessage::getInstance()->mSLURLRegionHandle = 0; + + callback(handle, LLWorldMapMessage::getInstance()->mSLURL, image_id, LLWorldMapMessage::getInstance()->mSLURLTeleport); + } + } + if( gAgent.mPendingLure && + (U16)(gAgent.mPendingLure->mPosGlobal.mdV[0] / REGION_WIDTH_UNITS) == x_regions && + (U16)(gAgent.mPendingLure->mPosGlobal.mdV[1] / REGION_WIDTH_UNITS) == y_regions ) + { + gAgent.onFoundLureDestination(); + } + } + // 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; blockgetU32Fast(_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); + } +} +void LLWorldMapMessage::handleSLURL(std::string& name, U32 x_world, U32 y_world, LLUUID image_id) +{ + // Handle the SLURL callback if any + url_callback_t callback = LLWorldMapMessage::getInstance()->mSLURLCallback; + if(callback != 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)) + { + LLWorldMapMessage::getInstance()->mSLURLCallback = NULL; + LLWorldMapMessage::getInstance()->mSLURLRegionName.clear(); + LLWorldMapMessage::getInstance()->mSLURLRegionHandle = 0; + + callback(handle, LLWorldMapMessage::getInstance()->mSLURL, image_id, LLWorldMapMessage::getInstance()->mSLURLTeleport); + } + } +} + diff --git a/indra/newview/llworldmapmessage.h b/indra/newview/llworldmapmessage.h new file mode 100644 index 000000000..bd4bd7545 --- /dev/null +++ b/indra/newview/llworldmapmessage.h @@ -0,0 +1,79 @@ +/** + * @file llworldmapmessage.h + * @brief Handling of the messages to the DB made by and for the world map. + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#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 +{ +public: + typedef boost::function + 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, S32 layer = 2); + + // 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); + + void handleSLURL(std::string& name, U32 x_world, U32 y_world, LLUUID image_id); + +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 f8269833b..038b4ae33 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -109,8 +109,6 @@ 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; @@ -124,11 +122,18 @@ F32 CONE_SIZE = 0.6f; std::map LLWorldMapView::sStringsMap; -const int SIM_NULL_MAP_SCALE=4; // width in pixels, where we start drawing "null" sims +F32 DRAW_TEXT_THRESHOLD = 96.f; + const int SIM_MAP_AGENT_SCALE=8; // width in pixels, where we start drawing agents -const int SIM_MAP_SCALE=4; // width in pixels, where we start drawing sim tiles +const int SIM_DATA_SCALE=12; // width in pixels where we start requesting sim info const int SIM_LANDFORSALE_SCALE=32; +const int SIM_COMPOSITE_SCALE=2; // width in pixels, where we start drawing sim tiles. (legacy tiling method) +const int SIM_FETCH_SCALE=SIM_DATA_SCALE; // width in pixels, where we start requesting sim tile textures. (legacy tiling method) + +// When on, draw an outline for each mipmap tile gotten from S3 +#define DEBUG_DRAW_TILE 0 + void LLWorldMapView::initClass() { @@ -241,6 +246,7 @@ LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect ) LLWorldMapView::~LLWorldMapView() { + //LL_INFOS("World Map") << "Destroying the map -> LLWorldMapView::~LLWorldMapView()" << LL_ENDL; cleanupTextures(); } @@ -254,6 +260,10 @@ void LLWorldMapView::cleanupTextures() // static void LLWorldMapView::setScale( F32 scale ) { + if(!LLWorldMap::useWebMapTiles()) //adjust the scale range if drawing legacy tiles to avoid drawing a bajillion 1x1 tiles. + { + scale = SIM_COMPOSITE_SCALE + scale*((256.f-SIM_COMPOSITE_SCALE)/256.f); + } if (scale != sMapScale) { F32 old_scale = sMapScale; @@ -306,7 +316,7 @@ void LLWorldMapView::setPan( S32 x, S32 y, BOOL snap ) BOOL is_agent_in_region(LLViewerRegion* region, LLSimInfo* info) { - return ((region && info) && (info->isName(region->getName()))); + return (region && info && info->isName(region->getName())); } @@ -337,7 +347,6 @@ void LLWorldMapView::draw() gGL.matrixMode(LLRender::MM_MODELVIEW); // Clear the background alpha to 0 - gGL.flush(); gGL.setColorMask(false, true); gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f); gGL.setSceneBlendType(LLRender::BT_REPLACE); @@ -345,22 +354,29 @@ void LLWorldMapView::draw() gl_rect_2d(0, height, width, 0); } - gGL.flush(); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setColorMask(true, true); gGL.setSceneBlendType(LLRender::BT_ALPHA); - if(gHippoGridManager->getConnectedGrid()->isSecondLife()) + static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); + if(LLWorldMap::useWebMapTiles()) drawMipmap(width, height); else - drawTiles(width, height); - gGL.flush(); - LLFontGL* font = LLFontGL::getFontSansSerifSmall(); + drawLegacyBackgroundLayers(width, height); - - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gGL.setColorMask(true, true); + //Singu Note: This is done before drawing the transparent offline overlay. drawMipmap doesn't actually + // fill every possible block on the minimap. Every space must be filled for the offline overlay to look correct. + // Draw background rectangle + LLGLSUIDefault gls_ui; + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f); + gGL.blendFunc(LLRender::BF_ONE_MINUS_DEST_ALPHA, LLRender::BF_DEST_ALPHA); + gGL.color4fv( mBackgroundColor.mV ); + gl_rect_2d(0, height, width, 0); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + } // Draw the region name in the lower left corner for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin(); @@ -368,7 +384,7 @@ void LLWorldMapView::draw() { U64 handle = it->first; LLSimInfo* info = it->second; - + LLVector3d origin_global = from_region_handle(handle); // Find x and y position relative to camera's center. @@ -380,27 +396,104 @@ void LLWorldMapView::draw() // 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 + sMapScale ; - //F32 right = left + sMapScale ; + F32 top = bottom + sMapScale * ((F32)info->getSizeY() / REGION_WIDTH_METERS); + F32 right = left + sMapScale * ((F32)info->getSizeX() / REGION_WIDTH_METERS); + + // Discard if region is outside the screen rectangle (not visible on screen) + if ((top < 0.f) || (bottom > height) || + (right < 0.f) || (left > width) ) + { + // Drop the "land for sale" fetching priority since it's outside the view rectangle + info->dropImagePriority(); + continue; + } + + // This list is used by other methods to know which regions are indeed displayed on screen + + mVisibleRegions.push_back(handle); - info->mShowAgentLocations = (sMapScale >= SIM_MAP_AGENT_SCALE); - mVisibleRegions.push_back(handle); // Update the agent count for that region if we're not too zoomed out already if (sMapScale >= SIM_MAP_AGENT_SCALE) { info->updateAgentCount(current_time); } - std::string mesg; - if (sMapScale < sThresholdA) + F32 alpha = !LLWorldMap::useWebMapTiles() ? drawLegacySimTile(*info,left,top,right,bottom) : 1.f; + + if (info->isDown()) { + // Draw a transparent red square over down sims + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA); + gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f); + + 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.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); } - else if (sMapScale < sThresholdB) + // 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. + /********************** + else if (!info->isPG() && gAgent.isTeen()) { - // mesg = llformat( info->mAgents); + // 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); + gGL.vertex2f(left, top); + gGL.vertex2f(right, bottom); + gGL.vertex2f(left, bottom); + gGL.vertex2f(right, top); + gGL.end(); + } + **********************/ + else if (map_show_land_for_sale && (sMapScale >= SIM_LANDFORSALE_SCALE)) + { + // 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] * ((F32)info->getSizeX() / REGION_WIDTH_METERS)), + llround(draw_size * LLUI::sGLScaleFactor.mV[VY] * ((F32)info->getSizeY() / REGION_WIDTH_METERS))); + // Draw something whenever we have enough info + if (overlayimage->hasGLTexture() && !overlayimage->isMissingAsset() && overlayimage->getID() != IMG_DEFAULT) + { + 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(); + } + } } else { + // If we're not displaying the "land for sale", drop fetching priority of both. + info->dropImagePriority(SIM_LAYER_OVERLAY); + } + + // Draw the region name in the lower left corner + if (sMapScale >= DRAW_TEXT_THRESHOLD) + { + LLFontGL* font = LLFontGL::getFontSansSerifSmall(); + std::string mesg; + //mesg = llformat("%d / %s (%s)", // info->mAgents, // info->mName.c_str(), @@ -408,14 +501,18 @@ void LLWorldMapView::draw() // [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-04 (RLVa-1.0.0a) if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) { - mesg = RlvStrings::getString(RLV_STRING_HIDDEN); + if(!info->getName().empty()) + mesg = RlvStrings::getString(RLV_STRING_HIDDEN); } // [/RLVa:KB] else if (info->isDown()) { - mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str()); + if(info->getName().empty()) + mesg = llformat( "(%s)", sStringsMap["offline"].c_str()); + else + mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str()); } - else + else if(!info->getName().empty()) // Online sims should have names... { mesg = info->getName(); U8 access = info->getAccess(); @@ -438,91 +535,151 @@ void LLWorldMapView::draw() break; } } - } - - 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), - LLColor4::white, - LLFontGL::LEFT, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); - }*/ + mesg, 0, + llfloor(left + 3), llfloor(bottom + 2), + LLColor4::white, + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); + } } + } - } - - - // Draw background rectangle - LLGLSUIDefault gls_ui; + static const LLCachedControl map_show_requests("MapShowRequests", false); + if(map_show_requests) { + const F32 map_to_pixels = MAP_MAX_SIZE*sMapScale; + const F32 block_to_pixels = MAP_BLOCK_SIZE*sMapScale; + const F32 padding = .25f*sMapScale; + + //In sim coords. + const F32 centerX = -sPanX/sMapScale + camera_global.mdV[VX]/REGION_WIDTH_METERS; + const F32 centerY = -sPanY/sMapScale + camera_global.mdV[VY]/REGION_WIDTH_METERS; + const F32 bottom = centerY - half_height/sMapScale ; + const F32 left = centerX - half_width/sMapScale ; + const F32 top = centerY + half_height/sMapScale ; + const F32 right = centerX + half_width/sMapScale ; + + const U32 max_range = (U16_MAX+1)/MAP_BLOCK_RES/MAP_BLOCK_SIZE - 1; + const U32 map_block_x0 = (U32)(llmax(left,0.f) / MAP_MAX_SIZE); + const U32 map_block_x1 = llclamp(U32(right / MAP_MAX_SIZE), U32(0), max_range); + const U32 map_block_y0 = (U32)(llmax(bottom,0.f) / MAP_MAX_SIZE); + const U32 map_block_y1 = llclamp(U32(top / MAP_MAX_SIZE), U32(0), max_range); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f); - gGL.blendFunc(LLRender::BF_ONE_MINUS_DEST_ALPHA, LLRender::BF_DEST_ALPHA); - gGL.color4fv( mBackgroundColor.mV ); - gl_rect_2d(0, height, width, 0); + + for(U32 i = map_block_x0; i <= map_block_x1; ++i) + { + const F32 base_left = i*map_to_pixels-left*sMapScale; + const F32 base_right = base_left + map_to_pixels; + if( base_right <= 0.f) + continue; + if( base_left >= width) + break; + for (U32 j = map_block_y0; j <= map_block_y1; ++j) + { + const F32 base_bottom = j*map_to_pixels-bottom*sMapScale; + const F32 base_top = base_bottom + map_to_pixels; + if( base_top <= 0.f) + continue; + if( base_bottom >= height) + break; + + std::map >::const_iterator it = LLWorldMap::getInstance()->findMapBlock(SIM_LAYER_OVERLAY,i,j); + + if(it != LLWorldMap::getInstance()->getMapBlockEnd(SIM_LAYER_OVERLAY)) + gGL.color4f(0.5f, 0.0f, 0.0f, 0.4f); + else + gGL.color4f(0.2f, .2f, 0.2f, 0.4f); + gGL.begin(LLRender::QUADS); + gGL.vertex2f(base_left+padding, base_top-padding); + gGL.vertex2f(base_left+padding, base_bottom+padding); + gGL.vertex2f(base_right-padding, base_bottom+padding); + gGL.vertex2f(base_right-padding, base_top-padding); + gGL.end(); + if(it != LLWorldMap::getInstance()->getMapBlockEnd(SIM_LAYER_OVERLAY)) + { + for(U32 x=0;x= width) + break; + for(U32 y=0;y= height) + break; + if(it->second[x | (y * MAP_BLOCK_RES)]) + gGL.color4f(0.0f, 0.5f, 0.0f, 0.4f); + else + gGL.color4f(0.4f, 0.0f, 0.0f, 0.4f); + gGL.begin(LLRender::QUADS); + gGL.vertex2f(block_left+padding, block_top-padding); + gGL.vertex2f(block_left+padding, block_bottom+padding); + gGL.vertex2f(block_right-padding, block_bottom+padding); + gGL.vertex2f(block_right-padding, block_top-padding); + gGL.end(); + + for(U32 sim_x=0;sim_x map_show_infohubs("MapShowInfohubs"); - if (map_show_infohubs) //(sMapScale >= sThresholdB) - { - drawGenericItems(LLWorldMap::getInstance()->mInfohubs, sInfohubImage); - } - - // Telehubs static const LLCachedControl map_show_telehubs("MapShowTelehubs"); - if (map_show_telehubs) //(sMapScale >= sThresholdB) + static const LLCachedControl map_show_mature_events("MapShowMatureEvents"); + static const LLCachedControl map_show_adult_events("MapShowAdultEvents"); + if(sMapScale >= DRAW_TEXT_THRESHOLD && (map_show_infohubs || + map_show_telehubs || + map_show_land_for_sale || + map_show_mature_events || + map_show_adult_events)) { - drawGenericItems(LLWorldMap::getInstance()->mTelehubs, sTelehubImage); + drawItems(); } - // Home Sweet Home + // Draw the Home location (always) LLVector3d home; if (gAgent.getHomePosGlobal(&home)) { drawImage(home, sHomeImage); } - static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); - if (map_show_land_for_sale) - { - 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); - } - } - - 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, sAvatarYouImage); @@ -543,7 +700,7 @@ void LLWorldMapView::draw() // Draw icons for the avatars in each region. // Drawn after your avatar so you can see nearby people. static const LLCachedControl map_show_people("MapShowPeople"); - if (map_show_people) + if (map_show_people && sMapScale >= SIM_MAP_AGENT_SCALE) { drawAgents(); } @@ -565,23 +722,33 @@ void LLWorldMapView::draw() drawTracking( pos_global, gTrackColor, 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, "Invalid Location", ""); + drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, LLTrans::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, "Loading...", ""); + drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, LLTrans::getString("LoadingData"), ""); } } // #endif used to be here + + //Provide some feedback, because nothing will load if zoomed far out on the map when using legacy sim drawing. + if(!LLWorldMap::useWebMapTiles() && (sMapScale < SIM_FETCH_SCALE || sMapScale < SIM_DATA_SCALE)) + { + LLFontGL::getFontSansSerifSmall()->renderUTF8("(Zoom to resume loading)", 0, + width-2, LLFontGL::getFontSansSerifSmall()->getLineHeight()*1.5f, + LLColor4::white, + LLFontGL::RIGHT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); + } // turn off the scissor LLGLDisable no_scissor(GL_SCISSOR_TEST); @@ -591,6 +758,8 @@ void LLWorldMapView::draw() LLView::draw(); updateVisibleBlocks(); + + gGL.flush(); } // end draw() @@ -600,63 +769,50 @@ void LLWorldMapView::setVisible(BOOL visible) LLPanel::setVisible(visible); if (!visible) { - for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; map++) - { - for (U32 layer_idx=0; layer_idxmMapLayers[map].size(); ++layer_idx) - { - if (LLWorldMap::getInstance()->mMapLayers[map][layer_idx].LayerDefined) - { - LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[map][layer_idx]; - layer->LayerImage->setBoostLevel(0); - } - } - } - for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin(); - it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + std::vector::iterator begin = LLWorldMap::getInstance()->getMapLayerBegin(); + std::vector::iterator end = LLWorldMap::getInstance()->getMapLayerEnd(); + for(std::vector::iterator it = begin; it != end; ++it) { - LLSimInfo* info = (*it).second; - if (info->mCurrentImage.notNull()) + if (it->LayerDefined) { - info->mCurrentImage->setBoostLevel(0); - } - if (info->mOverlayImage.notNull()) - { - info->mOverlayImage->setBoostLevel(0); + it->LayerImage->setBoostLevel(0); } } + // Drop the download of tiles and images priority to nil if we hide the map + LLWorldMap::getInstance()->dropImagePriorities(); } } -void LLWorldMapView::drawTiles(S32 width, S32 height) { +void LLWorldMapView::drawLegacyBackgroundLayers(S32 width, S32 height) { const F32 half_width = F32(width) / 2.0f; const F32 half_height = F32(height) / 2.0f; - F32 layer_alpha = 1.f; LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); - // Draw one image per layer - for (U32 layer_idx=0; layer_idxmMapLayers[LLWorldMap::getInstance()->mCurrentMap].size(); ++layer_idx) + std::vector::const_iterator begin = LLWorldMap::getInstance()->getMapLayerBegin(); + std::vector::const_iterator end = LLWorldMap::getInstance()->getMapLayerEnd(); + for (std::vector::const_iterator it = begin; it != end; ++it) { - if (!LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx].LayerDefined) + if (!it->LayerDefined) { continue; } - LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx]; - LLViewerTexture *current_image = layer->LayerImage; + const LLWorldMapLayer& layer = *it; + LLViewerTexture *current_image = layer.LayerImage; - if (current_image->isMissingAsset()) + if (!current_image || current_image->isMissingAsset() || current_image->getID() == IMG_DEFAULT) { 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); + 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) * sMapScale; F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale; - F32 pix_width = sMapScale*(layer->LayerExtents.getWidth() + 1); - F32 pix_height = sMapScale*(layer->LayerExtents.getHeight() + 1); + F32 pix_width = sMapScale*(layer.LayerExtents.getWidth() + 1); + F32 pix_height = sMapScale*(layer.LayerExtents.getHeight() + 1); // When the view isn't panned, 0,0 = center of rectangle F32 bottom = sPanY + half_height + relative_y; @@ -676,11 +832,11 @@ void LLWorldMapView::drawTiles(S32 width, S32 height) { continue; } - current_image->setBoostLevel(LLViewerTexture::BOOST_MAP_VISIBLE); + 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()) + if (!current_image->hasGLTexture()) //Still loading. { continue; // better to draw nothing than the default image } @@ -692,11 +848,8 @@ void LLWorldMapView::drawTiles(S32 width, S32 height) { 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.color4f(1.f, 1.f, 1.f, 1.f); gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.0f, 1.0f); gGL.vertex3f(left, top, -1.0f); @@ -707,9 +860,7 @@ void LLWorldMapView::drawTiles(S32 width, S32 height) { 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); @@ -723,458 +874,78 @@ void LLWorldMapView::drawTiles(S32 width, S32 height) { gGL.texCoord2f(1.0f, 1.0f); gGL.vertex2f(right, top); gGL.end(); + + gGL.setColorMask(true, true); } +} - gGL.flush(); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gGL.setColorMask(true, true); - - F32 sim_alpha = 1.f; - - // Draw one image per region, centered on the camera position. +F32 LLWorldMapView::drawLegacySimTile(LLSimInfo& sim_info, S32 left, S32 top, S32 right, S32 bottom) +{ + const F32 ALPHA_CUTOFF = 0.001f; 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; + LLViewerFetchedTexture* simimage = sim_info.mLayerImage[SIM_LAYER_COMPOSITE]; - bool use_web_map_tiles = LLWorldMap::useWebMapTiles(); - - for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin(); - it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) + const bool sim_visible = sMapScale >= SIM_COMPOSITE_SCALE; + const bool sim_fetchable = sMapScale >= SIM_FETCH_SCALE; + + if(sim_fetchable) { - U64 handle = (*it).first; - LLSimInfo* info = (*it).second; - - LLViewerTexture* simimage = info->mCurrentImage; - LLViewerTexture* overlayimage = info->mOverlayImage; - - if (sMapScale < 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 = gAgentCamera.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) * sMapScale; - F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale; - - // 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 + sMapScale * ((F32)info->getSizeY() / 256.f); - F32 right = left + sMapScale * ((F32)info->getSizeX() / 256.f); - - // 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 0 // This is always false, as REGION_FLAGS_NULL_LAYER doesn't exist anymore - if ((info->getRegionFlags() & REGION_FLAGS_NULL_LAYER) > 0) - { - map_scale_cutoff = SIM_NULL_MAP_SCALE; - } -#endif - - bool sim_visible = - (sMapScale >= map_scale_cutoff) && - (simimage != NULL) && - (simimage->hasGLTexture()); - - if (sim_visible) - { - // Fade in - if (info->getAlpha() < 0.0f) - info->setAlpha( 1.f ); // don't fade initially - else - info->setAlpha(lerp(info->getAlpha(), 1.f, LLCriticalDamp::getInterpolant(0.15f))); - } - else - { - // Fade out - if (info->getAlpha() < 0.0f) - info->setAlpha( 0.f ); // don't fade initially - else - info->setAlpha(lerp(info->getAlpha(), 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 ) - { - if (simimage != NULL) simimage->setBoostLevel(0); - if (overlayimage != NULL) overlayimage->setBoostLevel(0); - continue; - } - - if (info->mCurrentImage.isNull()) + if (!simimage && sim_info.mMapImageID[SIM_LAYER_COMPOSITE].notNull() && sim_info.mMapImageID[SIM_LAYER_COMPOSITE] != IMG_DEFAULT) { 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++; - if (use_web_map_tiles && info->getSizeX() == REGION_WIDTH_UNITS && - info->getSizeY() == REGION_WIDTH_UNITS) - { - LLVector3d region_pos = info->getGlobalOrigin(); - info->mCurrentImage = LLWorldMap::loadObjectsTile((U32)(region_pos.mdV[VX] / REGION_WIDTH_UNITS), (U32)(region_pos.mdV[VY] / REGION_WIDTH_UNITS)); - } - else - { - info->mCurrentImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE); - } - 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); - info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); - overlayimage = info->mOverlayImage; - gGL.getTexUnit(0)->bind(overlayimage); + simimage = sim_info.mLayerImage[SIM_LAYER_COMPOSITE] = LLViewerTextureManager::getFetchedTexture(sim_info.mMapImageID[SIM_LAYER_COMPOSITE], MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + simimage->setAddressMode(LLTexUnit::TAM_CLAMP); } } + } - // Bias the priority escalation for images nearer - LLVector3d center_global = origin_global; - center_global.mdV[VX] += 128.0; - center_global.mdV[VY] += 128.0; + const bool sim_drawable = simimage && !simimage->isMissingAsset() && simimage->getID() != IMG_DEFAULT; + const bool sim_fetching = sim_drawable && !simimage->hasGLTexture(); + const F32 fade_target = sim_visible ? 1.f : 0.f; + //Logic is a bit confusing here. Basically, we want to fade out on zoom-out, and fade in on either zoom-in OR texture has finished fetching. + //However, we instantly hide the tile if the texture is invalid or hasn't loaded. The tile never would have been visible before this, anyhow. + if (!sim_drawable || sim_fetching) + sim_info.setAlpha( 0.f ); + else if (llabs(sim_info.getAlpha() - fade_target) > ALPHA_CUTOFF) //This gives us a nice fade when a visible sims texture finishes loading, or visiblity has changed. + sim_info.setAlpha(lerp(sim_info.getAlpha(), fade_target, LLCriticalDamp::getInterpolant(0.15f))); + F32 alpha = sim_info.getAlpha(); + + //call setKnownDrawSize if image is still loading, or its actually being drawn. + if(sim_fetching || alpha >= ALPHA_CUTOFF) + { S32 draw_size = llround(sMapScale); - if (simimage != NULL) + simimage->setKnownDrawSize( llround(draw_size * LLUI::sGLScaleFactor.mV[VX] * ((F32)sim_info.getSizeX() / REGION_WIDTH_METERS)), + llround(draw_size * LLUI::sGLScaleFactor.mV[VY] * ((F32)sim_info.getSizeY() / REGION_WIDTH_METERS))); + simimage->setBoostLevel(LLViewerTexture::BOOST_MAP); + if(alpha >= ALPHA_CUTOFF) { - simimage->setBoostLevel(LLViewerTexture::BOOST_MAP); - simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX] * ((F32)info->getSizeX() / REGION_WIDTH_UNITS)), - llround(draw_size * LLUI::sGLScaleFactor.mV[VY] * ((F32)info->getSizeY() / REGION_WIDTH_UNITS))); - } - - if (overlayimage != NULL) - { - overlayimage->setBoostLevel(LLViewerTexture::BOOST_MAP); - overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX] * ((F32)info->getSizeX() / REGION_WIDTH_UNITS)), - llround(draw_size * LLUI::sGLScaleFactor.mV[VY] * ((F32)info->getSizeY() / REGION_WIDTH_UNITS))); - } - -// LLTextureView::addDebugImage(simimage); - - if (sim_visible && info->getAlpha() > 0.001f) - { - // 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->getAlpha(); - gGL.color4f(1.f, 1.0f, 1.0f, alpha); - + gGL.getTexUnit(0)->bind(simimage); + gGL.color4f(1.f, 1.f, 1.f, alpha); gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); - gGL.vertex3f(left, top, 0.f); + gGL.vertex2f(left, top); gGL.texCoord2f(0.f, 0.f); - gGL.vertex3f(left, bottom, 0.f); + gGL.vertex2f(left, bottom); gGL.texCoord2f(1.f, 0.f); - gGL.vertex3f(right, bottom, 0.f); + gGL.vertex2f(right, bottom); gGL.texCoord2f(1.f, 1.f); - gGL.vertex3f(right, top, 0.f); - gGL.end(); - - static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); - if (map_show_land_for_sale && 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 (true /*V3: REGION_FLAGS_NULL_LAYER doesn't exist... (info->getRegionFlags() & 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); - } - } - - if (info->isDown()) - { - // Draw a transparent red square over down sims - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA); - gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f); - - 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(); } - - // 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()) - { - 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); - gGL.vertex2f(left, top); - gGL.vertex2f(right, bottom); - gGL.vertex2f(left, bottom); - gGL.vertex2f(right, top); - gGL.end(); - } - **********************/ } -} - -void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image) -{ - LLWorldMap::item_info_list_t::const_iterator e; - for (e = items.begin(); e != items.end(); ++e) + else //Either the texture is invalid or view has zoomed out far enough and the sim has fully faded away. { - drawGenericItem(*e, image); + sim_info.dropImagePriority(SIM_LAYER_COMPOSITE); } -} - -void LLWorldMapView::drawGenericItem(const LLItemInfo& item, LLUIImagePtr image) -{ - drawImage(item.getGlobalPosition(), image); -} - - -void LLWorldMapView::drawImage(const LLVector3d& global_pos, LLUIImagePtr image, const LLColor4& color) -{ - LLVector3 pos_map = globalPosToView( global_pos ); - image->draw(llround(pos_map.mV[VX] - image->getWidth() /2.f), - llround(pos_map.mV[VY] - image->getHeight()/2.f), - color); -} - -void LLWorldMapView::drawImageStack(const LLVector3d& global_pos, LLUIImagePtr image, U32 count, F32 offset, const LLColor4& color) -{ - LLVector3 pos_map = globalPosToView( global_pos ); - for(U32 i=0; idraw(llround(pos_map.mV[VX] - image->getWidth() /2.f), - llround(pos_map.mV[VY] - image->getHeight()/2.f + i*offset), - color); - } -} - - -void LLWorldMapView::drawAgents() -{ - if(sMapScale < SIM_MAP_AGENT_SCALE) - return; - - F32 agents_scale = (sMapScale * 0.9f) / 256.f; - - LLColor4 avatar_color = gColors.getColor( "MapAvatar" ); - // LLColor4 friend_color = gColors.getColor( "MapFriend" ); - - for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) - { - U64 handle = *iter; - LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); - if (siminfo && (siminfo->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()) - { - // 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)) ? friend_color : avatar_color; - drawImageStack(info.getGlobalPosition(), sAvatarSmallImage, agent_count, 3.f, avatar_color); - } - LLWorldMap::getInstance()->mNumAgents[handle] = sim_agent_count; // override mNumAgents for this sim - } - else - { - // Show agent 'stack' at center of sim - S32 num_agents = LLWorldMap::getInstance()->mNumAgents[handle]; - if (num_agents > 0) - { - 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, avatar_color); - } - } - } -} - - -void LLWorldMapView::drawEvents() -{ - bool mature_enabled = gAgent.canAccessMature(); - bool adult_enabled = gAgent.canAccessAdult(); - - static const LLCachedControl map_show_pg_events("MapShowPGEvents"); - static const LLCachedControl map_show_mature_events("MapShowMatureEvents"); - static const LLCachedControl map_show_adult_events("MapShowAdultEvents"); - - BOOL show_pg = map_show_pg_events; - BOOL show_mature = mature_enabled && map_show_mature_events; - BOOL show_adult = adult_enabled && map_show_adult_events; - - // First the non-selected events - LLWorldMap::item_info_list_t::const_iterator e; - if (show_pg) - { - for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e) - { - if (!e->mSelected) - { - drawGenericItem(*e, sEventImage); - } - } - } - 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) - { - if (e->mSelected) - { - drawGenericItem(*e, sEventImage); - } - } - } - 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 = sMapScale/ REGION_WIDTH_METERS; - - F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); - F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); - F32 far_clip_pixels = far_clip_meters * meters_to_pixels; - - F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 ); - F32 half_width_pixels = half_width_meters * meters_to_pixels; - - F32 ctr_x = getRect().getWidth() * 0.5f + sPanX; - F32 ctr_y = getRect().getHeight() * 0.5f + sPanY; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Since we don't rotate the map, we have to rotate the frustum. - gGL.pushMatrix(); - gGL.translatef( ctr_x, ctr_y, 0 ); - gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); - - // Draw triangle with more alpha in far pixels to make it - // fade out in distance. - gGL.begin( LLRender::TRIANGLES ); - gGL.color4f(1.f, 1.f, 1.f, 0.25f); - gGL.vertex2f( 0, 0 ); - - gGL.color4f(1.f, 1.f, 1.f, 0.02f); - gGL.vertex2f( -half_width_pixels, far_clip_pixels ); - - gGL.color4f(1.f, 1.f, 1.f, 0.02f); - gGL.vertex2f( half_width_pixels, far_clip_pixels ); - gGL.end(); - gGL.popMatrix(); + return alpha; } void LLWorldMapView::drawMipmap(S32 width, S32 height) @@ -1212,90 +983,6 @@ void LLWorldMapView::drawMipmap(S32 width, S32 height) // Render the current level sVisibleTilesLoaded = drawMipmapLevel(width, height, level); - const F32 half_width = F32(width) / 2.0f; - const F32 half_height = F32(height) / 2.0f; - LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); - - 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; - - LLVector3d origin_global = from_region_handle(handle); - - // 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) * 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 + 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) ) - { - // Drop the "land for sale" fetching priority since it's outside the view rectangle - info->dropImagePriority(); - continue; - } - - if (info->isDown()) - { - // Draw a transparent red square over down sims - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA); - gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f); - - 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(); - } - - if (gSavedSettings.getBOOL("MapShowLandForSale") && (sMapScale >= SIM_LANDFORSALE_SCALE)) - { - // 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() && !overlayimage->isMissingAsset()) - { - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - 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 we're not displaying the "land for sale", drop its fetching priority - info->dropImagePriority(); - } - } - return; } @@ -1348,13 +1035,13 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load F32 left = pos_screen[VX]; F32 bottom = pos_screen[VY]; // Compute the NE corner coordinates of the tile now - LLSimInfo* simInfo = LLWorldMap::instance().simInfoFromHandle(to_region_handle(grid_x, grid_y)); + /*LLSimInfo* simInfo = LLWorldMap::instance().simInfoFromHandle(to_region_handle(grid_x, grid_y)); if(simInfo != NULL) { pos_global[VX] += ((F32)tile_width * ((F32)simInfo->getSizeX() / REGION_WIDTH_METERS)); pos_global[VY] += ((F32)tile_width * ((F32)simInfo->getSizeY() / REGION_WIDTH_METERS)); } - else + else*/ { pos_global[VX] += tile_width; pos_global[VY] += tile_width; @@ -1367,10 +1054,7 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load 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); @@ -1385,6 +1069,7 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load drawTileOutline(level, top, left, bottom, right); #endif // DEBUG_DRAW_TILE } + //else } else { @@ -1398,6 +1083,206 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load 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(); + + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); +} + +void LLWorldMapView::drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image) +{ + LLSimInfo::item_info_list_t::const_iterator e; + for (e = items.begin(); e != items.end(); ++e) + { + drawGenericItem(*e, image); + } +} + +void LLWorldMapView::drawGenericItem(const LLItemInfo& item, LLUIImagePtr image) +{ + drawImage(item.getGlobalPosition(), image); +} + + +void LLWorldMapView::drawImage(const LLVector3d& global_pos, LLUIImagePtr image, const LLColor4& color) +{ + LLVector3 pos_map = globalPosToView( global_pos ); + image->draw(llround(pos_map.mV[VX] - image->getWidth() /2.f), + llround(pos_map.mV[VY] - image->getHeight()/2.f), + color); +} + +void LLWorldMapView::drawImageStack(const LLVector3d& global_pos, LLUIImagePtr image, U32 count, F32 offset, const LLColor4& color) +{ + LLVector3 pos_map = globalPosToView( global_pos ); + for(U32 i=0; idraw(llround(pos_map.mV[VX] - image->getWidth() /2.f), + llround(pos_map.mV[VY] - image->getHeight()/2.f + i*offset), + color); + } +} + +void LLWorldMapView::drawItems() +{ + bool mature_enabled = gAgent.canAccessMature(); + bool adult_enabled = gAgent.canAccessAdult(); + + static const LLCachedControl map_show_infohubs("MapShowInfohubs"); + static const LLCachedControl map_show_telehubs("MapShowTelehubs"); + static const LLCachedControl map_show_pg_events("MapShowPGEvents"); + static const LLCachedControl map_show_mature_events("MapShowMatureEvents"); + static const LLCachedControl map_show_adult_events("MapShowAdultEvents"); + static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); + + BOOL show_mature = mature_enabled && map_show_mature_events; + BOOL show_adult = adult_enabled && map_show_adult_events; + + for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) + { + U64 handle = *iter; + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if ((info == NULL) || (info->isDown())) + { + continue; + } + // Infohubs + if (map_show_infohubs) + { + drawGenericItems(info->getInfoHub(), sInfohubImage); + } + // Telehubs + if (map_show_telehubs) + { + drawGenericItems(info->getTeleHub(), sTelehubImage); + } + // Land for sale + if (map_show_land_for_sale) + { + 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()) + { + drawGenericItems(info->getLandForSaleAdult(), sForSaleAdultImage); + } + } + // PG Events + if (map_show_pg_events) + { + drawGenericItems(info->getPGEvent(), sEventImage); + } + // Mature Events + if (show_mature) + { + drawGenericItems(info->getMatureEvent(), sEventMatureImage); + } + // Adult Events + if (show_adult) + { + drawGenericItems(info->getAdultEvent(), sEventAdultImage); + } + } +} + +void LLWorldMapView::drawAgents() +{ + F32 agents_scale = (sMapScale * 0.9f) / 256.f; + + LLColor4 avatar_color = gColors.getColor( "MapAvatar" ); + // LLColor4 friend_color = gColors.getColor( "MapFriend" ); + + for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) + { + U64 handle = *iter; + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle); + if ((siminfo == NULL) || (siminfo->isDown())) + { + continue; + } + LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAgentLocation().begin(); + while (it != siminfo->getAgentLocation().end()) + { + // 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; + // Reduce the stack size as you zoom out - always display at lease one agent where there is one or more + S32 agent_count = (S32)(((it->getCount()-1) * agents_scale + (it->getCount()-1) * 0.1f)+.1f) + 1; + drawImageStack(it->getGlobalPosition(), sAvatarSmallImage, agent_count, 3.f, avatar_color); + ++it; + } + } +} + +void LLWorldMapView::drawFrustum() +{ + // Draw frustum + F32 meters_to_pixels = sMapScale/ REGION_WIDTH_METERS; + + F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); + F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); + F32 far_clip_pixels = far_clip_meters * meters_to_pixels; + + F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 ); + F32 half_width_pixels = half_width_meters * meters_to_pixels; + + F32 ctr_x = getRect().getWidth() * 0.5f + sPanX; + F32 ctr_y = getRect().getHeight() * 0.5f + sPanY; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // Since we don't rotate the map, we have to rotate the frustum. + gGL.pushMatrix(); + gGL.translatef( ctr_x, ctr_y, 0 ); + gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); + + // Draw triangle with more alpha in far pixels to make it + // fade out in distance. + gGL.begin( LLRender::TRIANGLES ); + gGL.color4f(1.f, 1.f, 1.f, 0.25f); + gGL.vertex2f( 0, 0 ); + + gGL.color4f(1.f, 1.f, 1.f, 0.02f); + gGL.vertex2f( -half_width_pixels, far_clip_pixels ); + + gGL.color4f(1.f, 1.f, 1.f, 0.02f); + gGL.vertex2f( half_width_pixels, far_clip_pixels ); + gGL.end(); + gGL.popMatrix(); +} LLVector3 LLWorldMapView::globalPosToView( const LLVector3d& global_pos ) { LLVector3d relative_pos_global = global_pos - gAgentCamera.getCameraPositionGlobal(); @@ -1468,9 +1353,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& text_x, text_y, LLColor4::white, LLFontGL::HCENTER, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); + LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); if (tooltip != "") { @@ -1481,9 +1364,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4& text_x, text_y, LLColor4::white, LLFontGL::HCENTER, - LLFontGL::BASELINE, - LLFontGL::NORMAL, - LLFontGL::DROP_SHADOW); + LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); } } } @@ -1517,8 +1398,9 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y ) BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen ) { LLVector3d pos_global = viewPosToGlobal(x, y); + U64 handle = to_region_handle(pos_global); - LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global); + LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); if (info) { LLViewerRegion *region = gAgent.getRegion(); @@ -1532,8 +1414,8 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic if (!info->isDown()) { - S32 agent_count = LLWorldMap::getInstance()->mNumAgents[info->getHandle()]; - if (region && region->getHandle() == info->getHandle()) + S32 agent_count = info->getAgentCount(); + if (region && (region->getHandle() == handle)) { ++agent_count; // Bump by 1 if we're here } @@ -1621,7 +1503,7 @@ static void drawDot(F32 x_pixels, F32 y_pixels, // static void LLWorldMapView::drawAvatar(F32 x_pixels, F32 y_pixels, - LLColor4 color, + const LLColor4& color, F32 relative_z, F32 dot_radius) { @@ -1932,7 +1814,7 @@ bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bo gFloaterWorldMap->trackGenericItem(item); } - item.mSelected = TRUE; +// item.mSelected = TRUE; *id = item.getUUID(); return true; @@ -1956,111 +1838,119 @@ 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) - { - (*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 static const LLCachedControl map_show_pg_events("MapShowPGEvents"); - if (map_show_pg_events) - { - 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; - } - } - } static const LLCachedControl map_show_mature_events("MapShowMatureEvents"); - if (map_show_mature_events) - { - 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; - } - } - } static const LLCachedControl map_show_adult_events("MapShowAdultEvents"); - if (map_show_adult_events) - { - 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; - } - } - } static const LLCachedControl map_show_land_for_sale("MapShowLandForSale"); - if (map_show_land_for_sale) - { - for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it) - { - LLItemInfo& land = *it; - 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) - { - LLItemInfo& land = *it; + if(sMapScale >= DRAW_TEXT_THRESHOLD) + { + bool show_mature = gAgent.canAccessMature() && map_show_mature_events; + bool show_adult = gAgent.canAccessAdult() && map_show_adult_events; - if (checkItemHit(x, y, land, id, true)) - { - *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT; - mItemPicked = TRUE; - return; - } + // Test hits if trackable data are displayed, otherwise, we don't even bother + if (map_show_pg_events || show_mature || show_adult || map_show_land_for_sale) + { + // Iterate through the visible regions + for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter) + { + 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 (map_show_pg_events) + { + 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 (map_show_land_for_sale) + { + 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; } @@ -2121,58 +2011,35 @@ 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]) - { -// 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++; - } - return blocks_requested; -} - -U32 LLWorldMapView::updateVisibleBlocks() -{ - if (sMapScale < SIM_MAP_SCALE) + if (sMapScale < SIM_DATA_SCALE) { // We don't care what is loaded if we're zoomed out - return 0; + return; } + // Load the blocks visible in the current World Map view + + // Get the World Map view coordinates and boundaries LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal(); - - F32 pixels_per_region = sMapScale; 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)); + const F32 half_width = F32(width) / 2.0f; + const F32 half_height = F32(height) / 2.0f; - // 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; + // 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)); - U32 blocks_requested = 0; - const U32 max_blocks_requested = 9; + // 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; - 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; + //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 ) @@ -2262,9 +2129,9 @@ 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 { diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index 97c79dddf..1df0bfba2 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -86,16 +86,17 @@ public: LLVector3d viewPosToGlobal(S32 x,S32 y); virtual void draw(); - void drawTiles(S32 width, S32 height); - void drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image); + void drawLegacyBackgroundLayers(S32 width, S32 height); //draw legacy background 'layer' tiles. Only available on official grids, I believe. + F32 drawLegacySimTile(LLSimInfo& sim_info, S32 left, S32 top, S32 right, S32 bottom); //draw legacy sim texture (provided in MapBlockReply message). + 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); + bool drawMipmapLevel(S32 width, S32 height, S32 level, bool load = true); static void cleanupTextures(); @@ -119,7 +120,7 @@ public: S32 overlap ); static void drawAvatar( F32 x_pixels, F32 y_pixels, - LLColor4 color, + const LLColor4& color, F32 relative_z = 0.f, F32 dot_radius = 3.f); static void drawIconName(F32 x_pixels, @@ -132,9 +133,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 ); @@ -161,8 +160,6 @@ 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 @@ -202,6 +199,9 @@ public: handle_list_t mVisibleRegions; // set every frame static std::map 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 index 17ca2d573..0302ac92f 100644 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -78,7 +78,7 @@ void LLWorldMipmap::equalizeBoostLevels() // For each tile for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) { - LLPointer img = iter->second; + LLPointer img = iter->second; S32 current_boost_level = img->getBoostLevel(); if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE) { @@ -120,7 +120,7 @@ void LLWorldMipmap::dropBoostLevels() // For each tile for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++) { - LLPointer img = iter->second; + LLPointer img = iter->second; img->setBoostLevel(LLViewerTexture::BOOST_NONE); } } @@ -195,7 +195,7 @@ LLPointer LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 // END DEBUG //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; - LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl); + LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); img->setBoostLevel(LLViewerTexture::BOOST_MAP); // Return the smart pointer @@ -224,7 +224,7 @@ void LLWorldMipmap::cleanMissedTilesFromLevel(S32 level) sublevel_tiles_t::iterator it = level_mipmap.begin(); while (it != level_mipmap.end()) { - LLPointer img = it->second; + LLPointer img = it->second; if (img->isMissingAsset()) { level_mipmap.erase(it++); diff --git a/indra/newview/llxmlrpcresponder.h b/indra/newview/llxmlrpcresponder.h index df01692ae..dbaa45260 100644 --- a/indra/newview/llxmlrpcresponder.h +++ b/indra/newview/llxmlrpcresponder.h @@ -99,6 +99,8 @@ private: XMLRPC_REQUEST mResponse; public: + XMLRPCResponder(void) : mBufferSize(0), mReceivedHTTPHeader(false), mResponse(NULL) { } + // Accessors. F64 transferRate(void) const; bool is_downloading(void) const { return mReceivedHTTPHeader; } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 867370945..1620f16b3 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -142,6 +142,8 @@ void check_stack_depth(S32 stack_depth) //#define DEBUG_INDICES #endif +bool gShiftFrame = false; + const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f; const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f; const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f; @@ -345,8 +347,9 @@ void validate_framebuffer_object(); bool addDeferredAttachments(LLRenderTarget& target) { + static const LLCachedControl SHPrecisionDeferredNormals("SHPrecisionDeferredNormals",false); return target.addColorAttachment(GL_RGBA) && //specular - target.addColorAttachment(GL_RGBA); //normal+z + target.addColorAttachment(SHPrecisionDeferredNormals ? GL_RGB10_A2 : GL_RGBA); //normal+z } LLPipeline::LLPipeline() : @@ -403,6 +406,7 @@ void LLPipeline::init() refreshCachedSettings(); gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); + gOctreeReserveCapacity = llmin(gSavedSettings.getU32("OctreeReserveNodeCapacity"),U32(512)); sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO"); @@ -547,6 +551,7 @@ void LLPipeline::cleanup() mInitialized = FALSE; mDeferredVB = NULL; + mCubeVB = NULL; } //============================================================================ @@ -860,7 +865,7 @@ void LLPipeline::releaseGLBuffers() mWaterRef.release(); mWaterDis.release(); - for (U32 i = 0; i < 3; i++) + for (U32 i = 0; i < 2; i++) { mGlow[i].release(); } @@ -926,16 +931,26 @@ void LLPipeline::createGLBuffers() GLuint resX = gViewerWindow->getWorldViewWidthRaw(); GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + + if (LLPipeline::sRenderGlow) { //screen space glow buffers const U32 glow_res = llmax(1, llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow"))); - for (U32 i = 0; i < 3; i++) + glClearColor(0,0,0,0); + gGL.setColorMask(true, true); + for (U32 i = 0; i < 2; i++) { - mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE); + if(mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE)) + { + mGlow[i].bindTarget(); + mGlow[i].clear(); + mGlow[i].unbindTarget(); + } } + allocateScreenBuffer(resX,resY); } @@ -1456,6 +1471,22 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) } +//static +void LLPipeline::removeMutedAVsLights(LLVOAvatar* muted_avatar) +{ + LLFastTimer t(FTM_REMOVE_FROM_LIGHT_SET); + for (light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); + iter != gPipeline.mNearbyLights.end();) + { + if (iter->drawable->getVObj()->isAttachment() && iter->drawable->getVObj()->getAvatar() == muted_avatar) + { + gPipeline.mLights.erase(iter->drawable); + gPipeline.mNearbyLights.erase(iter++); + } + else ++iter; + } +} + U32 LLPipeline::addObject(LLViewerObject *vobj) { llassert_always(vobj); @@ -1643,6 +1674,10 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED); if (done) { + if (drawablep->isRoot()) + { + drawablep->makeStatic(); + } drawablep->clearState(LLDrawable::ON_MOVE_LIST); if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) { //will likely not receive any future world matrix updates @@ -1775,6 +1810,7 @@ void LLPipeline::grabReferences(LLCullResult& result) void LLPipeline::clearReferences() { sCull = NULL; + mGroupSaveQ1.clear(); } void check_references(LLSpatialGroup* group, LLDrawable* drawable) @@ -2337,6 +2373,65 @@ void LLPipeline::updateGL() }*/ } +void LLPipeline::clearRebuildGroups() +{ + LLSpatialGroup::sg_vector_t hudGroups; + + mGroupQ1Locked = true; + // Iterate through all drawables on the priority build queue, + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); + iter != mGroupQ1.end(); ++iter) + { + LLSpatialGroup* group = *iter; + + // If the group contains HUD objects, save the group + if (group->isHUDGroup()) + { + hudGroups.push_back(group); + } + // Else, no HUD objects so clear the build state + else + { + group->clearState(LLSpatialGroup::IN_BUILD_Q1); + } + } + + // Clear the group + //mGroupQ1.clear(); //Assign already clears... + + // Copy the saved HUD groups back in + mGroupQ1.assign(hudGroups.begin(), hudGroups.end()); + mGroupQ1Locked = false; + + // Clear the HUD groups + hudGroups.clear(); + + mGroupQ2Locked = true; + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); + iter != mGroupQ2.end(); ++iter) + { + LLSpatialGroup* group = *iter; + + // If the group contains HUD objects, save the group + if (group->isHUDGroup()) + { + hudGroups.push_back(group); + } + // Else, no HUD objects so clear the build state + else + { + group->clearState(LLSpatialGroup::IN_BUILD_Q2); + } + } + + // Clear the group + //mGroupQ2.clear(); //Assign already clears... + + // Copy the saved HUD groups back in + mGroupQ2.assign(hudGroups.begin(), hudGroups.end()); + mGroupQ2Locked = false; +} + static LLFastTimer::DeclareTimer FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups"); void LLPipeline::rebuildPriorityGroups() @@ -2359,6 +2454,7 @@ void LLPipeline::rebuildPriorityGroups() group->clearState(LLSpatialGroup::IN_BUILD_Q1); } + mGroupSaveQ1 = mGroupQ1; mGroupQ1.clear(); mGroupQ1Locked = false; @@ -5037,38 +5133,34 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad // UPDATE THE EXISTING NEARBY LIGHTS - if (!LLPipeline::sSkipUpdate) + light_set_t cur_nearby_lights; + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); iter++) { - light_set_t cur_nearby_lights; - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); iter++) + const Light* light = &(*iter); + LLDrawable* drawable = light->drawable; + LLVOVolume* volight = drawable->getVOVolume(); + if (!volight || !drawable->isState(LLDrawable::LIGHT)) { - const Light* light = &(*iter); - LLDrawable* drawable = light->drawable; - LLVOVolume* volight = drawable->getVOVolume(); - if (!volight || !drawable->isState(LLDrawable::LIGHT)) - { - setLight(drawable,false); //remove from mLight list - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } - if (light->fade <= -LIGHT_FADE_TIME) - { - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } - if (!sRenderAttachedLights && volight && volight->isAttachment()) - { - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } - - F32 dist = calc_light_dist(volight, cam_pos, max_dist); - cur_nearby_lights.insert(Light(drawable, dist, light->fade)); + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; } - mNearbyLights = cur_nearby_lights; + if (light->fade <= -LIGHT_FADE_TIME) + { + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; + } + if (!sRenderAttachedLights && volight && volight->isAttachment()) + { + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; + } + + F32 dist = calc_light_dist(volight, cam_pos, max_dist); + cur_nearby_lights.insert(Light(drawable, dist, light->fade)); } - + mNearbyLights = cur_nearby_lights; + // FIND NEW LIGHTS THAT ARE IN RANGE light_set_t new_nearby_lights; for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); @@ -6159,7 +6251,8 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) } void LLPipeline::resetVertexBuffers() -{ mResetVertexBuffers = true; +{ + mResetVertexBuffers = true; } static LLFastTimer::DeclareTimer FTM_RESET_VB("Reset VB"); @@ -6200,6 +6293,8 @@ void LLPipeline::doResetVertexBuffers() if(LLPostProcess::instanceExists()) LLPostProcess::getInstance()->destroyGL(); + LLVOPartGroup::destroyGL(); + LLVertexBuffer::cleanupClass(); //delete all name pool caches @@ -6432,8 +6527,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b { { LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); - mGlow[2].bindTarget(); - mGlow[2].clear(); + mGlow[1].bindTarget(); + mGlow[1].clear(); } gGlowExtractProgram.bind(); @@ -6472,7 +6567,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGL.getTexUnit(0)->unbind(mScreen.getUsage()); - mGlow[2].flush(); + mGlow[1].flush(); } tc1.setVec(0,0); @@ -6504,14 +6599,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b mGlow[i%2].clear(); } - if (i == 0) - { - gGL.getTexUnit(0)->bind(&mGlow[2]); - } - else - { - gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]); - } + gGL.getTexUnit(0)->bind(&mGlow[(i+1)%2]); if (i%2 == 0) { @@ -7217,14 +7305,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0/ssao_factor); LLVector3 ssao_effect = RenderSSAOEffect; - F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0; - F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0; - // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by - // value factor, and scales remainder by saturation factor - F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag, - matrix_nondiag, matrix_diag, matrix_nondiag, - matrix_nondiag, matrix_nondiag, matrix_diag}; - shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat); + shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_EFFECT, ssao_effect[0]); F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); F32 shadow_bias_error = 1.f + RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); @@ -7774,10 +7855,10 @@ void LLPipeline::renderDeferredLighting() pushRenderTypeMask(); andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, LLPipeline::RENDER_TYPE_FULLBRIGHT, - LLPipeline::RENDER_TYPE_VOLUME, + //LLPipeline::RENDER_TYPE_VOLUME, LLPipeline::RENDER_TYPE_GLOW, LLPipeline::RENDER_TYPE_BUMP, - LLPipeline::RENDER_TYPE_PASS_SIMPLE, + /*LLPipeline::RENDER_TYPE_PASS_SIMPLE, //These aren't used. LLPipeline::RENDER_TYPE_PASS_ALPHA, LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, LLPipeline::RENDER_TYPE_PASS_BUMP, @@ -7789,7 +7870,7 @@ void LLPipeline::renderDeferredLighting() LLPipeline::RENDER_TYPE_PASS_GRASS, LLPipeline::RENDER_TYPE_PASS_SHINY, LLPipeline::RENDER_TYPE_PASS_INVISIBLE, - LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, + LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,*/ LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); @@ -9682,25 +9763,25 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) BOOL LLPipeline::hasRenderBatches(const U32 type) const { - return sCull->getRenderMapSize(type) > 0; + return sCull->hasRenderMap(type); } -LLCullResult::drawinfo_iterator LLPipeline::beginRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLPipeline::beginRenderMap(U32 type) const { return sCull->beginRenderMap(type); } -LLCullResult::drawinfo_iterator LLPipeline::endRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLPipeline::endRenderMap(U32 type) const { return sCull->endRenderMap(type); } -LLCullResult::sg_iterator LLPipeline::beginAlphaGroups() +LLCullResult::sg_iterator LLPipeline::beginAlphaGroups() const { return sCull->beginAlphaGroups(); } -LLCullResult::sg_iterator LLPipeline::endAlphaGroups() +LLCullResult::sg_iterator LLPipeline::endAlphaGroups() const { return sCull->endAlphaGroups(); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index e5ed58ca1..5fca4ea91 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -155,6 +155,8 @@ public: void unlinkDrawable(LLDrawable*); + static void removeMutedAVsLights(LLVOAvatar*); + // Object related methods void markVisible(LLDrawable *drawablep, LLCamera& camera); void markOccluder(LLSpatialGroup* group); @@ -227,6 +229,7 @@ public: void updateGL(); void rebuildPriorityGroups(); void rebuildGroups(); + void clearRebuildGroups(); //calculate pixel area of given box from vantage point of given camera static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); @@ -296,10 +299,10 @@ public: void setLight(LLDrawable *drawablep, BOOL is_light); BOOL hasRenderBatches(const U32 type) const; - LLCullResult::drawinfo_iterator beginRenderMap(U32 type); - LLCullResult::drawinfo_iterator endRenderMap(U32 type); - LLCullResult::sg_iterator beginAlphaGroups(); - LLCullResult::sg_iterator endAlphaGroups(); + LLCullResult::drawinfo_iterator beginRenderMap(U32 type) const; + LLCullResult::drawinfo_iterator endRenderMap(U32 type) const; + LLCullResult::sg_iterator beginAlphaGroups() const; + LLCullResult::sg_iterator endAlphaGroups() const; void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); @@ -582,7 +585,7 @@ public: LLRenderTarget mWaterDis; //texture for making the glow - LLRenderTarget mGlow[3]; + LLRenderTarget mGlow[2]; //noise map U32 mNoiseMap; @@ -655,6 +658,8 @@ protected: LLSpatialGroup::sg_vector_t mGroupQ1; //priority LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority + LLSpatialGroup::sg_vector_t mGroupSaveQ1; // a place to save mGroupQ1 until it is safe to unref + LLSpatialGroup::sg_vector_t mMeshDirtyGroup; //groups that need rebuildMesh called U32 mMeshDirtyQueryObject; diff --git a/indra/newview/rlvui.cpp b/indra/newview/rlvui.cpp index 2f1d59091..405dc7909 100644 --- a/indra/newview/rlvui.cpp +++ b/indra/newview/rlvui.cpp @@ -265,7 +265,7 @@ void RlvUIEnabler::onToggleShowNames(bool fQuitting) else { LLAvatarNameCache::setForceDisplayNames(false); - LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getS32("PhoenixNameSystem") != 0); + LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getS32("PhoenixNameSystem") == 1 || gSavedSettings.getS32("PhoenixNameSystem") == 2); } LLVOAvatar::invalidateNameTags(); // See handleDisplayNamesOptionChanged() } diff --git a/indra/newview/sgmemstat.cpp b/indra/newview/sgmemstat.cpp index d4e22a882..d8c4a3f5a 100644 --- a/indra/newview/sgmemstat.cpp +++ b/indra/newview/sgmemstat.cpp @@ -18,7 +18,7 @@ #include "llviewerprecompiledheaders.h" #include "sgmemstat.h" -#if (!LL_WINDOWS && !LL_LINUX) +#if (!(LL_LINUX || LL_USE_TCMALLOC)) bool SGMemStat::haveStat() { return false; } diff --git a/indra/newview/skins/Blackdark/colors.xml b/indra/newview/skins/Blackdark/colors.xml new file mode 100644 index 000000000..e076f94eb --- /dev/null +++ b/indra/newview/skins/Blackdark/colors.xml @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/Blackdark/textures/0098b015-3daf-4cfe-a72f-915369ea97c2.tga b/indra/newview/skins/Blackdark/textures/0098b015-3daf-4cfe-a72f-915369ea97c2.tga new file mode 100644 index 000000000..352bcdad2 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/0098b015-3daf-4cfe-a72f-915369ea97c2.tga differ diff --git a/indra/newview/skins/Blackdark/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga b/indra/newview/skins/Blackdark/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga new file mode 100644 index 000000000..e90ab295b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga differ diff --git a/indra/newview/skins/Blackdark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/Blackdark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga new file mode 100644 index 000000000..55e379309 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga differ diff --git a/indra/newview/skins/Blackdark/textures/7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga b/indra/newview/skins/Blackdark/textures/7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga new file mode 100644 index 000000000..a79430cef Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga differ diff --git a/indra/newview/skins/Blackdark/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga b/indra/newview/skins/Blackdark/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga new file mode 100644 index 000000000..534ecba91 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga differ diff --git a/indra/newview/skins/Blackdark/textures/89e9fc7c-0b16-457d-be4f-136270759c4d.tga b/indra/newview/skins/Blackdark/textures/89e9fc7c-0b16-457d-be4f-136270759c4d.tga new file mode 100644 index 000000000..6cc9ea194 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/89e9fc7c-0b16-457d-be4f-136270759c4d.tga differ diff --git a/indra/newview/skins/Blackdark/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga b/indra/newview/skins/Blackdark/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga new file mode 100644 index 000000000..e90ab295b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga differ diff --git a/indra/newview/skins/Blackdark/textures/active_speakers.tga b/indra/newview/skins/Blackdark/textures/active_speakers.tga new file mode 100644 index 000000000..1e0eb5a32 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/active_speakers.tga differ diff --git a/indra/newview/skins/Blackdark/textures/active_voice_tab.tga b/indra/newview/skins/Blackdark/textures/active_voice_tab.tga new file mode 100644 index 000000000..c104ba289 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/active_voice_tab.tga differ diff --git a/indra/newview/skins/Blackdark/textures/arrow_down.tga b/indra/newview/skins/Blackdark/textures/arrow_down.tga new file mode 100644 index 000000000..89a793bcb Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/arrow_down.tga differ diff --git a/indra/newview/skins/Blackdark/textures/arrow_up.tga b/indra/newview/skins/Blackdark/textures/arrow_up.tga new file mode 100644 index 000000000..5b03c5433 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/arrow_up.tga differ diff --git a/indra/newview/skins/Blackdark/textures/b4870163-6208-42a9-9801-93133bf9a6cd.tga b/indra/newview/skins/Blackdark/textures/b4870163-6208-42a9-9801-93133bf9a6cd.tga new file mode 100644 index 000000000..35d979972 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/b4870163-6208-42a9-9801-93133bf9a6cd.tga differ diff --git a/indra/newview/skins/Blackdark/textures/badge_error.j2c b/indra/newview/skins/Blackdark/textures/badge_error.j2c new file mode 100644 index 000000000..efb5c375c Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/badge_error.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/badge_note.j2c b/indra/newview/skins/Blackdark/textures/badge_note.j2c new file mode 100644 index 000000000..ef5db9e0d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/badge_note.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/badge_ok.j2c b/indra/newview/skins/Blackdark/textures/badge_ok.j2c new file mode 100644 index 000000000..8ceee01c6 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/badge_ok.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/badge_warn.j2c b/indra/newview/skins/Blackdark/textures/badge_warn.j2c new file mode 100644 index 000000000..8fb85be69 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/badge_warn.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/black.tga b/indra/newview/skins/Blackdark/textures/black.tga new file mode 100644 index 000000000..e368ea496 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/black.tga differ diff --git a/indra/newview/skins/Blackdark/textures/btn_chatbar.tga b/indra/newview/skins/Blackdark/textures/btn_chatbar.tga new file mode 100644 index 000000000..07117925a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/btn_chatbar.tga differ diff --git a/indra/newview/skins/Blackdark/textures/btn_chatbar_selected.tga b/indra/newview/skins/Blackdark/textures/btn_chatbar_selected.tga new file mode 100644 index 000000000..a935ed396 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/btn_chatbar_selected.tga differ diff --git a/indra/newview/skins/Blackdark/textures/button_anim_pause.tga b/indra/newview/skins/Blackdark/textures/button_anim_pause.tga new file mode 100644 index 000000000..5a8f2f544 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/button_anim_pause.tga differ diff --git a/indra/newview/skins/Blackdark/textures/button_anim_pause_selected.tga b/indra/newview/skins/Blackdark/textures/button_anim_pause_selected.tga new file mode 100644 index 000000000..380e00416 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/button_anim_pause_selected.tga differ diff --git a/indra/newview/skins/Blackdark/textures/button_anim_play.tga b/indra/newview/skins/Blackdark/textures/button_anim_play.tga new file mode 100644 index 000000000..d7a7220d4 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/button_anim_play.tga differ diff --git a/indra/newview/skins/Blackdark/textures/button_anim_play_selected.tga b/indra/newview/skins/Blackdark/textures/button_anim_play_selected.tga new file mode 100644 index 000000000..778fbf062 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/button_anim_play_selected.tga differ diff --git a/indra/newview/skins/Blackdark/textures/button_anim_stop.tga b/indra/newview/skins/Blackdark/textures/button_anim_stop.tga new file mode 100644 index 000000000..f470fa927 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/button_anim_stop.tga differ diff --git a/indra/newview/skins/Blackdark/textures/button_anim_stop_selected.tga b/indra/newview/skins/Blackdark/textures/button_anim_stop_selected.tga new file mode 100644 index 000000000..e07ea176a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/button_anim_stop_selected.tga differ diff --git a/indra/newview/skins/Blackdark/textures/button_disabled_32x128.tga b/indra/newview/skins/Blackdark/textures/button_disabled_32x128.tga new file mode 100644 index 000000000..fd117209f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/button_disabled_32x128.tga differ diff --git a/indra/newview/skins/Blackdark/textures/button_enabled_32x128.tga b/indra/newview/skins/Blackdark/textures/button_enabled_32x128.tga new file mode 100644 index 000000000..fd117209f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/button_enabled_32x128.tga differ diff --git a/indra/newview/skins/Blackdark/textures/button_enabled_selected_32x128.tga b/indra/newview/skins/Blackdark/textures/button_enabled_selected_32x128.tga new file mode 100644 index 000000000..138b908b2 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/button_enabled_selected_32x128.tga differ diff --git a/indra/newview/skins/Blackdark/textures/c1e21504-f136-451d-b8e9-929037812f1d.tga b/indra/newview/skins/Blackdark/textures/c1e21504-f136-451d-b8e9-929037812f1d.tga new file mode 100644 index 000000000..53c8959a6 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/c1e21504-f136-451d-b8e9-929037812f1d.tga differ diff --git a/indra/newview/skins/Blackdark/textures/c63f124c-6340-4fbf-b59e-0869a44adb64.tga b/indra/newview/skins/Blackdark/textures/c63f124c-6340-4fbf-b59e-0869a44adb64.tga new file mode 100644 index 000000000..cbc02b4a4 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/c63f124c-6340-4fbf-b59e-0869a44adb64.tga differ diff --git a/indra/newview/skins/Blackdark/textures/cam_rotate_in.tga b/indra/newview/skins/Blackdark/textures/cam_rotate_in.tga new file mode 100644 index 000000000..84c647202 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/cam_rotate_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/cam_rotate_out.tga b/indra/newview/skins/Blackdark/textures/cam_rotate_out.tga new file mode 100644 index 000000000..2bcd371a7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/cam_rotate_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/cam_tracking_in.tga b/indra/newview/skins/Blackdark/textures/cam_tracking_in.tga new file mode 100644 index 000000000..c23119944 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/cam_tracking_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/cam_tracking_out.tga b/indra/newview/skins/Blackdark/textures/cam_tracking_out.tga new file mode 100644 index 000000000..9cc25d21c Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/cam_tracking_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/cam_zoom_minus_in.tga b/indra/newview/skins/Blackdark/textures/cam_zoom_minus_in.tga new file mode 100644 index 000000000..29261e484 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/cam_zoom_minus_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/cam_zoom_out.tga b/indra/newview/skins/Blackdark/textures/cam_zoom_out.tga new file mode 100644 index 000000000..c0e771aab Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/cam_zoom_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/cam_zoom_plus_in.tga b/indra/newview/skins/Blackdark/textures/cam_zoom_plus_in.tga new file mode 100644 index 000000000..b342dde08 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/cam_zoom_plus_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga b/indra/newview/skins/Blackdark/textures/ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga new file mode 100644 index 000000000..0717b393e Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga differ diff --git a/indra/newview/skins/Blackdark/textures/checkbox_disabled_false.tga b/indra/newview/skins/Blackdark/textures/checkbox_disabled_false.tga new file mode 100644 index 000000000..aa57cd211 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/checkbox_disabled_false.tga differ diff --git a/indra/newview/skins/Blackdark/textures/checkbox_disabled_true.tga b/indra/newview/skins/Blackdark/textures/checkbox_disabled_true.tga new file mode 100644 index 000000000..5dfee7d46 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/checkbox_disabled_true.tga differ diff --git a/indra/newview/skins/Blackdark/textures/checkbox_enabled_false.tga b/indra/newview/skins/Blackdark/textures/checkbox_enabled_false.tga new file mode 100644 index 000000000..fb8265b18 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/checkbox_enabled_false.tga differ diff --git a/indra/newview/skins/Blackdark/textures/checkbox_enabled_true.tga b/indra/newview/skins/Blackdark/textures/checkbox_enabled_true.tga new file mode 100644 index 000000000..8372e309b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/checkbox_enabled_true.tga differ diff --git a/indra/newview/skins/Blackdark/textures/circle.tga b/indra/newview/skins/Blackdark/textures/circle.tga new file mode 100644 index 000000000..d7097e3a3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/circle.tga differ diff --git a/indra/newview/skins/Blackdark/textures/close_in_blue.tga b/indra/newview/skins/Blackdark/textures/close_in_blue.tga new file mode 100644 index 000000000..c58e052b8 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/close_in_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/close_inactive.tga b/indra/newview/skins/Blackdark/textures/close_inactive.tga new file mode 100644 index 000000000..30f6e7b5f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/close_inactive.tga differ diff --git a/indra/newview/skins/Blackdark/textures/close_inactive_blue.tga b/indra/newview/skins/Blackdark/textures/close_inactive_blue.tga new file mode 100644 index 000000000..2f912df59 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/close_inactive_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/closebox.tga b/indra/newview/skins/Blackdark/textures/closebox.tga new file mode 100644 index 000000000..5e1195526 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/closebox.tga differ diff --git a/indra/newview/skins/Blackdark/textures/combobox_arrow.tga b/indra/newview/skins/Blackdark/textures/combobox_arrow.tga new file mode 100644 index 000000000..4bdcf6e14 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/combobox_arrow.tga differ diff --git a/indra/newview/skins/Blackdark/textures/d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c b/indra/newview/skins/Blackdark/textures/d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c new file mode 100644 index 000000000..4b73b25ac Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/darkgray.tga b/indra/newview/skins/Blackdark/textures/darkgray.tga new file mode 100644 index 000000000..e69be0893 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/darkgray.tga differ diff --git a/indra/newview/skins/Blackdark/textures/default_land_picture.j2c b/indra/newview/skins/Blackdark/textures/default_land_picture.j2c new file mode 100644 index 000000000..6e2a85a46 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/default_land_picture.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/default_profile_picture.j2c b/indra/newview/skins/Blackdark/textures/default_profile_picture.j2c new file mode 100644 index 000000000..31d741e88 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/default_profile_picture.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/direction_arrow.tga b/indra/newview/skins/Blackdark/textures/direction_arrow.tga new file mode 100644 index 000000000..59149e1d5 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/direction_arrow.tga differ diff --git a/indra/newview/skins/Blackdark/textures/down_arrow.png b/indra/newview/skins/Blackdark/textures/down_arrow.png new file mode 100644 index 000000000..46bb251f5 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/down_arrow.png differ diff --git a/indra/newview/skins/Blackdark/textures/eye_button_active.tga b/indra/newview/skins/Blackdark/textures/eye_button_active.tga new file mode 100644 index 000000000..d4a9c2455 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/eye_button_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/eye_button_inactive.tga b/indra/newview/skins/Blackdark/textures/eye_button_inactive.tga new file mode 100644 index 000000000..edfdeba45 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/eye_button_inactive.tga differ diff --git a/indra/newview/skins/Blackdark/textures/ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga b/indra/newview/skins/Blackdark/textures/ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga new file mode 100644 index 000000000..534ecba91 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga differ diff --git a/indra/newview/skins/Blackdark/textures/ff_edit_mine_button.tga b/indra/newview/skins/Blackdark/textures/ff_edit_mine_button.tga new file mode 100644 index 000000000..150354d99 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/ff_edit_mine_button.tga differ diff --git a/indra/newview/skins/Blackdark/textures/ff_edit_theirs_button.tga b/indra/newview/skins/Blackdark/textures/ff_edit_theirs_button.tga new file mode 100644 index 000000000..2a0efd61f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/ff_edit_theirs_button.tga differ diff --git a/indra/newview/skins/Blackdark/textures/ff_online_status_button.tga b/indra/newview/skins/Blackdark/textures/ff_online_status_button.tga new file mode 100644 index 000000000..058a66f26 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/ff_online_status_button.tga differ diff --git a/indra/newview/skins/Blackdark/textures/ff_visible_map_button.tga b/indra/newview/skins/Blackdark/textures/ff_visible_map_button.tga new file mode 100644 index 000000000..9053eed64 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/ff_visible_map_button.tga differ diff --git a/indra/newview/skins/Blackdark/textures/ff_visible_online_button.tga b/indra/newview/skins/Blackdark/textures/ff_visible_online_button.tga new file mode 100644 index 000000000..8d4d3a8d2 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/ff_visible_online_button.tga differ diff --git a/indra/newview/skins/Blackdark/textures/flyout_btn_left.tga b/indra/newview/skins/Blackdark/textures/flyout_btn_left.tga new file mode 100644 index 000000000..1ff9aea29 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/flyout_btn_left.tga differ diff --git a/indra/newview/skins/Blackdark/textures/flyout_btn_left_disabled.tga b/indra/newview/skins/Blackdark/textures/flyout_btn_left_disabled.tga new file mode 100644 index 000000000..1ff9aea29 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/flyout_btn_left_disabled.tga differ diff --git a/indra/newview/skins/Blackdark/textures/flyout_btn_left_selected.tga b/indra/newview/skins/Blackdark/textures/flyout_btn_left_selected.tga new file mode 100644 index 000000000..c0245c65d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/flyout_btn_left_selected.tga differ diff --git a/indra/newview/skins/Blackdark/textures/flyout_btn_right.tga b/indra/newview/skins/Blackdark/textures/flyout_btn_right.tga new file mode 100644 index 000000000..932e39abd Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/flyout_btn_right.tga differ diff --git a/indra/newview/skins/Blackdark/textures/flyout_btn_right_disabled.tga b/indra/newview/skins/Blackdark/textures/flyout_btn_right_disabled.tga new file mode 100644 index 000000000..932e39abd Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/flyout_btn_right_disabled.tga differ diff --git a/indra/newview/skins/Blackdark/textures/flyout_btn_right_selected.tga b/indra/newview/skins/Blackdark/textures/flyout_btn_right_selected.tga new file mode 100644 index 000000000..9a69d39d9 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/flyout_btn_right_selected.tga differ diff --git a/indra/newview/skins/Blackdark/textures/flyout_left.tga b/indra/newview/skins/Blackdark/textures/flyout_left.tga new file mode 100644 index 000000000..af599c019 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/flyout_left.tga differ diff --git a/indra/newview/skins/Blackdark/textures/flyout_left_disabled.tga b/indra/newview/skins/Blackdark/textures/flyout_left_disabled.tga new file mode 100644 index 000000000..af599c019 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/flyout_left_disabled.tga differ diff --git a/indra/newview/skins/Blackdark/textures/flyout_left_selected.tga b/indra/newview/skins/Blackdark/textures/flyout_left_selected.tga new file mode 100644 index 000000000..b55567d88 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/flyout_left_selected.tga differ diff --git a/indra/newview/skins/Blackdark/textures/folder_arrow.tga b/indra/newview/skins/Blackdark/textures/folder_arrow.tga new file mode 100644 index 000000000..734a00a84 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/folder_arrow.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/Blackdark/textures/icn_active-speakers-dot-lvl0.tga new file mode 100644 index 000000000..35846cef3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_active-speakers-dot-lvl0.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/Blackdark/textures/icn_active-speakers-dot-lvl1.tga new file mode 100644 index 000000000..1f9f564fa Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_active-speakers-dot-lvl1.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/Blackdark/textures/icn_active-speakers-dot-lvl2.tga new file mode 100644 index 000000000..b2e5609f1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_active-speakers-dot-lvl2.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/Blackdark/textures/icn_active-speakers-typing1.tga new file mode 100644 index 000000000..3706c96e0 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_active-speakers-typing1.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/Blackdark/textures/icn_active-speakers-typing2.tga new file mode 100644 index 000000000..0d127f946 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_active-speakers-typing2.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/Blackdark/textures/icn_active-speakers-typing3.tga new file mode 100644 index 000000000..031b3ad34 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_active-speakers-typing3.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_chatbar.tga b/indra/newview/skins/Blackdark/textures/icn_chatbar.tga new file mode 100644 index 000000000..b89dfc432 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_chatbar.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_clear_lineeditor.tga b/indra/newview/skins/Blackdark/textures/icn_clear_lineeditor.tga new file mode 100644 index 000000000..8cd8310c6 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_clear_lineeditor.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_label_media.tga b/indra/newview/skins/Blackdark/textures/icn_label_media.tga new file mode 100644 index 000000000..b16c528e9 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_label_media.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_label_music.tga b/indra/newview/skins/Blackdark/textures/icn_label_music.tga new file mode 100644 index 000000000..515f170b6 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_label_music.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_label_web.tga b/indra/newview/skins/Blackdark/textures/icn_label_web.tga new file mode 100644 index 000000000..6cacfad7a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_label_web.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_media-pause_active.tga b/indra/newview/skins/Blackdark/textures/icn_media-pause_active.tga new file mode 100644 index 000000000..8988829aa Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_media-pause_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_media-pause_disabled.tga b/indra/newview/skins/Blackdark/textures/icn_media-pause_disabled.tga new file mode 100644 index 000000000..4690f4256 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_media-pause_disabled.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_media-pause_enabled.tga b/indra/newview/skins/Blackdark/textures/icn_media-pause_enabled.tga new file mode 100644 index 000000000..c01399e27 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_media-pause_enabled.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_media-play_enabled.tga b/indra/newview/skins/Blackdark/textures/icn_media-play_enabled.tga new file mode 100644 index 000000000..accac38b0 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_media-play_enabled.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_media-stop_enabled.tga b/indra/newview/skins/Blackdark/textures/icn_media-stop_enabled.tga new file mode 100644 index 000000000..d935fa317 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_media-stop_enabled.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_media.tga b/indra/newview/skins/Blackdark/textures/icn_media.tga new file mode 100644 index 000000000..2a035ba5d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_media.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_media_movie.tga b/indra/newview/skins/Blackdark/textures/icn_media_movie.tga new file mode 100644 index 000000000..b16c528e9 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_media_movie.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_media_web.tga b/indra/newview/skins/Blackdark/textures/icn_media_web.tga new file mode 100644 index 000000000..a92ae962b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_media_web.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_music.tga b/indra/newview/skins/Blackdark/textures/icn_music.tga new file mode 100644 index 000000000..81da5abcf Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_music.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_pause.tga b/indra/newview/skins/Blackdark/textures/icn_pause.tga new file mode 100644 index 000000000..3bc286f5f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_pause.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_play.tga b/indra/newview/skins/Blackdark/textures/icn_play.tga new file mode 100644 index 000000000..a23ef52e3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_play.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_rounded-text-field.tga b/indra/newview/skins/Blackdark/textures/icn_rounded-text-field.tga new file mode 100644 index 000000000..1f1e72572 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_rounded-text-field.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_scrollbar.tga b/indra/newview/skins/Blackdark/textures/icn_scrollbar.tga new file mode 100644 index 000000000..5b56da71a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_scrollbar.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_scrollbar_bg.tga b/indra/newview/skins/Blackdark/textures/icn_scrollbar_bg.tga new file mode 100644 index 000000000..5b56da71a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_scrollbar_bg.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_scrollbar_thumb.tga b/indra/newview/skins/Blackdark/textures/icn_scrollbar_thumb.tga new file mode 100644 index 000000000..5b56da71a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_scrollbar_thumb.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_slide-groove_dark.tga b/indra/newview/skins/Blackdark/textures/icn_slide-groove_dark.tga new file mode 100644 index 000000000..d893fada0 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_slide-groove_dark.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_slide-highlight.tga b/indra/newview/skins/Blackdark/textures/icn_slide-highlight.tga new file mode 100644 index 000000000..d371cd066 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_slide-highlight.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_slide-thumb_dark.tga b/indra/newview/skins/Blackdark/textures/icn_slide-thumb_dark.tga new file mode 100644 index 000000000..cf96786fd Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_slide-thumb_dark.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_speaker-muted_dark.tga b/indra/newview/skins/Blackdark/textures/icn_speaker-muted_dark.tga new file mode 100644 index 000000000..8f2c80dd2 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_speaker-muted_dark.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_speaker_dark.tga b/indra/newview/skins/Blackdark/textures/icn_speaker_dark.tga new file mode 100644 index 000000000..c2ee04044 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_speaker_dark.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_stop.tga b/indra/newview/skins/Blackdark/textures/icn_stop.tga new file mode 100644 index 000000000..2925b3853 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_stop.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_toolbar_build.tga b/indra/newview/skins/Blackdark/textures/icn_toolbar_build.tga new file mode 100644 index 000000000..c7cab6b38 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_toolbar_build.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_toolbar_fly.tga b/indra/newview/skins/Blackdark/textures/icn_toolbar_fly.tga new file mode 100644 index 000000000..c7cab6b38 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_toolbar_fly.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_toolbar_inventory.tga b/indra/newview/skins/Blackdark/textures/icn_toolbar_inventory.tga new file mode 100644 index 000000000..c7cab6b38 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_toolbar_inventory.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_toolbar_map.tga b/indra/newview/skins/Blackdark/textures/icn_toolbar_map.tga new file mode 100644 index 000000000..c7cab6b38 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_toolbar_map.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_toolbar_minimap.tga b/indra/newview/skins/Blackdark/textures/icn_toolbar_minimap.tga new file mode 100644 index 000000000..c7cab6b38 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_toolbar_minimap.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_toolbar_radar.tga b/indra/newview/skins/Blackdark/textures/icn_toolbar_radar.tga new file mode 100644 index 000000000..d1a55ed74 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_toolbar_radar.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_toolbar_search.tga b/indra/newview/skins/Blackdark/textures/icn_toolbar_search.tga new file mode 100644 index 000000000..c7cab6b38 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_toolbar_search.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_toolbar_snapshot.tga b/indra/newview/skins/Blackdark/textures/icn_toolbar_snapshot.tga new file mode 100644 index 000000000..c7cab6b38 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_toolbar_snapshot.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice-call-end.tga b/indra/newview/skins/Blackdark/textures/icn_voice-call-end.tga new file mode 100644 index 000000000..84056b90a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice-call-end.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice-call-start.tga b/indra/newview/skins/Blackdark/textures/icn_voice-call-start.tga new file mode 100644 index 000000000..7babfd318 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice-call-start.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice-groupfocus.tga b/indra/newview/skins/Blackdark/textures/icn_voice-groupfocus.tga new file mode 100644 index 000000000..913bd0969 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice-groupfocus.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice-localchat.tga b/indra/newview/skins/Blackdark/textures/icn_voice-localchat.tga new file mode 100644 index 000000000..5c1456602 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice-localchat.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice-pvtfocus.tga b/indra/newview/skins/Blackdark/textures/icn_voice-pvtfocus.tga new file mode 100644 index 000000000..76e72fd3a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice-pvtfocus.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice_ptt-off.tga b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-off.tga new file mode 100644 index 000000000..530425dd7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-off.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on-lvl1.tga b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on-lvl1.tga new file mode 100644 index 000000000..95cadd33d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on-lvl1.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on-lvl2.tga b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on-lvl2.tga new file mode 100644 index 000000000..aeae781c5 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on-lvl2.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on-lvl3.tga b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on-lvl3.tga new file mode 100644 index 000000000..081265efb Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on-lvl3.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on.tga b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on.tga new file mode 100644 index 000000000..78f21cc59 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icn_voice_ptt-on.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_auction.tga b/indra/newview/skins/Blackdark/textures/icon_auction.tga new file mode 100644 index 000000000..3aa21d323 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_auction.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_avatar_offline.tga b/indra/newview/skins/Blackdark/textures/icon_avatar_offline.tga new file mode 100644 index 000000000..620e0f7c1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_avatar_offline.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_avatar_online.tga b/indra/newview/skins/Blackdark/textures/icon_avatar_online.tga new file mode 100644 index 000000000..6350237ee Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_avatar_online.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_event.tga b/indra/newview/skins/Blackdark/textures/icon_event.tga new file mode 100644 index 000000000..23f246b91 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_event.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_event_adult.tga b/indra/newview/skins/Blackdark/textures/icon_event_adult.tga new file mode 100644 index 000000000..7202e6734 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_event_adult.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_event_mature.tga b/indra/newview/skins/Blackdark/textures/icon_event_mature.tga new file mode 100644 index 000000000..103c5e535 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_event_mature.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_for_sale.tga b/indra/newview/skins/Blackdark/textures/icon_for_sale.tga new file mode 100644 index 000000000..09405d383 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_for_sale.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_for_sale_adult.tga b/indra/newview/skins/Blackdark/textures/icon_for_sale_adult.tga new file mode 100644 index 000000000..147f724e7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_for_sale_adult.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_group.tga b/indra/newview/skins/Blackdark/textures/icon_group.tga new file mode 100644 index 000000000..1e5c31aa3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_group.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_groupnotice.tga b/indra/newview/skins/Blackdark/textures/icon_groupnotice.tga new file mode 100644 index 000000000..b8cd107d3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_groupnotice.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_groupnoticeinventory.tga b/indra/newview/skins/Blackdark/textures/icon_groupnoticeinventory.tga new file mode 100644 index 000000000..9749e5779 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_groupnoticeinventory.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_lock.tga b/indra/newview/skins/Blackdark/textures/icon_lock.tga new file mode 100644 index 000000000..5de6cc10e Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_lock.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_place.tga b/indra/newview/skins/Blackdark/textures/icon_place.tga new file mode 100644 index 000000000..7f842ba65 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_place.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_popular.tga b/indra/newview/skins/Blackdark/textures/icon_popular.tga new file mode 100644 index 000000000..6bdc6ede3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_popular.tga differ diff --git a/indra/newview/skins/Blackdark/textures/icon_top_pick.tga b/indra/newview/skins/Blackdark/textures/icon_top_pick.tga new file mode 100644 index 000000000..4466e8be7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/icon_top_pick.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_animation.tga b/indra/newview/skins/Blackdark/textures/inv_folder_animation.tga new file mode 100644 index 000000000..b7eae76e3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_animation.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_bodypart.tga b/indra/newview/skins/Blackdark/textures/inv_folder_bodypart.tga new file mode 100644 index 000000000..17658d7b0 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_bodypart.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_callingcard.tga b/indra/newview/skins/Blackdark/textures/inv_folder_callingcard.tga new file mode 100644 index 000000000..dd42c8c68 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_callingcard.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_clothing.tga b/indra/newview/skins/Blackdark/textures/inv_folder_clothing.tga new file mode 100644 index 000000000..bc4f71a5a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_clothing.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_gesture.tga b/indra/newview/skins/Blackdark/textures/inv_folder_gesture.tga new file mode 100644 index 000000000..f3a775c29 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_gesture.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_landmark.tga b/indra/newview/skins/Blackdark/textures/inv_folder_landmark.tga new file mode 100644 index 000000000..2b7ca30d6 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_landmark.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_lostandfound.tga b/indra/newview/skins/Blackdark/textures/inv_folder_lostandfound.tga new file mode 100644 index 000000000..dbef38773 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_lostandfound.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_notecard.tga b/indra/newview/skins/Blackdark/textures/inv_folder_notecard.tga new file mode 100644 index 000000000..675717e8d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_notecard.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_object.tga b/indra/newview/skins/Blackdark/textures/inv_folder_object.tga new file mode 100644 index 000000000..a477d020f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_object.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_plain_closed.tga b/indra/newview/skins/Blackdark/textures/inv_folder_plain_closed.tga new file mode 100644 index 000000000..824dd9569 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_plain_closed.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_plain_open.tga b/indra/newview/skins/Blackdark/textures/inv_folder_plain_open.tga new file mode 100644 index 000000000..c5f6ee59c Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_plain_open.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_script.tga b/indra/newview/skins/Blackdark/textures/inv_folder_script.tga new file mode 100644 index 000000000..919967843 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_script.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_snapshot.tga b/indra/newview/skins/Blackdark/textures/inv_folder_snapshot.tga new file mode 100644 index 000000000..8610eb5ae Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_snapshot.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_sound.tga b/indra/newview/skins/Blackdark/textures/inv_folder_sound.tga new file mode 100644 index 000000000..f9988a916 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_sound.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_texture.tga b/indra/newview/skins/Blackdark/textures/inv_folder_texture.tga new file mode 100644 index 000000000..924224ec1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_texture.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_folder_trash.tga b/indra/newview/skins/Blackdark/textures/inv_folder_trash.tga new file mode 100644 index 000000000..7613d8cde Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_folder_trash.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_animation.tga b/indra/newview/skins/Blackdark/textures/inv_item_animation.tga new file mode 100644 index 000000000..527cef6d0 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_animation.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_attach.tga b/indra/newview/skins/Blackdark/textures/inv_item_attach.tga new file mode 100644 index 000000000..d5ed000d3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_attach.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_callingcard_offline.tga b/indra/newview/skins/Blackdark/textures/inv_item_callingcard_offline.tga new file mode 100644 index 000000000..e47b728ac Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_callingcard_offline.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_callingcard_online.tga b/indra/newview/skins/Blackdark/textures/inv_item_callingcard_online.tga new file mode 100644 index 000000000..e42058b76 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_callingcard_online.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_clothing.tga b/indra/newview/skins/Blackdark/textures/inv_item_clothing.tga new file mode 100644 index 000000000..10fa1b05a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_clothing.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_eyes.tga b/indra/newview/skins/Blackdark/textures/inv_item_eyes.tga new file mode 100644 index 000000000..4ddf340fa Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_eyes.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_gesture.tga b/indra/newview/skins/Blackdark/textures/inv_item_gesture.tga new file mode 100644 index 000000000..93b4194f6 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_gesture.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_gloves.tga b/indra/newview/skins/Blackdark/textures/inv_item_gloves.tga new file mode 100644 index 000000000..d09ae8d9d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_gloves.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_hair.tga b/indra/newview/skins/Blackdark/textures/inv_item_hair.tga new file mode 100644 index 000000000..98bb2e62f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_hair.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_jacket.tga b/indra/newview/skins/Blackdark/textures/inv_item_jacket.tga new file mode 100644 index 000000000..3056bbea3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_jacket.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_landmark.tga b/indra/newview/skins/Blackdark/textures/inv_item_landmark.tga new file mode 100644 index 000000000..aed756f7e Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_landmark.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_landmark_visited.tga b/indra/newview/skins/Blackdark/textures/inv_item_landmark_visited.tga new file mode 100644 index 000000000..6260fc544 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_landmark_visited.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_notecard.tga b/indra/newview/skins/Blackdark/textures/inv_item_notecard.tga new file mode 100644 index 000000000..ca3b77fdf Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_notecard.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_object.tga b/indra/newview/skins/Blackdark/textures/inv_item_object.tga new file mode 100644 index 000000000..447dc0f0b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_object.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_object_multi.tga b/indra/newview/skins/Blackdark/textures/inv_item_object_multi.tga new file mode 100644 index 000000000..85c0142f7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_object_multi.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_pants.tga b/indra/newview/skins/Blackdark/textures/inv_item_pants.tga new file mode 100644 index 000000000..f2c55a7e0 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_pants.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_script.tga b/indra/newview/skins/Blackdark/textures/inv_item_script.tga new file mode 100644 index 000000000..310049e71 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_script.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_script_dangerous.tga b/indra/newview/skins/Blackdark/textures/inv_item_script_dangerous.tga new file mode 100644 index 000000000..2898a5f97 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_script_dangerous.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_shape.tga b/indra/newview/skins/Blackdark/textures/inv_item_shape.tga new file mode 100644 index 000000000..051a5cb3f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_shape.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_shirt.tga b/indra/newview/skins/Blackdark/textures/inv_item_shirt.tga new file mode 100644 index 000000000..10fa1b05a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_shirt.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_shoes.tga b/indra/newview/skins/Blackdark/textures/inv_item_shoes.tga new file mode 100644 index 000000000..4888cb8a6 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_shoes.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_skin.tga b/indra/newview/skins/Blackdark/textures/inv_item_skin.tga new file mode 100644 index 000000000..f9db6b04c Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_skin.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_skirt.tga b/indra/newview/skins/Blackdark/textures/inv_item_skirt.tga new file mode 100644 index 000000000..af9f20482 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_skirt.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_snapshot.tga b/indra/newview/skins/Blackdark/textures/inv_item_snapshot.tga new file mode 100644 index 000000000..97dea8760 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_snapshot.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_socks.tga b/indra/newview/skins/Blackdark/textures/inv_item_socks.tga new file mode 100644 index 000000000..57dbc1841 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_socks.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_sound.tga b/indra/newview/skins/Blackdark/textures/inv_item_sound.tga new file mode 100644 index 000000000..4f4e6b1ee Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_sound.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_texture.tga b/indra/newview/skins/Blackdark/textures/inv_item_texture.tga new file mode 100644 index 000000000..f67e02571 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_texture.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_underpants.tga b/indra/newview/skins/Blackdark/textures/inv_item_underpants.tga new file mode 100644 index 000000000..017a890cf Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_underpants.tga differ diff --git a/indra/newview/skins/Blackdark/textures/inv_item_undershirt.tga b/indra/newview/skins/Blackdark/textures/inv_item_undershirt.tga new file mode 100644 index 000000000..2eca04dbd Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/inv_item_undershirt.tga differ diff --git a/indra/newview/skins/Blackdark/textures/lightgray.tga b/indra/newview/skins/Blackdark/textures/lightgray.tga new file mode 100644 index 000000000..e69be0893 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/lightgray.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_avatar_16.tga b/indra/newview/skins/Blackdark/textures/map_avatar_16.tga new file mode 100644 index 000000000..42d8c1e29 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_avatar_16.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_avatar_8.tga b/indra/newview/skins/Blackdark/textures/map_avatar_8.tga new file mode 100644 index 000000000..7eb7c20f1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_avatar_8.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_avatar_above_8.tga b/indra/newview/skins/Blackdark/textures/map_avatar_above_8.tga new file mode 100644 index 000000000..6faefccc7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_avatar_above_8.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_avatar_below_8.tga b/indra/newview/skins/Blackdark/textures/map_avatar_below_8.tga new file mode 100644 index 000000000..5ad671c26 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_avatar_below_8.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_avatar_you_8.tga b/indra/newview/skins/Blackdark/textures/map_avatar_you_8.tga new file mode 100644 index 000000000..f10f96b10 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_avatar_you_8.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_event.tga b/indra/newview/skins/Blackdark/textures/map_event.tga new file mode 100644 index 000000000..103c5e535 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_event.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_event_adult.tga b/indra/newview/skins/Blackdark/textures/map_event_adult.tga new file mode 100644 index 000000000..7202e6734 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_event_adult.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_event_mature.tga b/indra/newview/skins/Blackdark/textures/map_event_mature.tga new file mode 100644 index 000000000..23f246b91 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_event_mature.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_home.tga b/indra/newview/skins/Blackdark/textures/map_home.tga new file mode 100644 index 000000000..85dde9ef7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_home.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_infohub.tga b/indra/newview/skins/Blackdark/textures/map_infohub.tga new file mode 100644 index 000000000..173b93e39 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_infohub.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_telehub.tga b/indra/newview/skins/Blackdark/textures/map_telehub.tga new file mode 100644 index 000000000..d89bcfa40 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_telehub.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_track_16.tga b/indra/newview/skins/Blackdark/textures/map_track_16.tga new file mode 100644 index 000000000..14d49b93b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_track_16.tga differ diff --git a/indra/newview/skins/Blackdark/textures/map_track_8.tga b/indra/newview/skins/Blackdark/textures/map_track_8.tga new file mode 100644 index 000000000..d9605dde1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/map_track_8.tga differ diff --git a/indra/newview/skins/Blackdark/textures/minimize.tga b/indra/newview/skins/Blackdark/textures/minimize.tga new file mode 100644 index 000000000..151a3078f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/minimize.tga differ diff --git a/indra/newview/skins/Blackdark/textures/minimize_inactive.tga b/indra/newview/skins/Blackdark/textures/minimize_inactive.tga new file mode 100644 index 000000000..d7e1b4057 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/minimize_inactive.tga differ diff --git a/indra/newview/skins/Blackdark/textures/minimize_pressed.tga b/indra/newview/skins/Blackdark/textures/minimize_pressed.tga new file mode 100644 index 000000000..573452ce9 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/minimize_pressed.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_backward_in.tga b/indra/newview/skins/Blackdark/textures/move_backward_in.tga new file mode 100644 index 000000000..56b605382 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_backward_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_backward_out.tga b/indra/newview/skins/Blackdark/textures/move_backward_out.tga new file mode 100644 index 000000000..b8064fd58 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_backward_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_down_in.tga b/indra/newview/skins/Blackdark/textures/move_down_in.tga new file mode 100644 index 000000000..eec8f5764 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_down_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_down_out.tga b/indra/newview/skins/Blackdark/textures/move_down_out.tga new file mode 100644 index 000000000..47993a89e Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_down_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_forward_in.tga b/indra/newview/skins/Blackdark/textures/move_forward_in.tga new file mode 100644 index 000000000..3a9644124 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_forward_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_forward_out.tga b/indra/newview/skins/Blackdark/textures/move_forward_out.tga new file mode 100644 index 000000000..f0f72d1d6 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_forward_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_left_in.tga b/indra/newview/skins/Blackdark/textures/move_left_in.tga new file mode 100644 index 000000000..5c0e910a7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_left_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_left_out.tga b/indra/newview/skins/Blackdark/textures/move_left_out.tga new file mode 100644 index 000000000..68947f297 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_left_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_right_in.tga b/indra/newview/skins/Blackdark/textures/move_right_in.tga new file mode 100644 index 000000000..086e24bfd Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_right_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_right_out.tga b/indra/newview/skins/Blackdark/textures/move_right_out.tga new file mode 100644 index 000000000..b242201ca Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_right_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_turn_left_in.tga b/indra/newview/skins/Blackdark/textures/move_turn_left_in.tga new file mode 100644 index 000000000..6aad5b2c6 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_turn_left_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_turn_left_out.tga b/indra/newview/skins/Blackdark/textures/move_turn_left_out.tga new file mode 100644 index 000000000..c6e3c4f8f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_turn_left_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_turn_right_in.tga b/indra/newview/skins/Blackdark/textures/move_turn_right_in.tga new file mode 100644 index 000000000..f8b56235b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_turn_right_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_turn_right_out.tga b/indra/newview/skins/Blackdark/textures/move_turn_right_out.tga new file mode 100644 index 000000000..f20a6cfac Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_turn_right_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_up_in.tga b/indra/newview/skins/Blackdark/textures/move_up_in.tga new file mode 100644 index 000000000..9d2da6942 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_up_in.tga differ diff --git a/indra/newview/skins/Blackdark/textures/move_up_out.tga b/indra/newview/skins/Blackdark/textures/move_up_out.tga new file mode 100644 index 000000000..8caed0655 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/move_up_out.tga differ diff --git a/indra/newview/skins/Blackdark/textures/mute_icon.tga b/indra/newview/skins/Blackdark/textures/mute_icon.tga new file mode 100644 index 000000000..879b9e618 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/mute_icon.tga differ diff --git a/indra/newview/skins/Blackdark/textures/notify_box_icon.tga b/indra/newview/skins/Blackdark/textures/notify_box_icon.tga new file mode 100644 index 000000000..880aca9b4 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/notify_box_icon.tga differ diff --git a/indra/newview/skins/Blackdark/textures/notify_caution_icon.tga b/indra/newview/skins/Blackdark/textures/notify_caution_icon.tga new file mode 100644 index 000000000..ac6660c16 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/notify_caution_icon.tga differ diff --git a/indra/newview/skins/Blackdark/textures/notify_next.png b/indra/newview/skins/Blackdark/textures/notify_next.png new file mode 100644 index 000000000..9b371e03e Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/notify_next.png differ diff --git a/indra/newview/skins/Blackdark/textures/notify_tip_icon.tga b/indra/newview/skins/Blackdark/textures/notify_tip_icon.tga new file mode 100644 index 000000000..0451da099 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/notify_tip_icon.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_cone.tga b/indra/newview/skins/Blackdark/textures/object_cone.tga new file mode 100644 index 000000000..13f0ef4c3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_cone.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_cone_active.tga b/indra/newview/skins/Blackdark/textures/object_cone_active.tga new file mode 100644 index 000000000..6d537ffc0 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_cone_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_cube.tga b/indra/newview/skins/Blackdark/textures/object_cube.tga new file mode 100644 index 000000000..4ff84f30a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_cube.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_cube_active.tga b/indra/newview/skins/Blackdark/textures/object_cube_active.tga new file mode 100644 index 000000000..69baee736 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_cube_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_cylinder.tga b/indra/newview/skins/Blackdark/textures/object_cylinder.tga new file mode 100644 index 000000000..bf379550b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_cylinder.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_cylinder_active.tga b/indra/newview/skins/Blackdark/textures/object_cylinder_active.tga new file mode 100644 index 000000000..fdf9edc10 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_cylinder_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_grass.tga b/indra/newview/skins/Blackdark/textures/object_grass.tga new file mode 100644 index 000000000..4ab3ee64d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_grass.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_grass_active.tga b/indra/newview/skins/Blackdark/textures/object_grass_active.tga new file mode 100644 index 000000000..4457a81b8 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_grass_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_hemi_cone.tga b/indra/newview/skins/Blackdark/textures/object_hemi_cone.tga new file mode 100644 index 000000000..89b17d3dc Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_hemi_cone.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_hemi_cone_active.tga b/indra/newview/skins/Blackdark/textures/object_hemi_cone_active.tga new file mode 100644 index 000000000..1cffd21f3 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_hemi_cone_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_hemi_cylinder.tga b/indra/newview/skins/Blackdark/textures/object_hemi_cylinder.tga new file mode 100644 index 000000000..933c42f52 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_hemi_cylinder.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_hemi_cylinder_active.tga b/indra/newview/skins/Blackdark/textures/object_hemi_cylinder_active.tga new file mode 100644 index 000000000..18ee8cf14 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_hemi_cylinder_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_hemi_sphere.tga b/indra/newview/skins/Blackdark/textures/object_hemi_sphere.tga new file mode 100644 index 000000000..7293b45a7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_hemi_sphere.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_hemi_sphere_active.tga b/indra/newview/skins/Blackdark/textures/object_hemi_sphere_active.tga new file mode 100644 index 000000000..5fe5bbf3c Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_hemi_sphere_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_prism.tga b/indra/newview/skins/Blackdark/textures/object_prism.tga new file mode 100644 index 000000000..f1fccda62 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_prism.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_prism_active.tga b/indra/newview/skins/Blackdark/textures/object_prism_active.tga new file mode 100644 index 000000000..30f16efb1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_prism_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_pyramid.tga b/indra/newview/skins/Blackdark/textures/object_pyramid.tga new file mode 100644 index 000000000..f4d1d46e1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_pyramid.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_pyramid_active.tga b/indra/newview/skins/Blackdark/textures/object_pyramid_active.tga new file mode 100644 index 000000000..9b2e5ceab Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_pyramid_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_ring.tga b/indra/newview/skins/Blackdark/textures/object_ring.tga new file mode 100644 index 000000000..aaf5783f5 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_ring.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_ring_active.tga b/indra/newview/skins/Blackdark/textures/object_ring_active.tga new file mode 100644 index 000000000..2e133b3bf Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_ring_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_sphere.tga b/indra/newview/skins/Blackdark/textures/object_sphere.tga new file mode 100644 index 000000000..5875478ba Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_sphere.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_sphere_active.tga b/indra/newview/skins/Blackdark/textures/object_sphere_active.tga new file mode 100644 index 000000000..0abbb0247 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_sphere_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_tetrahedron.tga b/indra/newview/skins/Blackdark/textures/object_tetrahedron.tga new file mode 100644 index 000000000..808456f85 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_tetrahedron.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_tetrahedron_active.tga b/indra/newview/skins/Blackdark/textures/object_tetrahedron_active.tga new file mode 100644 index 000000000..3eedb5b92 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_tetrahedron_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_torus.tga b/indra/newview/skins/Blackdark/textures/object_torus.tga new file mode 100644 index 000000000..3ef02f88d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_torus.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_torus_active.tga b/indra/newview/skins/Blackdark/textures/object_torus_active.tga new file mode 100644 index 000000000..df5120ae4 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_torus_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_tree.tga b/indra/newview/skins/Blackdark/textures/object_tree.tga new file mode 100644 index 000000000..b4df5cd6c Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_tree.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_tree_active.tga b/indra/newview/skins/Blackdark/textures/object_tree_active.tga new file mode 100644 index 000000000..38099b213 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_tree_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_tube.tga b/indra/newview/skins/Blackdark/textures/object_tube.tga new file mode 100644 index 000000000..c89c56846 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_tube.tga differ diff --git a/indra/newview/skins/Blackdark/textures/object_tube_active.tga b/indra/newview/skins/Blackdark/textures/object_tube_active.tga new file mode 100644 index 000000000..1ba9ebc70 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/object_tube_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/preview.png b/indra/newview/skins/Blackdark/textures/preview.png new file mode 100644 index 000000000..2022d7c88 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/preview.png differ diff --git a/indra/newview/skins/Blackdark/textures/progress_fill.tga b/indra/newview/skins/Blackdark/textures/progress_fill.tga new file mode 100644 index 000000000..bbdf5dd0b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/progress_fill.tga differ diff --git a/indra/newview/skins/Blackdark/textures/progressbar_fill.tga b/indra/newview/skins/Blackdark/textures/progressbar_fill.tga new file mode 100644 index 000000000..144c18790 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/progressbar_fill.tga differ diff --git a/indra/newview/skins/Blackdark/textures/progressbar_track.tga b/indra/newview/skins/Blackdark/textures/progressbar_track.tga new file mode 100644 index 000000000..4b84e9ec9 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/progressbar_track.tga differ diff --git a/indra/newview/skins/Blackdark/textures/ptt_lock_off.tga b/indra/newview/skins/Blackdark/textures/ptt_lock_off.tga new file mode 100644 index 000000000..d66f49840 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/ptt_lock_off.tga differ diff --git a/indra/newview/skins/Blackdark/textures/ptt_lock_on.tga b/indra/newview/skins/Blackdark/textures/ptt_lock_on.tga new file mode 100644 index 000000000..432db2f00 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/ptt_lock_on.tga differ diff --git a/indra/newview/skins/Blackdark/textures/radio_active_false.tga b/indra/newview/skins/Blackdark/textures/radio_active_false.tga new file mode 100644 index 000000000..6a83f31fe Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/radio_active_false.tga differ diff --git a/indra/newview/skins/Blackdark/textures/radio_active_true.tga b/indra/newview/skins/Blackdark/textures/radio_active_true.tga new file mode 100644 index 000000000..feac2ee2b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/radio_active_true.tga differ diff --git a/indra/newview/skins/Blackdark/textures/radio_inactive_false.tga b/indra/newview/skins/Blackdark/textures/radio_inactive_false.tga new file mode 100644 index 000000000..950f09c39 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/radio_inactive_false.tga differ diff --git a/indra/newview/skins/Blackdark/textures/radio_inactive_true.tga b/indra/newview/skins/Blackdark/textures/radio_inactive_true.tga new file mode 100644 index 000000000..8e57118ae Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/radio_inactive_true.tga differ diff --git a/indra/newview/skins/Blackdark/textures/resize_handle_bottom_right_blue.tga b/indra/newview/skins/Blackdark/textures/resize_handle_bottom_right_blue.tga new file mode 100644 index 000000000..8290bfa65 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/resize_handle_bottom_right_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/restore.tga b/indra/newview/skins/Blackdark/textures/restore.tga new file mode 100644 index 000000000..5e369fdfc Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/restore.tga differ diff --git a/indra/newview/skins/Blackdark/textures/restore_inactive.tga b/indra/newview/skins/Blackdark/textures/restore_inactive.tga new file mode 100644 index 000000000..ce545d90d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/restore_inactive.tga differ diff --git a/indra/newview/skins/Blackdark/textures/restore_pressed.tga b/indra/newview/skins/Blackdark/textures/restore_pressed.tga new file mode 100644 index 000000000..8a25087be Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/restore_pressed.tga differ diff --git a/indra/newview/skins/Blackdark/textures/rounded_square.j2c b/indra/newview/skins/Blackdark/textures/rounded_square.j2c new file mode 100644 index 000000000..c3dfe8f10 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/rounded_square.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/rounded_square.tga b/indra/newview/skins/Blackdark/textures/rounded_square.tga new file mode 100644 index 000000000..4f4bf05f8 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/rounded_square.tga differ diff --git a/indra/newview/skins/Blackdark/textures/rounded_square_soft.tga b/indra/newview/skins/Blackdark/textures/rounded_square_soft.tga new file mode 100644 index 000000000..4f4bf05f8 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/rounded_square_soft.tga differ diff --git a/indra/newview/skins/Blackdark/textures/script_error.j2c b/indra/newview/skins/Blackdark/textures/script_error.j2c new file mode 100644 index 000000000..ad6be04a7 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/script_error.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/script_error.tga b/indra/newview/skins/Blackdark/textures/script_error.tga new file mode 100644 index 000000000..8fa12e711 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/script_error.tga differ diff --git a/indra/newview/skins/Blackdark/textures/scrollbutton_down_in_blue.tga b/indra/newview/skins/Blackdark/textures/scrollbutton_down_in_blue.tga new file mode 100644 index 000000000..4bdcf6e14 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/scrollbutton_down_in_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/scrollbutton_down_out_blue.tga b/indra/newview/skins/Blackdark/textures/scrollbutton_down_out_blue.tga new file mode 100644 index 000000000..4bdcf6e14 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/scrollbutton_down_out_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/scrollbutton_left_in_blue.tga b/indra/newview/skins/Blackdark/textures/scrollbutton_left_in_blue.tga new file mode 100644 index 000000000..e90ab295b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/scrollbutton_left_in_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/scrollbutton_left_out_blue.tga b/indra/newview/skins/Blackdark/textures/scrollbutton_left_out_blue.tga new file mode 100644 index 000000000..e90ab295b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/scrollbutton_left_out_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/scrollbutton_right_in_blue.tga b/indra/newview/skins/Blackdark/textures/scrollbutton_right_in_blue.tga new file mode 100644 index 000000000..534ecba91 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/scrollbutton_right_in_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/scrollbutton_right_out_blue.tga b/indra/newview/skins/Blackdark/textures/scrollbutton_right_out_blue.tga new file mode 100644 index 000000000..534ecba91 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/scrollbutton_right_out_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/scrollbutton_up_in_blue.tga b/indra/newview/skins/Blackdark/textures/scrollbutton_up_in_blue.tga new file mode 100644 index 000000000..2e2f58339 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/scrollbutton_up_in_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/scrollbutton_up_out_blue.tga b/indra/newview/skins/Blackdark/textures/scrollbutton_up_out_blue.tga new file mode 100644 index 000000000..2e2f58339 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/scrollbutton_up_out_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/sm_rounded_corners_simple.tga b/indra/newview/skins/Blackdark/textures/sm_rounded_corners_simple.tga new file mode 100644 index 000000000..054fdd39a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/sm_rounded_corners_simple.tga differ diff --git a/indra/newview/skins/Blackdark/textures/spacer24.tga b/indra/newview/skins/Blackdark/textures/spacer24.tga new file mode 100644 index 000000000..c7cab6b38 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/spacer24.tga differ diff --git a/indra/newview/skins/Blackdark/textures/spacer35.tga b/indra/newview/skins/Blackdark/textures/spacer35.tga new file mode 100644 index 000000000..b88bc6680 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/spacer35.tga differ diff --git a/indra/newview/skins/Blackdark/textures/spin_down_in_blue.tga b/indra/newview/skins/Blackdark/textures/spin_down_in_blue.tga new file mode 100644 index 000000000..bcbf526f1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/spin_down_in_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/spin_down_out_blue.tga b/indra/newview/skins/Blackdark/textures/spin_down_out_blue.tga new file mode 100644 index 000000000..1af2ed9cb Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/spin_down_out_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/spin_up_in_blue.tga b/indra/newview/skins/Blackdark/textures/spin_up_in_blue.tga new file mode 100644 index 000000000..6bf3c1306 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/spin_up_in_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/spin_up_out_blue.tga b/indra/newview/skins/Blackdark/textures/spin_up_out_blue.tga new file mode 100644 index 000000000..9a9bc6468 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/spin_up_out_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/square_btn_32x128.tga b/indra/newview/skins/Blackdark/textures/square_btn_32x128.tga new file mode 100644 index 000000000..d23d413aa Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/square_btn_32x128.tga differ diff --git a/indra/newview/skins/Blackdark/textures/square_btn_selected_32x128.tga b/indra/newview/skins/Blackdark/textures/square_btn_selected_32x128.tga new file mode 100644 index 000000000..2f48098d2 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/square_btn_selected_32x128.tga differ diff --git a/indra/newview/skins/Blackdark/textures/startup_logo.j2c b/indra/newview/skins/Blackdark/textures/startup_logo.j2c new file mode 100644 index 000000000..ab28cf37d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/startup_logo.j2c differ diff --git a/indra/newview/skins/Blackdark/textures/status_buy_currency.tga b/indra/newview/skins/Blackdark/textures/status_buy_currency.tga new file mode 100644 index 000000000..f4a28b32b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_buy_currency.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_buy_currency_pressed.tga b/indra/newview/skins/Blackdark/textures/status_buy_currency_pressed.tga new file mode 100644 index 000000000..f4a28b32b Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_buy_currency_pressed.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_buy_land.tga b/indra/newview/skins/Blackdark/textures/status_buy_land.tga new file mode 100644 index 000000000..60c395c03 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_buy_land.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_buy_land_pressed.tga b/indra/newview/skins/Blackdark/textures/status_buy_land_pressed.tga new file mode 100644 index 000000000..60c395c03 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_buy_land_pressed.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_health.tga b/indra/newview/skins/Blackdark/textures/status_health.tga new file mode 100644 index 000000000..f5eefc5a9 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_health.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_no_build.tga b/indra/newview/skins/Blackdark/textures/status_no_build.tga new file mode 100644 index 000000000..41934a600 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_no_build.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_no_fly.tga b/indra/newview/skins/Blackdark/textures/status_no_fly.tga new file mode 100644 index 000000000..0aa7fa71d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_no_fly.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_no_push.tga b/indra/newview/skins/Blackdark/textures/status_no_push.tga new file mode 100644 index 000000000..6d5987217 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_no_push.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_no_scripts.tga b/indra/newview/skins/Blackdark/textures/status_no_scripts.tga new file mode 100644 index 000000000..3bce6ad6f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_no_scripts.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_no_voice.tga b/indra/newview/skins/Blackdark/textures/status_no_voice.tga new file mode 100644 index 000000000..aeeed6ed0 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_no_voice.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_script_debug.tga b/indra/newview/skins/Blackdark/textures/status_script_debug.tga new file mode 100644 index 000000000..7d895eb0a Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_script_debug.tga differ diff --git a/indra/newview/skins/Blackdark/textures/status_search_btn.png b/indra/newview/skins/Blackdark/textures/status_search_btn.png new file mode 100644 index 000000000..b755f6f10 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_search_btn.png differ diff --git a/indra/newview/skins/Blackdark/textures/status_search_btn_pressed.png b/indra/newview/skins/Blackdark/textures/status_search_btn_pressed.png new file mode 100644 index 000000000..c19945885 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_search_btn_pressed.png differ diff --git a/indra/newview/skins/Blackdark/textures/status_voice.tga b/indra/newview/skins/Blackdark/textures/status_voice.tga new file mode 100644 index 000000000..aeeed6ed0 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/status_voice.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tab_bottom_blue.tga b/indra/newview/skins/Blackdark/textures/tab_bottom_blue.tga new file mode 100644 index 000000000..e6de7a5a1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tab_bottom_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tab_bottom_selected_blue.tga b/indra/newview/skins/Blackdark/textures/tab_bottom_selected_blue.tga new file mode 100644 index 000000000..b7f6db9b8 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tab_bottom_selected_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tab_left.tga b/indra/newview/skins/Blackdark/textures/tab_left.tga new file mode 100644 index 000000000..4348b19ce Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tab_left.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tab_left_selected.tga b/indra/newview/skins/Blackdark/textures/tab_left_selected.tga new file mode 100644 index 000000000..63932fc15 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tab_left_selected.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tab_top_blue.tga b/indra/newview/skins/Blackdark/textures/tab_top_blue.tga new file mode 100644 index 000000000..ddcd519f2 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tab_top_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tab_top_selected_blue.tga b/indra/newview/skins/Blackdark/textures/tab_top_selected_blue.tga new file mode 100644 index 000000000..3b7df6e46 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tab_top_selected_blue.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tabarea.tga b/indra/newview/skins/Blackdark/textures/tabarea.tga new file mode 100644 index 000000000..5517aebfc Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tabarea.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tearoff_pressed.tga b/indra/newview/skins/Blackdark/textures/tearoff_pressed.tga new file mode 100644 index 000000000..8581ab701 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tearoff_pressed.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tearoffbox.tga b/indra/newview/skins/Blackdark/textures/tearoffbox.tga new file mode 100644 index 000000000..27af31c4d Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tearoffbox.tga differ diff --git a/indra/newview/skins/Blackdark/textures/textures.xml b/indra/newview/skins/Blackdark/textures/textures.xml new file mode 100644 index 000000000..5955a8ede --- /dev/null +++ b/indra/newview/skins/Blackdark/textures/textures.xml @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/Blackdark/textures/tool_dozer.tga b/indra/newview/skins/Blackdark/textures/tool_dozer.tga new file mode 100644 index 000000000..e4b05a581 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tool_dozer.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tool_dozer_active.tga b/indra/newview/skins/Blackdark/textures/tool_dozer_active.tga new file mode 100644 index 000000000..d76f7d5d1 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tool_dozer_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tool_zoom.tga b/indra/newview/skins/Blackdark/textures/tool_zoom.tga new file mode 100644 index 000000000..72fe14195 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tool_zoom.tga differ diff --git a/indra/newview/skins/Blackdark/textures/tool_zoom_active.tga b/indra/newview/skins/Blackdark/textures/tool_zoom_active.tga new file mode 100644 index 000000000..9579aef2e Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/tool_zoom_active.tga differ diff --git a/indra/newview/skins/Blackdark/textures/toolbar_bg.tga b/indra/newview/skins/Blackdark/textures/toolbar_bg.tga new file mode 100644 index 000000000..dbea376a4 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/toolbar_bg.tga differ diff --git a/indra/newview/skins/Blackdark/textures/toolbar_btn_disabled.tga b/indra/newview/skins/Blackdark/textures/toolbar_btn_disabled.tga new file mode 100644 index 000000000..fd117209f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/toolbar_btn_disabled.tga differ diff --git a/indra/newview/skins/Blackdark/textures/toolbar_btn_enabled.tga b/indra/newview/skins/Blackdark/textures/toolbar_btn_enabled.tga new file mode 100644 index 000000000..fd117209f Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/toolbar_btn_enabled.tga differ diff --git a/indra/newview/skins/Blackdark/textures/toolbar_btn_selected.tga b/indra/newview/skins/Blackdark/textures/toolbar_btn_selected.tga new file mode 100644 index 000000000..86dc40f09 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/toolbar_btn_selected.tga differ diff --git a/indra/newview/skins/Blackdark/textures/toolbar_tab.tga b/indra/newview/skins/Blackdark/textures/toolbar_tab.tga new file mode 100644 index 000000000..610d2f335 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/toolbar_tab.tga differ diff --git a/indra/newview/skins/Blackdark/textures/up_arrow.png b/indra/newview/skins/Blackdark/textures/up_arrow.png new file mode 100644 index 000000000..5c60a61db Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/up_arrow.png differ diff --git a/indra/newview/skins/Blackdark/textures/white.tga b/indra/newview/skins/Blackdark/textures/white.tga new file mode 100644 index 000000000..55e379309 Binary files /dev/null and b/indra/newview/skins/Blackdark/textures/white.tga differ diff --git a/indra/newview/skins/Blacklightblue/License and Credit.txt b/indra/newview/skins/Blacklightblue/License and Credit.txt new file mode 100644 index 000000000..8e57c5ba0 --- /dev/null +++ b/indra/newview/skins/Blacklightblue/License and Credit.txt @@ -0,0 +1,4 @@ +This skin was modified by JB Kraft from the default linden skin provided. +This skin was modified by Chalice Yao from the default linden skin and JB Kraft's skin. + +All Images and modifications done are provided free to use, modify, and distribute, so long as this infomation is distributed with it. diff --git a/indra/newview/skins/Blacklightblue/colors.xml b/indra/newview/skins/Blacklightblue/colors.xml new file mode 100644 index 000000000..ac4ad8772 --- /dev/null +++ b/indra/newview/skins/Blacklightblue/colors.xml @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/Blacklightblue/textures/0098b015-3daf-4cfe-a72f-915369ea97c2.tga b/indra/newview/skins/Blacklightblue/textures/0098b015-3daf-4cfe-a72f-915369ea97c2.tga new file mode 100644 index 000000000..a60bd521f Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/0098b015-3daf-4cfe-a72f-915369ea97c2.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga b/indra/newview/skins/Blacklightblue/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga new file mode 100644 index 000000000..e90ab295b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga b/indra/newview/skins/Blacklightblue/textures/7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga new file mode 100644 index 000000000..b776b11d0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga b/indra/newview/skins/Blacklightblue/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga new file mode 100644 index 000000000..534ecba91 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga b/indra/newview/skins/Blacklightblue/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga new file mode 100644 index 000000000..e90ab295b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/active_speakers.tga b/indra/newview/skins/Blacklightblue/textures/active_speakers.tga new file mode 100644 index 000000000..ec097fcd4 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/active_speakers.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/active_voice_tab.tga b/indra/newview/skins/Blacklightblue/textures/active_voice_tab.tga new file mode 100644 index 000000000..3037e9668 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/active_voice_tab.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/arrow_down.tga b/indra/newview/skins/Blacklightblue/textures/arrow_down.tga new file mode 100644 index 000000000..89a793bcb Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/arrow_down.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/arrow_up.tga b/indra/newview/skins/Blacklightblue/textures/arrow_up.tga new file mode 100644 index 000000000..5b03c5433 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/arrow_up.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/b4870163-6208-42a9-9801-93133bf9a6cd.tga b/indra/newview/skins/Blacklightblue/textures/b4870163-6208-42a9-9801-93133bf9a6cd.tga new file mode 100644 index 000000000..54f7c6ece Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/b4870163-6208-42a9-9801-93133bf9a6cd.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/badge_error.j2c b/indra/newview/skins/Blacklightblue/textures/badge_error.j2c new file mode 100644 index 000000000..efb5c375c Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/badge_error.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/badge_note.j2c b/indra/newview/skins/Blacklightblue/textures/badge_note.j2c new file mode 100644 index 000000000..ef5db9e0d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/badge_note.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/badge_ok.j2c b/indra/newview/skins/Blacklightblue/textures/badge_ok.j2c new file mode 100644 index 000000000..8ceee01c6 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/badge_ok.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/badge_warn.j2c b/indra/newview/skins/Blacklightblue/textures/badge_warn.j2c new file mode 100644 index 000000000..8fb85be69 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/badge_warn.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/btn_chatbar.tga b/indra/newview/skins/Blacklightblue/textures/btn_chatbar.tga new file mode 100644 index 000000000..07117925a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/btn_chatbar.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/btn_chatbar_selected.tga b/indra/newview/skins/Blacklightblue/textures/btn_chatbar_selected.tga new file mode 100644 index 000000000..3446bf168 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/btn_chatbar_selected.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/button_anim_pause.tga b/indra/newview/skins/Blacklightblue/textures/button_anim_pause.tga new file mode 100644 index 000000000..f4ad7adc0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/button_anim_pause.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/button_anim_pause_selected.tga b/indra/newview/skins/Blacklightblue/textures/button_anim_pause_selected.tga new file mode 100644 index 000000000..64268de2c Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/button_anim_pause_selected.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/button_anim_play.tga b/indra/newview/skins/Blacklightblue/textures/button_anim_play.tga new file mode 100644 index 000000000..9843aec5f Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/button_anim_play.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/button_anim_play_selected.tga b/indra/newview/skins/Blacklightblue/textures/button_anim_play_selected.tga new file mode 100644 index 000000000..d102c2b06 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/button_anim_play_selected.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/button_anim_stop.tga b/indra/newview/skins/Blacklightblue/textures/button_anim_stop.tga new file mode 100644 index 000000000..4c28986bf Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/button_anim_stop.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/button_anim_stop_selected.tga b/indra/newview/skins/Blacklightblue/textures/button_anim_stop_selected.tga new file mode 100644 index 000000000..afb1536e0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/button_anim_stop_selected.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/button_disabled_32x128.tga b/indra/newview/skins/Blacklightblue/textures/button_disabled_32x128.tga new file mode 100644 index 000000000..d33fbe464 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/button_disabled_32x128.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/button_enabled_32x128.tga b/indra/newview/skins/Blacklightblue/textures/button_enabled_32x128.tga new file mode 100644 index 000000000..d33fbe464 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/button_enabled_32x128.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/button_enabled_selected_32x128.tga b/indra/newview/skins/Blacklightblue/textures/button_enabled_selected_32x128.tga new file mode 100644 index 000000000..a7ef5b78d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/button_enabled_selected_32x128.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/c1e21504-f136-451d-b8e9-929037812f1d.tga b/indra/newview/skins/Blacklightblue/textures/c1e21504-f136-451d-b8e9-929037812f1d.tga new file mode 100644 index 000000000..0db2e5061 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/c1e21504-f136-451d-b8e9-929037812f1d.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/c63f124c-6340-4fbf-b59e-0869a44adb64.tga b/indra/newview/skins/Blacklightblue/textures/c63f124c-6340-4fbf-b59e-0869a44adb64.tga new file mode 100644 index 000000000..2e8d54b35 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/c63f124c-6340-4fbf-b59e-0869a44adb64.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/cam_rotate_in.tga b/indra/newview/skins/Blacklightblue/textures/cam_rotate_in.tga new file mode 100644 index 000000000..129c9982e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/cam_rotate_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/cam_rotate_out.tga b/indra/newview/skins/Blacklightblue/textures/cam_rotate_out.tga new file mode 100644 index 000000000..bd7c80e29 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/cam_rotate_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/cam_tracking_in.tga b/indra/newview/skins/Blacklightblue/textures/cam_tracking_in.tga new file mode 100644 index 000000000..1d5b32a3c Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/cam_tracking_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/cam_tracking_out.tga b/indra/newview/skins/Blacklightblue/textures/cam_tracking_out.tga new file mode 100644 index 000000000..8bac4a1f2 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/cam_tracking_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/cam_zoom_minus_in.tga b/indra/newview/skins/Blacklightblue/textures/cam_zoom_minus_in.tga new file mode 100644 index 000000000..58cb426be Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/cam_zoom_minus_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/cam_zoom_out.tga b/indra/newview/skins/Blacklightblue/textures/cam_zoom_out.tga new file mode 100644 index 000000000..6b117abc1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/cam_zoom_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/cam_zoom_plus_in.tga b/indra/newview/skins/Blacklightblue/textures/cam_zoom_plus_in.tga new file mode 100644 index 000000000..c427f4ba9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/cam_zoom_plus_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga b/indra/newview/skins/Blacklightblue/textures/ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga new file mode 100644 index 000000000..dfe32943a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/checkbox_disabled_false.tga b/indra/newview/skins/Blacklightblue/textures/checkbox_disabled_false.tga new file mode 100644 index 000000000..aa57cd211 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/checkbox_disabled_false.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/checkbox_disabled_true.tga b/indra/newview/skins/Blacklightblue/textures/checkbox_disabled_true.tga new file mode 100644 index 000000000..30bc6d4c9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/checkbox_disabled_true.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/checkbox_enabled_false.tga b/indra/newview/skins/Blacklightblue/textures/checkbox_enabled_false.tga new file mode 100644 index 000000000..fb8265b18 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/checkbox_enabled_false.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/checkbox_enabled_true.tga b/indra/newview/skins/Blacklightblue/textures/checkbox_enabled_true.tga new file mode 100644 index 000000000..1b43d2abb Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/checkbox_enabled_true.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/close_in_blue.tga b/indra/newview/skins/Blacklightblue/textures/close_in_blue.tga new file mode 100644 index 000000000..c58e052b8 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/close_in_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/close_inactive_blue.tga b/indra/newview/skins/Blacklightblue/textures/close_inactive_blue.tga new file mode 100644 index 000000000..2f912df59 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/close_inactive_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/closebox.tga b/indra/newview/skins/Blacklightblue/textures/closebox.tga new file mode 100644 index 000000000..5e1195526 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/closebox.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/combobox_arrow.tga b/indra/newview/skins/Blacklightblue/textures/combobox_arrow.tga new file mode 100644 index 000000000..cd592c3df Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/combobox_arrow.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c b/indra/newview/skins/Blacklightblue/textures/d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c new file mode 100644 index 000000000..4b73b25ac Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/default_land_picture.j2c b/indra/newview/skins/Blacklightblue/textures/default_land_picture.j2c new file mode 100644 index 000000000..6e2a85a46 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/default_land_picture.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/default_profile_picture.j2c b/indra/newview/skins/Blacklightblue/textures/default_profile_picture.j2c new file mode 100644 index 000000000..31d741e88 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/default_profile_picture.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/direction_arrow.tga b/indra/newview/skins/Blacklightblue/textures/direction_arrow.tga new file mode 100644 index 000000000..59149e1d5 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/direction_arrow.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/down_arrow.png b/indra/newview/skins/Blacklightblue/textures/down_arrow.png new file mode 100644 index 000000000..88c8c8481 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/down_arrow.png differ diff --git a/indra/newview/skins/Blacklightblue/textures/eye_button_active.tga b/indra/newview/skins/Blacklightblue/textures/eye_button_active.tga new file mode 100644 index 000000000..8cda9a6a0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/eye_button_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/eye_button_inactive.tga b/indra/newview/skins/Blacklightblue/textures/eye_button_inactive.tga new file mode 100644 index 000000000..92a289f11 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/eye_button_inactive.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga b/indra/newview/skins/Blacklightblue/textures/ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga new file mode 100644 index 000000000..534ecba91 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ff_edit_mine_button.tga b/indra/newview/skins/Blacklightblue/textures/ff_edit_mine_button.tga new file mode 100644 index 000000000..d2feac64b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ff_edit_mine_button.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ff_edit_theirs_button.tga b/indra/newview/skins/Blacklightblue/textures/ff_edit_theirs_button.tga new file mode 100644 index 000000000..ae0f5c977 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ff_edit_theirs_button.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ff_online_status_button.tga b/indra/newview/skins/Blacklightblue/textures/ff_online_status_button.tga new file mode 100644 index 000000000..30b70ccd4 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ff_online_status_button.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ff_visible_map.tga b/indra/newview/skins/Blacklightblue/textures/ff_visible_map.tga new file mode 100644 index 000000000..d8ed32336 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ff_visible_map.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ff_visible_map_button.tga b/indra/newview/skins/Blacklightblue/textures/ff_visible_map_button.tga new file mode 100644 index 000000000..ca1bb7697 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ff_visible_map_button.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ff_visible_online.tga b/indra/newview/skins/Blacklightblue/textures/ff_visible_online.tga new file mode 100644 index 000000000..2b76d72ec Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ff_visible_online.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ff_visible_online_button.tga b/indra/newview/skins/Blacklightblue/textures/ff_visible_online_button.tga new file mode 100644 index 000000000..f0a4414e0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ff_visible_online_button.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/flyout_btn_left.tga b/indra/newview/skins/Blacklightblue/textures/flyout_btn_left.tga new file mode 100644 index 000000000..3e4e2625c Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/flyout_btn_left.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/flyout_btn_left_disabled.tga b/indra/newview/skins/Blacklightblue/textures/flyout_btn_left_disabled.tga new file mode 100644 index 000000000..3e4e2625c Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/flyout_btn_left_disabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/flyout_btn_left_selected.tga b/indra/newview/skins/Blacklightblue/textures/flyout_btn_left_selected.tga new file mode 100644 index 000000000..b8e809c57 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/flyout_btn_left_selected.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/flyout_btn_right.tga b/indra/newview/skins/Blacklightblue/textures/flyout_btn_right.tga new file mode 100644 index 000000000..c59ad0043 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/flyout_btn_right.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/flyout_btn_right_disabled.tga b/indra/newview/skins/Blacklightblue/textures/flyout_btn_right_disabled.tga new file mode 100644 index 000000000..c59ad0043 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/flyout_btn_right_disabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/flyout_btn_right_selected.tga b/indra/newview/skins/Blacklightblue/textures/flyout_btn_right_selected.tga new file mode 100644 index 000000000..70afe2d34 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/flyout_btn_right_selected.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/flyout_left.tga b/indra/newview/skins/Blacklightblue/textures/flyout_left.tga new file mode 100644 index 000000000..a759112e1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/flyout_left.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/flyout_left_disabled.tga b/indra/newview/skins/Blacklightblue/textures/flyout_left_disabled.tga new file mode 100644 index 000000000..a759112e1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/flyout_left_disabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/flyout_left_selected.tga b/indra/newview/skins/Blacklightblue/textures/flyout_left_selected.tga new file mode 100644 index 000000000..783dc6270 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/flyout_left_selected.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/folder_arrow.tga b/indra/newview/skins/Blacklightblue/textures/folder_arrow.tga new file mode 100644 index 000000000..734a00a84 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/folder_arrow.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_chatbar.tga b/indra/newview/skins/Blacklightblue/textures/icn_chatbar.tga new file mode 100644 index 000000000..b89dfc432 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_chatbar.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_label_media.tga b/indra/newview/skins/Blacklightblue/textures/icn_label_media.tga new file mode 100644 index 000000000..b16c528e9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_label_media.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_label_music.tga b/indra/newview/skins/Blacklightblue/textures/icn_label_music.tga new file mode 100644 index 000000000..515f170b6 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_label_music.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_label_web.tga b/indra/newview/skins/Blacklightblue/textures/icn_label_web.tga new file mode 100644 index 000000000..6cacfad7a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_label_web.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media-pause_active.tga b/indra/newview/skins/Blacklightblue/textures/icn_media-pause_active.tga new file mode 100644 index 000000000..4d10aff70 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media-pause_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media-pause_disabled.tga b/indra/newview/skins/Blacklightblue/textures/icn_media-pause_disabled.tga new file mode 100644 index 000000000..7689cb709 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media-pause_disabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media-pause_enabled.tga b/indra/newview/skins/Blacklightblue/textures/icn_media-pause_enabled.tga new file mode 100644 index 000000000..6ea800a30 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media-pause_enabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media-play_active.tga b/indra/newview/skins/Blacklightblue/textures/icn_media-play_active.tga new file mode 100644 index 000000000..fb7d843a3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media-play_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media-play_disabled.tga b/indra/newview/skins/Blacklightblue/textures/icn_media-play_disabled.tga new file mode 100644 index 000000000..0306e94c6 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media-play_disabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media-play_enabled.tga b/indra/newview/skins/Blacklightblue/textures/icn_media-play_enabled.tga new file mode 100644 index 000000000..51b6807ae Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media-play_enabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media-stop_active.tga b/indra/newview/skins/Blacklightblue/textures/icn_media-stop_active.tga new file mode 100644 index 000000000..de0644867 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media-stop_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media-stop_disabled.tga b/indra/newview/skins/Blacklightblue/textures/icn_media-stop_disabled.tga new file mode 100644 index 000000000..6c18bbeda Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media-stop_disabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media-stop_enabled.tga b/indra/newview/skins/Blacklightblue/textures/icn_media-stop_enabled.tga new file mode 100644 index 000000000..8738cdc9e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media-stop_enabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media.tga b/indra/newview/skins/Blacklightblue/textures/icn_media.tga new file mode 100644 index 000000000..9743d4708 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media_movie.tga b/indra/newview/skins/Blacklightblue/textures/icn_media_movie.tga new file mode 100644 index 000000000..b16c528e9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media_movie.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_media_web.tga b/indra/newview/skins/Blacklightblue/textures/icn_media_web.tga new file mode 100644 index 000000000..a92ae962b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_media_web.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_music-play.tga b/indra/newview/skins/Blacklightblue/textures/icn_music-play.tga new file mode 100644 index 000000000..4249627ca Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_music-play.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_music.tga b/indra/newview/skins/Blacklightblue/textures/icn_music.tga new file mode 100644 index 000000000..a7c2845dc Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_music.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_pause.tga b/indra/newview/skins/Blacklightblue/textures/icn_pause.tga new file mode 100644 index 000000000..3bc286f5f Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_pause.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_play.tga b/indra/newview/skins/Blacklightblue/textures/icn_play.tga new file mode 100644 index 000000000..a23ef52e3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_play.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_rounded-text-field.tga b/indra/newview/skins/Blacklightblue/textures/icn_rounded-text-field.tga new file mode 100644 index 000000000..1f1e72572 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_rounded-text-field.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_slide-groove_dark.tga b/indra/newview/skins/Blacklightblue/textures/icn_slide-groove_dark.tga new file mode 100644 index 000000000..9b9c2e4c4 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_slide-groove_dark.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_slide-highlight.tga b/indra/newview/skins/Blacklightblue/textures/icn_slide-highlight.tga new file mode 100644 index 000000000..d371cd066 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_slide-highlight.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_slide-thumb_dark.tga b/indra/newview/skins/Blacklightblue/textures/icn_slide-thumb_dark.tga new file mode 100644 index 000000000..dd34dc0df Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_slide-thumb_dark.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_speaker-muted_dark.tga b/indra/newview/skins/Blacklightblue/textures/icn_speaker-muted_dark.tga new file mode 100644 index 000000000..8f2c80dd2 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_speaker-muted_dark.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_speaker_dark.tga b/indra/newview/skins/Blacklightblue/textures/icn_speaker_dark.tga new file mode 100644 index 000000000..c2ee04044 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_speaker_dark.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_stop.tga b/indra/newview/skins/Blacklightblue/textures/icn_stop.tga new file mode 100644 index 000000000..2925b3853 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_stop.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_toolbar_radar.tga b/indra/newview/skins/Blacklightblue/textures/icn_toolbar_radar.tga new file mode 100644 index 000000000..d1a55ed74 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_toolbar_radar.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_voice-groupfocus.tga b/indra/newview/skins/Blacklightblue/textures/icn_voice-groupfocus.tga new file mode 100644 index 000000000..913bd0969 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_voice-groupfocus.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_voice-localchat.tga b/indra/newview/skins/Blacklightblue/textures/icn_voice-localchat.tga new file mode 100644 index 000000000..5c1456602 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_voice-localchat.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_voice-pvtfocus.tga b/indra/newview/skins/Blacklightblue/textures/icn_voice-pvtfocus.tga new file mode 100644 index 000000000..76e72fd3a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_voice-pvtfocus.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-off.tga b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-off.tga new file mode 100644 index 000000000..530425dd7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-off.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on-lvl1.tga b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on-lvl1.tga new file mode 100644 index 000000000..b64551cc0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on-lvl1.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on-lvl2.tga b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on-lvl2.tga new file mode 100644 index 000000000..348591e3d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on-lvl2.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on-lvl3.tga b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on-lvl3.tga new file mode 100644 index 000000000..081265efb Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on-lvl3.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on.tga b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on.tga new file mode 100644 index 000000000..f9eb32926 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icn_voice_ptt-on.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_auction.tga b/indra/newview/skins/Blacklightblue/textures/icon_auction.tga new file mode 100644 index 000000000..3aa21d323 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_auction.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_avatar_offline.tga b/indra/newview/skins/Blacklightblue/textures/icon_avatar_offline.tga new file mode 100644 index 000000000..620e0f7c1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_avatar_offline.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_avatar_online.tga b/indra/newview/skins/Blacklightblue/textures/icon_avatar_online.tga new file mode 100644 index 000000000..6350237ee Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_avatar_online.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_diurnal.tga b/indra/newview/skins/Blacklightblue/textures/icon_diurnal.tga new file mode 100644 index 000000000..fc720c826 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_diurnal.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_event.tga b/indra/newview/skins/Blacklightblue/textures/icon_event.tga new file mode 100644 index 000000000..23f246b91 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_event.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_event_adult.tga b/indra/newview/skins/Blacklightblue/textures/icon_event_adult.tga new file mode 100644 index 000000000..7202e6734 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_event_adult.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_event_mature.tga b/indra/newview/skins/Blacklightblue/textures/icon_event_mature.tga new file mode 100644 index 000000000..103c5e535 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_event_mature.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_for_sale.tga b/indra/newview/skins/Blacklightblue/textures/icon_for_sale.tga new file mode 100644 index 000000000..09405d383 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_for_sale.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_for_sale_adult.tga b/indra/newview/skins/Blacklightblue/textures/icon_for_sale_adult.tga new file mode 100644 index 000000000..147f724e7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_for_sale_adult.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_group.tga b/indra/newview/skins/Blacklightblue/textures/icon_group.tga new file mode 100644 index 000000000..1e5c31aa3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_group.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_groupnotice.tga b/indra/newview/skins/Blacklightblue/textures/icon_groupnotice.tga new file mode 100644 index 000000000..6b312a9ec Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_groupnotice.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_groupnoticeinventory.tga b/indra/newview/skins/Blacklightblue/textures/icon_groupnoticeinventory.tga new file mode 100644 index 000000000..06f59e583 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_groupnoticeinventory.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_lock.tga b/indra/newview/skins/Blacklightblue/textures/icon_lock.tga new file mode 100644 index 000000000..5de6cc10e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_lock.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_place.tga b/indra/newview/skins/Blacklightblue/textures/icon_place.tga new file mode 100644 index 000000000..7f842ba65 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_place.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_popular.tga b/indra/newview/skins/Blacklightblue/textures/icon_popular.tga new file mode 100644 index 000000000..6bdc6ede3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_popular.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/icon_top_pick.tga b/indra/newview/skins/Blacklightblue/textures/icon_top_pick.tga new file mode 100644 index 000000000..4466e8be7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/icon_top_pick.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_animation.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_animation.tga new file mode 100644 index 000000000..ffe56a15f Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_animation.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_bodypart.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_bodypart.tga new file mode 100644 index 000000000..10076c380 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_bodypart.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_callingcard.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_callingcard.tga new file mode 100644 index 000000000..b5d08a816 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_callingcard.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_clothing.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_clothing.tga new file mode 100644 index 000000000..5467b3bf8 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_clothing.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_gesture.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_gesture.tga new file mode 100644 index 000000000..400a8e5c7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_gesture.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_landmark.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_landmark.tga new file mode 100644 index 000000000..901526259 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_landmark.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_lostandfound.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_lostandfound.tga new file mode 100644 index 000000000..7451c35b8 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_lostandfound.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_notecard.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_notecard.tga new file mode 100644 index 000000000..d8ebca11a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_notecard.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_object.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_object.tga new file mode 100644 index 000000000..c7951ccce Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_object.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_plain_closed.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_plain_closed.tga new file mode 100644 index 000000000..b46f97d11 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_plain_closed.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_plain_open.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_plain_open.tga new file mode 100644 index 000000000..c4b0f3f61 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_plain_open.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_script.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_script.tga new file mode 100644 index 000000000..c280d4282 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_script.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_snapshot.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_snapshot.tga new file mode 100644 index 000000000..8b2dfa5fa Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_snapshot.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_sound.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_sound.tga new file mode 100644 index 000000000..e0ebed0d3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_sound.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_texture.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_texture.tga new file mode 100644 index 000000000..2d69c84f6 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_texture.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_folder_trash.tga b/indra/newview/skins/Blacklightblue/textures/inv_folder_trash.tga new file mode 100644 index 000000000..e6ffad1e0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_folder_trash.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_animation.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_animation.tga new file mode 100644 index 000000000..715189fda Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_animation.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_attach.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_attach.tga new file mode 100644 index 000000000..2da7ef8e7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_attach.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_callingcard_offline.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_callingcard_offline.tga new file mode 100644 index 000000000..70e7a2645 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_callingcard_offline.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_callingcard_online.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_callingcard_online.tga new file mode 100644 index 000000000..8e394063b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_callingcard_online.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_clothing.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_clothing.tga new file mode 100644 index 000000000..b41096371 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_clothing.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_eyes.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_eyes.tga new file mode 100644 index 000000000..0cfebb69d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_eyes.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_gesture.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_gesture.tga new file mode 100644 index 000000000..95c1da44e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_gesture.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_gloves.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_gloves.tga new file mode 100644 index 000000000..6f55738ee Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_gloves.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_hair.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_hair.tga new file mode 100644 index 000000000..13ffe09c3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_hair.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_jacket.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_jacket.tga new file mode 100644 index 000000000..a1b518c63 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_jacket.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_landmark.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_landmark.tga new file mode 100644 index 000000000..addf5eb0e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_landmark.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_landmark_visited.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_landmark_visited.tga new file mode 100644 index 000000000..b16f9a1b8 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_landmark_visited.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_notecard.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_notecard.tga new file mode 100644 index 000000000..c7b3bf557 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_notecard.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_object.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_object.tga new file mode 100644 index 000000000..9c407b1d5 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_object.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_object_multi.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_object_multi.tga new file mode 100644 index 000000000..d2ed12df3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_object_multi.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_pants.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_pants.tga new file mode 100644 index 000000000..517c94712 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_pants.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_script.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_script.tga new file mode 100644 index 000000000..8e602f595 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_script.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_script_dangerous.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_script_dangerous.tga new file mode 100644 index 000000000..b5a1bc947 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_script_dangerous.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_shape.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_shape.tga new file mode 100644 index 000000000..d28bb2583 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_shape.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_shirt.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_shirt.tga new file mode 100644 index 000000000..b41096371 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_shirt.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_shoes.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_shoes.tga new file mode 100644 index 000000000..f124ed458 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_shoes.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_skin.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_skin.tga new file mode 100644 index 000000000..169fbc1d5 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_skin.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_skirt.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_skirt.tga new file mode 100644 index 000000000..cd0292210 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_skirt.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_snapshot.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_snapshot.tga new file mode 100644 index 000000000..fcf7316bd Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_snapshot.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_socks.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_socks.tga new file mode 100644 index 000000000..0ccb575ce Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_socks.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_sound.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_sound.tga new file mode 100644 index 000000000..1bb8adfa1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_sound.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_texture.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_texture.tga new file mode 100644 index 000000000..7016ae080 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_texture.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_underpants.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_underpants.tga new file mode 100644 index 000000000..b9f29c688 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_underpants.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/inv_item_undershirt.tga b/indra/newview/skins/Blacklightblue/textures/inv_item_undershirt.tga new file mode 100644 index 000000000..a62b1d853 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/inv_item_undershirt.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_avatar_16.tga b/indra/newview/skins/Blacklightblue/textures/map_avatar_16.tga new file mode 100644 index 000000000..42d8c1e29 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_avatar_16.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_avatar_8.tga b/indra/newview/skins/Blacklightblue/textures/map_avatar_8.tga new file mode 100644 index 000000000..7eb7c20f1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_avatar_8.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_avatar_above_8.tga b/indra/newview/skins/Blacklightblue/textures/map_avatar_above_8.tga new file mode 100644 index 000000000..6faefccc7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_avatar_above_8.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_avatar_below_8.tga b/indra/newview/skins/Blacklightblue/textures/map_avatar_below_8.tga new file mode 100644 index 000000000..5ad671c26 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_avatar_below_8.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_avatar_you_8.tga b/indra/newview/skins/Blacklightblue/textures/map_avatar_you_8.tga new file mode 100644 index 000000000..a865e017b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_avatar_you_8.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_event.tga b/indra/newview/skins/Blacklightblue/textures/map_event.tga new file mode 100644 index 000000000..103c5e535 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_event.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_event_adult.tga b/indra/newview/skins/Blacklightblue/textures/map_event_adult.tga new file mode 100644 index 000000000..7202e6734 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_event_adult.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_event_mature.tga b/indra/newview/skins/Blacklightblue/textures/map_event_mature.tga new file mode 100644 index 000000000..23f246b91 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_event_mature.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_home.tga b/indra/newview/skins/Blacklightblue/textures/map_home.tga new file mode 100644 index 000000000..85dde9ef7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_home.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_infohub.tga b/indra/newview/skins/Blacklightblue/textures/map_infohub.tga new file mode 100644 index 000000000..173b93e39 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_infohub.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_telehub.tga b/indra/newview/skins/Blacklightblue/textures/map_telehub.tga new file mode 100644 index 000000000..d89bcfa40 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_telehub.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_track_16.tga b/indra/newview/skins/Blacklightblue/textures/map_track_16.tga new file mode 100644 index 000000000..14d49b93b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_track_16.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/map_track_8.tga b/indra/newview/skins/Blacklightblue/textures/map_track_8.tga new file mode 100644 index 000000000..d9605dde1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/map_track_8.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/media_icon.tga b/indra/newview/skins/Blacklightblue/textures/media_icon.tga new file mode 100644 index 000000000..868da3734 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/media_icon.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/minimize.tga b/indra/newview/skins/Blacklightblue/textures/minimize.tga new file mode 100644 index 000000000..151a3078f Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/minimize.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/minimize_inactive.tga b/indra/newview/skins/Blacklightblue/textures/minimize_inactive.tga new file mode 100644 index 000000000..d7e1b4057 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/minimize_inactive.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/minimize_pressed.tga b/indra/newview/skins/Blacklightblue/textures/minimize_pressed.tga new file mode 100644 index 000000000..573452ce9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/minimize_pressed.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_backward_in.tga b/indra/newview/skins/Blacklightblue/textures/move_backward_in.tga new file mode 100644 index 000000000..74bfba196 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_backward_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_backward_out.tga b/indra/newview/skins/Blacklightblue/textures/move_backward_out.tga new file mode 100644 index 000000000..0cb143cd8 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_backward_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_down_in.tga b/indra/newview/skins/Blacklightblue/textures/move_down_in.tga new file mode 100644 index 000000000..90b0c76d5 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_down_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_down_out.tga b/indra/newview/skins/Blacklightblue/textures/move_down_out.tga new file mode 100644 index 000000000..93058b043 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_down_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_forward_in.tga b/indra/newview/skins/Blacklightblue/textures/move_forward_in.tga new file mode 100644 index 000000000..5f1735552 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_forward_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_forward_out.tga b/indra/newview/skins/Blacklightblue/textures/move_forward_out.tga new file mode 100644 index 000000000..e5c826b9b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_forward_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_left_in.tga b/indra/newview/skins/Blacklightblue/textures/move_left_in.tga new file mode 100644 index 000000000..8ba5abdd2 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_left_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_left_out.tga b/indra/newview/skins/Blacklightblue/textures/move_left_out.tga new file mode 100644 index 000000000..a428f9739 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_left_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_right_in.tga b/indra/newview/skins/Blacklightblue/textures/move_right_in.tga new file mode 100644 index 000000000..6dd30876f Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_right_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_right_out.tga b/indra/newview/skins/Blacklightblue/textures/move_right_out.tga new file mode 100644 index 000000000..bfce731ab Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_right_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_turn_left_in.tga b/indra/newview/skins/Blacklightblue/textures/move_turn_left_in.tga new file mode 100644 index 000000000..db410d697 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_turn_left_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_turn_left_out.tga b/indra/newview/skins/Blacklightblue/textures/move_turn_left_out.tga new file mode 100644 index 000000000..31bcc42a1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_turn_left_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_turn_right_in.tga b/indra/newview/skins/Blacklightblue/textures/move_turn_right_in.tga new file mode 100644 index 000000000..e22898c2a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_turn_right_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_turn_right_out.tga b/indra/newview/skins/Blacklightblue/textures/move_turn_right_out.tga new file mode 100644 index 000000000..69fb9f400 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_turn_right_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_up_in.tga b/indra/newview/skins/Blacklightblue/textures/move_up_in.tga new file mode 100644 index 000000000..54c641f5b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_up_in.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/move_up_out.tga b/indra/newview/skins/Blacklightblue/textures/move_up_out.tga new file mode 100644 index 000000000..28e6f60aa Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/move_up_out.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/mute_icon.tga b/indra/newview/skins/Blacklightblue/textures/mute_icon.tga new file mode 100644 index 000000000..879b9e618 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/mute_icon.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/notify_box_icon.tga b/indra/newview/skins/Blacklightblue/textures/notify_box_icon.tga new file mode 100644 index 000000000..880aca9b4 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/notify_box_icon.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/notify_caution_icon.tga b/indra/newview/skins/Blacklightblue/textures/notify_caution_icon.tga new file mode 100644 index 000000000..ac6660c16 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/notify_caution_icon.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/notify_next.png b/indra/newview/skins/Blacklightblue/textures/notify_next.png new file mode 100644 index 000000000..9b371e03e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/notify_next.png differ diff --git a/indra/newview/skins/Blacklightblue/textures/notify_tip_icon.tga b/indra/newview/skins/Blacklightblue/textures/notify_tip_icon.tga new file mode 100644 index 000000000..0451da099 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/notify_tip_icon.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_cone.tga b/indra/newview/skins/Blacklightblue/textures/object_cone.tga new file mode 100644 index 000000000..3cd51dfeb Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_cone.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_cone_active.tga b/indra/newview/skins/Blacklightblue/textures/object_cone_active.tga new file mode 100644 index 000000000..ab8137c05 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_cone_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_cube.tga b/indra/newview/skins/Blacklightblue/textures/object_cube.tga new file mode 100644 index 000000000..3395522c2 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_cube.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_cube_active.tga b/indra/newview/skins/Blacklightblue/textures/object_cube_active.tga new file mode 100644 index 000000000..40886cf0d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_cube_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_cylinder.tga b/indra/newview/skins/Blacklightblue/textures/object_cylinder.tga new file mode 100644 index 000000000..2d13f3be6 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_cylinder.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_cylinder_active.tga b/indra/newview/skins/Blacklightblue/textures/object_cylinder_active.tga new file mode 100644 index 000000000..328d10355 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_cylinder_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_grass.tga b/indra/newview/skins/Blacklightblue/textures/object_grass.tga new file mode 100644 index 000000000..8b1943d18 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_grass.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_grass_active.tga b/indra/newview/skins/Blacklightblue/textures/object_grass_active.tga new file mode 100644 index 000000000..55cdbaa3a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_grass_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_hemi_cone.tga b/indra/newview/skins/Blacklightblue/textures/object_hemi_cone.tga new file mode 100644 index 000000000..2cd4a33b0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_hemi_cone.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_hemi_cone_active.tga b/indra/newview/skins/Blacklightblue/textures/object_hemi_cone_active.tga new file mode 100644 index 000000000..459c723b9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_hemi_cone_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_hemi_cylinder.tga b/indra/newview/skins/Blacklightblue/textures/object_hemi_cylinder.tga new file mode 100644 index 000000000..669f78f89 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_hemi_cylinder.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_hemi_cylinder_active.tga b/indra/newview/skins/Blacklightblue/textures/object_hemi_cylinder_active.tga new file mode 100644 index 000000000..154ab9b13 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_hemi_cylinder_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_hemi_sphere.tga b/indra/newview/skins/Blacklightblue/textures/object_hemi_sphere.tga new file mode 100644 index 000000000..d1815a5a9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_hemi_sphere.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_hemi_sphere_active.tga b/indra/newview/skins/Blacklightblue/textures/object_hemi_sphere_active.tga new file mode 100644 index 000000000..e5e0c45c7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_hemi_sphere_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_prism.tga b/indra/newview/skins/Blacklightblue/textures/object_prism.tga new file mode 100644 index 000000000..099026cc4 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_prism.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_prism_active.tga b/indra/newview/skins/Blacklightblue/textures/object_prism_active.tga new file mode 100644 index 000000000..fa9d0b98d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_prism_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_pyramid.tga b/indra/newview/skins/Blacklightblue/textures/object_pyramid.tga new file mode 100644 index 000000000..7927c8b4e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_pyramid.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_pyramid_active.tga b/indra/newview/skins/Blacklightblue/textures/object_pyramid_active.tga new file mode 100644 index 000000000..b20b33e26 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_pyramid_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_ring.tga b/indra/newview/skins/Blacklightblue/textures/object_ring.tga new file mode 100644 index 000000000..49603f1bd Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_ring.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_ring_active.tga b/indra/newview/skins/Blacklightblue/textures/object_ring_active.tga new file mode 100644 index 000000000..0229818c6 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_ring_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_sphere.tga b/indra/newview/skins/Blacklightblue/textures/object_sphere.tga new file mode 100644 index 000000000..7bfae3b6d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_sphere.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_sphere_active.tga b/indra/newview/skins/Blacklightblue/textures/object_sphere_active.tga new file mode 100644 index 000000000..6d27f4fc1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_sphere_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_tetrahedron.tga b/indra/newview/skins/Blacklightblue/textures/object_tetrahedron.tga new file mode 100644 index 000000000..717881b4e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_tetrahedron.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_tetrahedron_active.tga b/indra/newview/skins/Blacklightblue/textures/object_tetrahedron_active.tga new file mode 100644 index 000000000..fc0a609f6 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_tetrahedron_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_torus.tga b/indra/newview/skins/Blacklightblue/textures/object_torus.tga new file mode 100644 index 000000000..33d493106 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_torus.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_torus_active.tga b/indra/newview/skins/Blacklightblue/textures/object_torus_active.tga new file mode 100644 index 000000000..44f42ed8e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_torus_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_tree.tga b/indra/newview/skins/Blacklightblue/textures/object_tree.tga new file mode 100644 index 000000000..880a2fa2a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_tree.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_tree_active.tga b/indra/newview/skins/Blacklightblue/textures/object_tree_active.tga new file mode 100644 index 000000000..219f1f829 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_tree_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_tube.tga b/indra/newview/skins/Blacklightblue/textures/object_tube.tga new file mode 100644 index 000000000..49ee35ede Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_tube.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/object_tube_active.tga b/indra/newview/skins/Blacklightblue/textures/object_tube_active.tga new file mode 100644 index 000000000..655ebb01f Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/object_tube_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/preview.png b/indra/newview/skins/Blacklightblue/textures/preview.png new file mode 100644 index 000000000..57c16eaf3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/preview.png differ diff --git a/indra/newview/skins/Blacklightblue/textures/progress_fill.tga b/indra/newview/skins/Blacklightblue/textures/progress_fill.tga new file mode 100644 index 000000000..a5363463a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/progress_fill.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/progressbar_fill.tga b/indra/newview/skins/Blacklightblue/textures/progressbar_fill.tga new file mode 100644 index 000000000..266f47288 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/progressbar_fill.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/progressbar_track.tga b/indra/newview/skins/Blacklightblue/textures/progressbar_track.tga new file mode 100644 index 000000000..4b84e9ec9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/progressbar_track.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ptt_lock_off.tga b/indra/newview/skins/Blacklightblue/textures/ptt_lock_off.tga new file mode 100644 index 000000000..d66f49840 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ptt_lock_off.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/ptt_lock_on.tga b/indra/newview/skins/Blacklightblue/textures/ptt_lock_on.tga new file mode 100644 index 000000000..432db2f00 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/ptt_lock_on.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/radio_active_false.tga b/indra/newview/skins/Blacklightblue/textures/radio_active_false.tga new file mode 100644 index 000000000..3fdaecb5b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/radio_active_false.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/radio_active_true.tga b/indra/newview/skins/Blacklightblue/textures/radio_active_true.tga new file mode 100644 index 000000000..8d7520a21 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/radio_active_true.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/radio_inactive_false.tga b/indra/newview/skins/Blacklightblue/textures/radio_inactive_false.tga new file mode 100644 index 000000000..6cc182a27 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/radio_inactive_false.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/radio_inactive_true.tga b/indra/newview/skins/Blacklightblue/textures/radio_inactive_true.tga new file mode 100644 index 000000000..c8a4e5b2c Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/radio_inactive_true.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/resize_handle_bottom_right_blue.tga b/indra/newview/skins/Blacklightblue/textures/resize_handle_bottom_right_blue.tga new file mode 100644 index 000000000..8290bfa65 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/resize_handle_bottom_right_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/restore.tga b/indra/newview/skins/Blacklightblue/textures/restore.tga new file mode 100644 index 000000000..5e369fdfc Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/restore.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/restore_inactive.tga b/indra/newview/skins/Blacklightblue/textures/restore_inactive.tga new file mode 100644 index 000000000..ce545d90d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/restore_inactive.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/restore_pressed.tga b/indra/newview/skins/Blacklightblue/textures/restore_pressed.tga new file mode 100644 index 000000000..8a25087be Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/restore_pressed.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/rounded_square.j2c b/indra/newview/skins/Blacklightblue/textures/rounded_square.j2c new file mode 100644 index 000000000..c3dfe8f10 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/rounded_square.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/rounded_square.tga b/indra/newview/skins/Blacklightblue/textures/rounded_square.tga new file mode 100644 index 000000000..4f4bf05f8 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/rounded_square.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/rounded_square_soft.tga b/indra/newview/skins/Blacklightblue/textures/rounded_square_soft.tga new file mode 100644 index 000000000..4f4bf05f8 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/rounded_square_soft.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/script_error.j2c b/indra/newview/skins/Blacklightblue/textures/script_error.j2c new file mode 100644 index 000000000..ad6be04a7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/script_error.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/script_error.tga b/indra/newview/skins/Blacklightblue/textures/script_error.tga new file mode 100644 index 000000000..8fa12e711 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/script_error.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/scrollbutton_down_in_blue.tga b/indra/newview/skins/Blacklightblue/textures/scrollbutton_down_in_blue.tga new file mode 100644 index 000000000..cd592c3df Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/scrollbutton_down_in_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/scrollbutton_down_out_blue.tga b/indra/newview/skins/Blacklightblue/textures/scrollbutton_down_out_blue.tga new file mode 100644 index 000000000..cd592c3df Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/scrollbutton_down_out_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/scrollbutton_left_in_blue.tga b/indra/newview/skins/Blacklightblue/textures/scrollbutton_left_in_blue.tga new file mode 100644 index 000000000..b65d199ae Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/scrollbutton_left_in_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/scrollbutton_left_out_blue.tga b/indra/newview/skins/Blacklightblue/textures/scrollbutton_left_out_blue.tga new file mode 100644 index 000000000..b65d199ae Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/scrollbutton_left_out_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/scrollbutton_right_in_blue.tga b/indra/newview/skins/Blacklightblue/textures/scrollbutton_right_in_blue.tga new file mode 100644 index 000000000..9b571add3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/scrollbutton_right_in_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/scrollbutton_right_out_blue.tga b/indra/newview/skins/Blacklightblue/textures/scrollbutton_right_out_blue.tga new file mode 100644 index 000000000..9b571add3 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/scrollbutton_right_out_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/scrollbutton_up_in_blue.tga b/indra/newview/skins/Blacklightblue/textures/scrollbutton_up_in_blue.tga new file mode 100644 index 000000000..8e78742ff Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/scrollbutton_up_in_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/scrollbutton_up_out_blue.tga b/indra/newview/skins/Blacklightblue/textures/scrollbutton_up_out_blue.tga new file mode 100644 index 000000000..8e78742ff Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/scrollbutton_up_out_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/sm_rounded_corners_simple.tga b/indra/newview/skins/Blacklightblue/textures/sm_rounded_corners_simple.tga new file mode 100644 index 000000000..054fdd39a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/sm_rounded_corners_simple.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/smicon_warn.tga b/indra/newview/skins/Blacklightblue/textures/smicon_warn.tga new file mode 100644 index 000000000..de8cce2a7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/smicon_warn.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/spacer24.tga b/indra/newview/skins/Blacklightblue/textures/spacer24.tga new file mode 100644 index 000000000..c7cab6b38 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/spacer24.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/spacer35.tga b/indra/newview/skins/Blacklightblue/textures/spacer35.tga new file mode 100644 index 000000000..b88bc6680 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/spacer35.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/spin_down_in_blue.tga b/indra/newview/skins/Blacklightblue/textures/spin_down_in_blue.tga new file mode 100644 index 000000000..ebf99c3a7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/spin_down_in_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/spin_down_out_blue.tga b/indra/newview/skins/Blacklightblue/textures/spin_down_out_blue.tga new file mode 100644 index 000000000..1af2ed9cb Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/spin_down_out_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/spin_up_in_blue.tga b/indra/newview/skins/Blacklightblue/textures/spin_up_in_blue.tga new file mode 100644 index 000000000..54412201e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/spin_up_in_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/spin_up_out_blue.tga b/indra/newview/skins/Blacklightblue/textures/spin_up_out_blue.tga new file mode 100644 index 000000000..9a9bc6468 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/spin_up_out_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/startup_logo.j2c b/indra/newview/skins/Blacklightblue/textures/startup_logo.j2c new file mode 100644 index 000000000..e0a705489 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/startup_logo.j2c differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_buy_currency.tga b/indra/newview/skins/Blacklightblue/textures/status_buy_currency.tga new file mode 100644 index 000000000..f4a28b32b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_buy_currency.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_buy_currency_pressed.tga b/indra/newview/skins/Blacklightblue/textures/status_buy_currency_pressed.tga new file mode 100644 index 000000000..f4a28b32b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_buy_currency_pressed.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_buy_land.tga b/indra/newview/skins/Blacklightblue/textures/status_buy_land.tga new file mode 100644 index 000000000..60c395c03 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_buy_land.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_buy_land_pressed.tga b/indra/newview/skins/Blacklightblue/textures/status_buy_land_pressed.tga new file mode 100644 index 000000000..60c395c03 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_buy_land_pressed.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_health.tga b/indra/newview/skins/Blacklightblue/textures/status_health.tga new file mode 100644 index 000000000..f5eefc5a9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_health.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_no_build.tga b/indra/newview/skins/Blacklightblue/textures/status_no_build.tga new file mode 100644 index 000000000..41934a600 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_no_build.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_no_fly.tga b/indra/newview/skins/Blacklightblue/textures/status_no_fly.tga new file mode 100644 index 000000000..0aa7fa71d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_no_fly.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_no_push.tga b/indra/newview/skins/Blacklightblue/textures/status_no_push.tga new file mode 100644 index 000000000..6d5987217 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_no_push.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_no_scripts.tga b/indra/newview/skins/Blacklightblue/textures/status_no_scripts.tga new file mode 100644 index 000000000..3bce6ad6f Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_no_scripts.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_no_voice.tga b/indra/newview/skins/Blacklightblue/textures/status_no_voice.tga new file mode 100644 index 000000000..aeeed6ed0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_no_voice.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_script_debug.tga b/indra/newview/skins/Blacklightblue/textures/status_script_debug.tga new file mode 100644 index 000000000..7d895eb0a Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_script_debug.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_search_btn.png b/indra/newview/skins/Blacklightblue/textures/status_search_btn.png new file mode 100644 index 000000000..1798559e7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_search_btn.png differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_search_btn_pressed.png b/indra/newview/skins/Blacklightblue/textures/status_search_btn_pressed.png new file mode 100644 index 000000000..c19945885 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_search_btn_pressed.png differ diff --git a/indra/newview/skins/Blacklightblue/textures/status_voice.tga b/indra/newview/skins/Blacklightblue/textures/status_voice.tga new file mode 100644 index 000000000..aeeed6ed0 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/status_voice.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tab_bottom_blue.tga b/indra/newview/skins/Blacklightblue/textures/tab_bottom_blue.tga new file mode 100644 index 000000000..e6de7a5a1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tab_bottom_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tab_bottom_selected_blue.tga b/indra/newview/skins/Blacklightblue/textures/tab_bottom_selected_blue.tga new file mode 100644 index 000000000..685d4da55 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tab_bottom_selected_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tab_left.tga b/indra/newview/skins/Blacklightblue/textures/tab_left.tga new file mode 100644 index 000000000..0220020e8 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tab_left.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tab_left_selected.tga b/indra/newview/skins/Blacklightblue/textures/tab_left_selected.tga new file mode 100644 index 000000000..485f324d1 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tab_left_selected.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tab_top_blue.tga b/indra/newview/skins/Blacklightblue/textures/tab_top_blue.tga new file mode 100644 index 000000000..ddcd519f2 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tab_top_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tab_top_selected_blue.tga b/indra/newview/skins/Blacklightblue/textures/tab_top_selected_blue.tga new file mode 100644 index 000000000..1e871986e Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tab_top_selected_blue.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tabarea.tga b/indra/newview/skins/Blacklightblue/textures/tabarea.tga new file mode 100644 index 000000000..5517aebfc Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tabarea.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tearoff_pressed.tga b/indra/newview/skins/Blacklightblue/textures/tearoff_pressed.tga new file mode 100644 index 000000000..8581ab701 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tearoff_pressed.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tearoffbox.tga b/indra/newview/skins/Blacklightblue/textures/tearoffbox.tga new file mode 100644 index 000000000..27af31c4d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tearoffbox.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/textures.xml b/indra/newview/skins/Blacklightblue/textures/textures.xml new file mode 100644 index 000000000..5955a8ede --- /dev/null +++ b/indra/newview/skins/Blacklightblue/textures/textures.xml @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/Blacklightblue/textures/tool_dozer.tga b/indra/newview/skins/Blacklightblue/textures/tool_dozer.tga new file mode 100644 index 000000000..bf3a8999d Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tool_dozer.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tool_dozer_active.tga b/indra/newview/skins/Blacklightblue/textures/tool_dozer_active.tga new file mode 100644 index 000000000..09c0e79f9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tool_dozer_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tool_zoom.tga b/indra/newview/skins/Blacklightblue/textures/tool_zoom.tga new file mode 100644 index 000000000..67692e95b Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tool_zoom.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/tool_zoom_active.tga b/indra/newview/skins/Blacklightblue/textures/tool_zoom_active.tga new file mode 100644 index 000000000..084ff39be Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/tool_zoom_active.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/toolbar_bg.tga b/indra/newview/skins/Blacklightblue/textures/toolbar_bg.tga new file mode 100644 index 000000000..3a1127611 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/toolbar_bg.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/toolbar_btn_disabled.tga b/indra/newview/skins/Blacklightblue/textures/toolbar_btn_disabled.tga new file mode 100644 index 000000000..d33fbe464 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/toolbar_btn_disabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/toolbar_btn_enabled.tga b/indra/newview/skins/Blacklightblue/textures/toolbar_btn_enabled.tga new file mode 100644 index 000000000..d33fbe464 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/toolbar_btn_enabled.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/toolbar_btn_selected.tga b/indra/newview/skins/Blacklightblue/textures/toolbar_btn_selected.tga new file mode 100644 index 000000000..1b46118b9 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/toolbar_btn_selected.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/toolbar_tab.tga b/indra/newview/skins/Blacklightblue/textures/toolbar_tab.tga new file mode 100644 index 000000000..f9a7d50d2 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/toolbar_tab.tga differ diff --git a/indra/newview/skins/Blacklightblue/textures/up_arrow.png b/indra/newview/skins/Blacklightblue/textures/up_arrow.png new file mode 100644 index 000000000..1e55b6ca7 Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/up_arrow.png differ diff --git a/indra/newview/skins/Blacklightblue/textures/up_arrow.tga b/indra/newview/skins/Blacklightblue/textures/up_arrow.tga new file mode 100644 index 000000000..4dcb587ca Binary files /dev/null and b/indra/newview/skins/Blacklightblue/textures/up_arrow.tga differ diff --git a/indra/newview/skins/Blackred/License and Credit.txt b/indra/newview/skins/Blackred/License and Credit.txt new file mode 100644 index 000000000..fe1f04c89 --- /dev/null +++ b/indra/newview/skins/Blackred/License and Credit.txt @@ -0,0 +1,6 @@ +This skin was modified by JB Kraft from the default linden skin provided. +This skin was modified by Chalice Yao from the default linden skin and JB Kraft's skin. +This skin was modified by LordGregGreg Back from the default linden skin and JB Kraft's skin. + + +All Images and modifications done are provided free to use, modify, and distribute, so long as this infomation is distributed with it. diff --git a/indra/newview/skins/Blackred/colors.xml b/indra/newview/skins/Blackred/colors.xml new file mode 100644 index 000000000..640ef35d9 --- /dev/null +++ b/indra/newview/skins/Blackred/colors.xml @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/Blackred/textures/0098b015-3daf-4cfe-a72f-915369ea97c2.tga b/indra/newview/skins/Blackred/textures/0098b015-3daf-4cfe-a72f-915369ea97c2.tga new file mode 100644 index 000000000..d930e8964 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/0098b015-3daf-4cfe-a72f-915369ea97c2.tga differ diff --git a/indra/newview/skins/Blackred/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga b/indra/newview/skins/Blackred/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga new file mode 100644 index 000000000..e90ab295b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga differ diff --git a/indra/newview/skins/Blackred/textures/7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga b/indra/newview/skins/Blackred/textures/7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga new file mode 100644 index 000000000..febd7d6ee Binary files /dev/null and b/indra/newview/skins/Blackred/textures/7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga differ diff --git a/indra/newview/skins/Blackred/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga b/indra/newview/skins/Blackred/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga new file mode 100644 index 000000000..534ecba91 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga differ diff --git a/indra/newview/skins/Blackred/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga b/indra/newview/skins/Blackred/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga new file mode 100644 index 000000000..e90ab295b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga differ diff --git a/indra/newview/skins/Blackred/textures/active_speakers.tga b/indra/newview/skins/Blackred/textures/active_speakers.tga new file mode 100644 index 000000000..492669ee4 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/active_speakers.tga differ diff --git a/indra/newview/skins/Blackred/textures/active_voice_tab.tga b/indra/newview/skins/Blackred/textures/active_voice_tab.tga new file mode 100644 index 000000000..100df0d64 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/active_voice_tab.tga differ diff --git a/indra/newview/skins/Blackred/textures/arrow_down.tga b/indra/newview/skins/Blackred/textures/arrow_down.tga new file mode 100644 index 000000000..89a793bcb Binary files /dev/null and b/indra/newview/skins/Blackred/textures/arrow_down.tga differ diff --git a/indra/newview/skins/Blackred/textures/arrow_up.tga b/indra/newview/skins/Blackred/textures/arrow_up.tga new file mode 100644 index 000000000..5b03c5433 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/arrow_up.tga differ diff --git a/indra/newview/skins/Blackred/textures/b4870163-6208-42a9-9801-93133bf9a6cd.tga b/indra/newview/skins/Blackred/textures/b4870163-6208-42a9-9801-93133bf9a6cd.tga new file mode 100644 index 000000000..fd2743fed Binary files /dev/null and b/indra/newview/skins/Blackred/textures/b4870163-6208-42a9-9801-93133bf9a6cd.tga differ diff --git a/indra/newview/skins/Blackred/textures/badge_error.j2c b/indra/newview/skins/Blackred/textures/badge_error.j2c new file mode 100644 index 000000000..efb5c375c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/badge_error.j2c differ diff --git a/indra/newview/skins/Blackred/textures/badge_note.j2c b/indra/newview/skins/Blackred/textures/badge_note.j2c new file mode 100644 index 000000000..ef5db9e0d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/badge_note.j2c differ diff --git a/indra/newview/skins/Blackred/textures/badge_ok.j2c b/indra/newview/skins/Blackred/textures/badge_ok.j2c new file mode 100644 index 000000000..8ceee01c6 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/badge_ok.j2c differ diff --git a/indra/newview/skins/Blackred/textures/badge_warn.j2c b/indra/newview/skins/Blackred/textures/badge_warn.j2c new file mode 100644 index 000000000..8fb85be69 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/badge_warn.j2c differ diff --git a/indra/newview/skins/Blackred/textures/black.tga b/indra/newview/skins/Blackred/textures/black.tga new file mode 100644 index 000000000..e368ea496 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/black.tga differ diff --git a/indra/newview/skins/Blackred/textures/btn_chatbar.tga b/indra/newview/skins/Blackred/textures/btn_chatbar.tga new file mode 100644 index 000000000..07117925a Binary files /dev/null and b/indra/newview/skins/Blackred/textures/btn_chatbar.tga differ diff --git a/indra/newview/skins/Blackred/textures/btn_chatbar_selected.tga b/indra/newview/skins/Blackred/textures/btn_chatbar_selected.tga new file mode 100644 index 000000000..57e515005 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/btn_chatbar_selected.tga differ diff --git a/indra/newview/skins/Blackred/textures/button_anim_pause.tga b/indra/newview/skins/Blackred/textures/button_anim_pause.tga new file mode 100644 index 000000000..7f81d1536 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/button_anim_pause.tga differ diff --git a/indra/newview/skins/Blackred/textures/button_anim_pause_selected.tga b/indra/newview/skins/Blackred/textures/button_anim_pause_selected.tga new file mode 100644 index 000000000..650ca0aad Binary files /dev/null and b/indra/newview/skins/Blackred/textures/button_anim_pause_selected.tga differ diff --git a/indra/newview/skins/Blackred/textures/button_anim_play.tga b/indra/newview/skins/Blackred/textures/button_anim_play.tga new file mode 100644 index 000000000..a8b7b74c5 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/button_anim_play.tga differ diff --git a/indra/newview/skins/Blackred/textures/button_anim_play_selected.tga b/indra/newview/skins/Blackred/textures/button_anim_play_selected.tga new file mode 100644 index 000000000..ff9fb98b1 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/button_anim_play_selected.tga differ diff --git a/indra/newview/skins/Blackred/textures/button_anim_stop.tga b/indra/newview/skins/Blackred/textures/button_anim_stop.tga new file mode 100644 index 000000000..f8583d2da Binary files /dev/null and b/indra/newview/skins/Blackred/textures/button_anim_stop.tga differ diff --git a/indra/newview/skins/Blackred/textures/button_anim_stop_selected.tga b/indra/newview/skins/Blackred/textures/button_anim_stop_selected.tga new file mode 100644 index 000000000..0e1b3eb8c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/button_anim_stop_selected.tga differ diff --git a/indra/newview/skins/Blackred/textures/button_disabled_32x128.tga b/indra/newview/skins/Blackred/textures/button_disabled_32x128.tga new file mode 100644 index 000000000..9e7f3744d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/button_disabled_32x128.tga differ diff --git a/indra/newview/skins/Blackred/textures/button_enabled_32x128.tga b/indra/newview/skins/Blackred/textures/button_enabled_32x128.tga new file mode 100644 index 000000000..9e7f3744d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/button_enabled_32x128.tga differ diff --git a/indra/newview/skins/Blackred/textures/button_enabled_selected_32x128.tga b/indra/newview/skins/Blackred/textures/button_enabled_selected_32x128.tga new file mode 100644 index 000000000..e77a70a1c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/button_enabled_selected_32x128.tga differ diff --git a/indra/newview/skins/Blackred/textures/c1e21504-f136-451d-b8e9-929037812f1d.tga b/indra/newview/skins/Blackred/textures/c1e21504-f136-451d-b8e9-929037812f1d.tga new file mode 100644 index 000000000..7251dcc18 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/c1e21504-f136-451d-b8e9-929037812f1d.tga differ diff --git a/indra/newview/skins/Blackred/textures/c63f124c-6340-4fbf-b59e-0869a44adb64.tga b/indra/newview/skins/Blackred/textures/c63f124c-6340-4fbf-b59e-0869a44adb64.tga new file mode 100644 index 000000000..6fa784e11 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/c63f124c-6340-4fbf-b59e-0869a44adb64.tga differ diff --git a/indra/newview/skins/Blackred/textures/cam_rotate_in.tga b/indra/newview/skins/Blackred/textures/cam_rotate_in.tga new file mode 100644 index 000000000..9eadb772b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/cam_rotate_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/cam_rotate_out.tga b/indra/newview/skins/Blackred/textures/cam_rotate_out.tga new file mode 100644 index 000000000..f86135251 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/cam_rotate_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/cam_tracking_in.tga b/indra/newview/skins/Blackred/textures/cam_tracking_in.tga new file mode 100644 index 000000000..b3d5b2ad2 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/cam_tracking_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/cam_tracking_out.tga b/indra/newview/skins/Blackred/textures/cam_tracking_out.tga new file mode 100644 index 000000000..2835219ff Binary files /dev/null and b/indra/newview/skins/Blackred/textures/cam_tracking_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/cam_zoom_minus_in.tga b/indra/newview/skins/Blackred/textures/cam_zoom_minus_in.tga new file mode 100644 index 000000000..ac54c5332 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/cam_zoom_minus_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/cam_zoom_out.tga b/indra/newview/skins/Blackred/textures/cam_zoom_out.tga new file mode 100644 index 000000000..8e6c519a9 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/cam_zoom_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/cam_zoom_plus_in.tga b/indra/newview/skins/Blackred/textures/cam_zoom_plus_in.tga new file mode 100644 index 000000000..cd2960d8e Binary files /dev/null and b/indra/newview/skins/Blackred/textures/cam_zoom_plus_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga b/indra/newview/skins/Blackred/textures/ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga new file mode 100644 index 000000000..3c7cb5594 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga differ diff --git a/indra/newview/skins/Blackred/textures/checkbox_disabled_false.tga b/indra/newview/skins/Blackred/textures/checkbox_disabled_false.tga new file mode 100644 index 000000000..aa57cd211 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/checkbox_disabled_false.tga differ diff --git a/indra/newview/skins/Blackred/textures/checkbox_disabled_true.tga b/indra/newview/skins/Blackred/textures/checkbox_disabled_true.tga new file mode 100644 index 000000000..a198113bc Binary files /dev/null and b/indra/newview/skins/Blackred/textures/checkbox_disabled_true.tga differ diff --git a/indra/newview/skins/Blackred/textures/checkbox_enabled_false.tga b/indra/newview/skins/Blackred/textures/checkbox_enabled_false.tga new file mode 100644 index 000000000..fb8265b18 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/checkbox_enabled_false.tga differ diff --git a/indra/newview/skins/Blackred/textures/checkbox_enabled_true.tga b/indra/newview/skins/Blackred/textures/checkbox_enabled_true.tga new file mode 100644 index 000000000..59d67abdf Binary files /dev/null and b/indra/newview/skins/Blackred/textures/checkbox_enabled_true.tga differ diff --git a/indra/newview/skins/Blackred/textures/close_in_blue.tga b/indra/newview/skins/Blackred/textures/close_in_blue.tga new file mode 100644 index 000000000..c58e052b8 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/close_in_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/close_inactive_blue.tga b/indra/newview/skins/Blackred/textures/close_inactive_blue.tga new file mode 100644 index 000000000..2f912df59 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/close_inactive_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/closebox.tga b/indra/newview/skins/Blackred/textures/closebox.tga new file mode 100644 index 000000000..5e1195526 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/closebox.tga differ diff --git a/indra/newview/skins/Blackred/textures/combobox_arrow.tga b/indra/newview/skins/Blackred/textures/combobox_arrow.tga new file mode 100644 index 000000000..3c01e32d2 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/combobox_arrow.tga differ diff --git a/indra/newview/skins/Blackred/textures/d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c b/indra/newview/skins/Blackred/textures/d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c new file mode 100644 index 000000000..4b73b25ac Binary files /dev/null and b/indra/newview/skins/Blackred/textures/d07f6eed-b96a-47cd-b51d-400ad4a1c428.j2c differ diff --git a/indra/newview/skins/Blackred/textures/darkgray.tga b/indra/newview/skins/Blackred/textures/darkgray.tga new file mode 100644 index 000000000..e69be0893 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/darkgray.tga differ diff --git a/indra/newview/skins/Blackred/textures/default_land_picture.j2c b/indra/newview/skins/Blackred/textures/default_land_picture.j2c new file mode 100644 index 000000000..6e2a85a46 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/default_land_picture.j2c differ diff --git a/indra/newview/skins/Blackred/textures/default_profile_picture.j2c b/indra/newview/skins/Blackred/textures/default_profile_picture.j2c new file mode 100644 index 000000000..31d741e88 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/default_profile_picture.j2c differ diff --git a/indra/newview/skins/Blackred/textures/direction_arrow.tga b/indra/newview/skins/Blackred/textures/direction_arrow.tga new file mode 100644 index 000000000..59149e1d5 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/direction_arrow.tga differ diff --git a/indra/newview/skins/Blackred/textures/down_arrow.png b/indra/newview/skins/Blackred/textures/down_arrow.png new file mode 100644 index 000000000..abd706481 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/down_arrow.png differ diff --git a/indra/newview/skins/Blackred/textures/eye_button_active.tga b/indra/newview/skins/Blackred/textures/eye_button_active.tga new file mode 100644 index 000000000..d0f7f6a3f Binary files /dev/null and b/indra/newview/skins/Blackred/textures/eye_button_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/eye_button_inactive.tga b/indra/newview/skins/Blackred/textures/eye_button_inactive.tga new file mode 100644 index 000000000..7e7ca0619 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/eye_button_inactive.tga differ diff --git a/indra/newview/skins/Blackred/textures/ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga b/indra/newview/skins/Blackred/textures/ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga new file mode 100644 index 000000000..534ecba91 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga differ diff --git a/indra/newview/skins/Blackred/textures/ff_edit_mine_button.tga b/indra/newview/skins/Blackred/textures/ff_edit_mine_button.tga new file mode 100644 index 000000000..0398bbae1 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/ff_edit_mine_button.tga differ diff --git a/indra/newview/skins/Blackred/textures/ff_edit_theirs_button.tga b/indra/newview/skins/Blackred/textures/ff_edit_theirs_button.tga new file mode 100644 index 000000000..06109c1d2 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/ff_edit_theirs_button.tga differ diff --git a/indra/newview/skins/Blackred/textures/ff_online_status_button.tga b/indra/newview/skins/Blackred/textures/ff_online_status_button.tga new file mode 100644 index 000000000..0cc4d4f10 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/ff_online_status_button.tga differ diff --git a/indra/newview/skins/Blackred/textures/ff_visible_map_button.tga b/indra/newview/skins/Blackred/textures/ff_visible_map_button.tga new file mode 100644 index 000000000..7daf492f8 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/ff_visible_map_button.tga differ diff --git a/indra/newview/skins/Blackred/textures/ff_visible_online_button.tga b/indra/newview/skins/Blackred/textures/ff_visible_online_button.tga new file mode 100644 index 000000000..8a18d4d44 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/ff_visible_online_button.tga differ diff --git a/indra/newview/skins/Blackred/textures/flyout_btn_left.tga b/indra/newview/skins/Blackred/textures/flyout_btn_left.tga new file mode 100644 index 000000000..eeb4e944b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/flyout_btn_left.tga differ diff --git a/indra/newview/skins/Blackred/textures/flyout_btn_left_disabled.tga b/indra/newview/skins/Blackred/textures/flyout_btn_left_disabled.tga new file mode 100644 index 000000000..eeb4e944b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/flyout_btn_left_disabled.tga differ diff --git a/indra/newview/skins/Blackred/textures/flyout_btn_left_selected.tga b/indra/newview/skins/Blackred/textures/flyout_btn_left_selected.tga new file mode 100644 index 000000000..67df7dc38 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/flyout_btn_left_selected.tga differ diff --git a/indra/newview/skins/Blackred/textures/flyout_btn_right.tga b/indra/newview/skins/Blackred/textures/flyout_btn_right.tga new file mode 100644 index 000000000..2f4a5bbec Binary files /dev/null and b/indra/newview/skins/Blackred/textures/flyout_btn_right.tga differ diff --git a/indra/newview/skins/Blackred/textures/flyout_btn_right_disabled.tga b/indra/newview/skins/Blackred/textures/flyout_btn_right_disabled.tga new file mode 100644 index 000000000..2f4a5bbec Binary files /dev/null and b/indra/newview/skins/Blackred/textures/flyout_btn_right_disabled.tga differ diff --git a/indra/newview/skins/Blackred/textures/flyout_btn_right_selected.tga b/indra/newview/skins/Blackred/textures/flyout_btn_right_selected.tga new file mode 100644 index 000000000..36f63c3de Binary files /dev/null and b/indra/newview/skins/Blackred/textures/flyout_btn_right_selected.tga differ diff --git a/indra/newview/skins/Blackred/textures/flyout_left.tga b/indra/newview/skins/Blackred/textures/flyout_left.tga new file mode 100644 index 000000000..4503ddf8c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/flyout_left.tga differ diff --git a/indra/newview/skins/Blackred/textures/flyout_left_disabled.tga b/indra/newview/skins/Blackred/textures/flyout_left_disabled.tga new file mode 100644 index 000000000..4503ddf8c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/flyout_left_disabled.tga differ diff --git a/indra/newview/skins/Blackred/textures/flyout_left_selected.tga b/indra/newview/skins/Blackred/textures/flyout_left_selected.tga new file mode 100644 index 000000000..7552ba6ed Binary files /dev/null and b/indra/newview/skins/Blackred/textures/flyout_left_selected.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_media-pause_active.tga b/indra/newview/skins/Blackred/textures/icn_media-pause_active.tga new file mode 100644 index 000000000..8988829aa Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_media-pause_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_media-pause_disabled.tga b/indra/newview/skins/Blackred/textures/icn_media-pause_disabled.tga new file mode 100644 index 000000000..4690f4256 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_media-pause_disabled.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_media-pause_enabled.tga b/indra/newview/skins/Blackred/textures/icn_media-pause_enabled.tga new file mode 100644 index 000000000..c01399e27 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_media-pause_enabled.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_media-play_enabled.tga b/indra/newview/skins/Blackred/textures/icn_media-play_enabled.tga new file mode 100644 index 000000000..accac38b0 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_media-play_enabled.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_media-stop_enabled.tga b/indra/newview/skins/Blackred/textures/icn_media-stop_enabled.tga new file mode 100644 index 000000000..d935fa317 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_media-stop_enabled.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_media.tga b/indra/newview/skins/Blackred/textures/icn_media.tga new file mode 100644 index 000000000..2a035ba5d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_media.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_music.tga b/indra/newview/skins/Blackred/textures/icn_music.tga new file mode 100644 index 000000000..81da5abcf Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_music.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_rounded-text-field.tga b/indra/newview/skins/Blackred/textures/icn_rounded-text-field.tga new file mode 100644 index 000000000..1f1e72572 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_rounded-text-field.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_slide-groove_dark.tga b/indra/newview/skins/Blackred/textures/icn_slide-groove_dark.tga new file mode 100644 index 000000000..96a247ad9 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_slide-groove_dark.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_slide-highlight.tga b/indra/newview/skins/Blackred/textures/icn_slide-highlight.tga new file mode 100644 index 000000000..d371cd066 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_slide-highlight.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_slide-thumb_dark.tga b/indra/newview/skins/Blackred/textures/icn_slide-thumb_dark.tga new file mode 100644 index 000000000..452cdc6d1 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_slide-thumb_dark.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_speaker-muted_dark.tga b/indra/newview/skins/Blackred/textures/icn_speaker-muted_dark.tga new file mode 100644 index 000000000..8f2c80dd2 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_speaker-muted_dark.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_toolbar_radar.tga b/indra/newview/skins/Blackred/textures/icn_toolbar_radar.tga new file mode 100644 index 000000000..d1a55ed74 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_toolbar_radar.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice-call-end.tga b/indra/newview/skins/Blackred/textures/icn_voice-call-end.tga new file mode 100644 index 000000000..84056b90a Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice-call-end.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice-call-start.tga b/indra/newview/skins/Blackred/textures/icn_voice-call-start.tga new file mode 100644 index 000000000..7babfd318 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice-call-start.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice-groupfocus.tga b/indra/newview/skins/Blackred/textures/icn_voice-groupfocus.tga new file mode 100644 index 000000000..913bd0969 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice-groupfocus.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice-localchat.tga b/indra/newview/skins/Blackred/textures/icn_voice-localchat.tga new file mode 100644 index 000000000..5c1456602 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice-localchat.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice-pvtfocus.tga b/indra/newview/skins/Blackred/textures/icn_voice-pvtfocus.tga new file mode 100644 index 000000000..76e72fd3a Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice-pvtfocus.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice_ptt-off.tga b/indra/newview/skins/Blackred/textures/icn_voice_ptt-off.tga new file mode 100644 index 000000000..530425dd7 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice_ptt-off.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice_ptt-on-lvl1.tga b/indra/newview/skins/Blackred/textures/icn_voice_ptt-on-lvl1.tga new file mode 100644 index 000000000..818c58915 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice_ptt-on-lvl1.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice_ptt-on-lvl2.tga b/indra/newview/skins/Blackred/textures/icn_voice_ptt-on-lvl2.tga new file mode 100644 index 000000000..48d44b10a Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice_ptt-on-lvl2.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice_ptt-on-lvl3.tga b/indra/newview/skins/Blackred/textures/icn_voice_ptt-on-lvl3.tga new file mode 100644 index 000000000..081265efb Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice_ptt-on-lvl3.tga differ diff --git a/indra/newview/skins/Blackred/textures/icn_voice_ptt-on.tga b/indra/newview/skins/Blackred/textures/icn_voice_ptt-on.tga new file mode 100644 index 000000000..8ce21f4a6 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icn_voice_ptt-on.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_auction.tga b/indra/newview/skins/Blackred/textures/icon_auction.tga new file mode 100644 index 000000000..3aa21d323 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_auction.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_avatar_offline.tga b/indra/newview/skins/Blackred/textures/icon_avatar_offline.tga new file mode 100644 index 000000000..620e0f7c1 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_avatar_offline.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_avatar_online.tga b/indra/newview/skins/Blackred/textures/icon_avatar_online.tga new file mode 100644 index 000000000..6350237ee Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_avatar_online.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_event.tga b/indra/newview/skins/Blackred/textures/icon_event.tga new file mode 100644 index 000000000..23f246b91 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_event.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_event_adult.tga b/indra/newview/skins/Blackred/textures/icon_event_adult.tga new file mode 100644 index 000000000..7202e6734 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_event_adult.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_event_mature.tga b/indra/newview/skins/Blackred/textures/icon_event_mature.tga new file mode 100644 index 000000000..103c5e535 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_event_mature.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_for_sale.tga b/indra/newview/skins/Blackred/textures/icon_for_sale.tga new file mode 100644 index 000000000..09405d383 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_for_sale.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_for_sale_adult.tga b/indra/newview/skins/Blackred/textures/icon_for_sale_adult.tga new file mode 100644 index 000000000..147f724e7 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_for_sale_adult.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_group.tga b/indra/newview/skins/Blackred/textures/icon_group.tga new file mode 100644 index 000000000..1e5c31aa3 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_group.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_groupnotice.tga b/indra/newview/skins/Blackred/textures/icon_groupnotice.tga new file mode 100644 index 000000000..a3e35a0bf Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_groupnotice.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_groupnoticeinventory.tga b/indra/newview/skins/Blackred/textures/icon_groupnoticeinventory.tga new file mode 100644 index 000000000..780d6fadd Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_groupnoticeinventory.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_lock.tga b/indra/newview/skins/Blackred/textures/icon_lock.tga new file mode 100644 index 000000000..5de6cc10e Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_lock.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_place.tga b/indra/newview/skins/Blackred/textures/icon_place.tga new file mode 100644 index 000000000..7f842ba65 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_place.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_popular.tga b/indra/newview/skins/Blackred/textures/icon_popular.tga new file mode 100644 index 000000000..6bdc6ede3 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_popular.tga differ diff --git a/indra/newview/skins/Blackred/textures/icon_top_pick.tga b/indra/newview/skins/Blackred/textures/icon_top_pick.tga new file mode 100644 index 000000000..4466e8be7 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/icon_top_pick.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_animation.tga b/indra/newview/skins/Blackred/textures/inv_folder_animation.tga new file mode 100644 index 000000000..2054a466d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_animation.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_bodypart.tga b/indra/newview/skins/Blackred/textures/inv_folder_bodypart.tga new file mode 100644 index 000000000..9a17c90b8 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_bodypart.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_callingcard.tga b/indra/newview/skins/Blackred/textures/inv_folder_callingcard.tga new file mode 100644 index 000000000..514cc6095 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_callingcard.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_clothing.tga b/indra/newview/skins/Blackred/textures/inv_folder_clothing.tga new file mode 100644 index 000000000..c61e15c66 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_clothing.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_gesture.tga b/indra/newview/skins/Blackred/textures/inv_folder_gesture.tga new file mode 100644 index 000000000..761b1b87b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_gesture.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_landmark.tga b/indra/newview/skins/Blackred/textures/inv_folder_landmark.tga new file mode 100644 index 000000000..94bf17e62 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_landmark.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_lostandfound.tga b/indra/newview/skins/Blackred/textures/inv_folder_lostandfound.tga new file mode 100644 index 000000000..c31b71f15 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_lostandfound.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_notecard.tga b/indra/newview/skins/Blackred/textures/inv_folder_notecard.tga new file mode 100644 index 000000000..8fe38da90 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_notecard.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_object.tga b/indra/newview/skins/Blackred/textures/inv_folder_object.tga new file mode 100644 index 000000000..56bce2ca0 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_object.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_plain_closed.tga b/indra/newview/skins/Blackred/textures/inv_folder_plain_closed.tga new file mode 100644 index 000000000..28c78ce39 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_plain_closed.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_plain_open.tga b/indra/newview/skins/Blackred/textures/inv_folder_plain_open.tga new file mode 100644 index 000000000..baf6db64a Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_plain_open.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_script.tga b/indra/newview/skins/Blackred/textures/inv_folder_script.tga new file mode 100644 index 000000000..b42b464fa Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_script.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_snapshot.tga b/indra/newview/skins/Blackred/textures/inv_folder_snapshot.tga new file mode 100644 index 000000000..d3c02d31d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_snapshot.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_sound.tga b/indra/newview/skins/Blackred/textures/inv_folder_sound.tga new file mode 100644 index 000000000..d7cf45f11 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_sound.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_texture.tga b/indra/newview/skins/Blackred/textures/inv_folder_texture.tga new file mode 100644 index 000000000..684ca9d43 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_texture.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_folder_trash.tga b/indra/newview/skins/Blackred/textures/inv_folder_trash.tga new file mode 100644 index 000000000..50ad9dacd Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_folder_trash.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_animation.tga b/indra/newview/skins/Blackred/textures/inv_item_animation.tga new file mode 100644 index 000000000..1269e7c7b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_animation.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_attach.tga b/indra/newview/skins/Blackred/textures/inv_item_attach.tga new file mode 100644 index 000000000..38204e590 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_attach.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_callingcard_offline.tga b/indra/newview/skins/Blackred/textures/inv_item_callingcard_offline.tga new file mode 100644 index 000000000..7373451db Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_callingcard_offline.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_callingcard_online.tga b/indra/newview/skins/Blackred/textures/inv_item_callingcard_online.tga new file mode 100644 index 000000000..602648494 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_callingcard_online.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_clothing.tga b/indra/newview/skins/Blackred/textures/inv_item_clothing.tga new file mode 100644 index 000000000..0dd6ddb90 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_clothing.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_eyes.tga b/indra/newview/skins/Blackred/textures/inv_item_eyes.tga new file mode 100644 index 000000000..c75ebbccf Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_eyes.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_gesture.tga b/indra/newview/skins/Blackred/textures/inv_item_gesture.tga new file mode 100644 index 000000000..45e94bb0f Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_gesture.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_gloves.tga b/indra/newview/skins/Blackred/textures/inv_item_gloves.tga new file mode 100644 index 000000000..f380dd9af Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_gloves.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_hair.tga b/indra/newview/skins/Blackred/textures/inv_item_hair.tga new file mode 100644 index 000000000..dce7798af Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_hair.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_jacket.tga b/indra/newview/skins/Blackred/textures/inv_item_jacket.tga new file mode 100644 index 000000000..af742f687 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_jacket.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_landmark.tga b/indra/newview/skins/Blackred/textures/inv_item_landmark.tga new file mode 100644 index 000000000..db67487fb Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_landmark.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_landmark_visited.tga b/indra/newview/skins/Blackred/textures/inv_item_landmark_visited.tga new file mode 100644 index 000000000..c74745070 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_landmark_visited.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_notecard.tga b/indra/newview/skins/Blackred/textures/inv_item_notecard.tga new file mode 100644 index 000000000..c7d3decc8 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_notecard.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_object.tga b/indra/newview/skins/Blackred/textures/inv_item_object.tga new file mode 100644 index 000000000..8431a6081 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_object.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_object_multi.tga b/indra/newview/skins/Blackred/textures/inv_item_object_multi.tga new file mode 100644 index 000000000..f1485c0ae Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_object_multi.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_pants.tga b/indra/newview/skins/Blackred/textures/inv_item_pants.tga new file mode 100644 index 000000000..fc2f1779c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_pants.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_script.tga b/indra/newview/skins/Blackred/textures/inv_item_script.tga new file mode 100644 index 000000000..1ac3df150 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_script.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_script_dangerous.tga b/indra/newview/skins/Blackred/textures/inv_item_script_dangerous.tga new file mode 100644 index 000000000..613f80445 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_script_dangerous.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_shape.tga b/indra/newview/skins/Blackred/textures/inv_item_shape.tga new file mode 100644 index 000000000..fb78f6c6f Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_shape.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_shirt.tga b/indra/newview/skins/Blackred/textures/inv_item_shirt.tga new file mode 100644 index 000000000..0dd6ddb90 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_shirt.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_shoes.tga b/indra/newview/skins/Blackred/textures/inv_item_shoes.tga new file mode 100644 index 000000000..c46fddc01 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_shoes.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_skin.tga b/indra/newview/skins/Blackred/textures/inv_item_skin.tga new file mode 100644 index 000000000..9e9b952a9 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_skin.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_skirt.tga b/indra/newview/skins/Blackred/textures/inv_item_skirt.tga new file mode 100644 index 000000000..cf1b928f4 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_skirt.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_snapshot.tga b/indra/newview/skins/Blackred/textures/inv_item_snapshot.tga new file mode 100644 index 000000000..59e032d8e Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_snapshot.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_socks.tga b/indra/newview/skins/Blackred/textures/inv_item_socks.tga new file mode 100644 index 000000000..2b80ebca0 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_socks.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_sound.tga b/indra/newview/skins/Blackred/textures/inv_item_sound.tga new file mode 100644 index 000000000..d43a10e1d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_sound.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_texture.tga b/indra/newview/skins/Blackred/textures/inv_item_texture.tga new file mode 100644 index 000000000..ede9fd9a8 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_texture.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_underpants.tga b/indra/newview/skins/Blackred/textures/inv_item_underpants.tga new file mode 100644 index 000000000..abcffc3bd Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_underpants.tga differ diff --git a/indra/newview/skins/Blackred/textures/inv_item_undershirt.tga b/indra/newview/skins/Blackred/textures/inv_item_undershirt.tga new file mode 100644 index 000000000..22c47f8df Binary files /dev/null and b/indra/newview/skins/Blackred/textures/inv_item_undershirt.tga differ diff --git a/indra/newview/skins/Blackred/textures/lightgray.tga b/indra/newview/skins/Blackred/textures/lightgray.tga new file mode 100644 index 000000000..e69be0893 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/lightgray.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_avatar_16.tga b/indra/newview/skins/Blackred/textures/map_avatar_16.tga new file mode 100644 index 000000000..42d8c1e29 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_avatar_16.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_avatar_8.tga b/indra/newview/skins/Blackred/textures/map_avatar_8.tga new file mode 100644 index 000000000..7eb7c20f1 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_avatar_8.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_avatar_above_8.tga b/indra/newview/skins/Blackred/textures/map_avatar_above_8.tga new file mode 100644 index 000000000..6faefccc7 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_avatar_above_8.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_avatar_below_8.tga b/indra/newview/skins/Blackred/textures/map_avatar_below_8.tga new file mode 100644 index 000000000..5ad671c26 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_avatar_below_8.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_avatar_you_8.tga b/indra/newview/skins/Blackred/textures/map_avatar_you_8.tga new file mode 100644 index 000000000..673b30e19 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_avatar_you_8.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_event.tga b/indra/newview/skins/Blackred/textures/map_event.tga new file mode 100644 index 000000000..103c5e535 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_event.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_event_adult.tga b/indra/newview/skins/Blackred/textures/map_event_adult.tga new file mode 100644 index 000000000..7202e6734 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_event_adult.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_event_mature.tga b/indra/newview/skins/Blackred/textures/map_event_mature.tga new file mode 100644 index 000000000..23f246b91 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_event_mature.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_home.tga b/indra/newview/skins/Blackred/textures/map_home.tga new file mode 100644 index 000000000..85dde9ef7 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_home.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_infohub.tga b/indra/newview/skins/Blackred/textures/map_infohub.tga new file mode 100644 index 000000000..173b93e39 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_infohub.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_telehub.tga b/indra/newview/skins/Blackred/textures/map_telehub.tga new file mode 100644 index 000000000..d89bcfa40 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_telehub.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_track_16.tga b/indra/newview/skins/Blackred/textures/map_track_16.tga new file mode 100644 index 000000000..14d49b93b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_track_16.tga differ diff --git a/indra/newview/skins/Blackred/textures/map_track_8.tga b/indra/newview/skins/Blackred/textures/map_track_8.tga new file mode 100644 index 000000000..d9605dde1 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/map_track_8.tga differ diff --git a/indra/newview/skins/Blackred/textures/minimize.tga b/indra/newview/skins/Blackred/textures/minimize.tga new file mode 100644 index 000000000..151a3078f Binary files /dev/null and b/indra/newview/skins/Blackred/textures/minimize.tga differ diff --git a/indra/newview/skins/Blackred/textures/minimize_inactive.tga b/indra/newview/skins/Blackred/textures/minimize_inactive.tga new file mode 100644 index 000000000..d7e1b4057 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/minimize_inactive.tga differ diff --git a/indra/newview/skins/Blackred/textures/minimize_pressed.tga b/indra/newview/skins/Blackred/textures/minimize_pressed.tga new file mode 100644 index 000000000..573452ce9 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/minimize_pressed.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_backward_in.tga b/indra/newview/skins/Blackred/textures/move_backward_in.tga new file mode 100644 index 000000000..8fe21404c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_backward_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_backward_out.tga b/indra/newview/skins/Blackred/textures/move_backward_out.tga new file mode 100644 index 000000000..f46c021f9 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_backward_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_down_in.tga b/indra/newview/skins/Blackred/textures/move_down_in.tga new file mode 100644 index 000000000..6405730ff Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_down_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_down_out.tga b/indra/newview/skins/Blackred/textures/move_down_out.tga new file mode 100644 index 000000000..8d3efee37 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_down_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_forward_in.tga b/indra/newview/skins/Blackred/textures/move_forward_in.tga new file mode 100644 index 000000000..ba3454a95 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_forward_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_forward_out.tga b/indra/newview/skins/Blackred/textures/move_forward_out.tga new file mode 100644 index 000000000..67e407a41 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_forward_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_left_in.tga b/indra/newview/skins/Blackred/textures/move_left_in.tga new file mode 100644 index 000000000..11109bff1 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_left_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_left_out.tga b/indra/newview/skins/Blackred/textures/move_left_out.tga new file mode 100644 index 000000000..a2ea88a82 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_left_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_right_in.tga b/indra/newview/skins/Blackred/textures/move_right_in.tga new file mode 100644 index 000000000..2634947d2 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_right_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_right_out.tga b/indra/newview/skins/Blackred/textures/move_right_out.tga new file mode 100644 index 000000000..cab385318 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_right_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_turn_left_in.tga b/indra/newview/skins/Blackred/textures/move_turn_left_in.tga new file mode 100644 index 000000000..5dc8a0e6b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_turn_left_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_turn_left_out.tga b/indra/newview/skins/Blackred/textures/move_turn_left_out.tga new file mode 100644 index 000000000..00c4bfebe Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_turn_left_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_turn_right_in.tga b/indra/newview/skins/Blackred/textures/move_turn_right_in.tga new file mode 100644 index 000000000..17ddb7b72 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_turn_right_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_turn_right_out.tga b/indra/newview/skins/Blackred/textures/move_turn_right_out.tga new file mode 100644 index 000000000..c26cb2c2c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_turn_right_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_up_in.tga b/indra/newview/skins/Blackred/textures/move_up_in.tga new file mode 100644 index 000000000..251a561bf Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_up_in.tga differ diff --git a/indra/newview/skins/Blackred/textures/move_up_out.tga b/indra/newview/skins/Blackred/textures/move_up_out.tga new file mode 100644 index 000000000..e1e377d09 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/move_up_out.tga differ diff --git a/indra/newview/skins/Blackred/textures/notify_box_icon.tga b/indra/newview/skins/Blackred/textures/notify_box_icon.tga new file mode 100644 index 000000000..880aca9b4 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/notify_box_icon.tga differ diff --git a/indra/newview/skins/Blackred/textures/notify_caution_icon.tga b/indra/newview/skins/Blackred/textures/notify_caution_icon.tga new file mode 100644 index 000000000..ac6660c16 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/notify_caution_icon.tga differ diff --git a/indra/newview/skins/Blackred/textures/notify_next.png b/indra/newview/skins/Blackred/textures/notify_next.png new file mode 100644 index 000000000..9b371e03e Binary files /dev/null and b/indra/newview/skins/Blackred/textures/notify_next.png differ diff --git a/indra/newview/skins/Blackred/textures/notify_tip_icon.tga b/indra/newview/skins/Blackred/textures/notify_tip_icon.tga new file mode 100644 index 000000000..0451da099 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/notify_tip_icon.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_cone.tga b/indra/newview/skins/Blackred/textures/object_cone.tga new file mode 100644 index 000000000..943433322 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_cone.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_cone_active.tga b/indra/newview/skins/Blackred/textures/object_cone_active.tga new file mode 100644 index 000000000..44055b403 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_cone_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_cube.tga b/indra/newview/skins/Blackred/textures/object_cube.tga new file mode 100644 index 000000000..d62bdb89c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_cube.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_cube_active.tga b/indra/newview/skins/Blackred/textures/object_cube_active.tga new file mode 100644 index 000000000..07ca2cd7c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_cube_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_cylinder.tga b/indra/newview/skins/Blackred/textures/object_cylinder.tga new file mode 100644 index 000000000..82bf54261 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_cylinder.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_cylinder_active.tga b/indra/newview/skins/Blackred/textures/object_cylinder_active.tga new file mode 100644 index 000000000..2ab658cbb Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_cylinder_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_grass.tga b/indra/newview/skins/Blackred/textures/object_grass.tga new file mode 100644 index 000000000..6f91db20d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_grass.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_grass_active.tga b/indra/newview/skins/Blackred/textures/object_grass_active.tga new file mode 100644 index 000000000..58f54ac9b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_grass_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_hemi_cone.tga b/indra/newview/skins/Blackred/textures/object_hemi_cone.tga new file mode 100644 index 000000000..44ce6d4be Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_hemi_cone.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_hemi_cone_active.tga b/indra/newview/skins/Blackred/textures/object_hemi_cone_active.tga new file mode 100644 index 000000000..011206ec5 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_hemi_cone_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_hemi_cylinder.tga b/indra/newview/skins/Blackred/textures/object_hemi_cylinder.tga new file mode 100644 index 000000000..1d1eca748 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_hemi_cylinder.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_hemi_cylinder_active.tga b/indra/newview/skins/Blackred/textures/object_hemi_cylinder_active.tga new file mode 100644 index 000000000..24f68e9f9 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_hemi_cylinder_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_hemi_sphere.tga b/indra/newview/skins/Blackred/textures/object_hemi_sphere.tga new file mode 100644 index 000000000..fbce7dcfc Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_hemi_sphere.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_hemi_sphere_active.tga b/indra/newview/skins/Blackred/textures/object_hemi_sphere_active.tga new file mode 100644 index 000000000..a9a0e6939 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_hemi_sphere_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_prism.tga b/indra/newview/skins/Blackred/textures/object_prism.tga new file mode 100644 index 000000000..e5586d59e Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_prism.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_prism_active.tga b/indra/newview/skins/Blackred/textures/object_prism_active.tga new file mode 100644 index 000000000..961efc9bd Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_prism_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_pyramid.tga b/indra/newview/skins/Blackred/textures/object_pyramid.tga new file mode 100644 index 000000000..bbf8164ce Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_pyramid.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_pyramid_active.tga b/indra/newview/skins/Blackred/textures/object_pyramid_active.tga new file mode 100644 index 000000000..fec59ac62 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_pyramid_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_ring.tga b/indra/newview/skins/Blackred/textures/object_ring.tga new file mode 100644 index 000000000..37d242f41 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_ring.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_ring_active.tga b/indra/newview/skins/Blackred/textures/object_ring_active.tga new file mode 100644 index 000000000..ba9e01c81 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_ring_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_sphere.tga b/indra/newview/skins/Blackred/textures/object_sphere.tga new file mode 100644 index 000000000..3d6d9ca39 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_sphere.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_sphere_active.tga b/indra/newview/skins/Blackred/textures/object_sphere_active.tga new file mode 100644 index 000000000..201006ddb Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_sphere_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_tetrahedron.tga b/indra/newview/skins/Blackred/textures/object_tetrahedron.tga new file mode 100644 index 000000000..4808cb3f3 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_tetrahedron.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_tetrahedron_active.tga b/indra/newview/skins/Blackred/textures/object_tetrahedron_active.tga new file mode 100644 index 000000000..ddbf9ddfb Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_tetrahedron_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_torus.tga b/indra/newview/skins/Blackred/textures/object_torus.tga new file mode 100644 index 000000000..70154676b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_torus.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_torus_active.tga b/indra/newview/skins/Blackred/textures/object_torus_active.tga new file mode 100644 index 000000000..99ef2666b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_torus_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_tree.tga b/indra/newview/skins/Blackred/textures/object_tree.tga new file mode 100644 index 000000000..246ad80f6 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_tree.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_tree_active.tga b/indra/newview/skins/Blackred/textures/object_tree_active.tga new file mode 100644 index 000000000..1adf9c3f3 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_tree_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_tube.tga b/indra/newview/skins/Blackred/textures/object_tube.tga new file mode 100644 index 000000000..15e0a1c3d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_tube.tga differ diff --git a/indra/newview/skins/Blackred/textures/object_tube_active.tga b/indra/newview/skins/Blackred/textures/object_tube_active.tga new file mode 100644 index 000000000..d382e740e Binary files /dev/null and b/indra/newview/skins/Blackred/textures/object_tube_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/preview.png b/indra/newview/skins/Blackred/textures/preview.png new file mode 100644 index 000000000..294a6a03a Binary files /dev/null and b/indra/newview/skins/Blackred/textures/preview.png differ diff --git a/indra/newview/skins/Blackred/textures/progress_fill.tga b/indra/newview/skins/Blackred/textures/progress_fill.tga new file mode 100644 index 000000000..bbdf5dd0b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/progress_fill.tga differ diff --git a/indra/newview/skins/Blackred/textures/progressbar_fill.tga b/indra/newview/skins/Blackred/textures/progressbar_fill.tga new file mode 100644 index 000000000..03601c432 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/progressbar_fill.tga differ diff --git a/indra/newview/skins/Blackred/textures/progressbar_track.tga b/indra/newview/skins/Blackred/textures/progressbar_track.tga new file mode 100644 index 000000000..4b84e9ec9 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/progressbar_track.tga differ diff --git a/indra/newview/skins/Blackred/textures/ptt_lock_off.tga b/indra/newview/skins/Blackred/textures/ptt_lock_off.tga new file mode 100644 index 000000000..d66f49840 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/ptt_lock_off.tga differ diff --git a/indra/newview/skins/Blackred/textures/ptt_lock_on.tga b/indra/newview/skins/Blackred/textures/ptt_lock_on.tga new file mode 100644 index 000000000..432db2f00 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/ptt_lock_on.tga differ diff --git a/indra/newview/skins/Blackred/textures/radio_active_false.tga b/indra/newview/skins/Blackred/textures/radio_active_false.tga new file mode 100644 index 000000000..c3a3c2951 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/radio_active_false.tga differ diff --git a/indra/newview/skins/Blackred/textures/radio_active_true.tga b/indra/newview/skins/Blackred/textures/radio_active_true.tga new file mode 100644 index 000000000..9c03e4f16 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/radio_active_true.tga differ diff --git a/indra/newview/skins/Blackred/textures/radio_inactive_false.tga b/indra/newview/skins/Blackred/textures/radio_inactive_false.tga new file mode 100644 index 000000000..5154d2511 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/radio_inactive_false.tga differ diff --git a/indra/newview/skins/Blackred/textures/radio_inactive_true.tga b/indra/newview/skins/Blackred/textures/radio_inactive_true.tga new file mode 100644 index 000000000..c1b5c829f Binary files /dev/null and b/indra/newview/skins/Blackred/textures/radio_inactive_true.tga differ diff --git a/indra/newview/skins/Blackred/textures/resize_handle_bottom_right_blue.tga b/indra/newview/skins/Blackred/textures/resize_handle_bottom_right_blue.tga new file mode 100644 index 000000000..8290bfa65 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/resize_handle_bottom_right_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/restore.tga b/indra/newview/skins/Blackred/textures/restore.tga new file mode 100644 index 000000000..5e369fdfc Binary files /dev/null and b/indra/newview/skins/Blackred/textures/restore.tga differ diff --git a/indra/newview/skins/Blackred/textures/restore_inactive.tga b/indra/newview/skins/Blackred/textures/restore_inactive.tga new file mode 100644 index 000000000..ce545d90d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/restore_inactive.tga differ diff --git a/indra/newview/skins/Blackred/textures/restore_pressed.tga b/indra/newview/skins/Blackred/textures/restore_pressed.tga new file mode 100644 index 000000000..8a25087be Binary files /dev/null and b/indra/newview/skins/Blackred/textures/restore_pressed.tga differ diff --git a/indra/newview/skins/Blackred/textures/rounded_square.j2c b/indra/newview/skins/Blackred/textures/rounded_square.j2c new file mode 100644 index 000000000..c3dfe8f10 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/rounded_square.j2c differ diff --git a/indra/newview/skins/Blackred/textures/rounded_square.tga b/indra/newview/skins/Blackred/textures/rounded_square.tga new file mode 100644 index 000000000..4f4bf05f8 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/rounded_square.tga differ diff --git a/indra/newview/skins/Blackred/textures/rounded_square_soft.tga b/indra/newview/skins/Blackred/textures/rounded_square_soft.tga new file mode 100644 index 000000000..4f4bf05f8 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/rounded_square_soft.tga differ diff --git a/indra/newview/skins/Blackred/textures/script_error.j2c b/indra/newview/skins/Blackred/textures/script_error.j2c new file mode 100644 index 000000000..ad6be04a7 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/script_error.j2c differ diff --git a/indra/newview/skins/Blackred/textures/script_error.tga b/indra/newview/skins/Blackred/textures/script_error.tga new file mode 100644 index 000000000..8fa12e711 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/script_error.tga differ diff --git a/indra/newview/skins/Blackred/textures/scrollbutton_down_in_blue.tga b/indra/newview/skins/Blackred/textures/scrollbutton_down_in_blue.tga new file mode 100644 index 000000000..3c01e32d2 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/scrollbutton_down_in_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/scrollbutton_down_out_blue.tga b/indra/newview/skins/Blackred/textures/scrollbutton_down_out_blue.tga new file mode 100644 index 000000000..3c01e32d2 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/scrollbutton_down_out_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/scrollbutton_left_in_blue.tga b/indra/newview/skins/Blackred/textures/scrollbutton_left_in_blue.tga new file mode 100644 index 000000000..6e2de5448 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/scrollbutton_left_in_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/scrollbutton_left_out_blue.tga b/indra/newview/skins/Blackred/textures/scrollbutton_left_out_blue.tga new file mode 100644 index 000000000..6e2de5448 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/scrollbutton_left_out_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/scrollbutton_right_in_blue.tga b/indra/newview/skins/Blackred/textures/scrollbutton_right_in_blue.tga new file mode 100644 index 000000000..bd5b99a6e Binary files /dev/null and b/indra/newview/skins/Blackred/textures/scrollbutton_right_in_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/scrollbutton_right_out_blue.tga b/indra/newview/skins/Blackred/textures/scrollbutton_right_out_blue.tga new file mode 100644 index 000000000..bd5b99a6e Binary files /dev/null and b/indra/newview/skins/Blackred/textures/scrollbutton_right_out_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/scrollbutton_up_in_blue.tga b/indra/newview/skins/Blackred/textures/scrollbutton_up_in_blue.tga new file mode 100644 index 000000000..e513eb409 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/scrollbutton_up_in_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/scrollbutton_up_out_blue.tga b/indra/newview/skins/Blackred/textures/scrollbutton_up_out_blue.tga new file mode 100644 index 000000000..e513eb409 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/scrollbutton_up_out_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/sm_rounded_corners_simple.tga b/indra/newview/skins/Blackred/textures/sm_rounded_corners_simple.tga new file mode 100644 index 000000000..054fdd39a Binary files /dev/null and b/indra/newview/skins/Blackred/textures/sm_rounded_corners_simple.tga differ diff --git a/indra/newview/skins/Blackred/textures/spin_down_in_blue.tga b/indra/newview/skins/Blackred/textures/spin_down_in_blue.tga new file mode 100644 index 000000000..c52fbce3a Binary files /dev/null and b/indra/newview/skins/Blackred/textures/spin_down_in_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/spin_down_out_blue.tga b/indra/newview/skins/Blackred/textures/spin_down_out_blue.tga new file mode 100644 index 000000000..1af2ed9cb Binary files /dev/null and b/indra/newview/skins/Blackred/textures/spin_down_out_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/spin_up_in_blue.tga b/indra/newview/skins/Blackred/textures/spin_up_in_blue.tga new file mode 100644 index 000000000..03e45db36 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/spin_up_in_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/spin_up_out_blue.tga b/indra/newview/skins/Blackred/textures/spin_up_out_blue.tga new file mode 100644 index 000000000..9a9bc6468 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/spin_up_out_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/square_btn_32x128.tga b/indra/newview/skins/Blackred/textures/square_btn_32x128.tga new file mode 100644 index 000000000..d23d413aa Binary files /dev/null and b/indra/newview/skins/Blackred/textures/square_btn_32x128.tga differ diff --git a/indra/newview/skins/Blackred/textures/square_btn_selected_32x128.tga b/indra/newview/skins/Blackred/textures/square_btn_selected_32x128.tga new file mode 100644 index 000000000..2f48098d2 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/square_btn_selected_32x128.tga differ diff --git a/indra/newview/skins/Blackred/textures/startup_logo.j2c b/indra/newview/skins/Blackred/textures/startup_logo.j2c new file mode 100644 index 000000000..b28219f36 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/startup_logo.j2c differ diff --git a/indra/newview/skins/Blackred/textures/status_buy_currency.tga b/indra/newview/skins/Blackred/textures/status_buy_currency.tga new file mode 100644 index 000000000..f4a28b32b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_buy_currency.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_buy_currency_pressed.tga b/indra/newview/skins/Blackred/textures/status_buy_currency_pressed.tga new file mode 100644 index 000000000..f4a28b32b Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_buy_currency_pressed.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_buy_land.tga b/indra/newview/skins/Blackred/textures/status_buy_land.tga new file mode 100644 index 000000000..60c395c03 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_buy_land.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_buy_land_pressed.tga b/indra/newview/skins/Blackred/textures/status_buy_land_pressed.tga new file mode 100644 index 000000000..60c395c03 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_buy_land_pressed.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_health.tga b/indra/newview/skins/Blackred/textures/status_health.tga new file mode 100644 index 000000000..f5eefc5a9 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_health.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_no_build.tga b/indra/newview/skins/Blackred/textures/status_no_build.tga new file mode 100644 index 000000000..41934a600 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_no_build.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_no_fly.tga b/indra/newview/skins/Blackred/textures/status_no_fly.tga new file mode 100644 index 000000000..0aa7fa71d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_no_fly.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_no_push.tga b/indra/newview/skins/Blackred/textures/status_no_push.tga new file mode 100644 index 000000000..6d5987217 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_no_push.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_no_scripts.tga b/indra/newview/skins/Blackred/textures/status_no_scripts.tga new file mode 100644 index 000000000..3bce6ad6f Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_no_scripts.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_no_voice.tga b/indra/newview/skins/Blackred/textures/status_no_voice.tga new file mode 100644 index 000000000..aeeed6ed0 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_no_voice.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_script_debug.tga b/indra/newview/skins/Blackred/textures/status_script_debug.tga new file mode 100644 index 000000000..7d895eb0a Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_script_debug.tga differ diff --git a/indra/newview/skins/Blackred/textures/status_search_btn.png b/indra/newview/skins/Blackred/textures/status_search_btn.png new file mode 100644 index 000000000..f6db36fbc Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_search_btn.png differ diff --git a/indra/newview/skins/Blackred/textures/status_search_btn_pressed.png b/indra/newview/skins/Blackred/textures/status_search_btn_pressed.png new file mode 100644 index 000000000..c19945885 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_search_btn_pressed.png differ diff --git a/indra/newview/skins/Blackred/textures/status_voice.tga b/indra/newview/skins/Blackred/textures/status_voice.tga new file mode 100644 index 000000000..aeeed6ed0 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/status_voice.tga differ diff --git a/indra/newview/skins/Blackred/textures/tab_bottom_blue.tga b/indra/newview/skins/Blackred/textures/tab_bottom_blue.tga new file mode 100644 index 000000000..e6de7a5a1 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tab_bottom_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/tab_bottom_selected_blue.tga b/indra/newview/skins/Blackred/textures/tab_bottom_selected_blue.tga new file mode 100644 index 000000000..ae38121e0 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tab_bottom_selected_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/tab_left.tga b/indra/newview/skins/Blackred/textures/tab_left.tga new file mode 100644 index 000000000..db15d2734 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tab_left.tga differ diff --git a/indra/newview/skins/Blackred/textures/tab_left_selected.tga b/indra/newview/skins/Blackred/textures/tab_left_selected.tga new file mode 100644 index 000000000..212e58575 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tab_left_selected.tga differ diff --git a/indra/newview/skins/Blackred/textures/tab_top_blue.tga b/indra/newview/skins/Blackred/textures/tab_top_blue.tga new file mode 100644 index 000000000..ddcd519f2 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tab_top_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/tab_top_selected_blue.tga b/indra/newview/skins/Blackred/textures/tab_top_selected_blue.tga new file mode 100644 index 000000000..93a5695a6 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tab_top_selected_blue.tga differ diff --git a/indra/newview/skins/Blackred/textures/tearoff_pressed.tga b/indra/newview/skins/Blackred/textures/tearoff_pressed.tga new file mode 100644 index 000000000..8581ab701 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tearoff_pressed.tga differ diff --git a/indra/newview/skins/Blackred/textures/tearoffbox.tga b/indra/newview/skins/Blackred/textures/tearoffbox.tga new file mode 100644 index 000000000..27af31c4d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tearoffbox.tga differ diff --git a/indra/newview/skins/Blackred/textures/textures.xml b/indra/newview/skins/Blackred/textures/textures.xml new file mode 100644 index 000000000..5955a8ede --- /dev/null +++ b/indra/newview/skins/Blackred/textures/textures.xml @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/Blackred/textures/tool_dozer.tga b/indra/newview/skins/Blackred/textures/tool_dozer.tga new file mode 100644 index 000000000..a8814a1ac Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tool_dozer.tga differ diff --git a/indra/newview/skins/Blackred/textures/tool_dozer_active.tga b/indra/newview/skins/Blackred/textures/tool_dozer_active.tga new file mode 100644 index 000000000..40557c9cb Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tool_dozer_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/tool_zoom.tga b/indra/newview/skins/Blackred/textures/tool_zoom.tga new file mode 100644 index 000000000..3ebbe4fcd Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tool_zoom.tga differ diff --git a/indra/newview/skins/Blackred/textures/tool_zoom_active.tga b/indra/newview/skins/Blackred/textures/tool_zoom_active.tga new file mode 100644 index 000000000..df1b379e9 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/tool_zoom_active.tga differ diff --git a/indra/newview/skins/Blackred/textures/toolbar_bg.tga b/indra/newview/skins/Blackred/textures/toolbar_bg.tga new file mode 100644 index 000000000..bddb1f41c Binary files /dev/null and b/indra/newview/skins/Blackred/textures/toolbar_bg.tga differ diff --git a/indra/newview/skins/Blackred/textures/toolbar_btn_disabled.tga b/indra/newview/skins/Blackred/textures/toolbar_btn_disabled.tga new file mode 100644 index 000000000..9e7f3744d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/toolbar_btn_disabled.tga differ diff --git a/indra/newview/skins/Blackred/textures/toolbar_btn_enabled.tga b/indra/newview/skins/Blackred/textures/toolbar_btn_enabled.tga new file mode 100644 index 000000000..9e7f3744d Binary files /dev/null and b/indra/newview/skins/Blackred/textures/toolbar_btn_enabled.tga differ diff --git a/indra/newview/skins/Blackred/textures/toolbar_btn_selected.tga b/indra/newview/skins/Blackred/textures/toolbar_btn_selected.tga new file mode 100644 index 000000000..d37f2d872 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/toolbar_btn_selected.tga differ diff --git a/indra/newview/skins/Blackred/textures/toolbar_tab.tga b/indra/newview/skins/Blackred/textures/toolbar_tab.tga new file mode 100644 index 000000000..a79d8bc43 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/toolbar_tab.tga differ diff --git a/indra/newview/skins/Blackred/textures/up_arrow.png b/indra/newview/skins/Blackred/textures/up_arrow.png new file mode 100644 index 000000000..6beea5fd7 Binary files /dev/null and b/indra/newview/skins/Blackred/textures/up_arrow.png differ diff --git a/indra/newview/skins/apollo/colors.xml b/indra/newview/skins/apollo/colors.xml index 434115514..eb3cbaeb0 100644 --- a/indra/newview/skins/apollo/colors.xml +++ b/indra/newview/skins/apollo/colors.xml @@ -152,7 +152,7 @@ - + diff --git a/indra/newview/skins/blackdark.xml b/indra/newview/skins/blackdark.xml new file mode 100644 index 000000000..8f83e11f1 --- /dev/null +++ b/indra/newview/skins/blackdark.xml @@ -0,0 +1,14 @@ + + + skin_name + Black Dark + author_name + Unknown + additional_author_names + Linden Lab + skin_info + + folder_name + Blackdark + + diff --git a/indra/newview/skins/blacklightblue.xml b/indra/newview/skins/blacklightblue.xml new file mode 100644 index 000000000..8ade2a477 --- /dev/null +++ b/indra/newview/skins/blacklightblue.xml @@ -0,0 +1,14 @@ + + + skin_name + Black Light Blue + author_name + Chalice Yao + additional_author_names + JB Kraft, Linden Lab + skin_info + + folder_name + Blacklightblue + + diff --git a/indra/newview/skins/blackred.xml b/indra/newview/skins/blackred.xml new file mode 100644 index 000000000..93a2ed074 --- /dev/null +++ b/indra/newview/skins/blackred.xml @@ -0,0 +1,14 @@ + + + skin_name + Black Red + author_name + LordGregGreg Back + additional_author_names + Chalice Yao, JB Kraft, Linden Lab + skin_info + + folder_name + Blackred + + diff --git a/indra/newview/skins/default/colors_base.xml b/indra/newview/skins/default/colors_base.xml index eaed66c4d..651f4c232 100644 --- a/indra/newview/skins/default/colors_base.xml +++ b/indra/newview/skins/default/colors_base.xml @@ -153,6 +153,7 @@ + diff --git a/indra/newview/skins/default/textures/icon_name.tga b/indra/newview/skins/default/textures/icon_name.tga new file mode 100644 index 000000000..54b1a3d6a Binary files /dev/null and b/indra/newview/skins/default/textures/icon_name.tga differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 3552b3eaf..a49fdd786 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -100,7 +100,8 @@ - + + diff --git a/indra/newview/skins/default/xui/en-us/floater_about_land.xml b/indra/newview/skins/default/xui/en-us/floater_about_land.xml index f40659986..ae6c96de5 100644 --- a/indra/newview/skins/default/xui/en-us/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en-us/floater_about_land.xml @@ -773,7 +773,7 @@ Only large parcels can be listed in search. mouse_opaque="true" name="Snapshot:" v_pad="0" width="278"> Snapshot: - diff --git a/indra/newview/skins/default/xui/en-us/floater_inventory.xml b/indra/newview/skins/default/xui/en-us/floater_inventory.xml index aa860ce0b..28da7d9a7 100644 --- a/indra/newview/skins/default/xui/en-us/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en-us/floater_inventory.xml @@ -190,6 +190,10 @@ + + + diff --git a/indra/newview/skins/default/xui/en-us/floater_mute.xml b/indra/newview/skins/default/xui/en-us/floater_mute.xml index b1ab1155f..1dd889b62 100644 --- a/indra/newview/skins/default/xui/en-us/floater_mute.xml +++ b/indra/newview/skins/default/xui/en-us/floater_mute.xml @@ -1,14 +1,17 @@ - + + + + + + + diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index acb78b1f4..b76a3e958 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -264,6 +264,22 @@ An error occurred while updating [APP_NAME]. Please download the latest version yestext="Ok"/> + +[GRIDNAME] requires a non-empty first name to login. +Please try again. + + + +[GRIDNAME] requires a non-empty last name to login. +Please try again. + + + type="alert"> A new folder has been created for each item you have transferred into the top level of your Merchant Outbox. @@ -322,9 +338,9 @@ A new folder has been created for each item you have transferred into the top le + type="alert"> Success All folders were successfully sent to the Marketplace. @@ -336,9 +352,9 @@ All folders were successfully sent to the Marketplace. + type="alert"> Some folders did not transfer Errors occurred when some folders were sent to the Marketplace. Those folders are still in your Merchant Outbox. @@ -351,9 +367,9 @@ See the [[MARKETPLACE_IMPORTS_URL] error log] for more information. + type="alertmodal"> Transfer failed No folders were sent to the Marketplace because of a system or network error. Try again later. @@ -364,9 +380,9 @@ No folders were sent to the Marketplace because of a system or network error. T + type="alertmodal"> Marketplace initialization failed Initialization with the Marketplace failed because of a system or network error. Try again later. @@ -405,6 +421,13 @@ There was a problem writing animation data. Please try again later. There was a problem uploading the auction snapshot due to the following reason: [REASON] + +There was a problem uploading the snapshot due to the following reason: [REASON] + + + +It is not possible to make a snapshot with this size and aspect. +Try a smaller size or a less stretched aspect. + + -You are not allowed in that Region due to your maturity Rating. This may be a result of a lack of information validating your age. - -Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating. - -You are not allowed in that region due to your maturity Rating. - + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. + Go to the Knowledge Base for more information about maturity Ratings? - https://support.secondlife.com/ics/support/default.asp?deptID=4417&task=knowledge&questionID=6010 + http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview + ignoretext="Region crossing: The region you're trying to visit contains content which is accessible to adults only."/> -You are not allowed in that region due to your maturity Rating. +The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + + + + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. -You are not allowed in that Region due to your maturity Rating preference. +The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. You can click 'Change Preference' to raise your maturity Rating preference now and allow you to enter. You will be able to search and access [REGIONMATURITY] content from now on. If you later want to change this setting back, go to Edit > Preferences... > General.
@@ -3723,68 +3759,211 @@ You can click 'Change Preference' to raise your maturity Rating prefer default="true" index="1" name="Cancel" - text="Close"/> - + text="Cancel"/> +
+ + We are having technical difficulties with your teleport because your preferences are out of sync with the server. + + + + + The region you're trying to visit contains content exceeding your current preferences. You can change your preferences using Edit > Preferences > General. + + + + + + REGIONMATURITY + + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. + + Go to the Knowledge Base for more information about maturity Ratings? + + http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview + + + + + + + REGIONMATURITY + + The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. + + + + + REGIONMATURITY + + The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. + + + + + REGIONMATURITY + + The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. We can change your preferences and continue with the teleport, or you can cancel this teleport. +
+