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/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/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/develop.py b/indra/develop.py index 5e94ca125..a38758d39 100755 --- a/indra/develop.py +++ b/indra/develop.py @@ -782,13 +782,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 61966–2–1 */ - 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/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 66217f902..f7843c3f1 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1690,6 +1690,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..88fc0562e 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -134,7 +134,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); 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..754083286 100644 --- a/indra/llmessage/aicurl.cpp +++ b/indra/llmessage/aicurl.cpp @@ -418,6 +418,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 +492,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 @@ -1348,11 +1347,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. 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..ee28ae849 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) diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index 1fbe57d3e..b8c700997 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -1065,6 +1065,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()) { @@ -1609,7 +1613,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); @@ -2148,10 +2154,14 @@ void stopCurlThread(void) ms_sleep(10); } Dout(dc::curl, "Curl thread" << (curlThreadIsRunning() ? " not" : "") << " stopped after " << ((100 - count) * 10) << "ms."); - // Clear the command queue, for a cleaner cleanup. + } +} + +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(); - } } //----------------------------------------------------------------------------- @@ -2162,6 +2172,12 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const& mStatus = status; mReason = reason; 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->followRedir()) + { + llerrs << "Received " << status << " (" << reason << ") for responder \"" << mTimeoutPolicy->name() << "\" which has no followRedir()!" << llendl; + } } void BufferedCurlEasyRequest::processOutput(void) @@ -2353,10 +2369,10 @@ 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) { + BufferedCurlEasyRequest* request = (BufferedCurlEasyRequest*)user_ptr; + #ifdef CWDEBUG using namespace ::libcwd; - - BufferedCurlEasyRequest* request = (BufferedCurlEasyRequest*)user_ptr; std::ostringstream marker; marker << (void*)request->get_lockobj(); libcw_do.push_marker(); diff --git a/indra/llmessage/aihttptimeoutpolicy.cpp b/indra/llmessage/aihttptimeoutpolicy.cpp index 7e8cc1f91..602db6bc3 100644 --- a/indra/llmessage/aihttptimeoutpolicy.cpp +++ b/indra/llmessage/aihttptimeoutpolicy.cpp @@ -820,6 +820,7 @@ P(accountingCostResponder); P(agentStateResponder); P(assetUploadResponder); P(asyncConsoleResponder); +P(avatarPickerResponder); P(authHandler); P(avatarNameResponder); P2(baseCapabilitiesComplete, transfer_18s); @@ -890,6 +891,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..825cffcc9 100644 --- a/indra/llmessage/debug_libcurl.cpp +++ b/indra/llmessage/debug_libcurl.cpp @@ -624,7 +624,7 @@ void debug_curl_easy_reset(CURL* handle) CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...) { - CURLcode ret; + CURLcode ret = CURLE_UNKNOWN_OPTION; // Suppress compiler warning. va_list ap; union param_type { long along; @@ -841,7 +841,7 @@ CURLMcode debug_curl_multi_remove_handle(CURLM* multi_handle, CURL* easy_handle) 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; diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index af6fb01ec..48b6e4f63 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -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; @@ -695,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 @@ -712,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; } } } @@ -725,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; } } } @@ -742,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 @@ -796,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? @@ -810,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 b5745c77b..99e3fba57 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -77,10 +77,11 @@ namespace LLAvatarNameCache 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); @@ -96,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.h b/indra/llmessage/llhttpclient.h index 3e491de82..ec4e88955 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -161,7 +161,7 @@ public: // 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; } // Timeout policy to use. virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0; @@ -188,6 +188,7 @@ public: class ResponderHeadersOnly : public ResponderBase { private: /*virtual*/ bool needsHeaders(void) const { return true; } + /*virtual*/ bool followRedir(void) const { return true; } protected: // ResponderBase event diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 927b64b7a..3ffb9e5cc 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -85,11 +85,6 @@ LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string cons 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" : ""); diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index 8f019310f..fbe97c22f 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -84,11 +84,6 @@ class LLURLRequest : public AICurlEasyRequestStateMachine { /*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. */ 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/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..385f2e847 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -660,6 +660,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 +1120,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/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index ea168a35c..11d6433d0 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; } @@ -1034,15 +1104,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 +1158,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 +1201,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 +1255,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 +1287,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 +1318,7 @@ BOOL LLScrollListCtrl::selectFirstItem() { deselectItem(itemp); } - first_item = FALSE; + first_item = false; } if (mCommitOnSelectionChange) { @@ -1240,6 +1342,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 +1398,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 +1413,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 +1439,8 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index) return; } + updateSort(); + LLScrollListItem *itemp; itemp = mItemList[target_index]; if (itemp == mLastSelected) @@ -1388,7 +1497,7 @@ void LLScrollListCtrl::deleteSelectedItems() dirtyColumns(); } -void LLScrollListCtrl::highlightNthItem(S32 target_index) +void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index) { if (mHighlightedItem != target_index) { @@ -1396,14 +1505,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 +1534,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 +1552,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 +1579,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection) } else { + updateSort(); + item_list::iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { @@ -1508,6 +1623,8 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection) } else { + updateSort(); + item_list::reverse_iterator iter; for (iter = mItemList.rbegin(); iter != mItemList.rend(); iter++) { @@ -1559,16 +1676,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 +1693,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 +1710,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 +1936,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 +1946,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 +2008,6 @@ void LLScrollListCtrl::drawItems() cur_y -= mLineHeight; } - line++; } } } @@ -1905,15 +2018,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 +2034,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 +2068,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 +2107,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 +2119,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 +2162,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { if(mOnMaximumSelectCallback) { - mOnMaximumSelectCallback(mCallbackUserData); + mOnMaximumSelectCallback(); } break; } @@ -2088,7 +2200,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { if(mOnMaximumSelectCallback) { - mOnMaximumSelectCallback(mCallbackUserData); + mOnMaximumSelectCallback(); } } } @@ -2133,7 +2245,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 +2265,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 +2291,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 +2321,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 +2350,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 +2361,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 +2371,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 +2442,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 +2456,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 +2465,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 +2498,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) { // commit implicit in call selectPrevItem(FALSE); - mNeedsScroll = TRUE; + mNeedsScroll = true; handled = TRUE; } break; @@ -2393,7 +2507,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) { // commit implicit in call selectNextItem(FALSE); - mNeedsScroll = TRUE; + mNeedsScroll = true; handled = TRUE; } break; @@ -2401,7 +2515,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 +2528,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 +2541,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectFirstItem(); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2440,7 +2554,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getItemCount() - 1); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2479,7 +2593,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 +2633,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 +2679,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 +2750,7 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it } itemp->setSelected(TRUE); mLastSelected = itemp; - mSelectionChanged = TRUE; + mSelectionChanged = true; } } @@ -2657,7 +2771,7 @@ void LLScrollListCtrl::deselectItem(LLScrollListItem* itemp) { cellp->highlightText(0, 0); } - mSelectionChanged = TRUE; + mSelectionChanged = true; } } @@ -2665,7 +2779,7 @@ void LLScrollListCtrl::commitIfChanged() { if (mSelectionChanged) { - mDirty = TRUE; + mDirty = true; mSelectionChanged = FALSE; onCommit(); } @@ -2684,9 +2798,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 +2824,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 +2848,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 +2886,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 +2930,8 @@ void LLScrollListCtrl::scrollToShowSelected() return; } + updateSort(); + S32 index = getFirstSelectedIndex(); if (index < 0) { @@ -2813,7 +2946,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 +2956,7 @@ void LLScrollListCtrl::scrollToShowSelected() } else if (highest <= index) { - setScrollPos(index - mPageLines + 1); + setScrollPos(index - page_lines + 1); } } @@ -2869,9 +3003,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 +3127,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 +3351,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 +3373,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 +3393,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 +3436,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 +3455,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata) if (parent->mOnSortChangedCallback) { - parent->mOnSortChangedCallback(parent->getCallbackUserData()); + parent->mOnSortChangedCallback(); } } @@ -3332,23 +3467,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 +3498,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 +3518,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 +3538,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 +3583,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 +3606,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 +3720,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 +3802,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 +3835,7 @@ void LLScrollListCtrl::resetDirty() void LLScrollListCtrl::onFocusReceived() { // forget latent selection changes when getting focus - mSelectionChanged = FALSE; + mSelectionChanged = false; LLUICtrl::onFocusReceived(); } @@ -3688,10 +3846,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 +3865,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,11 +3892,11 @@ 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; @@ -3848,7 +4009,7 @@ 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)) { @@ -3864,7 +4025,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 +4034,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 +4049,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 +4071,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 +4157,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 +4167,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 +4192,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 +4230,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()*/); @@ -4151,7 +4312,7 @@ void LLColumnHeader::handleReshape(const LLRect& new_rect, bool by_user) } } -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 +4324,7 @@ void LLColumnHeader::setHasResizableElement(BOOL resizable) } } -void LLColumnHeader::updateResizeBars() +void LLScrollColumnHeader::updateResizeBars() { S32 num_resizable_columns = 0; S32 col; @@ -4192,7 +4353,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 +4362,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 +4398,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 +4421,6 @@ LLScrollListColumn::LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent) } else { - setWidth(sd.get("width").asInteger()); } @@ -4280,3 +4434,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..9ea4d82b8 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,25 @@ 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 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 +671,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 +685,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 +693,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 +729,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 +746,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 +760,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/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..0a988c7a7 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -41,7 +41,7 @@ #include "llviewmodel.h" // *TODO move dependency to .cpp file class LLUICtrl -: public LLView +: public LLView { public: typedef boost::function commit_callback_t; @@ -103,7 +103,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/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3ef620b2b..6f049c585 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) @@ -370,6 +370,7 @@ set(viewer_SOURCE_FILES llpanelpermissions.cpp llpanelpick.cpp llpanelplace.cpp + llpanelprofile.cpp llpanelskins.cpp llpanelvolume.cpp llpanelweb.cpp @@ -538,6 +539,7 @@ set(viewer_SOURCE_FILES llwearablelist.cpp llwearabletype.cpp llweb.cpp + llwebprofile.cpp llwind.cpp llwlanimator.cpp llwldaycycle.cpp @@ -546,6 +548,7 @@ set(viewer_SOURCE_FILES llwlparamset.cpp llworld.cpp llworldmap.cpp + llworldmapmessage.cpp llworldmipmap.cpp llworldmapview.cpp llxmlrpcresponder.cpp @@ -874,6 +877,7 @@ set(viewer_HEADER_FILES llpanelpermissions.h llpanelpick.h llpanelplace.h + llpanelprofile.h llpanelskins.h llpanelvolume.h llpanelweb.h @@ -1047,6 +1051,7 @@ set(viewer_HEADER_FILES llwearablelist.h llwearabletype.h llweb.h + llwebprofile.h llwind.h llwindebug.h llwlanimator.h @@ -1056,6 +1061,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/settings.xml b/indra/newview/app_settings/settings.xml index 915a147b2..540eb44c8 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7425,7 +7425,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 @@ -7433,6 +7433,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 @@ -9905,17 +9916,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 @@ -10174,6 +10174,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 @@ -10547,7 +10559,7 @@ This should be as low as possible, but too low may break functionality Type F32 Value - 500.0 + 1500.0 RenderSSAOMaxScale @@ -10558,7 +10570,7 @@ This should be as low as possible, but too low may break functionality Type U32 Value - 200 + 250 RenderSSAOFactor @@ -10569,19 +10581,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 @@ -11168,7 +11180,7 @@ This should be as low as possible, but too low may break functionality Vector3 Value - 3.0 + 1.0 2.0 0.0 @@ -11183,7 +11195,7 @@ This should be as low as possible, but too low may break functionality Type F32 Value - 1.4 + 3.0 RenderShadowBlurSamples 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..46b34c6d3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -61,6 +61,11 @@ 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); +//#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/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 66e3cf6d1..33856994d 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,26 @@ 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); 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..71486156f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl @@ -40,5 +40,10 @@ void main() frag_data[0] = col; 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/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/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..1455be080 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; @@ -205,22 +205,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,13 +266,26 @@ 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); 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/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/ascentprefssys.cpp b/indra/newview/ascentprefssys.cpp index 8b90011f2..f8eac7fec 100644 --- a/indra/newview/ascentprefssys.cpp +++ b/indra/newview/ascentprefssys.cpp @@ -268,7 +268,7 @@ void LLPrefsAscentSys::refreshValues() mResetCameraAfterTP = gSavedSettings.getBOOL("OptionRotateCamAfterLocalTP"); mOffsetTPByUserHeight = gSavedSettings.getBOOL("OptionOffsetTPByAgentHeight"); mPreviewAnimInWorld = gSavedSettings.getBOOL("PreviewAnimInWorld"); -// mSaveScriptsAsMono = gSavedSettings.getBOOL("SaveScriptsAsMono"); + mSaveScriptsAsMono = gSavedSettings.getBOOL("SaveInventoryScriptsAsMono"); mAlwaysRezInGroup = gSavedSettings.getBOOL("AscentAlwaysRezInGroup"); mBuildAlwaysEnabled = gSavedSettings.getBOOL("AscentBuildAlwaysEnabled"); mAlwaysShowFly = gSavedSettings.getBOOL("AscentFlyAlwaysEnabled"); @@ -417,7 +417,7 @@ void LLPrefsAscentSys::cancel() gSavedSettings.setBOOL("OptionRotateCamAfterLocalTP", mResetCameraAfterTP); gSavedSettings.setBOOL("OptionOffsetTPByAgentHeight", mOffsetTPByUserHeight); 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..336828999 100644 --- a/indra/newview/ascentprefssys.h +++ b/indra/newview/ascentprefssys.h @@ -59,7 +59,7 @@ protected: BOOL mResetCameraAfterTP; BOOL mOffsetTPByUserHeight; BOOL mPreviewAnimInWorld; -// BOOL mSaveScriptsAsMono; + BOOL mSaveScriptsAsMono; BOOL mAlwaysRezInGroup; BOOL mBuildAlwaysEnabled; BOOL mAlwaysShowFly; 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..4de1c7ad8 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), @@ -80,6 +81,12 @@ 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; @@ -220,12 +227,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..5d58a1b5f 100644 --- a/indra/newview/hippogridmanager.h +++ b/indra/newview/hippogridmanager.h @@ -39,6 +39,7 @@ public: Platform getPlatform(); bool isOpenSimulator() 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 +111,7 @@ private: std::string mPasswordUrl; std::string mSearchUrl; std::string mVoiceConnector; + bool mIsInProductionGrid; bool mRenderCompat; bool mInvLinks; bool mAutoUpdate; 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..38d77b8fc 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -77,6 +77,7 @@ #include "llvoavatarself.h" #include "llworld.h" #include "llworldmap.h" +#include "llworldmapmessage.h" //Misc non-standard includes #include "llurldispatcher.h" @@ -1421,7 +1422,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; @@ -3518,8 +3519,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")) { @@ -3677,7 +3682,7 @@ void LLAgent::teleportViaLocation(const LLVector3d& 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 +3692,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]))) @@ -3736,10 +3741,6 @@ void LLAgent::teleportViaLocationLookAt(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 +4180,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 } } diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 93390e1e5..8e940c4f5 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -1844,8 +1844,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()) { @@ -2802,18 +2803,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 +2845,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 +2863,6 @@ void LLAgentCamera::lookAtObject(const LLUUID &object_id, bool self) else mCameraFocusOffsetTarget.setVec(radius, radius, 0.f); } - setFocusOnAvatar(FALSE, TRUE); } else { @@ -2882,17 +2882,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..a0c1481c7 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,12 @@ void LLAppViewer::idle() return; } + static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); + if (!hide_tp_screen && gAgent.getTeleportState() != LLAgent::TELEPORT_NONE && gAgent.getTeleportState() != LLAgent::TELEPORT_LOCAL) + { + return; + } + gViewerWindow->updateUI(); /////////////////////////////////////// diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 874299df3..858c26909 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -208,7 +208,7 @@ BOOL LLFloaterScriptQueue::start() buffer = getString ("Starting", args); LLScrollListCtrl* list = getChild("queue output"); - list->addCommentText(buffer); + list->setCommentText(buffer); return nextObject(); } @@ -244,7 +244,7 @@ BOOL LLFloaterScriptQueue::nextObject() LLScrollListCtrl* list = getChild("queue output"); mDone = TRUE; - list->addCommentText(getString("Done")); + list->setCommentText(getString("Done")); childSetEnabled("close",TRUE); } return successful_start; @@ -325,7 +325,7 @@ LLFloaterCompileQueue* LLFloaterCompileQueue::create(BOOL mono) } LLScrollListCtrl* list = queue->getChild("queue output"); - list->addCommentText(message.c_str()); + list->setCommentText(message.c_str()); } private: @@ -520,7 +520,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, if(queue && (buffer.size() > 0)) { LLScrollListCtrl* list = queue->getChild("queue output"); - list->addCommentText(buffer); + list->setCommentText(buffer); } delete data; } @@ -707,7 +707,7 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj, LLScrollListCtrl* list = getChild("queue output"); std::string buffer; buffer = getString("Resetting") + LLTrans::getString(":") + " " + item->getName(); - list->addCommentText(buffer); + list->setCommentText(buffer); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_ScriptReset); msg->nextBlockFast(_PREHASH_AgentData); @@ -769,7 +769,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->setCommentText(buffer); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_SetScriptRunning); @@ -833,7 +833,7 @@ 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->setCommentText(buffer); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_SetScriptRunning); 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..c9e956a09 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"); @@ -260,8 +262,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 +372,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,8 +411,8 @@ 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 @@ -674,7 +705,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/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/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..5415c1acf 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,45 @@ 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) + { + --(*delay_iter); + if (*delay_iter <= 0) + { + (*iter)->doIdleUpdate(); + } + ++delay_iter; + } +} + LLVector3 LLVolumeImplFlexible::getFramePosition() const { return mVO->getRenderPosition(); @@ -296,22 +335,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 +355,45 @@ 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()) - { - id = mID; - } - 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) + if (visible) { - updateRenderRes(); - gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + 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] = (S32) update_period-1; + + updateRenderRes(); + + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + } + } + } + else + { + sUpdateDelay[mInstanceIndex] = (S32) 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..cba941bcd 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() { memset(&sUpdateDelay[0], 0, sizeof(S32)*sUpdateDelay.size()); } + 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 b6dbd16a3..5eb9afa32 100644 --- a/indra/newview/llfloateractivespeakers.cpp +++ b/indra/newview/llfloateractivespeakers.cpp @@ -316,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"); @@ -593,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 @@ -796,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 a2cf940a5..757c00bc7 100644 --- a/indra/newview/llfloateractivespeakers.h +++ b/indra/newview/llfloateractivespeakers.h @@ -227,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/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 1655c2714..887afe476 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -52,7 +52,7 @@ #include #include - +#include #include "llworld.h" #include "llsdutil.h" @@ -138,10 +138,11 @@ 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) { } @@ -221,12 +222,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; } @@ -240,7 +241,7 @@ void LLAvatarListEntry::setActivity(ACTIVITY_TYPE activity) } } -LLAvatarListEntry::ACTIVITY_TYPE LLAvatarListEntry::getActivity() +const LLAvatarListEntry::ACTIVITY_TYPE LLAvatarListEntry::getActivity() { if ( mActivityTimer.getElapsedTimeF32() > ACTIVITY_TIMEOUT ) { @@ -251,10 +252,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() @@ -316,46 +321,46 @@ 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)); // 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); @@ -439,9 +444,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)) { @@ -495,12 +500,13 @@ 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 { @@ -508,7 +514,7 @@ void LLFloaterAvatarList::updateAvatarList() LLAvatarListEntry entry(avid, name, position); if(announce && avatarp->getRegion() == gAgent.getRegion()) announce_keys.push(avid); - mAvatars[avid] = entry; + mAvatars.push_back(entry); } } else @@ -528,18 +534,19 @@ void LLFloaterAvatarList::updateAvatarList() 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(entry); } } } @@ -601,28 +608,39 @@ 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()) + if(!it->isDead()) + (it++)->getAlive(); + else { - //llinfos << "radar: expiring avatar " << entry->getName() << llendl; - LLUUID av_id = entry->getID(); - delete_queue.push(av_id); + *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; + } + } } } @@ -639,7 +657,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(); @@ -649,25 +667,24 @@ 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()) + if (entry.isDead()) { continue; } - av_id = entry->getID(); - av_name = entry->getName().c_str(); + entry.setInList(); - LLVector3d position = entry->getPosition(); + av_id = entry.getID(); + av_name = entry.getName().c_str(); + + LLVector3d position = entry.getPosition(); BOOL UnknownAltitude = false; LLVector3d delta = position - mypos; @@ -703,7 +720,7 @@ void LLFloaterAvatarList::refreshAvatarList() element["columns"][LIST_MARK]["column"] = "marked"; element["columns"][LIST_MARK]["type"] = "text"; - if (entry->isMarked()) + if (entry.isMarked()) { element["columns"][LIST_MARK]["value"] = "X"; element["columns"][LIST_MARK]["color"] = LLColor4::blue.getValue(); @@ -717,7 +734,7 @@ void LLFloaterAvatarList::refreshAvatarList() element["columns"][LIST_AVATAR_NAME]["column"] = "avatar_name"; element["columns"][LIST_AVATAR_NAME]["type"] = "text"; element["columns"][LIST_AVATAR_NAME]["value"] = av_name; - if (entry->isFocused()) + if (entry.isFocused()) { element["columns"][LIST_AVATAR_NAME]["font-style"] = "BOLD"; } @@ -725,7 +742,7 @@ void LLFloaterAvatarList::refreshAvatarList() // custom colors for certain types of avatars! //Changed a bit so people can modify them in settings. And since they're colors, again it's possibly account-based. Starting to think I need a function just to determine that. - HgB //element["columns"][LIST_AVATAR_NAME]["color"] = gColors.getColor( "MapAvatar" ).getValue(); - LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(entry->getPosition()); + LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(entry.getPosition()); LLUUID estate_owner = LLUUID::null; if(parent_estate && parent_estate->isAlive()) { @@ -776,7 +793,7 @@ void LLFloaterAvatarList::refreshAvatarList() if (UnknownAltitude) { strcpy(temp, "?"); - if (entry->isDrawn()) + if (entry.isDrawn()) { color = sRadarTextDrawDist; } @@ -797,7 +814,7 @@ void LLFloaterAvatarList::refreshAvatarList() } else { - if (entry->isDrawn()) + if (entry.isDrawn()) { color = sRadarTextDrawDist; } @@ -855,7 +872,7 @@ void LLFloaterAvatarList::refreshAvatarList() element["columns"][LIST_ACTIVITY]["type"] = "icon"; std::string activity_icon = ""; - switch(entry->getActivity()) + switch(entry.getActivity()) { case LLAvatarListEntry::ACTIVITY_MOVING: activity_icon = "inv_item_animation.tga"; @@ -927,22 +944,21 @@ void LLFloaterAvatarList::refreshAvatarList() } // finish - mAvatarList->sortItems(); + mAvatarList->updateSort(); mAvatarList->selectMultiple(selected); mAvatarList->setScrollPos(scrollpos); + + mDirtyAvatarSorting = true; // 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) { @@ -967,42 +983,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)); } } @@ -1012,15 +1020,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 @@ -1031,6 +1036,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()) @@ -1038,32 +1054,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); + 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) @@ -1075,8 +1070,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)) @@ -1093,7 +1087,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) @@ -1121,143 +1115,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); + 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) + LLAvatarListEntry& entry = *(--prev_iter); + 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); @@ -1270,39 +1194,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; @@ -1313,7 +1207,7 @@ void LLFloaterAvatarList::onClickGetKey(void *userdata) gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); } -//static + void LLFloaterAvatarList::sendKeys() { LLViewerRegion* regionp = gAgent.getRegion(); @@ -1411,11 +1305,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) { @@ -1500,46 +1389,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; } @@ -1564,6 +1451,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) @@ -1579,6 +1469,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) @@ -1594,6 +1487,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) @@ -1605,6 +1501,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) @@ -1627,32 +1526,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; @@ -1674,86 +1569,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..d9fe93581 100644 --- a/indra/newview/llfloateravatarlist.h +++ b/indra/newview/llfloateravatarlist.h @@ -59,7 +59,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,46 +72,61 @@ 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; } /** * @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 LLAvatarListEntry& l) { return l.getID() == mID; } + LLUUID mID; + }; + private: friend class LLFloaterAvatarList; @@ -119,8 +134,9 @@ private: std::string mName; LLVector3d mPosition; LLVector3d mDrawPosition; - BOOL mMarked; - BOOL mFocused; + bool mMarked; + bool mFocused; + bool mIsInList; /** * @brief Timer to keep track of whether avatars are still there @@ -212,7 +228,9 @@ public: static void lookAtAvatar(LLUUID &uuid); static void sound_trigger_hook(LLMessageSystem* msg,void **); - static void sendKeys(); + void sendKeys(); + + typedef std::vector av_list_t; private: // when a line editor loses keyboard focus, it is committed. @@ -230,8 +248,7 @@ private: 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 +256,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 +272,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 +283,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 +323,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 b66309ac4..dc0ad358c 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -33,20 +33,25 @@ #include "llfloateravatarpicker.h" +// Viewer includes #include "llagent.h" -#include "llavatarnamecache.h" -#include "llbutton.h" #include "llfocusmgr.h" #include "llfoldervieweventlistener.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] @@ -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; iaddElement(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/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/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/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index c3b9826c6..92f89eb41 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -165,7 +165,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); @@ -184,13 +184,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); } @@ -364,9 +364,9 @@ BOOL LLPanelFriends::postBuild() { mFriendsList = getChild("friend_list"); mFriendsList->setCommitOnSelectionChange(TRUE); - childSetCommitCallback("friend_list", onSelectName, this); + mFriendsList->setCommitCallback(onSelectName, this); childSetCommitCallback("buddy_group_combobox", onChangeContactGroup, this); - childSetDoubleClickCallback("friend_list", onClickIM); + mFriendsList->setDoubleClickCallback(onClickIM, this); // // Contact search and group system. @@ -548,7 +548,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; @@ -571,7 +571,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) @@ -620,7 +620,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 @@ -646,7 +646,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); @@ -748,18 +748,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) { @@ -779,8 +767,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; @@ -795,7 +783,7 @@ 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); } } @@ -846,8 +834,8 @@ 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()) { if(ids.size() == 1) { @@ -912,13 +900,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 @@ -954,7 +941,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); @@ -967,9 +954,9 @@ 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) @@ -985,7 +972,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) { @@ -1189,8 +1176,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); } @@ -1201,8 +1188,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]); } @@ -1213,7 +1200,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); 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..c786e94a6 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; @@ -478,15 +472,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 +560,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..054d8b1f3 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) - { + if( is_group_owned ) self->mOwnerList->addGroupNameItem(row, ADD_BOTTOM); - } else - { self->mOwnerList->addNameItem(row, 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..aebb4009a 100644 --- a/indra/newview/llfloatermute.cpp +++ b/indra/newview/llfloatermute.cpp @@ -43,6 +43,7 @@ // project include #include "llagent.h" +#include "llavatarnamecache.h" #include "llfloateravatarpicker.h" #include "llbutton.h" #include "lllineeditor.h" @@ -314,22 +315,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..9034bf670 100644 --- a/indra/newview/llfloatermute.h +++ b/indra/newview/llfloatermute.h @@ -37,6 +37,7 @@ #include "llmutelist.h" #include +class LLAvatarName; class LLButton; class LLLineEditor; class LLMessageSystem; @@ -68,7 +69,7 @@ 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*); 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/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..06497b028 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(); }; } 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/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/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..f21bb2902 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) @@ -904,12 +924,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 +986,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 +1003,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 +1013,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 +1027,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 +1040,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 +1069,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 +1081,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 +1116,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 +1127,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 +1166,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 +1200,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 +1243,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 +1357,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 +1458,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 +1538,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 +1620,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/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/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..84e1d1199 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(); } @@ -993,7 +993,7 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const LLInventoryModel* LLInvFVBridge::getInventoryModel() const { - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLInventoryPanel* panel = mInventoryPanel.get(); return panel ? panel->getModel() : NULL; } @@ -1952,7 +1952,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) { @@ -3322,7 +3322,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 +3603,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 +3797,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 +3846,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 +3980,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 +3998,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 +4163,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 +4574,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) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 8b386710d..945c653ba 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -160,7 +160,7 @@ protected: BOOL restamp); void removeBatchNoCheck(LLDynamicArray& batch); protected: - LLHandle mInventoryPanel; + LLHandle mInventoryPanel; LLFolderView* mRoot; const LLUUID mUUID; // item id LLInventoryType::EType mInvType; 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/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..3cb77c432 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -41,24 +41,54 @@ // 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". + std::string::size_type len = domain.length(); + llassert(len > 14 && domain.substr(len - 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,7 +197,8 @@ 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) { 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 8a09fa7b1..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; } } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 7f707e519..cf1f3c23c 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -306,7 +306,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(); @@ -568,11 +568,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/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index e46049a3d..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 @@ -871,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); @@ -935,7 +918,7 @@ 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(); 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 858dfc22a..2f44a34bc 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -37,6 +37,7 @@ #include "llavatarnamecache.h" #include "llfloateravatarpicker.h" #include "llbutton.h" +#include "llcallingcard.h" #include "llcombobox.h" #include "llgroupmgr.h" #include "llnamelistctrl.h" @@ -55,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(); @@ -66,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: @@ -81,6 +86,8 @@ public: LLButton *mRemoveButton; LLTextBox *mGroupName; std::string mOwnerWarning; + std::string mAlreadyInGroup; + std::string mTooManySelected; bool mConfirmedOwnerInvite; void (*mCloseCallback)(void* data); @@ -108,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; @@ -139,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); } } @@ -168,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); @@ -185,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) { @@ -274,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); + } } } @@ -343,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()); } @@ -388,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(LLAvatarNameCache::getPNSName(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(); @@ -500,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); @@ -510,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); } @@ -525,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 c624c93cd..b7f09bd69 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -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 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/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/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/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..afc63690f 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(); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index dbc2a1961..5c41199c3 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(); } } } @@ -4489,251 +4511,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..cb82d8722 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); @@ -3394,8 +3394,8 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); msg->setHandlerFunc("MapLayerReply", LLWorldMap::processMapLayerReply); - msg->setHandlerFunc("MapBlockReply", LLWorldMap::processMapBlockReply); - msg->setHandlerFunc("MapItemReply", LLWorldMap::processMapItemReply); + msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply); + msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply); msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply); msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index 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/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..835c8ff97 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 @@ -223,6 +226,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 +324,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,6 +422,7 @@ 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() ) { @@ -418,11 +430,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo // Transition to REQUESTED. Viewer has sent some kind // of TeleportRequest to the source simulator gTeleportDisplayTimer.reset(); - if(!gSavedSettings.getBOOL("AscentDisableTeleportScreens"))gViewerWindow->setShowProgress(TRUE); + if(!hide_tp_screen) + gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(0); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); + gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: @@ -446,14 +460,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 +1124,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..48661cd54 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -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..13381f167 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -75,14 +75,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 +93,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 +118,7 @@ public: public: viewer_media_t mMediaImpl; + std::string mDefaultMimeType; bool mInitialized; }; @@ -168,6 +174,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) @@ -1312,7 +1319,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..9c1dea408 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -264,6 +264,10 @@ #include "llagentui.h" #include "llpathfindingmanager.h" +#include "lltexturecache.h" +#include "llvovolume.h" +#include + #include "hippogridmanager.h" using namespace LLOldEvents; @@ -2265,6 +2269,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 +3702,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(); @@ -9469,6 +9571,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/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 70ee4f5bf..e5c7dbcb3 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -208,6 +208,7 @@ 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); @@ -4204,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; @@ -7236,40 +7238,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..f22a1a1af 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), @@ -809,6 +810,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 +1265,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()) { @@ -2132,9 +2135,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 +2217,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 +2234,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 +2248,7 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } updateDrawable(FALSE); - - return TRUE; +} } @@ -5450,9 +5456,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 +5487,6 @@ U8 LLViewerObject::getPhysicsShapeType() const { if (mPhysicsShapeUnknown) { - mPhysicsShapeUnknown = false; gObjectList.updatePhysicsFlags(this); } diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 791393533..c83b1695a 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 }; @@ -219,6 +219,8 @@ public: 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 diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index a53805fe8..2934596e1 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()) @@ -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 67e6ee7ee..f075e7c15 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1538,7 +1538,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 { diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 25014b640..0cd49f717 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1293,7 +1293,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(); @@ -2396,7 +2398,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 +2411,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/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..6e1c57fb3 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,28 @@ 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) + if(gAgent.getTeleportState() != LLAgent::TELEPORT_NONE && gAgent.getTeleportState() != LLAgent::TELEPORT_LOCAL && + (!hide_tp_screen || gAgent.getTeleportState() == LLAgent::TELEPORT_START_ARRIVAL)) { - clearFetchingRequests(); + if(!cleared) + { + 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 +724,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..2348fb588 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -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) { @@ -4093,10 +4093,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 { @@ -4879,6 +4883,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 +4979,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 +5034,8 @@ BOOL LLViewerWindow::checkSettings() desired_screen_size, gSavedSettings.getBOOL("DisableVerticalSync"), mShowFullscreenProgress); - LLGLState::checkStates(); LLGLState::checkTextureChannels(); - mStatesDirty = true; return TRUE; } } @@ -5038,12 +5044,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 +5120,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 +5199,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 +5208,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..990b1799c 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -449,7 +449,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/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 217f165f7..3abfd49a7 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1861,8 +1861,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 +2853,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 +2861,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 +2935,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) if (gNoRender) { - return TRUE; + return; } idleUpdateVoiceVisualizer( voice_enabled ); @@ -2954,8 +2952,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 +3131,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (isImpostor() && !mNeedsImpostorUpdate) { - LLVector4a ext[2]; + LL_ALIGN_16(LLVector4a ext[2]); F32 distance; LLVector3 angle; @@ -5245,7 +5241,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" < is_layer_baked; @@ -8206,7 +8215,7 @@ void LLVOAvatar::onFirstTEMessageReceived() if(!isSelf()) { src_callback_list = &mCallbackTextureList ; - paused = mLoadedCallbacksPaused ; + paused = !isVisible(); } for (U32 i = 0; i < mBakedTextureDatas.size(); i++) @@ -8824,6 +8833,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 +9755,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..2869e1670 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 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..c6df5951f 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() 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/llwebprofile.cpp b/indra/newview/llwebprofile.cpp new file mode 100644 index 000000000..d1c769285 --- /dev/null +++ b/indra/newview/llwebprofile.cpp @@ -0,0 +1,324 @@ +/** + * @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 << "]" << llendl; + LLWebProfile::post(mImagep, config, upload_url); + } + +protected: + /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; } + +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 << "]" << llendl; + LLWebProfile::reportImageUploadStatus(true); + } + +protected: + /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; } + +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 completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + // Viewer seems to fail to follow a 303 redirect on POST request + // (URLRequest Error: 65, 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()); + const std::string& redir_url = content["location"]; + LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl; + LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers); + } + else + { + llwarns << "Unexpected POST status: " << status << " " << reason << llendl; + LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << llendl; + 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; } +}; + +/////////////////////////////////////////////////////////////////////////////// +// 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 << llendl; + 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 << llendl; + 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"; + + // Insert the image data. + // *FIX: Treating this as a string will probably screw it up ... + U8* image_data = image->getData(); + for (S32 i = 0; i < image->getDataSize(); ++i) + { + body << image_data[i]; + } + + body << "\r\n--" << boundary << "--\r\n"; + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = body.str().size(); + char* data = new char [size]; + memcpy(data, body.str().data(), size); + + // Send request, successful upload will trigger posting metadata. + LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers); +} + +// 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/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/pipeline.cpp b/indra/newview/pipeline.cpp index 867370945..6b450d841 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; } //============================================================================ @@ -1456,6 +1461,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 +1664,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 +1800,7 @@ void LLPipeline::grabReferences(LLCullResult& result) void LLPipeline::clearReferences() { sCull = NULL; + mGroupSaveQ1.clear(); } void check_references(LLSpatialGroup* group, LLDrawable* drawable) @@ -2337,6 +2363,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 +2444,7 @@ void LLPipeline::rebuildPriorityGroups() group->clearState(LLSpatialGroup::IN_BUILD_Q1); } + mGroupSaveQ1 = mGroupQ1; mGroupQ1.clear(); mGroupQ1Locked = false; @@ -5037,38 +5123,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 +6241,8 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) } void LLPipeline::resetVertexBuffers() -{ mResetVertexBuffers = true; +{ + mResetVertexBuffers = true; } static LLFastTimer::DeclareTimer FTM_RESET_VB("Reset VB"); @@ -6200,6 +6283,8 @@ void LLPipeline::doResetVertexBuffers() if(LLPostProcess::instanceExists()) LLPostProcess::getInstance()->destroyGL(); + LLVOPartGroup::destroyGL(); + LLVertexBuffer::cleanupClass(); //delete all name pool caches @@ -7217,14 +7302,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 +7852,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 +7867,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 +9760,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..c88e76f69 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); @@ -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/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/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_texture_ctrl.xml b/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml index 83a0d1b16..4ab70c46a 100644 --- a/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml @@ -30,6 +30,9 @@