diff options
103 files changed, 4613 insertions, 3213 deletions
@@ -44,3 +44,4 @@ dc6483491b4af559060bccaef8e9045a303212dd 2.4.0-beta1  3bc1f50a72e117f4d4ad8d555f0c785ea8cc201e 2.4.0-beta1  25bd6007e3d2fc15db9326ed4b18a24a5969a46a 2.4.0-beta2  1ed382c6a08ba3850b6ce9061bc551ddece0ea07 2.4.0-release +a82e5b1e22c7f90e3c7977d146b80588f004ed0d 2.5.0-start diff --git a/doc/contributions.txt b/doc/contributions.txt index 1f52d3e1ef..8b040d333e 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -221,6 +221,8 @@ Catherine Pfeffer  Celierra Darling  	VWR-1274  	VWR-6975 +Coaldust Numbers +    VWR-1095  Cron Stardust  	VWR-10579  Cypren Christenson @@ -366,15 +368,17 @@ JB Kraft  Joghert LeSabre  	VWR-64  Jonathan Yap -	STORM-596  	STORM-523 +	STORM-596 +	STORM-615  	STORM-616  	STORM-679 -	STORM-737 +	STORM-723  	STORM-726 +	STORM-737 +	STORM-785  	STORM-812  	VWR-17801 -	STORM-785  Kage Pixel  	VWR-11  Ken March diff --git a/etc/message.xml b/etc/message.xml index 490d73e1b2..3445975545 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -685,20 +685,17 @@  			<key>EstateChangeInfo</key>  			<boolean>true</boolean> -			<key>FetchInventoryDescendents</key> +			<key>FetchInventoryDescendents2</key>  			<boolean>false</boolean> -			<key>WebFetchInventoryDescendents</key> -			<boolean>true</boolean> -		 -			<key>FetchInventory</key> -			<boolean>true</boolean> +			<key>FetchInventory2</key> +			<boolean>false</boolean> -			<key>FetchLibDescendents</key> -			<boolean>true</boolean> +			<key>FetchLibDescendents2</key> +			<boolean>false</boolean> -			<key>FetchLib</key> -			<boolean>true</boolean> +			<key>FetchLib2</key> +			<boolean>false</boolean>  			<key>UploadBakedTexture</key>  			<boolean>true</boolean> diff --git a/indra/cmake/GetPrerequisites_2_8.cmake b/indra/cmake/GetPrerequisites_2_8.cmake index 5a24842c89..05ec1539ba 100644 --- a/indra/cmake/GetPrerequisites_2_8.cmake +++ b/indra/cmake/GetPrerequisites_2_8.cmake @@ -1,786 +1,786 @@ -# GetPrerequisites.cmake
 -#
 -# This script provides functions to list the .dll, .dylib or .so files that an
 -# executable or shared library file depends on. (Its prerequisites.)
 -#
 -# It uses various tools to obtain the list of required shared library files:
 -#   dumpbin (Windows)
 -#   ldd (Linux/Unix)
 -#   otool (Mac OSX)
 -#
 -# The following functions are provided by this script:
 -#   gp_append_unique
 -#   is_file_executable
 -#   gp_item_default_embedded_path
 -#     (projects can override with gp_item_default_embedded_path_override)
 -#   gp_resolve_item
 -#     (projects can override with gp_resolve_item_override)
 -#   gp_resolved_file_type
 -#   gp_file_type
 -#   get_prerequisites
 -#   list_prerequisites
 -#   list_prerequisites_by_glob
 -#
 -# Requires CMake 2.6 or greater because it uses function, break, return and
 -# PARENT_SCOPE.
 -
 -#=============================================================================
 -# Copyright 2008-2009 Kitware, Inc.
 -#
 -# Distributed under the OSI-approved BSD License (the "License");
 -# see accompanying file Copyright.txt for details.
 -#
 -# This software is distributed WITHOUT ANY WARRANTY; without even the
 -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 -# See the License for more information.
 -#=============================================================================
 -# (To distributed this file outside of CMake, substitute the full
 -#  License text for the above reference.)
 -
 -# gp_append_unique list_var value
 -#
 -# Append value to the list variable ${list_var} only if the value is not
 -# already in the list.
 -#
 -function(gp_append_unique list_var value)
 -  set(contains 0)
 -
 -  foreach(item ${${list_var}})
 -    if("${item}" STREQUAL "${value}")
 -      set(contains 1)
 -      break()
 -    endif("${item}" STREQUAL "${value}")
 -  endforeach(item)
 -
 -  if(NOT contains)
 -    set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE)
 -  endif(NOT contains)
 -endfunction(gp_append_unique)
 -
 -
 -# is_file_executable file result_var
 -#
 -# Return 1 in ${result_var} if ${file} is a binary executable.
 -#
 -# Return 0 in ${result_var} otherwise.
 -#
 -function(is_file_executable file result_var)
 -  #
 -  # A file is not executable until proven otherwise:
 -  #
 -  set(${result_var} 0 PARENT_SCOPE)
 -
 -  get_filename_component(file_full "${file}" ABSOLUTE)
 -  string(TOLOWER "${file_full}" file_full_lower)
 -
 -  # If file name ends in .exe on Windows, *assume* executable:
 -  #
 -  if(WIN32)
 -    if("${file_full_lower}" MATCHES "\\.exe$")
 -      set(${result_var} 1 PARENT_SCOPE)
 -      return()
 -    endif("${file_full_lower}" MATCHES "\\.exe$")
 -
 -    # A clause could be added here that uses output or return value of dumpbin
 -    # to determine ${result_var}. In 99%+? practical cases, the exe name
 -    # match will be sufficient...
 -    #
 -  endif(WIN32)
 -
 -  # Use the information returned from the Unix shell command "file" to
 -  # determine if ${file_full} should be considered an executable file...
 -  #
 -  # If the file command's output contains "executable" and does *not* contain
 -  # "text" then it is likely an executable suitable for prerequisite analysis
 -  # via the get_prerequisites macro.
 -  #
 -  if(UNIX)
 -    if(NOT file_cmd)
 -      find_program(file_cmd "file")
 -    endif(NOT file_cmd)
 -
 -    if(file_cmd)
 -      execute_process(COMMAND "${file_cmd}" "${file_full}"
 -        OUTPUT_VARIABLE file_ov
 -        OUTPUT_STRIP_TRAILING_WHITESPACE
 -        )
 -
 -      # Replace the name of the file in the output with a placeholder token
 -      # (the string " _file_full_ ") so that just in case the path name of
 -      # the file contains the word "text" or "executable" we are not fooled
 -      # into thinking "the wrong thing" because the file name matches the
 -      # other 'file' command output we are looking for...
 -      #
 -      string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}")
 -      string(TOLOWER "${file_ov}" file_ov)
 -
 -      #message(STATUS "file_ov='${file_ov}'")
 -      if("${file_ov}" MATCHES "executable")
 -        #message(STATUS "executable!")
 -        if("${file_ov}" MATCHES "text")
 -          #message(STATUS "but text, so *not* a binary executable!")
 -        else("${file_ov}" MATCHES "text")
 -          set(${result_var} 1 PARENT_SCOPE)
 -          return()
 -        endif("${file_ov}" MATCHES "text")
 -      endif("${file_ov}" MATCHES "executable")
 -    else(file_cmd)
 -      message(STATUS "warning: No 'file' command, skipping execute_process...")
 -    endif(file_cmd)
 -  endif(UNIX)
 -endfunction(is_file_executable)
 -
 -
 -# gp_item_default_embedded_path item default_embedded_path_var
 -#
 -# Return the path that others should refer to the item by when the item
 -# is embedded inside a bundle.
 -#
 -# Override on a per-project basis by providing a project-specific
 -# gp_item_default_embedded_path_override function.
 -#
 -function(gp_item_default_embedded_path item default_embedded_path_var)
 -
 -  # On Windows and Linux, "embed" prerequisites in the same directory
 -  # as the executable by default:
 -  #
 -  set(path "@executable_path")
 -  set(overridden 0)
 -
 -  # On the Mac, relative to the executable depending on the type
 -  # of the thing we are embedding:
 -  #
 -  if(APPLE)
 -    #
 -    # The assumption here is that all executables in the bundle will be
 -    # in same-level-directories inside the bundle. The parent directory
 -    # of an executable inside the bundle should be MacOS or a sibling of
 -    # MacOS and all embedded paths returned from here will begin with
 -    # "@executable_path/../" and will work from all executables in all
 -    # such same-level-directories inside the bundle.
 -    #
 -
 -    # By default, embed things right next to the main bundle executable:
 -    #
 -    set(path "@executable_path/../../Contents/MacOS")
 -
 -    # Embed .dylibs right next to the main bundle executable:
 -    #
 -    if(item MATCHES "\\.dylib$")
 -      set(path "@executable_path/../MacOS")
 -      set(overridden 1)
 -    endif(item MATCHES "\\.dylib$")
 -
 -    # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS):
 -    #
 -    if(NOT overridden)
 -      if(item MATCHES "[^/]+\\.framework/")
 -        set(path "@executable_path/../Frameworks")
 -        set(overridden 1)
 -      endif(item MATCHES "[^/]+\\.framework/")
 -    endif(NOT overridden)
 -  endif()
 -
 -  # Provide a hook so that projects can override the default embedded location
 -  # of any given library by whatever logic they choose:
 -  #
 -  if(COMMAND gp_item_default_embedded_path_override)
 -    gp_item_default_embedded_path_override("${item}" path)
 -  endif(COMMAND gp_item_default_embedded_path_override)
 -
 -  set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
 -endfunction(gp_item_default_embedded_path)
 -
 -
 -# gp_resolve_item context item exepath dirs resolved_item_var
 -#
 -# Resolve an item into an existing full path file.
 -#
 -# Override on a per-project basis by providing a project-specific
 -# gp_resolve_item_override function.
 -#
 -function(gp_resolve_item context item exepath dirs resolved_item_var)
 -  set(resolved 0)
 -  set(resolved_item "${item}")
 -
 -  # Is it already resolved?
 -  #
 -  if(EXISTS "${resolved_item}")
 -    set(resolved 1)
 -  endif(EXISTS "${resolved_item}")
 -
 -  if(NOT resolved)
 -    if(item MATCHES "@executable_path")
 -      #
 -      # @executable_path references are assumed relative to exepath
 -      #
 -      string(REPLACE "@executable_path" "${exepath}" ri "${item}")
 -      get_filename_component(ri "${ri}" ABSOLUTE)
 -
 -      if(EXISTS "${ri}")
 -        #message(STATUS "info: embedded item exists (${ri})")
 -        set(resolved 1)
 -        set(resolved_item "${ri}")
 -      else(EXISTS "${ri}")
 -        message(STATUS "warning: embedded item does not exist '${ri}'")
 -      endif(EXISTS "${ri}")
 -    endif(item MATCHES "@executable_path")
 -  endif(NOT resolved)
 -
 -  if(NOT resolved)
 -    if(item MATCHES "@loader_path")
 -      #
 -      # @loader_path references are assumed relative to the
 -      # PATH of the given "context" (presumably another library)
 -      #
 -      get_filename_component(contextpath "${context}" PATH)
 -      string(REPLACE "@loader_path" "${contextpath}" ri "${item}")
 -      get_filename_component(ri "${ri}" ABSOLUTE)
 -
 -      if(EXISTS "${ri}")
 -        #message(STATUS "info: embedded item exists (${ri})")
 -        set(resolved 1)
 -        set(resolved_item "${ri}")
 -      else(EXISTS "${ri}")
 -        message(STATUS "warning: embedded item does not exist '${ri}'")
 -      endif(EXISTS "${ri}")
 -    endif(item MATCHES "@loader_path")
 -  endif(NOT resolved)
 -
 -  if(NOT resolved)
 -    set(ri "ri-NOTFOUND")
 -    find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
 -    find_file(ri "${item}" ${exepath} ${dirs} /usr/lib)
 -    if(ri)
 -      #message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
 -      set(resolved 1)
 -      set(resolved_item "${ri}")
 -      set(ri "ri-NOTFOUND")
 -    endif(ri)
 -  endif(NOT resolved)
 -
 -  if(NOT resolved)
 -    if(item MATCHES "[^/]+\\.framework/")
 -      set(fw "fw-NOTFOUND")
 -      find_file(fw "${item}"
 -        "~/Library/Frameworks"
 -        "/Library/Frameworks"
 -        "/System/Library/Frameworks"
 -      )
 -      if(fw)
 -        #message(STATUS "info: 'find_file' found framework (${fw})")
 -        set(resolved 1)
 -        set(resolved_item "${fw}")
 -        set(fw "fw-NOTFOUND")
 -      endif(fw)
 -    endif(item MATCHES "[^/]+\\.framework/")
 -  endif(NOT resolved)
 -
 -  # Using find_program on Windows will find dll files that are in the PATH.
 -  # (Converting simple file names into full path names if found.)
 -  #
 -  if(WIN32)
 -  if(NOT resolved)
 -    set(ri "ri-NOTFOUND")
 -    find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH)
 -    find_program(ri "${item}" PATHS "${exepath};${dirs}")
 -    if(ri)
 -      #message(STATUS "info: 'find_program' in exepath/dirs (${ri})")
 -      set(resolved 1)
 -      set(resolved_item "${ri}")
 -      set(ri "ri-NOTFOUND")
 -    endif(ri)
 -  endif(NOT resolved)
 -  endif(WIN32)
 -
 -  # Provide a hook so that projects can override item resolution
 -  # by whatever logic they choose:
 -  #
 -  if(COMMAND gp_resolve_item_override)
 -    gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved)
 -  endif(COMMAND gp_resolve_item_override)
 -
 -  if(NOT resolved)
 -    message(STATUS "
 -warning: cannot resolve item '${item}'
 -
 -  possible problems:
 -    need more directories?
 -    need to use InstallRequiredSystemLibraries?
 -    run in install tree instead of build tree?
 -")
 -#    message(STATUS "
 -#******************************************************************************
 -#warning: cannot resolve item '${item}'
 -#
 -#  possible problems:
 -#    need more directories?
 -#    need to use InstallRequiredSystemLibraries?
 -#    run in install tree instead of build tree?
 -#
 -#    context='${context}'
 -#    item='${item}'
 -#    exepath='${exepath}'
 -#    dirs='${dirs}'
 -#    resolved_item_var='${resolved_item_var}'
 -#******************************************************************************
 -#")
 -  endif(NOT resolved)
 -
 -  set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
 -endfunction(gp_resolve_item)
 -
 -
 -# gp_resolved_file_type original_file file exepath dirs type_var
 -#
 -# Return the type of ${file} with respect to ${original_file}. String
 -# describing type of prerequisite is returned in variable named ${type_var}.
 -#
 -# Use ${exepath} and ${dirs} if necessary to resolve non-absolute ${file}
 -# values -- but only for non-embedded items.
 -#
 -# Possible types are:
 -#   system
 -#   local
 -#   embedded
 -#   other
 -#
 -function(gp_resolved_file_type original_file file exepath dirs type_var)
 -  #message(STATUS "**")
 -
 -  if(NOT IS_ABSOLUTE "${original_file}")
 -    message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file")
 -  endif()
 -
 -  set(is_embedded 0)
 -  set(is_local 0)
 -  set(is_system 0)
 -
 -  set(resolved_file "${file}")
 -
 -  if("${file}" MATCHES "^@(executable|loader)_path")
 -    set(is_embedded 1)
 -  endif()
 -
 -  if(NOT is_embedded)
 -    if(NOT IS_ABSOLUTE "${file}")
 -      gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file)
 -    endif()
 -
 -    string(TOLOWER "${original_file}" original_lower)
 -    string(TOLOWER "${resolved_file}" lower)
 -
 -    if(UNIX)
 -      if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/)")
 -        set(is_system 1)
 -      endif()
 -    endif()
 -
 -    if(APPLE)
 -      if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)")
 -        set(is_system 1)
 -      endif()
 -    endif()
 -
 -    if(WIN32)
 -      string(TOLOWER "$ENV{SystemRoot}" sysroot)
 -      string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}")
 -
 -      string(TOLOWER "$ENV{windir}" windir)
 -      string(REGEX REPLACE "\\\\" "/" windir "${windir}")
 -
 -      if(lower MATCHES "^(${sysroot}/system|${windir}/system|${sysroot}/syswow|${windir}/syswow|(.*/)*msvc[^/]+dll)")
 -        set(is_system 1)
 -      endif()
 -    endif()
 -
 -    if(NOT is_system)
 -      get_filename_component(original_path "${original_lower}" PATH)
 -      get_filename_component(path "${lower}" PATH)
 -      if("${original_path}" STREQUAL "${path}")
 -        set(is_local 1)
 -      endif()
 -    endif()
 -  endif()
 -
 -  # Return type string based on computed booleans:
 -  #
 -  set(type "other")
 -
 -  if(is_system)
 -    set(type "system")
 -  elseif(is_embedded)
 -    set(type "embedded")
 -  elseif(is_local)
 -    set(type "local")
 -  endif()
 -
 -  #message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'")
 -  #message(STATUS "                type: '${type}'")
 -
 -  if(NOT is_embedded)
 -    if(NOT IS_ABSOLUTE "${resolved_file}")
 -      if(lower MATCHES "^msvc[^/]+dll" AND is_system)
 -        message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'")
 -      else()
 -        message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect")
 -      endif()
 -    endif()
 -  endif()
 -
 -  set(${type_var} "${type}" PARENT_SCOPE)
 -
 -  #message(STATUS "**")
 -endfunction()
 -
 -
 -# gp_file_type original_file file type_var
 -#
 -# Return the type of ${file} with respect to ${original_file}. String
 -# describing type of prerequisite is returned in variable named ${type_var}.
 -#
 -# Possible types are:
 -#   system
 -#   local
 -#   embedded
 -#   other
 -#
 -function(gp_file_type original_file file type_var)
 -  if(NOT IS_ABSOLUTE "${original_file}")
 -    message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file")
 -  endif()
 -
 -  get_filename_component(exepath "${original_file}" PATH)
 -
 -  set(type "")
 -  gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type)
 -
 -  set(${type_var} "${type}" PARENT_SCOPE)
 -endfunction(gp_file_type)
 -
 -
 -# get_prerequisites target prerequisites_var exclude_system recurse dirs
 -#
 -# Get the list of shared library files required by ${target}. The list in
 -# the variable named ${prerequisites_var} should be empty on first entry to
 -# this function. On exit, ${prerequisites_var} will contain the list of
 -# required shared library files.
 -#
 -#  target is the full path to an executable file
 -#
 -#  prerequisites_var is the name of a CMake variable to contain the results
 -#
 -#  exclude_system is 0 or 1: 0 to include "system" prerequisites , 1 to
 -#   exclude them
 -#
 -#  recurse is 0 or 1: 0 for direct prerequisites only, 1 for all prerequisites
 -#   recursively
 -#
 -#  exepath is the path to the top level executable used for @executable_path
 -#   replacment on the Mac
 -#
 -#  dirs is a list of paths where libraries might be found: these paths are
 -#   searched first when a target without any path info is given. Then standard
 -#   system locations are also searched: PATH, Framework locations, /usr/lib...
 -#
 -function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs)
 -  set(verbose 0)
 -  set(eol_char "E")
 -
 -  if(NOT IS_ABSOLUTE "${target}")
 -    message("warning: target '${target}' is not absolute...")
 -  endif(NOT IS_ABSOLUTE "${target}")
 -
 -  if(NOT EXISTS "${target}")
 -    message("warning: target '${target}' does not exist...")
 -  endif(NOT EXISTS "${target}")
 -
 -  # <setup-gp_tool-vars>
 -  #
 -  # Try to choose the right tool by default. Caller can set gp_tool prior to
 -  # calling this function to force using a different tool.
 -  #
 -  if("${gp_tool}" STREQUAL "")
 -    set(gp_tool "ldd")
 -    if(APPLE)
 -      set(gp_tool "otool")
 -    endif(APPLE)
 -    if(WIN32)
 -      set(gp_tool "dumpbin")
 -    endif(WIN32)
 -  endif("${gp_tool}" STREQUAL "")
 -
 -  set(gp_tool_known 0)
 -
 -  if("${gp_tool}" STREQUAL "ldd")
 -    set(gp_cmd_args "")
 -    set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$")
 -    set(gp_regex_cmp_count 1)
 -    set(gp_tool_known 1)
 -  endif("${gp_tool}" STREQUAL "ldd")
 -
 -  if("${gp_tool}" STREQUAL "otool")
 -    set(gp_cmd_args "-L")
 -    set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$")
 -    set(gp_regex_cmp_count 3)
 -    set(gp_tool_known 1)
 -  endif("${gp_tool}" STREQUAL "otool")
 -
 -  if("${gp_tool}" STREQUAL "dumpbin")
 -    set(gp_cmd_args "/dependents")
 -    set(gp_regex "^    ([^ ].*[Dd][Ll][Ll])${eol_char}$")
 -    set(gp_regex_cmp_count 1)
 -    set(gp_tool_known 1)
 -    set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE.
 -  endif("${gp_tool}" STREQUAL "dumpbin")
 -
 -  if(NOT gp_tool_known)
 -    message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...")
 -    message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'")
 -    message(STATUS "Valid gp_tool values are dumpbin, ldd and otool.")
 -    return()
 -  endif(NOT gp_tool_known)
 -
 -  set(gp_cmd_paths ${gp_cmd_paths}
 -    "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin"
 -    "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin"
 -    "C:/Program Files/Microsoft Visual Studio 8/VC/BIN"
 -    "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN"
 -    "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN"
 -    "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN"
 -    "/usr/local/bin"
 -    "/usr/bin"
 -    )
 -
 -  find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths})
 -
 -  if(NOT gp_cmd)
 -    message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...")
 -    return()
 -  endif(NOT gp_cmd)
 -
 -  if("${gp_tool}" STREQUAL "dumpbin")
 -    # When running dumpbin, it also needs the "Common7/IDE" directory in the
 -    # PATH. It will already be in the PATH if being run from a Visual Studio
 -    # command prompt. Add it to the PATH here in case we are running from a
 -    # different command prompt.
 -    #
 -    get_filename_component(gp_cmd_dir "${gp_cmd}" PATH)
 -    get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE)
 -    if(EXISTS "${gp_cmd_dlls_dir}")
 -      # only add to the path if it is not already in the path
 -      if(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
 -        set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}")
 -      endif(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
 -    endif(EXISTS "${gp_cmd_dlls_dir}")
 -  endif("${gp_tool}" STREQUAL "dumpbin")
 -  #
 -  # </setup-gp_tool-vars>
 -
 -  if("${gp_tool}" STREQUAL "ldd")
 -    set(old_ld_env "$ENV{LD_LIBRARY_PATH}")
 -    foreach(dir ${exepath} ${dirs})
 -      set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}")
 -    endforeach(dir)
 -  endif("${gp_tool}" STREQUAL "ldd")
 -
 -
 -  # Track new prerequisites at each new level of recursion. Start with an
 -  # empty list at each level:
 -  #
 -  set(unseen_prereqs)
 -
 -  # Run gp_cmd on the target:
 -  #
 -  execute_process(
 -    COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
 -    OUTPUT_VARIABLE gp_cmd_ov
 -    )
 -
 -  if("${gp_tool}" STREQUAL "ldd")
 -    set(ENV{LD_LIBRARY_PATH} "${old_ld_env}")
 -  endif("${gp_tool}" STREQUAL "ldd")
 -
 -  if(verbose)
 -    message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>")
 -    message(STATUS "gp_cmd_ov='${gp_cmd_ov}'")
 -    message(STATUS "</RawOutput>")
 -  endif(verbose)
 -
 -  get_filename_component(target_dir "${target}" PATH)
 -
 -  # Convert to a list of lines:
 -  #
 -  string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}")
 -  string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}")
 -
 -  # Analyze each line for file names that match the regular expression:
 -  #
 -  foreach(candidate ${candidates})
 -  if("${candidate}" MATCHES "${gp_regex}")
 -    # Extract information from each candidate:
 -    string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}")
 -
 -    if(gp_regex_cmp_count GREATER 1)
 -      string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}")
 -      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}")
 -      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}")
 -      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}")
 -    endif(gp_regex_cmp_count GREATER 1)
 -
 -    if(gp_regex_cmp_count GREATER 2)
 -      string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}")
 -      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}")
 -      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}")
 -      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}")
 -    endif(gp_regex_cmp_count GREATER 2)
 -
 -    # Use the raw_item as the list entries returned by this function. Use the
 -    # gp_resolve_item function to resolve it to an actual full path file if
 -    # necessary.
 -    #
 -    set(item "${raw_item}")
 -
 -    # Add each item unless it is excluded:
 -    #
 -    set(add_item 1)
 -
 -    if(${exclude_system})
 -      set(type "")
 -      gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type)
 -      if("${type}" STREQUAL "system")
 -        set(add_item 0)
 -      endif("${type}" STREQUAL "system")
 -    endif(${exclude_system})
 -
 -    if(add_item)
 -      list(LENGTH ${prerequisites_var} list_length_before_append)
 -      gp_append_unique(${prerequisites_var} "${item}")
 -      list(LENGTH ${prerequisites_var} list_length_after_append)
 -
 -      if(${recurse})
 -        # If item was really added, this is the first time we have seen it.
 -        # Add it to unseen_prereqs so that we can recursively add *its*
 -        # prerequisites...
 -        #
 -        # But first: resolve its name to an absolute full path name such
 -        # that the analysis tools can simply accept it as input.
 -        #
 -        if(NOT list_length_before_append EQUAL list_length_after_append)
 -          gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item)
 -          set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
 -        endif(NOT list_length_before_append EQUAL list_length_after_append)
 -      endif(${recurse})
 -    endif(add_item)
 -  else("${candidate}" MATCHES "${gp_regex}")
 -    if(verbose)
 -      message(STATUS "ignoring non-matching line: '${candidate}'")
 -    endif(verbose)
 -  endif("${candidate}" MATCHES "${gp_regex}")
 -  endforeach(candidate)
 -
 -  list(LENGTH ${prerequisites_var} prerequisites_var_length)
 -  if(prerequisites_var_length GREATER 0)
 -    list(SORT ${prerequisites_var})
 -  endif(prerequisites_var_length GREATER 0)
 -  if(${recurse})
 -    set(more_inputs ${unseen_prereqs})
 -    foreach(input ${more_inputs})
 -      get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}")
 -    endforeach(input)
 -  endif(${recurse})
 -
 -  set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE)
 -endfunction(get_prerequisites)
 -
 -
 -# list_prerequisites target all exclude_system verbose
 -#
 -#  ARGV0 (target) is the full path to an executable file
 -#
 -#  optional ARGV1 (all) is 0 or 1: 0 for direct prerequisites only,
 -#   1 for all prerequisites recursively
 -#
 -#  optional ARGV2 (exclude_system) is 0 or 1: 0 to include "system"
 -#   prerequisites , 1 to exclude them
 -#
 -#  optional ARGV3 (verbose) is 0 or 1: 0 to print only full path
 -#   names of prerequisites, 1 to print extra information
 -#
 -function(list_prerequisites target)
 -  if("${ARGV1}" STREQUAL "")
 -    set(all 1)
 -  else("${ARGV1}" STREQUAL "")
 -    set(all "${ARGV1}")
 -  endif("${ARGV1}" STREQUAL "")
 -
 -  if("${ARGV2}" STREQUAL "")
 -    set(exclude_system 0)
 -  else("${ARGV2}" STREQUAL "")
 -    set(exclude_system "${ARGV2}")
 -  endif("${ARGV2}" STREQUAL "")
 -
 -  if("${ARGV3}" STREQUAL "")
 -    set(verbose 0)
 -  else("${ARGV3}" STREQUAL "")
 -    set(verbose "${ARGV3}")
 -  endif("${ARGV3}" STREQUAL "")
 -
 -  set(count 0)
 -  set(count_str "")
 -  set(print_count "${verbose}")
 -  set(print_prerequisite_type "${verbose}")
 -  set(print_target "${verbose}")
 -  set(type_str "")
 -
 -  get_filename_component(exepath "${target}" PATH)
 -
 -  set(prereqs "")
 -  get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "")
 -
 -  if(print_target)
 -    message(STATUS "File '${target}' depends on:")
 -  endif(print_target)
 -
 -  foreach(d ${prereqs})
 -    math(EXPR count "${count} + 1")
 -
 -    if(print_count)
 -      set(count_str "${count}. ")
 -    endif(print_count)
 -
 -    if(print_prerequisite_type)
 -      gp_file_type("${target}" "${d}" type)
 -      set(type_str " (${type})")
 -    endif(print_prerequisite_type)
 -
 -    message(STATUS "${count_str}${d}${type_str}")
 -  endforeach(d)
 -endfunction(list_prerequisites)
 -
 -
 -# list_prerequisites_by_glob glob_arg glob_exp
 -#
 -#  glob_arg is GLOB or GLOB_RECURSE
 -#
 -#  glob_exp is a globbing expression used with "file(GLOB" to retrieve a list
 -#   of matching files. If a matching file is executable, its prerequisites are
 -#   listed.
 -#
 -# Any additional (optional) arguments provided are passed along as the
 -# optional arguments to the list_prerequisites calls.
 -#
 -function(list_prerequisites_by_glob glob_arg glob_exp)
 -  message(STATUS "=============================================================================")
 -  message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'")
 -  message(STATUS "")
 -  file(${glob_arg} file_list ${glob_exp})
 -  foreach(f ${file_list})
 -    is_file_executable("${f}" is_f_executable)
 -    if(is_f_executable)
 -      message(STATUS "=============================================================================")
 -      list_prerequisites("${f}" ${ARGN})
 -      message(STATUS "")
 -    endif(is_f_executable)
 -  endforeach(f)
 -endfunction(list_prerequisites_by_glob)
 +# GetPrerequisites.cmake +# +# This script provides functions to list the .dll, .dylib or .so files that an +# executable or shared library file depends on. (Its prerequisites.) +# +# It uses various tools to obtain the list of required shared library files: +#   dumpbin (Windows) +#   ldd (Linux/Unix) +#   otool (Mac OSX) +# +# The following functions are provided by this script: +#   gp_append_unique +#   is_file_executable +#   gp_item_default_embedded_path +#     (projects can override with gp_item_default_embedded_path_override) +#   gp_resolve_item +#     (projects can override with gp_resolve_item_override) +#   gp_resolved_file_type +#   gp_file_type +#   get_prerequisites +#   list_prerequisites +#   list_prerequisites_by_glob +# +# Requires CMake 2.6 or greater because it uses function, break, return and +# PARENT_SCOPE. + +#============================================================================= +# Copyright 2008-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distributed this file outside of CMake, substitute the full +#  License text for the above reference.) + +# gp_append_unique list_var value +# +# Append value to the list variable ${list_var} only if the value is not +# already in the list. +# +function(gp_append_unique list_var value) +  set(contains 0) + +  foreach(item ${${list_var}}) +    if("${item}" STREQUAL "${value}") +      set(contains 1) +      break() +    endif("${item}" STREQUAL "${value}") +  endforeach(item) + +  if(NOT contains) +    set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE) +  endif(NOT contains) +endfunction(gp_append_unique) + + +# is_file_executable file result_var +# +# Return 1 in ${result_var} if ${file} is a binary executable. +# +# Return 0 in ${result_var} otherwise. +# +function(is_file_executable file result_var) +  # +  # A file is not executable until proven otherwise: +  # +  set(${result_var} 0 PARENT_SCOPE) + +  get_filename_component(file_full "${file}" ABSOLUTE) +  string(TOLOWER "${file_full}" file_full_lower) + +  # If file name ends in .exe on Windows, *assume* executable: +  # +  if(WIN32) +    if("${file_full_lower}" MATCHES "\\.exe$") +      set(${result_var} 1 PARENT_SCOPE) +      return() +    endif("${file_full_lower}" MATCHES "\\.exe$") + +    # A clause could be added here that uses output or return value of dumpbin +    # to determine ${result_var}. In 99%+? practical cases, the exe name +    # match will be sufficient... +    # +  endif(WIN32) + +  # Use the information returned from the Unix shell command "file" to +  # determine if ${file_full} should be considered an executable file... +  # +  # If the file command's output contains "executable" and does *not* contain +  # "text" then it is likely an executable suitable for prerequisite analysis +  # via the get_prerequisites macro. +  # +  if(UNIX) +    if(NOT file_cmd) +      find_program(file_cmd "file") +    endif(NOT file_cmd) + +    if(file_cmd) +      execute_process(COMMAND "${file_cmd}" "${file_full}" +        OUTPUT_VARIABLE file_ov +        OUTPUT_STRIP_TRAILING_WHITESPACE +        ) + +      # Replace the name of the file in the output with a placeholder token +      # (the string " _file_full_ ") so that just in case the path name of +      # the file contains the word "text" or "executable" we are not fooled +      # into thinking "the wrong thing" because the file name matches the +      # other 'file' command output we are looking for... +      # +      string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}") +      string(TOLOWER "${file_ov}" file_ov) + +      #message(STATUS "file_ov='${file_ov}'") +      if("${file_ov}" MATCHES "executable") +        #message(STATUS "executable!") +        if("${file_ov}" MATCHES "text") +          #message(STATUS "but text, so *not* a binary executable!") +        else("${file_ov}" MATCHES "text") +          set(${result_var} 1 PARENT_SCOPE) +          return() +        endif("${file_ov}" MATCHES "text") +      endif("${file_ov}" MATCHES "executable") +    else(file_cmd) +      message(STATUS "warning: No 'file' command, skipping execute_process...") +    endif(file_cmd) +  endif(UNIX) +endfunction(is_file_executable) + + +# gp_item_default_embedded_path item default_embedded_path_var +# +# Return the path that others should refer to the item by when the item +# is embedded inside a bundle. +# +# Override on a per-project basis by providing a project-specific +# gp_item_default_embedded_path_override function. +# +function(gp_item_default_embedded_path item default_embedded_path_var) + +  # On Windows and Linux, "embed" prerequisites in the same directory +  # as the executable by default: +  # +  set(path "@executable_path") +  set(overridden 0) + +  # On the Mac, relative to the executable depending on the type +  # of the thing we are embedding: +  # +  if(APPLE) +    # +    # The assumption here is that all executables in the bundle will be +    # in same-level-directories inside the bundle. The parent directory +    # of an executable inside the bundle should be MacOS or a sibling of +    # MacOS and all embedded paths returned from here will begin with +    # "@executable_path/../" and will work from all executables in all +    # such same-level-directories inside the bundle. +    # + +    # By default, embed things right next to the main bundle executable: +    # +    set(path "@executable_path/../../Contents/MacOS") + +    # Embed .dylibs right next to the main bundle executable: +    # +    if(item MATCHES "\\.dylib$") +      set(path "@executable_path/../MacOS") +      set(overridden 1) +    endif(item MATCHES "\\.dylib$") + +    # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS): +    # +    if(NOT overridden) +      if(item MATCHES "[^/]+\\.framework/") +        set(path "@executable_path/../Frameworks") +        set(overridden 1) +      endif(item MATCHES "[^/]+\\.framework/") +    endif(NOT overridden) +  endif() + +  # Provide a hook so that projects can override the default embedded location +  # of any given library by whatever logic they choose: +  # +  if(COMMAND gp_item_default_embedded_path_override) +    gp_item_default_embedded_path_override("${item}" path) +  endif(COMMAND gp_item_default_embedded_path_override) + +  set(${default_embedded_path_var} "${path}" PARENT_SCOPE) +endfunction(gp_item_default_embedded_path) + + +# gp_resolve_item context item exepath dirs resolved_item_var +# +# Resolve an item into an existing full path file. +# +# Override on a per-project basis by providing a project-specific +# gp_resolve_item_override function. +# +function(gp_resolve_item context item exepath dirs resolved_item_var) +  set(resolved 0) +  set(resolved_item "${item}") + +  # Is it already resolved? +  # +  if(EXISTS "${resolved_item}") +    set(resolved 1) +  endif(EXISTS "${resolved_item}") + +  if(NOT resolved) +    if(item MATCHES "@executable_path") +      # +      # @executable_path references are assumed relative to exepath +      # +      string(REPLACE "@executable_path" "${exepath}" ri "${item}") +      get_filename_component(ri "${ri}" ABSOLUTE) + +      if(EXISTS "${ri}") +        #message(STATUS "info: embedded item exists (${ri})") +        set(resolved 1) +        set(resolved_item "${ri}") +      else(EXISTS "${ri}") +        message(STATUS "warning: embedded item does not exist '${ri}'") +      endif(EXISTS "${ri}") +    endif(item MATCHES "@executable_path") +  endif(NOT resolved) + +  if(NOT resolved) +    if(item MATCHES "@loader_path") +      # +      # @loader_path references are assumed relative to the +      # PATH of the given "context" (presumably another library) +      # +      get_filename_component(contextpath "${context}" PATH) +      string(REPLACE "@loader_path" "${contextpath}" ri "${item}") +      get_filename_component(ri "${ri}" ABSOLUTE) + +      if(EXISTS "${ri}") +        #message(STATUS "info: embedded item exists (${ri})") +        set(resolved 1) +        set(resolved_item "${ri}") +      else(EXISTS "${ri}") +        message(STATUS "warning: embedded item does not exist '${ri}'") +      endif(EXISTS "${ri}") +    endif(item MATCHES "@loader_path") +  endif(NOT resolved) + +  if(NOT resolved) +    set(ri "ri-NOTFOUND") +    find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH) +    find_file(ri "${item}" ${exepath} ${dirs} /usr/lib) +    if(ri) +      #message(STATUS "info: 'find_file' in exepath/dirs (${ri})") +      set(resolved 1) +      set(resolved_item "${ri}") +      set(ri "ri-NOTFOUND") +    endif(ri) +  endif(NOT resolved) + +  if(NOT resolved) +    if(item MATCHES "[^/]+\\.framework/") +      set(fw "fw-NOTFOUND") +      find_file(fw "${item}" +        "~/Library/Frameworks" +        "/Library/Frameworks" +        "/System/Library/Frameworks" +      ) +      if(fw) +        #message(STATUS "info: 'find_file' found framework (${fw})") +        set(resolved 1) +        set(resolved_item "${fw}") +        set(fw "fw-NOTFOUND") +      endif(fw) +    endif(item MATCHES "[^/]+\\.framework/") +  endif(NOT resolved) + +  # Using find_program on Windows will find dll files that are in the PATH. +  # (Converting simple file names into full path names if found.) +  # +  if(WIN32) +  if(NOT resolved) +    set(ri "ri-NOTFOUND") +    find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH) +    find_program(ri "${item}" PATHS "${exepath};${dirs}") +    if(ri) +      #message(STATUS "info: 'find_program' in exepath/dirs (${ri})") +      set(resolved 1) +      set(resolved_item "${ri}") +      set(ri "ri-NOTFOUND") +    endif(ri) +  endif(NOT resolved) +  endif(WIN32) + +  # Provide a hook so that projects can override item resolution +  # by whatever logic they choose: +  # +  if(COMMAND gp_resolve_item_override) +    gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved) +  endif(COMMAND gp_resolve_item_override) + +  if(NOT resolved) +    message(STATUS " +warning: cannot resolve item '${item}' + +  possible problems: +    need more directories? +    need to use InstallRequiredSystemLibraries? +    run in install tree instead of build tree? +") +#    message(STATUS " +#****************************************************************************** +#warning: cannot resolve item '${item}' +# +#  possible problems: +#    need more directories? +#    need to use InstallRequiredSystemLibraries? +#    run in install tree instead of build tree? +# +#    context='${context}' +#    item='${item}' +#    exepath='${exepath}' +#    dirs='${dirs}' +#    resolved_item_var='${resolved_item_var}' +#****************************************************************************** +#") +  endif(NOT resolved) + +  set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE) +endfunction(gp_resolve_item) + + +# gp_resolved_file_type original_file file exepath dirs type_var +# +# Return the type of ${file} with respect to ${original_file}. String +# describing type of prerequisite is returned in variable named ${type_var}. +# +# Use ${exepath} and ${dirs} if necessary to resolve non-absolute ${file} +# values -- but only for non-embedded items. +# +# Possible types are: +#   system +#   local +#   embedded +#   other +# +function(gp_resolved_file_type original_file file exepath dirs type_var) +  #message(STATUS "**") + +  if(NOT IS_ABSOLUTE "${original_file}") +    message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file") +  endif() + +  set(is_embedded 0) +  set(is_local 0) +  set(is_system 0) + +  set(resolved_file "${file}") + +  if("${file}" MATCHES "^@(executable|loader)_path") +    set(is_embedded 1) +  endif() + +  if(NOT is_embedded) +    if(NOT IS_ABSOLUTE "${file}") +      gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file) +    endif() + +    string(TOLOWER "${original_file}" original_lower) +    string(TOLOWER "${resolved_file}" lower) + +    if(UNIX) +      if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/)") +        set(is_system 1) +      endif() +    endif() + +    if(APPLE) +      if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)") +        set(is_system 1) +      endif() +    endif() + +    if(WIN32) +      string(TOLOWER "$ENV{SystemRoot}" sysroot) +      string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}") + +      string(TOLOWER "$ENV{windir}" windir) +      string(REGEX REPLACE "\\\\" "/" windir "${windir}") + +      if(lower MATCHES "^(${sysroot}/system|${windir}/system|${sysroot}/syswow|${windir}/syswow|(.*/)*msvc[^/]+dll)") +        set(is_system 1) +      endif() +    endif() + +    if(NOT is_system) +      get_filename_component(original_path "${original_lower}" PATH) +      get_filename_component(path "${lower}" PATH) +      if("${original_path}" STREQUAL "${path}") +        set(is_local 1) +      endif() +    endif() +  endif() + +  # Return type string based on computed booleans: +  # +  set(type "other") + +  if(is_system) +    set(type "system") +  elseif(is_embedded) +    set(type "embedded") +  elseif(is_local) +    set(type "local") +  endif() + +  #message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'") +  #message(STATUS "                type: '${type}'") + +  if(NOT is_embedded) +    if(NOT IS_ABSOLUTE "${resolved_file}") +      if(lower MATCHES "^msvc[^/]+dll" AND is_system) +        message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'") +      else() +        message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect") +      endif() +    endif() +  endif() + +  set(${type_var} "${type}" PARENT_SCOPE) + +  #message(STATUS "**") +endfunction() + + +# gp_file_type original_file file type_var +# +# Return the type of ${file} with respect to ${original_file}. String +# describing type of prerequisite is returned in variable named ${type_var}. +# +# Possible types are: +#   system +#   local +#   embedded +#   other +# +function(gp_file_type original_file file type_var) +  if(NOT IS_ABSOLUTE "${original_file}") +    message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file") +  endif() + +  get_filename_component(exepath "${original_file}" PATH) + +  set(type "") +  gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type) + +  set(${type_var} "${type}" PARENT_SCOPE) +endfunction(gp_file_type) + + +# get_prerequisites target prerequisites_var exclude_system recurse dirs +# +# Get the list of shared library files required by ${target}. The list in +# the variable named ${prerequisites_var} should be empty on first entry to +# this function. On exit, ${prerequisites_var} will contain the list of +# required shared library files. +# +#  target is the full path to an executable file +# +#  prerequisites_var is the name of a CMake variable to contain the results +# +#  exclude_system is 0 or 1: 0 to include "system" prerequisites , 1 to +#   exclude them +# +#  recurse is 0 or 1: 0 for direct prerequisites only, 1 for all prerequisites +#   recursively +# +#  exepath is the path to the top level executable used for @executable_path +#   replacment on the Mac +# +#  dirs is a list of paths where libraries might be found: these paths are +#   searched first when a target without any path info is given. Then standard +#   system locations are also searched: PATH, Framework locations, /usr/lib... +# +function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs) +  set(verbose 0) +  set(eol_char "E") + +  if(NOT IS_ABSOLUTE "${target}") +    message("warning: target '${target}' is not absolute...") +  endif(NOT IS_ABSOLUTE "${target}") + +  if(NOT EXISTS "${target}") +    message("warning: target '${target}' does not exist...") +  endif(NOT EXISTS "${target}") + +  # <setup-gp_tool-vars> +  # +  # Try to choose the right tool by default. Caller can set gp_tool prior to +  # calling this function to force using a different tool. +  # +  if("${gp_tool}" STREQUAL "") +    set(gp_tool "ldd") +    if(APPLE) +      set(gp_tool "otool") +    endif(APPLE) +    if(WIN32) +      set(gp_tool "dumpbin") +    endif(WIN32) +  endif("${gp_tool}" STREQUAL "") + +  set(gp_tool_known 0) + +  if("${gp_tool}" STREQUAL "ldd") +    set(gp_cmd_args "") +    set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$") +    set(gp_regex_cmp_count 1) +    set(gp_tool_known 1) +  endif("${gp_tool}" STREQUAL "ldd") + +  if("${gp_tool}" STREQUAL "otool") +    set(gp_cmd_args "-L") +    set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$") +    set(gp_regex_cmp_count 3) +    set(gp_tool_known 1) +  endif("${gp_tool}" STREQUAL "otool") + +  if("${gp_tool}" STREQUAL "dumpbin") +    set(gp_cmd_args "/dependents") +    set(gp_regex "^    ([^ ].*[Dd][Ll][Ll])${eol_char}$") +    set(gp_regex_cmp_count 1) +    set(gp_tool_known 1) +    set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE. +  endif("${gp_tool}" STREQUAL "dumpbin") + +  if(NOT gp_tool_known) +    message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...") +    message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'") +    message(STATUS "Valid gp_tool values are dumpbin, ldd and otool.") +    return() +  endif(NOT gp_tool_known) + +  set(gp_cmd_paths ${gp_cmd_paths} +    "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin" +    "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin" +    "C:/Program Files/Microsoft Visual Studio 8/VC/BIN" +    "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN" +    "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN" +    "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN" +    "/usr/local/bin" +    "/usr/bin" +    ) + +  find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths}) + +  if(NOT gp_cmd) +    message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...") +    return() +  endif(NOT gp_cmd) + +  if("${gp_tool}" STREQUAL "dumpbin") +    # When running dumpbin, it also needs the "Common7/IDE" directory in the +    # PATH. It will already be in the PATH if being run from a Visual Studio +    # command prompt. Add it to the PATH here in case we are running from a +    # different command prompt. +    # +    get_filename_component(gp_cmd_dir "${gp_cmd}" PATH) +    get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE) +    if(EXISTS "${gp_cmd_dlls_dir}") +      # only add to the path if it is not already in the path +      if(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}") +        set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}") +      endif(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}") +    endif(EXISTS "${gp_cmd_dlls_dir}") +  endif("${gp_tool}" STREQUAL "dumpbin") +  # +  # </setup-gp_tool-vars> + +  if("${gp_tool}" STREQUAL "ldd") +    set(old_ld_env "$ENV{LD_LIBRARY_PATH}") +    foreach(dir ${exepath} ${dirs}) +      set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}") +    endforeach(dir) +  endif("${gp_tool}" STREQUAL "ldd") + + +  # Track new prerequisites at each new level of recursion. Start with an +  # empty list at each level: +  # +  set(unseen_prereqs) + +  # Run gp_cmd on the target: +  # +  execute_process( +    COMMAND ${gp_cmd} ${gp_cmd_args} ${target} +    OUTPUT_VARIABLE gp_cmd_ov +    ) + +  if("${gp_tool}" STREQUAL "ldd") +    set(ENV{LD_LIBRARY_PATH} "${old_ld_env}") +  endif("${gp_tool}" STREQUAL "ldd") + +  if(verbose) +    message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>") +    message(STATUS "gp_cmd_ov='${gp_cmd_ov}'") +    message(STATUS "</RawOutput>") +  endif(verbose) + +  get_filename_component(target_dir "${target}" PATH) + +  # Convert to a list of lines: +  # +  string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}") +  string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}") + +  # Analyze each line for file names that match the regular expression: +  # +  foreach(candidate ${candidates}) +  if("${candidate}" MATCHES "${gp_regex}") +    # Extract information from each candidate: +    string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}") + +    if(gp_regex_cmp_count GREATER 1) +      string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}") +      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}") +      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}") +      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}") +    endif(gp_regex_cmp_count GREATER 1) + +    if(gp_regex_cmp_count GREATER 2) +      string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}") +      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}") +      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}") +      string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}") +    endif(gp_regex_cmp_count GREATER 2) + +    # Use the raw_item as the list entries returned by this function. Use the +    # gp_resolve_item function to resolve it to an actual full path file if +    # necessary. +    # +    set(item "${raw_item}") + +    # Add each item unless it is excluded: +    # +    set(add_item 1) + +    if(${exclude_system}) +      set(type "") +      gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type) +      if("${type}" STREQUAL "system") +        set(add_item 0) +      endif("${type}" STREQUAL "system") +    endif(${exclude_system}) + +    if(add_item) +      list(LENGTH ${prerequisites_var} list_length_before_append) +      gp_append_unique(${prerequisites_var} "${item}") +      list(LENGTH ${prerequisites_var} list_length_after_append) + +      if(${recurse}) +        # If item was really added, this is the first time we have seen it. +        # Add it to unseen_prereqs so that we can recursively add *its* +        # prerequisites... +        # +        # But first: resolve its name to an absolute full path name such +        # that the analysis tools can simply accept it as input. +        # +        if(NOT list_length_before_append EQUAL list_length_after_append) +          gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item) +          set(unseen_prereqs ${unseen_prereqs} "${resolved_item}") +        endif(NOT list_length_before_append EQUAL list_length_after_append) +      endif(${recurse}) +    endif(add_item) +  else("${candidate}" MATCHES "${gp_regex}") +    if(verbose) +      message(STATUS "ignoring non-matching line: '${candidate}'") +    endif(verbose) +  endif("${candidate}" MATCHES "${gp_regex}") +  endforeach(candidate) + +  list(LENGTH ${prerequisites_var} prerequisites_var_length) +  if(prerequisites_var_length GREATER 0) +    list(SORT ${prerequisites_var}) +  endif(prerequisites_var_length GREATER 0) +  if(${recurse}) +    set(more_inputs ${unseen_prereqs}) +    foreach(input ${more_inputs}) +      get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}") +    endforeach(input) +  endif(${recurse}) + +  set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE) +endfunction(get_prerequisites) + + +# list_prerequisites target all exclude_system verbose +# +#  ARGV0 (target) is the full path to an executable file +# +#  optional ARGV1 (all) is 0 or 1: 0 for direct prerequisites only, +#   1 for all prerequisites recursively +# +#  optional ARGV2 (exclude_system) is 0 or 1: 0 to include "system" +#   prerequisites , 1 to exclude them +# +#  optional ARGV3 (verbose) is 0 or 1: 0 to print only full path +#   names of prerequisites, 1 to print extra information +# +function(list_prerequisites target) +  if("${ARGV1}" STREQUAL "") +    set(all 1) +  else("${ARGV1}" STREQUAL "") +    set(all "${ARGV1}") +  endif("${ARGV1}" STREQUAL "") + +  if("${ARGV2}" STREQUAL "") +    set(exclude_system 0) +  else("${ARGV2}" STREQUAL "") +    set(exclude_system "${ARGV2}") +  endif("${ARGV2}" STREQUAL "") + +  if("${ARGV3}" STREQUAL "") +    set(verbose 0) +  else("${ARGV3}" STREQUAL "") +    set(verbose "${ARGV3}") +  endif("${ARGV3}" STREQUAL "") + +  set(count 0) +  set(count_str "") +  set(print_count "${verbose}") +  set(print_prerequisite_type "${verbose}") +  set(print_target "${verbose}") +  set(type_str "") + +  get_filename_component(exepath "${target}" PATH) + +  set(prereqs "") +  get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "") + +  if(print_target) +    message(STATUS "File '${target}' depends on:") +  endif(print_target) + +  foreach(d ${prereqs}) +    math(EXPR count "${count} + 1") + +    if(print_count) +      set(count_str "${count}. ") +    endif(print_count) + +    if(print_prerequisite_type) +      gp_file_type("${target}" "${d}" type) +      set(type_str " (${type})") +    endif(print_prerequisite_type) + +    message(STATUS "${count_str}${d}${type_str}") +  endforeach(d) +endfunction(list_prerequisites) + + +# list_prerequisites_by_glob glob_arg glob_exp +# +#  glob_arg is GLOB or GLOB_RECURSE +# +#  glob_exp is a globbing expression used with "file(GLOB" to retrieve a list +#   of matching files. If a matching file is executable, its prerequisites are +#   listed. +# +# Any additional (optional) arguments provided are passed along as the +# optional arguments to the list_prerequisites calls. +# +function(list_prerequisites_by_glob glob_arg glob_exp) +  message(STATUS "=============================================================================") +  message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'") +  message(STATUS "") +  file(${glob_arg} file_list ${glob_exp}) +  foreach(f ${file_list}) +    is_file_executable("${f}" is_f_executable) +    if(is_f_executable) +      message(STATUS "=============================================================================") +      list_prerequisites("${f}" ${ARGN}) +      message(STATUS "") +    endif(is_f_executable) +  endforeach(f) +endfunction(list_prerequisites_by_glob) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 62b764bb30..05f0492234 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -1,276 +1,276 @@ -# -*- cmake -*-
 -include(LLTestCommand)
 -include(GoogleMock)
 -
 -MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
 -  # Given a project name and a list of sourcefiles (with optional properties on each),
 -  # add targets to build and run the tests specified.
 -  # ASSUMPTIONS:
 -  # * this macro is being executed in the project file that is passed in
 -  # * current working SOURCE dir is that project dir
 -  # * there is a subfolder tests/ with test code corresponding to the filenames passed in
 -  # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT)
 -  #
 -  # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
 -  #
 -  # WARNING: do NOT modify this code without working with poppy -
 -  # there is another branch that will conflict heavily with any changes here.
 -INCLUDE(GoogleMock)
 -
 -
 -  IF(LL_TEST_VERBOSE)
 -    MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
 -  ENDIF(LL_TEST_VERBOSE)
 -
 -  # Start with the header and project-wide setup before making targets
 -  #project(UNITTEST_PROJECT_${project})
 -  # Setup includes, paths, etc
 -  SET(alltest_SOURCE_FILES
 -    ${CMAKE_SOURCE_DIR}/test/test.cpp
 -    ${CMAKE_SOURCE_DIR}/test/lltut.cpp
 -    )
 -  SET(alltest_DEP_TARGETS
 -    # needed by the test harness itself
 -    ${APRUTIL_LIBRARIES}
 -    ${APR_LIBRARIES}
 -    llcommon
 -    )
 -  IF(NOT "${project}" STREQUAL "llmath")
 -    # add llmath as a dep unless the tested module *is* llmath!
 -    LIST(APPEND alltest_DEP_TARGETS
 -      llmath
 -      )
 -  ENDIF(NOT "${project}" STREQUAL "llmath")
 -  SET(alltest_INCLUDE_DIRS
 -    ${LLMATH_INCLUDE_DIRS}
 -    ${LLCOMMON_INCLUDE_DIRS}
 -    ${LIBS_OPEN_DIR}/test
 -    ${GOOGLEMOCK_INCLUDE_DIRS}
 -    )
 -  SET(alltest_LIBRARIES
 -    ${GOOGLEMOCK_LIBRARIES}
 -    ${PTHREAD_LIBRARY}
 -    ${WINDOWS_LIBRARIES}
 -    )
 -  # Headers, for convenience in targets.
 -  SET(alltest_HEADER_FILES
 -    ${CMAKE_SOURCE_DIR}/test/test.h
 -    )
 -
 -  # Use the default flags
 -  if (LINUX)
 -    SET(CMAKE_EXE_LINKER_FLAGS "")
 -  endif (LINUX)
 -
 -  # start the source test executable definitions
 -  SET(${project}_TEST_OUTPUT "")
 -  FOREACH (source ${sources})
 -    STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} )
 -    STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} )
 -    IF(LL_TEST_VERBOSE)
 -      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})")
 -    ENDIF(LL_TEST_VERBOSE)
 -
 -    #
 -    # Per-codefile additional / external source, header, and include dir property extraction
 -    #
 -    # Source
 -    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
 -    IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
 -      SET(${name}_test_additional_SOURCE_FILES "")
 -    ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
 -    SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} )
 -    IF(LL_TEST_VERBOSE)
 -      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
 -    ENDIF(LL_TEST_VERBOSE)
 -    # Headers
 -    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
 -    IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
 -      SET(${name}_test_additional_HEADER_FILES "")
 -    ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
 -    SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
 -    set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
 -    LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES})
 -    IF(LL_TEST_VERBOSE)
 -      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}")
 -    ENDIF(LL_TEST_VERBOSE)
 -    # Include dirs
 -    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
 -    IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
 -      SET(${name}_test_additional_INCLUDE_DIRS "")
 -    ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
 -    INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS )
 -    IF(LL_TEST_VERBOSE)
 -      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
 -    ENDIF(LL_TEST_VERBOSE)
 -
 -
 -    # Setup target
 -    ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
 -    SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
 -
 -    #
 -    # Per-codefile additional / external project dep and lib dep property extraction
 -    #
 -    # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19
 -    # Projects
 -    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
 -    IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
 -      SET(${name}_test_additional_PROJECTS "")
 -    ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
 -    # Libraries
 -    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
 -    IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
 -      SET(${name}_test_additional_LIBRARIES "")
 -    ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
 -    IF(LL_TEST_VERBOSE)
 -      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}")
 -      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}")
 -    ENDIF(LL_TEST_VERBOSE)
 -    # Add to project
 -    TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} )
 -    # Compile-time Definitions
 -    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS)
 -     IF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
 -       SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES COMPILE_FLAGS ${${name}_test_additional_CFLAGS} )
 -       IF(LL_TEST_VERBOSE)
 -         MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}")
 -       ENDIF(LL_TEST_VERBOSE)
 -     ENDIF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
 -     
 -    #
 -    # Setup test targets
 -    #
 -    GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION)
 -    SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt)
 -    SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
 -
 -    # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
 -    IF(LL_TEST_VERBOSE)
 -      MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd  = ${TEST_CMD}")
 -    ENDIF(LL_TEST_VERBOSE)
 -
 -    SET_TEST_PATH(LD_LIBRARY_PATH)
 -    LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD})
 -    IF(LL_TEST_VERBOSE)
 -      MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script  = ${TEST_SCRIPT_CMD}")
 -    ENDIF(LL_TEST_VERBOSE)
 -    # Add test 
 -    ADD_CUSTOM_COMMAND(
 -        OUTPUT ${TEST_OUTPUT}
 -        COMMAND ${TEST_SCRIPT_CMD}
 -        DEPENDS PROJECT_${project}_TEST_${name}
 -        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
 -        )
 -    # Why not add custom target and add POST_BUILD command?
 -    # Slightly less uncertain behavior
 -    # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19
 -    # > I did not use a post build step as I could not make it notify of a 
 -    # > failure after the first time you build and fail a test. - daveh 2009-04-20
 -    LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT})
 -  ENDFOREACH (source)
 -
 -  # Add the test runner target per-project
 -  # (replaces old _test_ok targets all over the place)
 -  ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT})
 -  ADD_DEPENDENCIES(${project} ${project}_tests)
 -ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
 -
 -FUNCTION(LL_ADD_INTEGRATION_TEST 
 -    testname
 -    additional_source_files
 -    library_dependencies
 -# variable args
 -    )
 -  if(TEST_DEBUG)
 -    message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on")
 -  endif(TEST_DEBUG)
 -  
 -  SET(source_files
 -    tests/${testname}_test.cpp
 -    ${CMAKE_SOURCE_DIR}/test/test.cpp
 -    ${CMAKE_SOURCE_DIR}/test/lltut.cpp
 -    ${additional_source_files}
 -    )
 -
 -  SET(libraries
 -    ${library_dependencies}
 -    ${GOOGLEMOCK_LIBRARIES}
 -    ${PTHREAD_LIBRARY}
 -    )
 -
 -  # Add test executable build target
 -  if(TEST_DEBUG)
 -    message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})")
 -  endif(TEST_DEBUG)
 -  ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
 -  SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
 -  if(STANDALONE)
 -    SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}")
 -  endif(STANDALONE)
 -
 -  # Add link deps to the executable
 -  if(TEST_DEBUG)
 -    message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})")
 -  endif(TEST_DEBUG)
 -  TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})
 -
 -  # Create the test running command
 -  SET(test_command ${ARGN})
 -  GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION)
 -  LIST(FIND test_command "{}" test_exe_pos)
 -  IF(test_exe_pos LESS 0)
 -    # The {} marker means "the full pathname of the test executable."
 -    # test_exe_pos -1 means we didn't find it -- so append the test executable
 -    # name to $ARGN, the variable part of the arg list. This is convenient
 -    # shorthand for both straightforward execution of the test program (empty
 -    # $ARGN) and for running a "wrapper" program of some kind accepting the
 -    # pathname of the test program as the last of its args. You need specify
 -    # {} only if the test program's pathname isn't the last argument in the
 -    # desired command line.
 -    LIST(APPEND test_command "${TEST_EXE}")
 -  ELSE (test_exe_pos LESS 0)
 -    # Found {} marker at test_exe_pos. Remove the {}...
 -    LIST(REMOVE_AT test_command test_exe_pos)
 -    # ...and replace it with the actual name of the test executable.
 -    LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
 -  ENDIF (test_exe_pos LESS 0)
 -
 -  SET_TEST_PATH(LD_LIBRARY_PATH)
 -  LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command})
 -
 -  if(TEST_DEBUG)
 -    message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}")
 -  endif(TEST_DEBUG)
 -
 -  ADD_CUSTOM_COMMAND(
 -    TARGET INTEGRATION_TEST_${testname}
 -    POST_BUILD
 -    COMMAND ${TEST_SCRIPT_CMD}
 -    )
 -
 -  # Use CTEST? Not sure how to yet...
 -  # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD})
 -
 -ENDFUNCTION(LL_ADD_INTEGRATION_TEST)
 -
 -MACRO(SET_TEST_PATH LISTVAR)
 -  IF(WINDOWS)
 -    # We typically build/package only Release variants of third-party
 -    # libraries, so append the Release staging dir in case the library being
 -    # sought doesn't have a debug variant.
 -    set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release)
 -  ELSEIF(DARWIN)
 -    # We typically build/package only Release variants of third-party
 -    # libraries, so append the Release staging dir in case the library being
 -    # sought doesn't have a debug variant.
 -    set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib)
 -  ELSE(WINDOWS)
 -    # Linux uses a single staging directory anyway.
 -    IF (STANDALONE)
 -      set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib)
 -    ELSE (STANDALONE)
 -      set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib)
 -    ENDIF (STANDALONE)
 -  ENDIF(WINDOWS)
 -ENDMACRO(SET_TEST_PATH)
 +# -*- cmake -*- +include(LLTestCommand) +include(GoogleMock) + +MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) +  # Given a project name and a list of sourcefiles (with optional properties on each), +  # add targets to build and run the tests specified. +  # ASSUMPTIONS: +  # * this macro is being executed in the project file that is passed in +  # * current working SOURCE dir is that project dir +  # * there is a subfolder tests/ with test code corresponding to the filenames passed in +  # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT) +  # +  # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code +  # +  # WARNING: do NOT modify this code without working with poppy - +  # there is another branch that will conflict heavily with any changes here. +INCLUDE(GoogleMock) + + +  IF(LL_TEST_VERBOSE) +    MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}") +  ENDIF(LL_TEST_VERBOSE) + +  # Start with the header and project-wide setup before making targets +  #project(UNITTEST_PROJECT_${project}) +  # Setup includes, paths, etc +  SET(alltest_SOURCE_FILES +    ${CMAKE_SOURCE_DIR}/test/test.cpp +    ${CMAKE_SOURCE_DIR}/test/lltut.cpp +    ) +  SET(alltest_DEP_TARGETS +    # needed by the test harness itself +    ${APRUTIL_LIBRARIES} +    ${APR_LIBRARIES} +    llcommon +    ) +  IF(NOT "${project}" STREQUAL "llmath") +    # add llmath as a dep unless the tested module *is* llmath! +    LIST(APPEND alltest_DEP_TARGETS +      llmath +      ) +  ENDIF(NOT "${project}" STREQUAL "llmath") +  SET(alltest_INCLUDE_DIRS +    ${LLMATH_INCLUDE_DIRS} +    ${LLCOMMON_INCLUDE_DIRS} +    ${LIBS_OPEN_DIR}/test +    ${GOOGLEMOCK_INCLUDE_DIRS} +    ) +  SET(alltest_LIBRARIES +    ${GOOGLEMOCK_LIBRARIES} +    ${PTHREAD_LIBRARY} +    ${WINDOWS_LIBRARIES} +    ) +  # Headers, for convenience in targets. +  SET(alltest_HEADER_FILES +    ${CMAKE_SOURCE_DIR}/test/test.h +    ) + +  # Use the default flags +  if (LINUX) +    SET(CMAKE_EXE_LINKER_FLAGS "") +  endif (LINUX) + +  # start the source test executable definitions +  SET(${project}_TEST_OUTPUT "") +  FOREACH (source ${sources}) +    STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} ) +    STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} ) +    IF(LL_TEST_VERBOSE) +      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})") +    ENDIF(LL_TEST_VERBOSE) + +    # +    # Per-codefile additional / external source, header, and include dir property extraction +    # +    # Source +    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES) +    IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND) +      SET(${name}_test_additional_SOURCE_FILES "") +    ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND) +    SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} ) +    IF(LL_TEST_VERBOSE) +      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}") +    ENDIF(LL_TEST_VERBOSE) +    # Headers +    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES) +    IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND) +      SET(${name}_test_additional_HEADER_FILES "") +    ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND) +    SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES}) +    set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) +    LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES}) +    IF(LL_TEST_VERBOSE) +      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}") +    ENDIF(LL_TEST_VERBOSE) +    # Include dirs +    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS) +    IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND) +      SET(${name}_test_additional_INCLUDE_DIRS "") +    ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND) +    INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS ) +    IF(LL_TEST_VERBOSE) +      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}") +    ENDIF(LL_TEST_VERBOSE) + + +    # Setup target +    ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES}) +    SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}") + +    # +    # Per-codefile additional / external project dep and lib dep property extraction +    # +    # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19 +    # Projects +    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS) +    IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND) +      SET(${name}_test_additional_PROJECTS "") +    ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND) +    # Libraries +    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES) +    IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND) +      SET(${name}_test_additional_LIBRARIES "") +    ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND) +    IF(LL_TEST_VERBOSE) +      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}") +      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}") +    ENDIF(LL_TEST_VERBOSE) +    # Add to project +    TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} ) +    # Compile-time Definitions +    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS) +     IF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND) +       SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES COMPILE_FLAGS ${${name}_test_additional_CFLAGS} ) +       IF(LL_TEST_VERBOSE) +         MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}") +       ENDIF(LL_TEST_VERBOSE) +     ENDIF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND) +      +    # +    # Setup test targets +    # +    GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION) +    SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt) +    SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR}) + +    # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19 +    IF(LL_TEST_VERBOSE) +      MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd  = ${TEST_CMD}") +    ENDIF(LL_TEST_VERBOSE) + +    SET_TEST_PATH(LD_LIBRARY_PATH) +    LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD}) +    IF(LL_TEST_VERBOSE) +      MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script  = ${TEST_SCRIPT_CMD}") +    ENDIF(LL_TEST_VERBOSE) +    # Add test  +    ADD_CUSTOM_COMMAND( +        OUTPUT ${TEST_OUTPUT} +        COMMAND ${TEST_SCRIPT_CMD} +        DEPENDS PROJECT_${project}_TEST_${name} +        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +        ) +    # Why not add custom target and add POST_BUILD command? +    # Slightly less uncertain behavior +    # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19 +    # > I did not use a post build step as I could not make it notify of a  +    # > failure after the first time you build and fail a test. - daveh 2009-04-20 +    LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT}) +  ENDFOREACH (source) + +  # Add the test runner target per-project +  # (replaces old _test_ok targets all over the place) +  ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT}) +  ADD_DEPENDENCIES(${project} ${project}_tests) +ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS) + +FUNCTION(LL_ADD_INTEGRATION_TEST  +    testname +    additional_source_files +    library_dependencies +# variable args +    ) +  if(TEST_DEBUG) +    message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on") +  endif(TEST_DEBUG) +   +  SET(source_files +    tests/${testname}_test.cpp +    ${CMAKE_SOURCE_DIR}/test/test.cpp +    ${CMAKE_SOURCE_DIR}/test/lltut.cpp +    ${additional_source_files} +    ) + +  SET(libraries +    ${library_dependencies} +    ${GOOGLEMOCK_LIBRARIES} +    ${PTHREAD_LIBRARY} +    ) + +  # Add test executable build target +  if(TEST_DEBUG) +    message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})") +  endif(TEST_DEBUG) +  ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files}) +  SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}") +  if(STANDALONE) +    SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}") +  endif(STANDALONE) + +  # Add link deps to the executable +  if(TEST_DEBUG) +    message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})") +  endif(TEST_DEBUG) +  TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries}) + +  # Create the test running command +  SET(test_command ${ARGN}) +  GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION) +  LIST(FIND test_command "{}" test_exe_pos) +  IF(test_exe_pos LESS 0) +    # The {} marker means "the full pathname of the test executable." +    # test_exe_pos -1 means we didn't find it -- so append the test executable +    # name to $ARGN, the variable part of the arg list. This is convenient +    # shorthand for both straightforward execution of the test program (empty +    # $ARGN) and for running a "wrapper" program of some kind accepting the +    # pathname of the test program as the last of its args. You need specify +    # {} only if the test program's pathname isn't the last argument in the +    # desired command line. +    LIST(APPEND test_command "${TEST_EXE}") +  ELSE (test_exe_pos LESS 0) +    # Found {} marker at test_exe_pos. Remove the {}... +    LIST(REMOVE_AT test_command test_exe_pos) +    # ...and replace it with the actual name of the test executable. +    LIST(INSERT test_command test_exe_pos "${TEST_EXE}") +  ENDIF (test_exe_pos LESS 0) + +  SET_TEST_PATH(LD_LIBRARY_PATH) +  LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command}) + +  if(TEST_DEBUG) +    message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}") +  endif(TEST_DEBUG) + +  ADD_CUSTOM_COMMAND( +    TARGET INTEGRATION_TEST_${testname} +    POST_BUILD +    COMMAND ${TEST_SCRIPT_CMD} +    ) + +  # Use CTEST? Not sure how to yet... +  # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD}) + +ENDFUNCTION(LL_ADD_INTEGRATION_TEST) + +MACRO(SET_TEST_PATH LISTVAR) +  IF(WINDOWS) +    # We typically build/package only Release variants of third-party +    # libraries, so append the Release staging dir in case the library being +    # sought doesn't have a debug variant. +    set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release) +  ELSEIF(DARWIN) +    # We typically build/package only Release variants of third-party +    # libraries, so append the Release staging dir in case the library being +    # sought doesn't have a debug variant. +    set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib) +  ELSE(WINDOWS) +    # Linux uses a single staging directory anyway. +    IF (STANDALONE) +      set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib) +    ELSE (STANDALONE) +      set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib) +    ENDIF (STANDALONE) +  ENDIF(WINDOWS) +ENDMACRO(SET_TEST_PATH) diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index c9cb1cd6e7..5e540ad8c5 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -97,7 +97,11 @@ void LLAudioEngine::setDefaults()  	}  	mMasterGain = 1.f; -	mInternalGain = 0.f; +	// Setting mInternalGain to an out of range value fixes the issue reported in STORM-830. +	// There is an edge case in setMasterGain during startup which prevents setInternalGain from  +	// being called if the master volume setting and mInternalGain both equal 0, so using -1 forces +	// the if statement in setMasterGain to execute when the viewer starts up. +	mInternalGain = -1.f;  	mNextWindUpdate = 0.f;  	mStreamingAudioImpl = NULL; diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 8f02391e75..c32a776c3f 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -92,6 +92,17 @@ LLFILE*	LLFile::_fsopen(const std::string& filename, const char* mode, int shari  #endif  } +int	LLFile::close(LLFILE * file) +{ +	int ret_value = 0; +	if (file) +	{ +		ret_value = fclose(file); +	} +	return ret_value; +} + +  int	LLFile::remove(const std::string& filename)  {  #if	LL_WINDOWS diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 4913af7cb5..dd7d36513a 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -71,6 +71,8 @@ public:  	static	LLFILE*	fopen(const std::string& filename,const char* accessmode);	/* Flawfinder: ignore */  	static	LLFILE*	_fsopen(const std::string& filename,const char* accessmode,int	sharingFlag); +	static	int		close(LLFILE * file); +  	// perms is a permissions mask like 0777 or 0700.  In most cases it will  	// be overridden by the user's umask.  It is ignored on Windows.  	static	int		mkdir(const std::string& filename, int perms = 0700); diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index c8acbbe591..1526e6ac3c 100644 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h @@ -103,7 +103,7 @@ public:    void				raw_digest(unsigned char *array) const;	// provide 16-byte array for binary data    void				hex_digest(char *string) const;			// provide 33-byte array for ascii-hex string -  friend std::ostream&   operator<< (std::ostream&, LLMD5 context); +  friend LL_COMMON_API std::ostream&   operator<< (std::ostream&, LLMD5 context);  private: diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 356e0f4c0f..7d5afe92dc 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -28,7 +28,7 @@  #define LL_LLVERSIONVIEWER_H  const S32 LL_VERSION_MAJOR = 2; -const S32 LL_VERSION_MINOR = 5; +const S32 LL_VERSION_MINOR = 6;  const S32 LL_VERSION_PATCH = 0;  const S32 LL_VERSION_BUILD = 0; diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp index b46a6e03d2..3e2c05a6e6 100644 --- a/indra/llmath/llbbox.cpp +++ b/indra/llmath/llbbox.cpp @@ -89,6 +89,19 @@ void LLBBox::addBBoxAgent(const LLBBox& b)  	}  } +LLBBox LLBBox::getAxisAligned() const +{ +	// no rotation = axis aligned rotation +	LLBBox aligned(mPosAgent, LLQuaternion(), LLVector3(), LLVector3()); + +	// add the center point so that it's not empty +	aligned.addPointAgent(mPosAgent); + +	// add our BBox +	aligned.addBBoxAgent(*this); + +	return aligned; +}  void LLBBox::expand( F32 delta )  { @@ -147,6 +160,15 @@ BOOL LLBBox::containsPointAgent(const LLVector3& p) const  	return containsPointLocal(point_local);  } +LLVector3 LLBBox::getMinAgent() const +{ +	return localToAgent(mMinLocal); +} + +LLVector3 LLBBox::getMaxAgent() const +{ +	return localToAgent(mMaxLocal); +}  /*  LLBBox operator*(const LLBBox &a, const LLMatrix4 &b) diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h index 5b911793f0..28e69b75e1 100644 --- a/indra/llmath/llbbox.h +++ b/indra/llmath/llbbox.h @@ -51,9 +51,11 @@ public:  	const LLVector3&	getPositionAgent() const			{ return mPosAgent; }  	const LLQuaternion&	getRotation() const					{ return mRotation; } +	LLVector3           getMinAgent() const;  	const LLVector3&	getMinLocal() const					{ return mMinLocal; }  	void				setMinLocal( const LLVector3& min )	{ mMinLocal = min; } +	LLVector3           getMaxAgent() const;  	const LLVector3&	getMaxLocal() const					{ return mMaxLocal; }  	void				setMaxLocal( const LLVector3& max )	{ mMaxLocal = max; } @@ -80,6 +82,8 @@ public:  	LLVector3			localToAgentBasis(const LLVector3& v) const;  	LLVector3			agentToLocalBasis(const LLVector3& v) const; +	// Get the smallest possible axis aligned bbox that contains this bbox +	LLBBox              getAxisAligned() const;  //	friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b); diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index b9b974ec4f..7b796a0fa8 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -42,9 +42,6 @@ const U32 REGION_FLAGS_RESET_HOME_ON_TELEPORT	= (1 << 3);  // Does the sun move?  const U32 REGION_FLAGS_SUN_FIXED				= (1 << 4); -// Tax free zone (no taxes on objects, land, etc.) -const U32 REGION_FLAGS_TAX_FREE					= (1 << 5); -  // Can't change the terrain heightfield, even on owned parcels,  // but can plant trees and grass.  const U32 REGION_FLAGS_BLOCK_TERRAFORM			= (1 << 6); @@ -54,17 +51,12 @@ const U32 REGION_FLAGS_BLOCK_LAND_RESELL		= (1 << 7);  // All content wiped once per night  const U32 REGION_FLAGS_SANDBOX					= (1 << 8); -const U32 REGION_FLAGS_NULL_LAYER				= (1 << 9); -// const U32 REGION_FLAGS_SKIP_AGENT_ACTION		= (1 << 10); -const U32 REGION_FLAGS_HARD_ALLOW_LAND_TRANSFER	= (1 << 10);	// Region allows land reselling -// const U32 REGION_FLAGS_SKIP_UPDATE_INTEREST_LIST= (1 << 11); -const U32 REGION_FLAGS_HARD_ALLOW_POST_CLASSIFIED	= (1 << 11);	// Region allows posting of classified ads  const U32 REGION_FLAGS_SKIP_COLLISIONS			= (1 << 12); // Pin all non agent rigid bodies  const U32 REGION_FLAGS_SKIP_SCRIPTS				= (1 << 13);  const U32 REGION_FLAGS_SKIP_PHYSICS				= (1 << 14); // Skip all physics  const U32 REGION_FLAGS_EXTERNALLY_VISIBLE		= (1 << 15); -//const U32 REGION_FLAGS_MAINLAND_VISIBLE			= (1 << 16); -const U32 REGION_FLAGS_PUBLIC_ALLOWED			= (1 << 17); +const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16); +const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17);  const U32 REGION_FLAGS_BLOCK_DWELL				= (1 << 18);  // Is flight allowed? @@ -81,18 +73,13 @@ const U32 REGION_FLAGS_ESTATE_SKIP_SCRIPTS		= (1 << 21);  const U32 REGION_FLAGS_RESTRICT_PUSHOBJECT		= (1 << 22);  const U32 REGION_FLAGS_DENY_ANONYMOUS			= (1 << 23); -// const U32 REGION_FLAGS_DENY_IDENTIFIED			= (1 << 24); -// const U32 REGION_FLAGS_DENY_TRANSACTED			= (1 << 25);  const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES		= (1 << 26); -// const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); // We no longer support ELAR -  const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28);  const U32 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29);  const U32 REGION_FLAGS_DENY_AGEUNVERIFIED	= (1 << 30); -const U32 REGION_FLAGS_SKIP_MONO_SCRIPTS	= (1 << 31);  const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK |  								 REGION_FLAGS_ALLOW_SET_HOME | @@ -105,7 +92,6 @@ const U32 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK  									   | REGION_FLAGS_ALLOW_SET_HOME;  const U32 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE -									 | REGION_FLAGS_PUBLIC_ALLOWED	  									 | REGION_FLAGS_SUN_FIXED  									 | REGION_FLAGS_DENY_ANONYMOUS  									 | REGION_FLAGS_DENY_AGEUNVERIFIED; diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 6b06040b8a..8b6a73af56 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -94,6 +94,7 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p)  	mMaxChars(p.max_chars),  	mPrearrangeCallback(p.prearrange_callback()),  	mTextEntryCallback(p.text_entry_callback()), +	mTextChangedCallback(p.text_changed_callback()),  	mListPosition(p.list_position),  	mLastSelectedIndex(-1),  	mLabel(p.label) @@ -834,6 +835,10 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor)  			mList->deselectAllItems();  			mLastSelectedIndex = -1;  		} +		if (mTextChangedCallback != NULL) +		{ +			(mTextChangedCallback)(line_editor, LLSD()); +		}  		return;  	} @@ -878,6 +883,10 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor)  		// RN: presumably text entry  		updateSelection();  	} +	if (mTextChangedCallback != NULL) +	{ +		(mTextChangedCallback)(line_editor, LLSD()); +	}  }  void LLComboBox::updateSelection() diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 5f0e4a6843..74d64269bd 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -73,7 +73,8 @@ public:  											allow_new_values;  		Optional<S32>						max_chars;  		Optional<commit_callback_t> 		prearrange_callback, -											text_entry_callback; +											text_entry_callback, +											text_changed_callback;  		Optional<EPreferredPosition, PreferredPositionValues>	list_position; @@ -190,6 +191,7 @@ public:  	void			setPrearrangeCallback( commit_callback_t cb ) { mPrearrangeCallback = cb; }  	void			setTextEntryCallback( commit_callback_t cb ) { mTextEntryCallback = cb; } +	void			setTextChangedCallback( commit_callback_t cb ) { mTextChangedCallback = cb; }  	void			setButtonVisible(BOOL visible); @@ -220,6 +222,7 @@ private:  	BOOL				mTextEntryTentative;  	commit_callback_t	mPrearrangeCallback;  	commit_callback_t	mTextEntryCallback; +	commit_callback_t	mTextChangedCallback;  	commit_callback_t	mSelectionCallback;  	boost::signals2::connection mTopLostSignalConnection;  	S32                 mLastSelectedIndex; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index d30697e178..c425782715 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -272,9 +272,6 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)  	initFromParams(p); -	// chrome floaters don't take focus at all -	setFocusRoot(!getIsChrome()); -  	initFloater(p);  } @@ -2910,8 +2907,6 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str  	params.from_xui = true;  	applyXUILayout(params, parent);   	initFromParams(params); -	// chrome floaters don't take focus at all -	setFocusRoot(!getIsChrome());  	initFloater(params); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 6c0d47ef63..32d7be377a 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1637,6 +1637,10 @@ LLMenuScrollItem::LLMenuScrollItem(const Params& p)  	}  	LLButton::Params bparams; + +	// Disabled the Return key handling by LLMenuScrollItem instead of +	// passing the key press to the currently selected menu item. See STORM-385. +	bparams.commit_on_return(false);  	bparams.mouse_opaque(true);  	bparams.scale_image(false);  	bparams.click_callback(p.scroll_callback); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 4f7b4be526..9db1feafd1 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -36,6 +36,7 @@  #include "llcachename.h"  #include "lltrans.h"  #include "lluicolortable.h" +#include "message.h"  #define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))" @@ -684,8 +685,8 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa  LLStyle::Params LLUrlEntryGroup::getStyle() const  {  	LLStyle::Params style_params = LLUrlEntryBase::getStyle(); -	style_params.color = LLUIColorTable::instance().getColor("GroupLinkColor"); -	style_params.readonly_color = LLUIColorTable::instance().getColor("GroupLinkColor"); +	style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); +	style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");  	return style_params;  } @@ -740,6 +741,13 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const  	return LLUrlEntryBase::getLocation(url);  } +// LLUrlEntryParcel statics. +LLUUID	LLUrlEntryParcel::sAgentID(LLUUID::null); +LLUUID	LLUrlEntryParcel::sSessionID(LLUUID::null); +LLHost	LLUrlEntryParcel::sRegionHost(LLHost::invalid); +bool	LLUrlEntryParcel::sDisconnected(false); +std::set<LLUrlEntryParcel*> LLUrlEntryParcel::sParcelInfoObservers; +  ///  /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,  /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about @@ -751,13 +759,88 @@ LLUrlEntryParcel::LLUrlEntryParcel()  							boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_parcel.xml";  	mTooltip = LLTrans::getString("TooltipParcelUrl"); + +	sParcelInfoObservers.insert(this); +} + +LLUrlEntryParcel::~LLUrlEntryParcel() +{ +	sParcelInfoObservers.erase(this);  }  std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)  { +	LLSD path_array = LLURI(url).pathArray(); +	S32 path_parts = path_array.size(); + +	if (path_parts < 3) // no parcel id +	{ +		llwarns << "Failed to parse url [" << url << "]" << llendl; +		return url; +	} + +	std::string parcel_id_string = unescapeUrl(path_array[2]); // parcel id + +	// Add an observer to call LLUrlLabelCallback when we have parcel name. +	addObserver(parcel_id_string, url, cb); + +	LLUUID parcel_id(parcel_id_string); + +	sendParcelInfoRequest(parcel_id); +  	return unescapeUrl(url);  } +void LLUrlEntryParcel::sendParcelInfoRequest(const LLUUID& parcel_id) +{ +	if (sRegionHost == LLHost::invalid || sDisconnected) return; + +	LLMessageSystem *msg = gMessageSystem; +	msg->newMessage("ParcelInfoRequest"); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, sAgentID ); +	msg->addUUID("SessionID", sSessionID); +	msg->nextBlock("Data"); +	msg->addUUID("ParcelID", parcel_id); +	msg->sendReliable(sRegionHost); +} + +void LLUrlEntryParcel::onParcelInfoReceived(const std::string &id, const std::string &label) +{ +	callObservers(id, label.empty() ? LLTrans::getString("RegionInfoError") : label, mIcon); +} + +// static +void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data) +{ +	std::string label(LLStringUtil::null); +	if (!parcel_data.name.empty()) +	{ +		label = parcel_data.name; +	} +	// If parcel name is empty use Sim_name (x, y, z) for parcel label. +	else if (!parcel_data.sim_name.empty()) +	{ +		S32 region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS; +		S32 region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS; +		S32 region_z = llround(parcel_data.global_z); + +		label = llformat("%s (%d, %d, %d)", +				parcel_data.sim_name.c_str(), region_x, region_y, region_z); +	} + +	for (std::set<LLUrlEntryParcel*>::iterator iter = sParcelInfoObservers.begin(); +			iter != sParcelInfoObservers.end(); +			++iter) +	{ +		LLUrlEntryParcel* url_entry = *iter; +		if (url_entry) +		{ +			url_entry->onParcelInfoReceived(parcel_data.parcel_id.asString(), label); +		} +	} +} +  //  // LLUrlEntryPlace Describes secondlife://<location> URLs  // diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 1791739061..5f82721c0f 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -31,6 +31,9 @@  #include "lluuid.h"  #include "lluicolor.h"  #include "llstyle.h" + +#include "llhost.h" // for resolving parcel name by parcel id +  #include <boost/signals2.hpp>  #include <boost/regex.hpp>  #include <string> @@ -285,8 +288,44 @@ private:  class LLUrlEntryParcel : public LLUrlEntryBase  {  public: +	struct LLParcelData +	{ +		LLUUID		parcel_id; +		std::string	name; +		std::string	sim_name; +		F32			global_x; +		F32			global_y; +		F32			global_z; +	}; +  	LLUrlEntryParcel(); +	~LLUrlEntryParcel();  	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + +	// Sends a parcel info request to sim. +	void sendParcelInfoRequest(const LLUUID& parcel_id); + +	// Calls observers of certain parcel id providing them with parcel label. +	void onParcelInfoReceived(const std::string &id, const std::string &label); + +	// Processes parcel label and triggers notifying observers. +	static void processParcelInfo(const LLParcelData& parcel_data); + +	// Next 4 setters are used to update agent and viewer connection information +	// upon events like user login, viewer disconnect and user changing region host. +	// These setters are made public to be accessible from newview and should not be +	// used in other cases. +	static void setAgentID(const LLUUID& id) { sAgentID = id; } +	static void setSessionID(const LLUUID& id) { sSessionID = id; } +	static void setRegionHost(const LLHost& host) { sRegionHost = host; } +	static void setDisconnected(bool disconnected) { sDisconnected = disconnected; } + +private: +	static LLUUID						sAgentID; +	static LLUUID						sSessionID; +	static LLHost						sRegionHost; +	static bool							sDisconnected; +	static std::set<LLUrlEntryParcel*>	sParcelInfoObservers;  };  /// diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index f30704cb22..96ebe83826 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -30,6 +30,7 @@  #include "llavatarnamecache.h"  #include "llcachename.h"  #include "lluuid.h" +#include "message.h"  #include <string> @@ -191,3 +192,20 @@ LLFontGL* LLFontGL::getFontDefault()  {  	return NULL;   } + +char* _PREHASH_AgentData = "AgentData"; +char* _PREHASH_AgentID = "AgentID"; + +LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS); + +LLMessageSystem* gMessageSystem = NULL; + +// +// Stub implementation for LLMessageSystem +// +void LLMessageSystem::newMessage(const char *name) { } +void LLMessageSystem::nextBlockFast(const char *blockname) { } +void LLMessageSystem::nextBlock(const char *blockname) { } +void LLMessageSystem::addUUIDFast( const char *varname, const LLUUID& uuid) { } +void LLMessageSystem::addUUID( const char *varname, const LLUUID& uuid) { } +S32 LLMessageSystem::sendReliable(const LLHost &host) { return 0; } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8ea0dd1089..437be15150 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -542,6 +542,7 @@ set(viewer_SOURCE_FILES      llviewerregion.cpp      llviewershadermgr.cpp      llviewerstats.cpp +    llviewerstatsrecorder.cpp      llviewertexteditor.cpp      llviewertexture.cpp      llviewertextureanim.cpp @@ -1081,6 +1082,7 @@ set(viewer_HEADER_FILES      llviewerregion.h      llviewershadermgr.h      llviewerstats.h +    llviewerstatsrecorder.h      llviewertexteditor.h      llviewertexture.h      llviewertextureanim.h diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 705c73cbf7..8efec1cff0 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -160,6 +160,17 @@          <key>Value</key>              <integer>0</integer>          </map> +      <key>ShowFavoritesOnLogin</key> +        <map> +        <key>Comment</key> +             <string>Determines whether favorites of last logged in user will be saved on exit from viewer and shown on login screen</string> +        <key>Persist</key> +             <integer>1</integer> +        <key>Type</key> +             <string>Boolean</string> +        <key>Value</key> +             <integer>0</integer> +        </map>      <!-- End of back compatibility settings -->      </map>  </llsd> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3e0b4f9998..de7073be24 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -64,6 +64,7 @@  #include "lltool.h"  #include "lltoolmgr.h"  #include "lltrans.h" +#include "llurlentry.h"  #include "llviewercontrol.h"  #include "llviewerdisplay.h"  #include "llviewerjoystick.h" @@ -649,6 +650,10 @@ void LLAgent::setRegion(LLViewerRegion *regionp)  	}  	mRegionp = regionp; +	// Pass the region host to LLUrlEntryParcel to resolve parcel name +	// with a server request. +	LLUrlEntryParcel::setRegionHost(getRegionHost()); +  	// Must shift hole-covering water object locations because local  	// coordinate frame changed.  	LLWorld::getInstance()->updateWaterObjects(); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 0e080e713b..c45be8b05e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1300,8 +1300,16 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)  		return false;  	} -	// Check whether the outfit contains the full set of body parts (shape+skin+hair+eyes). -	return getCanMakeFolderIntoOutfit(outfit_cat_id); +	// Check whether the outfit contains any wearables we aren't wearing already (STORM-702). +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); +	gInventory.collectDescendentsIf(outfit_cat_id, +		cats, +		items, +		LLInventoryModel::EXCLUDE_TRASH, +		is_worn); +	return items.size() > 0;  }  void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0093279859..7e8c68632d 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -44,6 +44,7 @@  #include "llagentwearables.h"  #include "llwindow.h"  #include "llviewerstats.h" +#include "llviewerstatsrecorder.h"  #include "llmd5.h"  #include "llmeshrepository.h"  #include "llpumpio.h" @@ -96,6 +97,7 @@  #include "llmemory.h"  #include "llprimitive.h"  #include "llurlaction.h" +#include "llurlentry.h"  #include "llvfile.h"  #include "llvfsthread.h"  #include "llvolumemgr.h" @@ -670,6 +672,10 @@ bool LLAppViewer::init()      mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); +#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::initClass(); +#endif +      // *NOTE:Mani - LLCurl::initClass is not thread safe.       // Called before threads are created.      LLCurl::initClass(); @@ -993,6 +999,8 @@ bool LLAppViewer::init()  	LLAgentLanguage::init(); + +  	return true;  } @@ -1734,6 +1742,10 @@ bool LLAppViewer::cleanup()  	LLMetricPerformanceTesterBasic::cleanClass() ; +#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::cleanupClass(); +#endif +  	llinfos << "Cleaning up Media and Textures" << llendflush;  	//Note: @@ -4610,6 +4622,10 @@ void LLAppViewer::disconnectViewer()  	cleanup_xfer_manager();  	gDisconnected = TRUE; + +	// Pass the connection state to LLUrlEntryParcel not to attempt +	// parcel info requests while disconnected. +	LLUrlEntryParcel::setDisconnected(gDisconnected);  }  void LLAppViewer::forceErrorLLError() diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 375ab82f50..c08771c5e7 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -228,6 +228,7 @@ void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason)  			break;  	}  	LLUploadDialog::modalUploadFinished(); +	LLFilePicker::instance().reset();  // unlock file picker when bulk upload fails  }  //virtual  diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 0c0fdd5572..0b17d64eb0 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -607,6 +607,15 @@ void LLFavoritesBarCtrl::changed(U32 mask)  	}	  	else  	{ +		LLInventoryModel::item_array_t items; +		LLInventoryModel::cat_array_t cats; +		LLIsType is_type(LLAssetType::AT_LANDMARK); +		gInventory.collectDescendentsIf(mFavoriteFolderId, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); +		 +		for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) +		{ +			(*i)->getSLURL(); +		}  		updateButtons();  	}  } diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index c0b5b7cfa6..cc2a8c8aac 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -291,7 +291,7 @@ BOOL LLFloaterModelPreview::postBuild()  	childSetCommitCallback("lod_mode", onLODParamCommit, this);  	childSetCommitCallback("lod_error_threshold", onLODParamCommit, this); -	childSetCommitCallback("lod_triangle_limit", onLODParamCommit, this); +	childSetCommitCallback("lod_triangle_limit", onLODParamCommitTriangleLimit, this);  	childSetCommitCallback("build_operator", onLODParamCommit, this);  	childSetCommitCallback("queue_mode", onLODParamCommit, this);  	childSetCommitCallback("border_mode", onLODParamCommit, this); @@ -340,6 +340,7 @@ BOOL LLFloaterModelPreview::postBuild()  	mModelPreview = new LLModelPreview(512, 512, this);  	mModelPreview->setPreviewTarget(16.f); +	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));  	//set callbacks for left click on line editor rows  	for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) @@ -379,7 +380,8 @@ LLFloaterModelPreview::~LLFloaterModelPreview()  {  	sInstance = NULL; -	if ( mModelPreview->mModelLoader->mResetJoints ) +	const LLModelLoader *model_loader = mModelPreview->mModelLoader; +	if (model_loader && model_loader->mResetJoints)  	{  		gAgentAvatarp->resetJointPositions();  	} @@ -531,9 +533,14 @@ void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata)  void LLFloaterModelPreview::onLODParamCommit(LLUICtrl* ctrl, void* userdata)  {  	LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; -	fp->mModelPreview->genLODs(fp->mModelPreview->mPreviewLOD); -	fp->mModelPreview->updateStatusMessages(); -	fp->mModelPreview->refresh(); +	fp->mModelPreview->onLODParamCommit(false); +} + +//static +void LLFloaterModelPreview::onLODParamCommitTriangleLimit(LLUICtrl* ctrl, void* userdata) +{ +	LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; +	fp->mModelPreview->onLODParamCommit(true);  } @@ -1664,6 +1671,8 @@ void LLModelLoader::run()  			setLoadState( ERROR_PARSING );  			return;  		} +		setLoadState( DONE ); +  		processElement(scene);  		doOnIdleOneTime(boost::bind(&LLModelPreview::loadModelCallback,mPreview,mLod)); @@ -1789,7 +1798,25 @@ void LLModelLoader::processJointNode( domNode* pNode, std::map<std::string,LLMat  		daeElement* pTranslateElement = getChildFromElement( pNode, "translate" );  		if ( !pTranslateElement || pTranslateElement->typeID() != domTranslate::ID() )  		{ -			llwarns<< "The found element is not a translate node" <<llendl; +			//llwarns<< "The found element is not a translate node" <<llendl; +			daeSIDResolver jointResolver( pNode, "./matrix" ); +			domMatrix* pMatrix = daeSafeCast<domMatrix>( jointResolver.getElement() ); +			if ( pMatrix ) +			{ +				//llinfos<<"A matrix SID was however found!"<<llendl; +				domFloat4x4 domArray = pMatrix->getValue();									 +				for ( int i = 0; i < 4; i++ ) +				{ +					for( int j = 0; j < 4; j++ ) +					{ +						workingTransform.mMatrix[i][j] = domArray[i + j*4]; +					} +				} +			} +			else +			{ +				llwarns<< "The found element is not translate or matrix node - most likely a corrupt export!" <<llendl; +			}  		}  		else  		{ @@ -2245,18 +2272,24 @@ U32 LLModelPreview::calcResourceCost()  	//mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[HULLS]", llformat("%d",num_hulls));  	//mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[POINTS]", llformat("%d",num_points)); -	mFMP->childSetTextArg("streaming cost", "[COST]", llformat("%.3f", streaming_cost)); -	mFMP->childSetTextArg("physics cost", "[COST]", llformat("%.3f", physics_cost));	  	F32 scale = mFMP->childGetValue("import_scale").asReal()*2.f; -	mFMP->childSetTextArg("import_dimensions", "[X]", llformat("%.3f", mPreviewScale[0]*scale)); -	mFMP->childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", mPreviewScale[1]*scale)); -	mFMP->childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", mPreviewScale[2]*scale)); + +	mDetailsSignal(mPreviewScale[0]*scale, mPreviewScale[1]*scale, mPreviewScale[2]*scale, streaming_cost, physics_cost);  	updateStatusMessages();  	return cost;  } +void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost) +{ +	childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x)); +	childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y)); +	childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z)); +	childSetTextArg("streaming cost", "[COST]", llformat("%.3f", streaming_cost)); +	childSetTextArg("physics cost", "[COST]", llformat("%.3f", physics_cost));	 +} +  void LLModelPreview::rebuildUploadData()  {  	assert_main_thread(); @@ -2373,11 +2406,9 @@ void LLModelPreview::loadModel(std::string filename, S32 lod)  	LLMutexLock lock(this); -	if (mModelLoader) -	{ -		delete mModelLoader; -		mModelLoader = NULL; -	} +	// This triggers if you bring up the file picker and then hit CANCEL. +	// Just use the previous model (if any) and ignore that you brought up +	// the file picker.  	if (filename.empty())  	{ @@ -2386,12 +2417,17 @@ void LLModelPreview::loadModel(std::string filename, S32 lod)  			// this is the initial file picking. Close the whole floater  			// if we don't have a base model to show for high LOD.  			mFMP->closeFloater(false); +			mLoading = false;  		} - -		mLoading = false;  		return;  	} +	if (mModelLoader) +	{ +		delete mModelLoader; +		mModelLoader = NULL; +	} +  	mLODFile[lod] = filename;  	if (lod == LLModel::LOD_HIGH) @@ -2530,6 +2566,8 @@ void LLModelPreview::loadModelCallback(S32 lod)  	mLoading = false;  	refresh(); + +	mModelLoadedSignal();  }  void LLModelPreview::resetPreviewTarget() @@ -2795,22 +2833,7 @@ void LLModelPreview::clearMaterials()  	refresh();  } -bool LLModelPreview::containsRiggedAsset( void ) -{ -	//loop through the models and determine if any of them contained a rigged asset, and if so -	//return true. -	//This is used to cleanup the joint positions after a preview. -	for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) -	{ -		LLModel* pModel = *iter; -		if ( pModel->mAlternateBindMatrix.size() > 0 ) -		{ -			return true; -		} -	} -	return false; -} -void LLModelPreview::genLODs(S32 which_lod, U32 decimation) +void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)  {  	if (mBaseModel.empty())  	{ @@ -3041,7 +3064,17 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation)  		}  		else  		{ -			triangle_count = limit; +			if (enforce_tri_limit) +			{ +				triangle_count = limit; +			} +			else +			{ +				for (S32 j=LLModel::LOD_HIGH; j>which_lod; --j) +				{ +					triangle_count /= decimation; +				} +			}  		}  		mModel[lod].clear(); @@ -4307,6 +4340,13 @@ void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture  	preview->refresh();  } +void LLModelPreview::onLODParamCommit(bool enforce_tri_limit) +{ +	genLODs(mPreviewLOD, 3, enforce_tri_limit); +	updateStatusMessages(); +	refresh(); +} +  LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LLModel* mdl)  {  	mStage = stage; diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 04e5b9591c..8fc85cebb9 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -152,6 +152,8 @@ public:  	static void onMouseCaptureLostModelPreview(LLMouseHandler*);  	static void setUploadAmount(S32 amount) { sUploadAmount = amount; } + +	void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost);  	static void onBrowseLOD(void* data); @@ -187,6 +189,7 @@ protected:  	static void		onAutoFillCommit(LLUICtrl*,void*);  	static void		onLODParamCommit(LLUICtrl*,void*); +	static void		onLODParamCommitTriangleLimit(LLUICtrl*,void*);  	static void		onExplodeCommit(LLUICtrl*, void*); @@ -232,6 +235,7 @@ protected:  	LLMenuButton* mViewOptionMenuButton;  	LLToggleableMenu* mViewOptionMenu;  	LLMutex* mStatusLock; +  };  class LLMeshFilePicker : public LLFilePickerThread @@ -247,10 +251,12 @@ private:  class LLModelPreview : public LLViewerDynamicTexture, public LLMutex -{ - public: -	 -	 LLModelPreview(S32 width, S32 height, LLFloater* fmp); +{	 +	typedef boost::signals2::signal<void (F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)> details_signal_t; +	typedef boost::signals2::signal<void (void)> model_loaded_signal_t; + +public: +	LLModelPreview(S32 width, S32 height, LLFloater* fmp);  	virtual ~LLModelPreview();  	void resetPreviewTarget(); @@ -271,7 +277,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex  	void clearModel(S32 lod);  	void loadModel(std::string filename, S32 lod);  	void loadModelCallback(S32 lod); -	void genLODs(S32 which_lod = -1, U32 decimation = 3); +	void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);  	void generateNormals();  	void consolidate();  	void clearMaterials(); @@ -279,12 +285,14 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex  	void rebuildUploadData();  	void clearIncompatible(S32 lod);  	void updateStatusMessages(); -	bool containsRiggedAsset( void );  	void clearGLODGroup(); - +	void onLODParamCommit(bool enforce_tri_limit);  	static void	textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); - +	 +	boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){  return mDetailsSignal.connect(cb);  } +	boost::signals2::connection setModelLoadedCallback( const model_loaded_signal_t::slot_type& cb ){  return mModelLoadedSignal.connect(cb);  } +	   protected:  	friend class LLFloaterModelPreview;  	friend class LLFloaterModelWizard; @@ -336,6 +344,9 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex  	//map of vertex buffers to models (one vertex buffer in vector per face in model  	std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1]; + +	details_signal_t mDetailsSignal; +	model_loaded_signal_t mModelLoadedSignal;  }; diff --git a/indra/newview/llfloatermodelwizard.cpp b/indra/newview/llfloatermodelwizard.cpp index fe53eafa40..095499e6b0 100644 --- a/indra/newview/llfloatermodelwizard.cpp +++ b/indra/newview/llfloatermodelwizard.cpp @@ -30,6 +30,7 @@  #include "llbutton.h"  #include "lldrawable.h" +#include "llcheckboxctrl.h"  #include "llcombobox.h"  #include "llfloater.h"  #include "llfloatermodelwizard.h" @@ -51,7 +52,14 @@ static	const std::string stateNames[]={  LLFloaterModelWizard::LLFloaterModelWizard(const LLSD& key)  	: LLFloater(key)  { +	mLastEnabledState = CHOOSE_FILE;  	sInstance = this; + +	mCommitCallbackRegistrar.add("Wizard.Choose", boost::bind(&LLFloaterModelWizard::setState, this, CHOOSE_FILE)); +	mCommitCallbackRegistrar.add("Wizard.Optimize", boost::bind(&LLFloaterModelWizard::setState, this, OPTIMIZE)); +	mCommitCallbackRegistrar.add("Wizard.Physics", boost::bind(&LLFloaterModelWizard::setState, this, PHYSICS)); +	mCommitCallbackRegistrar.add("Wizard.Review", boost::bind(&LLFloaterModelWizard::setState, this, REVIEW)); +	mCommitCallbackRegistrar.add("Wizard.Upload", boost::bind(&LLFloaterModelWizard::setState, this, UPLOAD));  }  LLFloaterModelWizard::~LLFloaterModelWizard()  { @@ -59,67 +67,115 @@ LLFloaterModelWizard::~LLFloaterModelWizard()  }  void LLFloaterModelWizard::setState(int state)  { +  	mState = state; -	setButtons(state);  	for(size_t t=0; t<LL_ARRAY_SIZE(stateNames); ++t)  	{ -		LLView *view = getChild<LLView>(stateNames[t]+"_panel"); +		LLView *view = getChildView(stateNames[t]+"_panel");  		if (view)   		{  			view->setVisible(state == (int) t ? TRUE : FALSE);  		}  	} +	if (state == CHOOSE_FILE) +	{ +		mModelPreview->mViewOption["show_physics"] = false; + +		getChildView("close")->setVisible(false); +		getChildView("back")->setVisible(true); +		getChildView("back")->setEnabled(false); +		getChildView("next")->setVisible(true); +		getChildView("upload")->setVisible(false); +		getChildView("cancel")->setVisible(true); +	} +  	if (state == OPTIMIZE)  	{ -		mModelPreview->genLODs(-1); +		if (mLastEnabledState < state) +		{			 +			mModelPreview->genLODs(-1); +		} +  		mModelPreview->mViewOption["show_physics"] = false; + +		getChildView("back")->setVisible(true); +		getChildView("back")->setEnabled(true); +		getChildView("close")->setVisible(false); +		getChildView("next")->setVisible(true); +		getChildView("upload")->setVisible(false); +		getChildView("cancel")->setVisible(true);  	}  	if (state == PHYSICS)  	{ -		mModelPreview->setPhysicsFromLOD(1); +		if (mLastEnabledState < state) +		{ +			mModelPreview->setPhysicsFromLOD(1); +		} +  		mModelPreview->mViewOption["show_physics"] = true; -		getChild<LLView>("next")->setVisible(true); -		getChild<LLView>("upload")->setVisible(false); +		getChildView("next")->setVisible(true); +		getChildView("upload")->setVisible(false); +		getChildView("close")->setVisible(false); +		getChildView("back")->setVisible(true); +		getChildView("back")->setEnabled(true); +		getChildView("cancel")->setVisible(true);  	}  	if (state == REVIEW)  	{ -		executePhysicsStage("Decompose"); -		getChild<LLView>("close")->setVisible(false); -		getChild<LLView>("next")->setVisible(false); -		getChild<LLView>("back")->setVisible(true); -		getChild<LLView>("upload")->setVisible(true); -		getChild<LLView>("cancel")->setVisible(true); +		if (mLastEnabledState < state) +		{ +			executePhysicsStage("Decompose"); +		} +		 +		mModelPreview->mViewOption["show_physics"] = true; + +		getChildView("close")->setVisible(false); +		getChildView("next")->setVisible(false); +		getChildView("back")->setVisible(true); +		getChildView("back")->setEnabled(true); +		getChildView("upload")->setVisible(true); +		getChildView("cancel")->setVisible(true);  	}  	if (state == UPLOAD)  	{ -		getChild<LLView>("close")->setVisible(true); -		getChild<LLView>("back")->setVisible(false); -		getChild<LLView>("upload")->setVisible(false); -		getChild<LLView>("cancel")->setVisible(false); +		getChildView("close")->setVisible(true); +		getChildView("next")->setVisible(false); +		getChildView("back")->setVisible(false); +		getChildView("upload")->setVisible(false); +		getChildView("cancel")->setVisible(false);  	} + +	updateButtons();  } -void LLFloaterModelWizard::setButtons(int state) + + +void LLFloaterModelWizard::updateButtons()  { +	if (mLastEnabledState < mState) +	{ +		mLastEnabledState = mState; +	} +  	for(size_t i=0; i<LL_ARRAY_SIZE(stateNames); ++i)  	{  		LLButton *button = getChild<LLButton>(stateNames[i]+"_btn"); -		if (i < state) +		if (i == mState)  		{  			button->setEnabled(TRUE); -			button->setToggleState(FALSE); +			button->setToggleState(TRUE);  		} -		else if (i == state) +		else if (i <= mLastEnabledState)  		{  			button->setEnabled(TRUE); -			button->setToggleState(TRUE); +			button->setToggleState(FALSE);  		}  		else  		{ @@ -418,11 +474,12 @@ void LLFloaterModelWizard::DecompRequest::completed()  BOOL LLFloaterModelWizard::postBuild()  { -	LLView* preview_panel = getChild<LLView>("preview_panel"); +	LLView* preview_panel = getChildView("preview_panel");  	childSetValue("import_scale", (F32) 0.67335826);  	getChild<LLUICtrl>("browse")->setCommitCallback(boost::bind(&LLFloaterModelWizard::loadModel, this)); +	//getChild<LLUICtrl>("lod_file")->setCommitCallback(boost::bind(&LLFloaterModelWizard::loadModel, this));  	getChild<LLUICtrl>("cancel")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCancel, this));  	getChild<LLUICtrl>("close")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCancel, this));  	getChild<LLUICtrl>("back")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickBack, this)); @@ -430,17 +487,20 @@ BOOL LLFloaterModelWizard::postBuild()  	getChild<LLUICtrl>("preview_lod_combo")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1));  	getChild<LLUICtrl>("accuracy_slider")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onAccuracyPerformance, this, _2));  	getChild<LLUICtrl>("upload")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onUpload, this)); -	 +	getChild<LLUICtrl>("physics_slider")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPhysicsChanged, this)); +  	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;  	enable_registrar.add("Next.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableNext, this));  	enable_registrar.add("Back.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableBack, this)); -	 +  	mPreviewRect = preview_panel->getRect();  	mModelPreview = new LLModelPreview(512, 512, this);  	mModelPreview->setPreviewTarget(16.f); +	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelWizard::setDetails, this, _1, _2, _3, _4, _5)); +	mModelPreview->setModelLoadedCallback(boost::bind(&LLFloaterModelWizard::modelLoadedCallback, this));  	center(); @@ -455,6 +515,37 @@ BOOL LLFloaterModelWizard::postBuild()  	return TRUE;  } + +void LLFloaterModelWizard::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost) +{ +	// iterate through all the panels, setting the dimensions +	for(size_t t=0; t<LL_ARRAY_SIZE(stateNames); ++t) +	{ +		LLPanel *panel = getChild<LLPanel>(stateNames[t]+"_panel"); +		if (panel)  +		{ +			panel->childSetText("dimension_x", llformat("%.1f", x)); +			panel->childSetText("dimension_y", llformat("%.1f", y)); +			panel->childSetText("dimension_z", llformat("%.1f", z)); +			panel->childSetTextArg("streaming cost", "[COST]", llformat("%.3f", streaming_cost)); +			panel->childSetTextArg("physics cost", "[COST]", llformat("%.3f", physics_cost));	 +		} +	} +} + +void LLFloaterModelWizard::modelLoadedCallback() +{ +	mLastEnabledState = CHOOSE_FILE; +	getChild<LLCheckBoxCtrl>("confirm_checkbox")->set(FALSE); +	updateButtons(); +} + +void LLFloaterModelWizard::onPhysicsChanged() +{ +	mLastEnabledState = PHYSICS; +	updateButtons(); +} +  void LLFloaterModelWizard::onUpload()  {	  	mModelPreview->rebuildUploadData(); @@ -466,7 +557,6 @@ void LLFloaterModelWizard::onUpload()  } -  void LLFloaterModelWizard::onAccuracyPerformance(const LLSD& data)  {  	int val = (int) data.asInteger(); @@ -476,6 +566,7 @@ void LLFloaterModelWizard::onAccuracyPerformance(const LLSD& data)  	mModelPreview->refresh();  } +  void LLFloaterModelWizard::onPreviewLODCommit(LLUICtrl* ctrl)  {  	if (!mModelPreview) @@ -492,8 +583,30 @@ void LLFloaterModelWizard::onPreviewLODCommit(LLUICtrl* ctrl)  	mModelPreview->setPreviewLOD(which_mode);  } +void LLFloaterModelWizard::refresh() +{ +	if (mState == CHOOSE_FILE) +	{ +		bool model_loaded = false; + +		if (mModelPreview && mModelPreview->mModelLoader && mModelPreview->mModelLoader->getLoadState() == LLModelLoader::DONE) +		{ +			model_loaded = true; +		} +		 +		getChildView("next")->setEnabled(model_loaded); +	} +	if (mState == REVIEW) +	{ +		getChildView("upload")->setEnabled(getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean()); +	} + +} +  void LLFloaterModelWizard::draw()  { +	refresh(); +  	LLFloater::draw();  	LLRect r = getRect(); @@ -505,8 +618,8 @@ void LLFloaterModelWizard::draw()  		gGL.getTexUnit(0)->bind(mModelPreview); -		LLView *view = getChild<LLView>(stateNames[mState]+"_panel"); -		LLView* preview_panel = view->getChild<LLView>("preview_panel"); +		LLView *view = getChildView(stateNames[mState]+"_panel"); +		LLView* preview_panel = view->getChildView("preview_panel");  		LLRect rect = preview_panel->getRect();  		if (rect != mPreviewRect) diff --git a/indra/newview/llfloatermodelwizard.h b/indra/newview/llfloatermodelwizard.h index eaf188ed40..50e4ab1a96 100644 --- a/indra/newview/llfloatermodelwizard.h +++ b/indra/newview/llfloatermodelwizard.h @@ -57,13 +57,16 @@ public:  	virtual ~LLFloaterModelWizard();  	/*virtual*/	BOOL	postBuild();  	void			draw(); +	void            refresh();  	BOOL handleMouseDown(S32 x, S32 y, MASK mask);  	BOOL handleMouseUp(S32 x, S32 y, MASK mask);  	BOOL handleHover(S32 x, S32 y, MASK mask);  	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);  -	 +	void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost); +	void modelLoadedCallback(); +	void onPhysicsChanged();  	void initDecompControls();  	LLPhysicsDecomp::decomp_params mDecompParams; @@ -82,7 +85,7 @@ private:  	};  	void setState(int state); -	void setButtons(int state); +	void updateButtons();  	void onClickCancel();  	void onClickBack();  	void onClickNext(); @@ -100,6 +103,8 @@ private:  	S32				mLastMouseX;  	S32				mLastMouseY; +	U32			    mLastEnabledState; +  }; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index fa8ed3d13e..456005f1fe 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -105,6 +105,7 @@  #include "llteleporthistorystorage.h"  #include "lllogininstance.h"        // to check if logged in yet +#include "llsdserialize.h"  const F32 MAX_USER_FAR_CLIP = 512.f;  const F32 MIN_USER_FAR_CLIP = 64.f; @@ -284,7 +285,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)  	mGotPersonalInfo(false),  	mOriginalIMViaEmail(false),  	mLanguageChanged(false), -	mDoubleClickActionDirty(false) +	mDoubleClickActionDirty(false), +	mFavoritesRecordMayExist(false)  {  	//Build Floater is now Called from 	LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); @@ -541,6 +543,34 @@ void LLFloaterPreference::apply()  		updateDoubleClickSettings();  		mDoubleClickActionDirty = false;  	} + +	if (mFavoritesRecordMayExist && !gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) +	{ +		removeFavoritesRecordOfUser();		 +	} +} + +void LLFloaterPreference::removeFavoritesRecordOfUser() +{ +	mFavoritesRecordMayExist = false; +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	LLSD fav_llsd; +	llifstream file; +	file.open(filename); +	if (!file.is_open()) return; +	LLSDSerialize::fromXML(fav_llsd, file); +	 +	LLAvatarName av_name; +	LLAvatarNameCache::get( gAgentID, &av_name ); +	if (fav_llsd.has(av_name.getLegacyName())) +	{ +		fav_llsd.erase(av_name.getLegacyName()); +	} +	 +	llofstream out_file; +	out_file.open(filename); +	LLSDSerialize::toPrettyXML(fav_llsd, out_file); +  }  void LLFloaterPreference::cancel() @@ -626,6 +656,11 @@ void LLFloaterPreference::onOpen(const LLSD& key)  		getChildView("maturity_desired_combobox")->setVisible( false);  	} +	if (LLStartUp::getStartupState() == STATE_STARTED) +	{ +		mFavoritesRecordMayExist = gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin"); +	} +  	// Forget previous language changes.  	mLanguageChanged = false; @@ -1338,6 +1373,7 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im  //	getChild<LLUICtrl>("busy_response")->setValue(gSavedSettings.getString("BusyModeResponse2")); +	getChildView("favorites_on_login_check")->setEnabled(TRUE);  	getChildView("log_nearby_chat")->setEnabled(TRUE);  	getChildView("log_instant_messages")->setEnabled(TRUE);  	getChildView("show_timestamps_check_im")->setEnabled(TRUE); @@ -1553,6 +1589,10 @@ BOOL LLPanelPreference::postBuild()  	{  		getChild<LLCheckBoxCtrl>("voice_call_friends_only_check")->setCommitCallback(boost::bind(&showFriendsOnlyWarning, _1, _2));  	} +	if (hasChild("favorites_on_login_check")) +	{ +		getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2)); +	}  	// Panel Advanced  	if (hasChild("modifier_combo")) @@ -1620,6 +1660,14 @@ void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& v  	}  } +void LLPanelPreference::showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value) +{ +	if (checkbox && checkbox->getValue()) +	{ +		LLNotificationsUtil::add("FavoritesOnLogin"); +	} +} +  void LLPanelPreference::cancel()  {  	for (control_values_map_t::iterator iter =  mSavedValues.begin(); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 165de9f42d..784033ae95 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -159,6 +159,8 @@ public:  	void buildPopupLists();  	static void refreshSkin(void* data); +	// Remove record of current user's favorites from file on disk. +	void removeFavoritesRecordOfUser();  private:  	static std::string sSkin;  	// set true if state of double-click action checkbox or radio-group was changed by user @@ -169,6 +171,8 @@ private:  	bool mLanguageChanged;  	bool mOriginalHideOnlineStatus; +	// Record of current user's favorites may be stored in file on disk. +	bool mFavoritesRecordMayExist;  	std::string mDirectoryVisibility;  	LLAvatarData mAvatarProperties; @@ -192,6 +196,8 @@ public:  private:  	//for "Only friends and groups can call or IM me"  	static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&); +	//for "Show my Favorite Landmarks at Login" +	static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value);  	typedef std::map<LLControlVariable*, LLSD> control_values_map_t;  	control_values_map_t mSavedValues; diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 51726112a0..058567492b 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -1,402 +1,402 @@ -/**
 - * @file llfloaterwebcontent.cpp
 - * @brief floater for displaying web content - e.g. profiles and search (eventually)
 - *
 - * $LicenseInfo:firstyear=2006&license=viewerlgpl$
 - * Second Life Viewer Source Code
 - * Copyright (C) 2010, Linden Research, Inc.
 - *
 - * This library is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU Lesser General Public
 - * License as published by the Free Software Foundation;
 - * version 2.1 of the License only.
 - *
 - * This library is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - * Lesser General Public License for more details.
 - *
 - * You should have received a copy of the GNU Lesser General Public
 - * License along with this library; if not, write to the Free Software
 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 - *
 - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 - * $/LicenseInfo$
 - */
 -
 -#include "llviewerprecompiledheaders.h"
 -
 -#include "llcombobox.h"
 -#include "lliconctrl.h"
 -#include "llfloaterreg.h"
 -#include "lllayoutstack.h"
 -#include "llpluginclassmedia.h"
 -#include "llprogressbar.h"
 -#include "lltextbox.h"
 -#include "llurlhistory.h"
 -#include "llviewercontrol.h"
 -#include "llweb.h"
 -#include "llwindow.h"
 -
 -#include "llfloaterwebcontent.h"
 -
 -LLFloaterWebContent::LLFloaterWebContent( const LLSD& key )
 -	: LLFloater( key )
 -{
 -	mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
 -	mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
 -	mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));
 -	mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));
 -	mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this ));
 -	mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this ));
 -}
 -
 -BOOL LLFloaterWebContent::postBuild()
 -{
 -	// these are used in a bunch of places so cache them
 -	mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" );
 -	mAddressCombo = getChild< LLComboBox >( "address" );
 -	mStatusBarText = getChild< LLTextBox >( "statusbartext" );
 -	mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" );
 -
 -	// observe browser events
 -	mWebBrowser->addObserver( this );
 -
 -	// these buttons are always enabled
 -	getChildView("reload")->setEnabled( true );
 -	getChildView("popexternal")->setEnabled( true );
 -
 -	// cache image for secure browsing
 -	mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag");
 -
 -	// initialize the URL history using the system URL History manager
 -	initializeURLHistory();
 -
 -	return TRUE;
 -}
 -
 -void LLFloaterWebContent::initializeURLHistory()
 -{
 -	// start with an empty list
 -	LLCtrlListInterface* url_list = childGetListInterface("address");
 -	if (url_list)
 -	{
 -		url_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
 -	}
 -
 -	// Get all of the entries in the "browser" collection
 -	LLSD browser_history = LLURLHistory::getURLHistory("browser");
 -	LLSD::array_iterator iter_history =
 -		browser_history.beginArray();
 -	LLSD::array_iterator end_history =
 -		browser_history.endArray();
 -	for(; iter_history != end_history; ++iter_history)
 -	{
 -		std::string url = (*iter_history).asString();
 -		if(! url.empty())
 -			url_list->addSimpleElement(url);
 -	}
 -}
 -
 -//static
 -void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid )
 -{
 -	lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl;
 -
 -	std::string tag = target;
 -
 -	if(target.empty() || target == "_blank")
 -	{
 -		if(!uuid.empty())
 -		{
 -			tag = uuid;
 -		}
 -		else
 -		{
 -			// create a unique tag for this instance
 -			LLUUID id;
 -			id.generate();
 -			tag = id.asString();
 -		}
 -	}
 -
 -	S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit");
 -
 -	if(LLFloaterReg::findInstance("web_content", tag) != NULL)
 -	{
 -		// There's already a web browser for this tag, so we won't be opening a new window.
 -	}
 -	else if(browser_window_limit != 0)
 -	{
 -		// showInstance will open a new window.  Figure out how many web browsers are already open,
 -		// and close the least recently opened one if this will put us over the limit.
 -
 -		LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content");
 -		lldebugs << "total instance count is " << instances.size() << llendl;
 -
 -		for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
 -		{
 -			lldebugs << "    " << (*iter)->getKey() << llendl;
 -		}
 -
 -		if(instances.size() >= (size_t)browser_window_limit)
 -		{
 -			// Destroy the least recently opened instance
 -			(*instances.begin())->closeFloater();
 -		}
 -	}
 -
 -	LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::showInstance("web_content", tag));
 -	llassert(browser);
 -	if(browser)
 -	{
 -		browser->mUUID = uuid;
 -
 -		// tell the browser instance to load the specified URL
 -		browser->open_media(url, target);
 -		LLViewerMedia::proxyWindowOpened(target, uuid);
 -	}
 -}
 -
 -//static
 -void LLFloaterWebContent::closeRequest(const std::string &uuid)
 -{
 -	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content");
 -	lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl;
 -	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
 -	{
 -		LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter);
 -		lldebugs << "    " << i->mUUID << llendl;
 -		if (i && i->mUUID == uuid)
 -		{
 -			i->closeFloater(false);
 -			return;
 - 		}
 - 	}
 -}
 -
 -//static
 -void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height)
 -{
 -	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content");
 -	lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl;
 -	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
 -	{
 -		LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter);
 -		lldebugs << "    " << i->mUUID << llendl;
 -		if (i && i->mUUID == uuid)
 -		{
 -			i->geometryChanged(x, y, width, height);
 -			return;
 -		}
 -	}
 -}
 -
 -void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
 -{
 -	// Make sure the layout of the browser control is updated, so this calculation is correct.
 -	LLLayoutStack::updateClass();
 -
 -	// TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc.
 -	LLCoordWindow window_size;
 -	getWindow()->getSize(&window_size);
 -
 -	// Adjust width and height for the size of the chrome on the web Browser window.
 -	width += getRect().getWidth() - mWebBrowser->getRect().getWidth();
 -	height += getRect().getHeight() - mWebBrowser->getRect().getHeight();
 -
 -	LLRect geom;
 -	geom.setOriginAndSize(x, window_size.mY - (y + height), width, height);
 -
 -	lldebugs << "geometry change: " << geom << llendl;
 -
 -	handleReshape(geom,false);
 -}
 -
 -void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target)
 -{
 -	// Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
 -	mWebBrowser->setHomePageUrl(web_url, "text/html");
 -	mWebBrowser->setTarget(target);
 -	mWebBrowser->navigateTo(web_url, "text/html");
 -	set_current_url(web_url);
 -}
 -
 -//virtual
 -void LLFloaterWebContent::onClose(bool app_quitting)
 -{
 -	LLViewerMedia::proxyWindowClosed(mUUID);
 -	destroy();
 -}
 -
 -// virtual
 -void LLFloaterWebContent::draw()
 -{
 -	// this is asychronous so we need to keep checking
 -	getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() );
 -	getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() );
 -
 -	LLFloater::draw();
 -}
 -
 -// virtual
 -void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
 -{
 -	if(event == MEDIA_EVENT_LOCATION_CHANGED)
 -	{
 -		const std::string url = self->getLocation();
 -
 -		if ( url.length() )
 -			mStatusBarText->setText( url );
 -
 -		set_current_url( url );
 -	}
 -	else if(event == MEDIA_EVENT_NAVIGATE_BEGIN)
 -	{
 -		// flags are sent with this event
 -		getChildView("back")->setEnabled( self->getHistoryBackAvailable() );
 -		getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() );
 -
 -		// toggle visibility of these buttons based on browser state
 -		getChildView("reload")->setVisible( false );
 -		getChildView("stop")->setVisible( true );
 -
 -		// turn "on" progress bar now we're about to start loading
 -		mStatusBarProgress->setVisible( true );
 -	}
 -	else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
 -	{
 -		// flags are sent with this event
 -		getChildView("back")->setEnabled( self->getHistoryBackAvailable() );
 -		getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() );
 -
 -		// toggle visibility of these buttons based on browser state
 -		getChildView("reload")->setVisible( true );
 -		getChildView("stop")->setVisible( false );
 -
 -		// turn "off" progress bar now we're loaded
 -		mStatusBarProgress->setVisible( false );
 -
 -		// we populate the status bar with URLs as they change so clear it now we're done
 -		const std::string end_str = "";
 -		mStatusBarText->setText( end_str );
 -
 -		// decide if secure browsing icon should be displayed
 -		std::string prefix =  std::string("https://");
 -		std::string test_prefix = mCurrentURL.substr(0, prefix.length());
 -		LLStringUtil::toLower(test_prefix);
 -		if(test_prefix == prefix)
 -		{
 -			mSecureLockIcon->setVisible(true);
 -		}
 -		else
 -		{
 -			mSecureLockIcon->setVisible(false);
 -		}
 -	}
 -	else if(event == MEDIA_EVENT_CLOSE_REQUEST)
 -	{
 -		// The browser instance wants its window closed.
 -		closeFloater();
 -	}
 -	else if(event == MEDIA_EVENT_GEOMETRY_CHANGE)
 -	{
 -		geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight());
 -	}
 -	else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED )
 -	{
 -		const std::string text = self->getStatusText();
 -		if ( text.length() )
 -			mStatusBarText->setText( text );
 -	}
 -	else if(event == MEDIA_EVENT_PROGRESS_UPDATED )
 -	{
 -		int percent = (int)self->getProgressPercent();
 -		mStatusBarProgress->setValue( percent );
 -	}
 -	else if(event == MEDIA_EVENT_NAME_CHANGED )
 -	{
 -		std::string page_title = self->getMediaName();
 -		// simulate browser behavior - title is empty, use the current URL
 -		if ( page_title.length() > 0 )
 -			setTitle( page_title );
 -		else
 -			setTitle( mCurrentURL );
 -	}
 -	else if(event == MEDIA_EVENT_LINK_HOVERED )
 -	{
 -		const std::string link = self->getHoverLink();
 -		mStatusBarText->setText( link );
 -	}
 -}
 -
 -void LLFloaterWebContent::set_current_url(const std::string& url)
 -{
 -	mCurrentURL = url;
 -
 -	// serialize url history into the system URL History manager
 -	LLURLHistory::removeURL("browser", mCurrentURL);
 -	LLURLHistory::addURL("browser", mCurrentURL);
 -
 -	mAddressCombo->remove( mCurrentURL );
 -	mAddressCombo->add( mCurrentURL );
 -	mAddressCombo->selectByValue( mCurrentURL );
 -}
 -
 -void LLFloaterWebContent::onClickForward()
 -{
 -	mWebBrowser->navigateForward();
 -}
 -
 -void LLFloaterWebContent::onClickBack()
 -{
 -	mWebBrowser->navigateBack();
 -}
 -
 -void LLFloaterWebContent::onClickReload()
 -{
 -
 -	if( mWebBrowser->getMediaPlugin() )
 -	{
 -		bool ignore_cache = true;
 -		mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache );
 -	}
 -	else
 -	{
 -		mWebBrowser->navigateTo(mCurrentURL);
 -	}
 -}
 -
 -void LLFloaterWebContent::onClickStop()
 -{
 -	if( mWebBrowser->getMediaPlugin() )
 -		mWebBrowser->getMediaPlugin()->browse_stop();
 -
 -	// still should happen when we catch the navigate complete event
 -	// but sometimes (don't know why) that event isn't sent from Qt
 -	// and we getto a point where the stop button stays active.
 -	getChildView("reload")->setVisible( true );
 -	getChildView("stop")->setVisible( false );
 -}
 -
 -void LLFloaterWebContent::onEnterAddress()
 -{
 -	// make sure there is at least something there.
 -	// (perhaps this test should be for minimum length of a URL)
 -	std::string url = mAddressCombo->getValue().asString();
 -	if ( url.length() > 0 )
 -	{
 -		mWebBrowser->navigateTo( url, "text/html");
 -	};
 -}
 -
 -void LLFloaterWebContent::onPopExternal()
 -{
 -	// make sure there is at least something there.
 -	// (perhaps this test should be for minimum length of a URL)
 -	std::string url = mAddressCombo->getValue().asString();
 -	if ( url.length() > 0 )
 -	{
 -		LLWeb::loadURLExternal( url );
 -	};
 -}
 +/** + * @file llfloaterwebcontent.cpp + * @brief floater for displaying web content - e.g. profiles and search (eventually) + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcombobox.h" +#include "lliconctrl.h" +#include "llfloaterreg.h" +#include "lllayoutstack.h" +#include "llpluginclassmedia.h" +#include "llprogressbar.h" +#include "lltextbox.h" +#include "llurlhistory.h" +#include "llviewercontrol.h" +#include "llweb.h" +#include "llwindow.h" + +#include "llfloaterwebcontent.h" + +LLFloaterWebContent::LLFloaterWebContent( const LLSD& key ) +	: LLFloater( key ) +{ +	mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this )); +	mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this )); +	mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this )); +	mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this )); +	mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this )); +	mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this )); +} + +BOOL LLFloaterWebContent::postBuild() +{ +	// these are used in a bunch of places so cache them +	mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" ); +	mAddressCombo = getChild< LLComboBox >( "address" ); +	mStatusBarText = getChild< LLTextBox >( "statusbartext" ); +	mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" ); + +	// observe browser events +	mWebBrowser->addObserver( this ); + +	// these buttons are always enabled +	getChildView("reload")->setEnabled( true ); +	getChildView("popexternal")->setEnabled( true ); + +	// cache image for secure browsing +	mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag"); + +	// initialize the URL history using the system URL History manager +	initializeURLHistory(); + +	return TRUE; +} + +void LLFloaterWebContent::initializeURLHistory() +{ +	// start with an empty list +	LLCtrlListInterface* url_list = childGetListInterface("address"); +	if (url_list) +	{ +		url_list->operateOnAll(LLCtrlListInterface::OP_DELETE); +	} + +	// Get all of the entries in the "browser" collection +	LLSD browser_history = LLURLHistory::getURLHistory("browser"); +	LLSD::array_iterator iter_history = +		browser_history.beginArray(); +	LLSD::array_iterator end_history = +		browser_history.endArray(); +	for(; iter_history != end_history; ++iter_history) +	{ +		std::string url = (*iter_history).asString(); +		if(! url.empty()) +			url_list->addSimpleElement(url); +	} +} + +//static +void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid ) +{ +	lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl; + +	std::string tag = target; + +	if(target.empty() || target == "_blank") +	{ +		if(!uuid.empty()) +		{ +			tag = uuid; +		} +		else +		{ +			// create a unique tag for this instance +			LLUUID id; +			id.generate(); +			tag = id.asString(); +		} +	} + +	S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit"); + +	if(LLFloaterReg::findInstance("web_content", tag) != NULL) +	{ +		// There's already a web browser for this tag, so we won't be opening a new window. +	} +	else if(browser_window_limit != 0) +	{ +		// showInstance will open a new window.  Figure out how many web browsers are already open, +		// and close the least recently opened one if this will put us over the limit. + +		LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content"); +		lldebugs << "total instance count is " << instances.size() << llendl; + +		for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) +		{ +			lldebugs << "    " << (*iter)->getKey() << llendl; +		} + +		if(instances.size() >= (size_t)browser_window_limit) +		{ +			// Destroy the least recently opened instance +			(*instances.begin())->closeFloater(); +		} +	} + +	LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::showInstance("web_content", tag)); +	llassert(browser); +	if(browser) +	{ +		browser->mUUID = uuid; + +		// tell the browser instance to load the specified URL +		browser->open_media(url, target); +		LLViewerMedia::proxyWindowOpened(target, uuid); +	} +} + +//static +void LLFloaterWebContent::closeRequest(const std::string &uuid) +{ +	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); +	lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; +	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) +	{ +		LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter); +		lldebugs << "    " << i->mUUID << llendl; +		if (i && i->mUUID == uuid) +		{ +			i->closeFloater(false); +			return; + 		} + 	} +} + +//static +void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height) +{ +	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); +	lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; +	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) +	{ +		LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter); +		lldebugs << "    " << i->mUUID << llendl; +		if (i && i->mUUID == uuid) +		{ +			i->geometryChanged(x, y, width, height); +			return; +		} +	} +} + +void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) +{ +	// Make sure the layout of the browser control is updated, so this calculation is correct. +	LLLayoutStack::updateClass(); + +	// TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc. +	LLCoordWindow window_size; +	getWindow()->getSize(&window_size); + +	// Adjust width and height for the size of the chrome on the web Browser window. +	width += getRect().getWidth() - mWebBrowser->getRect().getWidth(); +	height += getRect().getHeight() - mWebBrowser->getRect().getHeight(); + +	LLRect geom; +	geom.setOriginAndSize(x, window_size.mY - (y + height), width, height); + +	lldebugs << "geometry change: " << geom << llendl; + +	handleReshape(geom,false); +} + +void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target) +{ +	// Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. +	mWebBrowser->setHomePageUrl(web_url, "text/html"); +	mWebBrowser->setTarget(target); +	mWebBrowser->navigateTo(web_url, "text/html"); +	set_current_url(web_url); +} + +//virtual +void LLFloaterWebContent::onClose(bool app_quitting) +{ +	LLViewerMedia::proxyWindowClosed(mUUID); +	destroy(); +} + +// virtual +void LLFloaterWebContent::draw() +{ +	// this is asychronous so we need to keep checking +	getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() ); +	getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() ); + +	LLFloater::draw(); +} + +// virtual +void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ +	if(event == MEDIA_EVENT_LOCATION_CHANGED) +	{ +		const std::string url = self->getLocation(); + +		if ( url.length() ) +			mStatusBarText->setText( url ); + +		set_current_url( url ); +	} +	else if(event == MEDIA_EVENT_NAVIGATE_BEGIN) +	{ +		// flags are sent with this event +		getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); +		getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); + +		// toggle visibility of these buttons based on browser state +		getChildView("reload")->setVisible( false ); +		getChildView("stop")->setVisible( true ); + +		// turn "on" progress bar now we're about to start loading +		mStatusBarProgress->setVisible( true ); +	} +	else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) +	{ +		// flags are sent with this event +		getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); +		getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); + +		// toggle visibility of these buttons based on browser state +		getChildView("reload")->setVisible( true ); +		getChildView("stop")->setVisible( false ); + +		// turn "off" progress bar now we're loaded +		mStatusBarProgress->setVisible( false ); + +		// we populate the status bar with URLs as they change so clear it now we're done +		const std::string end_str = ""; +		mStatusBarText->setText( end_str ); + +		// decide if secure browsing icon should be displayed +		std::string prefix =  std::string("https://"); +		std::string test_prefix = mCurrentURL.substr(0, prefix.length()); +		LLStringUtil::toLower(test_prefix); +		if(test_prefix == prefix) +		{ +			mSecureLockIcon->setVisible(true); +		} +		else +		{ +			mSecureLockIcon->setVisible(false); +		} +	} +	else if(event == MEDIA_EVENT_CLOSE_REQUEST) +	{ +		// The browser instance wants its window closed. +		closeFloater(); +	} +	else if(event == MEDIA_EVENT_GEOMETRY_CHANGE) +	{ +		geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight()); +	} +	else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED ) +	{ +		const std::string text = self->getStatusText(); +		if ( text.length() ) +			mStatusBarText->setText( text ); +	} +	else if(event == MEDIA_EVENT_PROGRESS_UPDATED ) +	{ +		int percent = (int)self->getProgressPercent(); +		mStatusBarProgress->setValue( percent ); +	} +	else if(event == MEDIA_EVENT_NAME_CHANGED ) +	{ +		std::string page_title = self->getMediaName(); +		// simulate browser behavior - title is empty, use the current URL +		if ( page_title.length() > 0 ) +			setTitle( page_title ); +		else +			setTitle( mCurrentURL ); +	} +	else if(event == MEDIA_EVENT_LINK_HOVERED ) +	{ +		const std::string link = self->getHoverLink(); +		mStatusBarText->setText( link ); +	} +} + +void LLFloaterWebContent::set_current_url(const std::string& url) +{ +	mCurrentURL = url; + +	// serialize url history into the system URL History manager +	LLURLHistory::removeURL("browser", mCurrentURL); +	LLURLHistory::addURL("browser", mCurrentURL); + +	mAddressCombo->remove( mCurrentURL ); +	mAddressCombo->add( mCurrentURL ); +	mAddressCombo->selectByValue( mCurrentURL ); +} + +void LLFloaterWebContent::onClickForward() +{ +	mWebBrowser->navigateForward(); +} + +void LLFloaterWebContent::onClickBack() +{ +	mWebBrowser->navigateBack(); +} + +void LLFloaterWebContent::onClickReload() +{ + +	if( mWebBrowser->getMediaPlugin() ) +	{ +		bool ignore_cache = true; +		mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache ); +	} +	else +	{ +		mWebBrowser->navigateTo(mCurrentURL); +	} +} + +void LLFloaterWebContent::onClickStop() +{ +	if( mWebBrowser->getMediaPlugin() ) +		mWebBrowser->getMediaPlugin()->browse_stop(); + +	// still should happen when we catch the navigate complete event +	// but sometimes (don't know why) that event isn't sent from Qt +	// and we getto a point where the stop button stays active. +	getChildView("reload")->setVisible( true ); +	getChildView("stop")->setVisible( false ); +} + +void LLFloaterWebContent::onEnterAddress() +{ +	// make sure there is at least something there. +	// (perhaps this test should be for minimum length of a URL) +	std::string url = mAddressCombo->getValue().asString(); +	if ( url.length() > 0 ) +	{ +		mWebBrowser->navigateTo( url, "text/html"); +	}; +} + +void LLFloaterWebContent::onPopExternal() +{ +	// make sure there is at least something there. +	// (perhaps this test should be for minimum length of a URL) +	std::string url = mAddressCombo->getValue().asString(); +	if ( url.length() > 0 ) +	{ +		LLWeb::loadURLExternal( url ); +	}; +} diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 001d822ada..ecc7e970d8 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -1,82 +1,82 @@ -/**
 - * @file llfloaterwebcontent.h
 - * @brief floater for displaying web content - e.g. profiles and search (eventually)
 - *
 - * $LicenseInfo:firstyear=2006&license=viewerlgpl$
 - * Second Life Viewer Source Code
 - * Copyright (C) 2010, Linden Research, Inc.
 - *
 - * This library is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU Lesser General Public
 - * License as published by the Free Software Foundation;
 - * version 2.1 of the License only.
 - *
 - * This library is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - * Lesser General Public License for more details.
 - *
 - * You should have received a copy of the GNU Lesser General Public
 - * License along with this library; if not, write to the Free Software
 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 - *
 - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 - * $/LicenseInfo$
 - */
 -
 -#ifndef LL_LLFLOATERWEBCONTENT_H
 -#define LL_LLFLOATERWEBCONTENT_H
 -
 -#include "llfloater.h"
 -#include "llmediactrl.h"
 -
 -class LLMediaCtrl;
 -class LLComboBox;
 -class LLTextBox;
 -class LLProgressBar;
 -class LLIconCtrl;
 -
 -class LLFloaterWebContent :
 -	public LLFloater,
 -	public LLViewerMediaObserver
 -{
 -public:
 -    LOG_CLASS(LLFloaterWebContent);
 -	LLFloaterWebContent(const LLSD& key);
 -
 +/** + * @file llfloaterwebcontent.h + * @brief floater for displaying web content - e.g. profiles and search (eventually) + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERWEBCONTENT_H +#define LL_LLFLOATERWEBCONTENT_H + +#include "llfloater.h" +#include "llmediactrl.h" + +class LLMediaCtrl; +class LLComboBox; +class LLTextBox; +class LLProgressBar; +class LLIconCtrl; + +class LLFloaterWebContent : +	public LLFloater, +	public LLViewerMediaObserver +{ +public: +    LOG_CLASS(LLFloaterWebContent); +	LLFloaterWebContent(const LLSD& key); +  	void initializeURLHistory(); -
 -	static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null);
 -
 -	static void closeRequest(const std::string &uuid);
 -	static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height);
 -	void geometryChanged(S32 x, S32 y, S32 width, S32 height);
 -
 -	/* virtual */ BOOL postBuild();
 -	/* virtual */ void onClose(bool app_quitting);
 -	/* virtual */ void draw();
 -
 -	// inherited from LLViewerMediaObserver
 -	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
 -
 -	void onClickBack();
 -	void onClickForward();
 -	void onClickReload();
 -	void onClickStop();
 -	void onEnterAddress();
 -	void onPopExternal();
 -
 -private:
 -	void open_media(const std::string& media_url, const std::string& target);
 -	void set_current_url(const std::string& url);
 -
 -	LLMediaCtrl* mWebBrowser;
 -	LLComboBox* mAddressCombo;
 -	LLIconCtrl *mSecureLockIcon;
 -	LLTextBox* mStatusBarText;
 -	LLProgressBar* mStatusBarProgress;
 -	std::string mCurrentURL;
 -	std::string mUUID;
 -};
 -
 -#endif  // LL_LLFLOATERWEBCONTENT_H
 + +	static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null); + +	static void closeRequest(const std::string &uuid); +	static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height); +	void geometryChanged(S32 x, S32 y, S32 width, S32 height); + +	/* virtual */ BOOL postBuild(); +	/* virtual */ void onClose(bool app_quitting); +	/* virtual */ void draw(); + +	// inherited from LLViewerMediaObserver +	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + +	void onClickBack(); +	void onClickForward(); +	void onClickReload(); +	void onClickStop(); +	void onEnterAddress(); +	void onPopExternal(); + +private: +	void open_media(const std::string& media_url, const std::string& target); +	void set_current_url(const std::string& url); + +	LLMediaCtrl* mWebBrowser; +	LLComboBox* mAddressCombo; +	LLIconCtrl *mSecureLockIcon; +	LLTextBox* mStatusBarText; +	LLProgressBar* mStatusBarProgress; +	std::string mCurrentURL; +	std::string mUUID; +}; + +#endif  // LL_LLFLOATERWEBCONTENT_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index ce305dcd89..afd565bb26 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -280,19 +280,19 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&  void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name)  {  	if (av_name.mIsDummy) -	{
 -		S32 separator_index = mName.rfind(" ");
 -		std::string name = mName.substr(0, separator_index);
 -		++separator_index;
 -		std::string conference_word = mName.substr(separator_index, mName.length());
 -
 -		// additional check that session name is what we expected
 -		if ("Conference" == conference_word)
 -		{
 -			LLStringUtil::format_map_t args;
 -			args["[AGENT_NAME]"] = name;
 -			LLTrans::findString(mName, "conference-title-incoming", args);
 -		}
 +	{ +		S32 separator_index = mName.rfind(" "); +		std::string name = mName.substr(0, separator_index); +		++separator_index; +		std::string conference_word = mName.substr(separator_index, mName.length()); + +		// additional check that session name is what we expected +		if ("Conference" == conference_word) +		{ +			LLStringUtil::format_map_t args; +			args["[AGENT_NAME]"] = name; +			LLTrans::findString(mName, "conference-title-incoming", args); +		}  	}  	else  	{ diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index e765a8da2f..a15776c207 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -100,7 +100,7 @@ public:  		void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name); -		void onAdHocNameCache(const LLAvatarName& av_name);
 +		void onAdHocNameCache(const LLAvatarName& av_name);  		//*TODO make private  		static std::string generateHash(const std::set<LLUUID>& sorted_uuids); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1b07aa279b..342d15cf0f 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -686,6 +686,12 @@ bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* it  		return false;  	} +	// Skip broken links. +	if (vitem->getIsBrokenLink()) +	{ +		return false; +	} +  	return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;  } diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index eab8f187a7..570e48d526 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -181,7 +181,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  	if (mBackgroundFetchActive && gAgent.getRegion())  	{  		// If we'll be using the capability, we'll be sending batches and the background thing isn't as important. -		std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");    +		std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");     		if (!url.empty())   		{  			bulkFetch(url); @@ -604,7 +604,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  		}  		if (body_lib["folders"].size())  		{ -			std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents"); +			std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");  			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats);  			LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0); diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 91ff8c7867..0fd4b2bee5 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -203,8 +203,8 @@ void fetch_items_from_llsd(const LLSD& items_llsd)  {  	if (!items_llsd.size() || gDisconnected) return;  	LLSD body; -	body[0]["cap_name"] = "FetchInventory"; -	body[1]["cap_name"] = "FetchLib"; +	body[0]["cap_name"] = "FetchInventory2"; +	body[1]["cap_name"] = "FetchLib2";  	for (S32 i=0; i<items_llsd.size();i++)  	{  		if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString()) diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 1527f8f4c9..55164f6094 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -547,6 +547,10 @@ void LLLocationInputCtrl::onFocusLost()  {  	LLUICtrl::onFocusLost();  	refreshLocation(); + +	// Setting cursor to 0  to show the left edge of the text. See STORM-370. +	mTextEntry->setCursor(0); +  	if(mTextEntry->hasSelection()){  		mTextEntry->deselect();  	} diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 0121bbb1ed..9adf374c71 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -89,15 +89,15 @@ const static boost::regex TIMESTAMP_AND_STUFF("^(\\[\\d{4}/\\d{1,2}/\\d{1,2}\\s+   */  const static boost::regex NAME_AND_TEXT("([^:]+[:]{1})?(\\s*)(.*)"); -/**
 - * These are recognizers for matching the names of ad-hoc conferences when generating the log file name
 - * On invited side, an ad-hoc is named like "<first name> <last name> Conference 2010/11/19 03:43 f0f4"
 - * On initiating side, an ad-hoc is named like Ad-hoc Conference hash<hash>"
 - * If the naming system for ad-hoc conferences are change in LLIMModel::LLIMSession::buildHistoryFileName()
 - * then these definition need to be adjusted as well.
 - */
 -const static boost::regex INBOUND_CONFERENCE("^[a-zA-Z]{1,31} [a-zA-Z]{1,31} Conference [0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2} [0-9a-f]{4}");
 -const static boost::regex OUTBOUND_CONFERENCE("^Ad-hoc Conference hash[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}");
 +/** + * These are recognizers for matching the names of ad-hoc conferences when generating the log file name + * On invited side, an ad-hoc is named like "<first name> <last name> Conference 2010/11/19 03:43 f0f4" + * On initiating side, an ad-hoc is named like Ad-hoc Conference hash<hash>" + * If the naming system for ad-hoc conferences are change in LLIMModel::LLIMSession::buildHistoryFileName() + * then these definition need to be adjusted as well. + */ +const static boost::regex INBOUND_CONFERENCE("^[a-zA-Z]{1,31} [a-zA-Z]{1,31} Conference [0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2} [0-9a-f]{4}"); +const static boost::regex OUTBOUND_CONFERENCE("^Ad-hoc Conference hash[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}");  //is used to parse complex object names like "Xstreet SL Terminal v2.2.5 st"  const static std::string NAME_TEXT_DIVIDER(": "); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index d2f76eceb0..b772999ee2 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -2299,7 +2299,7 @@ void LLMeshRepository::notifyLoadedMeshes()  	if (gAgent.getRegion())  	{ //update capability url  -		if (gAgent.getRegion()->getName() != region_name) +		if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())  		{  			region_name = gAgent.getRegion()->getName(); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 5f89097c17..c143aff2d4 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -253,11 +253,67 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,  	gResponsePtr = LLIamHereLogin::build( this );  	LLHTTPClient::head( LLGridManager::getInstance()->getLoginPage(), gResponsePtr ); -	 + +	// Show last logged in user favorites in "Start at" combo. +	addUsersWithFavoritesToUsername(); +	getChild<LLComboBox>("username_combo")->setTextChangedCallback(boost::bind(&LLPanelLogin::addFavoritesToStartLocation, this)); +  	updateLocationCombo(false);  } +void LLPanelLogin::addUsersWithFavoritesToUsername() +{ +	LLComboBox* combo = getChild<LLComboBox>("username_combo"); +	if (!combo) return; +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	LLSD fav_llsd; +	llifstream file; +	file.open(filename); +	if (!file.is_open()) return; +	LLSDSerialize::fromXML(fav_llsd, file); +	for (LLSD::map_const_iterator iter = fav_llsd.beginMap(); +		iter != fav_llsd.endMap(); ++iter) +	{ +		combo->add(iter->first); +	} +} + +void LLPanelLogin::addFavoritesToStartLocation() +{ +	LLComboBox* combo = getChild<LLComboBox>("start_location_combo"); +	if (!combo) return; +	int num_items = combo->getItemCount(); +	for (int i = num_items - 1; i > 2; i--) +	{ +		combo->remove(i); +	} +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	LLSD fav_llsd; +	llifstream file; +	file.open(filename); +	if (!file.is_open()) return; +	LLSDSerialize::fromXML(fav_llsd, file); +	for (LLSD::map_const_iterator iter = fav_llsd.beginMap(); +		iter != fav_llsd.endMap(); ++iter) +	{ +		if(iter->first != getChild<LLComboBox>("username_combo")->getSimple()) continue; +		combo->addSeparator(); +		LLSD user_llsd = iter->second; +		for (LLSD::array_const_iterator iter1 = user_llsd.beginArray(); +			iter1 != user_llsd.endArray(); ++iter1) +		{ +			std::string label = (*iter1)["name"].asString(); +			std::string value = (*iter1)["slurl"].asString(); +			if(label != "" && value != "") +			{ +				combo->add(label, value); +			} +		} +		break; +	} +} +  // force the size to be correct (XML doesn't seem to be sufficient to do this)  // (with some padding so the other login screen doesn't show through)  void LLPanelLogin::reshapeBrowser() @@ -393,13 +449,14 @@ void LLPanelLogin::giveFocus()  	if( sInstance )  	{  		// Grab focus and move cursor to first blank input field -		std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString(); +		std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();  		std::string pass = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();  		BOOL have_username = !username.empty();  		BOOL have_pass = !pass.empty();  		LLLineEditor* edit = NULL; +		LLComboBox* combo = NULL;  		if (have_username && !have_pass)  		{  			// User saved his name but not his password.  Move @@ -409,7 +466,7 @@ void LLPanelLogin::giveFocus()  		else  		{  			// User doesn't have a name, so start there. -			edit = sInstance->getChild<LLLineEditor>("username_edit"); +			combo = sInstance->getChild<LLComboBox>("username_combo");  		}  		if (edit) @@ -417,6 +474,10 @@ void LLPanelLogin::giveFocus()  			edit->setFocus(TRUE);  			edit->selectAll();  		} +		else if (combo) +		{ +			combo->setFocus(TRUE); +		}  	}  } @@ -431,8 +492,8 @@ void LLPanelLogin::showLoginWidgets()  	// *TODO: Append all the usual login parameters, like first_login=Y etc.  	std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();  	web_browser->navigateTo( splash_screen_url, "text/html" ); -	LLUICtrl* username_edit = sInstance->getChild<LLUICtrl>("username_edit"); -	username_edit->setFocus(TRUE); +	LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo"); +	username_combo->setFocus(TRUE);  }  // static @@ -476,16 +537,17 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,  		    login_id += " ";  		    login_id += lastname;  	    } -		sInstance->getChild<LLUICtrl>("username_edit")->setValue(login_id);	 +		sInstance->getChild<LLComboBox>("username_combo")->setLabel(login_id);	  	}  	else if((std::string)identifier["type"] == "account")  	{ -		sInstance->getChild<LLUICtrl>("username_edit")->setValue((std::string)identifier["account_name"]);		 +		sInstance->getChild<LLComboBox>("username_combo")->setLabel((std::string)identifier["account_name"]);		  	}  	else  	{ -	  sInstance->getChild<LLUICtrl>("username_edit")->setValue(std::string());	 +	  sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());	  	} +	sInstance->addFavoritesToStartLocation();  	// if the password exists in the credential, set the password field with  	// a filler to get some stars  	LLSD authenticator = credential->getAuthenticator(); @@ -533,7 +595,7 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,  		authenticator = credential->getAuthenticator();  	} -	std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString(); +	std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();  	LLStringUtil::trim(username);  	std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString(); @@ -625,15 +687,15 @@ BOOL LLPanelLogin::areCredentialFieldsDirty()  	}  	else  	{ -		std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString(); +		std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();  		LLStringUtil::trim(username);  		std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString(); -		LLLineEditor* ctrl = sInstance->getChild<LLLineEditor>("username_edit"); -		if(ctrl && ctrl->isDirty()) +		LLComboBox* combo = sInstance->getChild<LLComboBox>("username_combo"); +		if(combo && combo->isDirty())  		{  			return true;  		} -		ctrl = sInstance->getChild<LLLineEditor>("password_edit"); +		LLLineEditor* ctrl = sInstance->getChild<LLLineEditor>("password_edit");  		if(ctrl && ctrl->isDirty())   		{  			return true; @@ -873,7 +935,7 @@ void LLPanelLogin::onClickConnect(void *)  			return;  		}  		updateStartSLURL(); -		std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString(); +		std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();  		if(username.empty()) diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 83e76a308b..1ef6539ecc 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -85,6 +85,8 @@ public:  private:  	friend class LLPanelLoginListener;  	void reshapeBrowser(); +	void addFavoritesToStartLocation(); +	void addUsersWithFavoritesToUsername();  	static void onClickConnect(void*);  	static void onClickNewAccount(void*);  //	static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index 5ea94e0611..d3c9c3e131 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -76,17 +76,19 @@ void LLPanelMe::onOpen(const LLSD& key)  {  	LLPanelProfile::onOpen(key); -	// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) -	bool opened = gSavedSettings.getBOOL("MePanelOpened"); -	// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this -	// is the last time onOpen() is called -	if( !opened && !LLSideTray::getInstance()->getCollapsed() ) -	{ -		buildEditPanel(); -		openPanel(mEditPanel, getAvatarId()); - -		gSavedSettings.setBOOL("MePanelOpened", true); -	} +	// Removed this action as per SOCIAL-431 The first time a new resident opens the profile tab  +	//                                       in the sidebar, they see the old profile editing panel +	// +	//// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) +	//bool opened = gSavedSettings.getBOOL("MePanelOpened"); +	//// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this +	//// is the last time onOpen() is called +	//if( !opened && !LLSideTray::getInstance()->getCollapsed() ) +	//{ +	//	buildEditPanel(); +	//	openPanel(mEditPanel, getAvatarId()); +	//	gSavedSettings.setBOOL("MePanelOpened", true); +	//}  }  bool LLPanelMe::notifyChildren(const LLSD& info) diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index e5ef51bdd1..3862dac340 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -33,6 +33,7 @@  #include "llpanel.h"  #include "llhttpclient.h"  #include "llsdserialize.h" +#include "llurlentry.h"  #include "llviewerregion.h"  #include "llview.h" @@ -168,6 +169,18 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v  	{  		observers.erase(*i);  	} + +	LLUrlEntryParcel::LLParcelData url_data; +	url_data.parcel_id = parcel_data.parcel_id; +	url_data.name = parcel_data.name; +	url_data.sim_name = parcel_data.sim_name; +	url_data.global_x = parcel_data.global_x; +	url_data.global_y = parcel_data.global_y; +	url_data.global_z = parcel_data.global_z; + +	// Pass the parcel data to LLUrlEntryParcel to render +	// human readable parcel name. +	LLUrlEntryParcel::processParcelInfo(url_data);  }  void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id) diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index aef665a35c..19d1bdee86 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -498,8 +498,8 @@ private:  LLSideTray::Params::Params()  :	collapsed("collapsed",false), -	tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("sidebar_tab_left.tga")), -	tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("button_enabled_selected_32x128.tga")), +	tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Off.png")), +	tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Selected.png")),  	default_button_width("tab_btn_width",32),  	default_button_height("tab_btn_height",32),  	default_button_margin("tab_btn_margin",0) diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index ec9bc86ea0..b9063b3c81 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2673,6 +2673,49 @@ void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color)  	gGL.end();  } +void renderUpdateType(LLDrawable* drawablep) +{ +	LLViewerObject* vobj = drawablep->getVObj(); +	if (!vobj || OUT_UNKNOWN == vobj->getLastUpdateType()) +	{ +		return; +	} +	LLGLEnable blend(GL_BLEND); +	switch (vobj->getLastUpdateType()) +	{ +	case OUT_FULL: +		glColor4f(0,1,0,0.5f); +		break; +	case OUT_TERSE_IMPROVED: +		glColor4f(0,1,1,0.5f); +		break; +	case OUT_FULL_COMPRESSED: +		if (vobj->getLastUpdateCached()) +		{ +			glColor4f(1,0,0,0.5f); +		} +		else +		{ +			glColor4f(1,1,0,0.5f); +		} +		break; +	case OUT_FULL_CACHED: +		glColor4f(0,0,1,0.5f); +		break; +	default: +		llwarns << "Unknown update_type " << vobj->getLastUpdateType() << llendl; +		break; +	}; +	S32 num_faces = drawablep->getNumFaces(); +	if (num_faces) +	{ +		for (S32 i = 0; i < num_faces; ++i) +		{ +			pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); +		} +	} +} +  void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)  { @@ -3776,6 +3819,10 @@ public:  			{  				renderRaycast(drawable);  			} +			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_UPDATE_TYPE)) +			{ +				renderUpdateType(drawable); +			}  			LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get()); @@ -3992,6 +4039,7 @@ void LLSpatialPartition::renderDebug()  									  LLPipeline::RENDER_DEBUG_OCCLUSION |  									  LLPipeline::RENDER_DEBUG_LIGHTS |  									  LLPipeline::RENDER_DEBUG_BATCH_SIZE | +									  LLPipeline::RENDER_DEBUG_UPDATE_TYPE |  									  LLPipeline::RENDER_DEBUG_BBOXES |  									  LLPipeline::RENDER_DEBUG_NORMALS |  									  LLPipeline::RENDER_DEBUG_POINTS | diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 5dcbf079a4..029a48480f 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -139,6 +139,7 @@  #include "lltrans.h"  #include "llui.h"  #include "llurldispatcher.h" +#include "llurlentry.h"  #include "llslurl.h"  #include "llurlhistory.h"  #include "llurlwhitelist.h" @@ -2882,9 +2883,17 @@ bool process_login_success_response()  	if(!text.empty()) gAgentID.set(text);  	gDebugInfo["AgentID"] = text; +	// Agent id needed for parcel info request in LLUrlEntryParcel +	// to resolve parcel name. +	LLUrlEntryParcel::setAgentID(gAgentID); +  	text = response["session_id"].asString();  	if(!text.empty()) gAgentSessionID.set(text);  	gDebugInfo["SessionID"] = text; + +	// Session id needed for parcel info request in LLUrlEntryParcel +	// to resolve parcel name. +	LLUrlEntryParcel::setSessionID(gAgentSessionID);  	text = response["secure_session_id"].asString();  	if(!text.empty()) gAgent.mSecureSessionID.set(text); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 70696dc762..cc851e676b 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -48,6 +48,7 @@  #include "llinventorybridge.h"  #include "llinventorypanel.h"  #include "llfloaterinventory.h" +#include "lllandmarkactions.h"  #include "llviewerassettype.h"  #include "llviewerregion.h" @@ -59,7 +60,9 @@  #include "llcommandhandler.h"  #include "llviewermessage.h"  #include "llsidepanelappearance.h" +#include "llavatarnamecache.h"  #include "llavataractions.h" +#include "lllogininstance.h"  ///----------------------------------------------------------------------------  /// Helper class to store special inventory item names and their localized values. @@ -363,11 +366,11 @@ void LLViewerInventoryItem::fetchFromServer(void) const  		{  		  if(gAgent.getID() != mPermissions.getOwner())  		    { -		      url = region->getCapability("FetchLib"); +		      url = region->getCapability("FetchLib2");  		    }  		  else  		    {	 -		      url = region->getCapability("FetchInventory"); +		      url = region->getCapability("FetchInventory2");  		    }  		}  		else @@ -645,7 +648,7 @@ bool LLViewerInventoryCategory::fetch()  		std::string url;  		if (gAgent.getRegion())  		{ -			url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); +			url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");  		}  		else  		{ @@ -657,7 +660,7 @@ bool LLViewerInventoryCategory::fetch()  		}  		else  		{	//Deprecated, but if we don't have a capability, use the old system. -			llinfos << "WebFetchInventoryDescendents capability not found.  Using deprecated UDP message." << llendl; +			llinfos << "FetchInventoryDescendents2 capability not found.  Using deprecated UDP message." << llendl;  			LLMessageSystem* msg = gMessageSystem;  			msg->newMessage("FetchInventoryDescendents");  			msg->nextBlock("AgentData"); @@ -1416,6 +1419,8 @@ public:  	S32 getSortIndex(const LLUUID& inv_item_id);  	void removeSortIndex(const LLUUID& inv_item_id); +	void getSLURL(const LLUUID& asset_id); +  	/**  	 * Implementation of LLDestroyClass. Calls cleanup() instance method.  	 * @@ -1442,9 +1447,17 @@ private:  	void load();  	void save(); +	void saveFavoritesSLURLs(); + +	void onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark); +	void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); +  	typedef std::map<LLUUID, S32> sort_index_map_t;  	sort_index_map_t mSortIndexes; +	typedef std::map<LLUUID, std::string> slurls_map_t; +	slurls_map_t mSLURLs; +  	bool mIsDirty;  	struct IsNotInFavorites @@ -1499,10 +1512,27 @@ void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id)  	mIsDirty = true;  } +void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) +{ +	slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); +	if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached + +	LLLandmark* lm = gLandmarkList.getAsset(asset_id, +			boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); +	if (lm) +	{ +		onLandmarkLoaded(asset_id, lm); +	} +} +  // static  void LLFavoritesOrderStorage::destroyClass()  {  	LLFavoritesOrderStorage::instance().cleanup(); +	if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) +	{ +		LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); +	}  }  void LLFavoritesOrderStorage::load() @@ -1525,6 +1555,76 @@ void LLFavoritesOrderStorage::load()  	}  } +void LLFavoritesOrderStorage::saveFavoritesSLURLs() +{ +	// Do not change the file if we are not logged in yet. +	if (!LLLoginInstance::getInstance()->authSuccess()) return; +	 +	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); +	if (user_dir.empty()) return; + +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	llifstream in_file; +	in_file.open(filename); +	LLSD fav_llsd; +	if (in_file.is_open()) +	{ +		LLSDSerialize::fromXML(fav_llsd, in_file); +	} + +	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + +	LLSD user_llsd; +	for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) +	{ +		LLSD value; +		value["name"] = (*it)->getName(); +		value["asset_id"] = (*it)->getAssetUUID(); + +		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); +		if (slurl_iter != mSLURLs.end()) +		{ +			value["slurl"] = slurl_iter->second; +			user_llsd[(*it)->getSortField()] = value; +		} +	} + +	LLAvatarName av_name; +	LLAvatarNameCache::get( gAgentID, &av_name ); +	fav_llsd[av_name.getLegacyName()] = user_llsd; + +	llofstream file; +	file.open(filename); +	LLSDSerialize::toPrettyXML(fav_llsd, file); +} + +void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) +{ +	if (!landmark) return; + +	LLVector3d pos_global; +	if (!landmark->getGlobalPos(pos_global)) +	{ +		// If global position was unknown on first getGlobalPos() call +		// it should be set for the subsequent calls. +		landmark->getGlobalPos(pos_global); +	} + +	if (!pos_global.isExactlyZero()) +	{ +		LLLandmarkActions::getSLURLfromPosGlobal(pos_global, +				boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); +	} +} + +void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) +{ +	mSLURLs[asset_id] = slurl; +} +  void LLFavoritesOrderStorage::save()  {  	// nothing to save if clean @@ -1581,6 +1681,12 @@ S32 LLViewerInventoryItem::getSortField() const  void LLViewerInventoryItem::setSortField(S32 sortField)  {  	LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); +	getSLURL(); +} + +void LLViewerInventoryItem::getSLURL() +{ +	LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID);  }  const LLPermissions& LLViewerInventoryItem::getPermissions() const diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 1af06a1be8..41542a4e0f 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -62,6 +62,7 @@ public:  	virtual const std::string& getName() const;  	virtual S32 getSortField() const;  	virtual void setSortField(S32 sortField); +	virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here.  	virtual const LLPermissions& getPermissions() const;  	virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied  	virtual const LLUUID& getCreatorUUID() const; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 75531cef8d..a152ab4aa0 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -913,6 +913,10 @@ U32 info_display_from_string(std::string info_display)  	{  		return LLPipeline::RENDER_DEBUG_BATCH_SIZE;  	} +	else if ("update type" == info_display) +	{ +		return LLPipeline::RENDER_DEBUG_UPDATE_TYPE; +	}  	else if ("texture anim" == info_display)  	{  		return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM; @@ -4204,9 +4208,9 @@ class LLObjectEnableReturn : public view_listener_t  					{  						virtual bool apply(LLViewerObject* obj)  						{ -							return (obj->isOverAgentOwnedLand() || -									obj->isOverGroupOwnedLand() || -									obj->permModify()); +							return  +								obj->permModify() || +								obj->isReturnable();  						}  					} func;  					const bool firstonly = true; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1209183229..bf550e9c70 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -241,13 +241,12 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe  	mState(0),  	mMedia(NULL),  	mClickAction(0), -	mObjectCost(0.f), -	mLinksetCost(0.f), -	mPhysicsCost(0.f),  	mLinksetPhysicsCost(0.f),  	mCostStale(true),  	mPhysicsShapeUnknown(true), -	mAttachmentItemID(LLUUID::null) +	mAttachmentItemID(LLUUID::null), +	mLastUpdateType(OUT_UNKNOWN), +	mLastUpdateCached(FALSE)  {  	if (!is_global)  	{ @@ -529,20 +528,23 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list)  // This method returns true if the object is over land owned by the  // agent. -BOOL LLViewerObject::isOverAgentOwnedLand() const +bool LLViewerObject::isReturnable()  { -	return mRegionp -		&& mRegionp->getParcelOverlay() -		&& mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion()); -} +	if (isAttachment()) +	{ +		return false; +	} +	std::vector<LLBBox> boxes; +	boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); +	for (child_list_t::iterator iter = mChildList.begin(); +		 iter != mChildList.end(); iter++) +	{ +		LLViewerObject* child = *iter; +		boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); +	} -// This method returns true if the object is over land owned by the -// agent. -BOOL LLViewerObject::isOverGroupOwnedLand() const -{ -	return mRegionp  -		&& mRegionp->getParcelOverlay() -		&& mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion()); +	return mRegionp +		&& mRegionp->objectIsReturnable(getPositionRegion(), boxes);  }  BOOL LLViewerObject::setParent(LLViewerObject* parent) @@ -5598,6 +5600,26 @@ void LLViewerObject::setAttachmentItemID(const LLUUID &id)  	mAttachmentItemID = id;  } +EObjectUpdateType LLViewerObject::getLastUpdateType() const +{ +	return mLastUpdateType; +} + +void LLViewerObject::setLastUpdateType(EObjectUpdateType last_update_type) +{ +	mLastUpdateType = last_update_type; +} + +BOOL LLViewerObject::getLastUpdateCached() const +{ +	return mLastUpdateCached; +} + +void LLViewerObject::setLastUpdateCached(BOOL last_update_cached) +{ +	mLastUpdateCached = last_update_cached; +} +  const LLUUID &LLViewerObject::extractAttachmentItemID()  {  	LLUUID item_id = LLUUID::null; @@ -5614,7 +5636,6 @@ const LLUUID &LLViewerObject::extractAttachmentItemID()  	return getAttachmentItemID();  } -  //virtual  LLVOAvatar* LLViewerObject::getAvatar() const  { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 3ba51a6448..8883272cde 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -77,6 +77,7 @@ typedef enum e_object_update_type  	OUT_TERSE_IMPROVED,  	OUT_FULL_COMPRESSED,  	OUT_FULL_CACHED, +	OUT_UNKNOWN,  } EObjectUpdateType; @@ -228,12 +229,9 @@ public:  	virtual BOOL hasLightTexture() const			{ return FALSE; }  	// This method returns true if the object is over land owned by -	// the agent. -	BOOL isOverAgentOwnedLand() const; - -	// True if over land owned by group of which the agent is -	// either officer or member. -	BOOL isOverGroupOwnedLand() const; +	// the agent, one of its groups, or it encroaches and  +	// anti-encroachment is enabled +	bool isReturnable();  	/*  	// This method will scan through this object, and then query the @@ -746,8 +744,15 @@ public:  	const LLUUID &getAttachmentItemID() const;  	void setAttachmentItemID(const LLUUID &id);  	const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object +	EObjectUpdateType getLastUpdateType() const; +	void setLastUpdateType(EObjectUpdateType last_update_type); +	BOOL getLastUpdateCached() const; +	void setLastUpdateCached(BOOL last_update_cached); +  private:  	LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory. +	EObjectUpdateType	mLastUpdateType; +	BOOL	mLastUpdateCached;  };  /////////////////// diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index e4da9cca04..ca32ee4202 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -57,6 +57,7 @@  #include "llsdutil.h"  #include "llviewerregion.h"  #include "llviewerstats.h" +#include "llviewerstatsrecorder.h"  #include "llvoavatarself.h"  #include "lltoolmgr.h"  #include "lltoolpie.h" @@ -303,8 +304,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  	// have to transform to absolute coordinates.  	num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); +	// I don't think this case is ever hit.  TODO* Test this.  	if (!cached && !compressed && update_type != OUT_FULL)  	{ +		//llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl;  		gTerseObjectUpdates += num_objects;  		S32 size;  		if (mesgsys->getReceiveCompressedSize()) @@ -315,7 +318,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  		{  			size = mesgsys->getReceiveSize();  		} -		// llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; +		//llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;  	}  	else  	{ @@ -346,9 +349,14 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  	U8 compressed_dpbuffer[2048];  	LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);  	LLDataPacker *cached_dpp = NULL; -	 + +#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(regionp); +#endif +  	for (i = 0; i < num_objects; i++)  	{ +		// timer is unused?  		LLTimer update_timer;  		BOOL justCreated = FALSE; @@ -360,9 +368,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);  			// Lookup data packer and add this id to cache miss lists if necessary. -			cached_dpp = regionp->getDP(id, crc); +			U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; +			cached_dpp = regionp->getDP(id, crc, cache_miss_type);  			if (cached_dpp)  			{ +				// Cache Hit.  				cached_dpp->reset();  				cached_dpp->unpackUUID(fullid, "ID");  				cached_dpp->unpackU32(local_id, "LocalID"); @@ -370,6 +380,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			}  			else  			{ +				// Cache Miss. +				#if LL_RECORD_VIEWER_STATS +				LLViewerStatsRecorder::instance()->recordCacheMissEvent(id, update_type, cache_miss_type); +				#endif +  				continue; // no data packer, skip this object  			}  		} @@ -381,13 +396,15 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			compressed_dp.reset();  			U32 flags = 0; -			if (update_type != OUT_TERSE_IMPROVED) +			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?  			{  				mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);  			} +			// I don't think we ever use this flag from the server.  DK 2010/12/09  			if (flags & FLAGS_ZLIB_COMPRESSED)  			{ +				//llinfos << "TEST: flags & FLAGS_ZLIB_COMPRESSED" << llendl;  				compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);  				mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i);  				uncompressed_length = 2048; @@ -403,7 +420,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			} -			if (update_type != OUT_TERSE_IMPROVED) +			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?  			{  				compressed_dp.unpackUUID(fullid, "ID");  				compressed_dp.unpackU32(local_id, "LocalID"); @@ -423,7 +440,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  				}  			}  		} -		else if (update_type != OUT_FULL) +		else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only?  		{  			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);  			getUUIDFromLocal(fullid, @@ -436,7 +453,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  				mNumUnknownUpdates++;  			}  		} -		else +		else // OUT_FULL only?  		{  			mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);  			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); @@ -468,12 +485,12 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  							gMessageSystem->getSenderPort());  			if (objectp->mLocalID != local_id) -			{    // Update local ID in object with the one sent from the region +			{	// Update local ID in object with the one sent from the region  				objectp->mLocalID = local_id;  			}  			if (objectp->getRegion() != regionp) -			{    // Object changed region, so update it +			{	// Object changed region, so update it  				objectp->updateRegion(regionp); // for LLVOAvatar  			}  		} @@ -484,18 +501,24 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			{  				if (update_type == OUT_TERSE_IMPROVED)  				{ -					// llinfos << "terse update for an unknown object:" << fullid << llendl; +					// llinfos << "terse update for an unknown object (compressed):" << fullid << llendl; +					#if LL_RECORD_VIEWER_STATS +					LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); +					#endif  					continue;  				}  			} -			else if (cached) +			else if (cached) // Cache hit only?  			{  			}  			else  			{  				if (update_type != OUT_FULL)  				{ -					// llinfos << "terse update for an unknown object:" << fullid << llendl; +					//llinfos << "terse update for an unknown object:" << fullid << llendl; +					#if LL_RECORD_VIEWER_STATS +					LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); +					#endif  					continue;  				} @@ -505,7 +528,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			if (mDeadObjects.find(fullid) != mDeadObjects.end())  			{  				mNumDeadObjectUpdates++; -				// llinfos << "update for a dead object:" << fullid << llendl; +				//llinfos << "update for a dead object:" << fullid << llendl; +				#if LL_RECORD_VIEWER_STATS +				LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); +				#endif  				continue;  			}  #endif @@ -513,6 +539,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());  			if (!objectp)  			{ +				llinfos << "createObject failure for object: " << fullid << llendl; +				#if LL_RECORD_VIEWER_STATS +				LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); +				#endif  				continue;  			}  			justCreated = TRUE; @@ -525,19 +555,26 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;  		} +		bool bCached = false;  		if (compressed)  		{ -			if (update_type != OUT_TERSE_IMPROVED) +			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?  			{  				objectp->mLocalID = local_id;  			}  			processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); -			if (update_type != OUT_TERSE_IMPROVED) +			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?  			{ +				bCached = true; +				#if LL_RECORD_VIEWER_STATS +				LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); +				LLViewerStatsRecorder::instance()->recordCacheFullUpdate(local_id, update_type, result, objectp); +				#else  				objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); +				#endif  			}  		} -		else if (cached) +		else if (cached) // Cache hit only?  		{  			objectp->mLocalID = local_id;  			processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated); @@ -550,8 +587,17 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			}  			processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated);  		} +		#if LL_RECORD_VIEWER_STATS +		LLViewerStatsRecorder::instance()->recordObjectUpdateEvent(local_id, update_type, objectp); +		#endif +		objectp->setLastUpdateType(update_type); +		objectp->setLastUpdateCached(bCached);  	} +#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); +#endif +  	LLVOAvatar::cullAvatarsByPixelArea();  } @@ -865,12 +911,12 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  	// update global timer  	F32 last_time = gFrameTimeSeconds; -	U64 time = totalTime();                 // this will become the new gFrameTime when the update is done +	U64 time = totalTime();				 // this will become the new gFrameTime when the update is done  	// Time _can_ go backwards, for example if the user changes the system clock.  	// It doesn't cause any fatal problems (just some oddness with stats), so we shouldn't assert here.  //	llassert(time > gFrameTime);  	F64 time_diff = U64_to_F64(time - gFrameTime)/(F64)SEC_TO_MICROSEC; -	gFrameTime    = time; +	gFrameTime	= time;  	F64 time_since_start = U64_to_F64(gFrameTime - gStartTime)/(F64)SEC_TO_MICROSEC;  	gFrameTimeSeconds = (F32)time_since_start; @@ -975,7 +1021,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  		{  			std::string id_str;  			objectp->mID.toString(id_str); -			std::string tmpstr = std::string("Par:    ") + id_str; +			std::string tmpstr = std::string("Par:	") + id_str;  			addDebugBeacon(objectp->getPositionAgent(),  							tmpstr,  							LLColor4(1.f,0.f,0.f,1.f), @@ -995,12 +1041,12 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  			std::string tmpstr;  			if (objectp->getParent())  			{ -				tmpstr = std::string("ChP:    ") + id_str; +				tmpstr = std::string("ChP:	") + id_str;  				text_color = LLColor4(0.f, 1.f, 0.f, 1.f);  			}  			else  			{ -				tmpstr = std::string("ChNoP:    ") + id_str; +				tmpstr = std::string("ChNoP:	") + id_str;  				text_color = LLColor4(1.f, 0.f, 0.f, 1.f);  			}  			id = sIndexAndLocalIDToUUID[oi.mParentInfo]; @@ -1885,8 +1931,8 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)  			llinfos << "Agent: " << objectp->getPositionAgent() << llendl;  			addDebugBeacon(objectp->getPositionAgent(),"");  #endif -            gPipeline.markMoved(objectp->mDrawable);                 -            objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE); +			gPipeline.markMoved(objectp->mDrawable);				 +			objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE);  			// Flag the object as no longer orphaned  			childp->mOrphaned = FALSE; diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index eee653b0c1..d07e06f6a7 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -145,6 +145,35 @@ BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const  	return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay);  } +bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) const +{ +	// boxes are expected to already be axis aligned +	for (U32 i = 0; i < boxes.size(); ++i) +	{ +		LLVector3 min = boxes[i].getMinAgent(); +		LLVector3 max = boxes[i].getMaxAgent(); +		 +		S32 left   = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 right  = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 top    = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +	 +		for (S32 row = top; row <= bottom; row++) +		{ +			for (S32 column = left; column <= right; column++) +			{ +				U8 type = ownership(row, column); +				if ((PARCEL_SELF == type) +					|| (PARCEL_GROUP == type)) +				{ +					return true; +				} +			} +		} +	} +	return false; +} +  BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const  {  	S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS); diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 61be220312..c80baedda6 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -30,6 +30,7 @@  // The ownership data for land parcels.  // One of these structures per region. +#include "llbbox.h"  #include "lldarray.h"  #include "llframetimer.h"  #include "lluuid.h" @@ -54,6 +55,12 @@ public:  	BOOL			isOwnedSelf(const LLVector3& pos) const;  	BOOL			isOwnedGroup(const LLVector3& pos) const;  	BOOL			isOwnedOther(const LLVector3& pos) const; + +	// "encroaches" means the prim hangs over the parcel, but its center +	// might be in another parcel. for now, we simply test axis aligned  +	// bounding boxes which isn't perfect, but is close +	bool encroachesOwned(const std::vector<LLBBox>& boxes) const; +	  	BOOL			isSoundLocal(const LLVector3& pos) const;  	BOOL			isBuildCameraAllowed(const LLVector3& pos) const; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index a90c90a774..7fd6979702 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -59,6 +59,7 @@  #include "llurldispatcher.h"  #include "llviewerobjectlist.h"  #include "llviewerparceloverlay.h" +#include "llviewerstatsrecorder.h"  #include "llvlmanager.h"  #include "llvlcomposition.h"  #include "llvocache.h" @@ -1032,7 +1033,7 @@ void LLViewerRegion::getInfo(LLSD& info)  	info["Region"]["Handle"]["y"] = (LLSD::Integer)y;  } -void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp) +LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)  {  	U32 local_id = objectp->getLocalID();  	U32 crc = objectp->getCRC(); @@ -1046,35 +1047,36 @@ void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinary  		{  			// Record a hit  			entry->recordDupe(); +			return CACHE_UPDATE_DUPE;  		} -		else -		{ -			// Update the cache entry -			mCacheMap.erase(local_id); -			delete entry; -			entry = new LLVOCacheEntry(local_id, crc, dp); -			mCacheMap[local_id] = entry; -		} -	} -	else -	{ -		// we haven't seen this object before -		// Create new entry and add to map -		if (mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) -		{ -			mCacheMap.erase(mCacheMap.begin()); -		} +		// Update the cache entry +		mCacheMap.erase(local_id); +		delete entry;  		entry = new LLVOCacheEntry(local_id, crc, dp); -  		mCacheMap[local_id] = entry; +		return CACHE_UPDATE_CHANGED; +	} + +	// we haven't seen this object before + +	// Create new entry and add to map +	eCacheUpdateResult result = CACHE_UPDATE_ADDED; +	if (mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) +	{ +		mCacheMap.erase(mCacheMap.begin()); +		result = CACHE_UPDATE_REPLACED; +		  	} -	return ; +	entry = new LLVOCacheEntry(local_id, crc, dp); + +	mCacheMap[local_id] = entry; +	return result;  }  // Get data packer for this object, if we have cached data  // AND the CRC matches. JC -LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc) +LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type)  {  	//llassert(mCacheLoaded);  This assert failes often, changing to early-out -- davep, 2010/10/18 @@ -1089,17 +1091,20 @@ LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc)  			{  				// Record a hit  				entry->recordHit(); +			cache_miss_type = CACHE_MISS_TYPE_NONE;  				return entry->getDP(crc);  			}  			else  			{  				// llinfos << "CRC miss for " << local_id << llendl; +			cache_miss_type = CACHE_MISS_TYPE_CRC;  				mCacheMissCRC.put(local_id);  			}  		}  		else  		{  			// llinfos << "Cache miss for " << local_id << llendl; +		cache_miss_type = CACHE_MISS_TYPE_FULL;  			mCacheMissFull.put(local_id);  		}  	} @@ -1122,9 +1127,6 @@ void LLViewerRegion::requestCacheMisses()  	S32 blocks = 0;  	S32 i; -	const U8 CACHE_MISS_TYPE_FULL = 0; -	const U8 CACHE_MISS_TYPE_CRC  = 1; -  	// Send full cache miss updates.  For these, we KNOW we don't  	// have a viewer object.  	for (i = 0; i < full_count; i++) @@ -1187,6 +1189,11 @@ void LLViewerRegion::requestCacheMisses()  	mCacheDirty = TRUE ;  	// llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl; +	#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this); +	LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count); +	LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); +	#endif  }  void LLViewerRegion::dumpCache() @@ -1375,11 +1382,12 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("DispatchRegionInfo");  	capabilityNames.append("EstateChangeInfo");  	capabilityNames.append("EventQueueGet"); -	capabilityNames.append("FetchInventory");  	capabilityNames.append("ObjectMedia");  	capabilityNames.append("ObjectMediaNavigate"); -	capabilityNames.append("FetchLib"); -	capabilityNames.append("FetchLibDescendents"); +	capabilityNames.append("FetchLib2"); +	capabilityNames.append("FetchLibDescendents2"); +	capabilityNames.append("FetchInventory2"); +	capabilityNames.append("FetchInventoryDescendents2");  	capabilityNames.append("GetDisplayNames");  	capabilityNames.append("GetTexture");  	capabilityNames.append("GetMesh"); @@ -1410,7 +1418,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("SimConsole");  	capabilityNames.append("SimulatorFeatures");  	capabilityNames.append("SetDisplayName"); -	capabilityNames.append("SimConsole");  	capabilityNames.append("SimConsoleAsync");  	capabilityNames.append("StartGroupProposal");  	capabilityNames.append("TextureStats"); @@ -1428,7 +1435,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("ViewerMetrics");  	capabilityNames.append("ViewerStartAuction");  	capabilityNames.append("ViewerStats"); -	capabilityNames.append("WebFetchInventoryDescendents");  	// Please add new capabilities alphabetically to reduce  	// merge conflicts. @@ -1509,6 +1515,20 @@ LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)  	return NULL;  } +// the viewer can not yet distinquish between normal- and estate-owned objects +// so we collapse these two bits and enable the UI if either are set +const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT +											| REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; + +bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const +{ +	return (mParcelOverlay != NULL) +		&& (mParcelOverlay->isOwnedSelf(pos) +			|| mParcelOverlay->isOwnedGroup(pos) +			|| ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) +				&& mParcelOverlay->encroachesOwned(boxes)) ); +} +  void LLViewerRegion::showReleaseNotes()  {  	std::string url = this->getCapability("ServerReleaseNotes"); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 8b71998f60..7c6559203e 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -33,6 +33,7 @@  #include "lldarray.h"  #include "llwind.h" +#include "llbbox.h"  #include "llcloud.h"  #include "llstat.h"  #include "v3dmath.h" @@ -50,7 +51,7 @@  // Surface id's  #define LAND  1  #define WATER 2 -const U32	MAX_OBJECT_CACHE_ENTRIES = 10000; +const U32	MAX_OBJECT_CACHE_ENTRIES = 50000;  class LLEventPoll; @@ -274,9 +275,24 @@ public:  	void getInfo(LLSD& info); +	typedef enum +	{ +		CACHE_MISS_TYPE_FULL = 0, +		CACHE_MISS_TYPE_CRC, +		CACHE_MISS_TYPE_NONE +	} eCacheMissType; + +	typedef enum +	{ +		CACHE_UPDATE_DUPE = 0, +		CACHE_UPDATE_CHANGED, +		CACHE_UPDATE_ADDED, +		CACHE_UPDATE_REPLACED +	} eCacheUpdateResult; +  	// handle a full update message -	void cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp); -	LLDataPacker *getDP(U32 local_id, U32 crc); +	eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp); +	LLDataPacker *getDP(U32 local_id, U32 crc, U8 &cache_miss_type);  	void requestCacheMisses();  	void addCacheMissFull(const U32 local_id); @@ -293,6 +309,8 @@ public:  	std::string getHttpUrl() const { return mHttpUrl ;}  	LLSpatialPartition* getSpatialPartition(U32 type); + +	bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;  public:  	struct CompareDistance  	{ diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp new file mode 100644 index 0000000000..e9d21b4848 --- /dev/null +++ b/indra/newview/llviewerstatsrecorder.cpp @@ -0,0 +1,258 @@ +/** + * @file llviewerstatsrecorder.cpp + * @brief record info about viewer events to a metrics log file + * + * $LicenseInfo:firstyear=2010&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 "llviewerstatsrecorder.h" + +#if LL_RECORD_VIEWER_STATS + +#include "llfile.h" +#include "llviewerregion.h" +#include "llviewerobject.h" + + +// To do - something using region name or global position +#if LL_WINDOWS +	static const std::string STATS_FILE_NAME("C:\\ViewerObjectCacheStats.csv"); +#else +	static const std::string STATS_FILE_NAME("/tmp/viewerstats.csv"); +#endif + +LLViewerStatsRecorder* LLViewerStatsRecorder::sInstance = NULL; +LLViewerStatsRecorder::LLViewerStatsRecorder() : +	mObjectCacheFile(NULL), +	mTimer(), +	mRegionp(NULL), +	mStartTime(0.f), +	mProcessingTime(0.f) +{ +	if (NULL != sInstance) +	{ +		llerrs << "Attempted to create multiple instances of LLViewerStatsRecorder!" << llendl; +	} +	sInstance = this; +	clearStats(); +} + +LLViewerStatsRecorder::~LLViewerStatsRecorder() +{ +	if (mObjectCacheFile != NULL) +	{ +		LLFile::close(mObjectCacheFile); +		mObjectCacheFile = NULL; +	} +} + +// static +void LLViewerStatsRecorder::initClass() +{ +	sInstance = new LLViewerStatsRecorder(); +} + +// static +void LLViewerStatsRecorder::cleanupClass() +{ +	delete sInstance; +	sInstance = NULL; +} + + +void LLViewerStatsRecorder::initStatsRecorder(LLViewerRegion *regionp) +{ +	if (mObjectCacheFile == NULL) +	{ +		mStartTime = LLTimer::getTotalTime(); +		mObjectCacheFile = LLFile::fopen(STATS_FILE_NAME, "wb"); +		if (mObjectCacheFile) +		{	// Write column headers +			std::ostringstream data_msg; +			data_msg << "EventTime, " +				<< "ProcessingTime, " +				<< "CacheHits, " +				<< "CacheFullMisses, " +				<< "CacheCrcMisses, " +				<< "FullUpdates, " +				<< "TerseUpdates, " +				<< "CacheMissRequests, " +				<< "CacheMissResponses, " +				<< "CacheUpdateDupes, " +				<< "CacheUpdateChanges, " +				<< "CacheUpdateAdds, " +				<< "CacheUpdateReplacements, " +				<< "UpdateFailures" +				<< "\n"; + +			fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); +		} +	} +} + +void LLViewerStatsRecorder::beginObjectUpdateEvents(LLViewerRegion *regionp) +{ +	initStatsRecorder(regionp); +	mRegionp = regionp; +	mProcessingTime = LLTimer::getTotalTime(); +	clearStats(); +} + +void LLViewerStatsRecorder::clearStats() +{ +	mObjectCacheHitCount = 0; +	mObjectCacheMissFullCount = 0; +	mObjectCacheMissCrcCount = 0; +	mObjectFullUpdates = 0; +	mObjectTerseUpdates = 0; +	mObjectCacheMissRequests = 0; +	mObjectCacheMissResponses = 0; +	mObjectCacheUpdateDupes = 0; +	mObjectCacheUpdateChanges = 0; +	mObjectCacheUpdateAdds = 0; +	mObjectCacheUpdateReplacements = 0; +	mObjectUpdateFailures = 0; +} + + +void LLViewerStatsRecorder::recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type) +{ +	mObjectUpdateFailures++; +} + +void LLViewerStatsRecorder::recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type) +{ +	if (LLViewerRegion::CACHE_MISS_TYPE_FULL == cache_miss_type) +	{ +		mObjectCacheMissFullCount++; +	} +	else +	{ +		mObjectCacheMissCrcCount++; +	} +} + +void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp) +{ +	switch (update_type) +	{ +	case OUT_FULL: +		mObjectFullUpdates++; +		break; +	case OUT_TERSE_IMPROVED: +		mObjectTerseUpdates++; +		break; +	case OUT_FULL_COMPRESSED: +		mObjectCacheMissResponses++; +		break; +	case OUT_FULL_CACHED: +		mObjectCacheHitCount++; +		break; +	default: +		llwarns << "Unknown update_type" << llendl; +		break; +	}; +} + +void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp) +{ +	switch (update_result) +	{ +		case LLViewerRegion::CACHE_UPDATE_DUPE: +			mObjectCacheUpdateDupes++; +			break; +		case LLViewerRegion::CACHE_UPDATE_CHANGED: +			mObjectCacheUpdateChanges++; +			break; +		case LLViewerRegion::CACHE_UPDATE_ADDED: +			mObjectCacheUpdateAdds++; +			break; +		case LLViewerRegion::CACHE_UPDATE_REPLACED: +			mObjectCacheUpdateReplacements++; +			break; +		default: +			llwarns << "Unknown update_result type" << llendl; +			break; +	}; +} + +void LLViewerStatsRecorder::recordRequestCacheMissesEvent(S32 count) +{ +	mObjectCacheMissRequests += count; +} + +void LLViewerStatsRecorder::endObjectUpdateEvents() +{ +	llinfos << "ILX: "  +		<< mObjectCacheHitCount << " hits, "  +		<< mObjectCacheMissFullCount << " full misses, " +		<< mObjectCacheMissCrcCount << " crc misses, " +		<< mObjectFullUpdates << " full updates, " +		<< mObjectTerseUpdates << " terse updates, " +		<< mObjectCacheMissRequests << " cache miss requests, " +		<< mObjectCacheMissResponses << " cache miss responses, " +		<< mObjectCacheUpdateDupes << " cache update dupes, " +		<< mObjectCacheUpdateChanges << " cache update changes, " +		<< mObjectCacheUpdateAdds << " cache update adds, " +		<< mObjectCacheUpdateReplacements << " cache update replacements, " +		<< mObjectUpdateFailures << " update failures" +		<< llendl; + +	S32 total_objects = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures; +	if (mObjectCacheFile != NULL && +		total_objects > 0) +	{ +		std::ostringstream data_msg; +		F32 processing32 = (F32) ((LLTimer::getTotalTime() - mProcessingTime) / 1000.0); + +		data_msg << getTimeSinceStart() +			<< ", " << processing32 +			<< ", " << mObjectCacheHitCount +			<< ", " << mObjectCacheMissFullCount +			<< ", " << mObjectCacheMissCrcCount +			<< ", " << mObjectFullUpdates +			<< ", " << mObjectTerseUpdates +			<< ", " << mObjectCacheMissRequests +			<< ", " << mObjectCacheMissResponses +			<< ", " << mObjectCacheUpdateDupes +			<< ", " << mObjectCacheUpdateChanges +			<< ", " << mObjectCacheUpdateAdds +			<< ", " << mObjectCacheUpdateReplacements +			<< ", " << mObjectUpdateFailures +			<< "\n"; + +		fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); +	} + +	clearStats(); +} + +F32 LLViewerStatsRecorder::getTimeSinceStart() +{ +	return (F32) ((LLTimer::getTotalTime() - mStartTime) / 1000.0); +} + +#endif + + + diff --git a/indra/newview/llviewerstatsrecorder.h b/indra/newview/llviewerstatsrecorder.h new file mode 100644 index 0000000000..612ac380f7 --- /dev/null +++ b/indra/newview/llviewerstatsrecorder.h @@ -0,0 +1,97 @@ +/** + * @file llviewerstatsrecorder.h + * @brief record info about viewer events to a metrics log file + * + * $LicenseInfo:firstyear=2010&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 LLVIEWERSTATSRECORDER_H +#define LLVIEWERSTATSRECORDER_H + + +// This is a diagnostic class used to record information from the viewer +// for analysis. + +// This is normally 0.  Set to 1 to enable viewer stats recording +#define LL_RECORD_VIEWER_STATS	0 + + +#if LL_RECORD_VIEWER_STATS +#include "llframetimer.h" +#include "llviewerobject.h" +#include "llviewerregion.h" + +class LLMutex; +class LLViewerRegion; +class LLViewerObject; + +class LLViewerStatsRecorder +{ + public: +	LLViewerStatsRecorder(); +	~LLViewerStatsRecorder(); + +	static void initClass(); +	static void cleanupClass(); +	static LLViewerStatsRecorder* instance() {return sInstance; } + +	void initStatsRecorder(LLViewerRegion *regionp); + +	void beginObjectUpdateEvents(LLViewerRegion *regionp); +	void recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type); +	void recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type); +	void recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp); +	void recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp); +	void recordRequestCacheMissesEvent(S32 count); +	void endObjectUpdateEvents(); + +	F32 getTimeSinceStart(); + +private: +	static LLViewerStatsRecorder* sInstance; + +	LLFILE *	mObjectCacheFile;		// File to write data into +	LLFrameTimer	mTimer; +	LLViewerRegion*	mRegionp; +	F64			mStartTime; +	F64			mProcessingTime; + +	S32			mObjectCacheHitCount; +	S32			mObjectCacheMissFullCount; +	S32			mObjectCacheMissCrcCount; +	S32			mObjectFullUpdates; +	S32			mObjectTerseUpdates; +	S32			mObjectCacheMissRequests; +	S32			mObjectCacheMissResponses; +	S32			mObjectCacheUpdateDupes; +	S32			mObjectCacheUpdateChanges; +	S32			mObjectCacheUpdateAdds; +	S32			mObjectCacheUpdateReplacements; +	S32			mObjectUpdateFailures; + + +	void	clearStats(); +}; +#endif	// LL_RECORD_VIEWER_STATS + +#endif // LLVIEWERSTATSRECORDER_H + diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index ded3e36cf6..feb6db4700 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2128,31 +2128,6 @@ void LLVOAvatar::computeBodySize()  			gAgent.sendAgentSetAppearance();  		}  	} - -/* debug spam -	std::cout << "skull = " << skull << std::endl;				// adebug -	std::cout << "head = " << head << std::endl;				// adebug -	std::cout << "head_scale = " << head_scale << std::endl;	// adebug -	std::cout << "neck = " << neck << std::endl;				// adebug -	std::cout << "neck_scale = " << neck_scale << std::endl;	// adebug -	std::cout << "chest = " << chest << std::endl;				// adebug -	std::cout << "chest_scale = " << chest_scale << std::endl;	// adebug -	std::cout << "torso = " << torso << std::endl;				// adebug -	std::cout << "torso_scale = " << torso_scale << std::endl;	// adebug -	std::cout << std::endl;	// adebug - -	std::cout << "pelvis_scale = " << pelvis_scale << std::endl;// adebug -	std::cout << std::endl;	// adebug - -	std::cout << "hip = " << hip << std::endl;					// adebug -	std::cout << "hip_scale = " << hip_scale << std::endl;		// adebug -	std::cout << "ankle = " << ankle << std::endl;				// adebug -	std::cout << "ankle_scale = " << ankle_scale << std::endl;	// adebug -	std::cout << "foot = " << foot << std::endl;				// adebug -	std::cout << "mBodySize = " << mBodySize << std::endl;		// adebug -	std::cout << "mPelvisToFoot = " << mPelvisToFoot << std::endl;	// adebug -	std::cout << std::endl;		// adebug -*/  }  //------------------------------------------------------------------------ @@ -2446,9 +2421,19 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  		// here we get the approximate head position and set as sound source for the voice symbol  		// (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing)  		//-------------------------------------------------------------------------------------------- -		LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); -		mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset ); +		if ( mIsSitting ) +		{ +			LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); +			mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset ); +		} +		else  +		{ +			LLVector3 tagPos = mRoot.getWorldPosition(); +			tagPos[VZ] -= mPelvisToFoot; +			tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); +			mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); +		}  	}//if ( voiceEnabled )  }		 @@ -2895,10 +2880,8 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)  				}  	LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); -	mNameText->setPositionAgent(name_position); -				 -	idleUpdateNameTagText(new_name); -			 +	mNameText->setPositionAgent(name_position);				 +	idleUpdateNameTagText(new_name);			  	idleUpdateNameTagAlpha(new_name, alpha);  } @@ -3184,8 +3167,9 @@ void LLVOAvatar::invalidateNameTags()  		if (avatar->isDead()) continue;  		avatar->clearNameTag(); -				} -			} + +	} +}  // Compute name tag position during idle update  LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) @@ -3204,12 +3188,14 @@ LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)  	local_camera_up.scaleVec(mBodySize * 0.5f);  	local_camera_at.scaleVec(mBodySize * 0.5f); -	LLVector3 name_position = mRoot.getWorldPosition() +  -		(local_camera_up * root_rot) - -		(projected_vec(local_camera_at * root_rot, camera_to_av)); +	LLVector3 name_position = mRoot.getWorldPosition(); +	name_position[VZ] -= mPelvisToFoot; +	name_position[VZ] += (mBodySize[VZ]* 0.55f); +	name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av));	  	name_position += pixel_up_vec * 15.f; +  	return name_position; -		} +}  void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha)  { @@ -6026,6 +6012,34 @@ void LLVOAvatar::rebuildRiggedAttachments( void )  	}  }  //----------------------------------------------------------------------------- +// cleanupAttachedMesh() +//----------------------------------------------------------------------------- +void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) +{ +	//If a VO has a skin that we'll reset the joint positions to their default +	if ( pVO && pVO->mDrawable ) +	{ +		LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); +		if ( pVObj ) +		{ +			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID() ); +			if ( pSkinData ) +			{ +				const int jointCnt = pSkinData->mJointNames.size(); +				bool fullRig = ( jointCnt>=20 ) ? true : false; +				if ( fullRig ) +				{ +					const int bindCnt = pSkinData->mAlternateBindMatrix.size();							 +					if ( bindCnt > 0 ) +					{ +						LLVOAvatar::resetJointPositionsToDefault(); +					} +				} +			}				 +		} +	}	 +} +//-----------------------------------------------------------------------------  // detachObject()  //-----------------------------------------------------------------------------  BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) @@ -6035,9 +6049,10 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)  		 ++iter)  	{  		LLViewerJointAttachment* attachment = iter->second; - +		  		if (attachment->isObjectAttached(viewer_object))  		{ +			cleanupAttachedMesh( viewer_object );  			attachment->removeObject(viewer_object);  			lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl;  			return TRUE; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index ce5ce045b9..7ef35178ca 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -687,6 +687,7 @@ public:  	void 				clampAttachmentPositions();
  	virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
  	virtual BOOL 		detachObject(LLViewerObject *viewer_object);
 +	void				cleanupAttachedMesh( LLViewerObject* pVO );
  	static LLVOAvatar*  findAvatarFromAttachment(LLViewerObject* obj);
  protected:
  	LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object);
 diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 5d1020fce8..3c66c4860e 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1150,28 +1150,7 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object)  	const LLUUID attachment_id = viewer_object->getAttachmentItemID();  	if ( LLVOAvatar::detachObject(viewer_object) )  	{ -		//If a VO has a skin that we'll reset the joint positions to their default -		if ( viewer_object->mDrawable ) -		{ -			LLVOVolume* pVObj = viewer_object->mDrawable->getVOVolume(); -			if ( pVObj ) -			{ -				const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID() ); -				if ( pSkinData ) -				{ -					const int jointCnt = pSkinData->mJointNames.size(); -					bool fullRig = ( jointCnt>=20 ) ? true : false; -					if ( fullRig ) -					{ -						const int bindCnt = pSkinData->mAlternateBindMatrix.size();							 -						if ( bindCnt > 0 ) -						{ -							LLVOAvatar::resetJointPositionsToDefault(); -						} -					} -				}				 -			} -		} +		LLVOAvatar::cleanupAttachedMesh( viewer_object );  		// the simulator should automatically handle permission revocation diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 6ea88abab8..10d6b009ae 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -1,707 +1,719 @@ -/**  - * @file llvocache.cpp - * @brief Cache of objects on the viewer. - * - * $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 "llvocache.h" -#include "llerror.h" -#include "llregionhandle.h" -#include "llviewercontrol.h" - -BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes)  -{ -	return apr_file->read(src, n_bytes) == n_bytes ; -} - -BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes)  -{ -	return apr_file->write(src, n_bytes) == n_bytes ; -} - - -//--------------------------------------------------------------------------- -// LLVOCacheEntry -//--------------------------------------------------------------------------- - -LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp) -	: -	mLocalID(local_id), -	mCRC(crc), -	mHitCount(0), -	mDupeCount(0), -	mCRCChangeCount(0) -{ -	mBuffer = new U8[dp.getBufferSize()]; -	mDP.assignBuffer(mBuffer, dp.getBufferSize()); -	mDP = dp; -} - -LLVOCacheEntry::LLVOCacheEntry() -	: -	mLocalID(0), -	mCRC(0), -	mHitCount(0), -	mDupeCount(0), -	mCRCChangeCount(0), -	mBuffer(NULL) -{ -	mDP.assignBuffer(mBuffer, 0); -} - -LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) -{ -	S32 size = -1; -	BOOL success; - -	success = check_read(apr_file, &mLocalID, sizeof(U32)); -	if(success) -	{ -		success = check_read(apr_file, &mCRC, sizeof(U32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &mHitCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &mDupeCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &mCRCChangeCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &size, sizeof(S32)); - -		// Corruption in the cache entries -		if ((size > 10000) || (size < 1)) -		{ -			// We've got a bogus size, skip reading it. -			// We won't bother seeking, because the rest of this file -			// is likely bogus, and will be tossed anyway. -			llwarns << "Bogus cache entry, size " << size << ", aborting!" << llendl; -			success = FALSE; -		} -	} -	if(success && size > 0) -	{ -		mBuffer = new U8[size]; -		success = check_read(apr_file, mBuffer, size); - -		if(success) -		{ -			mDP.assignBuffer(mBuffer, size); -		} -		else -		{ -			delete[] mBuffer ; -			mBuffer = NULL ; -		} -	} - -	if(!success) -	{ -		mLocalID = 0; -		mCRC = 0; -		mHitCount = 0; -		mDupeCount = 0; -		mCRCChangeCount = 0; -		mBuffer = NULL; -	} -} - -LLVOCacheEntry::~LLVOCacheEntry() -{ -	delete [] mBuffer; -} - - -// New CRC means the object has changed. -void LLVOCacheEntry::assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp) -{ -	if (  (mCRC != crc) -		||(mDP.getBufferSize() == 0)) -	{ -		mCRC = crc; -		mHitCount = 0; -		mCRCChangeCount++; - -		mDP.freeBuffer(); -		mBuffer = new U8[dp.getBufferSize()]; -		mDP.assignBuffer(mBuffer, dp.getBufferSize()); -		mDP = dp; -	} -} - -LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc) -{ -	if (  (mCRC != crc) -		||(mDP.getBufferSize() == 0)) -	{ -		//llinfos << "Not getting cache entry, invalid!" << llendl; -		return NULL; -	} -	mHitCount++; -	return &mDP; -} - - -void LLVOCacheEntry::recordHit() -{ -	mHitCount++; -} - - -void LLVOCacheEntry::dump() const -{ -	llinfos << "local " << mLocalID -		<< " crc " << mCRC -		<< " hits " << mHitCount -		<< " dupes " << mDupeCount -		<< " change " << mCRCChangeCount -		<< llendl; -} - -BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const -{ -	BOOL success; -	success = check_write(apr_file, (void*)&mLocalID, sizeof(U32)); -	if(success) -	{ -		success = check_write(apr_file, (void*)&mCRC, sizeof(U32)); -	} -	if(success) -	{ -		success = check_write(apr_file, (void*)&mHitCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32)); -	} -	if(success) -	{ -		S32 size = mDP.getBufferSize(); -		success = check_write(apr_file, (void*)&size, sizeof(S32)); -	 -		if(success) -		{ -			success = check_write(apr_file, (void*)mBuffer, size); -		} -	} - -	return success ; -} - -//------------------------------------------------------------------- -//LLVOCache -//------------------------------------------------------------------- -// Format string used to construct filename for the object cache -static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; - -const U32 NUM_ENTRIES_TO_PURGE = 50; -const char* object_cache_dirname = "objectcache"; -const char* header_filename = "object.cache"; - -LLVOCache* LLVOCache::sInstance = NULL; - -//static  -LLVOCache* LLVOCache::getInstance()  -{	 -	if(!sInstance) -	{ -		sInstance = new LLVOCache() ; -	} -	return sInstance ; -} - -//static  -BOOL LLVOCache::hasInstance()  -{ -	return sInstance != NULL ; -} - -//static  -void LLVOCache::destroyClass()  -{ -	if(sInstance) -	{ -		delete sInstance ; -		sInstance = NULL ; -	} -} - -LLVOCache::LLVOCache(): -	mInitialized(FALSE), -	mReadOnly(TRUE), -	mCacheSize(1) -{ -	mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); -	mLocalAPRFilePoolp = new LLVolatileAPRPool() ; -} - -LLVOCache::~LLVOCache() -{ -	if(mEnabled) -	{ -		writeCacheHeader(); -		clearCacheInMemory(); -	} -	delete mLocalAPRFilePoolp; -} - -void LLVOCache::setDirNames(ELLPath location) -{ -	std::string delem = gDirUtilp->getDirDelimiter(); - -	mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename); -	mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname); -} - -void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) -{ -	if(!mEnabled) -	{ -		llwarns << "Not initializing cache: Cache is currently disabled." << llendl; -		return ; -	} - -	if(mInitialized) -	{ -		llwarns << "Cache already initialized." << llendl; -		return ; -	} - -	setDirNames(location); -	if (!mReadOnly) -	{ -		LLFile::mkdir(mObjectCacheDirName); -	} - -	mCacheSize = size; - -	mMetaInfo.mVersion = cache_version; -	readCacheHeader(); -	mInitialized = TRUE ; - -	if(mMetaInfo.mVersion != cache_version)  -	{ -		mMetaInfo.mVersion = cache_version ; -		if(mReadOnly) //disable cache -		{ -			clearCacheInMemory(); -		} -		else //delete the current cache if the format does not match. -		{			 -			removeCache(); -		} -	}	 -} -	 -void LLVOCache::removeCache(ELLPath location)  -{ -	if(mReadOnly) -	{ -		llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl; -		return ; -	} - -	std::string delem = gDirUtilp->getDirDelimiter(); -	std::string mask = delem + "*"; -	std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname); -	gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files -	LLFile::rmdir(cache_dir); - -	clearCacheInMemory(); -	mInitialized = FALSE ; -} - -void LLVOCache::removeCache()  -{ -	llassert_always(mInitialized) ; -	if(mReadOnly) -	{ -		llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl; -		return ; -	} - -	std::string delem = gDirUtilp->getDirDelimiter(); -	std::string mask = delem + "*"; -	gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask);  - -	clearCacheInMemory() ; -	writeCacheHeader(); -} - -void LLVOCache::clearCacheInMemory() -{ -	std::for_each(mHandleEntryMap.begin(), mHandleEntryMap.end(), DeletePairedPointer()); -	mHandleEntryMap.clear(); -} - -void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename)  -{ -	U32 region_x, region_y; - -	grid_from_region_handle(handle, ®ion_x, ®ion_y); -	filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname, -			   llformat(OBJECT_CACHE_FILENAME, region_x, region_y)); - -	return ; -} - -void LLVOCache::removeFromCache(U64 handle) -{ -	if(mReadOnly) -	{ -		llwarns << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << llendl; -		return ; -	} - -	std::string filename; -	getObjectCacheFilename(handle, filename); -	LLAPRFile::remove(filename, mLocalAPRFilePoolp);	 -} - -BOOL LLVOCache::checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes)  -{ -	if(!check_read(apr_file, src, n_bytes)) -	{ -		removeCache() ; -		return FALSE ; -	} - -	return TRUE ; -} - -BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes)  -{ -	if(!check_write(apr_file, src, n_bytes)) -	{ -		removeCache() ; -		return FALSE ; -	} - -	return TRUE ; -} - -void LLVOCache::readCacheHeader() -{ -	if(!mEnabled) -	{ -		llwarns << "Not reading cache header: Cache is currently disabled." << llendl; -		return; -	} - -	//clear stale info. -	clearCacheInMemory();	 - -	if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) -	{ -		LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp);		 -		 -		//read the meta element -		if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) -		{ -			llwarns << "Error reading meta information from cache header." << llendl; -			delete apr_file; -			return; -		} - -		HeaderEntryInfo* entry ; -		for(U32 entry_index = 0; entry_index < mCacheSize; ++entry_index) -		{ -			entry = new HeaderEntryInfo() ; -			if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo))) -			{ -				llwarns << "Error reading cache header entry. (entry_index=" << entry_index << ")" << llendl; -				delete entry ;			 -				break; -			} -			else if(!entry->mTime) //end of the cache. -			{ -				delete entry ; -				break; -			} - -			entry->mIndex = entry_index; -			mHandleEntryMap[entry->mHandle] = entry; -		} - -		delete apr_file ; -	} -	else -	{ -		writeCacheHeader() ; -	} -} - -void LLVOCache::writeCacheHeader() -{ -	if (!mEnabled) -	{ -		llwarns << "Not writing cache header: Cache is currently disabled." << llendl; -		return; -	} - -	if(mReadOnly) -	{ -		llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl; -		return; -	} - -	LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - -	//write the meta element -	if(!checkWrite(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) -	{ -		llwarns << "Error writing meta information to cache header." << llendl; -		delete apr_file; -		return; -	} - -	U32 entry_index = 0; -	handle_entry_map_t::iterator iter_end = mHandleEntryMap.end(); -	for(handle_entry_map_t::iterator iter = mHandleEntryMap.begin(); -		iter != iter_end; -		++iter) -	{ -		HeaderEntryInfo* entry = iter->second; -		entry->mIndex = entry_index++; -		if(!checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo))) -		{ -			llwarns << "Failed to write cache header for entry " << entry->mHandle << " (entry_index = " << entry_index << ")" << llendl; -			delete apr_file; -			return; -		} -	} - -	// Why do we need to fill the cache header with default entries?  DK 2010-12-14 -	// It looks like we currently rely on the file being pre-allocated so we can seek during updateEntry(). -	if(entry_index < mCacheSize) -	{ -		HeaderEntryInfo* entry = new HeaderEntryInfo() ; -		for(; entry_index < mCacheSize; ++entry_index) -		{ -			//fill the cache with the default entry. -			if(!checkWrite(apr_file, entry, sizeof(HeaderEntryInfo))) -			{ -				llwarns << "Failed to fill cache header with default entries (entry_index = " << entry_index << ").  Switching to read-only mode." << llendl; -				mReadOnly = TRUE ; //disable the cache. -				break; -			} -		} -		delete entry ; -	} -	delete apr_file ; -} - -BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) -{ -	LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); -	apr_file->seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; - -	BOOL result = checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; -	delete apr_file; -	return result; -} - -void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map)  -{ -	if(!mEnabled) -	{ -		llwarns << "Not reading cache for handle " << handle << "): Cache is currently disabled." << llendl; -		return ; -	} -	llassert_always(mInitialized); - -	handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; -	if(iter == mHandleEntryMap.end()) //no cache -	{ -		llwarns << "No handle map entry for " << handle << llendl; -		return ; -	} - -	std::string filename; -	getObjectCacheFilename(handle, filename); -	LLAPRFile* apr_file = new LLAPRFile(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); - -	LLUUID cache_id ; -	if(!checkRead(apr_file, cache_id.mData, UUID_BYTES)) -	{ -		llwarns << "Error reading cache_id from " << filename << llendl; -		delete apr_file; -		return ; -	} -	if(cache_id != id) -	{ -		llwarns << "Cache ID (" << cache_id << ") doesn't match id for this region (" << id << "), discarding.  handle = " << handle << llendl; -		delete apr_file ; -		return ; -	} - -	S32 num_entries; -	if(!checkRead(apr_file, &num_entries, sizeof(S32))) -	{ -		llwarns << "Error reading num_entries from " << filename << llendl; -		delete apr_file; -		return ; -	} -	 -	for (S32 i = 0; i < num_entries; i++) -	{ -		LLVOCacheEntry* entry = new LLVOCacheEntry(apr_file); -		if (!entry->getLocalID()) -		{ -			llwarns << "Aborting cache file load for " << filename << ", cache file corruption! (entry number = " << i << ")" << llendl; -			delete entry ; -			break; -		} -		cache_entry_map[entry->getLocalID()] = entry; -	} - -	delete apr_file ; -	return ; -} -	 -void LLVOCache::purgeEntries() -{ -	U32 limit = mCacheSize - NUM_ENTRIES_TO_PURGE ; -	// Construct a vector of entries out of the map so we can sort by time. -	std::vector<HeaderEntryInfo*> header_vector; -	handle_entry_map_t::iterator iter_end = mHandleEntryMap.end(); -	for (handle_entry_map_t::iterator iter = mHandleEntryMap.begin(); -		iter != iter_end; -		++iter) -	{ -		header_vector.push_back(iter->second); -	} -	// Sort by time, oldest first. -	std::sort(header_vector.begin(), header_vector.end(), header_entry_less()); -	while(header_vector.size() > limit) -	{ -		HeaderEntryInfo* entry = header_vector.front(); -		 -		removeFromCache(entry->mHandle); -		mHandleEntryMap.erase(entry->mHandle); -		header_vector.erase(header_vector.begin()); -		delete entry; -	} - -	writeCacheHeader() ; -	// *TODO: Verify that we can avoid re-reading the cache header.  DK 2010-12-14 -	readCacheHeader() ; -} - -void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache)  -{ -	if(!mEnabled) -	{ -		llwarns << "Not writing cache for handle " << handle << "): Cache is currently disabled." << llendl; -		return ; -	} -	llassert_always(mInitialized); - -	if(mReadOnly) -	{ -		llwarns << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << llendl; -		return ; -	} - -	HeaderEntryInfo* entry; -	handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; -	U32 num_handle_entries = mHandleEntryMap.size(); -	if(iter == mHandleEntryMap.end()) //new entry -	{ -		if(num_handle_entries >= mCacheSize) -		{ -			purgeEntries() ; -		} -		 -		entry = new HeaderEntryInfo(); -		entry->mHandle = handle ; -		entry->mTime = time(NULL) ; -		entry->mIndex = num_handle_entries++; -		mHandleEntryMap[handle] = entry ; -	} -	else -	{ -		// Update access time. -		entry = iter->second ; -		entry->mTime = time(NULL) ; -	} - -	//update cache header -	if(!updateEntry(entry)) -	{ -		llwarns << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << llendl; -		return ; //update failed. -	} - -	if(!dirty_cache) -	{ -		llwarns << "Skipping write to cache for handle " << handle << ": cache not dirty" << llendl; -		return ; //nothing changed, no need to update. -	} - -	//write to cache file -	std::string filename; -	getObjectCacheFilename(handle, filename); -	LLAPRFile* apr_file = new LLAPRFile(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); -	 -	if(!checkWrite(apr_file, (void*)id.mData, UUID_BYTES)) -	{ -		llwarns << "Error writing id to " << filename << llendl; -		delete apr_file; -		return ; -	} - -	S32 num_entries = cache_entry_map.size() ; -	if(!checkWrite(apr_file, &num_entries, sizeof(S32))) -	{ -		llwarns << "Error writing num_entries to " << filename << llendl; -		delete apr_file; -		return ; -	} - -	for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); iter != cache_entry_map.end(); ++iter) -	{ -		if(!iter->second->writeToFile(apr_file)) -		{ -			llwarns << "Aborting cache file write for " << filename << ", error writing to file!" << llendl; -			//failed -			removeCache() ; -			break; -		} -	} - -	delete apr_file ; -	return ; -} - +/** 
 + * @file llvocache.cpp
 + * @brief Cache of objects on the viewer.
 + *
 + * $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 "llvocache.h"
 +#include "llerror.h"
 +#include "llregionhandle.h"
 +#include "llviewercontrol.h"
 +
 +BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) 
 +{
 +	return apr_file->read(src, n_bytes) == n_bytes ;
 +}
 +
 +BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) 
 +{
 +	return apr_file->write(src, n_bytes) == n_bytes ;
 +}
 +
 +
 +//---------------------------------------------------------------------------
 +// LLVOCacheEntry
 +//---------------------------------------------------------------------------
 +
 +LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp)
 +	:
 +	mLocalID(local_id),
 +	mCRC(crc),
 +	mHitCount(0),
 +	mDupeCount(0),
 +	mCRCChangeCount(0)
 +{
 +	mBuffer = new U8[dp.getBufferSize()];
 +	mDP.assignBuffer(mBuffer, dp.getBufferSize());
 +	mDP = dp;
 +}
 +
 +LLVOCacheEntry::LLVOCacheEntry()
 +	:
 +	mLocalID(0),
 +	mCRC(0),
 +	mHitCount(0),
 +	mDupeCount(0),
 +	mCRCChangeCount(0),
 +	mBuffer(NULL)
 +{
 +	mDP.assignBuffer(mBuffer, 0);
 +}
 +
 +LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
 +{
 +	S32 size = -1;
 +	BOOL success;
 +
 +	success = check_read(apr_file, &mLocalID, sizeof(U32));
 +	if(success)
 +	{
 +		success = check_read(apr_file, &mCRC, sizeof(U32));
 +	}
 +	if(success)
 +	{
 +		success = check_read(apr_file, &mHitCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_read(apr_file, &mDupeCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_read(apr_file, &mCRCChangeCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_read(apr_file, &size, sizeof(S32));
 +
 +		// Corruption in the cache entries
 +		if ((size > 10000) || (size < 1))
 +		{
 +			// We've got a bogus size, skip reading it.
 +			// We won't bother seeking, because the rest of this file
 +			// is likely bogus, and will be tossed anyway.
 +			llwarns << "Bogus cache entry, size " << size << ", aborting!" << llendl;
 +			success = FALSE;
 +		}
 +	}
 +	if(success && size > 0)
 +	{
 +		mBuffer = new U8[size];
 +		success = check_read(apr_file, mBuffer, size);
 +
 +		if(success)
 +		{
 +			mDP.assignBuffer(mBuffer, size);
 +		}
 +		else
 +		{
 +			delete[] mBuffer ;
 +			mBuffer = NULL ;
 +		}
 +	}
 +
 +	if(!success)
 +	{
 +		mLocalID = 0;
 +		mCRC = 0;
 +		mHitCount = 0;
 +		mDupeCount = 0;
 +		mCRCChangeCount = 0;
 +		mBuffer = NULL;
 +	}
 +}
 +
 +LLVOCacheEntry::~LLVOCacheEntry()
 +{
 +	delete [] mBuffer;
 +}
 +
 +
 +// New CRC means the object has changed.
 +void LLVOCacheEntry::assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp)
 +{
 +	if (  (mCRC != crc)
 +		||(mDP.getBufferSize() == 0))
 +	{
 +		mCRC = crc;
 +		mHitCount = 0;
 +		mCRCChangeCount++;
 +
 +		mDP.freeBuffer();
 +		mBuffer = new U8[dp.getBufferSize()];
 +		mDP.assignBuffer(mBuffer, dp.getBufferSize());
 +		mDP = dp;
 +	}
 +}
 +
 +LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc)
 +{
 +	if (  (mCRC != crc)
 +		||(mDP.getBufferSize() == 0))
 +	{
 +		//llinfos << "Not getting cache entry, invalid!" << llendl;
 +		return NULL;
 +	}
 +	mHitCount++;
 +	return &mDP;
 +}
 +
 +
 +void LLVOCacheEntry::recordHit()
 +{
 +	mHitCount++;
 +}
 +
 +
 +void LLVOCacheEntry::dump() const
 +{
 +	llinfos << "local " << mLocalID
 +		<< " crc " << mCRC
 +		<< " hits " << mHitCount
 +		<< " dupes " << mDupeCount
 +		<< " change " << mCRCChangeCount
 +		<< llendl;
 +}
 +
 +BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
 +{
 +	BOOL success;
 +	success = check_write(apr_file, (void*)&mLocalID, sizeof(U32));
 +	if(success)
 +	{
 +		success = check_write(apr_file, (void*)&mCRC, sizeof(U32));
 +	}
 +	if(success)
 +	{
 +		success = check_write(apr_file, (void*)&mHitCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		S32 size = mDP.getBufferSize();
 +		success = check_write(apr_file, (void*)&size, sizeof(S32));
 +	
 +		if(success)
 +		{
 +			success = check_write(apr_file, (void*)mBuffer, size);
 +		}
 +	}
 +
 +	return success ;
 +}
 +
 +//-------------------------------------------------------------------
 +//LLVOCache
 +//-------------------------------------------------------------------
 +// Format string used to construct filename for the object cache
 +static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc";
 +
 +// Throw out 1/20 (5%) of our cache entries if we run out of room.
 +const U32 ENTRIES_PURGE_FACTOR = 20;
 +const char* object_cache_dirname = "objectcache";
 +const char* header_filename = "object.cache";
 +
 +LLVOCache* LLVOCache::sInstance = NULL;
 +
 +//static 
 +LLVOCache* LLVOCache::getInstance() 
 +{	
 +	if(!sInstance)
 +	{
 +		sInstance = new LLVOCache() ;
 +	}
 +	return sInstance ;
 +}
 +
 +//static 
 +BOOL LLVOCache::hasInstance() 
 +{
 +	return sInstance != NULL ;
 +}
 +
 +//static 
 +void LLVOCache::destroyClass() 
 +{
 +	if(sInstance)
 +	{
 +		delete sInstance ;
 +		sInstance = NULL ;
 +	}
 +}
 +
 +LLVOCache::LLVOCache():
 +	mInitialized(FALSE),
 +	mReadOnly(TRUE),
 +	mCacheSize(1)
 +{
 +	mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled");
 +	mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
 +}
 +
 +LLVOCache::~LLVOCache()
 +{
 +	if(mEnabled)
 +	{
 +		writeCacheHeader();
 +		clearCacheInMemory();
 +	}
 +	delete mLocalAPRFilePoolp;
 +}
 +
 +void LLVOCache::setDirNames(ELLPath location)
 +{
 +	std::string delem = gDirUtilp->getDirDelimiter();
 +
 +	mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename);
 +	mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname);
 +}
 +
 +void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version)
 +{
 +	if(!mEnabled)
 +	{
 +		llwarns << "Not initializing cache: Cache is currently disabled." << llendl;
 +		return ;
 +	}
 +
 +	if(mInitialized)
 +	{
 +		llwarns << "Cache already initialized." << llendl;
 +		return ;
 +	}
 +
 +	setDirNames(location);
 +	if (!mReadOnly)
 +	{
 +		LLFile::mkdir(mObjectCacheDirName);
 +	}
 +
 +	mCacheSize = size;
 +
 +	readCacheHeader();
 +	mInitialized = TRUE ;
 +
 +	if(mMetaInfo.mVersion != cache_version) 
 +	{
 +		mMetaInfo.mVersion = cache_version ;
 +		if(mReadOnly) //disable cache
 +		{
 +			clearCacheInMemory();
 +		}
 +		else //delete the current cache if the format does not match.
 +		{			
 +			removeCache();
 +		}
 +	}	
 +}
 +	
 +void LLVOCache::removeCache(ELLPath location) 
 +{
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl;
 +		return ;
 +	}
 +
 +	std::string delem = gDirUtilp->getDirDelimiter();
 +	std::string mask = delem + "*";
 +	std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname);
 +	llinfos << "Removing cache at " << cache_dir << llendl;
 +	gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files
 +	LLFile::rmdir(cache_dir);
 +
 +	clearCacheInMemory();
 +	mInitialized = FALSE ;
 +}
 +
 +void LLVOCache::removeCache() 
 +{
 +	llassert_always(mInitialized) ;
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl;
 +		return ;
 +	}
 +
 +	std::string delem = gDirUtilp->getDirDelimiter();
 +	std::string mask = delem + "*";
 +	llinfos << "Removing cache at " << mObjectCacheDirName << llendl;
 +	gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask); 
 +
 +	clearCacheInMemory() ;
 +	writeCacheHeader();
 +}
 +
 +void LLVOCache::clearCacheInMemory()
 +{
 +	std::for_each(mHandleEntryMap.begin(), mHandleEntryMap.end(), DeletePairedPointer());
 +	mHandleEntryMap.clear();
 +}
 +
 +void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename) 
 +{
 +	U32 region_x, region_y;
 +
 +	grid_from_region_handle(handle, ®ion_x, ®ion_y);
 +	filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname,
 +			   llformat(OBJECT_CACHE_FILENAME, region_x, region_y));
 +
 +	return ;
 +}
 +
 +void LLVOCache::removeFromCache(U64 handle)
 +{
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << llendl;
 +		return ;
 +	}
 +
 +	std::string filename;
 +	getObjectCacheFilename(handle, filename);
 +	LLAPRFile::remove(filename, mLocalAPRFilePoolp);	
 +}
 +
 +BOOL LLVOCache::checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error)
 +{
 +	if(!check_read(apr_file, src, n_bytes))
 +	{
 +		if (remove_cache_on_error)
 +		{
 +			removeCache() ;
 +		}
 +		return FALSE ;
 +	}
 +
 +	return TRUE ;
 +}
 +
 +BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error) 
 +{
 +	if(!check_write(apr_file, src, n_bytes))
 +	{
 +		if (remove_cache_on_error)
 +		{
 +			removeCache() ;
 +		}
 +		return FALSE ;
 +	}
 +
 +	return TRUE ;
 +}
 +
 +void LLVOCache::readCacheHeader()
 +{
 +	if(!mEnabled)
 +	{
 +		llwarns << "Not reading cache header: Cache is currently disabled." << llendl;
 +		return;
 +	}
 +
 +	//clear stale info.
 +	clearCacheInMemory();	
 +
 +	if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp))
 +	{
 +		LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_READ|APR_FOPEN_BINARY, mLocalAPRFilePoolp);		
 +		
 +		//read the meta element
 +		bool remove_cache_on_error = false;
 +		if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo), remove_cache_on_error))
 +		{
 +			llwarns << "Error reading meta information from cache header." << llendl;
 +			delete apr_file;
 +			return;
 +		}
 +
 +		HeaderEntryInfo* entry ;
 +		for(U32 entry_index = 0; entry_index < mCacheSize; ++entry_index)
 +		{
 +			entry = new HeaderEntryInfo() ;
 +			if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo), remove_cache_on_error))
 +			{
 +				llwarns << "Error reading cache header entry. (entry_index=" << entry_index << ")" << llendl;
 +				delete entry ;			
 +				break;
 +			}
 +			else if(!entry->mTime) //end of the cache.
 +			{
 +				delete entry ;
 +				break;
 +			}
 +
 +			entry->mIndex = entry_index;
 +			mHandleEntryMap[entry->mHandle] = entry;
 +		}
 +
 +		delete apr_file ;
 +	}
 +	else
 +	{
 +		writeCacheHeader() ;
 +	}
 +}
 +
 +void LLVOCache::writeCacheHeader()
 +{
 +	if (!mEnabled)
 +	{
 +		llwarns << "Not writing cache header: Cache is currently disabled." << llendl;
 +		return;
 +	}
 +
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl;
 +		return;
 +	}
 +
 +	LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BINARY|APR_FOPEN_TRUNCATE, mLocalAPRFilePoolp);
 +
 +	//write the meta element
 +	if(!checkWrite(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)))
 +	{
 +		llwarns << "Error writing meta information to cache header." << llendl;
 +		delete apr_file;
 +		return;
 +	}
 +
 +	U32 entry_index = 0;
 +	handle_entry_map_t::iterator iter_end = mHandleEntryMap.end();
 +	for(handle_entry_map_t::iterator iter = mHandleEntryMap.begin();
 +		iter != iter_end;
 +		++iter)
 +	{
 +		HeaderEntryInfo* entry = iter->second;
 +		entry->mIndex = entry_index++;
 +		if(!checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)))
 +		{
 +			llwarns << "Failed to write cache header for entry " << entry->mHandle << " (entry_index = " << entry_index << ")" << llendl;
 +			delete apr_file;
 +			return;
 +		}
 +	}
 +
 +	// Why do we need to fill the cache header with default entries?  DK 2010-12-14
 +	// It looks like we currently rely on the file being pre-allocated so we can seek during updateEntry().
 +	if(entry_index < mCacheSize)
 +	{
 +		HeaderEntryInfo* entry = new HeaderEntryInfo() ;
 +		for(; entry_index < mCacheSize; ++entry_index)
 +		{
 +			//fill the cache with the default entry.
 +			if(!checkWrite(apr_file, entry, sizeof(HeaderEntryInfo)))
 +			{
 +				llwarns << "Failed to fill cache header with default entries (entry_index = " << entry_index << ").  Switching to read-only mode." << llendl;
 +				mReadOnly = TRUE ; //disable the cache.
 +				break;
 +			}
 +		}
 +		delete entry ;
 +	}
 +	delete apr_file ;
 +}
 +
 +BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry)
 +{
 +	LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_WRITE|APR_FOPEN_BINARY, mLocalAPRFilePoolp);
 +	apr_file->seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ;
 +
 +	BOOL result = checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ;
 +	delete apr_file;
 +	return result;
 +}
 +
 +void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) 
 +{
 +	if(!mEnabled)
 +	{
 +		llwarns << "Not reading cache for handle " << handle << "): Cache is currently disabled." << llendl;
 +		return ;
 +	}
 +	llassert_always(mInitialized);
 +
 +	handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
 +	if(iter == mHandleEntryMap.end()) //no cache
 +	{
 +		llwarns << "No handle map entry for " << handle << llendl;
 +		return ;
 +	}
 +
 +	std::string filename;
 +	getObjectCacheFilename(handle, filename);
 +	LLAPRFile* apr_file = new LLAPRFile(filename, APR_FOPEN_READ|APR_FOPEN_BINARY, mLocalAPRFilePoolp);
 +
 +	LLUUID cache_id ;
 +	if(!checkRead(apr_file, cache_id.mData, UUID_BYTES))
 +	{
 +		llwarns << "Error reading cache_id from " << filename << llendl;
 +		delete apr_file;
 +		return ;
 +	}
 +	if(cache_id != id)
 +	{
 +		llwarns << "Cache ID (" << cache_id << ") doesn't match id for this region (" << id << "), discarding.  handle = " << handle << llendl;
 +		delete apr_file ;
 +		return ;
 +	}
 +
 +	S32 num_entries;
 +	if(!checkRead(apr_file, &num_entries, sizeof(S32)))
 +	{
 +		llwarns << "Error reading num_entries from " << filename << llendl;
 +		delete apr_file;
 +		return ;
 +	}
 +	
 +	for (S32 i = 0; i < num_entries; i++)
 +	{
 +		LLVOCacheEntry* entry = new LLVOCacheEntry(apr_file);
 +		if (!entry->getLocalID())
 +		{
 +			llwarns << "Aborting cache file load for " << filename << ", cache file corruption! (entry number = " << i << ")" << llendl;
 +			delete entry ;
 +			break;
 +		}
 +		cache_entry_map[entry->getLocalID()] = entry;
 +	}
 +
 +	delete apr_file ;
 +	return ;
 +}
 +	
 +void LLVOCache::purgeEntries()
 +{
 +	U32 limit = mCacheSize - (mCacheSize / ENTRIES_PURGE_FACTOR);
 +	limit = llclamp(limit, (U32)1, mCacheSize);
 +	// Construct a vector of entries out of the map so we can sort by time.
 +	std::vector<HeaderEntryInfo*> header_vector;
 +	handle_entry_map_t::iterator iter_end = mHandleEntryMap.end();
 +	for (handle_entry_map_t::iterator iter = mHandleEntryMap.begin();
 +		iter != iter_end;
 +		++iter)
 +	{
 +		header_vector.push_back(iter->second);
 +	}
 +	// Sort by time, oldest first.
 +	std::sort(header_vector.begin(), header_vector.end(), header_entry_less());
 +	while(header_vector.size() > limit)
 +	{
 +		HeaderEntryInfo* entry = header_vector.front();
 +		
 +		removeFromCache(entry->mHandle);
 +		mHandleEntryMap.erase(entry->mHandle);
 +		header_vector.erase(header_vector.begin());
 +		delete entry;
 +	}
 +
 +	writeCacheHeader() ;
 +	// *TODO: Verify that we can avoid re-reading the cache header.  DK 2010-12-14
 +	readCacheHeader() ;
 +}
 +
 +void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) 
 +{
 +	if(!mEnabled)
 +	{
 +		llwarns << "Not writing cache for handle " << handle << "): Cache is currently disabled." << llendl;
 +		return ;
 +	}
 +	llassert_always(mInitialized);
 +
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << llendl;
 +		return ;
 +	}
 +
 +	U32 num_handle_entries = mHandleEntryMap.size();
 +	
 +	HeaderEntryInfo* entry;
 +	handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
 +	if(iter == mHandleEntryMap.end()) //new entry
 +	{
 +		if(num_handle_entries >= mCacheSize)
 +		{
 +			purgeEntries() ;
 +			num_handle_entries = mHandleEntryMap.size();
 +		}
 +		
 +		entry = new HeaderEntryInfo();
 +		entry->mHandle = handle ;
 +		entry->mTime = time(NULL) ;
 +		entry->mIndex = num_handle_entries++;
 +		mHandleEntryMap[handle] = entry ;
 +	}
 +	else
 +	{
 +		// Update access time.
 +		entry = iter->second ;
 +		entry->mTime = time(NULL) ;
 +	}
 +
 +	//update cache header
 +	if(!updateEntry(entry))
 +	{
 +		llwarns << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << llendl;
 +		return ; //update failed.
 +	}
 +
 +	if(!dirty_cache)
 +	{
 +		llwarns << "Skipping write to cache for handle " << handle << ": cache not dirty" << llendl;
 +		return ; //nothing changed, no need to update.
 +	}
 +
 +	//write to cache file
 +	std::string filename;
 +	getObjectCacheFilename(handle, filename);
 +	LLAPRFile* apr_file = new LLAPRFile(filename, APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BINARY|APR_FOPEN_TRUNCATE, mLocalAPRFilePoolp);
 +	
 +	if(!checkWrite(apr_file, (void*)id.mData, UUID_BYTES))
 +	{
 +		llwarns << "Error writing id to " << filename << llendl;
 +		delete apr_file;
 +		return ;
 +	}
 +
 +	S32 num_entries = cache_entry_map.size() ;
 +	if(!checkWrite(apr_file, &num_entries, sizeof(S32)))
 +	{
 +		llwarns << "Error writing num_entries to " << filename << llendl;
 +		delete apr_file;
 +		return ;
 +	}
 +
 +	for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); iter != cache_entry_map.end(); ++iter)
 +	{
 +		if(!iter->second->writeToFile(apr_file))
 +		{
 +			llwarns << "Aborting cache file write for " << filename << ", error writing to file!" << llendl;
 +			//failed
 +			removeCache() ;
 +			break;
 +		}
 +	}
 +
 +	delete apr_file ;
 +	return ;
 +}
 +
 diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 014112718e..e103007979 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -128,8 +128,8 @@ private:  	void removeCache() ;  	void purgeEntries();  	BOOL updateEntry(const HeaderEntryInfo* entry); -	BOOL checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes) ; -	BOOL checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) ; +	BOOL checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error = true) ; +	BOOL checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error = true) ;  private:  	BOOL                 mEnabled; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 49269932f5..61264d380a 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -445,8 +445,9 @@ public:  		RENDER_DEBUG_AVATAR_VOLUME      = 0x0100000,  		RENDER_DEBUG_BUILD_QUEUE		= 0x0200000,  		RENDER_DEBUG_AGENT_TARGET       = 0x0400000, -		RENDER_DEBUG_PHYSICS_SHAPES     = 0x0800000, -		RENDER_DEBUG_NORMALS	        = 0x1000000, +		RENDER_DEBUG_UPDATE_TYPE		= 0x0800000, +		RENDER_DEBUG_PHYSICS_SHAPES     = 0x1000000, +		RENDER_DEBUG_NORMALS	        = 0x2000000,  	};  public: diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index feb6c1bb2a..7d767b9222 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -115,9 +115,6 @@       name="AlertCautionTextColor"       reference="LtYellow" />      <color -     name="AgentLinkColor" -     reference="EmphasisColor" /> -    <color       name="AlertTextColor"       value="0.58 0.66 0.84 1" />      <color @@ -349,9 +346,6 @@       name="GridlineShadowColor"       value="0 0 0 0.31" />      <color -     name="GroupLinkColor" -     reference="White" /> -    <color       name="GroupNotifyBoxColor"       value="0.3344 0.5456 0.5159 1" />      <color diff --git a/indra/newview/skins/default/textures/model_wizard/check_mark.png b/indra/newview/skins/default/textures/icons/check_mark.png Binary files differindex 2c05297f4f..2c05297f4f 100644 --- a/indra/newview/skins/default/textures/model_wizard/check_mark.png +++ b/indra/newview/skins/default/textures/icons/check_mark.png diff --git a/indra/newview/skins/default/textures/model_wizard/divider_line.png b/indra/newview/skins/default/textures/model_wizard/divider_line.png Binary files differnew file mode 100644 index 0000000000..76c9e68767 --- /dev/null +++ b/indra/newview/skins/default/textures/model_wizard/divider_line.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index e69c5775f0..d351c442d3 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -73,7 +73,22 @@ with the same filename but different name    <texture name="BackButton_Press" file_name="icons/back_arrow_press.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />    <texture name="Blank" file_name="Blank.png" preload="false" /> - +	 +  <texture name="BreadCrumbBtn_Left_Disabled" file_name="widgets/BreadCrumbBtn_Left_Disabled.png" preload="false"/> +  <texture name="BreadCrumbBtn_Left_Off" file_name="widgets/BreadCrumbBtn_Left_Off.png" preload="false"/> +  <texture name="BreadCrumbBtn_Left_Over" file_name="widgets/BreadCrumbBtn_Left_Over.png" preload="false"/> +  <texture name="BreadCrumbBtn_Left_Press" file_name="widgets/BreadCrumbBtn_Left_Press.png" preload="false"/> +  +  <texture name="BreadCrumbBtn_Middle_Disabled" file_name="widgets/BreadCrumbBtn_Middle_Disabled.png" preload="false"/> +  <texture name="BreadCrumbBtn_Middle_Off" file_name="widgets/BreadCrumbBtn_Middle_Off.png" preload="false"/> +  <texture name="BreadCrumbBtn_Middle_Over" file_name="widgets/BreadCrumbBtn_Middle_Over.png" preload="false"/> +  <texture name="BreadCrumbBtn_Middle_Press" file_name="widgets/BreadCrumbBtn_Middle_Press.png" preload="false"/> + +  <texture name="BreadCrumbBtn_Right_Disabled" file_name="widgets/BreadCrumbBtn_Right_Disabled.png" preload="false"/> +  <texture name="BreadCrumbBtn_Right_Off" file_name="widgets/BreadCrumbBtn_Right_Off.png" preload="false"/> +  <texture name="BreadCrumbBtn_Right_Over" file_name="widgets/BreadCrumbBtn_Right_Over.png" preload="false"/> +  <texture name="BreadCrumbBtn_Right_Press" file_name="widgets/BreadCrumbBtn_Right_Press.png" preload="false"/> +     <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="0" scale.top="1" scale.right="0" scale.bottom="0"  />    <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0"  /> @@ -102,6 +117,7 @@ with the same filename but different name    <texture name="Checkbox_On" file_name="widgets/Checkbox_On.png" preload="true" />    <texture name="Checkbox_On_Press" file_name="widgets/Checkbox_On_Press.png" preload="true" />    <texture name="Checkbox_Press" file_name="widgets/Checkbox_Press.png" preload="true" /> +  <texture name="Check_Mark" file_name="icons/check_mark" preload="true" />    <texture name="ComboButton_Disabled" file_name="widgets/ComboButton_Disabled.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />    <texture name="ComboButton_Selected" file_name="widgets/ComboButton_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> diff --git a/indra/newview/skins/default/textures/model_wizard/left_button_disabled.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Disabled.png Binary files differindex c7c0eaa96b..c7c0eaa96b 100644 --- a/indra/newview/skins/default/textures/model_wizard/left_button_disabled.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Disabled.png diff --git a/indra/newview/skins/default/textures/model_wizard/left_button_off.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Off.png Binary files differindex 4a73c254fc..4a73c254fc 100644 --- a/indra/newview/skins/default/textures/model_wizard/left_button_off.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Off.png diff --git a/indra/newview/skins/default/textures/model_wizard/left_button_over.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Over.png Binary files differindex 6fb5c432de..6fb5c432de 100644 --- a/indra/newview/skins/default/textures/model_wizard/left_button_over.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Over.png diff --git a/indra/newview/skins/default/textures/model_wizard/left_button_press.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Press.png Binary files differindex fa18517933..fa18517933 100644 --- a/indra/newview/skins/default/textures/model_wizard/left_button_press.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Press.png diff --git a/indra/newview/skins/default/textures/model_wizard/middle_button_disabled.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Disabled.png Binary files differindex bed1a701bd..bed1a701bd 100644 --- a/indra/newview/skins/default/textures/model_wizard/middle_button_disabled.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Disabled.png diff --git a/indra/newview/skins/default/textures/model_wizard/middle_button_off.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Off.png Binary files differindex 57ce9af574..57ce9af574 100644 --- a/indra/newview/skins/default/textures/model_wizard/middle_button_off.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Off.png diff --git a/indra/newview/skins/default/textures/model_wizard/middle_button_over.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Over.png Binary files differindex 2c43022f0e..2c43022f0e 100644 --- a/indra/newview/skins/default/textures/model_wizard/middle_button_over.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Over.png diff --git a/indra/newview/skins/default/textures/model_wizard/middle_button_press.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Press.png Binary files differindex 6b8c1baca4..6b8c1baca4 100644 --- a/indra/newview/skins/default/textures/model_wizard/middle_button_press.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Press.png diff --git a/indra/newview/skins/default/textures/model_wizard/right_button_disabled.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Disabled.png Binary files differindex 51505e80c5..51505e80c5 100644 --- a/indra/newview/skins/default/textures/model_wizard/right_button_disabled.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Disabled.png diff --git a/indra/newview/skins/default/textures/model_wizard/right_button_off.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Off.png Binary files differindex 9f93efbd93..9f93efbd93 100644 --- a/indra/newview/skins/default/textures/model_wizard/right_button_off.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Off.png diff --git a/indra/newview/skins/default/textures/model_wizard/right_button_over.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Over.png Binary files differindex 3a4ec1a315..3a4ec1a315 100644 --- a/indra/newview/skins/default/textures/model_wizard/right_button_over.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Over.png diff --git a/indra/newview/skins/default/textures/model_wizard/right_button_press.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Press.png Binary files differindex 1f1b4c2ed5..1f1b4c2ed5 100644 --- a/indra/newview/skins/default/textures/model_wizard/right_button_press.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Press.png diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml index 70299c61b4..593e686d4c 100644 --- a/indra/newview/skins/default/xui/da/notifications.xml +++ b/indra/newview/skins/default/xui/da/notifications.xml @@ -1636,7 +1636,7 @@ Knappen vil blive vist når der er nok plads til den.  	<notification name="ShareItemsConfirmation">  		Er du sikker på at du vil dele følgende genstande: -[ITEMS] +<nolink>[ITEMS]</nolink>  Med følgende beboere: diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 06cc02cd84..a2d0b5a170 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2747,7 +2747,7 @@ Die Schaltfläche wird angezeigt, wenn genügend Platz vorhanden ist.  	<notification name="ShareItemsConfirmation">  		Möchten Sie diese Objekte wirklich für andere freigeben: -[ITEMS] +<nolink>[ITEMS]</nolink>  Für folgende Einwohner: diff --git a/indra/newview/skins/default/xui/en/floater_model_wizard.xml b/indra/newview/skins/default/xui/en/floater_model_wizard.xml index e2ec557b06..2377a9e4ef 100644 --- a/indra/newview/skins/default/xui/en/floater_model_wizard.xml +++ b/indra/newview/skins/default/xui/en/floater_model_wizard.xml @@ -18,12 +18,15 @@  	 enabled="false"  	 label="5. Upload"  	 border="false" -	 image_unselected="model_wizard/middle_button_off.png" -	 image_selected="model_wizard/middle_button_press.png" -	 image_hover_unselected="model_wizard/middle_button_over.png" -	 image_disabled="model_wizard/middle_button_disabled.png" -	 image_disabled_selected="model_wizard/middle_button_disabled.png" -	 width="110"/> +	 image_unselected="BreadCrumbBtn_Right_Off" +	 image_selected="BreadCrumbBtn_Right_Press" +	 image_hover_unselected="BreadCrumbBtn_Right_Over" +	 image_disabled="BreadCrumbBtn_Right_Disabled" +	 image_disabled_selected="BreadCrumbBtn_Right_Disabled" +	 width="110"> +		<button.commit_callback +		function="Wizard.Upload"/> +	</button>  	<button  	 top="32"  	 left="310" @@ -33,12 +36,15 @@  	 label="4. Review"  	 enabled="false"  	 border="false" -	 image_unselected="model_wizard/middle_button_off.png" -	 image_selected="model_wizard/middle_button_press.png" -	 image_hover_unselected="model_wizard/middle_button_over.png" -	 image_disabled="model_wizard/middle_button_disabled.png" -	 image_disabled_selected="model_wizard/middle_button_disabled.png" -	 width="110"/> +	 image_unselected="BreadCrumbBtn_Middle_Off" +	 image_selected="BreadCrumbBtn_Middle_Press" +	 image_hover_unselected="BreadCrumbBtn_Middle_Over" +	 image_disabled="BreadCrumbBtn_Middle_Disabled" +	 image_disabled_selected="BreadCrumbBtn_Middle_Disabled" +	 width="110"> +		<button.commit_callback +		function="Wizard.Review"/> +	</button>  	<button  	 top="32"  	 left="210" @@ -48,12 +54,15 @@  	 tab_stop="false"  	 enabled="false"  	 border="false" -	 image_unselected="model_wizard/middle_button_off.png" -	 image_selected="model_wizard/middle_button_press.png" -	 image_hover_unselected="model_wizard/middle_button_over.png" -	 image_disabled="model_wizard/middle_button_disabled.png" -	 image_disabled_selected="model_wizard/middle_button_disabled.png" -	 width="110"/> +	 image_unselected="BreadCrumbBtn_Middle_Off" +	 image_selected="BreadCrumbBtn_Middle_Press" +	 image_hover_unselected="BreadCrumbBtn_Middle_Over" +	 image_disabled="BreadCrumbBtn_Middle_Disabled" +	 image_disabled_selected="BreadCrumbBtn_Middle_Disabled" +	 width="110"> +		<button.commit_callback +		function="Wizard.Physics"/> +	</button>  	<button  	 top="32"  	 left="115" @@ -62,12 +71,15 @@  	 tab_stop="false"  	 height="32"  	 border="false" -	 image_unselected="model_wizard/middle_button_off.png" -	 image_selected="model_wizard/middle_button_press.png" -	 image_hover_unselected="model_wizard/middle_button_over.png" -	 image_disabled="model_wizard/middle_button_disabled.png" -	 image_disabled_selected="model_wizard/middle_button_disabled.png" -	 width="110"/> +	 image_unselected="BreadCrumbBtn_Middle_Off" +	 image_selected="BreadCrumbBtn_Middle_Press" +	 image_hover_unselected="BreadCrumbBtn_Middle_Over" +	 image_disabled="BreadCrumbBtn_Middle_Disabled" +	 image_disabled_selected="BreadCrumbBtn_Middle_Disabled" +	 width="110"> +		<button.commit_callback +		function="Wizard.Optimize"/> +	</button>  	<button  	 top="32"  	 left="15" @@ -76,12 +88,15 @@  	 enabled="false"  	 label="1. Choose File"  	 height="32" -	 image_unselected="model_wizard/left_button_off.png" -	 image_selected="model_wizard/left_button_press.png" -	 image_hover_unselected="model_wizard/left_button_over.png" -	 image_disabled="model_wizard/left_button_disabled.png" -	 image_disabled_selected="model_wizard/left_button_disabled.png" -	 width="110"/> +	 image_unselected="BreadCrumbBtn_Left_Off" +	 image_selected="BreadCrumbBtn_Left_Press" +	 image_hover_unselected="BreadCrumbBtn_Left_Over" +	 image_disabled="BreadCrumbBtn_Left_Disabled" +	 image_disabled_selected="BreadCrumbBtn_Left_Disabled" +	 width="110"> +		<button.commit_callback +		function="Wizard.Choose"/> +	</button>  	<panel  		 height="388"  		 top_pad="0" @@ -190,21 +205,49 @@  			<text  			 top_pad="10"  			 width="130" -			 height="15" +			 height="14"  			 left="340"  			 text_color="White"  			 word_wrap="true">  				Dimensions (meters):  			</text>  			<text -			 top_pad="2" +			 top_pad="0"  			 width="160"  			 height="15" -			 name="import_dimensions" +			 font="SansSerifSmallBold"  +			 text_color="White" +			 name="dimensions"  			 left_delta="0"> -				X:  [X] |Y:  [Y] |Z: [Z] +				X:         Y:         Z:   			</text>  			<text +			 top_delta="0" +			 width="160" +			 height="15" +			 name="dimension_dividers" +			 left_delta="41"> +				 |               |    +			</text> +			<text +			 top_delta="0" +			 width="160" +			 height="15" +			 name="dimension_x" +			 left="356"/> +			<text +			 top_delta="0" +			 width="160" +			 height="15" +			 name="dimension_y" +			 left="403"/> +			<text +			 top_delta="0" +			 width="160" +			 height="15" +			 name="dimension_z" +			 left="450"/> +			<text  			 top="100"  			 width="320"  			 height="15" @@ -397,29 +440,66 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  		   width="290" />  			<text   			font="SansSerifSmall"  -			top_pad="1"   +			top_pad="0"    			width="300"   			left_delta="6"   			height="4">'                                             '                                             '</text> -			<text top_delta="25" width="100" text_color="White" left_delta="50"  height="20">Resource Cost:</text> + + +			<icon +				 top_pad="10" +				 left_delta="0" +				 width="280" +				 height="2" +				 image_name="model_wizard\divider_line.png"/> +	 +			<text top_delta="25" width="200" text_color="White" left_delta="50" name="streaming cost"  height="20">Resource Cost:    [COST]</text>  			<text top_delta="25" width="100" text_color="White" left_delta="0"  height="20">Upload Fee:</text>  			<text -			 top_pad="15" -			 width="130" -			 height="15" -			 left="10" -			 text_color="White" -			 word_wrap="true"> +						 top_pad="5" +						 width="130" +						 height="14" +						 left="10" +						 text_color="White" +						 word_wrap="true">  				Dimensions (meters):  			</text>  			<text  			 top_pad="0"  			 width="160"  			 height="15" -			 name="import_dimensions" +			 font="SansSerifSmallBold" +			 text_color="White" +			 name="dimensions"  			 left_delta="0"> -				X:  [X] |Y:  [Y] |Z: [Z] +				X:         Y:         Z: +			</text> +			<text +			 top_delta="0" +			 width="160" +			 height="15" +			 name="dimension_dividers" +			 left_delta="41"> +				|               |  			</text> +			<text +			 top_delta="0" +			 width="160" +			 height="15" +			 name="dimension_x" +			 left_delta="-25"/> +			<text +			 top_delta="0" +			 width="160" +			 height="15" +			 name="dimension_y" +			 left_delta="46"/> +			<text +			 top_delta="0" +			 width="160" +			 height="15" +			 name="dimension_z" +			 left_delta="46"/>  		</panel>  	</panel> @@ -466,7 +546,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se      <panel  		 top_delta="40"  		 left="15" -		 height="245" +		 height="265"  		 width="500"  		 name="content"  		 bg_opaque_color="DkGray2" @@ -499,9 +579,18 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se        <text top_pad="10" width="110" halign="center" word_wrap="true" left="25"  height="40">Recommended for solid objects</text>        <text top_delta="0" width="110" halign="center" word_wrap="true" left="190"  height="40">Recommended for buildings</text>        <text top_delta="0" width="110" halign="center" word_wrap="true" left="350"  height="40">Recommended for vehicles</text> -      <text top_delta="60" width="100" text_color="White" left="160"  height="20">Resource Cost:</text> -      <text top_delta="20" width="100" text_color="White" left_delta="0"  height="20">Physics Cost:</text> -      <text top_delta="20" width="100" text_color="White" left_delta="0"  height="20">Upload Fee:</text> + + +		<icon +			 top_pad="5" +			 left="15" +			 width="470" +			 height="2" +			 image_name="model_wizard\divider_line.png"/> +		 +	<text top_delta="20" width="180" text_color="White" left="160" name="streaming cost"  height="20">Resource Cost:       [COST]</text> +      <text top_delta="26" width="180" text_color="White" left_delta="0" name="physics cost"  height="20">Physics Cost:           [COST]</text> +      <text top_delta="26" width="180" text_color="White" left_delta="0"  height="20">Upload Fee:</text>      </panel>  	</panel> @@ -511,7 +600,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  		 height="388"  		 top_delta="0"  		 name="review_panel" -		 visible="false" +		 visible="true"  		 width="530"  		 left="0">  		<panel @@ -538,7 +627,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  		<text  		 top_pad="14"  		 width="460" -		 height="20" +		 height="24"  		 font="SansSerifSmall"  		 layout="topleft"  		 name="description" @@ -546,8 +635,14 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  		 left_delta="10">  			Review the details below then click. Upload to upload your model. Your L$ balance will be charged when you click Upload.  		</text> +		<icon +			 top_pad="10" +			 left="20" +			 width="495" +			 height="2" +			 image_name="model_wizard\divider_line.png"/>      <panel -		 top_delta="40" +		 top_pad="5"  		 left="15"  		 height="245"  		 width="500" @@ -555,7 +650,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se        <text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label">          Model Preview:        </text> -      <combo_box left_pad="5" top_delta="-2"  follows="left|top" list_position="below" height="18" +      <combo_box left_pad="5" top_delta="-5"  follows="left|top" list_position="below" height="22"  	     name="preview_lod_combo" width="90" tool_tip="LOD to view in preview render">          <combo_item name="high">            High @@ -580,32 +675,61 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  				 height="190"  				 follows="all"  				 width="190"> -			</panel>			 -      <text -			 top_pad="8" -			 width="130" -			 height="15" -			 left="10" -			 text_color="White" -			 word_wrap="true"> -				Dimensions (meters): -			</text> -      <text -			 top_pad="0" -			 width="160" -			 height="15" -			 name="import_dimensions" -			 left_delta="0"> -        X:  [X] |Y:  [Y] |Z: [Z] -      </text> +			</panel> +		<text +					 top_pad="8" +					 width="130" +					 height="14" +					 left="10" +					 text_color="White" +					 word_wrap="true"> +			Dimensions (meters): +		</text> +		<text +		 top_pad="0" +		 width="160" +		 height="15" +		 font="SansSerifSmallBold" +		 text_color="White" +		 name="dimensions" +		 left_delta="0"> +			X:         Y:         Z: +		</text> +		<text +		 top_delta="0" +		 width="160" +		 height="15" +		 name="dimension_dividers" +		 left_delta="41"> +			|               | +		</text> +		<text +		 top_delta="0" +		 width="160" +		 height="15" +		 name="dimension_x" +		 left_delta="-25"/> +		<text +		 top_delta="0" +		 width="160" +		 height="15" +		 name="dimension_y" +		 left_delta="46"/> +		<text +		 top_delta="0" +		 width="160" +		 height="15" +		 name="dimension_z" +		 left_delta="46"/>        </panel>      <text -      width="200" +      width="300"        height="12"        top="125"  +	  name="streaming cost"         left="230"         font="SansSerifSmallBold"  -      text_color="White">Resource Cost:</text> +      text_color="White">Resource Cost:         [COST]</text>      <text        width="285"        height="30" @@ -614,12 +738,13 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se        word_wrap="true"        font="SansSerifItalic">This is the cost to your Region's prim/object limit, at default scale</text>  	<text -	 width="200" +	 width="300"  	 height="12" +	 name="physics cost"   	 top_pad="10"  		 left_delta="0"  	 font="SansSerifSmallBold" -	 text_color="White">Physics Cost:</text> +	 text_color="White">Physics Cost:        [COST]</text>  	<text  	  width="285"  	  height="30" @@ -663,7 +788,7 @@ Advanced users familiar with 3d content creation tools may prefer to use the [se  		 height="388"  		 top_delta="0"  		 name="upload_panel" -		 visible="true" +		 visible="false"  		 width="530"  		 left="0">  		<panel diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index 2ad46824c2..d90d0feda9 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -1,190 +1,190 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 -<floater
 -  legacy_header_height="18"
 -  can_resize="true"
 -  height="440"
 -  layout="topleft"
 -  min_height="140"
 -  min_width="467"
 -  name="floater_web_content"
 -  help_topic="floater_web_content"
 -  save_rect="true"
 -  auto_tile="true"
 -  title=""
 -  initial_mime_type="text/html"
 -  width="820">
 -  <layout_stack
 -    bottom="440"
 -    follows="left|right|top|bottom"
 -    layout="topleft"
 -    left="5"
 -    name="stack1"
 -    orientation="vertical"
 -    top="20"
 -    width="810">
 -    <layout_panel
 -      auto_resize="false"
 -      default_tab_group="1"
 -      height="22"
 -      layout="topleft"
 -      left="0"
 -      min_height="20"
 -      name="nav_controls"
 -      top="400"
 -      user_resize="false"
 -      width="800">
 -      <button
 -        image_overlay="Arrow_Left_Off"
 -		    image_disabled="PushButton_Disabled"
 -		    image_disabled_selected="PushButton_Disabled"
 -		    image_selected="PushButton_Selected"
 -		    image_unselected="PushButton_Off"
 -		    hover_glow_amount="0.15"
 -        tool_tip="Navigate back"
 -        follows="left|top"
 -        height="22"
 -        layout="topleft"
 -        left="1"
 -        name="back"
 -        top="0"
 -        width="22">
 -        <button.commit_callback
 -          function="WebContent.Back" />
 -      </button>
 -      <button
 -        image_overlay="Arrow_Right_Off"
 -		    image_disabled="PushButton_Disabled"
 -		    image_disabled_selected="PushButton_Disabled"
 -		    image_selected="PushButton_Selected"
 -		    image_unselected="PushButton_Off"
 -        tool_tip="Navigate forward"
 -        follows="left|top"
 -        height="22"
 -        layout="topleft"
 -        left="27"
 -        name="forward"
 -        top_delta="0"
 -        width="22">
 -        <button.commit_callback
 -          function="WebContent.Forward" />
 -      </button>
 -      <button
 -        image_overlay="Stop_Off"
 -		    image_disabled="PushButton_Disabled"
 -		    image_disabled_selected="PushButton_Disabled"
 -		    image_selected="PushButton_Selected"
 -		    image_unselected="PushButton_Off"
 -        tool_tip="Stop navigation"
 -        enabled="true"
 -        follows="left|top"
 -        height="22"
 -        layout="topleft"
 -        left="51"
 -        name="stop"
 -        top_delta="0"
 -        width="22">
 -        <button.commit_callback
 -          function="WebContent.Stop" />
 -      </button>
 -      <button
 -        image_overlay="Refresh_Off"
 -		    image_disabled="PushButton_Disabled"
 -		    image_disabled_selected="PushButton_Disabled"
 -		    image_selected="PushButton_Selected"
 -		    image_unselected="PushButton_Off"
 -        tool_tip="Reload page"
 -        follows="left|top"
 -        height="22"
 -        layout="topleft"
 -        left="51"
 -        name="reload"
 -        top_delta="0"
 -        width="22">
 -        <button.commit_callback
 -          function="WebContent.Reload" />
 -      </button>
 -      <combo_box
 -        allow_text_entry="true"
 -        follows="left|top|right"
 -        tab_group="1"
 -        height="22"
 -        layout="topleft"
 -        left_pad="4"
 -        max_chars="1024"
 -        name="address"
 -        combo_editor.select_on_focus="true"
 -        tool_tip="Enter URL here"
 -        top_delta="0"
 -        width="702">
 -        <combo_box.commit_callback
 -          function="WebContent.EnterAddress" />
 -      </combo_box>
 -      <icon
 -        name="media_secure_lock_flag"
 -        height="16"
 -        follows="top|right"
 -        image_name="Lock2"
 -        layout="topleft"
 -        left_delta="656"
 -        top_delta="2"
 -        visible="false" 
 -        tool_tip="Secured Browsing"
 -        width="16" />
 -      <button
 -        image_overlay="ExternalBrowser_Off"
 -		    image_disabled="PushButton_Disabled"
 -		    image_disabled_selected="PushButton_Disabled"
 -		    image_selected="PushButton_Selected"
 -		    image_unselected="PushButton_Off"
 -        tool_tip="Open current URL in your desktop browser"
 -        follows="right|top"
 -        enabled="true" 
 -        height="22"
 -        layout="topleft"
 -        name="popexternal"
 -        right="800"
 -        top_delta="-2"
 -        width="22">
 -        <button.commit_callback
 -          function="WebContent.PopExternal" />
 -      </button>
 -    </layout_panel>
 -    <layout_panel
 -      height="40"
 -      layout="topleft"
 -      left_delta="0"
 -      name="external_controls"
 -      top_delta="0"
 -      user_resize="false"
 -      width="540">
 -      <web_browser
 -        bottom="-22"
 -        follows="all"
 -        layout="topleft"
 -        left="0"
 -        name="webbrowser"
 -        top="0"/>
 -      <text
 -        type="string"
 -        length="100"
 -        follows="bottom|left"
 -        height="20"
 -        layout="topleft"
 -        left_delta="0"
 -        name="statusbartext"
 -        parse_urls="false"
 -        text_color="0.4 0.4 0.4 1" 
 -        top_pad="5"
 -        width="452"/>
 -      <progress_bar
 -        color_bar="0.3 1.0 0.3 1"
 -        follows="bottom|right"
 -        height="16"
 -        top_delta="-1"
 -        left_pad="24"
 -        layout="topleft"
 -        name="statusbarprogress"
 -        width="64"/>
 -    </layout_panel>
 -  </layout_stack>
 -</floater>
 +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater +  legacy_header_height="18" +  can_resize="true" +  height="440" +  layout="topleft" +  min_height="140" +  min_width="467" +  name="floater_web_content" +  help_topic="floater_web_content" +  save_rect="true" +  auto_tile="true" +  title="" +  initial_mime_type="text/html" +  width="820"> +  <layout_stack +    bottom="440" +    follows="left|right|top|bottom" +    layout="topleft" +    left="5" +    name="stack1" +    orientation="vertical" +    top="20" +    width="810"> +    <layout_panel +      auto_resize="false" +      default_tab_group="1" +      height="22" +      layout="topleft" +      left="0" +      min_height="20" +      name="nav_controls" +      top="400" +      user_resize="false" +      width="800"> +      <button +        image_overlay="Arrow_Left_Off" +        image_disabled="PushButton_Disabled" +        image_disabled_selected="PushButton_Disabled" +        image_selected="PushButton_Selected" +        image_unselected="PushButton_Off" +        hover_glow_amount="0.15" +        tool_tip="Navigate back" +        follows="left|top" +        height="22" +        layout="topleft" +        left="1" +        name="back" +        top="0" +        width="22"> +        <button.commit_callback +          function="WebContent.Back" /> +      </button> +      <button +        image_overlay="Arrow_Right_Off" +        image_disabled="PushButton_Disabled" +        image_disabled_selected="PushButton_Disabled" +        image_selected="PushButton_Selected" +        image_unselected="PushButton_Off" +        tool_tip="Navigate forward" +        follows="left|top" +        height="22" +        layout="topleft" +        left="27" +        name="forward" +        top_delta="0" +        width="22"> +        <button.commit_callback +          function="WebContent.Forward" /> +      </button> +      <button +        image_overlay="Stop_Off" +        image_disabled="PushButton_Disabled" +        image_disabled_selected="PushButton_Disabled" +        image_selected="PushButton_Selected" +        image_unselected="PushButton_Off" +        tool_tip="Stop navigation" +        enabled="true" +        follows="left|top" +        height="22" +        layout="topleft" +        left="51" +        name="stop" +        top_delta="0" +        width="22"> +        <button.commit_callback +          function="WebContent.Stop" /> +      </button> +      <button +        image_overlay="Refresh_Off" +        image_disabled="PushButton_Disabled" +        image_disabled_selected="PushButton_Disabled" +        image_selected="PushButton_Selected" +        image_unselected="PushButton_Off" +        tool_tip="Reload page" +        follows="left|top" +        height="22" +        layout="topleft" +        left="51" +        name="reload" +        top_delta="0" +        width="22"> +        <button.commit_callback +          function="WebContent.Reload" /> +      </button> +      <combo_box +        allow_text_entry="true" +        follows="left|top|right" +        tab_group="1" +        height="22" +        layout="topleft" +        left_pad="4" +        max_chars="1024" +        name="address" +        combo_editor.select_on_focus="true" +        tool_tip="Enter URL here" +        top_delta="0" +        width="702"> +        <combo_box.commit_callback +          function="WebContent.EnterAddress" /> +      </combo_box> +      <icon +        name="media_secure_lock_flag" +        height="16" +        follows="top|right" +        image_name="Lock2" +        layout="topleft" +        left_delta="656" +        top_delta="2" +        visible="false"  +        tool_tip="Secured Browsing" +        width="16" /> +      <button +        image_overlay="ExternalBrowser_Off" +        image_disabled="PushButton_Disabled" +        image_disabled_selected="PushButton_Disabled" +        image_selected="PushButton_Selected" +        image_unselected="PushButton_Off" +        tool_tip="Open current URL in your desktop browser" +        follows="right|top" +        enabled="true"  +        height="22" +        layout="topleft" +        name="popexternal" +        right="800" +        top_delta="-2" +        width="22"> +        <button.commit_callback +          function="WebContent.PopExternal" /> +      </button> +    </layout_panel> +    <layout_panel +      height="40" +      layout="topleft" +      left_delta="0" +      name="external_controls" +      top_delta="0" +      user_resize="false" +      width="540"> +      <web_browser +        bottom="-22" +        follows="all" +        layout="topleft" +        left="0" +        name="webbrowser" +        top="0"/> +      <text +        type="string" +        length="100" +        follows="bottom|left" +        height="20" +        layout="topleft" +        left_delta="0" +        name="statusbartext" +        parse_urls="false" +        text_color="0.4 0.4 0.4 1"  +        top_pad="5" +        width="452"/> +      <progress_bar +        color_bar="0.3 1.0 0.3 1" +        follows="bottom|right" +        height="16" +        top_delta="-1" +        left_pad="24" +        layout="topleft" +        name="statusbarprogress" +        width="64"/> +    </layout_panel> +  </layout_stack> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml index c751aa4e0c..719509301b 100644 --- a/indra/newview/skins/default/xui/en/menu_object.xml +++ b/indra/newview/skins/default/xui/en/menu_object.xml @@ -100,7 +100,7 @@           name="Object Attach HUD" />     </context_menu>     <context_menu -         label="Remove" +         label="Manage"           name="Remove">     <menu_item_call           enabled="false" @@ -129,15 +129,6 @@           <menu_item_call.on_enable            function="Object.EnableReturn" />       </menu_item_call> -     <menu_item_call -   enabled="false" -   label="Delete" -   name="Delete"> -      <menu_item_call.on_click -       function="Object.Delete" /> -      <menu_item_call.on_enable -       function="Object.EnableDelete" /> -    </menu_item_call>      </context_menu>     <menu_item_separator layout="topleft" />     <menu_item_call @@ -176,4 +167,13 @@        <menu_item_call.on_enable         function="Object.EnableBuy" />     </menu_item_call> +   <menu_item_call +     enabled="false" +     label="Delete" +     name="Delete"> +      <menu_item_call.on_click +       function="Object.Delete" /> +      <menu_item_call.on_enable +       function="Object.EnableDelete" /> +  </menu_item_call>  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b7816b8e25..6211561a5d 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -89,7 +89,7 @@           visibility_control="VoiceMorphingEnabled">              <menu_item_check.on_check               function="Floater.Visible" -             parameter="voice_effect" /> +             Parameter="voice_effect" />              <menu_item_check.on_click               function="Floater.Toggle"               parameter="voice_effect" /> @@ -2208,6 +2208,16 @@             parameter="render batches" />          </menu_item_check>          <menu_item_check +         label="Update Type" +         name="Update Type"> +          <menu_item_check.on_check +           function="Advanced.CheckInfoDisplay" +           parameter="update type" /> +          <menu_item_check.on_click +           function="Advanced.ToggleInfoDisplay" +           parameter="update type" /> +        </menu_item_check> +        <menu_item_check           label="Texture Anim"           name="Texture Anim">            <menu_item_check.on_check @@ -2771,7 +2781,7 @@                   function="Floater.Toggle"                   parameter="region_debug_console" />              </menu_item_check> -  +            <menu_item_check             <menu_item_separator />              <menu_item_check @@ -2790,6 +2800,10 @@              <menu_item_separator />              <menu_item_check + +            <menu_item_separator /> + +            <menu_item_check               label="Debug SelectMgr"               name="Debug SelectMgr">                  <menu_item_check.on_check diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6af49fdecf..cac25b9312 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -253,6 +253,16 @@ Save all changes to clothing/body parts?    <notification     icon="alertmodal.tga" +   name="FavoritesOnLogin" +   type="alertmodal">     +    Note: When you turn on this option, anyone who uses this computer can see your list of favorite locations. +    <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga"     name="GrantModifyRights"     type="alertmodal">  Granting modify rights to another Resident allows them to change, delete or take ANY objects you may have in-world. Be VERY careful when handing out this permission. @@ -6440,7 +6450,7 @@ Select residents to share with.     type="alertmodal">  Are you sure you want to share the following items: -[ITEMS] +<nolink>[ITEMS]</nolink>  With the following Residents: diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index 61d6cbb2d0..eff674c628 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -67,23 +67,23 @@          <scroll_list.columns           label="Parcel"           name="name" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Region"           name="location" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Type"           name="type" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Area"           name="area" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Hidden"           name="hidden" -         width="47" /> +         relative_width="0.2" />      </scroll_list>      <text       type="string" diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 257ed799da..806182bcb4 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -61,23 +61,28 @@ left="20"  width="150">  Username:  </text> -<line_editor +<combo_box +allow_text_entry="true"  follows="left|bottom"  height="22" -label="bobsmith12 or Steller Sunshine"  left_delta="0" -max_length_bytes="63" -name="username_edit" -prevalidate_callback="ascii"  +max_chars="128" +prevalidate_callback="ascii"  select_on_focus="true"  tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"  top_pad="0" -width="150" /> +name="username_combo" +width="178"> +  <combo_box.combo_button +   visible ="false"/> +  <combo_box.drop_down_button +   visible ="false"/> +</combo_box>  <text  follows="left|bottom"  font="SansSerifSmall"  height="15" -left_pad="8" +left_pad="-19"  name="password_text"  top="20"      width="150"> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 16becbfe2a..ef25588ca3 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -78,6 +78,16 @@       name="auto_disengage_mic_check"       top_pad="10"       width="350" /> +    <check_box +     control_name="ShowFavoritesOnLogin" +     enabled="false"  +     height="16" +     label="Show my Favorite Landmarks at Login (via 'Start At' drop-down menu)" +     layout="topleft" +     left="30" +     name="favorites_on_login_check" +     top_pad="10" +     width="350" />  	<text        type="string"      length="1" @@ -87,7 +97,7 @@       left="30"       mouse_opaque="false"       name="Logs:" -     top_pad="30" +     top_pad="20"       width="350">          Chat Logs:      </text> @@ -179,7 +189,7 @@       layout="topleft"       left="30"       name="block_list" -     top_pad="35" +     top_pad="28"       width="145">          <!--<button.commit_callback           function="SideTray.ShowPanel"--> diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml index 85d0c633af..2e5ebafe46 100644 --- a/indra/newview/skins/default/xui/en/widgets/floater.xml +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -21,4 +21,5 @@   tear_off_pressed_image="tearoff_pressed.tga"   dock_pressed_image="Icon_Dock_Press"   help_pressed_image="Icon_Help_Press" + focus_root="true"    /> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 2dd7a6b0f5..14ce39e8fc 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2734,7 +2734,7 @@ Se mostrará cuando haya suficiente espacio.  	<notification name="ShareItemsConfirmation">  		¿Estás seguro de que quieres compartir los elementos siguientes? -[ITEMS] +<nolink>[ITEMS]</nolink>  Con los siguientes residentes: diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index ec362d7f22..f0b0e63af0 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2730,7 +2730,7 @@ Le bouton sera affiché quand il y aura suffisamment de place.  	<notification name="ShareItemsConfirmation">  		Voulez-vous vraiment partager les articles suivants : -[ITEMS] +<nolink>[ITEMS]</nolink>  avec les résidents suivants : diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 32483881b2..5e53080c77 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -2679,7 +2679,7 @@ Il pulsante verrà visualizzato quando lo spazio sarà sufficiente.  	<notification name="ShareItemsConfirmation">  		Sei sicuro di volere condividere gli oggetti -[ITEMS] +<nolink>[ITEMS]</nolink>  Con i seguenti residenti? diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index c0af0e03ff..f133bb361a 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -2731,7 +2731,7 @@ M キーを押して変更します。  	<notification name="ShareItemsConfirmation">  		次のアイテムを共有しますか: -[ITEMS] +<nolink>[ITEMS]</nolink>  次の住人と共有しますか: diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index 8151c7eb93..57a6b8b8ef 100644 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -2691,7 +2691,7 @@ Przycisk zostanie wyświetlony w przypadku dostatecznej ilości przestrzeni.  	<notification name="ShareItemsConfirmation">  		Jesteś pewien/pewna, że chcesz udostępnić następujące obiekty: -[ITEMS] +<nolink>[ITEMS]</nolink>  następującym Rezydentom: diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index dc38b740aa..a1855f2e89 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -477,7 +477,7 @@ Para aumentar a qualidade do vídeo, vá para Preferências > Vídeo.  	</notification>  	<notification name="CannotCopyWarning">  		Você não tem autorização para copiar os itens abaixo: -[ITENS] +[ITEMS]  ao dá-los, você ficará sem eles no seu inventário. Deseja realmente dar estes itens?  		<usetemplate name="okcancelbuttons" notext="Não" yestext="Sim"/>  	</notification> @@ -2714,7 +2714,7 @@ O botão será exibido quando houver espaço suficente.  	<notification name="ShareItemsConfirmation">  		Tem certeza de que quer compartilhar os items abaixo? -[ITENS] +<nolink>[ITEMS]</nolink>  Com os seguintes residentes: diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index a6c1f69c82..7862cce3a1 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -1,134 +1,136 @@ -/** 
 - * @file llremoteparcelrequest_test.cpp
 - * @author Brad Kittenbrink <brad@lindenlab.com>
 - *
 - * $LicenseInfo:firstyear=2010&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 "linden_common.h"
 -
 -#include "../test/lltut.h"
 -
 -#include "../llremoteparcelrequest.h"
 -
 -#include "../llagent.h"
 -#include "message.h"
 -
 -namespace {
 -	LLControlGroup s_saved_settings("dummy_settings");
 -	const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111");
 -}
 -
 -LLCurl::Responder::Responder() { }
 -LLCurl::Responder::~Responder() { }
 -void LLCurl::Responder::error(U32,std::string const &) { }
 -void LLCurl::Responder::result(LLSD const &) { }
 -void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { }
 -void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
 -void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { }
 -void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { }
 -void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { }
 -void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { }
 -void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { }
 -void LLMessageSystem::getString(char const *,char const *, std::string &,S32) { }
 -void LLMessageSystem::getUUID(char const *,char const *, LLUUID & out_id,S32)
 -{
 -	out_id = TEST_PARCEL_ID;
 -}
 -void LLMessageSystem::nextBlock(char const *) { }
 -void LLMessageSystem::addUUID(char const *,LLUUID const &) { }
 -void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { }
 -void LLMessageSystem::nextBlockFast(char const *) { }
 -void LLMessageSystem::newMessage(char const *) { }
 -LLMessageSystem * gMessageSystem;
 -char * _PREHASH_AgentID;
 -char * _PREHASH_AgentData;
 -LLAgent gAgent;
 -LLAgent::LLAgent() : mAgentAccess(s_saved_settings) { }
 -LLAgent::~LLAgent() { }
 -void LLAgent::sendReliableMessage(void) { }
 -LLUUID gAgentSessionID;
 -LLUUID gAgentID;
 -LLUIColor::LLUIColor(void) { }
 -LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { }
 -LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }
 -LLControlGroup::~LLControlGroup(void) { }
 -
 -namespace tut
 -{
 -	struct TestObserver : public LLRemoteParcelInfoObserver {
 -		TestObserver() : mProcessed(false) { }
 -
 -		virtual void processParcelInfo(const LLParcelData& parcel_data)
 -		{
 -			mProcessed = true;
 -		}
 -
 -		virtual void setParcelID(const LLUUID& parcel_id) { }
 -
 -		virtual void setErrorStatus(U32 status, const std::string& reason) { }
 -
 -		bool mProcessed;
 -	};
 -
 -    struct RemoteParcelRequestData
 -    {
 -		RemoteParcelRequestData()
 -		{
 -		}
 -    };
 -    
 -	typedef test_group<RemoteParcelRequestData> remoteparcelrequest_t;
 -	typedef remoteparcelrequest_t::object remoteparcelrequest_object_t;
 -	tut::remoteparcelrequest_t tut_remoteparcelrequest("LLRemoteParcelRequest");
 -
 -	template<> template<>
 -	void remoteparcelrequest_object_t::test<1>()
 -	{
 -		set_test_name("observer pointer");
 -
 -		boost::scoped_ptr<TestObserver> observer(new TestObserver());
 -
 -		LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance();
 -		processor.addObserver(LLUUID(TEST_PARCEL_ID), observer.get());
 -
 -		processor.processParcelInfoReply(gMessageSystem, NULL);
 -
 -		ensure(observer->mProcessed);
 -	}
 -
 -	template<> template<>
 -	void remoteparcelrequest_object_t::test<2>()
 -	{
 -		set_test_name("CHOP-220: dangling observer pointer");
 -
 -		LLRemoteParcelInfoObserver * observer = new TestObserver();
 -
 -		LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance();
 -		processor.addObserver(LLUUID(TEST_PARCEL_ID), observer);
 -
 -		delete observer;
 -		observer = NULL;
 -
 -		processor.processParcelInfoReply(gMessageSystem, NULL);
 -	}
 -}
 +/**  + * @file llremoteparcelrequest_test.cpp + * @author Brad Kittenbrink <brad@lindenlab.com> + * + * $LicenseInfo:firstyear=2010&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 "linden_common.h" + +#include "../test/lltut.h" + +#include "../llremoteparcelrequest.h" + +#include "../llagent.h" +#include "message.h" +#include "llurlentry.h" + +namespace { +	LLControlGroup s_saved_settings("dummy_settings"); +	const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111"); +} + +LLCurl::Responder::Responder() { } +LLCurl::Responder::~Responder() { } +void LLCurl::Responder::error(U32,std::string const &) { } +void LLCurl::Responder::result(LLSD const &) { } +void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { } +void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { } +void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { } +void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { } +void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { } +void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { } +void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { } +void LLMessageSystem::getString(char const *,char const *, std::string &,S32) { } +void LLMessageSystem::getUUID(char const *,char const *, LLUUID & out_id,S32) +{ +	out_id = TEST_PARCEL_ID; +} +void LLMessageSystem::nextBlock(char const *) { } +void LLMessageSystem::addUUID(char const *,LLUUID const &) { } +void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { } +void LLMessageSystem::nextBlockFast(char const *) { } +void LLMessageSystem::newMessage(char const *) { } +LLMessageSystem * gMessageSystem; +char * _PREHASH_AgentID; +char * _PREHASH_AgentData; +LLAgent gAgent; +LLAgent::LLAgent() : mAgentAccess(s_saved_settings) { } +LLAgent::~LLAgent() { } +void LLAgent::sendReliableMessage(void) { } +LLUUID gAgentSessionID; +LLUUID gAgentID; +LLUIColor::LLUIColor(void) { } +LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { } +LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { } +LLControlGroup::~LLControlGroup(void) { } +void LLUrlEntryParcel::processParcelInfo(const LLUrlEntryParcel::LLParcelData& parcel_data) { } + +namespace tut +{ +	struct TestObserver : public LLRemoteParcelInfoObserver { +		TestObserver() : mProcessed(false) { } + +		virtual void processParcelInfo(const LLParcelData& parcel_data) +		{ +			mProcessed = true; +		} + +		virtual void setParcelID(const LLUUID& parcel_id) { } + +		virtual void setErrorStatus(U32 status, const std::string& reason) { } + +		bool mProcessed; +	}; + +    struct RemoteParcelRequestData +    { +		RemoteParcelRequestData() +		{ +		} +    }; +     +	typedef test_group<RemoteParcelRequestData> remoteparcelrequest_t; +	typedef remoteparcelrequest_t::object remoteparcelrequest_object_t; +	tut::remoteparcelrequest_t tut_remoteparcelrequest("LLRemoteParcelRequest"); + +	template<> template<> +	void remoteparcelrequest_object_t::test<1>() +	{ +		set_test_name("observer pointer"); + +		boost::scoped_ptr<TestObserver> observer(new TestObserver()); + +		LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance(); +		processor.addObserver(LLUUID(TEST_PARCEL_ID), observer.get()); + +		processor.processParcelInfoReply(gMessageSystem, NULL); + +		ensure(observer->mProcessed); +	} + +	template<> template<> +	void remoteparcelrequest_object_t::test<2>() +	{ +		set_test_name("CHOP-220: dangling observer pointer"); + +		LLRemoteParcelInfoObserver * observer = new TestObserver(); + +		LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance(); +		processor.addObserver(LLUUID(TEST_PARCEL_ID), observer); + +		delete observer; +		observer = NULL; + +		processor.processParcelInfoReply(gMessageSystem, NULL); +	} +} diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 5f8cd28f29..88ab5a2284 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -1,200 +1,200 @@ -/**
 - * @file   llupdaterservice_test.cpp
 - * @brief  Tests of llupdaterservice.cpp.
 - * 
 - * $LicenseInfo:firstyear=2010&license=viewerlgpl$
 - * Second Life Viewer Source Code
 - * Copyright (C) 2010, Linden Research, Inc.
 - * 
 - * This library is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU Lesser General Public
 - * License as published by the Free Software Foundation;
 - * version 2.1 of the License only.
 - * 
 - * This library is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - * Lesser General Public License for more details.
 - * 
 - * You should have received a copy of the GNU Lesser General Public
 - * License along with this library; if not, write to the Free Software
 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 - * 
 - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 - * $/LicenseInfo$
 - */
 -
 -// Precompiled header
 -#include "linden_common.h"
 -// associated header
 -#include "../llupdaterservice.h"
 -#include "../llupdatechecker.h"
 -#include "../llupdatedownloader.h"
 -#include "../llupdateinstaller.h"
 -
 -#include "../../../test/lltut.h"
 -//#define DEBUG_ON
 -#include "../../../test/debug.h"
 -
 -#include "llevents.h"
 -#include "lldir.h"
 -
 -/*****************************************************************************
 -*   MOCK'd
 -*****************************************************************************/
 -LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)
 -{}
 -void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, 
 -								  std::string const & servicePath, std::string channel, std::string version)
 -{}
 -LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
 -void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){}
 -
 -class LLDir_Mock : public LLDir
 -{
 -	void initAppDirs(const std::string &app_name, 
 -		   			 const std::string& app_read_only_data_dir = "") {}
 -	U32 countFilesInDir(const std::string &dirname, const std::string &mask) 
 -	{
 -		return 0;
 -	}
 -
 -	BOOL getNextFileInDir(const std::string &dirname, 
 -						  const std::string &mask, 
 -						  std::string &fname) 
 -	{
 -		return false;
 -	}
 -	void getRandomFileInDir(const std::string &dirname, 
 -							const std::string &mask, 
 -							std::string &fname) {}
 -	std::string getCurPath() { return ""; }
 -	BOOL fileExists(const std::string &filename) const { return false; }
 -	std::string getLLPluginLauncher() { return ""; }
 -	std::string getLLPluginFilename(std::string base_name) { return ""; }
 -
 -} gDirUtil;
 -LLDir* gDirUtilp = &gDirUtil;
 -LLDir::LLDir() {}
 -LLDir::~LLDir() {}
 -S32 LLDir::deleteFilesInDir(const std::string &dirname, 
 -							const std::string &mask)
 -{ return 0; }
 -
 -void LLDir::setChatLogsDir(const std::string &path){}		
 -void LLDir::setPerAccountChatLogsDir(const std::string &username){}
 -void LLDir::setLindenUserDir(const std::string &username){}		
 -void LLDir::setSkinFolder(const std::string &skin_folder){}
 -bool LLDir::setCacheDir(const std::string &path){ return true; }
 -void LLDir::dumpCurrentDirectories() {}
 -
 -std::string LLDir::getExpandedFilename(ELLPath location, 
 -									   const std::string &filename) const 
 -{
 -	return "";
 -}
 -
 -std::string LLUpdateDownloader::downloadMarkerPath(void)
 -{
 -	return "";
 -}
 -
 -void LLUpdateDownloader::resume(void) {}
 -void LLUpdateDownloader::cancel(void) {}
 -void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {}
 -
 -int ll_install_update(std::string const &, std::string const &, bool, LLInstallScriptMode)
 -{
 -	return 0;
 -}
 -
 -std::string const & ll_install_failed_marker_path()
 -{
 -	static std::string wubba;
 -	return wubba;
 -}
 -
 -/*
 -#pragma warning(disable: 4273)
 -llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename,
 -										   ios_base::openmode _Mode,
 -										   int _Prot) :
 -	std::basic_istream<char,std::char_traits< char > >(NULL,true)
 -{}
 -
 -llus_mock_llifstream::~llus_mock_llifstream() {}
 -bool llus_mock_llifstream::is_open() const {return true;}
 -void llus_mock_llifstream::close() {}
 -*/
 -
 -/*****************************************************************************
 -*   TUT
 -*****************************************************************************/
 -namespace tut
 -{
 -    struct llupdaterservice_data
 -    {
 -		llupdaterservice_data() :
 -            pumps(LLEventPumps::instance()),
 -			test_url("dummy_url"),
 -			test_channel("dummy_channel"),
 -			test_version("dummy_version")
 -		{}
 -		LLEventPumps& pumps;
 -		std::string test_url;
 -		std::string test_channel;
 -		std::string test_version;
 -	};
 -
 -    typedef test_group<llupdaterservice_data> llupdaterservice_group;
 -    typedef llupdaterservice_group::object llupdaterservice_object;
 -    llupdaterservice_group llupdaterservicegrp("LLUpdaterService");
 -
 -    template<> template<>
 -    void llupdaterservice_object::test<1>()
 -    {
 -        DEBUG;
 -		LLUpdaterService updater;
 -		bool got_usage_error = false;
 -		try
 -		{
 -			updater.startChecking();
 -		}
 -		catch(LLUpdaterService::UsageError)
 -		{
 -			got_usage_error = true;
 -		}
 -		ensure("Caught start before params", got_usage_error);
 -	}
 -
 -    template<> template<>
 -    void llupdaterservice_object::test<2>()
 -    {
 -        DEBUG;
 -		LLUpdaterService updater;
 -		bool got_usage_error = false;
 -		try
 -		{
 -			updater.initialize("1.0",test_url, "update" ,test_channel, test_version);
 -			updater.startChecking();
 -			updater.initialize("1.0", "other_url", "update", test_channel, test_version);
 -		}
 -		catch(LLUpdaterService::UsageError)
 -		{
 -			got_usage_error = true;
 -		}
 -		ensure("Caught params while running", got_usage_error);
 -	}
 -
 -    template<> template<>
 -    void llupdaterservice_object::test<3>()
 -    {
 -        DEBUG;
 -		LLUpdaterService updater;
 -		updater.initialize("1.0", test_url, "update", test_channel, test_version);
 -		updater.startChecking();
 -		ensure(updater.isChecking());
 -		updater.stopChecking();
 -		ensure(!updater.isChecking());
 -	}
 -}
 +/** + * @file   llupdaterservice_test.cpp + * @brief  Tests of llupdaterservice.cpp. + *  + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "../llupdaterservice.h" +#include "../llupdatechecker.h" +#include "../llupdatedownloader.h" +#include "../llupdateinstaller.h" + +#include "../../../test/lltut.h" +//#define DEBUG_ON +#include "../../../test/debug.h" + +#include "llevents.h" +#include "lldir.h" + +/***************************************************************************** +*   MOCK'd +*****************************************************************************/ +LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) +{} +void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl,  +								  std::string const & servicePath, std::string channel, std::string version) +{} +LLUpdateDownloader::LLUpdateDownloader(Client & ) {} +void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){} + +class LLDir_Mock : public LLDir +{ +	void initAppDirs(const std::string &app_name,  +		   			 const std::string& app_read_only_data_dir = "") {} +	U32 countFilesInDir(const std::string &dirname, const std::string &mask)  +	{ +		return 0; +	} + +	BOOL getNextFileInDir(const std::string &dirname,  +						  const std::string &mask,  +						  std::string &fname)  +	{ +		return false; +	} +	void getRandomFileInDir(const std::string &dirname,  +							const std::string &mask,  +							std::string &fname) {} +	std::string getCurPath() { return ""; } +	BOOL fileExists(const std::string &filename) const { return false; } +	std::string getLLPluginLauncher() { return ""; } +	std::string getLLPluginFilename(std::string base_name) { return ""; } + +} gDirUtil; +LLDir* gDirUtilp = &gDirUtil; +LLDir::LLDir() {} +LLDir::~LLDir() {} +S32 LLDir::deleteFilesInDir(const std::string &dirname,  +							const std::string &mask) +{ return 0; } + +void LLDir::setChatLogsDir(const std::string &path){}		 +void LLDir::setPerAccountChatLogsDir(const std::string &username){} +void LLDir::setLindenUserDir(const std::string &username){}		 +void LLDir::setSkinFolder(const std::string &skin_folder){} +bool LLDir::setCacheDir(const std::string &path){ return true; } +void LLDir::dumpCurrentDirectories() {} + +std::string LLDir::getExpandedFilename(ELLPath location,  +									   const std::string &filename) const  +{ +	return ""; +} + +std::string LLUpdateDownloader::downloadMarkerPath(void) +{ +	return ""; +} + +void LLUpdateDownloader::resume(void) {} +void LLUpdateDownloader::cancel(void) {} +void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {} + +int ll_install_update(std::string const &, std::string const &, bool, LLInstallScriptMode) +{ +	return 0; +} + +std::string const & ll_install_failed_marker_path() +{ +	static std::string wubba; +	return wubba; +} + +/* +#pragma warning(disable: 4273) +llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename, +										   ios_base::openmode _Mode, +										   int _Prot) : +	std::basic_istream<char,std::char_traits< char > >(NULL,true) +{} + +llus_mock_llifstream::~llus_mock_llifstream() {} +bool llus_mock_llifstream::is_open() const {return true;} +void llus_mock_llifstream::close() {} +*/ + +/***************************************************************************** +*   TUT +*****************************************************************************/ +namespace tut +{ +    struct llupdaterservice_data +    { +		llupdaterservice_data() : +            pumps(LLEventPumps::instance()), +			test_url("dummy_url"), +			test_channel("dummy_channel"), +			test_version("dummy_version") +		{} +		LLEventPumps& pumps; +		std::string test_url; +		std::string test_channel; +		std::string test_version; +	}; + +    typedef test_group<llupdaterservice_data> llupdaterservice_group; +    typedef llupdaterservice_group::object llupdaterservice_object; +    llupdaterservice_group llupdaterservicegrp("LLUpdaterService"); + +    template<> template<> +    void llupdaterservice_object::test<1>() +    { +        DEBUG; +		LLUpdaterService updater; +		bool got_usage_error = false; +		try +		{ +			updater.startChecking(); +		} +		catch(LLUpdaterService::UsageError) +		{ +			got_usage_error = true; +		} +		ensure("Caught start before params", got_usage_error); +	} + +    template<> template<> +    void llupdaterservice_object::test<2>() +    { +        DEBUG; +		LLUpdaterService updater; +		bool got_usage_error = false; +		try +		{ +			updater.initialize("1.0",test_url, "update" ,test_channel, test_version); +			updater.startChecking(); +			updater.initialize("1.0", "other_url", "update", test_channel, test_version); +		} +		catch(LLUpdaterService::UsageError) +		{ +			got_usage_error = true; +		} +		ensure("Caught params while running", got_usage_error); +	} + +    template<> template<> +    void llupdaterservice_object::test<3>() +    { +        DEBUG; +		LLUpdaterService updater; +		updater.initialize("1.0", test_url, "update", test_channel, test_version); +		updater.startChecking(); +		ensure(updater.isChecking()); +		updater.stopChecking(); +		ensure(!updater.isChecking()); +	} +}  | 
